summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKim van der Riet <kpvdr@apache.org>2012-08-03 12:13:32 +0000
committerKim van der Riet <kpvdr@apache.org>2012-08-03 12:13:32 +0000
commitd43d1912b376322e27fdcda551a73f9ff5487972 (patch)
treece493e10baa95f44be8beb5778ce51783463196d
parent04877fec0c6346edec67072d7f2d247740cf2af5 (diff)
downloadqpid-python-d43d1912b376322e27fdcda551a73f9ff5487972.tar.gz
QPID-3858: Updated branch - merged from trunk r.1368650
git-svn-id: https://svn.apache.org/repos/asf/qpid/branches/asyncstore@1368910 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r--QPID_VERSION.txt2
-rwxr-xr-xbin/release.sh12
-rw-r--r--cpp/bindings/qmf/ruby/CMakeLists.txt5
-rw-r--r--cpp/bindings/qmf2/ruby/CMakeLists.txt5
-rw-r--r--cpp/bindings/qpid/python/python.i124
-rw-r--r--cpp/bindings/qpid/ruby/CMakeLists.txt5
-rw-r--r--cpp/bindings/qpid/ruby/LICENSE29
-rw-r--r--cpp/bindings/qpid/ruby/README.rdoc2
-rw-r--r--cpp/bindings/qpid/ruby/features/creating_a_receiver.feature4
-rw-r--r--cpp/bindings/qpid/ruby/features/creating_a_sender.feature6
-rw-r--r--cpp/bindings/qpid/ruby/features/receiving_a_message.feature10
-rw-r--r--cpp/bindings/qpid/ruby/features/sending_a_message.feature6
-rw-r--r--cpp/bindings/qpid/ruby/features/step_definitions/address_steps.rb7
-rw-r--r--cpp/bindings/qpid/ruby/features/step_definitions/receiver_steps.rb8
-rw-r--r--cpp/design_docs/log-model-category-for-correlation.txt112
-rw-r--r--cpp/etc/Makefile.am4
-rw-r--r--cpp/include/qmf/BrokerImportExport.h (renamed from cpp/src/qmf/BrokerImportExport.h)0
-rw-r--r--cpp/include/qmf/posix/EventNotifier.h2
-rw-r--r--cpp/include/qpid/Options.h9
-rw-r--r--cpp/include/qpid/RangeSet.h10
-rw-r--r--cpp/include/qpid/amqp_0_10/Codecs.h2
-rw-r--r--cpp/include/qpid/client/SessionBase_0_10.h13
-rw-r--r--cpp/include/qpid/client/SubscriptionSettings.h14
-rw-r--r--cpp/include/qpid/framing/Array.h2
-rw-r--r--cpp/include/qpid/framing/Buffer.h50
-rw-r--r--cpp/include/qpid/framing/ProtocolVersion.h2
-rw-r--r--cpp/include/qpid/framing/SequenceNumber.h12
-rw-r--r--cpp/include/qpid/framing/StructHelper.h2
-rw-r--r--cpp/include/qpid/framing/Uuid.h3
-rw-r--r--cpp/include/qpid/framing/amqp_types.h2
-rw-r--r--cpp/include/qpid/log/Logger.h2
-rw-r--r--cpp/include/qpid/log/Options.h2
-rw-r--r--cpp/include/qpid/log/Selector.h27
-rw-r--r--cpp/include/qpid/log/Statement.h170
-rw-r--r--cpp/include/qpid/management/Buffer.h3
-rw-r--r--cpp/include/qpid/sys/SystemInfo.h88
-rwxr-xr-xcpp/managementgen/qmf-gen7
-rwxr-xr-xcpp/managementgen/qmfgen/generate.py3
-rw-r--r--cpp/managementgen/qmfgen/templates/Class.cpp25
-rw-r--r--cpp/src/CMakeLists.txt82
-rw-r--r--cpp/src/Makefile.am9
-rw-r--r--cpp/src/ha.mk27
-rw-r--r--cpp/src/posix/QpiddBroker.cpp10
-rw-r--r--cpp/src/qmf.mk4
-rw-r--r--cpp/src/qmf/AgentSession.cpp25
-rw-r--r--cpp/src/qmf/AgentSessionImpl.h73
-rw-r--r--cpp/src/qmf/ConsoleSessionImpl.h2
-rw-r--r--cpp/src/qmf/EventNotifierImpl.cpp4
-rw-r--r--cpp/src/qmf/PrivateImplRef.h8
-rw-r--r--cpp/src/qpid/RefCounted.h12
-rw-r--r--cpp/src/qpid/acl/Acl.cpp12
-rw-r--r--cpp/src/qpid/acl/Acl.h11
-rw-r--r--cpp/src/qpid/acl/AclConnectionCounter.cpp226
-rw-r--r--cpp/src/qpid/acl/AclConnectionCounter.h36
-rw-r--r--cpp/src/qpid/acl/AclData.cpp81
-rw-r--r--cpp/src/qpid/acl/AclData.h38
-rw-r--r--cpp/src/qpid/acl/AclPlugin.cpp8
-rw-r--r--cpp/src/qpid/acl/AclReader.cpp55
-rw-r--r--cpp/src/qpid/acl/AclReader.h1
-rw-r--r--cpp/src/qpid/acl/AclTopicMatch.h89
-rw-r--r--cpp/src/qpid/acl/AclValidator.cpp2
-rw-r--r--cpp/src/qpid/acl/AclValidator.h2
-rw-r--r--cpp/src/qpid/acl/management-schema.xml17
-rw-r--r--cpp/src/qpid/amqp_0_10/Codecs.cpp344
-rw-r--r--cpp/src/qpid/broker/AclModule.h6
-rw-r--r--cpp/src/qpid/broker/Bridge.cpp155
-rw-r--r--cpp/src/qpid/broker/Bridge.h54
-rw-r--r--cpp/src/qpid/broker/Broker.cpp266
-rw-r--r--cpp/src/qpid/broker/Broker.h46
-rw-r--r--cpp/src/qpid/broker/ConfigurationObserver.h61
-rw-r--r--cpp/src/qpid/broker/ConfigurationObservers.h72
-rw-r--r--cpp/src/qpid/broker/Connection.cpp68
-rw-r--r--cpp/src/qpid/broker/Connection.h30
-rw-r--r--cpp/src/qpid/broker/ConnectionFactory.cpp11
-rw-r--r--cpp/src/qpid/broker/ConnectionHandler.cpp53
-rw-r--r--cpp/src/qpid/broker/ConnectionHandler.h4
-rw-r--r--cpp/src/qpid/broker/ConnectionObservers.h28
-rw-r--r--cpp/src/qpid/broker/Consumer.h2
-rw-r--r--cpp/src/qpid/broker/Daemon.h1
-rw-r--r--cpp/src/qpid/broker/DirectExchange.cpp3
-rw-r--r--cpp/src/qpid/broker/Exchange.cpp4
-rw-r--r--cpp/src/qpid/broker/Exchange.h5
-rw-r--r--cpp/src/qpid/broker/ExchangeRegistry.cpp78
-rw-r--r--cpp/src/qpid/broker/FanOutExchange.cpp3
-rw-r--r--cpp/src/qpid/broker/HeadersExchange.cpp3
-rw-r--r--cpp/src/qpid/broker/Link.cpp336
-rw-r--r--cpp/src/qpid/broker/Link.h47
-rw-r--r--cpp/src/qpid/broker/LinkRegistry.cpp254
-rw-r--r--cpp/src/qpid/broker/LinkRegistry.h62
-rw-r--r--cpp/src/qpid/broker/Message.cpp12
-rw-r--r--cpp/src/qpid/broker/Message.h1
-rw-r--r--cpp/src/qpid/broker/MessageDeque.cpp45
-rw-r--r--cpp/src/qpid/broker/MessageDeque.h2
-rw-r--r--cpp/src/qpid/broker/MessageMap.cpp11
-rw-r--r--cpp/src/qpid/broker/MessageMap.h3
-rw-r--r--cpp/src/qpid/broker/Messages.h9
-rw-r--r--cpp/src/qpid/broker/NameGenerator.h1
-rw-r--r--cpp/src/qpid/broker/Observers.h69
-rw-r--r--cpp/src/qpid/broker/PriorityQueue.cpp4
-rw-r--r--cpp/src/qpid/broker/PriorityQueue.h1
-rw-r--r--cpp/src/qpid/broker/PrivateImplRef.h8
-rw-r--r--cpp/src/qpid/broker/Queue.cpp117
-rw-r--r--cpp/src/qpid/broker/Queue.h20
-rw-r--r--cpp/src/qpid/broker/QueueFlowLimit.cpp4
-rw-r--r--cpp/src/qpid/broker/QueuePolicy.cpp4
-rw-r--r--cpp/src/qpid/broker/QueueRegistry.cpp66
-rw-r--r--cpp/src/qpid/broker/QueueRegistry.h18
-rw-r--r--cpp/src/qpid/broker/RecoveryManagerImpl.cpp8
-rw-r--r--cpp/src/qpid/broker/SaslAuthenticator.cpp78
-rw-r--r--cpp/src/qpid/broker/SaslAuthenticator.h2
-rw-r--r--cpp/src/qpid/broker/SecureConnectionFactory.cpp11
-rw-r--r--cpp/src/qpid/broker/SemanticState.cpp12
-rw-r--r--cpp/src/qpid/broker/SemanticState.h4
-rw-r--r--cpp/src/qpid/broker/SessionAdapter.cpp32
-rw-r--r--cpp/src/qpid/broker/SessionAdapter.h3
-rw-r--r--cpp/src/qpid/broker/SessionContext.h1
-rw-r--r--cpp/src/qpid/broker/SessionHandler.cpp36
-rw-r--r--cpp/src/qpid/broker/SessionHandler.h21
-rw-r--r--cpp/src/qpid/broker/SessionState.cpp2
-rw-r--r--cpp/src/qpid/broker/SessionState.h5
-rw-r--r--cpp/src/qpid/broker/System.cpp10
-rw-r--r--cpp/src/qpid/broker/System.h17
-rw-r--r--cpp/src/qpid/broker/TopicExchange.cpp369
-rw-r--r--cpp/src/qpid/broker/TopicExchange.h126
-rw-r--r--cpp/src/qpid/broker/TopicKeyNode.h371
-rw-r--r--cpp/src/qpid/broker/windows/SaslAuthenticator.cpp4
-rw-r--r--cpp/src/qpid/broker/windows/SslProtocolFactory.cpp53
-rw-r--r--cpp/src/qpid/client/Connection.cpp2
-rw-r--r--cpp/src/qpid/client/ConnectionHandler.cpp6
-rw-r--r--cpp/src/qpid/client/PrivateImplRef.h8
-rw-r--r--cpp/src/qpid/client/SessionImpl.cpp2
-rw-r--r--cpp/src/qpid/client/SslConnector.cpp3
-rw-r--r--cpp/src/qpid/client/SubscriptionManagerImpl.cpp10
-rw-r--r--cpp/src/qpid/client/SubscriptionManagerImpl.h3
-rw-r--r--cpp/src/qpid/client/TCPConnector.cpp6
-rw-r--r--cpp/src/qpid/client/TCPConnector.h4
-rw-r--r--cpp/src/qpid/client/amqp0_10/AddressResolution.cpp8
-rw-r--r--cpp/src/qpid/client/amqp0_10/ConnectionImpl.cpp2
-rw-r--r--cpp/src/qpid/client/amqp0_10/OutgoingMessage.cpp15
-rw-r--r--cpp/src/qpid/client/amqp0_10/OutgoingMessage.h1
-rw-r--r--cpp/src/qpid/client/amqp0_10/ReceiverImpl.h1
-rw-r--r--cpp/src/qpid/client/amqp0_10/SenderImpl.cpp8
-rw-r--r--cpp/src/qpid/client/amqp0_10/SenderImpl.h12
-rw-r--r--cpp/src/qpid/client/windows/SslConnector.cpp6
-rw-r--r--cpp/src/qpid/cluster/Connection.cpp29
-rw-r--r--cpp/src/qpid/cluster/Connection.h10
-rw-r--r--cpp/src/qpid/cluster/ConnectionCodec.cpp14
-rw-r--r--cpp/src/qpid/cluster/Cpg.cpp54
-rw-r--r--cpp/src/qpid/cluster/Cpg.h10
-rw-r--r--cpp/src/qpid/cluster/UpdateClient.cpp18
-rw-r--r--cpp/src/qpid/cluster/types.h23
-rw-r--r--cpp/src/qpid/console/ClassKey.cpp1
-rw-r--r--cpp/src/qpid/framing/AMQCommandControlBody.h70
-rw-r--r--cpp/src/qpid/framing/AMQContentBody.cpp2
-rw-r--r--cpp/src/qpid/framing/AMQContentBody.h8
-rw-r--r--cpp/src/qpid/framing/AMQFrame.cpp4
-rw-r--r--cpp/src/qpid/framing/Buffer.cpp16
-rw-r--r--cpp/src/qpid/framing/FieldTable.cpp2
-rw-r--r--cpp/src/qpid/framing/ProtocolInitiation.cpp2
-rw-r--r--cpp/src/qpid/framing/Uuid.cpp7
-rw-r--r--cpp/src/qpid/ha/AlternateExchangeSetter.h73
-rw-r--r--cpp/src/qpid/ha/Backup.cpp82
-rw-r--r--cpp/src/qpid/ha/Backup.h6
-rw-r--r--cpp/src/qpid/ha/BackupConnectionExcluder.h (renamed from cpp/src/qpid/ha/ConnectionExcluder.h)30
-rw-r--r--cpp/src/qpid/ha/BrokerInfo.cpp118
-rw-r--r--cpp/src/qpid/ha/BrokerInfo.h84
-rw-r--r--cpp/src/qpid/ha/BrokerReplicator.cpp420
-rw-r--r--cpp/src/qpid/ha/BrokerReplicator.h46
-rw-r--r--cpp/src/qpid/ha/ConnectionExcluder.cpp40
-rw-r--r--cpp/src/qpid/ha/ConnectionObserver.cpp94
-rw-r--r--cpp/src/qpid/ha/ConnectionObserver.h74
-rw-r--r--cpp/src/qpid/ha/HaBroker.cpp300
-rw-r--r--cpp/src/qpid/ha/HaBroker.h74
-rw-r--r--cpp/src/qpid/ha/HaPlugin.cpp32
-rw-r--r--cpp/src/qpid/ha/Membership.cpp85
-rw-r--r--cpp/src/qpid/ha/Membership.h68
-rw-r--r--cpp/src/qpid/ha/Primary.cpp252
-rw-r--r--cpp/src/qpid/ha/Primary.h115
-rw-r--r--cpp/src/qpid/ha/QueueGuard.cpp139
-rw-r--r--cpp/src/qpid/ha/QueueGuard.h118
-rw-r--r--cpp/src/qpid/ha/QueueRange.h85
-rw-r--r--cpp/src/qpid/ha/QueueReplicator.cpp115
-rw-r--r--cpp/src/qpid/ha/QueueReplicator.h15
-rw-r--r--cpp/src/qpid/ha/RemoteBackup.cpp120
-rw-r--r--cpp/src/qpid/ha/RemoteBackup.h111
-rw-r--r--cpp/src/qpid/ha/ReplicateLevel.cpp72
-rw-r--r--cpp/src/qpid/ha/ReplicateLevel.h52
-rw-r--r--cpp/src/qpid/ha/ReplicatingSubscription.cpp400
-rw-r--r--cpp/src/qpid/ha/ReplicatingSubscription.h107
-rw-r--r--cpp/src/qpid/ha/ReplicationTest.cpp75
-rw-r--r--cpp/src/qpid/ha/ReplicationTest.h67
-rw-r--r--cpp/src/qpid/ha/Settings.h10
-rw-r--r--cpp/src/qpid/ha/management-schema.xml32
-rw-r--r--cpp/src/qpid/ha/types.cpp80
-rw-r--r--cpp/src/qpid/ha/types.h109
-rw-r--r--cpp/src/qpid/log/Logger.cpp7
-rw-r--r--cpp/src/qpid/log/Options.cpp18
-rw-r--r--cpp/src/qpid/log/Selector.cpp31
-rw-r--r--cpp/src/qpid/log/Statement.cpp61
-rw-r--r--cpp/src/qpid/log/posix/SinkOptions.cpp5
-rw-r--r--cpp/src/qpid/management/Buffer.cpp3
-rw-r--r--cpp/src/qpid/management/ManagementAgent.cpp17
-rw-r--r--cpp/src/qpid/management/ManagementDirectExchange.cpp4
-rw-r--r--cpp/src/qpid/management/ManagementTopicExchange.cpp6
-rw-r--r--cpp/src/qpid/messaging/PrivateImplRef.h8
-rw-r--r--cpp/src/qpid/replication/ReplicationExchange.cpp2
-rw-r--r--cpp/src/qpid/sys/AsynchIOHandler.cpp43
-rw-r--r--cpp/src/qpid/sys/AsynchIOHandler.h10
-rw-r--r--cpp/src/qpid/sys/MemStat.cpp (renamed from cpp/src/qpid/sys/windows/MemStat.cpp)4
-rw-r--r--cpp/src/qpid/sys/SslPlugin.cpp28
-rw-r--r--cpp/src/qpid/sys/TCPIOPlugin.cpp21
-rw-r--r--cpp/src/qpid/sys/Timer.cpp55
-rw-r--r--cpp/src/qpid/sys/Timer.h7
-rw-r--r--cpp/src/qpid/sys/cyrus/CyrusSecurityLayer.cpp1
-rwxr-xr-xcpp/src/qpid/sys/posix/LockFile.cpp2
-rw-r--r--cpp/src/qpid/sys/posix/MemStat.cpp2
-rw-r--r--cpp/src/qpid/sys/posix/SocketAddress.cpp6
-rwxr-xr-xcpp/src/qpid/sys/posix/SystemInfo.cpp108
-rw-r--r--cpp/src/qpid/sys/ssl/SslHandler.cpp41
-rw-r--r--cpp/src/qpid/sys/ssl/SslHandler.h9
-rw-r--r--cpp/src/qpid/sys/ssl/SslIo.cpp12
-rw-r--r--cpp/src/qpid/sys/ssl/SslIo.h3
-rw-r--r--cpp/src/qpid/sys/unordered_map.h2
-rwxr-xr-xcpp/src/qpid/sys/windows/IocpPoller.cpp5
-rw-r--r--cpp/src/qpid/sys/windows/Socket.cpp17
-rwxr-xr-xcpp/src/qpid/sys/windows/SystemInfo.cpp10
-rw-r--r--cpp/src/qpid/types/Variant.cpp72
-rw-r--r--cpp/src/qpid/xml/XmlExchange.cpp34
-rw-r--r--cpp/src/qpid/xml/XmlExchange.h4
-rw-r--r--cpp/src/tests/CMakeLists.txt1
-rw-r--r--cpp/src/tests/ExchangeTest.cpp2
-rw-r--r--cpp/src/tests/FieldTable.cpp9
-rw-r--r--cpp/src/tests/Makefile.am12
-rw-r--r--cpp/src/tests/MessageBuilderTest.cpp6
-rw-r--r--cpp/src/tests/MessageTest.cpp9
-rw-r--r--cpp/src/tests/MessageUtils.h4
-rw-r--r--cpp/src/tests/MessagingSessionTests.cpp18
-rw-r--r--cpp/src/tests/QueueTest.cpp244
-rw-r--r--cpp/src/tests/RangeSet.cpp134
-rw-r--r--cpp/src/tests/ReplicationTest.cpp4
-rw-r--r--cpp/src/tests/SystemInfo.cpp52
-rw-r--r--cpp/src/tests/TestMessageStore.h2
-rw-r--r--cpp/src/tests/TimerTest.cpp2
-rw-r--r--cpp/src/tests/TopicExchangeTest.cpp14
-rw-r--r--cpp/src/tests/TxPublishTest.cpp4
-rw-r--r--cpp/src/tests/Uuid.cpp12
-rwxr-xr-xcpp/src/tests/acl.py148
-rw-r--r--cpp/src/tests/asyncstore.cmake3
-rw-r--r--cpp/src/tests/brokertest.py37
-rwxr-xr-xcpp/src/tests/cluster_test_logs.py3
-rwxr-xr-xcpp/src/tests/cluster_tests.py189
-rwxr-xr-xcpp/src/tests/federation.py467
-rwxr-xr-xcpp/src/tests/ha_tests.py539
-rwxr-xr-xcpp/src/tests/ipv6_test13
-rw-r--r--cpp/src/tests/logging.cpp10
-rwxr-xr-xcpp/src/tests/ping_broker127
-rw-r--r--cpp/src/tests/qpid-latency-test.cpp18
-rw-r--r--cpp/src/tests/qpid-receive.cpp5
-rwxr-xr-xcpp/src/tests/run_acl_tests4
-rwxr-xr-xcpp/src/tests/run_federation_tests8
-rwxr-xr-x[-rw-r--r--]cpp/src/tests/run_ha_tests (renamed from java/management/eclipse-plugin/build-release-common.properties)18
-rwxr-xr-xcpp/src/tests/sasl_test_setup.sh2
-rwxr-xr-xcpp/src/tests/ssl_test5
-rwxr-xr-xcpp/src/tests/storePerftools/asyncStorePerf_smoke_test.sh (renamed from cpp/src/tests/storePerftools/storePerftoolsSmokeTest.sh)29
-rwxr-xr-xcpp/src/tests/storePerftools/jrnl2Perf_smoke_test.sh33
-rw-r--r--cpp/src/tests/txjob.cpp6
-rw-r--r--cpp/src/tests/txshift.cpp2
-rw-r--r--cpp/xml/cluster.xml1
-rw-r--r--doc/book/src/cpp-broker/.gitignore1
-rw-r--r--doc/book/src/cpp-broker/Active-Passive-Cluster.xml390
-rw-r--r--doc/book/src/cpp-broker/Cheat-Sheet-for-configuring-Queue-Options.xml2
-rw-r--r--doc/book/src/java-broker/AMQP-Messaging-Broker-Java-Book.xml10
-rw-r--r--doc/book/src/java-broker/Broker-Configuration-Guide.xml4
-rw-r--r--doc/book/src/java-broker/HA-Guide.xml990
-rw-r--r--doc/book/src/java-broker/MessageStore-Tool.xml150
-rw-r--r--doc/book/src/java-broker/OtherQueueTypes.xml274
-rw-r--r--doc/book/src/java-broker/Producer-Flow-Control.xml217
-rw-r--r--doc/book/src/java-broker/Qpid-Java-FAQ.xml23
-rw-r--r--doc/book/src/java-broker/Use-Priority-Queues.xml138
-rw-r--r--doc/book/src/java-broker/images/HA-2N-Key.pngbin0 -> 25912 bytes
-rw-r--r--doc/book/src/java-broker/images/HA-2N-Key.svg3
-rw-r--r--doc/book/src/java-broker/images/HA-2N-MasterFail.pngbin0 -> 200842 bytes
-rw-r--r--doc/book/src/java-broker/images/HA-2N-MasterFail.svg3
-rw-r--r--doc/book/src/java-broker/images/HA-2N-NetworkPartition.pngbin0 -> 159519 bytes
-rw-r--r--doc/book/src/java-broker/images/HA-2N-NetworkPartition.svg3
-rw-r--r--doc/book/src/java-broker/images/HA-2N-Normal.pngbin0 -> 42088 bytes
-rw-r--r--doc/book/src/java-broker/images/HA-2N-Normal.svg3
-rw-r--r--doc/book/src/java-broker/images/HA-2N-ReplicaFail.pngbin0 -> 162077 bytes
-rw-r--r--doc/book/src/java-broker/images/HA-2N-ReplicaFail.svg3
-rw-r--r--doc/book/src/java-broker/images/HA-2N-SplitBrain.pngbin0 -> 130546 bytes
-rw-r--r--doc/book/src/java-broker/images/HA-2N-SplitBrain.svg3
-rw-r--r--doc/book/src/java-broker/images/HA-BDBHAMessageStore-MBean-jconsole.pngbin0 -> 52500 bytes
-rw-r--r--doc/book/src/java-broker/images/HA-perftests-results.pngbin0 -> 29998 bytes
-rw-r--r--doc/book/src/programming/Programming-In-Apache-Qpid-Book.xml12
-rwxr-xr-xextras/qmf/setup.py2
-rw-r--r--extras/qmf/src/py/qmf/console.py6
-rw-r--r--java/amqp-1-0-client-jms/build.xml4
-rw-r--r--java/amqp-1-0-client/build.xml4
-rw-r--r--java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Dump.java20
-rw-r--r--java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Filereceiver.java20
-rw-r--r--java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Filesender.java20
-rw-r--r--java/amqp-1-0-common/build.xml4
-rw-r--r--java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/codec/BinaryString.java20
-rw-r--r--java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/ConnectionEndpoint.java12
-rw-r--r--java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/ErrorHandler.java20
-rw-r--r--java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/ReceivingLinkEndpoint.java14
-rw-r--r--java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/SaslServerProvider.java (renamed from java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/CallbackHandlerSource.java)7
-rw-r--r--java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/SessionEndpoint.java24
-rw-r--r--java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/codec/AMQPDescribedTypeRegistry.java21
-rwxr-xr-xjava/bdbstore/bin/backup.sh2
-rw-r--r--java/bdbstore/build.xml27
-rw-r--r--java/bdbstore/jmx/MANIFEST.MF20
-rw-r--r--java/bdbstore/jmx/build.xml31
-rw-r--r--java/bdbstore/jmx/src/main/java/org/apache/qpid/server/store/berkeleydb/jmx/BDBHAMessageStoreManagerMBean.java232
-rw-r--r--java/bdbstore/jmx/src/main/java/org/apache/qpid/server/store/berkeleydb/jmx/BDBHAMessageStoreManagerMBeanProvider.java73
-rw-r--r--java/bdbstore/jmx/src/main/java/org/apache/qpid/server/store/berkeleydb/jmx/ManagedBDBHAMessageStore.java82
-rw-r--r--java/bdbstore/jmx/src/main/resources/META-INF/services/org.apache.qpid.server.jmx.MBeanProvider1
-rw-r--r--java/bdbstore/jmx/src/test/java/org/apache/qpid/server/store/berkeleydb/HAClusterManagementTest.java269
-rw-r--r--java/bdbstore/jmx/src/test/java/org/apache/qpid/server/store/berkeleydb/HAClusterTwoNodeTest.java217
-rw-r--r--java/bdbstore/jmx/src/test/java/org/apache/qpid/server/store/berkeleydb/jmx/BDBHAMessageStoreManagerMBeanTest.java233
-rw-r--r--java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/AbstractBDBMessageStore.java388
-rw-r--r--java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBHAMessageStore.java607
-rw-r--r--java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStore.java234
-rw-r--r--java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/CommitThreadWrapper.java265
-rw-r--r--java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuple/ConfiguredObjectBinding.java20
-rw-r--r--java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/CursorTemplate.java4
-rw-r--r--java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom5To6.java61
-rw-r--r--java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/Upgrader.java8
-rw-r--r--java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBHAMessageStoreTest.java165
-rw-r--r--java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStoreConfigurationTest.java20
-rw-r--r--java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStoreQuotaEventsTest.java73
-rw-r--r--java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStoreTest.java28
-rw-r--r--java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/HAClusterBlackboxTest.java165
-rw-r--r--java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/HAClusterWhiteboxTest.java266
-rw-r--r--java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/HAMessageStoreSmokeTest.java (renamed from java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/NumberVerifyListener.java)41
-rw-r--r--java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/HATestClusterCreator.java423
-rw-r--r--java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/tuple/ConfiguredObjectBindingTest.java2
-rw-r--r--java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/AbstractUpgradeTestCase.java4
-rw-r--r--java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom4to5Test.java44
-rw-r--r--java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom5To6Test.java141
-rw-r--r--java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgraderTest.java6
-rw-r--r--java/bdbstore/src/test/resources/upgrade/bdbstore-v4/test-store/00000000.jdbbin1357197 -> 1361990 bytes
-rw-r--r--java/bdbstore/src/test/resources/upgrade/bdbstore-v5/test-store/00000000.jdbbin1357227 -> 1361990 bytes
-rw-r--r--java/bdbstore/src/test/resources/upgrade/bdbstore-v5/test-store/00000001.jdbbin1332881 -> 1333643 bytes
-rw-r--r--java/broker-plugins/access-control/MANIFEST.MF2
-rw-r--r--java/broker-plugins/access-control/build.xml7
-rw-r--r--java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/PlainConfigurationTest.java7
-rw-r--r--java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/RuleSetTest.java90
-rw-r--r--java/broker-plugins/experimental/shutdown/MANIFEST.MF16
-rw-r--r--java/broker-plugins/experimental/shutdown/src/main/java/org/apache/qpid/shutdown/Activator.java57
-rw-r--r--java/broker-plugins/extras/MANIFEST.MF21
-rw-r--r--java/broker-plugins/extras/src/main/java/org/apache/qpid/extras/exchanges/diagnostic/DiagnosticExchange.java214
-rw-r--r--java/broker-plugins/extras/src/main/java/org/apache/qpid/extras/exchanges/diagnostic/DiagnosticExchangeType.java59
-rw-r--r--java/broker-plugins/extras/src/main/java/org/apache/qpid/extras/exchanges/example/TestExchange.java262
-rw-r--r--java/broker-plugins/extras/src/main/java/org/apache/qpid/extras/exchanges/example/TestExchangeType.java59
-rw-r--r--java/broker-plugins/extras/src/test/java/org/apache/qpid/server/plugins/ExtrasTest.java75
-rw-r--r--java/broker-plugins/firewall/MANIFEST.MF2
-rw-r--r--java/broker-plugins/firewall/build.xml7
-rw-r--r--java/broker-plugins/management-http/MANIFEST.MF70
-rw-r--r--java/broker-plugins/management-http/build.xml57
-rw-r--r--java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/Management.java248
-rw-r--r--java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/ManagementActivator.java73
-rw-r--r--java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/ManagementConfiguration.java77
-rw-r--r--java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/DefinedFileServlet.java79
-rw-r--r--java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/FileServlet.java109
-rw-r--r--java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/api/ExchangesServlet.java208
-rw-r--r--java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/api/VhostsServlet.java118
-rw-r--r--java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/AbstractServlet.java208
-rw-r--r--java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/KeyComparator.java (renamed from java/broker/src/main/java/org/apache/qpid/server/store/derby/DerbyMessageStoreFactory.java)35
-rw-r--r--java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/LogRecordsServlet.java85
-rw-r--r--java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MapComparator.java74
-rw-r--r--java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MessageContentServlet.java176
-rw-r--r--java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MessageServlet.java502
-rw-r--r--java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RestServlet.java586
-rw-r--r--java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/SaslServlet.java256
-rw-r--r--java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/StructureServlet.java103
-rw-r--r--java/broker-plugins/management-http/src/main/java/resources/addBinding.html42
-rw-r--r--java/broker-plugins/management-http/src/main/java/resources/addExchange.html54
-rw-r--r--java/broker-plugins/management-http/src/main/java/resources/addQueue.html182
-rw-r--r--java/broker-plugins/management-http/src/main/java/resources/authenticationprovider/addUser.html42
-rw-r--r--java/broker-plugins/management-http/src/main/java/resources/authenticationprovider/setPassword.html42
-rw-r--r--java/broker-plugins/management-http/src/main/java/resources/authenticationprovider/showPrincipalDatabaseAuthenticationManager.html (renamed from java/broker-plugins/experimental/shutdown/build.xml)21
-rw-r--r--java/broker-plugins/management-http/src/main/java/resources/css/common.css92
-rw-r--r--java/broker-plugins/management-http/src/main/java/resources/footer.html28
-rw-r--r--java/broker-plugins/management-http/src/main/java/resources/images/qpid-logo.pngbin0 -> 6600 bytes
-rw-r--r--java/broker-plugins/management-http/src/main/java/resources/js/qpid/authorization/sasl.js213
-rw-r--r--java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/UpdatableStore.js110
-rw-r--r--java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/footer.js30
-rw-r--r--java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/formatter.js99
-rw-r--r--java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/properties.js26
-rw-r--r--java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/updater.js (renamed from java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/type/ExchangeTypeTabControl.java)45
-rw-r--r--java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/util.js120
-rw-r--r--java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/AuthenticationProvider.js122
-rw-r--r--java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Broker.js205
-rw-r--r--java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Connection.js213
-rw-r--r--java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Exchange.js291
-rw-r--r--java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Queue.js485
-rw-r--r--java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/VirtualHost.js378
-rw-r--r--java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addBinding.js223
-rw-r--r--java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addExchange.js146
-rw-r--r--java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addQueue.js191
-rw-r--r--java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/authenticationprovider/PrincipalDatabaseAuthenticationManager.js327
-rw-r--r--java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/controller.js104
-rw-r--r--java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/moveCopyMessages.js137
-rw-r--r--java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/showMessage.js142
-rw-r--r--java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/treeView.js313
-rw-r--r--java/broker-plugins/management-http/src/main/java/resources/management.html92
-rw-r--r--java/broker-plugins/management-http/src/main/java/resources/moveCopyMessages.html36
-rw-r--r--java/broker-plugins/management-http/src/main/java/resources/showAuthProvider.html25
-rw-r--r--java/broker-plugins/management-http/src/main/java/resources/showBroker.html25
-rw-r--r--java/broker-plugins/management-http/src/main/java/resources/showConnection.html47
-rw-r--r--java/broker-plugins/management-http/src/main/java/resources/showExchange.html50
-rw-r--r--java/broker-plugins/management-http/src/main/java/resources/showMessage.html73
-rw-r--r--java/broker-plugins/management-http/src/main/java/resources/showQueue.html103
-rw-r--r--java/broker-plugins/management-http/src/main/java/resources/showVirtualHost.html87
-rw-r--r--java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/Asserts.java249
-rw-r--r--java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/AuthenticationProviderRestTest.java53
-rw-r--r--java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/BindingRestTest.java109
-rw-r--r--java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/BrokerRestHttpsTest.java86
-rw-r--r--java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/BrokerRestTest.java118
-rw-r--r--java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/ConnectionRestTest.java213
-rw-r--r--java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/ExchangeRestTest.java67
-rw-r--r--java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/LogRecordsRestTest.java42
-rw-r--r--java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/MessagesRestTest.java354
-rw-r--r--java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/PortRestTest.java41
-rw-r--r--java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/QpidRestTestCase.java245
-rw-r--r--java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/QueueRestTest.java225
-rw-r--r--java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/SaslRestTest.java22
-rw-r--r--java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/StructureRestTest.java115
-rw-r--r--java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/UserRestTest.java92
-rw-r--r--java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/VirtualHostRestTest.java434
-rw-r--r--java/broker-plugins/management-jmx/MANIFEST.MF66
-rw-r--r--java/broker-plugins/management-jmx/build.xml47
-rw-r--r--java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/AMQManagedObject.java (renamed from java/broker/src/main/java/org/apache/qpid/server/management/AMQManagedObject.java)39
-rw-r--r--java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/DefaultManagedObject.java (renamed from java/broker/src/main/java/org/apache/qpid/server/management/DefaultManagedObject.java)27
-rw-r--r--java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXActivator.java136
-rw-r--r--java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXConfiguration.java76
-rw-r--r--java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXManagedObjectRegistry.java (renamed from java/broker/src/main/java/org/apache/qpid/server/management/JMXManagedObjectRegistry.java)88
-rw-r--r--java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXService.java193
-rw-r--r--java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/MBeanIntrospector.java (renamed from java/broker/src/main/java/org/apache/qpid/server/management/MBeanIntrospector.java)9
-rw-r--r--java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/MBeanInvocationHandlerImpl.java (renamed from java/broker/src/main/java/org/apache/qpid/server/management/MBeanInvocationHandlerImpl.java)107
-rw-r--r--java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/MBeanProvider.java52
-rw-r--r--java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/ManagedObject.java (renamed from java/broker/src/main/java/org/apache/qpid/server/management/ManagedObject.java)10
-rw-r--r--java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/ManagedObjectRegistry.java (renamed from java/broker/src/main/java/org/apache/qpid/server/management/ManagedObjectRegistry.java)3
-rw-r--r--java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/AbstractStatisticsGatheringMBean.java200
-rw-r--r--java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/ConfigurationManagementMBean.java (renamed from java/broker/src/main/java/org/apache/qpid/server/configuration/management/ConfigurationManagementMBean.java)17
-rw-r--r--java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/ConnectionMBean.java182
-rw-r--r--java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/ExchangeMBean.java313
-rw-r--r--java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/LoggingManagementMBean.java324
-rw-r--r--java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/MBeanUtils.java57
-rw-r--r--java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/QueueMBean.java668
-rw-r--r--java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/ServerInformationMBean.java89
-rw-r--r--java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/Shutdown.java (renamed from java/broker-plugins/experimental/shutdown/src/main/java/org/apache/qpid/shutdown/Shutdown.java)27
-rw-r--r--java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/ShutdownMBean.java (renamed from java/broker-plugins/experimental/shutdown/src/main/java/org/apache/qpid/shutdown/ShutdownMBean.java)11
-rw-r--r--java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/UserManagementMBean.java (renamed from java/broker/src/main/java/org/apache/qpid/server/security/auth/management/AMQUserManagementMBean.java)77
-rw-r--r--java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/VirtualHostMBean.java211
-rw-r--r--java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/VirtualHostManagerMBean.java238
-rw-r--r--java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/NoopManagedObjectRegistry.java (renamed from java/broker/src/main/java/org/apache/qpid/server/management/NoopManagedObjectRegistry.java)14
-rw-r--r--java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/ConnectionMBeanTest.java237
-rw-r--r--java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/ExchangeMBeanTest.java234
-rw-r--r--java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/LoggingManagementMBeanTest.java245
-rw-r--r--java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/MBeanTestUtils.java (renamed from java/broker-plugins/extras/src/main/java/org/apache/qpid/extras/Activator.java)29
-rw-r--r--java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/QueueMBeanTest.java439
-rw-r--r--java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/ServerInformationMBeanTest.java94
-rw-r--r--java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/UserManagementMBeanTest.java157
-rw-r--r--java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/VirtualHostManagerMBeanTest.java174
-rw-r--r--java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/BrokerManagementTest.java (renamed from java/systests/src/main/java/org/apache/qpid/management/jmx/ManagedBrokerMBeanTest.java)54
-rw-r--r--java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/ConnectionManagementTest.java283
-rw-r--r--java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/LoggingManagementTest.java149
-rw-r--r--java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/ManagementActorLoggingTest.java (renamed from java/systests/src/main/java/org/apache/qpid/management/jmx/ManagementActorLoggingTest.java)2
-rw-r--r--java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/ManagementLoggingTest.java (renamed from java/systests/src/main/java/org/apache/qpid/server/logging/ManagementLoggingTest.java)5
-rw-r--r--java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/QueueManagementTest.java696
-rw-r--r--java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/StatisticsTest.java204
-rw-r--r--java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/UserManagementTest.java251
-rw-r--r--java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/UserManagementWithBase64MD5PasswordsTest.java (renamed from java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStoreFactory.java)19
-rw-r--r--java/broker/build.xml6
-rw-r--r--java/broker/etc/broker_example.acl19
-rw-r--r--java/broker/etc/config.xml3
-rw-r--r--java/broker/etc/log4j.xml13
-rw-r--r--java/broker/etc/passwd2
-rw-r--r--java/broker/etc/virtualhosts.xml12
-rwxr-xr-xjava/broker/src/main/java/broker.bnd2
-rw-r--r--java/broker/src/main/java/org/apache/log4j/xml/QpidLog4JConfigurator.java320
-rw-r--r--java/broker/src/main/java/org/apache/qpid/qmf/ManagementExchange.java20
-rw-r--r--java/broker/src/main/java/org/apache/qpid/qmf/QMFMessage.java18
-rw-r--r--java/broker/src/main/java/org/apache/qpid/qmf/QMFObject.java4
-rw-r--r--java/broker/src/main/java/org/apache/qpid/qmf/QMFService.java74
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/AMQBrokerManagerMBean.java410
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/AMQChannel.java177
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/Broker.java144
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/BrokerOptions.java38
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/Main.java58
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/ProtocolInclusion.java74
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/TransactionTimeoutHelper.java63
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/binding/Binding.java9
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/binding/BindingFactory.java4
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/configuration/ConfigStore.java4
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/configuration/ConfiguredObject.java2
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/configuration/ExchangeConfig.java5
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/configuration/LinkConfigType.java4
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/configuration/QueueConfiguration.java6
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/configuration/ServerConfiguration.java215
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/configuration/ServerNetworkTransportConfiguration.java13
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/configuration/SystemConfigImpl.java15
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/configuration/SystemConfigType.java2
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/configuration/TopicConfig.java3
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/configuration/VirtualHostConfiguration.java11
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/connection/ConnectionRegistry.java68
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/connection/IConnectionRegistry.java11
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java67
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/exchange/AbstractExchangeMBean.java215
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/exchange/DefaultExchangeRegistry.java62
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/exchange/DirectExchange.java5
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/exchange/DirectExchangeMBean.java85
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/exchange/Exchange.java2
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/exchange/ExchangeRegistry.java21
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/exchange/FanoutExchange.java5
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/exchange/FanoutExchangeMBean.java74
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersExchange.java5
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersExchangeMBean.java158
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/exchange/TopicExchange.java9
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/exchange/TopicExchangeMBean.java81
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/exchange/topic/TopicMatcherDFAState.java40
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/exchange/topic/TopicMatcherResult.java4
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/exchange/topic/TopicParser.java40
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/exchange/topic/TopicWord.java9
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/exchange/topic/TopicWordDictionary.java12
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/federation/Bridge.java11
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/federation/BrokerLink.java24
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/flow/BytesOnlyCreditManager.java10
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/flow/FlowCreditManager.java7
-rwxr-xr-xjava/broker/src/main/java/org/apache/qpid/server/flow/FlowCreditManager_0_10.java4
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/flow/LimitlessCreditManager.java6
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/flow/MessageAndBytesCreditManager.java6
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/flow/MessageOnlyCreditManager.java9
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/handler/AccessRequestHandler.java2
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/handler/BasicRecoverSyncMethodHandler.java2
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionSecureOkMethodHandler.java10
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionStartOkMethodHandler.java14
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/handler/QueueDeclareHandler.java5
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/handler/QueueUnbindHandler.java2
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/handler/TxCommitHandler.java20
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/information/management/ServerInformationMBean.java145
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/logging/LogRecorder.java210
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/logging/log4j/LoggingFacade.java579
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/logging/log4j/LoggingFacadeException.java (renamed from java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/exceptions/InfoRequiredException.java)27
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/logging/management/LoggingManagementMBean.java822
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/logging/messages/MessageStore_logmessages.properties2
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/logging/messages/VirtualHost_logmessages.properties4
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/management/AbstractAMQManagedConnectionObject.java90
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/management/Managable.java34
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/message/AMQMessageHeader.java6
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/message/ContentHeaderBodyAdapter.java18
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/message/MessageMetaData.java17
-rwxr-xr-xjava/broker/src/main/java/org/apache/qpid/server/message/MessageMetaData_1_0.java28
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/message/MessageTransferHeader.java29
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/model/Attribute.java199
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/model/AuthenticationMethod.java33
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/model/AuthenticationProvider.java55
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/model/Broker.java80
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/model/ConfigurationChangeListener.java3
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/model/ConfiguredObject.java25
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/model/ConfiguredObjectFinder.java (renamed from java/broker/src/main/java/org/apache/qpid/server/store/MemoryMessageStoreFactory.java)27
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/model/Connection.java107
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/model/Event.java (renamed from java/broker/src/main/java/org/apache/qpid/server/store/MessageStoreFactory.java)10
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/model/EventType.java60
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/model/Exchange.java2
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/model/Model.java97
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/model/PasswordCredentialManagingAuthenticationProvider.java46
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/model/Port.java91
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/model/Protocol.java33
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/model/Queue.java11
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/model/QueueNotificationListener.java (renamed from java/broker/src/main/java/org/apache/qpid/server/queue/QueueNotificationListener.java)5
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/model/QueueType.java29
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/model/Session.java82
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/model/Statistics.java11
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/model/Transport.java27
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/model/UUIDGenerator.java58
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/model/User.java59
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/model/VirtualHost.java152
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/model/VirtualHostAlias.java37
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/model/adapter/AbstractAdapter.java283
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/model/adapter/AuthenticationProviderAdapter.java488
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/model/adapter/BindingAdapter.java232
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/model/adapter/BrokerAdapter.java494
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/model/adapter/ConnectionAdapter.java313
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/model/adapter/ConsumerAdapter.java225
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/model/adapter/ExchangeAdapter.java437
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/model/adapter/HTTPPortAdapter.java273
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/model/adapter/NoStatistics.java46
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/model/adapter/PortAdapter.java320
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/model/adapter/QueueAdapter.java726
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/model/adapter/SessionAdapter.java240
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/model/adapter/StatisticsAdapter.java67
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/model/adapter/VirtualHostAdapter.java892
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/model/adapter/VirtualHostAliasAdapter.java143
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/output/ProtocolOutputConverterImpl.java2
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/plugins/OsgiSystemPackages.properties47
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/plugins/PluginManager.java91
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/protocol/AMQConnectionModel.java31
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolEngine.java246
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolSession.java18
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolSessionMBean.java344
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/protocol/AMQSessionModel.java30
-rwxr-xr-xjava/broker/src/main/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngine.java2
-rwxr-xr-xjava/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngine_0_10.java11
-rwxr-xr-xjava/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngine_1_0_0.java20
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngine_1_0_0_SASL.java21
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/Connection_1_0.java196
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/LinkRegistry.java20
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/ReceivingLinkAttachment.java20
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/SendingLinkAttachment.java20
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/SendingLink_1_0.java2
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/Session_1_0.java165
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/Subscription_1_0.java45
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/UnsettledAction.java20
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueue.java68
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueFactory.java99
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueMBean.java664
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/queue/ConflationQueueList.java147
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/queue/DefaultQueueRegistry.java50
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/queue/NotificationCheck.java39
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/queue/PriorityQueueList.java17
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntry.java12
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntryImpl.java4
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntryVisitor.java10
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/queue/QueueRegistry.java8
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/queue/SimpleAMQQueue.java496
-rwxr-xr-xjava/broker/src/main/java/org/apache/qpid/server/queue/SubFlushRunner.java2
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/registry/ApplicationRegistry.java322
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/registry/BrokerConfigAdapter.java13
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/registry/ConfigurationFileApplicationRegistry.java16
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/registry/IApplicationRegistry.java48
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/security/auth/database/AbstractPasswordFilePrincipalDatabase.java7
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AnonymousAuthenticationManager.java192
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AuthenticationManager.java20
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AuthenticationManagerRegistry.java203
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/ExternalAuthenticationManager.java177
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/IAuthenticationManagerRegistry.java59
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/KerberosAuthenticationManager.java213
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManager.java88
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/SimpleLDAPAuthenticationManager.java389
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/security/auth/rmi/RMIPasswordAuthenticator.java27
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/external/ExternalSaslServer.java82
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/state/AMQStateManager.java24
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/stats/StatisticsCounter.java8
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/stats/StatisticsGatherer.java12
-rwxr-xr-xjava/broker/src/main/java/org/apache/qpid/server/store/ConfigurationRecoveryHandler.java15
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/store/ConfiguredObjectHelper.java38
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/store/Event.java12
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/store/EventManager.java8
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/store/HAMessageStore.java (renamed from java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/exceptions/ManagementConsoleException.java)16
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/store/MemoryMessageStore.java12
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/store/MessageStore.java2
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/store/MessageStoreConstants.java2
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/store/NullMessageStore.java2
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/store/OperationalLoggingListener.java17
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/store/State.java27
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/store/StateManager.java33
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/store/derby/DerbyMessageStore.java326
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/subscription/AssignedSubscriptionMessageGroupManager.java4
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/subscription/DefinedGroupMessageGroupManager.java4
-rwxr-xr-xjava/broker/src/main/java/org/apache/qpid/server/subscription/ExplicitAcceptDispositionChangeListener.java2
-rwxr-xr-xjava/broker/src/main/java/org/apache/qpid/server/subscription/ImplicitAcceptDispositionChangeListener.java4
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/subscription/Subscription.java12
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionImpl.java95
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/subscription/Subscription_0_10.java64
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/transport/QpidAcceptor.java49
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnection.java183
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnectionDelegate.java60
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnectionMBean.java263
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/transport/ServerSession.java152
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/transport/ServerSessionDelegate.java36
-rwxr-xr-xjava/broker/src/main/java/org/apache/qpid/server/txn/AsyncAutoCommitTransaction.java26
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/txn/DtxBranch.java82
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/txn/DtxRegistry.java11
-rwxr-xr-xjava/broker/src/main/java/org/apache/qpid/server/txn/LocalTransaction.java157
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/virtualhost/HouseKeepingTask.java7
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/virtualhost/State.java4
-rwxr-xr-xjava/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHost.java11
-rwxr-xr-xjava/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostConfigRecoveryHandler.java37
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostImpl.java295
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostRegistry.java31
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/virtualhost/plugins/SlowConsumerDetection.java1
-rw-r--r--java/broker/src/test/java/org/apache/log4j/xml/QpidLog4JConfiguratorTest.java395
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/AMQBrokerManagerMBeanTest.java195
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/BrokerOptionsTest.java27
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/MainTest.java19
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/TransactionTimeoutHelperTest.java101
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/configuration/MockConnectionConfig.java10
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/configuration/QueueConfigurationTest.java43
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/configuration/ServerConfigurationTest.java186
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/configuration/TopicConfigurationTest.java6
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/configuration/VirtualHostConfigurationTest.java3
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/exchange/AbstractHeadersExchangeTestBase.java6
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/exchange/ExchangeMBeanTest.java235
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/exchange/HeadersBindingTest.java55
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/exchange/TopicExchangeTest.java45
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/logging/log4j/LoggingFacadeTest.java245
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/logging/log4j/LoggingFacadeTest.log4j.xml41
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/logging/management/LoggingManagementMBeanTest.java428
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/logging/messages/BrokerMessagesTest.java5
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/management/AMQUserManagementMBeanTest.java153
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/model/UUIDGeneratorTest.java213
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/plugins/OsgiSystemPackageUtilTest.java4
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/protocol/AMQProtocolSessionMBeanTest.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.java348
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueFactoryTest.java59
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueMBeanTest.java553
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/queue/AckTest.java3
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/queue/ConflationQueueListTest.java211
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/queue/MockAMQQueue.java119
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/queue/NotificationCheckTest.java106
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/queue/SimpleAMQQueueTest.java198
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/queue/SimpleAMQQueueThreadPoolTest.java7
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/registry/ApplicationRegistryShutdownTest.java2
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/security/auth/manager/AnonymousAuthenticationManagerTest.java109
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/security/auth/manager/AuthenticationManagerRegistryTest.java304
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/security/auth/manager/ExternalAuthenticationManagerTest.java120
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManagerTest.java2
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/security/auth/rmi/RMIPasswordAuthenticatorTest.java42
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/store/DurableConfigurationStoreTest.java109
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/store/MessageStoreQuotaEventsTestBase.java178
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/store/MessageStoreTest.java19
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/store/OperationalLoggingListenerTest.java44
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/store/StateManagerTest.java62
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/store/derby/DerbyMessageStoreQuotaEventsTest.java62
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/subscription/MockSubscription.java325
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/transport/ServerConnectionMBeanTest.java230
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/txn/AsyncAutoCommitTransactionTest.java140
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/txn/MockStoreTransaction.java6
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/util/InternalBrokerBaseCase.java22
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/util/TestApplicationRegistry.java43
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/virtualhost/HouseKeepingTaskTest.java46
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/virtualhost/MockVirtualHost.java27
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/virtualhost/VirtualHostImplTest.java4
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/virtualhost/plugins/policies/TopicDeletePolicyTest.java12
-rw-r--r--java/build.deps145
-rw-r--r--java/build.xml98
-rw-r--r--java/client/build.xml1
-rwxr-xr-xjava/client/src/main/java/client.bnd2
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/AMQConnection.java30
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/AMQConnectionDelegate_0_10.java1
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/AMQConnectionDelegate_8_0.java13
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/AMQConnectionFactory.java20
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/AMQSession.java39
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/AMQSession_0_10.java38
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/AMQXAResource.java32
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/XAResourceImpl.java99
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/XASessionImpl.java15
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/handler/AccessRequestOkMethodHandler.java2
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/handler/ChannelFlowMethodHandler.java40
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/message/AMQPEncodedMapMessage.java2
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/message/AMQPEncodedMapMessageFactory.java2
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/message/AbstractJMSMessage.java63
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/message/FieldTableSupport.java2
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/message/ReturnMessage.java2
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/security/crammd5hashed/CRAMMD5HashedSaslClient.java91
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/security/crammd5hashed/CRAMMD5HashedSaslClientFactory.java5
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/state/AMQStateManager.java4
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/state/StateWaiter.java5
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/url/URLParser.java2
-rw-r--r--java/client/src/main/java/org/apache/qpid/jms/FailoverPolicy.java4
-rw-r--r--java/client/src/main/java/org/apache/qpid/jms/TopicSubscriber.java2
-rw-r--r--java/client/src/main/java/org/apache/qpid/jndi/PropertiesFileInitialContextFactory.java56
-rw-r--r--java/client/src/main/java/org/apache/qpid/nclient/util/ByteBufferMessage.java2
-rw-r--r--java/client/src/main/java/org/apache/qpid/nclient/util/MessagePartListenerAdapter.java2
-rw-r--r--java/client/src/test/java/org/apache/qpid/client/AMQConnectionFactoryTest.java (renamed from java/client/src/test/java/org/apache/qpid/test/unit/jndi/ConnectionFactoryTest.java)20
-rw-r--r--java/client/src/test/java/org/apache/qpid/client/message/AbstractJMSMessageTest.java2
-rw-r--r--java/client/src/test/java/org/apache/qpid/jndi/PropertiesFileInitialContextFactoryTest.java78
-rw-r--r--java/client/src/test/java/org/apache/qpid/jndi/hello.properties27
-rw-r--r--java/common.xml160
-rw-r--r--java/common/build.xml8
-rwxr-xr-xjava/common/src/main/java/common.bnd2
-rw-r--r--java/common/src/main/java/org/apache/qpid/AMQException.java20
-rw-r--r--java/common/src/main/java/org/apache/qpid/AMQProtocolException.java11
-rw-r--r--java/common/src/main/java/org/apache/qpid/api/Message.java17
-rw-r--r--java/common/src/main/java/org/apache/qpid/configuration/ClientProperties.java24
-rw-r--r--java/common/src/main/java/org/apache/qpid/configuration/Validator.java2
-rw-r--r--java/common/src/main/java/org/apache/qpid/filter/FilterableMessage.java10
-rw-r--r--java/common/src/main/java/org/apache/qpid/filter/SelectorParsingException.java8
-rw-r--r--java/common/src/main/java/org/apache/qpid/framing/AMQMethodBodyImpl.java4
-rw-r--r--java/common/src/main/java/org/apache/qpid/framing/AMQShortStringTokenizer.java5
-rw-r--r--java/common/src/main/java/org/apache/qpid/ssl/SSLContextFactory.java29
-rw-r--r--java/common/src/main/java/org/apache/qpid/thread/RealtimeThreadFactory.java2
-rw-r--r--java/common/src/main/java/org/apache/qpid/thread/ThreadFactory.java2
-rw-r--r--java/common/src/main/java/org/apache/qpid/thread/Threading.java2
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/Connection.java18
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/ConnectionSettings.java27
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/NetworkTransportConfiguration.java22
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/ServerDelegate.java4
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/Session.java35
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/network/NetworkConnection.java10
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/network/io/IoNetworkConnection.java26
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/network/io/IoNetworkTransport.java31
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/network/security/SecurityLayerFactory.java2
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/network/security/sasl/SASLEncryptor.java2
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/network/security/sasl/SASLReceiver.java2
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/network/security/sasl/SASLSender.java2
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/network/security/ssl/QpidClientX509KeyManager.java4
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/network/security/ssl/SSLUtil.java6
-rw-r--r--java/common/src/main/java/org/apache/qpid/url/BindingURLParser.java2
-rw-r--r--java/common/src/main/java/org/apache/qpid/util/Serial.java2
-rw-r--r--java/common/src/test/java/org/apache/qpid/codec/AMQDecoderTest.java2
-rw-r--r--java/common/src/test/java/org/apache/qpid/codec/MockAMQVersionAwareProtocolSession.java2
-rw-r--r--java/common/src/test/java/org/apache/qpid/ssl/SSLContextFactoryTest.java13
-rw-r--r--java/common/src/test/java/org/apache/qpid/test/utils/PortHelper.java127
-rw-r--r--java/common/src/test/java/org/apache/qpid/test/utils/QpidTestCase.java65
-rw-r--r--java/common/src/test/java/org/apache/qpid/test/utils/TestFileUtils.java63
-rw-r--r--java/common/src/test/java/org/apache/qpid/transport/TestNetworkConnection.java12
-rw-r--r--java/common/src/test/java/org/apache/qpid/util/SerialTest.java2
-rwxr-xr-xjava/genpom4
-rw-r--r--java/ivy.nexus.xml (renamed from java/ivy.xml)2
-rw-r--r--java/ivy.retrieve.xml86
-rw-r--r--java/ivysettings.nexus.xml (renamed from java/ivysettings-nexus.xml)3
-rw-r--r--java/ivysettings.retrieve.xml48
-rw-r--r--java/jca/build.xml11
-rw-r--r--java/jca/example/README-EXAMPLE.txt5
-rw-r--r--java/jca/example/build-jboss7-properties.xml15
-rw-r--r--java/jca/example/conf/qpid-standalone.xml2
-rw-r--r--java/jca/src/main/java/org/apache/qpid/ra/QpidRAXAResource.java17
-rw-r--r--java/lib/bdbstore/README.txt14
-rw-r--r--java/lib/bnd-0.0.384.jarbin668180 -> 0 bytes
-rw-r--r--java/lib/cobertura/README.txt9
-rw-r--r--java/lib/com.ibm.icu_3.8.1.v20080530.jarbin4467363 -> 0 bytes
-rw-r--r--java/lib/commons-beanutils-core-1.8.0.jarbin206035 -> 0 bytes
-rw-r--r--java/lib/commons-cli-1.0.jarbin30117 -> 0 bytes
-rw-r--r--java/lib/commons-codec-1.3.jarbin46725 -> 0 bytes
-rw-r--r--java/lib/commons-collections-3.2.jarbin571259 -> 0 bytes
-rw-r--r--java/lib/commons-configuration-1.6.jarbin298829 -> 0 bytes
-rw-r--r--java/lib/commons-digester-1.8.1.jarbin146108 -> 0 bytes
-rw-r--r--java/lib/commons-lang-2.2.jarbin243016 -> 0 bytes
-rw-r--r--java/lib/commons-logging-1.0.4.jarbin38015 -> 0 bytes
-rw-r--r--java/lib/derby-10.6.1.0.jarbin2623509 -> 0 bytes
-rw-r--r--java/lib/findbugs/README.txt30
-rw-r--r--java/lib/geronimo-ejb_3.0_spec-1.0.1.jarbin32102 -> 0 bytes
-rw-r--r--java/lib/geronimo-j2ee-connector_1.5_spec-2.0.0.jarbin37477 -> 0 bytes
-rw-r--r--java/lib/geronimo-jms_1.1_spec-1.0.jarbin28211 -> 0 bytes
-rw-r--r--java/lib/geronimo-jta_1.1_spec-1.1.1.jarbin16030 -> 0 bytes
-rw-r--r--java/lib/geronimo-kernel-2.2.1.jarbin416154 -> 0 bytes
-rw-r--r--java/lib/gson-2.0.jarbin202952 -> 0 bytes
-rw-r--r--java/lib/jackson-core-asl-1.9.0.jarbin228286 -> 0 bytes
-rw-r--r--java/lib/jackson-mapper-asl-1.9.0.jarbin764075 -> 0 bytes
-rw-r--r--java/lib/javacc.jarbin298569 -> 0 bytes
-rw-r--r--java/lib/junit-3.8.1.jarbin121070 -> 0 bytes
-rw-r--r--java/lib/jython-2.5.0.jarbin8580107 -> 0 bytes
-rw-r--r--java/lib/log4j-1.2.12.jarbin358085 -> 0 bytes
-rw-r--r--java/lib/maven-ant-tasks-2.1.1.jarbin1314262 -> 0 bytes
-rw-r--r--java/lib/mockito-all-1.9.0.jarbin1495219 -> 0 bytes
-rw-r--r--java/lib/org.apache.commons.codec_1.3.0.v20080530-1600.jarbin53757 -> 0 bytes
-rw-r--r--java/lib/org.apache.felix.main-2.0.5.jarbin391763 -> 0 bytes
-rw-r--r--java/lib/org.eclipse.core.commands_3.4.0.I20080509-2000.jarbin105794 -> 0 bytes
-rw-r--r--java/lib/org.eclipse.core.contenttype_3.3.0.v20080604-1400.jarbin86969 -> 0 bytes
-rw-r--r--java/lib/org.eclipse.core.databinding_1.1.1.M20080827-0800b.jarbin347799 -> 0 bytes
-rw-r--r--java/lib/org.eclipse.core.expressions_3.4.0.v20080603-2000.jarbin83841 -> 0 bytes
-rw-r--r--java/lib/org.eclipse.core.jobs_3.4.0.v20080512.jarbin82491 -> 0 bytes
-rw-r--r--java/lib/org.eclipse.core.runtime.compatibility.registry_3.2.200.v20080610/META-INF/ECLIPSE.RSAbin3487 -> 0 bytes
-rw-r--r--java/lib/org.eclipse.core.runtime.compatibility.registry_3.2.200.v20080610/META-INF/ECLIPSE.SF17
-rw-r--r--java/lib/org.eclipse.core.runtime.compatibility.registry_3.2.200.v20080610/META-INF/MANIFEST.MF25
-rw-r--r--java/lib/org.eclipse.core.runtime.compatibility.registry_3.2.200.v20080610/META-INF/eclipse.inf3
-rw-r--r--java/lib/org.eclipse.core.runtime.compatibility.registry_3.2.200.v20080610/about.html28
-rw-r--r--java/lib/org.eclipse.core.runtime.compatibility.registry_3.2.200.v20080610/fragment.properties12
-rw-r--r--java/lib/org.eclipse.core.runtime.compatibility.registry_3.2.200.v20080610/runtime_registry_compatibility.jarbin10994 -> 0 bytes
-rw-r--r--java/lib/org.eclipse.core.runtime_3.4.0.v20080512.jarbin69019 -> 0 bytes
-rw-r--r--java/lib/org.eclipse.equinox.app_1.1.0.v20080421-2006.jarbin79866 -> 0 bytes
-rw-r--r--java/lib/org.eclipse.equinox.common_3.4.0.v20080421-2006.jarbin94649 -> 0 bytes
-rw-r--r--java/lib/org.eclipse.equinox.launcher.carbon.macosx_1.0.101.R34x_v20080731/META-INF/ECLIPSE.RSAbin3487 -> 0 bytes
-rw-r--r--java/lib/org.eclipse.equinox.launcher.carbon.macosx_1.0.101.R34x_v20080731/META-INF/ECLIPSE.SF17
-rw-r--r--java/lib/org.eclipse.equinox.launcher.carbon.macosx_1.0.101.R34x_v20080731/META-INF/MANIFEST.MF25
-rw-r--r--java/lib/org.eclipse.equinox.launcher.carbon.macosx_1.0.101.R34x_v20080731/META-INF/eclipse.inf3
-rw-r--r--java/lib/org.eclipse.equinox.launcher.carbon.macosx_1.0.101.R34x_v20080731/about.html28
-rw-r--r--java/lib/org.eclipse.equinox.launcher.carbon.macosx_1.0.101.R34x_v20080731/eclipse_1115.sobin118028 -> 0 bytes
-rw-r--r--java/lib/org.eclipse.equinox.launcher.carbon.macosx_1.0.101.R34x_v20080731/launcher.carbon.macosx.properties12
-rw-r--r--java/lib/org.eclipse.equinox.launcher.gtk.linux.x86_1.0.101.R34x_v20080805/META-INF/ECLIPSE.RSAbin3487 -> 0 bytes
-rw-r--r--java/lib/org.eclipse.equinox.launcher.gtk.linux.x86_1.0.101.R34x_v20080805/META-INF/ECLIPSE.SF17
-rw-r--r--java/lib/org.eclipse.equinox.launcher.gtk.linux.x86_1.0.101.R34x_v20080805/META-INF/MANIFEST.MF25
-rw-r--r--java/lib/org.eclipse.equinox.launcher.gtk.linux.x86_1.0.101.R34x_v20080805/META-INF/eclipse.inf3
-rw-r--r--java/lib/org.eclipse.equinox.launcher.gtk.linux.x86_1.0.101.R34x_v20080805/about.html28
-rw-r--r--java/lib/org.eclipse.equinox.launcher.gtk.linux.x86_1.0.101.R34x_v20080805/eclipse_1115.sobin133193 -> 0 bytes
-rw-r--r--java/lib/org.eclipse.equinox.launcher.gtk.linux.x86_1.0.101.R34x_v20080805/launcher.gtk.linux.x86.properties12
-rw-r--r--java/lib/org.eclipse.equinox.launcher.gtk.linux.x86_64_1.0.101.R34x_v20080731/META-INF/ECLIPSE.RSAbin3487 -> 0 bytes
-rw-r--r--java/lib/org.eclipse.equinox.launcher.gtk.linux.x86_64_1.0.101.R34x_v20080731/META-INF/ECLIPSE.SF17
-rw-r--r--java/lib/org.eclipse.equinox.launcher.gtk.linux.x86_64_1.0.101.R34x_v20080731/META-INF/MANIFEST.MF25
-rw-r--r--java/lib/org.eclipse.equinox.launcher.gtk.linux.x86_64_1.0.101.R34x_v20080731/META-INF/eclipse.inf3
-rw-r--r--java/lib/org.eclipse.equinox.launcher.gtk.linux.x86_64_1.0.101.R34x_v20080731/about.html28
-rw-r--r--java/lib/org.eclipse.equinox.launcher.gtk.linux.x86_64_1.0.101.R34x_v20080731/eclipse_1115.sobin169725 -> 0 bytes
-rw-r--r--java/lib/org.eclipse.equinox.launcher.gtk.linux.x86_64_1.0.101.R34x_v20080731/launcher.gtk.linux.x86_64.properties12
-rw-r--r--java/lib/org.eclipse.equinox.launcher.gtk.solaris.sparc_1.0.101.R34x_v20080731/META-INF/ECLIPSE.RSAbin3487 -> 0 bytes
-rw-r--r--java/lib/org.eclipse.equinox.launcher.gtk.solaris.sparc_1.0.101.R34x_v20080731/META-INF/ECLIPSE.SF17
-rw-r--r--java/lib/org.eclipse.equinox.launcher.gtk.solaris.sparc_1.0.101.R34x_v20080731/META-INF/MANIFEST.MF25
-rw-r--r--java/lib/org.eclipse.equinox.launcher.gtk.solaris.sparc_1.0.101.R34x_v20080731/META-INF/eclipse.inf3
-rw-r--r--java/lib/org.eclipse.equinox.launcher.gtk.solaris.sparc_1.0.101.R34x_v20080731/about.html28
-rw-r--r--java/lib/org.eclipse.equinox.launcher.gtk.solaris.sparc_1.0.101.R34x_v20080731/eclipse_1115.sobin76500 -> 0 bytes
-rw-r--r--java/lib/org.eclipse.equinox.launcher.gtk.solaris.sparc_1.0.101.R34x_v20080731/launcher.gtk.solaris.sparc.properties12
-rw-r--r--java/lib/org.eclipse.equinox.launcher.win32.win32.x86_1.0.101.R34x_v20080731/META-INF/ECLIPSE.RSAbin3487 -> 0 bytes
-rw-r--r--java/lib/org.eclipse.equinox.launcher.win32.win32.x86_1.0.101.R34x_v20080731/META-INF/ECLIPSE.SF17
-rw-r--r--java/lib/org.eclipse.equinox.launcher.win32.win32.x86_1.0.101.R34x_v20080731/META-INF/MANIFEST.MF25
-rw-r--r--java/lib/org.eclipse.equinox.launcher.win32.win32.x86_1.0.101.R34x_v20080731/META-INF/eclipse.inf3
-rw-r--r--java/lib/org.eclipse.equinox.launcher.win32.win32.x86_1.0.101.R34x_v20080731/about.html28
-rw-r--r--java/lib/org.eclipse.equinox.launcher.win32.win32.x86_1.0.101.R34x_v20080731/eclipse_1115.dllbin81920 -> 0 bytes
-rw-r--r--java/lib/org.eclipse.equinox.launcher.win32.win32.x86_1.0.101.R34x_v20080731/launcher.win32.win32.x86.properties12
-rw-r--r--java/lib/org.eclipse.equinox.launcher_1.0.101.R34x_v20080819.jarbin43682 -> 0 bytes
-rw-r--r--java/lib/org.eclipse.equinox.preferences_3.2.201.R34x_v20080709.jarbin104280 -> 0 bytes
-rw-r--r--java/lib/org.eclipse.equinox.registry_3.4.0.v20080516-0950.jarbin172936 -> 0 bytes
-rw-r--r--java/lib/org.eclipse.help_3.3.101.v20080702_34x.jarbin216698 -> 0 bytes
-rw-r--r--java/lib/org.eclipse.jface.databinding_1.2.1.M20080827-0800a.jarbin196505 -> 0 bytes
-rw-r--r--java/lib/org.eclipse.jface_3.4.1.M20080827-2000.jarbin1040433 -> 0 bytes
-rw-r--r--java/lib/org.eclipse.osgi_3.4.2.R34x_v20080826-1230.jarbin997883 -> 0 bytes
-rw-r--r--java/lib/org.eclipse.swt.carbon.macosx_3.4.1.v3449c.jarbin1852007 -> 0 bytes
-rw-r--r--java/lib/org.eclipse.swt.gtk.linux.x86_3.4.1.v3449c.jarbin2006608 -> 0 bytes
-rw-r--r--java/lib/org.eclipse.swt.gtk.linux.x86_64_3.4.1.v3449c.jarbin2123120 -> 0 bytes
-rw-r--r--java/lib/org.eclipse.swt.gtk.solaris.sparc_3.4.1.v3449c.jarbin1877410 -> 0 bytes
-rw-r--r--java/lib/org.eclipse.swt.win32.win32.x86_3.4.1.v3449c.jarbin2123125 -> 0 bytes
-rw-r--r--java/lib/org.eclipse.swt_3.4.1.v3449c.jarbin15807 -> 0 bytes
-rw-r--r--java/lib/org.eclipse.ui.forms_3.3.101.v20080708_34x.jarbin298053 -> 0 bytes
-rw-r--r--java/lib/org.eclipse.ui.workbench_3.4.1.M20080827-0800a.jarbin3922042 -> 0 bytes
-rw-r--r--java/lib/org.eclipse.ui_3.4.1.M20080910-0800.jarbin145322 -> 0 bytes
-rw-r--r--java/lib/poms/commons-beanutils-core-1.8.3.xml (renamed from java/lib/poms/commons-beanutils-core-1.8.0.xml)2
-rw-r--r--java/lib/poms/commons-cli-1.2.xml (renamed from java/lib/poms/commons-cli-1.0.xml)2
-rw-r--r--java/lib/poms/commons-codec-1.6.xml (renamed from java/lib/poms/commons-codec-1.3.xml)2
-rw-r--r--java/lib/poms/commons-collections-3.2.1.xml (renamed from java/lib/poms/commons-collections-3.2.xml)2
-rw-r--r--java/lib/poms/commons-configuration-1.8.xml (renamed from java/lib/poms/commons-configuration-1.6.xml)2
-rw-r--r--java/lib/poms/commons-lang-2.6.xml (renamed from java/lib/poms/commons-lang-2.2.xml)2
-rw-r--r--java/lib/poms/commons-logging-1.1.1.xml (renamed from java/lib/poms/commons-logging-1.0.4.xml)2
-rw-r--r--java/lib/poms/derby-10.8.2.2.xml (renamed from java/lib/poms/derby-10.6.1.0.xml)2
-rw-r--r--java/lib/poms/geronimo-servlet_2.5_spec-1.2.xml22
-rw-r--r--java/lib/poms/je-5.0.55.xml (renamed from java/lib/poms/je-5.0.34.xml)2
-rw-r--r--java/lib/poms/jetty-continuation-7.6.3.v20120416.xml22
-rw-r--r--java/lib/poms/jetty-http-7.6.3.v20120416.xml28
-rw-r--r--java/lib/poms/jetty-io-7.6.3.v20120416.xml28
-rw-r--r--java/lib/poms/jetty-security-7.6.3.v20120416.xml28
-rw-r--r--java/lib/poms/jetty-server-7.6.3.v20120416.xml36
-rw-r--r--java/lib/poms/jetty-servlet-7.6.3.v20120416.xml28
-rw-r--r--java/lib/poms/jetty-util-7.6.3.v20120416.xml22
-rw-r--r--java/lib/poms/jetty-websocket-7.6.3.v20120416.xml36
-rw-r--r--java/lib/poms/log4j-1.2.16.xml (renamed from java/lib/poms/log4j-1.2.12.xml)2
-rw-r--r--java/lib/poms/slf4j-api-1.6.4.xml (renamed from java/lib/poms/slf4j-api-1.6.1.xml)2
-rw-r--r--java/lib/poms/slf4j-log4j12-1.6.4.xml (renamed from java/lib/poms/slf4j-log4j12-1.6.1.xml)2
-rw-r--r--java/lib/slf4j-api-1.6.1.jarbin25496 -> 0 bytes
-rw-r--r--java/lib/slf4j-log4j12-1.6.1.jarbin9753 -> 0 bytes
-rw-r--r--java/lib/xalan-2.7.0.jarbin2730442 -> 0 bytes
-rw-r--r--java/management/common/build.xml1
-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/ManagedQueue.java44
-rw-r--r--java/management/common/src/main/java/org/apache/qpid/management/common/mbeans/ServerInformation.java2
-rw-r--r--java/management/eclipse-plugin/META-INF/MANIFEST.MF22
-rw-r--r--java/management/eclipse-plugin/build-release-linux-gtk-x86.properties36
-rw-r--r--java/management/eclipse-plugin/build-release-linux-gtk-x86_64.properties36
-rw-r--r--java/management/eclipse-plugin/build-release-macosx.properties40
-rw-r--r--java/management/eclipse-plugin/build-release-macosx.xml101
-rw-r--r--java/management/eclipse-plugin/build-release-solaris-gtk-sparc.properties39
-rw-r--r--java/management/eclipse-plugin/build-release-win32-win32-x86.properties34
-rw-r--r--java/management/eclipse-plugin/build-release.xml172
-rw-r--r--java/management/eclipse-plugin/build.xml88
-rw-r--r--java/management/eclipse-plugin/icons/add.gifbin318 -> 0 bytes
-rw-r--r--java/management/eclipse-plugin/icons/back.gifbin327 -> 0 bytes
-rw-r--r--java/management/eclipse-plugin/icons/configuration_management.gifbin343 -> 0 bytes
-rw-r--r--java/management/eclipse-plugin/icons/delete.gifbin143 -> 0 bytes
-rw-r--r--java/management/eclipse-plugin/icons/failure.gifbin353 -> 0 bytes
-rw-r--r--java/management/eclipse-plugin/icons/icon_ClosedFolder.gifbin160 -> 0 bytes
-rw-r--r--java/management/eclipse-plugin/icons/icon_OpenFolder.gifbin152 -> 0 bytes
-rw-r--r--java/management/eclipse-plugin/icons/logging_management.gifbin381 -> 0 bytes
-rw-r--r--java/management/eclipse-plugin/icons/mbean_view.pngbin2046 -> 0 bytes
-rw-r--r--java/management/eclipse-plugin/icons/notifications.gifbin104 -> 0 bytes
-rw-r--r--java/management/eclipse-plugin/icons/qpidConnections.gifbin200 -> 0 bytes
-rw-r--r--java/management/eclipse-plugin/icons/qpidmc.gifbin1225 -> 0 bytes
-rw-r--r--java/management/eclipse-plugin/icons/qpidmc16.gifbin928 -> 0 bytes
-rw-r--r--java/management/eclipse-plugin/icons/qpidmc32.bmpbin1139 -> 0 bytes
-rw-r--r--java/management/eclipse-plugin/icons/qpidmc32.gifbin1139 -> 0 bytes
-rw-r--r--java/management/eclipse-plugin/icons/reconnect.gifbin327 -> 0 bytes
-rw-r--r--java/management/eclipse-plugin/icons/refresh.gifbin336 -> 0 bytes
-rw-r--r--java/management/eclipse-plugin/icons/server_information.gifbin614 -> 0 bytes
-rw-r--r--java/management/eclipse-plugin/icons/splash.bmpbin275178 -> 0 bytes
-rw-r--r--java/management/eclipse-plugin/icons/stop.gifbin215 -> 0 bytes
-rw-r--r--java/management/eclipse-plugin/icons/success.gifbin343 -> 0 bytes
-rw-r--r--java/management/eclipse-plugin/icons/user_management.gifbin597 -> 0 bytes
-rw-r--r--java/management/eclipse-plugin/icons/virtualhost_manager.gifbin607 -> 0 bytes
-rw-r--r--java/management/eclipse-plugin/plugin.properties20
-rw-r--r--java/management/eclipse-plugin/plugin.xml225
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/Activator.java83
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ApiVersion.java110
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/Application.java63
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ApplicationActionBarAdvisor.java97
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ApplicationRegistry.java191
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ApplicationWorkbenchAdvisor.java46
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ApplicationWorkbenchWindowAdvisor.java65
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/Constants.java153
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ManagedBean.java176
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ManagedServer.java84
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/Perspective.java47
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/RefreshIntervalComboPanel.java132
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ServerRegistry.java263
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/actions/AbstractAction.java220
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/actions/AddServer.java316
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/actions/BackAction.java60
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/actions/CloseConnection.java58
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/actions/ReconnectServer.java267
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/actions/Refresh.java54
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/actions/RemoveServer.java51
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/actions/VersionAction.java95
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/jmx/ClientListener.java86
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/jmx/ClientNotificationListener.java40
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/jmx/JMXManagedObject.java70
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/jmx/JMXServerRegistry.java619
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/jmx/MBeanUtility.java612
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/model/AttributeData.java100
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/model/ManagedAttributeModel.java120
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/model/NotificationInfoModel.java51
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/model/NotificationObject.java131
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/model/OperationData.java110
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/model/OperationDataModel.java71
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/model/ParameterData.java103
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/AttributesTabControl.java937
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/MBeanTabFolderFactory.java466
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/MBeanView.java609
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/NavigationView.java1358
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/NotificationsTabControl.java393
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/OperationTabControl.java938
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/TabControl.java104
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/TreeObject.java126
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/VHNotificationsTabControl.java485
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/ViewUtility.java1036
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/connection/ConnectionOperationsTabControl.java545
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/exchange/ExchangeOperationsTabControl.java722
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/exchange/HeadersExchangeOperationsTabControl.java711
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/logging/ConfigurationFileTabControl.java590
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/logging/LoggingTableLabelProvider.java58
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/logging/LoggingTableSorter.java90
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/logging/RuntimeTabControl.java594
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/queue/QueueOperationsTabControl.java1111
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/type/ConnectionTypeTabControl.java51
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/type/MBeanTypeTabControl.java521
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/type/QueueTypeTabControl.java774
-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.java1016
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/vhost/VHostTabControl.java870
-rw-r--r--java/management/eclipse-plugin/src/main/resources/.eclipseproduct23
-rw-r--r--java/management/eclipse-plugin/src/main/resources/jmxremote.sasl-plugin/MANIFEST.MF20
-rw-r--r--java/management/eclipse-plugin/src/main/resources/linux-gtk-x86/Configuration/config.ini49
-rw-r--r--java/management/eclipse-plugin/src/main/resources/linux-gtk-x86/libcairo-swt.sobin266168 -> 0 bytes
-rw-r--r--java/management/eclipse-plugin/src/main/resources/linux-gtk-x86/qpidmcbin52576 -> 0 bytes
-rw-r--r--java/management/eclipse-plugin/src/main/resources/linux-gtk-x86/qpidmc.ini37
-rw-r--r--java/management/eclipse-plugin/src/main/resources/linux-gtk-x86_64/Configuration/config.ini49
-rw-r--r--java/management/eclipse-plugin/src/main/resources/linux-gtk-x86_64/libcairo-swt.sobin335360 -> 0 bytes
-rw-r--r--java/management/eclipse-plugin/src/main/resources/linux-gtk-x86_64/qpidmcbin67927 -> 0 bytes
-rw-r--r--java/management/eclipse-plugin/src/main/resources/linux-gtk-x86_64/qpidmc.ini37
-rw-r--r--java/management/eclipse-plugin/src/main/resources/macosx/Configuration/config.ini49
-rw-r--r--java/management/eclipse-plugin/src/main/resources/macosx/Contents/Info.plist55
-rwxr-xr-xjava/management/eclipse-plugin/src/main/resources/macosx/Contents/MacOS/qpidmcbin59200 -> 0 bytes
-rw-r--r--java/management/eclipse-plugin/src/main/resources/macosx/Contents/MacOS/qpidmc.ini42
-rw-r--r--java/management/eclipse-plugin/src/main/resources/macosx/Contents/Resources/Console.icnsbin51007 -> 0 bytes
-rw-r--r--java/management/eclipse-plugin/src/main/resources/solaris-gtk-sparc/Configuration/config.ini49
-rw-r--r--java/management/eclipse-plugin/src/main/resources/solaris-gtk-sparc/Qpidmc.l.pm311
-rw-r--r--java/management/eclipse-plugin/src/main/resources/solaris-gtk-sparc/Qpidmc.m.pm295
-rw-r--r--java/management/eclipse-plugin/src/main/resources/solaris-gtk-sparc/Qpidmc.s.pm287
-rw-r--r--java/management/eclipse-plugin/src/main/resources/solaris-gtk-sparc/Qpidmc.t.pm279
-rwxr-xr-xjava/management/eclipse-plugin/src/main/resources/solaris-gtk-sparc/qpidmcbin31668 -> 0 bytes
-rw-r--r--java/management/eclipse-plugin/src/main/resources/solaris-gtk-sparc/qpidmc.ini40
-rw-r--r--java/management/eclipse-plugin/src/main/resources/win32-win32-x86/Configuration/config.ini49
-rw-r--r--java/management/eclipse-plugin/src/main/resources/win32-win32-x86/qpidmc.exebin57344 -> 0 bytes
-rw-r--r--java/management/eclipse-plugin/src/main/resources/win32-win32-x86/qpidmc.ini36
-rw-r--r--java/management/eclipse-plugin/src/test/java/org/apache/qpid/management/ui/ApiVersionTest.java177
-rw-r--r--java/management/eclipse-plugin/src/test/java/org/apache/qpid/management/ui/ApplicationRegistryTest.java43
-rw-r--r--java/management/eclipse-plugin/src/test/java/org/apache/qpid/management/ui/ManagementConsoleTest.java123
-rw-r--r--java/management/example/build.xml1
-rw-r--r--java/module.xml136
-rw-r--r--java/perftests/build.xml26
-rw-r--r--java/perftests/etc/chartdefs/1001-MessageSize-Transient.chartdef (renamed from java/perftests/etc/chartdefs/MessageSizeNonPersistent.chartdef)11
-rw-r--r--java/perftests/etc/chartdefs/1002-MessageSize-Persistent.chartdef (renamed from java/perftests/etc/chartdefs/MessageSizePersistent.chartdef)9
-rw-r--r--java/perftests/etc/chartdefs/1011-VaryingNumberOfProducers.chartdef (renamed from java/perftests/etc/chartdefs/VaryingNumberOfProducers.chartdef)7
-rw-r--r--java/perftests/etc/chartdefs/1012-VaryingNumberOfConsumers.chartdef (renamed from java/perftests/etc/chartdefs/VaryingNumberOfConsumers.chartdef)7
-rw-r--r--java/perftests/etc/chartdefs/1021-AcknowledgementModes-AutoAck.chartdef (renamed from java/perftests/etc/chartdefs/AcknowledgementModesAutoAck.chartdef)7
-rw-r--r--java/perftests/etc/chartdefs/1022-AcknowledgementModes-Transacted.chartdef (renamed from java/perftests/etc/chartdefs/AcknowledgementModesTransacted.chartdef)6
-rw-r--r--java/perftests/etc/chartdefs/1030-BatchSize.chartdef (renamed from java/perftests/etc/chartdefs/BatchSize.chartdef)7
-rw-r--r--java/perftests/etc/chartdefs/1040-QueueTypes.chartdef (renamed from java/perftests/etc/chartdefs/QueueTypes.chartdef)4
-rw-r--r--java/perftests/etc/chartdefs/1500-Topic-NumberOfConsumers.chartdef32
-rw-r--r--java/perftests/etc/chartdefs/1501-Topic-NumberOfTopics.chartdef32
-rw-r--r--java/perftests/etc/chartdefs/1502-Topic-Persistence.chartdef32
-rw-r--r--java/perftests/etc/chartdefs/1503-Topic-AckModes.chartdef32
-rw-r--r--java/perftests/etc/chartdefs/2001-Latency-MessageSize-Transient.chartdef40
-rw-r--r--java/perftests/etc/chartdefs/2002-Latency-MessageSize-Persistent.chartdef40
-rw-r--r--java/perftests/etc/chartdefs/2011-Latency-QueuesWithNonOverlappingSelectors-Transient.chartdef40
-rw-r--r--java/perftests/etc/chartdefs/2012-Latency-QueuesWithOverlappingSelectors-Transient.chartdef40
-rw-r--r--java/perftests/etc/chartdefs/2021-Latency-QueuesWithNonOverlappingSelectors-Persistent.chartdef40
-rw-r--r--java/perftests/etc/chartdefs/2022-Latency-QueuesWithOverlappingSelectors-Persistent.chartdef40
-rw-r--r--java/perftests/etc/chartdefs/2031-Latency-VaryingNumberOfParticipants.chartdef44
-rw-r--r--java/perftests/etc/chartdefs/2041-Latency-QueueTypes.chartdef40
-rw-r--r--java/perftests/etc/log4j.properties2
-rw-r--r--java/perftests/etc/perftests-jndi.properties6
-rw-r--r--java/perftests/etc/testdefs/AcknowledgementModes.json (renamed from java/perftests/etc/testdefs/short/AcknowledgementModes.json)20
-rw-r--r--java/perftests/etc/testdefs/BatchSize.json (renamed from java/perftests/etc/testdefs/short/BatchSize.json)0
-rw-r--r--java/perftests/etc/testdefs/Latency-MessageSize.json (renamed from java/perftests/etc/testdefs/standard/MessageSize.json)106
-rw-r--r--java/perftests/etc/testdefs/Latency-QueueTypes.json261
-rw-r--r--java/perftests/etc/testdefs/Latency-QueuesWithSelectors.json (renamed from java/perftests/etc/testdefs/standard/QueuesWithSelectors.json)258
-rw-r--r--java/perftests/etc/testdefs/Latency-VaryingNumberOfParticipants.json (renamed from java/perftests/etc/testdefs/standard/VaryingNumberOfParticipants.json)756
-rw-r--r--java/perftests/etc/testdefs/MessageSize.json (renamed from java/perftests/etc/testdefs/short/MessageSize.json)81
-rw-r--r--java/perftests/etc/testdefs/QueueTypes.json (renamed from java/perftests/etc/testdefs/short/QueueTypes.json)12
-rw-r--r--java/perftests/etc/testdefs/Topic-AckModes.js68
-rw-r--r--java/perftests/etc/testdefs/Topic-NumberOfConsumers.js65
-rw-r--r--java/perftests/etc/testdefs/Topic-NumberOfTopics.js70
-rw-r--r--java/perftests/etc/testdefs/Topic-Persistence.js70
-rw-r--r--java/perftests/etc/testdefs/VaryingNumberOfParticipants.json (renamed from java/perftests/etc/testdefs/short/VaryingNumberOfParticipants.json)0
-rw-r--r--java/perftests/etc/testdefs/standard/AcknowledgementModes.json138
-rw-r--r--java/perftests/etc/testdefs/standard/BatchSize.json84
-rw-r--r--java/perftests/etc/testdefs/standard/QueueTypes.json16205
-rw-r--r--java/perftests/example/log4j.properties4
-rw-r--r--java/perftests/example/perftests-jndi.properties2
-rw-r--r--java/perftests/example/perftests.js106
-rw-r--r--java/perftests/src/main/java/json2.js487
-rw-r--r--java/perftests/src/main/java/org/apache/qpid/disttest/ConfigFileHelper.java74
-rw-r--r--java/perftests/src/main/java/org/apache/qpid/disttest/ControllerRunner.java54
-rw-r--r--java/perftests/src/main/java/org/apache/qpid/disttest/DistributedTestConstants.java6
-rw-r--r--java/perftests/src/main/java/org/apache/qpid/disttest/client/Client.java10
-rw-r--r--java/perftests/src/main/java/org/apache/qpid/disttest/client/ConsumerParticipant.java59
-rw-r--r--java/perftests/src/main/java/org/apache/qpid/disttest/client/MessageProvider.java8
-rw-r--r--java/perftests/src/main/java/org/apache/qpid/disttest/client/ParticipantExecutor.java6
-rw-r--r--java/perftests/src/main/java/org/apache/qpid/disttest/client/ParticipantResultFactory.java20
-rw-r--r--java/perftests/src/main/java/org/apache/qpid/disttest/client/ProducerParticipant.java82
-rw-r--r--java/perftests/src/main/java/org/apache/qpid/disttest/client/utils/ExecutorWithLimits.java (renamed from java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ManagedObject.java)27
-rw-r--r--java/perftests/src/main/java/org/apache/qpid/disttest/client/utils/ExecutorWithLimitsFactory.java49
-rw-r--r--java/perftests/src/main/java/org/apache/qpid/disttest/client/utils/ExecutorWithNoLimits.java (renamed from java/broker/src/test/java/org/apache/qpid/server/store/TestableMemoryMessageStoreFactory.java)17
-rw-r--r--java/perftests/src/main/java/org/apache/qpid/disttest/client/utils/ExecutorWithTimeLimit.java65
-rw-r--r--java/perftests/src/main/java/org/apache/qpid/disttest/controller/Controller.java13
-rw-r--r--java/perftests/src/main/java/org/apache/qpid/disttest/controller/TestRunner.java17
-rw-r--r--java/perftests/src/main/java/org/apache/qpid/disttest/controller/config/ConfigReader.java22
-rw-r--r--java/perftests/src/main/java/org/apache/qpid/disttest/controller/config/ConsumerConfig.java22
-rw-r--r--java/perftests/src/main/java/org/apache/qpid/disttest/controller/config/JavaScriptConfigEvaluator.java64
-rw-r--r--java/perftests/src/main/java/org/apache/qpid/disttest/controller/config/ParticipantConfig.java39
-rw-r--r--java/perftests/src/main/java/org/apache/qpid/disttest/controller/config/ProducerConfig.java2
-rw-r--r--java/perftests/src/main/java/org/apache/qpid/disttest/controller/config/QueueConfig.java3
-rw-r--r--java/perftests/src/main/java/org/apache/qpid/disttest/jms/ClientJmsDelegate.java168
-rw-r--r--java/perftests/src/main/java/org/apache/qpid/disttest/jms/ControllerJmsDelegate.java38
-rw-r--r--java/perftests/src/main/java/org/apache/qpid/disttest/jms/NoOpQueueCreator.java (renamed from java/systests/src/main/java/org/apache/qpid/server/store/SlowMessageStoreFactory.java)18
-rw-r--r--java/perftests/src/main/java/org/apache/qpid/disttest/jms/QpidQueueCreator.java8
-rw-r--r--java/perftests/src/main/java/org/apache/qpid/disttest/message/ConsumerParticipantResult.java67
-rw-r--r--java/perftests/src/main/java/org/apache/qpid/disttest/message/CreateConsumerCommand.java12
-rw-r--r--java/perftests/src/main/java/org/apache/qpid/disttest/message/ParticipantAttribute.java9
-rw-r--r--java/perftests/src/main/java/org/apache/qpid/disttest/results/aggregation/ParticipantResultAggregator.java59
-rw-r--r--java/perftests/src/main/java/org/apache/qpid/disttest/results/aggregation/SeriesStatistics.java111
-rw-r--r--java/perftests/src/main/java/test-utils.js85
-rw-r--r--java/perftests/src/test/java/org/apache/qpid/disttest/ConfigFileHelperTest.java79
-rw-r--r--java/perftests/src/test/java/org/apache/qpid/disttest/ConfigFileTestHelper.java (renamed from java/perftests/src/test/java/org/apache/qpid/disttest/ConfigFileHelper.java)2
-rw-r--r--java/perftests/src/test/java/org/apache/qpid/disttest/client/ClientTest.java2
-rw-r--r--java/perftests/src/test/java/org/apache/qpid/disttest/client/ConsumerParticipantTest.java23
-rw-r--r--java/perftests/src/test/java/org/apache/qpid/disttest/client/MessageProviderTest.java1
-rw-r--r--java/perftests/src/test/java/org/apache/qpid/disttest/client/ProducerParticipantTest.java2
-rw-r--r--java/perftests/src/test/java/org/apache/qpid/disttest/client/property/ListPropertyValueTest.java1
-rw-r--r--java/perftests/src/test/java/org/apache/qpid/disttest/client/property/PropertyValueFactoryTest.java1
-rw-r--r--java/perftests/src/test/java/org/apache/qpid/disttest/client/property/RandomPropertyValueTest.java1
-rw-r--r--java/perftests/src/test/java/org/apache/qpid/disttest/client/property/RangePropertyValueTest.java1
-rw-r--r--java/perftests/src/test/java/org/apache/qpid/disttest/client/utils/ExecutorWithNoLimitsTest.java61
-rw-r--r--java/perftests/src/test/java/org/apache/qpid/disttest/client/utils/ExecutorWithTimeLimitTest.java131
-rw-r--r--java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/ConfigReaderTest-test-config.js34
-rw-r--r--java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/ConfigReaderTest.java40
-rw-r--r--java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/IterationValueTest.java33
-rw-r--r--java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/JavaScriptConfigEvaluatorTest-test-config.js23
-rw-r--r--java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/JavaScriptConfigEvaluatorTest.java81
-rw-r--r--java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/ParticipantConfigTest.java43
-rw-r--r--java/perftests/src/test/java/org/apache/qpid/disttest/message/ParticipantResultTest.java4
-rw-r--r--java/perftests/src/test/java/org/apache/qpid/disttest/results/aggregation/SeriesStatisticsTest.java (renamed from java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/logging/LoggingTableContentProvider.java)46
-rw-r--r--java/perftests/src/test/java/org/apache/qpid/disttest/results/aggregation/TestResultAggregatorTest.java52
-rw-r--r--java/perftests/src/test/java/org/apache/qpid/disttest/results/formatting/CSVFormaterTest.java10
-rw-r--r--java/perftests/src/test/java/org/apache/qpid/disttest/results/formatting/expectedOutput.csv4
-rw-r--r--java/perftests/src/test/java/org/apache/qpid/systest/disttest/clientonly/ControllerQueue.java22
-rw-r--r--java/perftests/src/test/java/org/apache/qpid/systest/disttest/clientonly/DistributedClientTest.java18
-rw-r--r--java/perftests/src/test/java/org/apache/qpid/systest/disttest/controllerandclient/ControllerAndClientTest.java22
-rw-r--r--java/perftests/src/test/java/org/apache/qpid/systest/disttest/controllerandclient/producerAndConsumerInSeparateClients.json3
-rw-r--r--java/perftests/src/test/java/org/apache/qpid/systest/disttest/controlleronly/DistributedControllerTest.java4
-rw-r--r--java/perftests/src/test/java/org/apache/qpid/systest/disttest/endtoend/EndToEndTest.java6
-rw-r--r--java/perftests/visualisation-jfc/build.xml83
-rw-r--r--java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/ChartType.java3
-rw-r--r--java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/ChartingUtil.java71
-rw-r--r--java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/BarChart3DBuilder.java56
-rw-r--r--java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/BarChartBuilder.java15
-rw-r--r--java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/BaseChartBuilder.java58
-rw-r--r--java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/CategoryDataSetBasedChartBuilder.java (renamed from java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/DataSetBasedChartBuilder.java)48
-rw-r--r--java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/ChartBuilder.java6
-rw-r--r--java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/ChartBuilderFactory.java15
-rw-r--r--java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/LineChart3DBuilder.java52
-rw-r--r--java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/LineChartBuilder.java16
-rw-r--r--java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/StatisticalBarCharBuilder.java111
-rw-r--r--java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/XYDataSetBasedChartBuilder.java103
-rw-r--r--java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/XYLineChartBuilder.java51
-rw-r--r--java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/definition/ChartingDefinition.java12
-rw-r--r--java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/definition/ChartingDefinitionCreator.java9
-rw-r--r--java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/seriesbuilder/JdbcCsvSeriesBuilder.java (renamed from java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/SeriesBuilder.java)26
-rw-r--r--java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/seriesbuilder/SeriesBuilder.java (renamed from java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/INotificationViewer.java)22
-rw-r--r--java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/seriesbuilder/SeriesBuilderCallback.java (renamed from java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/DataPointCallback.java)9
-rw-r--r--java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/writer/ChartWriter.java139
-rw-r--r--java/perftests/visualisation-jfc/src/test/java/org/apache/qpid/disttest/charting/chartbuilder/ChartBuilderFactoryTest.java26
-rw-r--r--java/perftests/visualisation-jfc/src/test/java/org/apache/qpid/disttest/charting/chartbuilder/ChartProductionTest.java198
-rw-r--r--java/perftests/visualisation-jfc/src/test/java/org/apache/qpid/disttest/charting/definition/ChartingDefinitionCreatorTest.java4
-rw-r--r--java/perftests/visualisation-jfc/src/test/java/org/apache/qpid/disttest/charting/seriesbuilder/JdbcCsvSeriesBuilderTest.java (renamed from java/perftests/visualisation-jfc/src/test/java/org/apache/qpid/disttest/charting/chartbuilder/SeriesBuilderTest.java)18
-rw-r--r--java/perftests/visualisation-jfc/src/test/java/org/apache/qpid/disttest/charting/writer/ChartWriterTest.java117
-rw-r--r--java/perftests/visualisation-jfc/src/test/java/org/apache/qpid/disttest/charting/writer/expected-chart-summary.html9
-rw-r--r--java/systests/build.xml7
-rw-r--r--java/systests/etc/config-systests-bdb.xml1
-rw-r--r--java/systests/etc/config-systests-derby-mem-settings.xml (renamed from java/broker-plugins/extras/build.xml)21
-rw-r--r--java/systests/etc/config-systests-derby-mem.xml29
-rw-r--r--java/systests/etc/config-systests-derby.xml1
-rw-r--r--java/systests/etc/config-systests-firewall.xml1
-rw-r--r--java/systests/etc/config-systests-settings.xml62
-rw-r--r--java/systests/etc/config-systests.xml1
-rw-r--r--java/systests/etc/log.properties2
-rw-r--r--java/systests/etc/virtualhosts-systests-bdb-settings.xml6
-rw-r--r--java/systests/etc/virtualhosts-systests-bdb.xml2
-rw-r--r--java/systests/etc/virtualhosts-systests-derby-mem-settings.xml54
-rw-r--r--java/systests/etc/virtualhosts-systests-derby-mem.xml29
-rw-r--r--java/systests/etc/virtualhosts-systests-derby-settings.xml6
-rw-r--r--java/systests/etc/virtualhosts-systests-derby.xml2
-rw-r--r--java/systests/etc/virtualhosts-systests-firewall-2.xml4
-rw-r--r--java/systests/etc/virtualhosts-systests-firewall-3.xml4
-rw-r--r--java/systests/etc/virtualhosts-systests-firewall.xml2
-rw-r--r--java/systests/etc/virtualhosts-systests-settings.xml157
-rw-r--r--java/systests/etc/virtualhosts-systests.xml2
-rw-r--r--java/systests/src/main/java/org/apache/qpid/client/failover/FailoverBehaviourTest.java185
-rw-r--r--java/systests/src/main/java/org/apache/qpid/client/message/AMQPEncodedMapMessageTest.java2
-rw-r--r--java/systests/src/main/java/org/apache/qpid/client/ssl/SSLTest.java1
-rw-r--r--java/systests/src/main/java/org/apache/qpid/jms/xa/XAResourceTest.java73
-rw-r--r--java/systests/src/main/java/org/apache/qpid/management/jmx/ManagedConnectionMBeanTest.java278
-rw-r--r--java/systests/src/main/java/org/apache/qpid/management/jmx/ManagedQueueMBeanTest.java345
-rw-r--r--java/systests/src/main/java/org/apache/qpid/management/jmx/MessageConnectionStatisticsTest.java101
-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.java109
-rw-r--r--java/systests/src/main/java/org/apache/qpid/management/jmx/MessageStatisticsTest.java196
-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/ra/QpidRAXAResourceTest.java67
-rw-r--r--java/systests/src/main/java/org/apache/qpid/server/SupportedProtocolVersionsTest.java102
-rw-r--r--java/systests/src/main/java/org/apache/qpid/server/queue/ConflationQueueTest.java449
-rw-r--r--java/systests/src/main/java/org/apache/qpid/server/queue/ModelTest.java2
-rw-r--r--java/systests/src/main/java/org/apache/qpid/server/security/acl/ExternalACLJMXTest.java3
-rw-r--r--java/systests/src/main/java/org/apache/qpid/server/security/auth/manager/MultipleAuthenticationManagersTest.java109
-rw-r--r--java/systests/src/main/java/org/apache/qpid/server/stats/StatisticsReportingTest.java (renamed from java/systests/src/main/java/org/apache/qpid/management/jmx/MessageStatisticsReportingTest.java)94
-rw-r--r--java/systests/src/main/java/org/apache/qpid/server/store/QuotaMessageStore.java180
-rw-r--r--java/systests/src/main/java/org/apache/qpid/server/store/SlowMessageStore.java7
-rw-r--r--java/systests/src/main/java/org/apache/qpid/server/store/StoreOverfullTest.java343
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/client/DupsOkTest.java40
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/client/message/SelectorTest.java2
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/client/timeouts/SyncWaitDelayTest.java2
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/unit/client/MaxDeliveryCountTest.java74
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/unit/client/connection/BrokerClosesClientConnectionTest.java1
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/unit/client/connection/ConnectionFactoryTest.java19
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/unit/transacted/TransactionTimeoutTest.java2
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/unit/xa/FaultTest.java33
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/utils/BrokerHolder.java1
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/utils/InternalBrokerHolder.java51
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/utils/JMXTestUtils.java101
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/utils/QpidBrokerTestCase.java340
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/utils/SpawnedBrokerHolder.java44
-rwxr-xr-xjava/test-profiles/CPPExcludes20
-rwxr-xr-xjava/test-profiles/Java010Excludes9
-rw-r--r--java/test-profiles/JavaExcludes9
-rw-r--r--java/test-profiles/JavaPre010Excludes10
-rw-r--r--java/test-profiles/JavaTransientExcludes10
-rw-r--r--java/test-profiles/java-bdb-spawn.0-10.testprofile5
-rw-r--r--java/test-profiles/java-bdb-spawn.0-8.testprofile4
-rw-r--r--java/test-profiles/java-bdb-spawn.0-9-1.testprofile4
-rw-r--r--java/test-profiles/java-bdb-spawn.0-9.testprofile4
-rw-r--r--java/test-profiles/java-bdb.0-10.testprofile5
-rw-r--r--java/test-profiles/java-bdb.0-8.testprofile6
-rw-r--r--java/test-profiles/java-bdb.0-9-1.testprofile4
-rw-r--r--java/test-profiles/java-bdb.0-9.testprofile4
-rw-r--r--[-rwxr-xr-x]java/test-profiles/java-dby-mem.0-10.testprofile (renamed from java/broker-plugins/experimental/shutdown/src/main/java/shutdown.bnd)20
-rw-r--r--java/test-profiles/java-dby-mem.0-8.testprofile36
-rw-r--r--java/test-profiles/java-dby-mem.0-9-1.testprofile36
-rw-r--r--java/test-profiles/java-dby-mem.0-9.testprofile36
-rw-r--r--java/test-profiles/java-dby-spawn.0-10.testprofile5
-rw-r--r--java/test-profiles/java-dby-spawn.0-8.testprofile4
-rw-r--r--java/test-profiles/java-dby-spawn.0-9-1.testprofile4
-rw-r--r--java/test-profiles/java-dby-spawn.0-9.testprofile4
-rw-r--r--java/test-profiles/java-dby.0-10.testprofile5
-rw-r--r--java/test-profiles/java-dby.0-8.testprofile4
-rw-r--r--java/test-profiles/java-dby.0-9-1.testprofile4
-rw-r--r--java/test-profiles/java-dby.0-9.testprofile4
-rw-r--r--java/test-profiles/java-mms-spawn.0-10.testprofile3
-rw-r--r--java/test-profiles/java-mms-spawn.0-8.testprofile2
-rw-r--r--java/test-profiles/java-mms-spawn.0-9-1.testprofile2
-rw-r--r--java/test-profiles/java-mms-spawn.0-9.testprofile2
-rw-r--r--java/test-profiles/java-mms.0-10.testprofile3
-rw-r--r--java/test-profiles/java-mms.0-8.testprofile2
-rw-r--r--java/test-profiles/java-mms.0-9-1.testprofile2
-rw-r--r--java/test-profiles/java-mms.0-9.testprofile2
-rw-r--r--java/test-profiles/log4j-test.xml1
-rw-r--r--java/test-profiles/python_tests/Java010PythonExcludes1
-rw-r--r--java/test-profiles/python_tests/JavaPre010PythonExcludes34
-rw-r--r--java/test-profiles/test_resources/ssl/java_broker_keystore.jksbin2475 -> 2464 bytes
-rw-r--r--java/test-profiles/testprofile.defaults4
-rwxr-xr-xjava/tools/bin/Profile-run-from-source2
-rwxr-xr-x[-rw-r--r--]java/tools/bin/mercury-controller0
-rwxr-xr-x[-rw-r--r--]java/tools/bin/mercury-start-consumers0
-rwxr-xr-x[-rw-r--r--]java/tools/bin/mercury-start-producers0
-rwxr-xr-xjava/tools/bin/qpid-jms-benchmark316
-rwxr-xr-xjava/tools/bin/qpid-jms-receive193
-rwxr-xr-xjava/tools/bin/qpid-jms-send261
-rw-r--r--java/tools/build.xml5
-rw-r--r--java/tools/src/main/java/org/apache/qpid/testkit/ErrorHandler.java2
-rw-r--r--java/tools/src/main/java/org/apache/qpid/tools/Clock.java11
-rw-r--r--java/tools/src/main/java/org/apache/qpid/tools/JVMArgConfiguration.java749
-rw-r--r--java/tools/src/main/java/org/apache/qpid/tools/MessageFactory.java2
-rw-r--r--java/tools/src/main/java/org/apache/qpid/tools/QpidReceive.java296
-rw-r--r--java/tools/src/main/java/org/apache/qpid/tools/QpidSend.java460
-rw-r--r--java/tools/src/main/java/org/apache/qpid/tools/TestConfiguration.java118
-rw-r--r--java/tools/src/main/java/org/apache/qpid/tools/report/Statistics.java222
-rw-r--r--java/upload.xml90
-rw-r--r--packaging/windows/INSTALL_NOTES.html8
-rw-r--r--packaging/windows/installer.proj2
-rw-r--r--python/qpid/connection.py5
-rw-r--r--python/qpid/delegates.py67
-rw-r--r--python/qpid/framer.py14
-rw-r--r--python/qpid/messaging/util.py9
-rw-r--r--python/qpid/sasl.py3
-rw-r--r--python/qpid/selector.py24
-rw-r--r--python/qpid/tests/messaging/endpoints.py12
-rw-r--r--python/qpid/util.py4
-rwxr-xr-xpython/setup.py2
-rw-r--r--specs/apache-filters.xml7
-rw-r--r--specs/management-schema.xml42
-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/management.py13
-rw-r--r--tests/src/py/qpid_tests/broker_0_10/qmf_events.py83
-rw-r--r--tests/src/py/qpid_tests/broker_0_10/query.py2
-rwxr-xr-xtools/setup.py2
-rw-r--r--tools/src/py/.gitignore1
-rwxr-xr-xtools/src/py/qpid-cluster27
-rwxr-xr-xtools/src/py/qpid-config25
-rwxr-xr-xtools/src/py/qpid-ha86
-rwxr-xr-xtools/src/py/qpid-printevents126
-rwxr-xr-xtools/src/py/qpid-queue-stats14
-rwxr-xr-xtools/src/py/qpid-route31
-rwxr-xr-xtools/src/py/qpid-stat56
-rwxr-xr-xtools/src/py/qpid-tool10
-rw-r--r--tools/src/py/qpidtoollibs/broker.py46
-rw-r--r--tools/src/py/qpidtoollibs/disp.py12
-rw-r--r--wcf/src/Apache/Qpid/Interop/InputLink.cpp1
1336 files changed, 58702 insertions, 57534 deletions
diff --git a/QPID_VERSION.txt b/QPID_VERSION.txt
index 50653ad0a6..caa4836d8e 100644
--- a/QPID_VERSION.txt
+++ b/QPID_VERSION.txt
@@ -1 +1 @@
-0.17
+0.19
diff --git a/bin/release.sh b/bin/release.sh
index decc1cdd75..a2a187b4bc 100755
--- a/bin/release.sh
+++ b/bin/release.sh
@@ -205,19 +205,19 @@ fi
if [ "JAVA" == "$JAVA" ] ; then
# generate the java 'release' archive seperately to ensure it doesnt have any optional feature dependencies in it
pushd qpid-${VER}/java
- ant build release -Dsvnversion.output=${REV}
+ ant clean build release -Dsvnversion.output=${REV}
popd
cp qpid-${VER}/java/release/*.tar.gz artifacts/qpid-java-${VER}.tar.gz
# now generate the binary packages, with the glue for optional features
pushd qpid-${VER}/java
- ant build release-bin release-mvn -Dsvnversion.output=${REV} -Dmaven.snapshot=false -Dmodules.opt=bdbstore -Ddownload-bdb=true
+ ant build release-bin -Dsvnversion.output=${REV} -Dmodules.opt="bdbstore,bdbstore/jmx" -Ddownload-bdb=true
+ ant release-mvn -Dsvnversion.output=${REV} -Dmodules.opt="bdbstore,bdbstore/jmx" -Dmaven.snapshot=false
popd
cp qpid-${VER}/java/broker/release/*.tar.gz artifacts/qpid-java-broker-${VER}.tar.gz
cp qpid-${VER}/java/client/release/*.tar.gz artifacts/qpid-java-client-${VER}.tar.gz
- 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/
@@ -225,6 +225,12 @@ if [ "JAVA" == "$JAVA" ] ; then
cp -a qpid-${VER}/java/broker/release/maven artifacts/
cp -a qpid-${VER}/java/bdbstore/release/maven artifacts/
cp -a qpid-${VER}/java/management/common/release/maven artifacts/
+ cp -a qpid-${VER}/java/amqp-1-0-common/release/maven artifacts/
+ cp -a qpid-${VER}/java/broker-plugins/access-control/release/maven artifacts/
+ cp -a qpid-${VER}/java/broker-plugins/firewall/release/maven artifacts/
+ cp -a qpid-${VER}/java/broker-plugins/management-jmx/release/maven artifacts/
+ cp -a qpid-${VER}/java/broker-plugins/management-http/release/maven artifacts/
+ cp -a qpid-${VER}/java/bdbstore/jmx/release/maven artifacts/
fi
if [ "TOOLS" = "$TOOLS" ] ; then
diff --git a/cpp/bindings/qmf/ruby/CMakeLists.txt b/cpp/bindings/qmf/ruby/CMakeLists.txt
index 4b6ba2c1c3..702606139b 100644
--- a/cpp/bindings/qmf/ruby/CMakeLists.txt
+++ b/cpp/bindings/qmf/ruby/CMakeLists.txt
@@ -21,13 +21,12 @@
## 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")
+
+include_directories(${RUBY_INCLUDE_DIRS} ${qpid-cpp_SOURCE_DIR}/include)
swig_add_module(qmfengine_ruby ruby ${CMAKE_CURRENT_SOURCE_DIR}/ruby.i)
swig_link_libraries(qmfengine_ruby qmf qmfconsole ${RUBY_LIBRARY})
-set_source_files_properties(${swig_generated_file_fullname} PROPERTIES COMPILE_FLAGS "-I${RUBY_INCLUDE_DIR} -I${qpid-cpp_SOURCE_DIR}/include")
-
##----------------------------------
## Install the complete Ruby binding
##----------------------------------
diff --git a/cpp/bindings/qmf2/ruby/CMakeLists.txt b/cpp/bindings/qmf2/ruby/CMakeLists.txt
index 3bc97cf35f..1cb969f7dc 100644
--- a/cpp/bindings/qmf2/ruby/CMakeLists.txt
+++ b/cpp/bindings/qmf2/ruby/CMakeLists.txt
@@ -21,13 +21,12 @@
## 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")
+
+include_directories(${RUBY_INCLUDE_DIRS} ${qpid-cpp_SOURCE_DIR}/include)
swig_add_module(cqmf2_ruby ruby ${CMAKE_CURRENT_SOURCE_DIR}/ruby.i)
swig_link_libraries(cqmf2_ruby qmf2 ${RUBY_LIBRARY})
-set_source_files_properties(${swig_generated_file_fullname} PROPERTIES COMPILE_FLAGS "-I${RUBY_INCLUDE_DIR} -I${qpid-cpp_SOURCE_DIR}/include")
-
##----------------------------------
## Install the complete Ruby binding
##----------------------------------
diff --git a/cpp/bindings/qpid/python/python.i b/cpp/bindings/qpid/python/python.i
index a53cf3b853..4d8a64b376 100644
--- a/cpp/bindings/qpid/python/python.i
+++ b/cpp/bindings/qpid/python/python.i
@@ -33,41 +33,68 @@
* names as in the C++ library. They get renamed to their Python
* equivalents when brought into the Python wrapping
*/
+%define QPID_EXCEPTION(exception, parent)
%{
-static PyObject* pNoMessageAvailable;
-static PyObject* pTargetCapacityExceeded;
-static PyObject* pNotFound;
-static PyObject* pTransportFailure;
+static PyObject* exception;
%}
-
%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);
+ exception = PyErr_NewException(
+ (char *) ("_cqpid." #exception), parent, NULL);
+ Py_INCREF(exception);
+ PyModule_AddObject(m, #exception, exception);
%}
-
%pythoncode %{
- Empty = _cqpid.NoMessageAvailable
- TargetCapacityExceeded = _cqpid.TargetCapacityExceeded
- NotFound = _cqpid.NotFound
- ConnectError = _cqpid.TransportFailure
+ exception = _cqpid. ## exception
%}
+%enddef
+
+ /* Python equivalents of C++ exceptions. */
+ /* */
+ /* Commented out lines are exceptions in the Python library, but not */
+ /* in the C++ library. */
+
+QPID_EXCEPTION(MessagingError, NULL)
+
+QPID_EXCEPTION(LinkError, MessagingError)
+QPID_EXCEPTION(AddressError, LinkError)
+QPID_EXCEPTION(ResolutionError, AddressError)
+QPID_EXCEPTION(AssertionFailed, ResolutionError)
+QPID_EXCEPTION(NotFound, ResolutionError)
+QPID_EXCEPTION(InvalidOption, LinkError)
+QPID_EXCEPTION(MalformedAddress, LinkError)
+QPID_EXCEPTION(ReceiverError, LinkError)
+QPID_EXCEPTION(FetchError, ReceiverError)
+QPID_EXCEPTION(Empty, FetchError)
+/* QPID_EXCEPTION(InsufficientCapacity, LinkError) */
+/* QPID_EXCEPTION(LinkClosed, LinkError) */
+QPID_EXCEPTION(SenderError, LinkError)
+QPID_EXCEPTION(SendError, SenderError)
+QPID_EXCEPTION(TargetCapacityExceeded, SendError)
+
+QPID_EXCEPTION(ConnectionError, MessagingError)
+QPID_EXCEPTION(ConnectError, ConnectionError)
+/* QPID_EXCEPTION(AuthenticationFailure, ConnectError) */
+/* QPID_EXCEPTION(VersionError, ConnectError) */
+/* QPID_EXCEPTION(ConnectionClosed, ConnectionError) */
+/* QPID_EXCEPTION(HeartbeartTimeout, ConnectionError) */
+
+QPID_EXCEPTION(SessionError, MessagingError)
+/* QPID_EXCEPTION(Detached, SessionError) */
+/* QPID_EXCEPTION(NontransactionalSession, SessionError) */
+/* QPID_EXCEPTION(ServerError, SessionError) */
+/* QPID_EXCEPTION(SessionClosed, SessionError) */
+QPID_EXCEPTION(TransactionError, SessionError)
+QPID_EXCEPTION(TransactionAborted, TransactionError)
+QPID_EXCEPTION(UnauthorizedAccess, SessionError)
+
+/* QPID_EXCEPTION(InternalError, MessagingError) */
+
+%define TRANSLATE_EXCEPTION(cpp_exception, py_exception)
+ catch ( cpp_exception & ex) {
+ pExceptionType = py_exception;
+ error = ex.what();
+ }
+%enddef
/* Define the general-purpose exception handling */
%exception {
@@ -76,22 +103,31 @@ static PyObject* pTransportFailure;
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();
}
+ /* Catch and translate exceptions. */
+ TRANSLATE_EXCEPTION(qpid::messaging::NoMessageAvailable, Empty)
+ TRANSLATE_EXCEPTION(qpid::messaging::NotFound, NotFound)
+ TRANSLATE_EXCEPTION(qpid::messaging::AssertionFailed, AssertionFailed)
+ TRANSLATE_EXCEPTION(qpid::messaging::ResolutionError, ResolutionError)
+ TRANSLATE_EXCEPTION(qpid::messaging::TargetCapacityExceeded,
+ TargetCapacityExceeded)
+ TRANSLATE_EXCEPTION(qpid::messaging::TransportFailure, ConnectError)
+ TRANSLATE_EXCEPTION(qpid::messaging::MalformedAddress, MalformedAddress)
+ TRANSLATE_EXCEPTION(qpid::messaging::AddressError, AddressError)
+ TRANSLATE_EXCEPTION(qpid::messaging::FetchError, FetchError)
+ TRANSLATE_EXCEPTION(qpid::messaging::ReceiverError, ReceiverError)
+ TRANSLATE_EXCEPTION(qpid::messaging::SendError, SendError)
+ TRANSLATE_EXCEPTION(qpid::messaging::SenderError, SenderError)
+ TRANSLATE_EXCEPTION(qpid::messaging::InvalidOptionString, InvalidOption)
+ TRANSLATE_EXCEPTION(qpid::messaging::LinkError, LinkError)
+ TRANSLATE_EXCEPTION(qpid::messaging::TransactionAborted, TransactionAborted)
+ TRANSLATE_EXCEPTION(qpid::messaging::TransactionError, TransactionError)
+ TRANSLATE_EXCEPTION(qpid::messaging::UnauthorizedAccess, UnauthorizedAccess)
+ TRANSLATE_EXCEPTION(qpid::messaging::SessionError, SessionError)
+ TRANSLATE_EXCEPTION(qpid::messaging::ConnectionError, ConnectionError)
+ TRANSLATE_EXCEPTION(qpid::messaging::KeyError, PyExc_KeyError)
+ TRANSLATE_EXCEPTION(qpid::messaging::MessagingException, MessagingError)
+ TRANSLATE_EXCEPTION(qpid::types::Exception, PyExc_RuntimeError)
Py_END_ALLOW_THREADS;
if (!error.empty()) {
PyErr_SetString(pExceptionType, error.c_str());
diff --git a/cpp/bindings/qpid/ruby/CMakeLists.txt b/cpp/bindings/qpid/ruby/CMakeLists.txt
index 8a8c88b595..9b32ff5728 100644
--- a/cpp/bindings/qpid/ruby/CMakeLists.txt
+++ b/cpp/bindings/qpid/ruby/CMakeLists.txt
@@ -30,12 +30,13 @@ 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")
+
+include_directories(${RUBY_INCLUDE_DIRS} ${qpid-cpp_SOURCE_DIR}/include)
swig_add_module(cqpid_ruby ruby ${CMAKE_CURRENT_SOURCE_DIR}/ruby.i)
swig_link_libraries(cqpid_ruby 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")
+set_source_files_properties(${swig_generated_file_fullname} PROPERTIES COMPILE_FLAGS "-fno-strict-aliasing")
##----------------------------------
## Install the complete Ruby binding
diff --git a/cpp/bindings/qpid/ruby/LICENSE b/cpp/bindings/qpid/ruby/LICENSE
index cff2a5e25d..232fd660d6 100644
--- a/cpp/bindings/qpid/ruby/LICENSE
+++ b/cpp/bindings/qpid/ruby/LICENSE
@@ -203,32 +203,3 @@
WITHOUT 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/README.rdoc b/cpp/bindings/qpid/ruby/README.rdoc
index 478fc939d9..5c60a15588 100644
--- a/cpp/bindings/qpid/ruby/README.rdoc
+++ b/cpp/bindings/qpid/ruby/README.rdoc
@@ -2,7 +2,7 @@
Qpid is an cross-platform enterprise messaging system.
-Version :: 0.17.0
+Version :: 0.19.0
= Links
diff --git a/cpp/bindings/qpid/ruby/features/creating_a_receiver.feature b/cpp/bindings/qpid/ruby/features/creating_a_receiver.feature
index f509f49115..1f758153af 100644
--- a/cpp/bindings/qpid/ruby/features/creating_a_receiver.feature
+++ b/cpp/bindings/qpid/ruby/features/creating_a_receiver.feature
@@ -21,9 +21,9 @@ Feature: Creating a receiver
Scenario: The address string is fine
Given an open session
- Then creating a receiver with "my-queue;{create:always}" succeeds
+ Then creating a receiver with "my-queue;{create:always,delete:always}" succeeds
Scenario: Using an Address object
Given an open session
- And an Address with the name "create-receiver-test" and subject "foo" and option "create" set to "always"
+ And an Address with the name "create-receiver-test" and subject "foo" and option "create" set to "always" and "delete" set to "always"
Then creating a receiver with an Address succeeds
diff --git a/cpp/bindings/qpid/ruby/features/creating_a_sender.feature b/cpp/bindings/qpid/ruby/features/creating_a_sender.feature
index ac75543c2d..1c09ff837d 100644
--- a/cpp/bindings/qpid/ruby/features/creating_a_sender.feature
+++ b/cpp/bindings/qpid/ruby/features/creating_a_sender.feature
@@ -5,11 +5,11 @@ Feature: Creating a sender
Scenario: The session is closed
Given a closed session
- Then creating a sender with "my-queue;{create:always}" raises an exception
+ Then creating a sender with "my-queue;{create:always,delete:always}" raises an exception
Scenario: The connection is closed
Given an open session with a closed connection
- Then creating a sender with "my-queue;{create:always}" raises an exception
+ Then creating a sender with "my-queue;{create:always,delete:always}" raises an exception
Scenario: The address is malformed
Given an open session
@@ -17,7 +17,7 @@ Feature: Creating a sender
Scenario: The address string is valid
Given an open session
- Then creating a sender with "my-queue;{create:always}" succeeds
+ Then creating a sender with "my-queue;{create:always,delete:always}" succeeds
Scenario: Using an Address object
Given an open session
diff --git a/cpp/bindings/qpid/ruby/features/receiving_a_message.feature b/cpp/bindings/qpid/ruby/features/receiving_a_message.feature
index b68a78c337..7b6db4a5ac 100644
--- a/cpp/bindings/qpid/ruby/features/receiving_a_message.feature
+++ b/cpp/bindings/qpid/ruby/features/receiving_a_message.feature
@@ -4,24 +4,26 @@ Feature: Receving a message
I need to be able to receive messages
Scenario: Receiving after the session is closed
- Given a sender and receiver for "my-queue;{create:always}"
+ Given a sender and receiver for "my-queue;{create:always,delete:always}"
And the message "this is a test" is sent
And the session is closed
Then getting the next message raises an error
Scenario: Receiving after the connection is closed
- Given a sender and receiver for "my-queue;{create:always}"
+ Given a sender and receiver for "my-queue;{create:always,delete:always}"
And the message "this is a test" is sent
And the connection is closed
Then getting the next message raises an error
Scenario: No message is received on an empty queue
- Given an existing receiver for "my-queue;{create:always}"
+ Given an existing receiver for "my-queue;{create:always,delete:always}"
And the receiver has no pending messages
Then getting the next message raises an error
Scenario: A message is pending
- Given a sender and receiver for "my-queue;{create:always}"
+ Given an open session
+ And given a sender for "my-queue;{create:always}"
+ And given a receiver for "my-queue;{create:always,delete:always}"
And the receiver has a capacity of 1
And the message "this is a test" is sent
Then the receiver should have 1 message available
diff --git a/cpp/bindings/qpid/ruby/features/sending_a_message.feature b/cpp/bindings/qpid/ruby/features/sending_a_message.feature
index b1127d3664..45cbd42f06 100644
--- a/cpp/bindings/qpid/ruby/features/sending_a_message.feature
+++ b/cpp/bindings/qpid/ruby/features/sending_a_message.feature
@@ -5,17 +5,17 @@ Feature: Sending a message
Scenario: The session is closed
Given an open session
- And creating a sender with "my-queue;{create:always}" succeeds
+ And creating a sender with "my-queue;{create:always,delete:always}" succeeds
And the session is closed
Then sending the message "This is a test" should raise an error
Scenario: The connection is closed
Given an open session
- And creating a sender with "my-queue;{create:always}" succeeds
+ And creating a sender with "my-queue;{create:always,delete:always}" succeeds
And the connection is closed
Then sending the message "This is a test" should raise an error
Scenario: The message sends successfully
Given an open session
- And creating a sender with "my-queue;{create:always}" succeeds
+ And creating a sender with "my-queue;{create:always,delete:always}" succeeds
Then sending the message "This is a test" succeeds \ No newline at end of file
diff --git a/cpp/bindings/qpid/ruby/features/step_definitions/address_steps.rb b/cpp/bindings/qpid/ruby/features/step_definitions/address_steps.rb
index 845cc2b116..0531e5ee69 100644
--- a/cpp/bindings/qpid/ruby/features/step_definitions/address_steps.rb
+++ b/cpp/bindings/qpid/ruby/features/step_definitions/address_steps.rb
@@ -22,3 +22,10 @@ Given /^an Address with the name "([^"]*)" and subject "([^"]*)" and option "([^
options["#{key}"] = "#{value}"
@address = Qpid::Messaging::Address.new "#{name}", "#{subject}", options
end
+
+Given /^an Address with the name "([^"]*)" and subject "([^"]*)" and option "([^"]*)" set to "([^"]*)" and "([^"]*)" set to "([^"]*)"$/ do |name, subject, key1, value1, key2, value2|
+ options = Hash.new
+ options["#{key1}"] = "#{value1}"
+ options["#{key2}"] = "#{value2}"
+ @address = Qpid::Messaging::Address.new "#{name}", "#{subject}", options
+end
diff --git a/cpp/bindings/qpid/ruby/features/step_definitions/receiver_steps.rb b/cpp/bindings/qpid/ruby/features/step_definitions/receiver_steps.rb
index a8c8aa4a43..e454dac345 100644
--- a/cpp/bindings/qpid/ruby/features/step_definitions/receiver_steps.rb
+++ b/cpp/bindings/qpid/ruby/features/step_definitions/receiver_steps.rb
@@ -59,3 +59,11 @@ Then /^the receiver should have (\d+) message available$/ do |available|
sleep 1
@receiver.available.should == available.to_i
end
+
+Given /^given a sender for "([^"]*)"$/ do |address|
+ @sender = @session.create_sender "#{address}"
+end
+
+Given /^given a receiver for "([^"]*)"$/ do |address|
+ @receiver = @session.create_receiver "#{address}"
+end
diff --git a/cpp/design_docs/log-model-category-for-correlation.txt b/cpp/design_docs/log-model-category-for-correlation.txt
new file mode 100644
index 0000000000..69253a417a
--- /dev/null
+++ b/cpp/design_docs/log-model-category-for-correlation.txt
@@ -0,0 +1,112 @@
+This documennt describes the new logging entries written for
+"QPID-4079 C++ Broker needs log messages to track object life cycles for auditing".
+
+Please see https://issues.apache.org/jira/browse/QPID-4079 for an overview.
+
+The basic features are simple:
+
+* A new log category, [Model], is added and only the new log entries use it.
+
+* At 'debug' log level are log entries that mirror the corresponding management
+ events. Debug level statements include user names, remote host information, and
+ other references using the user-specified names for the referenced objects.
+
+* At 'trace' log level are log entries that track the construction and destruction
+ of managed resources. Trace level statements identify the objects using the
+ internal management keys. The trace statement for each deleted object includes the
+ management statistics for that object.
+
+Enabling the Model log
+
+* Use the switch: '--log-enable trace+:Model' to receive both flavors of log
+* Use the switch: '--log-enable debug+:Model' for a less verbose log
+
+Managed Objects in the logs
+
+All managed objects are included in the trace log.
+The debug log has information for:
+ Connection, Queue, Exchange, Binding, Subscription
+
+The following section lists actual log file data sorted and paired with the
+corresponding management Event captured with qpid-printevents.
+
+1. Connection
+
+Create connection
+event: Fri Jul 13 17:46:23 2012 org.apache.qpid.broker:clientConnect rhost=[::1]:5672-[::1]:34383 user=anonymous
+debug: 2012-07-13 13:46:23 [Model] debug Create connection. user:anonymous rhost:[::1]:5672-[::1]:34383
+trace: 2012-07-13 13:46:23 [Model] trace Mgmt create connection. id:[::1]:5672-[::1]:34383
+
+Delete connection
+event: Fri Jul 13 17:46:23 2012 org.apache.qpid.broker:clientDisconnect rhost=[::1]:5672-[::1]:34383 user=anonymous
+debug: 2012-07-13 13:46:23 [Model] debug Delete connection. user:anonymous rhost:[::1]:5672-[::1]:34383
+trace: 2012-07-13 13:46:29 [Model] trace Mgmt delete connection. id:[::1]:5672-[::1]:34383
+ Statistics: {bytesFromClient:1451, bytesToClient:892, closing:False, framesFromClient:25, framesToClient:21, msgsFromClient:1, msgsToClient:1}
+
+2. Session
+
+Create session
+event: TBD
+debug: TBD
+trace: 2012-07-13 13:46:09 [Model] trace Mgmt create session. id:18f52c22-efc5-4c2f-bd09-902d2a02b948:0
+
+Delete session
+event: TBD
+debug: TBD
+trace: 2012-07-13 13:47:13 [Model] trace Mgmt delete session. id:18f52c22-efc5-4c2f-bd09-902d2a02b948:0
+ Statistics: {TxnCommits:0, TxnCount:0, TxnRejects:0, TxnStarts:0, clientCredit:0, unackedMessages:0}
+
+
+3. Exchange
+
+Create exchange
+event: Fri Jul 13 17:46:34 2012 org.apache.qpid.broker:exchangeDeclare disp=created exName=myE exType=topic durable=False args={} autoDel=False rhost=[::1]:5672-[::1]:34384 altEx= user=anonymous
+debug: 2012-07-13 13:46:34 [Model] debug Create exchange. name:myE user:anonymous rhost:[::1]:5672-[::1]:34384 type:topic alternateExchange: durable:F
+trace: 2012-07-13 13:46:34 [Model] trace Mgmt create exchange. id:myE
+
+
+Delete exchange
+event: Fri Jul 13 18:19:33 2012 org.apache.qpid.broker:exchangeDelete exName=myE rhost=[::1]:5672-[::1]:37199 user=anonymous
+debug: 2012-07-13 14:19:33 [Model] debug Delete exchange. name:myE user:anonymous rhost:[::1]:5672-[::1]:37199
+trace: 2012-07-13 14:19:42 [Model] trace Mgmt delete exchange. id:myE
+ Statistics: {bindingCount:0, bindingCountHigh:0, bindingCountLow:0, byteDrops:0, byteReceives:0, byteRoutes:0, msgDrops:0, msgReceives:0, msgRoutes:0, producerCount:0, producerCountHigh:0, producerCountLow:0}
+
+
+4. Queue
+
+Create queue
+event: Fri Jul 13 18:19:35 2012 org.apache.qpid.broker:queueDeclare disp=created durable=False args={} qName=myQ autoDel=False rhost=[::1]:5672-[::1]:37200 altEx= excl=False user=anonymous
+debug: 2012-07-13 14:19:35 [Model] debug Create queue. name:myQ user:anonymous rhost:[::1]:5672-[::1]:37200 durable:F owner:0 autodelete:F alternateExchange:
+trace: 2012-07-13 14:19:35 [Model] trace Mgmt create queue. id:myQ
+
+Delete queue
+event: Fri Jul 13 18:19:37 2012 org.apache.qpid.broker:queueDelete user=anonymous qName=myQ rhost=[::1]:5672-[::1]:37201
+debug: 2012-07-13 14:19:37 [Model] debug Delete queue. name:myQ user:anonymous rhost:[::1]:5672-[::1]:37201
+trace: 2012-07-13 14:19:42 [Model] trace Mgmt delete queue. id:myQ
+ Statistics: {acquires:0, bindingCount:0, bindingCountHigh:0, bindingCountLow:0, byteDepth:0, byteFtdDepth:0, byteFtdDequeues:0, byteFtdEnqueues:0, bytePersistDequeues:0, bytePersistEnqueues:0, byteTotalDequeues:0, byteTotalEnqueues:0, byteTxnDequeues:0, byteTxnEnqueues:0, consumerCount:0, consumerCountHigh:0, consumerCountLow:0, discardsLvq:0, discardsOverflow:0, discardsPurge:0, discardsRing:0, discardsSubscriber:0, discardsTtl:0, flowStopped:False, flowStoppedCount:0, messageLatencyAvg:0, messageLatencyCount:0, messageLatencyMax:0, messageLatencyMin:0, msgDepth:0, msgFtdDepth:0, msgFtdDequeues:0, msgFtdEnqueues:0, msgPersistDequeues:0, msgPersistEnqueues:0, msgTotalDequeues:0, msgTotalEnqueues:0, msgTxnDequeues:0, msgTxnEnqueues:0, releases:0, reroutes:0, unackedMessages:0, unackedMessagesHigh:0, unackedMessagesLow:0}
+
+5. Binding
+
+Create binding
+event: Fri Jul 13 17:46:45 2012 org.apache.qpid.broker:bind exName=myE args={} qName=myQ user=anonymous key=myKey rhost=[::1]:5672-[::1]:34385
+debug: 2012-07-13 13:46:45 [Model] debug Create binding. exchange:myE queue:myQ key:myKey user:anonymous rhost:[::1]:5672-[::1]:34385
+trace: 2012-07-13 13:46:23 [Model] trace Mgmt create binding. id:org.apache.qpid.broker:exchange:,org.apache.qpid.broker:queue:myQ,myQ
+
+Delete binding
+event: Fri Jul 13 17:47:06 2012 org.apache.qpid.broker:unbind user=anonymous exName=myE qName=myQ key=myKey rhost=[::1]:5672-[::1]:34386
+debug: 2012-07-13 13:47:06 [Model] debug Delete binding. exchange:myE queue:myQ key:myKey user:anonymous rhost:[::1]:5672-[::1]:34386
+trace: 2012-07-13 13:47:09 [Model] trace Mgmt delete binding. id:org.apache.qpid.broker:exchange:myE,org.apache.qpid.broker:queue:myQ,myKey
+ Statistics: {msgMatched:0}
+
+6, Subscription
+
+Create subscription
+event: Fri Jul 13 18:19:28 2012 org.apache.qpid.broker:subscribe dest=0 args={} qName=b78b1818-7a20-4341-a253-76216b40ab4a:0.0 user=anonymous excl=False rhost=[::1]:5672-[::1]:37198
+debug: 2012-07-13 14:19:28 [Model] debug Create subscription. queue:b78b1818-7a20-4341-a253-76216b40ab4a:0.0 destination:0 user:anonymous rhost:[::1]:5672-[::1]:37198 exclusive:F
+trace: 2012-07-13 14:19:28 [Model] trace Mgmt create subscription. id:org.apache.qpid.broker:session:b78b1818-7a20-4341-a253-76216b40ab4a:0,org.apache.qpid.broker:queue:b78b1818-7a20-4341-a253-76216b40ab4a:0.0,0
+
+Delete subscription
+event: Fri Jul 13 18:19:28 2012 org.apache.qpid.broker:unsubscribe dest=0 rhost=[::1]:5672-[::1]:37198 user=anonymous
+debug: 2012-07-13 14:19:28 [Model] debug Delete subscription. destination:0 user:anonymous rhost:[::1]:5672-[::1]:37198
+trace: 2012-07-13 14:19:32 [Model] trace Mgmt delete subscription. id:org.apache.qpid.broker:session:b78b1818-7a20-4341-a253-76216b40ab4a:0,org.apache.qpid.broker:queue:b78b1818-7a20-4341-a253-76216b40ab4a:0.0,0
+ Statistics: {delivered:1}
diff --git a/cpp/etc/Makefile.am b/cpp/etc/Makefile.am
index b154a105d4..aa41c65b37 100644
--- a/cpp/etc/Makefile.am
+++ b/cpp/etc/Makefile.am
@@ -20,8 +20,8 @@ SASL_CONF = sasl2/qpidd.conf
EXTRA_DIST = \
$(SASL_CONF) \
- qpidd qpidd-primary qpidd.conf qpidc.conf CMakeLists.txt \
- cluster.conf-example.xml
+ qpidd.in qpidd-primary.in qpidd.conf qpidc.conf CMakeLists.txt \
+ cluster.conf-example.xml.in
confdir = $(sysconfdir)/qpid
nobase_conf_DATA=\
diff --git a/cpp/src/qmf/BrokerImportExport.h b/cpp/include/qmf/BrokerImportExport.h
index ee05788063..ee05788063 100644
--- a/cpp/src/qmf/BrokerImportExport.h
+++ b/cpp/include/qmf/BrokerImportExport.h
diff --git a/cpp/include/qmf/posix/EventNotifier.h b/cpp/include/qmf/posix/EventNotifier.h
index ebc1cb5364..c8b90b6421 100644
--- a/cpp/include/qmf/posix/EventNotifier.h
+++ b/cpp/include/qmf/posix/EventNotifier.h
@@ -28,7 +28,7 @@
namespace qmf {
class PosixEventNotifierImpl;
- class PosixEventNotifierImplAccess;
+ struct PosixEventNotifierImplAccess;
namespace posix {
diff --git a/cpp/include/qpid/Options.h b/cpp/include/qpid/Options.h
index 9860076195..0bbe7b704f 100644
--- a/cpp/include/qpid/Options.h
+++ b/cpp/include/qpid/Options.h
@@ -81,13 +81,12 @@ po::value_semantic* optValue(T& value, const char* name) {
*/
template <class T>
po::value_semantic* optValue(std::vector<T>& value, const char* name) {
- using namespace std;
- ostringstream os;
- copy(value.begin(), value.end(), ostream_iterator<T>(os, " "));
- string val=os.str();
+ std::ostringstream os;
+ std::copy(value.begin(), value.end(), std::ostream_iterator<T>(os, " "));
+ std::string val=os.str();
if (!val.empty())
val.erase(val.end()-1); // Remove trailing " "
- return (new OptionValue<vector<T> >(value, prettyArg(name, val)));
+ return (new OptionValue<std::vector<T> >(value, prettyArg(name, val)));
}
/** Create a boolean switch value. Presence of the option sets the value. */
diff --git a/cpp/include/qpid/RangeSet.h b/cpp/include/qpid/RangeSet.h
index 36991fd784..ef0ad032da 100644
--- a/cpp/include/qpid/RangeSet.h
+++ b/cpp/include/qpid/RangeSet.h
@@ -224,17 +224,15 @@ bool RangeSet<T>::contains(const Range<T>& r) const {
template <class T> void RangeSet<T>::addRange(const Range<T>& r) {
if (r.empty()) return;
- typename Ranges::iterator i =
- std::lower_bound(ranges.begin(), ranges.end(), r);
+ typename Ranges::iterator i = std::lower_bound(ranges.begin(), ranges.end(), r);
if (i == ranges.end() || !i->touching(r))
- ranges.insert(i, r);
+ ranges.insert(i, r); // No overlap
else {
i->merge(r);
typename Ranges::iterator j = i;
- if (++j != ranges.end() && i->touching(*j)) {
+ while (++j != ranges.end() && i->touching(*j))
i->merge(*j);
- ranges.erase(j);
- }
+ ranges.erase(i+1,j);
}
}
diff --git a/cpp/include/qpid/amqp_0_10/Codecs.h b/cpp/include/qpid/amqp_0_10/Codecs.h
index 73846f33a8..d632a9f20a 100644
--- a/cpp/include/qpid/amqp_0_10/Codecs.h
+++ b/cpp/include/qpid/amqp_0_10/Codecs.h
@@ -69,6 +69,8 @@ class QPID_COMMON_CLASS_EXTERN ListCodec
*/
QPID_COMMON_EXTERN void translate(const qpid::types::Variant::Map& from,
qpid::framing::FieldTable& to);
+QPID_COMMON_EXTERN void translate(const qpid::types::Variant::Map& from, const std::string& efield, const qpid::types::Variant& evalue,
+ qpid::framing::FieldTable& to);
QPID_COMMON_EXTERN void translate(const qpid::framing::FieldTable& from,
qpid::types::Variant::Map& to);
diff --git a/cpp/include/qpid/client/SessionBase_0_10.h b/cpp/include/qpid/client/SessionBase_0_10.h
index ea50ab32f7..630987c11d 100644
--- a/cpp/include/qpid/client/SessionBase_0_10.h
+++ b/cpp/include/qpid/client/SessionBase_0_10.h
@@ -36,14 +36,13 @@ namespace client {
class Connection;
class SessionImpl;
-using std::string;
-using framing::Content;
-using framing::FieldTable;
-using framing::SequenceNumber;
-using framing::SequenceSet;
-using framing::SequenceNumberSet;
+using qpid::framing::Content;
+using qpid::framing::FieldTable;
+using qpid::framing::SequenceNumber;
+using qpid::framing::SequenceSet;
+using qpid::framing::SequenceNumberSet;
using qpid::SessionId;
-using framing::Xid;
+using qpid::framing::Xid;
/** Unit of message credit: messages or bytes */
enum CreditUnit { MESSAGE_CREDIT=0, BYTE_CREDIT=1, UNLIMITED_CREDIT=0xFFFFFFFF };
diff --git a/cpp/include/qpid/client/SubscriptionSettings.h b/cpp/include/qpid/client/SubscriptionSettings.h
index b4cb302b56..bee39f6816 100644
--- a/cpp/include/qpid/client/SubscriptionSettings.h
+++ b/cpp/include/qpid/client/SubscriptionSettings.h
@@ -28,7 +28,19 @@ namespace qpid {
namespace client {
/** Bring AMQP enum definitions for message class into this namespace. */
-using namespace qpid::framing::message;
+using qpid::framing::message::AcceptMode;
+using qpid::framing::message::AcquireMode;
+using qpid::framing::message::ACCEPT_MODE_EXPLICIT;
+using qpid::framing::message::ACCEPT_MODE_NONE;
+using qpid::framing::message::ACQUIRE_MODE_NOT_ACQUIRED;
+using qpid::framing::message::ACQUIRE_MODE_PRE_ACQUIRED;
+using qpid::framing::message::CREDIT_UNIT_BYTE;
+using qpid::framing::message::CREDIT_UNIT_MESSAGE;
+using qpid::framing::message::DELIVERY_MODE_NON_PERSISTENT;
+using qpid::framing::message::DELIVERY_MODE_PERSISTENT;
+using qpid::framing::message::FLOW_MODE_CREDIT;
+using qpid::framing::message::FLOW_MODE_WINDOW;
+
enum CompletionMode {
MANUAL_COMPLETION = 0,
diff --git a/cpp/include/qpid/framing/Array.h b/cpp/include/qpid/framing/Array.h
index 4f82d4dbf0..6254f6271a 100644
--- a/cpp/include/qpid/framing/Array.h
+++ b/cpp/include/qpid/framing/Array.h
@@ -82,7 +82,7 @@ class QPID_COMMON_CLASS_EXTERN Array
// For use in standard algorithms
template <typename R, typename V>
static R get(const V& v) {
- return v->get<R>();
+ return v->template get<R>();
}
private:
diff --git a/cpp/include/qpid/framing/Buffer.h b/cpp/include/qpid/framing/Buffer.h
index 8b08e60762..2ccad3bd57 100644
--- a/cpp/include/qpid/framing/Buffer.h
+++ b/cpp/include/qpid/framing/Buffer.h
@@ -1,3 +1,6 @@
+#ifndef QPID_FRAMING_BUFFER_H
+#define QPID_FRAMING_BUFFER_H
+
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
@@ -18,13 +21,12 @@
* under the License.
*
*/
-#include "qpid/framing/amqp_types.h"
+
#include "qpid/Exception.h"
#include "qpid/CommonImportExport.h"
-#include <boost/iterator/iterator_facade.hpp>
+#include "qpid/sys/IntegerTypes.h"
-#ifndef _Buffer_
-#define _Buffer_
+#include <string>
namespace qpid {
namespace framing {
@@ -41,42 +43,18 @@ class QPID_COMMON_CLASS_EXTERN Buffer
uint32_t size;
char* data;
uint32_t position;
- uint32_t r_position;
public:
void checkAvailable(uint32_t count) { if (position + count > size) throw OutOfBounds(); }
- /** Buffer input/output iterator.
- * Supports using an amqp_0_10::Codec with a framing::Buffer.
- */
- class Iterator : public boost::iterator_facade<
- Iterator, char, boost::random_access_traversal_tag>
- {
- public:
- Iterator(Buffer& b) : buffer(&b) {}
-
- private:
- friend class boost::iterator_core_access;
- char& dereference() const { return buffer->data[buffer->position]; }
- void increment() { ++buffer->position; }
- bool equal(const Iterator& x) const { return buffer == x.buffer; }
-
- Buffer* buffer;
- };
-
- friend class Iterator;
-
QPID_COMMON_EXTERN Buffer(char* data=0, uint32_t size=0);
- QPID_COMMON_EXTERN void record();
- 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 void putOctet(uint8_t i);
@@ -108,16 +86,16 @@ class QPID_COMMON_CLASS_EXTERN Buffer
template <int n>
QPID_COMMON_EXTERN void putUInt(uint64_t);
- QPID_COMMON_EXTERN void putShortString(const string& s);
- QPID_COMMON_EXTERN void putMediumString(const string& s);
- QPID_COMMON_EXTERN void putLongString(const string& s);
- QPID_COMMON_EXTERN void getShortString(string& s);
- QPID_COMMON_EXTERN void getMediumString(string& s);
- QPID_COMMON_EXTERN void getLongString(string& s);
+ QPID_COMMON_EXTERN void putShortString(const std::string& s);
+ QPID_COMMON_EXTERN void putMediumString(const std::string& s);
+ QPID_COMMON_EXTERN void putLongString(const std::string& s);
+ QPID_COMMON_EXTERN void getShortString(std::string& s);
+ QPID_COMMON_EXTERN void getMediumString(std::string& s);
+ QPID_COMMON_EXTERN void getLongString(std::string& s);
QPID_COMMON_EXTERN void getBin128(uint8_t* b);
- QPID_COMMON_EXTERN void putRawData(const string& s);
- QPID_COMMON_EXTERN void getRawData(string& s, uint32_t size);
+ QPID_COMMON_EXTERN void putRawData(const std::string& s);
+ QPID_COMMON_EXTERN void getRawData(std::string& s, uint32_t size);
QPID_COMMON_EXTERN void putRawData(const uint8_t* data, size_t size);
QPID_COMMON_EXTERN void getRawData(uint8_t* data, size_t size);
diff --git a/cpp/include/qpid/framing/ProtocolVersion.h b/cpp/include/qpid/framing/ProtocolVersion.h
index 30094c165d..26d628e41c 100644
--- a/cpp/include/qpid/framing/ProtocolVersion.h
+++ b/cpp/include/qpid/framing/ProtocolVersion.h
@@ -24,6 +24,8 @@
#include "qpid/framing/amqp_types.h"
#include "qpid/CommonImportExport.h"
+#include <string>
+
namespace qpid
{
namespace framing
diff --git a/cpp/include/qpid/framing/SequenceNumber.h b/cpp/include/qpid/framing/SequenceNumber.h
index dd85d97a52..00fa2469c8 100644
--- a/cpp/include/qpid/framing/SequenceNumber.h
+++ b/cpp/include/qpid/framing/SequenceNumber.h
@@ -57,12 +57,18 @@ boost::equality_comparable<
QPID_COMMON_EXTERN uint32_t encodedSize() const;
template <class S> void serialize(S& s) { s(value); }
-
- friend inline int32_t operator-(const SequenceNumber& a, const SequenceNumber& b);
};
inline int32_t operator-(const SequenceNumber& a, const SequenceNumber& b) {
- return int32_t(a.value - b.value);
+ return int32_t(a.getValue() - b.getValue());
+}
+
+inline SequenceNumber operator+(const SequenceNumber& a, int32_t n) {
+ return SequenceNumber(a.getValue() + n);
+}
+
+inline SequenceNumber operator-(const SequenceNumber& a, int32_t n) {
+ return SequenceNumber(a.getValue() - n);
}
struct Window
diff --git a/cpp/include/qpid/framing/StructHelper.h b/cpp/include/qpid/framing/StructHelper.h
index 21f9b91fa9..fe2fa64ce7 100644
--- a/cpp/include/qpid/framing/StructHelper.h
+++ b/cpp/include/qpid/framing/StructHelper.h
@@ -34,7 +34,7 @@ class QPID_COMMON_CLASS_EXTERN StructHelper
{
public:
- template <class T> void encode(const T t, std::string& data) {
+ template <class T> void encode(const T& t, std::string& data) {
uint32_t size = t.bodySize() + 2/*type*/;
data.resize(size);
Buffer wbuffer(const_cast<char*>(data.data()), size);
diff --git a/cpp/include/qpid/framing/Uuid.h b/cpp/include/qpid/framing/Uuid.h
index ccfd7e9534..e9e56ed7c9 100644
--- a/cpp/include/qpid/framing/Uuid.h
+++ b/cpp/include/qpid/framing/Uuid.h
@@ -48,6 +48,9 @@ struct Uuid : public boost::array<uint8_t, 16> {
/** Copy from 16 bytes of data. */
QPID_COMMON_EXTERN Uuid(const uint8_t* data);
+ /** Parse format 1b4e28ba-2fa1-11d2-883f-b9a761bde3fb. */
+ QPID_COMMON_EXTERN Uuid(const std::string&);
+
// Default op= and copy ctor are fine.
// boost::array gives us ==, < etc.
diff --git a/cpp/include/qpid/framing/amqp_types.h b/cpp/include/qpid/framing/amqp_types.h
index d9088b7a12..2072a83904 100644
--- a/cpp/include/qpid/framing/amqp_types.h
+++ b/cpp/include/qpid/framing/amqp_types.h
@@ -27,12 +27,10 @@
*/
#include "qpid/sys/IntegerTypes.h"
-#include <string>
namespace qpid {
namespace framing {
-using std::string;
typedef uint8_t FrameType;
typedef uint16_t ChannelId;
typedef uint32_t BatchOffset;
diff --git a/cpp/include/qpid/log/Logger.h b/cpp/include/qpid/log/Logger.h
index d255b7e150..9464fa52dd 100644
--- a/cpp/include/qpid/log/Logger.h
+++ b/cpp/include/qpid/log/Logger.h
@@ -36,7 +36,7 @@ namespace log {
class QPID_COMMON_CLASS_EXTERN 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, HIRES=64, CATEGORY=128};
/**
* Logging output sink.
diff --git a/cpp/include/qpid/log/Options.h b/cpp/include/qpid/log/Options.h
index 17cbfde9bc..819f2c85f1 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, hiresTs, category;
bool trace;
std::string prefix;
std::auto_ptr<SinkOptions> sinkOptions;
diff --git a/cpp/include/qpid/log/Selector.h b/cpp/include/qpid/log/Selector.h
index 061152d7e2..498d4a7342 100644
--- a/cpp/include/qpid/log/Selector.h
+++ b/cpp/include/qpid/log/Selector.h
@@ -35,17 +35,24 @@ struct Options;
class Selector {
public:
/** Empty selector selects nothing */
- Selector() {}
+ Selector() {
+ reset();
+ }
/** Set selector from Options */
QPID_COMMON_EXTERN Selector(const Options&);
/** Equavlient to: Selector s; s.enable(l, s) */
Selector(Level l, const std::string& s=std::string()) {
+ reset();
enable(l,s);
}
- Selector(const std::string& enableStr) { enable(enableStr); }
+ Selector(const std::string& enableStr) {
+ reset();
+ enable(enableStr);
+ }
+
/**
* Enable messages with level in levels where the file
* name contains substring. Empty string matches all.
@@ -54,14 +61,30 @@ class Selector {
substrings[level].push_back(substring);
}
+ /**
+ * Enable messages at this level for this category
+ */
+ void enable(Level level, Category category) {
+ catFlags[level][category] = true;
+ }
+
/** Enable based on a 'level[+]:file' string */
QPID_COMMON_EXTERN void enable(const std::string& enableStr);
/** True if level is enabled for file. */
QPID_COMMON_EXTERN bool isEnabled(Level level, const char* function);
+ QPID_COMMON_EXTERN bool isEnabled(Level level, const char* function, Category category);
+
+ /** Reset the category enable flags */
+ QPID_COMMON_EXTERN void reset() {
+ for (int lt = 0; lt < LevelTraits::COUNT; ++lt)
+ for (int ct = 0; ct < CategoryTraits::COUNT; ++ct)
+ catFlags[lt][ct] = false;
+ }
private:
std::vector<std::string> substrings[LevelTraits::COUNT];
+ bool catFlags[LevelTraits::COUNT][CategoryTraits::COUNT];
};
diff --git a/cpp/include/qpid/log/Statement.h b/cpp/include/qpid/log/Statement.h
index 7b3ab60b81..ad84d66db6 100644
--- a/cpp/include/qpid/log/Statement.h
+++ b/cpp/include/qpid/log/Statement.h
@@ -22,6 +22,7 @@
#include "qpid/Msg.h"
#include "qpid/CommonImportExport.h"
#include <boost/current_function.hpp>
+#include <list>
namespace qpid {
namespace log {
@@ -55,15 +56,119 @@ struct LevelTraits {
static const char* name(Level);
};
-/** POD struct representing a logging statement in source code. */
+/** Formal message categories
+ * https://issues.apache.org/jira/browse/QPID-3902
+ *
+ * Category Source code directory
+ * -------- ---------------------
+ * Security acl ssl gssapi sasl cyrus
+ * Broker broker
+ * Management agent console qmf
+ * Protocol amqp_0_10 framing
+ * System log sys types xml thread mutex fork pipe time ...
+ * HA cluster ha replication
+ * Messaging messaging
+ * Client client
+ * Store store
+ * Network tcp rdma AsynchIO socket epoll
+ * Test
+ * Model <not related to a directory>
+ * Unspecified <must be last in enum>
+ */
+enum Category { security, broker, management, protocol, system, ha, messaging,
+ store, network, test, client, model, unspecified };
+struct CategoryTraits {
+ static const int COUNT=unspecified+1;
+
+ /** Test if given name is a Category name
+ */
+ static bool isCategory(const std::string& name);
+
+ /** Get category from string name
+ * @exception if name invalid.
+ */
+ static Category category(const char* name);
+
+ /** Get category from string name.
+ * @exception if name invalid.
+ */
+ static Category category(const std::string& name) {
+ return category(name.c_str());
+ }
+
+ /** String name of category */
+ static const char* name(Category);
+};
+
+
+class CategoryFileNameHints {
+public:
+ CategoryFileNameHints(){
+ hintList.push_back(std::make_pair("AsynchIo", network));
+ hintList.push_back(std::make_pair("TCP", network));
+ hintList.push_back(std::make_pair("epoll", network));
+ hintList.push_back(std::make_pair("Pollable", network));
+ hintList.push_back(std::make_pair("Socket", network));
+
+ hintList.push_back(std::make_pair("Sasl", security));
+ hintList.push_back(std::make_pair("Ssl", security));
+ hintList.push_back(std::make_pair("Acl", security));
+ hintList.push_back(std::make_pair("acl", security));
+ hintList.push_back(std::make_pair("cyrus", security));
+
+ hintList.push_back(std::make_pair("amqp_", protocol));
+ hintList.push_back(std::make_pair("framing", protocol));
+
+ hintList.push_back(std::make_pair("management", management));
+ hintList.push_back(std::make_pair("qmf", management));
+ hintList.push_back(std::make_pair("console", management));
+ hintList.push_back(std::make_pair("Management", management));
+
+ hintList.push_back(std::make_pair("cluster", ha));
+ hintList.push_back(std::make_pair("qpid/ha", ha));
+ hintList.push_back(std::make_pair("qpid\\ha", ha));
+ hintList.push_back(std::make_pair("replication", ha));
+ hintList.push_back(std::make_pair("ClusterSafe", ha));
+
+ hintList.push_back(std::make_pair("broker", broker));
+ hintList.push_back(std::make_pair("SessionState",broker));
+ hintList.push_back(std::make_pair("DataDir", broker));
+ hintList.push_back(std::make_pair("qpidd", broker));
+ hintList.push_back(std::make_pair("xml", broker));
+ hintList.push_back(std::make_pair("QpidBroker", broker));
+
+ hintList.push_back(std::make_pair("store", store));
+
+ hintList.push_back(std::make_pair("assert", system));
+ hintList.push_back(std::make_pair("Exception", system));
+ hintList.push_back(std::make_pair("sys", system));
+ hintList.push_back(std::make_pair("SCM", system));
+
+ hintList.push_back(std::make_pair("tests", test));
+
+ hintList.push_back(std::make_pair("messaging", messaging));
+ hintList.push_back(std::make_pair("types", messaging));
+
+ hintList.push_back(std::make_pair("client", client));
+ }
+
+ static Category categoryOf(const char*const fName);
+
+private:
+ std::list<std::pair<const char* const, Category> > hintList;
+};
+
+ /** POD struct representing a logging statement in source code. */
struct Statement {
bool enabled;
const char* file;
int line;
const char* function;
Level level;
+ Category category;
QPID_COMMON_EXTERN void log(const std::string& message);
+ QPID_COMMON_EXTERN static void categorize(Statement& s);
struct Initializer {
QPID_COMMON_EXTERN Initializer(Statement& s);
@@ -72,8 +177,14 @@ struct Statement {
};
///@internal static initializer for a Statement.
-#define QPID_LOG_STATEMENT_INIT(level) \
- { 0, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION, (::qpid::log::level) }
+#define QPID_LOG_STATEMENT_INIT_CAT(LEVEL, CATEGORY) \
+{ 0, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION, (::qpid::log::LEVEL), \
+(::qpid::log::CATEGORY) }
+
+
+///@internal static initializer for a Statement with unspecified category
+#define QPID_LOG_STATEMENT_INIT(LEVEL) \
+QPID_LOG_STATEMENT_INIT_CAT ( LEVEL , unspecified )
/**
* Like QPID_LOG but computes an additional boolean test expression
@@ -96,13 +207,26 @@ struct Statement {
} while(0)
/**
+ * Line QPID_LOG_IF but with the additional specification of a category.
+ * @param CATEGORY message category.
+ */
+#define QPID_LOG_IF_CAT(LEVEL, CATEGORY, TEST, MESSAGE) \
+ do { \
+ using ::qpid::log::Statement; \
+ static Statement stmt_= QPID_LOG_STATEMENT_INIT_CAT(LEVEL, CATEGORY); \
+ static Statement::Initializer init_(stmt_); \
+ if (stmt_.enabled && (TEST)) \
+ stmt_.log(::qpid::Msg() << MESSAGE); \
+ } while(0)
+
+/**
* FLAG must be a boolean variable. Assigns FLAG to true iff logging
* is enabled for LEVEL in the calling context. Use when extra
* support code is needed to generate log messages, to ensure that it
* is only run if the logging level is enabled.
* e.g.
* bool logWarning;
- * QPID_LOG_TEST(LEVEL, logWarning);
+ * QPID_LOG_TEST(warning, logWarning);
* if (logWarning) { do stuff needed for warning log messages }
*/
#define QPID_LOG_TEST(LEVEL, FLAG) \
@@ -113,12 +237,31 @@ struct Statement {
FLAG = stmt_.enabled; \
} while(0)
+ /**
+ * FLAG must be a boolean variable. Assigns FLAG to true iff logging
+ * is enabled for LEVEL in the calling context. Use when extra
+ * support code is needed to generate log messages, to ensure that it
+ * is only run if the logging level is enabled.
+ * e.g.
+ * bool logWarning;
+ * QPID_LOG_TEST_CAT(warning, System, logWarning);
+ * if (logWarning) { do stuff needed for warning log messages }
+ */
+ #define QPID_LOG_TEST_CAT(LEVEL, CATEGORY, FLAG) \
+ do { \
+ using ::qpid::log::Statement; \
+ static Statement stmt_= QPID_LOG_STATEMENT_INIT_CAT(LEVEL, CATEGORY); \
+ static Statement::Initializer init_(stmt_); \
+ FLAG = stmt_.enabled; \
+ } while(0)
+
/**
* Macro for log statements. Example of use:
* @code
* QPID_LOG(debug, "There are " << foocount << " foos in the bar.");
* QPID_LOG(error, boost::format("Dohickey %s exploded") % dohicky.name());
* @endcode
+ * Using QPID_LOG implies a category of Unspecified.
*
* You can subscribe to log messages by level, by component, by filename
* or a combination @see Configuration.
@@ -130,6 +273,25 @@ struct Statement {
*/
#define QPID_LOG(LEVEL, MESSAGE) QPID_LOG_IF(LEVEL, true, MESSAGE);
+/**
+ * Macro for log statements. Example of use:
+ * @code
+ * QPID_LOG_CAT(debug, System, "There are " << foocount << " foos in the bar.");
+ * QPID_LOG_CAT(error, System, boost::format("Dohickey %s exploded") % dohicky.name());
+ * @endcode
+ * Using QPID_LOG_CAT requires the specification of a category.
+ *
+ * You can subscribe to log messages by level, by component, by filename
+ * or a combination @see Configuration.
+ *
+ *@param LEVEL severity Level for message, should be one of:
+ * debug, info, notice, warning, error, critical. NB no qpid::log:: prefix.
+ *@param CATEGORY basic Category for the message.
+ *@param MESSAGE any object with an @eostream operator<<, or a sequence
+ * like of ostreamable objects separated by @e<<.
+ */
+#define QPID_LOG_CAT(LEVEL, CATEGORY, MESSAGE) QPID_LOG_IF_CAT(LEVEL, CATEGORY, true, MESSAGE);
+
}} // namespace qpid::log
diff --git a/cpp/include/qpid/management/Buffer.h b/cpp/include/qpid/management/Buffer.h
index c32494b8c0..1ac52bf276 100644
--- a/cpp/include/qpid/management/Buffer.h
+++ b/cpp/include/qpid/management/Buffer.h
@@ -46,13 +46,12 @@ public:
QPID_COMMON_EXTERN Buffer(char* data=0, uint32_t size=0);
QPID_COMMON_EXTERN ~Buffer();
- QPID_COMMON_EXTERN void record();
- QPID_COMMON_EXTERN void restore(bool reRecord = false);
QPID_COMMON_EXTERN void reset();
QPID_COMMON_EXTERN uint32_t available();
QPID_COMMON_EXTERN uint32_t getSize();
QPID_COMMON_EXTERN uint32_t getPosition();
+ QPID_COMMON_EXTERN void setPosition(uint32_t);
QPID_COMMON_EXTERN char* getPointer();
QPID_COMMON_EXTERN void putOctet(uint8_t i);
diff --git a/cpp/include/qpid/sys/SystemInfo.h b/cpp/include/qpid/sys/SystemInfo.h
index 23594cf650..24bc099d75 100644
--- a/cpp/include/qpid/sys/SystemInfo.h
+++ b/cpp/include/qpid/sys/SystemInfo.h
@@ -34,51 +34,61 @@ namespace sys {
* Results may be dependent on OS/hardware.
*/
namespace SystemInfo {
- /**
- * Estimate available concurrency, e.g. number of CPU cores.
- * -1 means estimate not available on this platform.
- */
- QPID_COMMON_EXTERN long concurrency();
+/**
+ * Estimate available concurrency, e.g. number of CPU cores.
+ * -1 means estimate not available on this platform.
+ */
+QPID_COMMON_EXTERN long concurrency();
- /**
- * Get the local host name and set it in the specified.
- * Returns false if it can't be obtained and sets errno to any error value.
- */
- QPID_COMMON_EXTERN bool getLocalHostname (Address &address);
+/**
+ * Get the local host name and set it in the specified.
+ * Returns false if it can't be obtained and sets errno to any error value.
+ */
+QPID_COMMON_EXTERN bool getLocalHostname (Address &address);
- QPID_COMMON_EXTERN void getLocalIpAddresses (uint16_t port, std::vector<Address> &addrList);
+/**
+ * Get the (possibly multiple) local IP addresses of this host
+ * using the specified port.
+ */
+QPID_COMMON_EXTERN void getLocalIpAddresses (uint16_t port, std::vector<Address> &addrList);
+
+/**
+ * Return true if host names an address of the local host.
+ *@param host host name or IP address.
+ */
+QPID_COMMON_EXTERN bool isLocalHost(const std::string& host);
- /**
- * Retrieve system identifiers and versions. This is information that can
- * generally be retrieved via POSIX uname().
- *
- * @param osName Receives the OS name; e.g., GNU/Linux or Windows
- * @param nodeName Receives the nodename. This may or may not match the
- * set hostname from getLocalHostname().
- * @param release Receives the OS release identifier.
- * @param version Receives the OS release version (kernel, build, sp, etc.)
- * @param machine Receives the hardware type.
- */
- QPID_COMMON_EXTERN void getSystemId (std::string &osName,
- std::string &nodeName,
- std::string &release,
- std::string &version,
- std::string &machine);
+/**
+ * Retrieve system identifiers and versions. This is information that can
+ * generally be retrieved via POSIX uname().
+ *
+ * @param osName Receives the OS name; e.g., GNU/Linux or Windows
+ * @param nodeName Receives the nodename. This may or may not match the
+ * set hostname from getLocalHostname().
+ * @param release Receives the OS release identifier.
+ * @param version Receives the OS release version (kernel, build, sp, etc.)
+ * @param machine Receives the hardware type.
+ */
+QPID_COMMON_EXTERN void getSystemId (std::string &osName,
+ std::string &nodeName,
+ std::string &release,
+ std::string &version,
+ std::string &machine);
- /**
- * Get the process ID of the current process.
- */
- QPID_COMMON_EXTERN uint32_t getProcessId();
+/**
+ * Get the process ID of the current process.
+ */
+QPID_COMMON_EXTERN uint32_t getProcessId();
- /**
- * Get the process ID of the parent of the current process.
- */
- QPID_COMMON_EXTERN uint32_t getParentProcessId();
+/**
+ * Get the process ID of the parent of the current process.
+ */
+QPID_COMMON_EXTERN uint32_t getParentProcessId();
- /**
- * Get the name of the current process (i.e. the name of the executable)
- */
- QPID_COMMON_EXTERN std::string getProcessName();
+/**
+ * Get the name of the current process (i.e. the name of the executable)
+ */
+QPID_COMMON_EXTERN std::string getProcessName();
}}} // namespace qpid::sys::SystemInfo
diff --git a/cpp/managementgen/qmf-gen b/cpp/managementgen/qmf-gen
index 6e8f864256..2f0cc0d8fd 100755
--- a/cpp/managementgen/qmf-gen
+++ b/cpp/managementgen/qmf-gen
@@ -49,6 +49,8 @@ parser.add_option("-b", "--broker-plugin", dest="brokerplugin", default=False, a
help="Generate code for use in a qpid broker plugin")
parser.add_option("-2", "--v2-style", dest="v2_style", default=False, action="store_true",
help="Generate code for use with the QMFv2 Agent API")
+parser.add_option("-l", "--qpid-logs", dest="qpidlogs", default=False, action="store_true",
+ help="Generate code for QPID_LOG statements in classes constructor/destructor")
(opts, args) = parser.parse_args()
@@ -70,6 +72,11 @@ else:
vargs["agentHeaderDir"] = "agent"
vargs["genQmfV1"] = None
+if opts.qpidlogs:
+ vargs["genLogs"] = True
+else:
+ vargs["genLogs"] = False
+
for schemafile in args:
package = SchemaPackage(typefile, schemafile, opts)
diff --git a/cpp/managementgen/qmfgen/generate.py b/cpp/managementgen/qmfgen/generate.py
index 4e688e3bc7..61111be01d 100755
--- a/cpp/managementgen/qmfgen/generate.py
+++ b/cpp/managementgen/qmfgen/generate.py
@@ -304,6 +304,9 @@ class Generator:
def testGenQMFv1 (self, variables):
return variables["genQmfV1"]
+ def testGenLogs (self, variables):
+ return variables["genLogs"]
+
def genDisclaimer (self, stream, variables):
prefix = variables["commentPrefix"]
stream.write (prefix + " This source file was created by a code generator.\n")
diff --git a/cpp/managementgen/qmfgen/templates/Class.cpp b/cpp/managementgen/qmfgen/templates/Class.cpp
index fc0b9c8177..d3033db7e1 100644
--- a/cpp/managementgen/qmfgen/templates/Class.cpp
+++ b/cpp/managementgen/qmfgen/templates/Class.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,8 +27,12 @@
#include "qpid//*MGEN:Class.AgentHeaderLocation*//ManagementAgent.h"
#include "/*MGEN:Class.NameCap*/.h"
/*MGEN:Class.MethodArgIncludes*/
+/*MGEN:IF(Root.GenLogs)*/
+#include "qpid/log/Statement.h"
+/*MGEN:ENDIF*/
#include <iostream>
#include <sstream>
+#include <string.h>
using namespace qmf::/*MGEN:Class.Namespace*/;
using qpid::management::ManagementAgent;
@@ -58,10 +62,26 @@ uint8_t /*MGEN:Class.NameCap*/::md5Sum[MD5_LEN] =
for (int idx = 0; idx < maxThreads; idx++)
perThreadStatsArray[idx] = 0;
/*MGEN:ENDIF*/
+/*MGEN:IF(Root.GenLogs)*/
+ QPID_LOG_CAT(trace, model, "Mgmt create " << className
+ << ". id:" << getKey());
+/*MGEN:ENDIF*/
}
/*MGEN:Class.NameCap*/::~/*MGEN:Class.NameCap*/ ()
{
+/*MGEN:IF(Root.GenLogs)*/
+ bool logEnabled;
+ QPID_LOG_TEST_CAT(trace, model, logEnabled);
+ if (logEnabled)
+ {
+ ::qpid::types::Variant::Map map;
+ mapEncodeValues(map, false, true);
+ QPID_LOG_CAT(trace, model, "Mgmt delete " << className
+ << ". id:" << getKey()
+ << " Statistics: " << map);
+ }
+/*MGEN:ENDIF*/
/*MGEN:IF(Class.ExistPerThreadStats)*/
for (int idx = 0; idx < maxThreads; idx++)
if (perThreadStatsArray[idx] != 0)
@@ -274,7 +294,6 @@ std::string /*MGEN:Class.NameCap*/::getKey() const
}
-
void /*MGEN:Class.NameCap*/::mapEncodeValues (::qpid::types::Variant::Map& _map,
bool includeProperties,
bool includeStatistics)
diff --git a/cpp/src/CMakeLists.txt b/cpp/src/CMakeLists.txt
index 1f3c2a739d..526f191f84 100644
--- a/cpp/src/CMakeLists.txt
+++ b/cpp/src/CMakeLists.txt
@@ -220,7 +220,7 @@ execute_process(COMMAND ${RUBY_EXECUTABLE} -I ${rgen_dir} ${rgen_dir}/generate $
endforeach (spec_file ${mgmt_specs})
if (regen_mgmt)
message(STATUS "Regenerating Qpid Management Framework sources")
-execute_process(COMMAND ${PYTHON_EXECUTABLE} ${mgen_dir}/qmf-gen -c managementgen.cmake -b -q -o ${CMAKE_CURRENT_BINARY_DIR}/qmf ${mgmt_specs}
+execute_process(COMMAND ${PYTHON_EXECUTABLE} ${mgen_dir}/qmf-gen -c managementgen.cmake -b -l -q -o ${CMAKE_CURRENT_BINARY_DIR}/qmf ${mgmt_specs}
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
else (regen_mgmt)
message(STATUS "No need to generate Qpid Management Framework sources")
@@ -281,7 +281,7 @@ endif (CMAKE_COMPILER_IS_GNUCXX)
if (CMAKE_CXX_COMPILER_ID STREQUAL SunPro)
set (COMPILER_FLAGS "-library=stlport4 -mt")
- set (WARNING_FLAGS "+w2")
+ set (WARNING_FLAGS "+w")
endif (CMAKE_CXX_COMPILER_ID STREQUAL SunPro)
option(ENABLE_WARNINGS "Enable lots of compiler warnings (recommended)" ON)
@@ -626,27 +626,42 @@ set (ha_default ON)
option(BUILD_HA "Build Active-Passive HA plugin" ${ha_default})
if (BUILD_HA)
set (ha_SOURCES
+ qpid/ha/AlternateExchangeSetter.h
+ qpid/ha/BackupConnectionExcluder.h
+ qpid/ha/BrokerInfo.cpp
+ qpid/ha/BrokerInfo.h
+ qpid/ha/QueueGuard.cpp
+ qpid/ha/QueueGuard.h
+ qpid/ha/ReplicationTest.cpp
+ qpid/ha/ReplicationTest.h
qpid/ha/Backup.cpp
qpid/ha/Backup.h
+ qpid/ha/BrokerReplicator.cpp
+ qpid/ha/BrokerReplicator.h
+ qpid/ha/ConnectionObserver.cpp
+ qpid/ha/ConnectionObserver.h
qpid/ha/HaBroker.cpp
qpid/ha/HaBroker.h
qpid/ha/HaPlugin.cpp
- qpid/ha/Settings.h
- qpid/ha/QueueReplicator.h
+ qpid/ha/Membership.cpp
+ qpid/ha/Membership.h
+ qpid/ha/Primary.cpp
+ qpid/ha/Primary.h
+ qpid/ha/QueueRange.h
qpid/ha/QueueReplicator.cpp
- qpid/ha/ReplicateLevel.h
- qpid/ha/ReplicateLevel.cpp
- qpid/ha/ReplicatingSubscription.h
+ qpid/ha/QueueReplicator.h
qpid/ha/ReplicatingSubscription.cpp
- qpid/ha/BrokerReplicator.cpp
- qpid/ha/BrokerReplicator.h
- qpid/ha/ConnectionExcluder.cpp
- qpid/ha/ConnectionExcluder.h
+ qpid/ha/ReplicatingSubscription.h
+ qpid/ha/Settings.h
+ qpid/ha/types.cpp
+ qpid/ha/types.h
+ qpid/ha/RemoteBackup.cpp
+ qpid/ha/RemoteBackup.h
)
add_library (ha MODULE ${ha_SOURCES})
set_target_properties (ha PROPERTIES PREFIX "")
- target_link_libraries (ha qpidcommon qpidbroker ${Boost_PROGRAM_OPTIONS_LIBRARY})
+ target_link_libraries (ha qpidtypes qpidcommon qpidbroker)
if (CMAKE_COMPILER_IS_GNUCXX)
set_target_properties (ha PROPERTIES
PREFIX ""
@@ -672,6 +687,11 @@ include (ssl.cmake)
# Check for syslog capabilities not present on all systems
check_symbol_exists (LOG_AUTHPRIV "sys/syslog.h" HAVE_LOG_AUTHPRIV)
check_symbol_exists (LOG_FTP "sys/syslog.h" HAVE_LOG_FTP)
+
+# Set default Memory Status module (Null implementation)
+set (qpid_memstat_module
+ qpid/sys/MemStat.cpp
+)
# Allow MSVC user to select 'WinXP-SP3/Windows Server 2003' as build target version
set (win32_winnt_default OFF)
@@ -734,7 +754,6 @@ if (CMAKE_SYSTEM_NAME STREQUAL Windows)
qpid/sys/windows/SystemInfo.cpp
qpid/sys/windows/Thread.cpp
qpid/sys/windows/Time.cpp
- qpid/sys/windows/MemStat.cpp
qpid/client/windows/SaslFactory.cpp
${sslcommon_windows_SOURCES}
)
@@ -780,41 +799,54 @@ else (CMAKE_SYSTEM_NAME STREQUAL Windows)
)
endif (POLLER STREQUAL poll)
+ # Set default System Info module
+ set (qpid_system_module
+ qpid/sys/posix/SystemInfo.cpp
+ )
+
if (CMAKE_SYSTEM_NAME STREQUAL Linux)
- set (qpid_system_module
- qpid/sys/posix/SystemInfo.cpp
- )
add_definitions(-pthread)
set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pthread")
if (CMAKE_COMPILER_IS_GNUCXX)
set (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${GCC_CATCH_UNDEFINED} -pthread")
+ set (CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -pthread")
endif (CMAKE_COMPILER_IS_GNUCXX)
+ # On Linux override memory status module
+ set (qpid_memstat_module
+ qpid/sys/posix/MemStat.cpp
+ )
endif (CMAKE_SYSTEM_NAME STREQUAL Linux)
- set (qpidtypes_platform_SOURCES)
- set (qpidtypes_platform_LIBS
- uuid
- ${Boost_SYSTEM_LIBRARY}
- )
-
if (CMAKE_SYSTEM_NAME STREQUAL SunOS)
+ # On Solaris override the system info module
set (qpid_system_module
qpid/sys/solaris/SystemInfo.cpp
)
-# On Sun we want -lpthread -lthread as the 2nd last and last libs passed to linker
+ # On Sun we want -lpthread -lthread as the 2nd last and last libs passed to linker
set (qpidtypes_platform_LIBS ${qpidtypes_platform_LIBS}
pthread
thread
)
endif (CMAKE_SYSTEM_NAME STREQUAL SunOS)
+ if (CMAKE_CXX_COMPILER_ID STREQUAL SunPro)
+ # -lmalloc needed for mallinfo.
+ set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lmalloc")
+ set (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -lmalloc")
+ endif (CMAKE_CXX_COMPILER_ID STREQUAL SunPro)
+
+ set (qpidtypes_platform_SOURCES)
+ set (qpidtypes_platform_LIBS
+ uuid
+ ${Boost_SYSTEM_LIBRARY}
+ )
+
set (qpidcommon_platform_SOURCES
qpid/sys/posix/AsynchIO.cpp
qpid/sys/posix/Fork.cpp
qpid/sys/posix/FileSysDir.cpp
qpid/sys/posix/IOHandle.cpp
qpid/sys/posix/LockFile.cpp
- qpid/sys/posix/MemStat.cpp
qpid/sys/posix/Mutex.cpp
qpid/sys/posix/PipeHandle.cpp
qpid/sys/posix/PollableCondition.cpp
@@ -917,6 +949,7 @@ set (qpidcommon_SOURCES
qpid/sys/Timer.cpp
qpid/sys/TimerWarnings.cpp
qpid/amqp_0_10/Codecs.cpp
+ ${qpid_memstat_module}
)
add_msvc_version (qpidcommon library dll)
@@ -1200,6 +1233,7 @@ set (qmf_SOURCES
set (qmf_HEADERS
../include/qpid/agent/ManagementAgent.h
../include/qpid/agent/QmfAgentImportExport.h
+ ../include/qmf/BrokerImportExport.h
)
add_msvc_version (qmf library dll)
diff --git a/cpp/src/Makefile.am b/cpp/src/Makefile.am
index 43e491a229..8a8e4b1928 100644
--- a/cpp/src/Makefile.am
+++ b/cpp/src/Makefile.am
@@ -28,6 +28,7 @@ windows_dist = \
qpid/log/windows/SinkOptions.cpp \
qpid/log/windows/SinkOptions.h \
../include/qpid/sys/windows/check.h \
+ qpid/sys/MemStat.cpp \
qpid/sys/windows/AsynchIO.cpp \
qpid/sys/windows/AsynchIoResult.h \
../include/qpid/sys/windows/Condition.h \
@@ -53,7 +54,6 @@ windows_dist = \
../include/qpid/sys/windows/Time.h \
qpid/sys/windows/uuid.cpp \
qpid/sys/windows/uuid.h \
- qpid/sys/windows/MemStat.cpp \
windows/QpiddBroker.cpp \
windows/SCM.h \
windows/SCM.cpp \
@@ -107,7 +107,7 @@ mgen_xml=$(top_srcdir)/../specs/management-schema.xml \
$(srcdir)/qpid/cluster/management-schema.xml \
$(srcdir)/qpid/ha/management-schema.xml
mgen_cmd=$(mgen_dir)/qmf-gen -m $(srcdir)/managementgen.mk \
- -c $(srcdir)/managementgen.cmake -q -b -o qmf \
+ -c $(srcdir)/managementgen.cmake -q -b -l -o qmf \
$(mgen_xml)
$(srcdir)/managementgen.mk $(mgen_broker_cpp) $(dist_qpid_management_HEADERS): mgen.timestamp
@@ -380,7 +380,6 @@ libqpidcommon_la_SOURCES += \
qpid/assert.h \
qpid/framing/AMQBody.cpp \
qpid/framing/AMQBody.h \
- qpid/framing/AMQCommandControlBody.h \
qpid/framing/AMQContentBody.cpp \
qpid/framing/AMQContentBody.h \
qpid/framing/AMQDataBlock.h \
@@ -553,6 +552,8 @@ libqpidbroker_la_SOURCES = \
qpid/broker/ConsumerFactory.h \
qpid/broker/ConnectionObserver.h \
qpid/broker/ConnectionObservers.h \
+ qpid/broker/ConfigurationObserver.h \
+ qpid/broker/ConfigurationObservers.h \
qpid/broker/Daemon.cpp \
qpid/broker/Daemon.h \
qpid/broker/Deliverable.h \
@@ -615,6 +616,7 @@ libqpidbroker_la_SOURCES = \
qpid/broker/NameGenerator.h \
qpid/broker/NullMessageStore.cpp \
qpid/broker/NullMessageStore.h \
+ qpid/broker/Observers.h \
qpid/broker/OwnershipToken.h \
qpid/broker/Persistable.h \
qpid/broker/PersistableConfig.h \
@@ -684,6 +686,7 @@ libqpidbroker_la_SOURCES = \
qpid/broker/ThresholdAlerts.h \
qpid/broker/TopicExchange.cpp \
qpid/broker/TopicExchange.h \
+ qpid/broker/TopicKeyNode.h \
qpid/broker/TransactionalStore.h \
qpid/broker/TxAccept.cpp \
qpid/broker/TxAccept.h \
diff --git a/cpp/src/ha.mk b/cpp/src/ha.mk
index be1fb73e89..96a3d872e4 100644
--- a/cpp/src/ha.mk
+++ b/cpp/src/ha.mk
@@ -23,22 +23,37 @@
dmoduleexec_LTLIBRARIES += ha.la
ha_la_SOURCES = \
+ qpid/ha/AlternateExchangeSetter.h \
qpid/ha/Backup.cpp \
qpid/ha/Backup.h \
+ qpid/ha/BackupConnectionExcluder.h \
+ qpid/ha/BrokerInfo.cpp \
+ qpid/ha/BrokerInfo.h \
qpid/ha/BrokerReplicator.cpp \
- qpid/ha/BrokerReplicator.h \
- qpid/ha/ConnectionExcluder.cpp \
- qpid/ha/ConnectionExcluder.h \
+ qpid/ha/BrokerReplicator.h \
+ qpid/ha/ConnectionObserver.cpp \
+ qpid/ha/ConnectionObserver.h \
qpid/ha/HaBroker.cpp \
qpid/ha/HaBroker.h \
qpid/ha/HaPlugin.cpp \
+ qpid/ha/Membership.cpp \
+ qpid/ha/Membership.h \
+ qpid/ha/Primary.cpp \
+ qpid/ha/Primary.h \
+ qpid/ha/QueueGuard.cpp \
+ qpid/ha/QueueGuard.h \
+ qpid/ha/QueueRange.h \
qpid/ha/QueueReplicator.cpp \
qpid/ha/QueueReplicator.h \
- qpid/ha/ReplicateLevel.cpp \
- qpid/ha/ReplicateLevel.h \
qpid/ha/ReplicatingSubscription.cpp \
qpid/ha/ReplicatingSubscription.h \
- qpid/ha/Settings.h
+ qpid/ha/ReplicationTest.cpp \
+ qpid/ha/ReplicationTest.h \
+ qpid/ha/Settings.h \
+ qpid/ha/RemoteBackup.cpp \
+ qpid/ha/RemoteBackup.h \
+ qpid/ha/types.cpp \
+ qpid/ha/types.h
ha_la_LIBADD = libqpidbroker.la
ha_la_LDFLAGS = $(PLUGINLDFLAGS)
diff --git a/cpp/src/posix/QpiddBroker.cpp b/cpp/src/posix/QpiddBroker.cpp
index fd2fb6184f..76e3bb6674 100644
--- a/cpp/src/posix/QpiddBroker.cpp
+++ b/cpp/src/posix/QpiddBroker.cpp
@@ -154,8 +154,14 @@ int QpiddBroker::execute (QpiddOptions *options) {
throw Exception("Internal error obtaining platform options");
if (myOptions->daemon.check || myOptions->daemon.quit) {
- pid_t pid = Daemon::getPid(myOptions->daemon.piddir,
- options->broker.port);
+ pid_t pid;
+ try {
+ pid = Daemon::getPid(myOptions->daemon.piddir, options->broker.port);
+ } catch (const ErrnoException& e) {
+ // This is not a critical error, usually means broker is not running
+ QPID_LOG(notice, "Cannot stop broker: " << e.what());
+ return 1;
+ }
if (pid < 0)
return 1;
if (myOptions->daemon.check)
diff --git a/cpp/src/qmf.mk b/cpp/src/qmf.mk
index 9b5df6c808..6a4bce4087 100644
--- a/cpp/src/qmf.mk
+++ b/cpp/src/qmf.mk
@@ -30,7 +30,8 @@ lib_LTLIBRARIES += \
#
QMF_API = \
../include/qpid/agent/ManagementAgent.h \
- ../include/qpid/agent/QmfAgentImportExport.h
+ ../include/qpid/agent/QmfAgentImportExport.h \
+ ../include/qmf/BrokerImportExport.h
#
# Public headers for the QMF2 API
@@ -96,7 +97,6 @@ libqmf2_la_SOURCES = \
qmf/AgentSessionImpl.h \
qmf/AgentSubscription.cpp \
qmf/AgentSubscription.h \
- qmf/BrokerImportExport.h \
qmf/ConsoleEvent.cpp \
qmf/ConsoleEventImpl.h \
qmf/ConsoleSession.cpp \
diff --git a/cpp/src/qmf/AgentSession.cpp b/cpp/src/qmf/AgentSession.cpp
index 3b5806aea4..4d7be33188 100644
--- a/cpp/src/qmf/AgentSession.cpp
+++ b/cpp/src/qmf/AgentSession.cpp
@@ -21,6 +21,22 @@
#include "qmf/AgentSessionImpl.h"
+#include <iostream>
+#include <memory>
+
+namespace qmf {
+
+using std::string;
+using std::map;
+
+using qpid::messaging::Address;
+using qpid::messaging::Connection;
+using qpid::messaging::Duration;
+using qpid::messaging::Message;
+using qpid::messaging::Receiver;
+using qpid::messaging::Sender;
+using qpid::types::Variant;
+
AgentSession::AgentSession(AgentSessionImpl* impl) { PI::ctor(*this, impl); }
AgentSession::AgentSession(const AgentSession& s) : qmf::Handle<AgentSessionImpl>() { PI::copy(*this, s); }
AgentSession::~AgentSession() { PI::dtor(*this); }
@@ -332,7 +348,7 @@ void AgentSessionImpl::delData(const DataAddr& addr)
void AgentSessionImpl::authAccept(AgentEvent& authEvent)
{
- auto_ptr<AgentEventImpl> eventImpl(new AgentEventImpl(AGENT_QUERY));
+ std::auto_ptr<AgentEventImpl> eventImpl(new AgentEventImpl(AGENT_QUERY));
eventImpl->setQuery(authEvent.getQuery());
eventImpl->setUserId(authEvent.getUserId());
eventImpl->setReplyTo(AgentEventImplAccess::get(authEvent).getReplyTo());
@@ -593,7 +609,7 @@ void AgentSessionImpl::handleMethodRequest(const Variant::Map& content, const Me
//
// Construct an AgentEvent to be sent to the application.
//
- auto_ptr<AgentEventImpl> eventImpl(new AgentEventImpl(AGENT_METHOD));
+ std::auto_ptr<AgentEventImpl> eventImpl(new AgentEventImpl(AGENT_METHOD));
eventImpl->setUserId(msg.getUserId());
eventImpl->setReplyTo(msg.getReplyTo());
eventImpl->setCorrelationId(msg.getCorrelationId());
@@ -655,8 +671,8 @@ void AgentSessionImpl::handleQueryRequest(const Variant::Map& content, const Mes
//
// Construct an AgentEvent to be sent to the application or directly handled by the agent.
//
- auto_ptr<QueryImpl> queryImpl(new QueryImpl(content));
- auto_ptr<AgentEventImpl> eventImpl(new AgentEventImpl(AGENT_AUTH_QUERY));
+ std::auto_ptr<QueryImpl> queryImpl(new QueryImpl(content));
+ std::auto_ptr<AgentEventImpl> eventImpl(new AgentEventImpl(AGENT_AUTH_QUERY));
eventImpl->setUserId(msg.getUserId());
eventImpl->setReplyTo(msg.getReplyTo());
eventImpl->setCorrelationId(msg.getCorrelationId());
@@ -1012,3 +1028,4 @@ const AgentSessionImpl& AgentSessionImplAccess::get(const AgentSession& session)
return *session.impl;
}
+}
diff --git a/cpp/src/qmf/AgentSessionImpl.h b/cpp/src/qmf/AgentSessionImpl.h
index ae512a4054..64a39ab2e8 100644
--- a/cpp/src/qmf/AgentSessionImpl.h
+++ b/cpp/src/qmf/AgentSessionImpl.h
@@ -57,17 +57,10 @@
#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 {
+ typedef qmf::PrivateImplRef<AgentSession> PI;
+
class AgentSessionImpl : public virtual qpid::RefCounted, public qpid::sys::Runnable {
public:
~AgentSessionImpl();
@@ -75,29 +68,29 @@ namespace qmf {
//
// 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; }
+ AgentSessionImpl(qpid::messaging::Connection& c, const std::string& o);
+ void setDomain(const std::string& d) { checkOpen(); domain = d; }
+ void setVendor(const std::string& v) { checkOpen(); attributes["_vendor"] = v; }
+ void setProduct(const std::string& p) { checkOpen(); attributes["_product"] = p; }
+ void setInstance(const std::string& i) { checkOpen(); attributes["_instance"] = i; }
+ void setAttribute(const std::string& k, const qpid::types::Variant& v) { checkOpen(); attributes[k] = v; }
+ const std::string& getName() const { return agentName; }
void open();
void closeAsync();
void close();
- bool nextEvent(AgentEvent& e, Duration t);
+ bool nextEvent(AgentEvent& e, qpid::messaging::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);
+ DataAddr addData(Data& d, const std::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 authReject(AgentEvent& e, const std::string& m);
+ void raiseException(AgentEvent& e, const std::string& s);
void raiseException(AgentEvent& e, const Data& d);
void response(AgentEvent& e, const Data& d);
void complete(AgentEvent& e);
@@ -106,21 +99,21 @@ namespace qmf {
void raiseEvent(const Data& d, int s);
private:
- typedef map<DataAddr, Data, DataAddrCompare> DataIndex;
- typedef map<SchemaId, Schema, SchemaIdCompare> SchemaMap;
+ typedef std::map<DataAddr, Data, DataAddrCompare> DataIndex;
+ typedef std::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;
+ qpid::messaging::Connection connection;
+ qpid::messaging::Session session;
+ qpid::messaging::Sender directSender;
+ qpid::messaging::Sender topicSender;
+ std::string domain;
+ qpid::types::Variant::Map attributes;
+ qpid::types::Variant::Map options;
+ std::string agentName;
bool opened;
- queue<AgentEvent> eventQueue;
+ std::queue<AgentEvent> eventQueue;
EventNotifierImpl* eventNotifier;
qpid::sys::Thread* thread;
bool threadCanceled;
@@ -140,25 +133,25 @@ namespace qmf {
bool strictSecurity;
uint32_t maxThreadWaitTime;
uint64_t schemaUpdateTime;
- string directBase;
- string topicBase;
+ std::string directBase;
+ std::string topicBase;
SchemaMap schemata;
DataIndex globalIndex;
- map<SchemaId, DataIndex, SchemaIdCompareNoHash> schemaIndex;
+ std::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 handleLocateRequest(const qpid::types::Variant::List& content, const qpid::messaging::Message& msg);
+ void handleMethodRequest(const qpid::types::Variant::Map& content, const qpid::messaging::Message& msg);
+ void handleQueryRequest(const qpid::types::Variant::Map& content, const qpid::messaging::Message& msg);
void handleSchemaRequest(AgentEvent&);
- void handleV1SchemaRequest(qpid::management::Buffer&, uint32_t, const Message&);
- void dispatch(Message);
+ void handleV1SchemaRequest(qpid::management::Buffer&, uint32_t, const qpid::messaging::Message&);
+ void dispatch(qpid::messaging::Message);
void sendHeartbeat();
- void send(Message, const Address&);
+ void send(qpid::messaging::Message, const qpid::messaging::Address&);
void flushResponses(AgentEvent&, bool);
void periodicProcessing(uint64_t);
void run();
diff --git a/cpp/src/qmf/ConsoleSessionImpl.h b/cpp/src/qmf/ConsoleSessionImpl.h
index e2b30602fa..2c06df030c 100644
--- a/cpp/src/qmf/ConsoleSessionImpl.h
+++ b/cpp/src/qmf/ConsoleSessionImpl.h
@@ -47,8 +47,6 @@
#include <map>
#include <queue>
-using namespace std;
-
namespace qmf {
class ConsoleSessionImpl : public virtual qpid::RefCounted, public qpid::sys::Runnable {
public:
diff --git a/cpp/src/qmf/EventNotifierImpl.cpp b/cpp/src/qmf/EventNotifierImpl.cpp
index 20114aaa5e..81b6d637a3 100644
--- a/cpp/src/qmf/EventNotifierImpl.cpp
+++ b/cpp/src/qmf/EventNotifierImpl.cpp
@@ -21,6 +21,8 @@
#include "qmf/AgentSessionImpl.h"
#include "qmf/ConsoleSessionImpl.h"
+namespace qmf {
+
EventNotifierImpl::EventNotifierImpl(AgentSession& agentSession)
: readable(false), agent(agentSession)
{
@@ -54,3 +56,5 @@ bool EventNotifierImpl::isReadable() const
{
return this->readable;
}
+
+}
diff --git a/cpp/src/qmf/PrivateImplRef.h b/cpp/src/qmf/PrivateImplRef.h
index 960cbb2e09..c0c07d7e1b 100644
--- a/cpp/src/qmf/PrivateImplRef.h
+++ b/cpp/src/qmf/PrivateImplRef.h
@@ -76,15 +76,15 @@ template <class T> class PrivateImplRef {
/** Set the implementation pointer in a handle */
static void set(T& t, const intrusive_ptr& p) {
if (t.impl == p) return;
- if (t.impl) boost::intrusive_ptr_release(t.impl);
+ if (t.impl) intrusive_ptr_release(t.impl);
t.impl = p.get();
- if (t.impl) boost::intrusive_ptr_add_ref(t.impl);
+ if (t.impl) intrusive_ptr_add_ref(t.impl);
}
// Helper functions to implement the ctor, dtor, copy, assign
- static void ctor(T& t, Impl* p) { t.impl = p; if (p) boost::intrusive_ptr_add_ref(p); }
+ static void ctor(T& t, Impl* p) { t.impl = p; if (p) intrusive_ptr_add_ref(p); }
static void copy(T& t, const T& x) { if (&t == &x) return; t.impl = 0; assign(t, x); }
- static void dtor(T& t) { if(t.impl) boost::intrusive_ptr_release(t.impl); }
+ static void dtor(T& t) { if(t.impl) intrusive_ptr_release(t.impl); }
static T& assign(T& t, const T& x) { set(t, get(x)); return t;}
};
diff --git a/cpp/src/qpid/RefCounted.h b/cpp/src/qpid/RefCounted.h
index f9e0107103..26e3e2c4ba 100644
--- a/cpp/src/qpid/RefCounted.h
+++ b/cpp/src/qpid/RefCounted.h
@@ -49,15 +49,11 @@ protected:
};
-} // namespace qpid
-
// 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 RefCounted* p) { p->addRef(); }
+inline void intrusive_ptr_release(const RefCounted* p) { p->release(); }
+
+} // namespace qpid
#endif /*!QPID_REFCOUNTED_H*/
diff --git a/cpp/src/qpid/acl/Acl.cpp b/cpp/src/qpid/acl/Acl.cpp
index 917c2e3398..d941577f6a 100644
--- a/cpp/src/qpid/acl/Acl.cpp
+++ b/cpp/src/qpid/acl/Acl.cpp
@@ -51,7 +51,7 @@ using qpid::management::Args;
namespace _qmf = qmf::org::apache::qpid::acl;
Acl::Acl (AclValues& av, Broker& b): aclValues(av), broker(&b), transferAcl(false), mgmtObject(0),
- connectionCounter(new ConnectionCounter(*this, aclValues.aclMaxConnectPerUser, aclValues.aclMaxConnectPerIp))
+ connectionCounter(new ConnectionCounter(*this, aclValues.aclMaxConnectPerUser, aclValues.aclMaxConnectPerIp, aclValues.aclMaxConnectTotal))
{
agent = broker->getManagementAgent();
@@ -60,11 +60,14 @@ Acl::Acl (AclValues& av, Broker& b): aclValues(av), broker(&b), transferAcl(fals
_qmf::Package packageInit(agent);
mgmtObject = new _qmf::Acl (agent, this, broker);
agent->addObject (mgmtObject);
+ mgmtObject->set_maxConnections(aclValues.aclMaxConnectTotal);
+ mgmtObject->set_maxConnectionsPerIp(aclValues.aclMaxConnectPerIp);
+ mgmtObject->set_maxConnectionsPerUser(aclValues.aclMaxConnectPerUser);
}
std::string errorString;
if (!readAclFile(errorString)){
- throw Exception("Could not read ACL file " + errorString);
if (mgmtObject!=0) mgmtObject->set_enforcingAcl(0);
+ throw Exception("Could not read ACL file " + errorString);
}
broker->getConnectionObservers().add(connectionCounter);
QPID_LOG(info, "ACL Plugin loaded");
@@ -121,6 +124,11 @@ bool Acl::authorise(
}
+bool Acl::approveConnection(const qpid::broker::Connection& conn)
+{
+ return connectionCounter->approveConnection(conn);
+}
+
bool Acl::result(
const AclResult& aclreslt,
const std::string& id,
diff --git a/cpp/src/qpid/acl/Acl.h b/cpp/src/qpid/acl/Acl.h
index c3451018ef..4893f71ef2 100644
--- a/cpp/src/qpid/acl/Acl.h
+++ b/cpp/src/qpid/acl/Acl.h
@@ -38,6 +38,7 @@
namespace qpid {
namespace broker {
class Broker;
+class Connection;
}
namespace acl {
@@ -45,8 +46,9 @@ class ConnectionCounter;
struct AclValues {
std::string aclFile;
- uint32_t aclMaxConnectPerUser;
- uint32_t aclMaxConnectPerIp;
+ uint16_t aclMaxConnectPerUser;
+ uint16_t aclMaxConnectPerIp;
+ uint16_t aclMaxConnectTotal;
};
@@ -66,6 +68,9 @@ private:
public:
Acl (AclValues& av, broker::Broker& b);
+ /** reportConnectLimit
+ * issue management counts and alerts for denied connections
+ */
void reportConnectLimit(const std::string user, const std::string addr);
inline virtual bool doTransferAcl() {
@@ -87,6 +92,8 @@ public:
const std::string& ExchangeName,
const std::string& RoutingKey);
+ virtual bool approveConnection(const broker::Connection& connection);
+
virtual ~Acl();
private:
bool result(
diff --git a/cpp/src/qpid/acl/AclConnectionCounter.cpp b/cpp/src/qpid/acl/AclConnectionCounter.cpp
index 5d4e3c1544..052fa3c222 100644
--- a/cpp/src/qpid/acl/AclConnectionCounter.cpp
+++ b/cpp/src/qpid/acl/AclConnectionCounter.cpp
@@ -34,37 +34,82 @@ namespace acl {
//
// This module instantiates a broker::ConnectionObserver and limits client
-// connections by counting connections per user name and per client IP address.
+// connections by counting connections per user name, per client IP address
+// and per total connection count.
//
//
//
//
-ConnectionCounter::ConnectionCounter(Acl& a, uint32_t nl, uint32_t hl) :
- acl(a), nameLimit(nl), hostLimit(hl) {}
+ConnectionCounter::ConnectionCounter(Acl& a, uint16_t nl, uint16_t hl, uint16_t tl) :
+ acl(a), nameLimit(nl), hostLimit(hl), totalLimit(tl), totalCurrentConnections(0) {}
ConnectionCounter::~ConnectionCounter() {}
//
-// limitCheckLH
+// limitApproveLH
+//
+// Connection creation approver. Return true only if user is under limit.
+// Called with lock held.
+//
+bool ConnectionCounter::limitApproveLH(
+ connectCountsMap_t& theMap,
+ const std::string& theName,
+ uint16_t theLimit,
+ bool emitLog) {
+
+ bool result(true);
+ if (theLimit > 0) {
+ uint16_t count;
+ connectCountsMap_t::iterator eRef = theMap.find(theName);
+ if (eRef != theMap.end()) {
+ count = (uint16_t)(*eRef).second;
+ result = count <= theLimit;
+ } else {
+ // Not found
+ count = 0;
+ }
+ if (emitLog) {
+ QPID_LOG(trace, "ACL ConnectionApprover IP=" << theName
+ << " limit=" << theLimit
+ << " curValue=" << count
+ << " result=" << (result ? "allow" : "deny"));
+ }
+ }
+ return result;
+}
+
+
+//
+// countConnectionLH
//
// Increment the name's count in map and return a comparison against the limit.
// called with dataLock already taken
//
-bool ConnectionCounter::limitCheckLH(
- connectCountsMap_t& theMap, const std::string& theName, uint32_t theLimit) {
+bool ConnectionCounter::countConnectionLH(
+ connectCountsMap_t& theMap,
+ const std::string& theName,
+ uint16_t theLimit,
+ bool emitLog) {
bool result(true);
+ uint16_t count(0);
if (theLimit > 0) {
connectCountsMap_t::iterator eRef = theMap.find(theName);
if (eRef != theMap.end()) {
- uint32_t count = (uint32_t)(*eRef).second + 1;
+ count = (uint16_t)(*eRef).second + 1;
(*eRef).second = count;
result = count <= theLimit;
} else {
- theMap[theName] = 1;
+ theMap[theName] = count = 1;
+ }
+ if (emitLog) {
+ QPID_LOG(trace, "ACL ConnectionApprover user=" << theName
+ << " limit=" << theLimit
+ << " curValue=" << count
+ << " result=" << (result ? "allow" : "deny"));
}
}
return result;
@@ -78,12 +123,12 @@ bool ConnectionCounter::limitCheckLH(
// called with dataLock already taken
//
void ConnectionCounter::releaseLH(
- connectCountsMap_t& theMap, const std::string& theName, uint32_t theLimit) {
+ connectCountsMap_t& theMap, const std::string& theName, uint16_t theLimit) {
if (theLimit > 0) {
connectCountsMap_t::iterator eRef = theMap.find(theName);
if (eRef != theMap.end()) {
- uint32_t count = (uint32_t) (*eRef).second;
+ uint16_t count = (uint16_t) (*eRef).second;
assert (count > 0);
if (1 == count) {
theMap.erase (eRef);
@@ -103,52 +148,20 @@ void ConnectionCounter::releaseLH(
// connection - called during Connection's constructor
//
void ConnectionCounter::connection(broker::Connection& connection) {
- QPID_LOG(trace, "ACL ConnectionCounter connection IP:" << connection.getMgmtId()
- << ", userId:" << connection.getUserId());
+ QPID_LOG(trace, "ACL ConnectionCounter new connection: " << connection.getMgmtId());
- Mutex::ScopedLock locker(dataLock);
-
- connectProgressMap[connection.getMgmtId()] = C_CREATED;
-}
-
-
-//
-// opened - called when first AMQP frame is received over Connection
-//
-void ConnectionCounter::opened(broker::Connection& connection) {
- QPID_LOG(trace, "ACL ConnectionCounter Opened IP:" << connection.getMgmtId()
- << ", userId:" << connection.getUserId());
+ const std::string& hostName(getClientHost(connection.getMgmtId()));
Mutex::ScopedLock locker(dataLock);
- const std::string& userName( connection.getUserId());
- const std::string& hostName(getClientHost(connection.getMgmtId()));
+ // Total connections goes up
+ totalCurrentConnections += 1;
- // Bump state from CREATED to OPENED
- (void) limitCheckLH(connectProgressMap, connection.getMgmtId(), C_OPENED);
-
- bool nameOk = limitCheckLH(connectByNameMap, userName, nameLimit);
- bool hostOk = limitCheckLH(connectByHostMap, hostName, hostLimit);
-
- if (!nameOk) {
- // User has too many
- acl.reportConnectLimit(userName, hostName);
- QPID_LOG(notice, "ACL ConnectionCounter User '" << userName
- << "' exceeded maximum allowed connections");
- throw Exception(
- QPID_MSG("User '" << userName
- << "' exceeded maximum allowed connections"));
- }
+ // Record the fact that this connection exists
+ connectProgressMap[connection.getMgmtId()] = C_CREATED;
- if (!hostOk) {
- // Host has too many
- acl.reportConnectLimit(userName, hostName);
- QPID_LOG(notice, "ACL ConnectionCounter Client host '" << hostName
- << "' exceeded maximum allowed connections");
- throw Exception(
- QPID_MSG("Client host '" << hostName
- << "' exceeded maximum allowed connections"));
- }
+ // Count the connection from this host.
+ (void) countConnectionLH(connectByHostMap, hostName, hostLimit, false);
}
@@ -156,7 +169,7 @@ void ConnectionCounter::opened(broker::Connection& connection) {
// closed - called during Connection's destructor
//
void ConnectionCounter::closed(broker::Connection& connection) {
- QPID_LOG(trace, "ACL ConnectionCounter Closed IP:" << connection.getMgmtId()
+ QPID_LOG(trace, "ACL ConnectionCounter closed: " << connection.getMgmtId()
<< ", userId:" << connection.getUserId());
Mutex::ScopedLock locker(dataLock);
@@ -165,32 +178,129 @@ void ConnectionCounter::closed(broker::Connection& connection) {
if (eRef != connectProgressMap.end()) {
if ((*eRef).second == C_OPENED){
// Normal case: connection was created and opened.
- // Decrement in-use counts
+ // Decrement user in-use counts
releaseLH(connectByNameMap,
connection.getUserId(),
nameLimit);
-
- releaseLH(connectByHostMap,
- getClientHost(connection.getMgmtId()),
- hostLimit);
} else {
// Connection was created but not opened.
- // Don't decrement any connection counts.
+ // Don't decrement user count.
}
+
+ // Decrement host in-use count.
+ releaseLH(connectByHostMap,
+ getClientHost(connection.getMgmtId()),
+ hostLimit);
+
+ // destroy connection progress indicator
connectProgressMap.erase(eRef);
} else {
// connection not found in progress map
- QPID_LOG(notice, "ACL ConnectionCounter info for '" << connection.getMgmtId()
+ QPID_LOG(notice, "ACL ConnectionCounter closed info for '" << connection.getMgmtId()
<< "' not found in connection state pool");
}
+
+ // total connections
+ totalCurrentConnections -= 1;
}
//
+// approveConnection
+// check total connections, connections from IP, connections by user and
+// disallow if over any limit
+//
+bool ConnectionCounter::approveConnection(const broker::Connection& connection)
+{
+ const std::string& hostName(getClientHost(connection.getMgmtId()));
+ const std::string& userName( connection.getUserId());
+
+ Mutex::ScopedLock locker(dataLock);
+
+ // Bump state from CREATED to OPENED
+ (void) countConnectionLH(connectProgressMap, connection.getMgmtId(),
+ C_OPENED, false);
+
+ // Approve total connections
+ bool okTotal = true;
+ if (totalLimit > 0) {
+ okTotal = totalCurrentConnections <= totalLimit;
+ if (!connection.isShadow()) {
+ QPID_LOG(trace, "ACL ConnectionApprover totalLimit=" << totalLimit
+ << " curValue=" << totalCurrentConnections
+ << " result=" << (okTotal ? "allow" : "deny"));
+ }
+ }
+
+ // Approve by IP host connections
+ bool okByIP = limitApproveLH(connectByHostMap, hostName, hostLimit, !connection.isShadow());
+
+ // Count and Approve the connection by the user
+ bool okByUser = countConnectionLH(connectByNameMap, userName, nameLimit, !connection.isShadow());
+
+ if (!connection.isShadow()) {
+ // Emit separate log for each disapproval
+ if (!okTotal) {
+ QPID_LOG(error, "Client max total connection count limit of " << totalLimit
+ << " exceeded by '"
+ << connection.getMgmtId() << "', user: '"
+ << userName << "'. Connection refused");
+ }
+ if (!okByIP) {
+ QPID_LOG(error, "Client max per-host connection count limit of "
+ << hostLimit << " exceeded by '"
+ << connection.getMgmtId() << "', user: '"
+ << userName << "'. Connection refused.");
+ }
+ if (!okByUser) {
+ QPID_LOG(error, "Client max per-user connection count limit of "
+ << nameLimit << " exceeded by '"
+ << connection.getMgmtId() << "', user: '"
+ << userName << "'. Connection refused.");
+ }
+
+ // Count/Event once for each disapproval
+ bool result = okTotal && okByIP && okByUser;
+ if (!result) {
+ acl.reportConnectLimit(userName, hostName);
+ }
+
+ return result;
+ } else {
+ // Always allow shadow connections
+ if (!okTotal) {
+ QPID_LOG(warning, "Client max total connection count limit of " << totalLimit
+ << " exceeded by '"
+ << connection.getMgmtId() << "', user: '"
+ << userName << "' but still within tolerance. Cluster connection allowed");
+ }
+ if (!okByIP) {
+ QPID_LOG(warning, "Client max per-host connection count limit of "
+ << hostLimit << " exceeded by '"
+ << connection.getMgmtId() << "', user: '"
+ << userName << "' but still within tolerance. Cluster connection allowed");
+ }
+ if (!okByUser) {
+ QPID_LOG(warning, "Client max per-user connection count limit of "
+ << nameLimit << " exceeded by '"
+ << connection.getMgmtId() << "', user: '"
+ << userName << "' but still within tolerance. Cluster connection allowed");
+ }
+ if (okTotal && okByIP && okByUser) {
+ QPID_LOG(debug, "Cluster client connection: '"
+ << connection.getMgmtId() << "', user '"
+ << userName << "' allowed");
+ }
+ return true;
+ }
+}
+
+//
// getClientIp - given a connection's mgmtId return the client host part.
//
// TODO: Ideally this would be a method of the connection itself.
+// TODO: Verify it works with rdma connection names.
//
std::string ConnectionCounter::getClientHost(const std::string mgmtId)
{
diff --git a/cpp/src/qpid/acl/AclConnectionCounter.h b/cpp/src/qpid/acl/AclConnectionCounter.h
index 31d11540fd..eec8e90256 100644
--- a/cpp/src/qpid/acl/AclConnectionCounter.h
+++ b/cpp/src/qpid/acl/AclConnectionCounter.h
@@ -48,32 +48,52 @@ private:
enum CONNECTION_PROGRESS { C_CREATED=1, C_OPENED=2 };
Acl& acl;
- uint32_t nameLimit;
- uint32_t hostLimit;
+ uint16_t nameLimit;
+ uint16_t hostLimit;
+ uint16_t totalLimit;
+ uint16_t totalCurrentConnections;
qpid::sys::Mutex dataLock;
+ /** Records per-connection state */
connectCountsMap_t connectProgressMap;
+
+ /** Records per-username counts */
connectCountsMap_t connectByNameMap;
+
+ /** Records per-host counts */
connectCountsMap_t connectByHostMap;
+ /** Given a connection's management ID, return the client host name */
std::string getClientHost(const std::string mgmtId);
- bool limitCheckLH(connectCountsMap_t& theMap,
- const std::string& theName,
- uint32_t theLimit);
+ /** Return approval for proposed connection */
+ bool limitApproveLH(connectCountsMap_t& theMap,
+ const std::string& theName,
+ uint16_t theLimit,
+ bool emitLog);
+
+ /** Record a connection.
+ * @return indication if user/host is over its limit */
+ bool countConnectionLH(connectCountsMap_t& theMap,
+ const std::string& theName,
+ uint16_t theLimit,
+ bool emitLog);
+ /** Release a connection */
void releaseLH(connectCountsMap_t& theMap,
const std::string& theName,
- uint32_t theLimit);
+ uint16_t theLimit);
public:
- ConnectionCounter(Acl& acl, uint32_t nl, uint32_t hl);
+ ConnectionCounter(Acl& acl, uint16_t nl, uint16_t hl, uint16_t tl);
~ConnectionCounter();
+ // ConnectionObserver interface
void connection(broker::Connection& connection);
- void opened(broker::Connection& connection);
void closed(broker::Connection& connection);
+ // Connection counting
+ bool approveConnection(const broker::Connection& conn);
};
}} // namespace qpid::ha
diff --git a/cpp/src/qpid/acl/AclData.cpp b/cpp/src/qpid/acl/AclData.cpp
index da7f240a9b..a07176dc76 100644
--- a/cpp/src/qpid/acl/AclData.cpp
+++ b/cpp/src/qpid/acl/AclData.cpp
@@ -305,7 +305,9 @@ namespace acl {
// lookup
//
// The ACL main business logic function of matching rules and declaring
- // an allow or deny result.
+ // an allow or deny result. This lookup is the fastpath per-message
+ // lookup to verify if a user is allowed to publish to an exchange with
+ // a given key.
//
AclResult AclData::lookup(
const std::string& id,
@@ -331,7 +333,8 @@ namespace acl {
if (itrRule != actionList[action][objType]->end() )
{
- //loop the vector
+ // Found a rule list for this user-action-object set.
+ // Search the rule list for a matching rule.
ruleSetItr rsItr = itrRule->second.end();
for (int cnt = itrRule->second.size(); cnt != 0; cnt--)
{
@@ -339,56 +342,46 @@ namespace acl {
QPID_LOG(debug, "ACL: checking rule " << rsItr->toString());
- // loop the names looking for match
+ // Search on exchange name and routing key only if specfied in rule.
bool match =true;
- for (specPropertyMapItr pMItr = rsItr->props.begin();
- (pMItr != rsItr->props.end()) && match;
- pMItr++)
+ if (rsItr->pubExchNameInRule)
{
- //match name is exists first
- switch (pMItr->first)
+ if (matchProp(rsItr->pubExchName, name))
{
- case acl::SPECPROP_NAME:
- if (matchProp(pMItr->second, name))
- {
- QPID_LOG(debug, "ACL: lookup exchange name '"
- << name << "' matched with rule name '"
- << pMItr->second << "'");
-
- }
- else
- {
- match= false;
- QPID_LOG(debug, "ACL: lookup exchange name '"
- << name << "' did not match with rule name '"
- << pMItr->second << "'");
- }
- break;
+ QPID_LOG(debug, "ACL: Rule: " << rsItr->rawRuleNum << " lookup exchange name '"
+ << name << "' matched with rule name '"
+ << rsItr->pubExchName << "'");
- case acl::SPECPROP_ROUTINGKEY:
- if (matchProp(pMItr->second, routingKey))
- {
- QPID_LOG(debug, "ACL: lookup key name '"
- << routingKey << "' matched with rule routing key '"
- << pMItr->second << "'");
- }
- else
- {
- match= false;
- QPID_LOG(debug, "ACL: lookup key name '"
- << routingKey << "' did not match with rule routing key '"
- << pMItr->second << "'");
- }
- break;
+ }
+ else
+ {
+ match= false;
+ QPID_LOG(debug, "ACL: Rule: " << rsItr->rawRuleNum << " lookup exchange name '"
+ << name << "' did not match with rule name '"
+ << rsItr->pubExchName << "'");
+ }
+ }
- default:
- // Don't care
- break;
- };
+ if (match && rsItr->pubRoutingKeyInRule)
+ {
+ if (rsItr->matchRoutingKey(routingKey))
+ {
+ QPID_LOG(debug, "ACL: Rule: " << rsItr->rawRuleNum << " lookup key name '"
+ << routingKey << "' matched with rule routing key '"
+ << rsItr->pubRoutingKey << "'");
+ }
+ else
+ {
+ QPID_LOG(debug, "ACL: Rule: " << rsItr->rawRuleNum << " lookup key name '"
+ << routingKey << "' did not match with rule routing key '"
+ << rsItr->pubRoutingKey << "'");
+ match = false;
+ }
}
+
if (match){
aclresult = rsItr->ruleMode;
- QPID_LOG(debug,"ACL: Successful match, the decision is:"
+ QPID_LOG(debug,"ACL: Rule: " << rsItr->rawRuleNum << " Successful match, the decision is:"
<< AclHelper::getAclResultStr(aclresult));
return aclresult;
}
diff --git a/cpp/src/qpid/acl/AclData.h b/cpp/src/qpid/acl/AclData.h
index 1c1cb3e9c6..ca0a676a1c 100644
--- a/cpp/src/qpid/acl/AclData.h
+++ b/cpp/src/qpid/acl/AclData.h
@@ -21,6 +21,9 @@
*/
#include "qpid/broker/AclModule.h"
+#include "AclTopicMatch.h"
+#include "qpid/log/Statement.h"
+#include "boost/shared_ptr.hpp"
#include <vector>
#include <sstream>
@@ -48,18 +51,29 @@ public:
// A single ACL file entry may create many rule entries in
// many ruleset vectors.
//
- struct rule {
+ struct Rule {
+ typedef broker::TopicExchange::TopicExchangeTester topicTester;
int rawRuleNum; // rule number in ACL file
qpid::acl::AclResult ruleMode; // combined allow/deny log/nolog
specPropertyMap props; //
+ bool pubRoutingKeyInRule;
+ std::string pubRoutingKey;
+ boost::shared_ptr<topicTester> pTTest;
+ bool pubExchNameInRule;
+ std::string pubExchName;
-
- rule (int ruleNum, qpid::acl::AclResult res, specPropertyMap& p) :
+ Rule (int ruleNum, qpid::acl::AclResult res, specPropertyMap& p) :
rawRuleNum(ruleNum),
ruleMode(res),
- props(p)
- {};
+ props(p),
+ pubRoutingKeyInRule(false),
+ pubRoutingKey(),
+ pTTest(boost::shared_ptr<topicTester>(new topicTester())),
+ pubExchNameInRule(false),
+ pubExchName()
+ {}
+
std::string toString () const {
std::ostringstream ruleStr;
@@ -76,9 +90,21 @@ public:
ruleStr << " }]";
return ruleStr.str();
}
+
+ void addTopicTest(const std::string& pattern) {
+ pTTest->addBindingKey(broker::TopicExchange::normalize(pattern));
+ }
+
+ // Topic Exchange tester
+ // return true if any bindings match 'pattern'
+ bool matchRoutingKey(const std::string& pattern) const
+ {
+ topicTester::BindingVec bv;
+ return pTTest->findMatches(pattern, bv);
+ }
};
- typedef std::vector<rule> ruleSet;
+ typedef std::vector<Rule> ruleSet;
typedef ruleSet::const_iterator ruleSetItr;
typedef std::map<std::string, ruleSet > actionObject; // user
typedef actionObject::iterator actObjItr;
diff --git a/cpp/src/qpid/acl/AclPlugin.cpp b/cpp/src/qpid/acl/AclPlugin.cpp
index 6c18cd2749..ebf5e90afe 100644
--- a/cpp/src/qpid/acl/AclPlugin.cpp
+++ b/cpp/src/qpid/acl/AclPlugin.cpp
@@ -39,10 +39,13 @@ struct AclOptions : public Options {
AclValues& values;
AclOptions(AclValues& v) : Options("ACL Options"), values(v) {
+ values.aclMaxConnectTotal = 500;
addOptions()
("acl-file", optValue(values.aclFile, "FILE"), "The policy file to load from, loaded from data dir")
- ("acl-max-connect-per-user", optValue(values.aclMaxConnectPerUser, "N"), "The maximum number of connections allowed per user")
- ("acl-max-connect-per-ip" , optValue(values.aclMaxConnectPerIp, "N"), "The maximum number of connections allowed per host IP address");
+ ("max-connections" , optValue(values.aclMaxConnectTotal, "N"), "The maximum combined number of connections allowed. 0 implies no limit.")
+ ("max-connections-per-user", optValue(values.aclMaxConnectPerUser, "N"), "The maximum number of connections allowed per user. 0 implies no limit.")
+ ("max-connections-per-ip" , optValue(values.aclMaxConnectPerIp, "N"), "The maximum number of connections allowed per host IP address. 0 implies no limit.")
+ ;
}
};
@@ -69,7 +72,6 @@ struct AclPlugin : public Plugin {
oss << b.getDataDir().getPath() << "/" << values.aclFile;
values.aclFile = oss.str();
}
-
acl = new Acl(values, b);
b.setAcl(acl.get());
b.addFinalizer(boost::bind(&AclPlugin::shutdown, this));
diff --git a/cpp/src/qpid/acl/AclReader.cpp b/cpp/src/qpid/acl/AclReader.cpp
index 80debf1bd1..f9be49b88d 100644
--- a/cpp/src/qpid/acl/AclReader.cpp
+++ b/cpp/src/qpid/acl/AclReader.cpp
@@ -101,7 +101,7 @@ namespace acl {
<< AclHelper::getAclResultStr(d->decisionMode));
foundmode = true;
} else {
- AclData::rule rule(cnt, (*i)->res, (*i)->props);
+ AclData::Rule rule(cnt, (*i)->res, (*i)->props);
// Action -> Object -> map<user -> set<Rule> >
std::ostringstream actionstr;
@@ -110,8 +110,27 @@ namespace acl {
(*i)->actionAll ? acnt++ : acnt = acl::ACTIONSIZE) {
if (acnt == acl::ACT_PUBLISH)
+ {
d->transferAcl = true; // we have transfer ACL
-
+ // For Publish the only object should be Exchange
+ // and the only property should be routingkey.
+ // Go through the rule properties and find the name and the key.
+ // If found then place them specially for the lookup engine.
+ for (pmCitr pItr=(*i)->props.begin(); pItr!=(*i)->props.end(); pItr++) {
+ if (acl::SPECPROP_ROUTINGKEY == pItr->first)
+ {
+ rule.pubRoutingKeyInRule = true;
+ rule.pubRoutingKey = (std::string)pItr->second;
+ rule.addTopicTest(rule.pubRoutingKey);
+ break;
+ }
+ if (acl::SPECPROP_NAME == pItr->first)
+ {
+ rule.pubExchNameInRule = true;
+ rule.pubExchName = pItr->second;
+ }
+ }
+ }
actionstr << AclHelper::getActionStr((Action) acnt) << ",";
//find the Action, create if not exist
@@ -285,7 +304,7 @@ namespace acl {
if (ws) {
ret = true;
} else {
- errorStream << ACL_FORMAT_ERR_LOG_PREFIX << "Line : " << lineNumber
+ errorStream << ACL_FORMAT_ERR_LOG_PREFIX << "Line : " << lineNumber
<< ", Non-continuation line must start with \"group\" or \"acl\".";
ret = false;
}
@@ -314,13 +333,23 @@ namespace acl {
if (contFlag) {
gmCitr citr = groups.find(groupName);
for (unsigned i = 0; i < toksSize; i++) {
- if (!isValidUserName(toks[i])) return false;
+ if (isValidGroupName(toks[i])) {
+ if (toks[i] == groupName) {
+ QPID_LOG(debug, "ACL: Line: " << lineNumber
+ << ", Ignoring recursive sub-group \"" << toks[i] << "\".");
+ continue;
+ } else if (groups.find(toks[i]) == groups.end()) {
+ errorStream << ACL_FORMAT_ERR_LOG_PREFIX << "Line : " << lineNumber
+ << ", Sub-group \"" << toks[i] << "\" not defined yet.";
+ return false;
+ }
+ } else if (!isValidUserName(toks[i])) return false;
addName(toks[i], citr->second);
}
} else {
const unsigned minimumSize = (cont ? 2 : 3);
if (toksSize < minimumSize) {
- errorStream << ACL_FORMAT_ERR_LOG_PREFIX << "Line : " << lineNumber
+ errorStream << ACL_FORMAT_ERR_LOG_PREFIX << "Line : " << lineNumber
<< ", Insufficient tokens for group definition.";
return false;
}
@@ -332,7 +361,17 @@ namespace acl {
gmCitr citr = addGroup(toks[1]);
if (citr == groups.end()) return false;
for (unsigned i = 2; i < toksSize; i++) {
- if (!isValidUserName(toks[i])) return false;
+ if (isValidGroupName(toks[i])) {
+ if (toks[i] == groupName) {
+ QPID_LOG(debug, "ACL: Line: " << lineNumber
+ << ", Ignoring recursive sub-group \"" << toks[i] << "\".");
+ continue;
+ } else if (groups.find(toks[i]) == groups.end()) {
+ errorStream << ACL_FORMAT_ERR_LOG_PREFIX << "Line : " << lineNumber
+ << ", Sub-group \"" << toks[i] << "\" not defined yet.";
+ return false;
+ }
+ } else if (!isValidUserName(toks[i])) return false;
addName(toks[i], citr->second);
}
}
@@ -356,7 +395,7 @@ namespace acl {
void AclReader::addName(const std::string& name, nameSetPtr groupNameSet) {
gmCitr citr = groups.find(name);
- if (citr != groups.end() && citr->first != name){
+ if (citr != groups.end()) {
// This is a previously defined group: add all the names in that group to this group
groupNameSet->insert(citr->second->begin(), citr->second->end());
} else {
@@ -459,7 +498,7 @@ namespace acl {
nvPair propNvp = splitNameValuePair(toks[i]);
if (propNvp.second.size() == 0) {
errorStream << ACL_FORMAT_ERR_LOG_PREFIX << "Line : " << lineNumber
- <<", Badly formed property name-value pair \""
+ <<", Badly formed property name-value pair \""
<< propNvp.first << "\". (Must be name=value)";
return false;
}
diff --git a/cpp/src/qpid/acl/AclReader.h b/cpp/src/qpid/acl/AclReader.h
index 730013f4ed..6351c1e509 100644
--- a/cpp/src/qpid/acl/AclReader.h
+++ b/cpp/src/qpid/acl/AclReader.h
@@ -26,6 +26,7 @@
#include <string>
#include <vector>
#include <sstream>
+#include <memory>
#include "qpid/acl/AclData.h"
#include "qpid/broker/AclModule.h"
diff --git a/cpp/src/qpid/acl/AclTopicMatch.h b/cpp/src/qpid/acl/AclTopicMatch.h
new file mode 100644
index 0000000000..486c229ad5
--- /dev/null
+++ b/cpp/src/qpid/acl/AclTopicMatch.h
@@ -0,0 +1,89 @@
+#ifndef QPID_ACL_TOPIC_MATCH_H
+#define QPID_ACL_TOPIC_MATCH_H
+
+/*
+ *
+ * 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.
+ *
+ */
+
+#include "qpid/broker/TopicKeyNode.h"
+#include "qpid/broker/TopicExchange.h"
+#include "qpid/log/Statement.h"
+#include "boost/shared_ptr.hpp"
+#include <vector>
+#include <sstream>
+
+namespace qpid {
+namespace broker {
+
+// Class for executing topic exchange routing key matching rules in
+// Acl code the allows or denies users publishing to an exchange.
+class TopicExchange::TopicExchangeTester {
+
+class boundNode;
+
+public:
+ typedef std::vector<bool> BindingVec;
+ typedef TopicKeyNode<boundNode> TestBindingNode;
+
+private:
+ // Target class to be bound into topic key tree
+ class boundNode {
+ public:
+ BindingVec bindingVector;
+ };
+
+ // Acl binding trees contain only one node each.
+ // When the iterator sees it then the node matches the caller's spec.
+ class TestFinder : public TestBindingNode::TreeIterator {
+ public:
+ TestFinder(BindingVec& m) : bv(m), found(false) {};
+ ~TestFinder() {};
+ bool visit(TestBindingNode& /*node*/) {
+ assert(!found);
+ found = true;
+ return true;
+ }
+ BindingVec& bv;
+ bool found;
+ };
+
+public:
+ TopicExchangeTester() {};
+ ~TopicExchangeTester() {};
+ bool addBindingKey(const std::string& bKey) {
+ std::string routingPattern = normalize(bKey);
+ boundNode *mbn = bindingTree.add(routingPattern);
+ if (mbn) {
+ // push a dummy binding to mark this node as "non-leaf"
+ mbn->bindingVector.push_back(true);
+ return true;
+ }
+ return false;
+ }
+
+ bool findMatches(const std::string& rKey, BindingVec& matches) {
+ TestFinder testFinder(matches);
+ bindingTree.iterateMatch( rKey, testFinder );
+ return testFinder.found;
+ }
+
+private:
+ TestBindingNode bindingTree;
+};
+}} // namespace qpid::broker
+
+#endif // QPID_ACL_TOPIC_MATCH_H
diff --git a/cpp/src/qpid/acl/AclValidator.cpp b/cpp/src/qpid/acl/AclValidator.cpp
index 49bb65db4b..85f0f7c240 100644
--- a/cpp/src/qpid/acl/AclValidator.cpp
+++ b/cpp/src/qpid/acl/AclValidator.cpp
@@ -131,7 +131,7 @@ namespace acl {
boost::bind(&AclValidator::validateRule, this, _1));
}
- void AclValidator::validateRule(qpid::acl::AclData::rule& rule){
+ void AclValidator::validateRule(qpid::acl::AclData::Rule& rule){
std::for_each(rule.props.begin(),
rule.props.end(),
boost::bind(&AclValidator::validateProperty, this, _1));
diff --git a/cpp/src/qpid/acl/AclValidator.h b/cpp/src/qpid/acl/AclValidator.h
index f85c241b06..76eb222d2f 100644
--- a/cpp/src/qpid/acl/AclValidator.h
+++ b/cpp/src/qpid/acl/AclValidator.h
@@ -71,7 +71,7 @@ class AclValidator {
public:
void validateRuleSet(std::pair<const std::string, qpid::acl::AclData::ruleSet>& rules);
- void validateRule(qpid::acl::AclData::rule& rule);
+ void validateRule(qpid::acl::AclData::Rule& rule);
void validateProperty(std::pair<const qpid::acl::SpecProperty, std::string>& prop);
void validate(boost::shared_ptr<AclData> d);
AclValidator();
diff --git a/cpp/src/qpid/acl/management-schema.xml b/cpp/src/qpid/acl/management-schema.xml
index 19fe37333c..f52c251bed 100644
--- a/cpp/src/qpid/acl/management-schema.xml
+++ b/cpp/src/qpid/acl/management-schema.xml
@@ -17,13 +17,16 @@
-->
<class name="Acl">
- <property name="brokerRef" type="objId" references="org.apache.qpid.broker:Broker" access="RO" index="y" parentRef="y"/>
- <property name="policyFile" type="lstr" access="RO" desc="Name of the policy file"/>
- <property name="enforcingAcl" type="bool" access="RO" desc="Currently Enforcing ACL"/>
- <property name="transferAcl" type="bool" access="RO" desc="Any transfer ACL rules in force"/>
- <property name="lastAclLoad" type="absTime" access="RO" desc="Timestamp of last successful load of ACL"/>
- <statistic name="aclDenyCount" type="count64" unit="request" desc="Number of ACL requests denied"/>
- <statistic name="connectionDenyCount" type="count64" unit="connection" desc="Number of connections denied"/>
+ <property name="brokerRef" type="objId" references="org.apache.qpid.broker:Broker" access="RO" index="y" parentRef="y"/>
+ <property name="policyFile" type="lstr" access="RO" desc="Name of the policy file"/>
+ <property name="enforcingAcl" type="bool" access="RO" desc="Currently Enforcing ACL"/>
+ <property name="transferAcl" type="bool" access="RO" desc="Any transfer ACL rules in force"/>
+ <property name="lastAclLoad" type="absTime" access="RO" desc="Timestamp of last successful load of ACL"/>
+ <property name="maxConnections" type="uint16" access="RO" desc="Maximum allowed connections"/>
+ <property name="maxConnectionsPerIp" type="uint16" access="RO" desc="Maximum allowed connections"/>
+ <property name="maxConnectionsPerUser" type="uint16" access="RO" desc="Maximum allowed connections"/>
+ <statistic name="aclDenyCount" type="count64" unit="request" desc="Number of ACL requests denied"/>
+ <statistic name="connectionDenyCount" type="count64" unit="connection" desc="Number of connections denied"/>
<method name="reloadACLFile" desc="Reload the ACL file"/>
diff --git a/cpp/src/qpid/amqp_0_10/Codecs.cpp b/cpp/src/qpid/amqp_0_10/Codecs.cpp
index b976a5d09b..1288652ee1 100644
--- a/cpp/src/qpid/amqp_0_10/Codecs.cpp
+++ b/cpp/src/qpid/amqp_0_10/Codecs.cpp
@@ -52,9 +52,7 @@ template <class T, class U, class F> void convert(const T& from, U& to, F f)
}
Variant::Map::value_type toVariantMapEntry(const FieldTable::value_type& in);
-FieldTable::value_type toFieldTableEntry(const Variant::Map::value_type& in);
Variant toVariant(boost::shared_ptr<FieldValue> in);
-boost::shared_ptr<FieldValue> toFieldValue(const Variant& in);
template <class T, class U, class F> void translate(boost::shared_ptr<FieldValue> in, U& u, F f)
{
@@ -70,20 +68,6 @@ template <class T, class U, class F> T* toFieldValueCollection(const U& u, F f)
return new T(t);
}
-FieldTableValue* toFieldTableValue(const Variant::Map& map)
-{
- FieldTable ft;
- convert(map, ft, &toFieldTableEntry);
- return new FieldTableValue(ft);
-}
-
-ListValue* toListValue(const Variant::List& list)
-{
- List l;
- convert(list, l, &toFieldValue);
- return new ListValue(l);
-}
-
void setEncodingFor(Variant& out, uint8_t code)
{
switch(code){
@@ -151,7 +135,7 @@ Variant toVariant(boost::shared_ptr<FieldValue> in)
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:
@@ -217,89 +201,254 @@ boost::shared_ptr<FieldValue> convertString(const std::string& value, const std:
}
}
-boost::shared_ptr<FieldValue> toFieldValue(const Variant& in)
+Variant::Map::value_type toVariantMapEntry(const FieldTable::value_type& in)
{
- boost::shared_ptr<FieldValue> out;
- switch (in.getType()) {
- case VAR_VOID: out = boost::shared_ptr<FieldValue>(new VoidValue()); break;
- case VAR_BOOL: out = boost::shared_ptr<FieldValue>(new BoolValue(in.asBool())); break;
- case VAR_UINT8: out = boost::shared_ptr<FieldValue>(new Unsigned8Value(in.asUint8())); break;
- case VAR_UINT16: out = boost::shared_ptr<FieldValue>(new Unsigned16Value(in.asUint16())); break;
- case VAR_UINT32: out = boost::shared_ptr<FieldValue>(new Unsigned32Value(in.asUint32())); break;
- case VAR_UINT64: out = boost::shared_ptr<FieldValue>(new Unsigned64Value(in.asUint64())); break;
- case VAR_INT8: out = boost::shared_ptr<FieldValue>(new Integer8Value(in.asInt8())); break;
- case VAR_INT16: out = boost::shared_ptr<FieldValue>(new Integer16Value(in.asInt16())); break;
- case VAR_INT32: out = boost::shared_ptr<FieldValue>(new Integer32Value(in.asInt32())); break;
- case VAR_INT64: out = boost::shared_ptr<FieldValue>(new Integer64Value(in.asInt64())); break;
- case VAR_FLOAT: out = boost::shared_ptr<FieldValue>(new FloatValue(in.asFloat())); break;
- case VAR_DOUBLE: out = boost::shared_ptr<FieldValue>(new DoubleValue(in.asDouble())); break;
- case VAR_STRING: out = convertString(in.asString(), in.getEncoding()); break;
- case VAR_UUID: out = boost::shared_ptr<FieldValue>(new UuidValue(in.asUuid().data())); break;
- case VAR_MAP:
- out = boost::shared_ptr<FieldValue>(toFieldTableValue(in.asMap()));
- break;
- case VAR_LIST:
- out = boost::shared_ptr<FieldValue>(toListValue(in.asList()));
+ return Variant::Map::value_type(in.first, toVariant(in.second));
+}
+
+struct DecodeBuffer
+{
+ Buffer buffer;
+
+ DecodeBuffer(const std::string& s) : buffer(const_cast<char*>(s.data()), s.size()) {}
+
+ template <class T> void decode(T& t) { t.decode(buffer); }
+
+};
+
+template <class T, class U, class F> void _decode(const std::string& data, U& value, F f)
+{
+ T t;
+ DecodeBuffer buffer(data);
+ buffer.decode(t);
+ convert(t, value, f);
+}
+
+uint32_t encodedSize(const Variant::Map& values);
+uint32_t encodedSize(const Variant::List& values);
+uint32_t encodedSize(const std::string& value);
+
+uint32_t encodedSize(const Variant& value)
+{
+ switch (value.getType()) {
+ case VAR_VOID:
+ return 0;
+ case VAR_BOOL:
+ case VAR_UINT8:
+ case VAR_INT8:
+ return 1;
+ case VAR_UINT16:
+ case VAR_INT16:
+ return 2;
break;
+ case VAR_UINT32:
+ case VAR_INT32:
+ case VAR_FLOAT:
+ return 4;
+ case VAR_UINT64:
+ case VAR_INT64:
+ case VAR_DOUBLE:
+ return 8;
+ case VAR_UUID:
+ return 16;
+ case VAR_MAP:
+ return encodedSize(value.asMap());
+ case VAR_LIST:
+ return encodedSize(value.asList());
+ case VAR_STRING:
+ return encodedSize(value.getString());
+ default:
+ throw Exception("Couldn't encode Variant: Illegal type code");
}
- return out;
}
-Variant::Map::value_type toVariantMapEntry(const FieldTable::value_type& in)
+uint32_t encodedSize(const Variant::Map& values)
{
- return Variant::Map::value_type(in.first, toVariant(in.second));
+ uint32_t size = 4/*size field*/ + 4/*count field*/;
+ for(Variant::Map::const_iterator i = values.begin(); i != values.end(); ++i) {
+ size += 1/*size of key*/ + (i->first).size() + 1/*typecode*/ + encodedSize(i->second);
+ }
+ return size;
}
-FieldTable::value_type toFieldTableEntry(const Variant::Map::value_type& in)
+uint32_t encodedSize(const Variant::Map& values, const std::string& efield, const Variant& evalue)
{
- return FieldTable::value_type(in.first, toFieldValue(in.second));
+ uint32_t size = 4/*size field*/ + 4/*count field*/;
+ for(Variant::Map::const_iterator i = values.begin(); i != values.end(); ++i) {
+ size += 1/*size of key*/ + (i->first).size() + 1/*typecode*/ + encodedSize(i->second);
+ }
+ size += 1/*size of key*/ + efield.size() + 1/*typecode*/ + encodedSize(evalue);
+ return size;
}
-struct EncodeBuffer
+uint32_t encodedSize(const Variant::List& values)
{
- char* data;
- Buffer buffer;
+ uint32_t size = 4/*size field*/ + 4/*count field*/;
+ for(Variant::List::const_iterator i = values.begin(); i != values.end(); ++i) {
+ size += 1/*typecode*/ + encodedSize(*i);
+ }
+ return size;
+}
+
+uint32_t encodedSize(const std::string& value)
+{
+ uint32_t size = value.size();
+ if (size > std::numeric_limits<uint16_t>::max()) {
+ return size + 4; /*Long size*/
+ } else {
+ return size + 2; /*Short size*/
+ }
+}
- EncodeBuffer(size_t size) : data(new char[size]), buffer(data, size) {}
- ~EncodeBuffer() { delete[] data; }
+void encode(const std::string& value, const std::string& encoding, qpid::framing::Buffer& buffer)
+{
+ uint32_t size = value.size();
+ if (size > std::numeric_limits<uint16_t>::max()) {
+ if (encoding == utf8 || encoding == utf16 || encoding == iso885915) {
+ throw Exception(QPID_MSG("Could not encode " << encoding << " character string - too long (" << size << " bytes)"));
+ } else {
+ buffer.putOctet(0xa0);
+ buffer.putLong(size);
+ buffer.putRawData(value);
+ }
+ } else {
+ if (encoding == utf8) {
+ buffer.putOctet(0x95);
+ } else if (encoding == utf16) {
+ buffer.putOctet(0x96);
+ } else if (encoding == iso885915) {
+ buffer.putOctet(0x94);
+ } else {
+ buffer.putOctet(0x90);
+ }
+ buffer.putShort(size);
+ buffer.putRawData(value);
+ }
+}
- template <class T> void encode(T& t) { t.encode(buffer); }
+void encode(const Variant::Map& map, uint32_t len, qpid::framing::Buffer& buffer);
+void encode(const Variant::List& list, uint32_t len, qpid::framing::Buffer& buffer);
- void getData(std::string& s) {
- s.assign(data, buffer.getSize());
+void encode(const Variant& value, qpid::framing::Buffer& buffer)
+{
+ switch (value.getType()) {
+ case VAR_VOID:
+ buffer.putOctet(0xf0);
+ break;
+ case VAR_BOOL:
+ buffer.putOctet(0x08);
+ buffer.putOctet(value.asBool());
+ break;
+ case VAR_INT8:
+ buffer.putOctet(0x01);
+ buffer.putInt8(value.asInt8());
+ break;
+ case VAR_UINT8:
+ buffer.putOctet(0x02);
+ buffer.putOctet(value.asUint8());
+ break;
+ case VAR_INT16:
+ buffer.putOctet(0x11);
+ buffer.putInt16(value.asInt16());
+ break;
+ case VAR_UINT16:
+ buffer.putOctet(0x12);
+ buffer.putShort(value.asUint16());
+ break;
+ case VAR_INT32:
+ buffer.putOctet(0x21);
+ buffer.putInt32(value.asInt32());
+ break;
+ case VAR_UINT32:
+ buffer.putOctet(0x22);
+ buffer.putLong(value.asUint32());
+ break;
+ case VAR_FLOAT:
+ buffer.putOctet(0x23);
+ buffer.putFloat(value.asFloat());
+ break;
+ case VAR_INT64:
+ buffer.putOctet(0x31);
+ buffer.putInt64(value.asInt64());
+ break;
+ case VAR_UINT64:
+ buffer.putOctet(0x32);
+ buffer.putLongLong(value.asUint64());
+ break;
+ case VAR_DOUBLE:
+ buffer.putOctet(0x33);
+ buffer.putDouble(value.asDouble());
+ break;
+ case VAR_UUID:
+ buffer.putOctet(0x48);
+ buffer.putBin128(value.asUuid().data());
+ break;
+ case VAR_MAP:
+ buffer.putOctet(0xa8);
+ encode(value.asMap(), encodedSize(value.asMap()), buffer);
+ break;
+ case VAR_LIST:
+ buffer.putOctet(0xa9);
+ encode(value.asList(), encodedSize(value.asList()), buffer);
+ break;
+ case VAR_STRING:
+ encode(value.getString(), value.getEncoding(), buffer);
+ break;
}
-};
+}
-struct DecodeBuffer
+void encode(const Variant::Map& map, uint32_t len, qpid::framing::Buffer& buffer)
{
- Buffer buffer;
+ uint32_t s = buffer.getPosition();
+ buffer.putLong(len - 4);//exclusive of the size field itself
+ buffer.putLong(map.size());
+ for (Variant::Map::const_iterator i = map.begin(); i != map.end(); ++i) {
+ buffer.putShortString(i->first);
+ encode(i->second, buffer);
+ }
+ (void) s; assert(s + len == buffer.getPosition());
+}
- DecodeBuffer(const std::string& s) : buffer(const_cast<char*>(s.data()), s.size()) {}
+void encode(const Variant::Map& map, const std::string& efield, const Variant& evalue, uint32_t len, qpid::framing::Buffer& buffer)
+{
+ uint32_t s = buffer.getPosition();
+ buffer.putLong(len - 4);//exclusive of the size field itself
+ buffer.putLong(map.size() + 1 /* The extra field */ );
+ for (Variant::Map::const_iterator i = map.begin(); i != map.end(); ++i) {
+ buffer.putShortString(i->first);
+ encode(i->second, buffer);
+ }
+ buffer.putShortString(efield);
+ encode(evalue, buffer);
- template <class T> void decode(T& t) { t.decode(buffer); }
-
-};
+ (void) s; assert(s + len == buffer.getPosition());
+}
-template <class T, class U, class F> void _encode(const U& value, std::string& data, F f)
+void encode(const Variant::List& list, uint32_t len, qpid::framing::Buffer& buffer)
{
- T t;
- convert(value, t, f);
- EncodeBuffer buffer(t.encodedSize());
- buffer.encode(t);
- buffer.getData(data);
+ uint32_t s = buffer.getPosition();
+ buffer.putLong(len - 4);//exclusive of the size field itself
+ buffer.putLong(list.size());
+ for (Variant::List::const_iterator i = list.begin(); i != list.end(); ++i) {
+ encode(*i, buffer);
+ }
+ (void) s; assert(s + len == buffer.getPosition());
}
-template <class T, class U, class F> void _decode(const std::string& data, U& value, F f)
+void decode(qpid::framing::Buffer&, Variant::Map&)
{
- T t;
- DecodeBuffer buffer(data);
- buffer.decode(t);
- convert(t, value, f);
}
+
void MapCodec::encode(const Variant::Map& value, std::string& data)
{
- _encode<FieldTable>(value, data, &toFieldTableEntry);
+ uint32_t len = qpid::amqp_0_10::encodedSize(value);
+ std::vector<char> space(len);
+ qpid::framing::Buffer buff(&space[0], len);
+
+ qpid::amqp_0_10::encode(value, len, buff);
+ assert( len == buff.getPosition() );
+ data.assign(&space[0], len);
}
void MapCodec::decode(const std::string& data, Variant::Map& value)
@@ -309,14 +458,18 @@ void MapCodec::decode(const std::string& data, Variant::Map& value)
size_t MapCodec::encodedSize(const Variant::Map& value)
{
- std::string encoded;
- encode(value, encoded);
- return encoded.size();
+ return qpid::amqp_0_10::encodedSize(value);
}
void ListCodec::encode(const Variant::List& value, std::string& data)
{
- _encode<List>(value, data, &toFieldValue);
+ uint32_t len = qpid::amqp_0_10::encodedSize(value);
+ std::vector<char> space(len);
+ qpid::framing::Buffer buff(&space[0], len);
+
+ qpid::amqp_0_10::encode(value, len, buff);
+ assert( len == buff.getPosition() );
+ data.assign(&space[0], len);
}
void ListCodec::decode(const std::string& data, Variant::List& value)
@@ -326,14 +479,47 @@ void ListCodec::decode(const std::string& data, Variant::List& value)
size_t ListCodec::encodedSize(const Variant::List& value)
{
- std::string encoded;
- encode(value, encoded);
- return encoded.size();
+ return qpid::amqp_0_10::encodedSize(value);
}
void translate(const Variant::Map& from, FieldTable& to)
{
- convert(from, to, &toFieldTableEntry);
+ // Create buffer of correct size to encode Variant::Map
+ uint32_t len = encodedSize(from);
+ std::vector<char> space(len);
+ qpid::framing::Buffer buff(&space[0], len);
+
+ // Encode Variant::Map into buffer directly -
+ // We pass the already calculated length in to avoid
+ // recalculating it.
+ encode(from, len, buff);
+
+ // Give buffer to FieldTable
+ // Could speed this up a bit by avoiding copying
+ // the buffer we just created into the FieldTable
+ assert( len == buff.getPosition() );
+ buff.reset();
+ to.decode(buff);
+}
+
+void translate(const Variant::Map& from, const std::string& efield, const Variant& evalue, FieldTable& to)
+{
+ // Create buffer of correct size to encode Variant::Map
+ uint32_t len = encodedSize(from, efield, evalue);
+ std::vector<char> space(len);
+ qpid::framing::Buffer buff(&space[0], len);
+
+ // Encode Variant::Map into buffer directly -
+ // We pass the already calculated length in to avoid
+ // recalculating it.
+ encode(from, efield, evalue, len, buff);
+
+ // Give buffer to FieldTable
+ // Could speed this up a bit by avoiding copying
+ // the buffer we just created into the FieldTable
+ assert( len == buff.getPosition() );
+ buff.reset();
+ to.decode(buff);
}
void translate(const FieldTable& from, Variant::Map& to)
diff --git a/cpp/src/qpid/broker/AclModule.h b/cpp/src/qpid/broker/AclModule.h
index ff9281b6fc..7c180439cf 100644
--- a/cpp/src/qpid/broker/AclModule.h
+++ b/cpp/src/qpid/broker/AclModule.h
@@ -113,6 +113,7 @@ namespace acl {
namespace broker {
+ class Connection;
class AclModule
{
@@ -139,6 +140,11 @@ namespace broker {
// Add specialized authorise() methods as required.
+ /** Approve connection by counting connections total, per-IP, and
+ * per-user.
+ */
+ virtual bool approveConnection (const Connection& connection)=0;
+
virtual ~AclModule() {};
};
} // namespace broker
diff --git a/cpp/src/qpid/broker/Bridge.cpp b/cpp/src/qpid/broker/Bridge.cpp
index 5b531e4636..d1706b5907 100644
--- a/cpp/src/qpid/broker/Bridge.cpp
+++ b/cpp/src/qpid/broker/Bridge.cpp
@@ -57,22 +57,25 @@ void Bridge::PushHandler::handle(framing::AMQFrame& frame)
conn->received(frame);
}
-Bridge::Bridge(Link* _link, framing::ChannelId _id, CancellationListener l,
- const _qmf::ArgsLinkBridge& _args,
- InitializeCallback init) :
- link(_link), id(_id), args(_args), mgmtObject(0),
- listener(l), name(Uuid(true).str()), queueName("qpid.bridge_queue_"), persistenceId(0),
- initialize(init), detached(false)
+Bridge::Bridge(const std::string& _name, Link* _link, framing::ChannelId _id,
+ CancellationListener l, const _qmf::ArgsLinkBridge& _args,
+ InitializeCallback init, const std::string& _queueName, const string& ae) :
+ link(_link), channel(_id), args(_args), mgmtObject(0),
+ listener(l), name(_name),
+ queueName(_queueName.empty() ? "qpid.bridge_queue_" + name + "_" + link->getBroker()->getFederationTag()
+ : _queueName),
+ altEx(ae), persistenceId(0),
+ connState(0), conn(0), initialize(init), detached(false),
+ useExistingQueue(!_queueName.empty()),
+ sessionName("qpid.bridge_session_" + name + "_" + link->getBroker()->getFederationTag())
{
- std::stringstream title;
- title << id << "_" << name;
- queueName += title.str();
ManagementAgent* agent = link->getBroker()->getManagementAgent();
if (agent != 0) {
mgmtObject = new _qmf::Bridge
- (agent, this, link, id, args.i_durable, args.i_src, args.i_dest,
+ (agent, this, link, name, args.i_durable, args.i_src, args.i_dest,
args.i_key, args.i_srcIsQueue, args.i_srcIsLocal,
args.i_tag, args.i_excludes, args.i_dynamic, args.i_sync);
+ mgmtObject->set_channelId(channel);
agent->addObject(mgmtObject);
}
QPID_LOG(debug, "Bridge " << name << " created from " << args.i_src << " to " << args.i_dest);
@@ -90,23 +93,22 @@ void Bridge::create(Connection& c)
conn = &c;
FieldTable options;
if (args.i_sync) options.setInt("qpid.sync_frequency", args.i_sync);
- SessionHandler& sessionHandler = c.getChannel(id);
- sessionHandler.setDetachedCallback(
- boost::bind(&Bridge::sessionDetached, shared_from_this()));
+ SessionHandler& sessionHandler = c.getChannel(channel);
+ sessionHandler.setErrorListener(shared_from_this());
if (args.i_srcIsLocal) {
if (args.i_dynamic)
throw Exception("Dynamic routing not supported for push routes");
// Point the bridging commands at the local connection handler
pushHandler.reset(new PushHandler(&c));
- channelHandler.reset(new framing::ChannelHandler(id, pushHandler.get()));
+ channelHandler.reset(new framing::ChannelHandler(channel, pushHandler.get()));
session.reset(new framing::AMQP_ServerProxy::Session(*channelHandler));
peer.reset(new framing::AMQP_ServerProxy(*channelHandler));
- session->attach(name, false);
+ session->attach(sessionName, false);
session->commandPoint(0,0);
} else {
- sessionHandler.attachAs(name);
+ sessionHandler.attachAs(sessionName);
// Point the bridging commands at the remote peer broker
peer.reset(new framing::AMQP_ServerProxy(sessionHandler.out));
}
@@ -115,7 +117,7 @@ void Bridge::create(Connection& c)
if (initialize) initialize(*this, sessionHandler);
else if (args.i_srcIsQueue) {
peer->getMessage().subscribe(args.i_src, args.i_dest, args.i_sync ? 0 : 1, 0, false, "", 0, options);
- peer->getMessage().flow(args.i_dest, 0, 0xFFFFFFFF);
+ peer->getMessage().flow(args.i_dest, 0, args.i_sync ? 2 * args.i_sync : 0xFFFFFFFF);
peer->getMessage().flow(args.i_dest, 1, 0xFFFFFFFF);
QPID_LOG(debug, "Activated bridge " << name << " for route from queue " << args.i_src << " to " << args.i_dest);
} else {
@@ -138,12 +140,13 @@ void Bridge::create(Connection& c)
}
bool durable = false;//should this be an arg, or would we use srcIsQueue for durable queues?
- bool autoDelete = !durable;//auto delete transient queues?
- peer->getQueue().declare(queueName, "", false, durable, true, autoDelete, queueSettings);
+ bool exclusive = !useExistingQueue; // only exclusive if the queue is owned by the bridge
+ bool autoDelete = exclusive && !durable;//auto delete transient queues?
+ peer->getQueue().declare(queueName, altEx, false, durable, exclusive, autoDelete, queueSettings);
if (!args.i_dynamic)
peer->getExchange().bind(queueName, args.i_src, args.i_key, FieldTable());
- peer->getMessage().subscribe(queueName, args.i_dest, 1, 0, false, "", 0, FieldTable());
- peer->getMessage().flow(args.i_dest, 0, 0xFFFFFFFF);
+ peer->getMessage().subscribe(queueName, args.i_dest, (useExistingQueue && args.i_sync) ? 0 : 1, 0, false, "", 0, options);
+ peer->getMessage().flow(args.i_dest, 0, (useExistingQueue && args.i_sync) ? 2 * args.i_sync : 0xFFFFFFFF);
peer->getMessage().flow(args.i_dest, 1, 0xFFFFFFFF);
if (args.i_dynamic) {
@@ -163,11 +166,12 @@ void Bridge::cancel(Connection&)
{
if (resetProxy()) {
peer->getMessage().cancel(args.i_dest);
- peer->getSession().detach(name);
+ peer->getSession().detach(sessionName);
}
QPID_LOG(debug, "Cancelled bridge " << name);
}
+/** Notify the bridge that the connection has closed */
void Bridge::closed()
{
if (args.i_dynamic) {
@@ -177,9 +181,10 @@ void Bridge::closed()
QPID_LOG(debug, "Closed bridge " << name);
}
-void Bridge::destroy()
+/** Shut down the bridge */
+void Bridge::close()
{
- listener(this);
+ listener(this); // ask the LinkRegistry to destroy us
}
void Bridge::setPersistenceId(uint64_t pId) const
@@ -187,8 +192,21 @@ void Bridge::setPersistenceId(uint64_t pId) const
persistenceId = pId;
}
+
+const std::string Bridge::ENCODED_IDENTIFIER("bridge.v2");
+const std::string Bridge::ENCODED_IDENTIFIER_V1("bridge");
+
+bool Bridge::isEncodedBridge(const std::string& key)
+{
+ return key == ENCODED_IDENTIFIER || key == ENCODED_IDENTIFIER_V1;
+}
+
+
Bridge::shared_ptr Bridge::decode(LinkRegistry& links, Buffer& buffer)
{
+ string kind;
+ buffer.getShortString(kind);
+
string host;
uint16_t port;
string src;
@@ -196,9 +214,33 @@ Bridge::shared_ptr Bridge::decode(LinkRegistry& links, Buffer& buffer)
string key;
string id;
string excludes;
+ string name;
+
+ Link::shared_ptr link;
+ if (kind == ENCODED_IDENTIFIER_V1) {
+ /** previous versions identified the bridge by host:port, not by name, and
+ * transport wasn't provided. Try to find a link using those paramters.
+ */
+ buffer.getShortString(host);
+ port = buffer.getShort();
+
+ link = links.getLink(host, port);
+ if (!link) {
+ QPID_LOG(error, "Bridge::decode() failed: cannot find Link for host=" << host << ", port=" << port);
+ return Bridge::shared_ptr();
+ }
+ } else {
+ string linkName;
+
+ buffer.getShortString(name);
+ buffer.getShortString(linkName);
+ link = links.getLink(linkName);
+ if (!link) {
+ QPID_LOG(error, "Bridge::decode() failed: cannot find Link named='" << linkName << "'");
+ return Bridge::shared_ptr();
+ }
+ }
- buffer.getShortString(host);
- port = buffer.getShort();
bool durable(buffer.getOctet());
buffer.getShortString(src);
buffer.getShortString(dest);
@@ -210,15 +252,21 @@ Bridge::shared_ptr Bridge::decode(LinkRegistry& links, Buffer& buffer)
bool dynamic(buffer.getOctet());
uint16_t sync = buffer.getShort();
- return links.declare(host, port, durable, src, dest, key,
- is_queue, is_local, id, excludes, dynamic, sync).first;
+ if (kind == ENCODED_IDENTIFIER_V1) {
+ /** previous versions did not provide a name for the bridge, so create one
+ */
+ name = createName(link->getName(), src, dest, key);
+ }
+
+ return links.declare(name, *link, durable, src, dest, key, is_queue,
+ is_local, id, excludes, dynamic, sync).first;
}
void Bridge::encode(Buffer& buffer) const
{
- buffer.putShortString(string("bridge"));
- buffer.putShortString(link->getHost());
- buffer.putShort(link->getPort());
+ buffer.putShortString(ENCODED_IDENTIFIER);
+ buffer.putShortString(name);
+ buffer.putShortString(link->getName());
buffer.putOctet(args.i_durable ? 1 : 0);
buffer.putShortString(args.i_src);
buffer.putShortString(args.i_dest);
@@ -233,9 +281,9 @@ void Bridge::encode(Buffer& buffer) const
uint32_t Bridge::encodedSize() const
{
- return link->getHost().size() + 1 // short-string (host)
- + 7 // short-string ("bridge")
- + 2 // port
+ return ENCODED_IDENTIFIER.size() + 1 // +1 byte length
+ + name.size() + 1
+ + link->getName().size() + 1
+ 1 // durable
+ args.i_src.size() + 1
+ args.i_dest.size() + 1
@@ -259,7 +307,8 @@ management::Manageable::status_t Bridge::ManagementMethod(uint32_t methodId,
{
if (methodId == _qmf::Bridge::METHOD_CLOSE) {
//notify that we are closed
- destroy();
+ QPID_LOG(debug, "Bridge::close() method called on bridge '" << name << "'");
+ close();
return management::Manageable::STATUS_OK;
} else {
return management::Manageable::STATUS_UNKNOWN_METHOD;
@@ -306,7 +355,7 @@ void Bridge::sendReorigin()
}
bool Bridge::resetProxy()
{
- SessionHandler& sessionHandler = conn->getChannel(id);
+ SessionHandler& sessionHandler = conn->getChannel(channel);
if (!sessionHandler.getSession()) peer.reset();
else peer.reset(new framing::AMQP_ServerProxy(sessionHandler.out));
return peer.get();
@@ -318,7 +367,7 @@ void Bridge::ioThreadPropagateBinding(const string& queue, const string& exchang
peer->getExchange().bind(queue, exchange, key, args);
} else {
QPID_LOG(error, "Cannot propagate binding for dynamic bridge as session has been detached, deleting dynamic bridge");
- destroy();
+ close();
}
}
@@ -333,8 +382,38 @@ const string& Bridge::getLocalTag() const
return link->getBroker()->getFederationTag();
}
-void Bridge::sessionDetached() {
+// SessionHandler::ErrorListener methods.
+void Bridge::connectionException(
+ framing::connection::CloseCode code, const std::string& msg)
+{
+ if (errorListener) errorListener->connectionException(code, msg);
+}
+
+void Bridge::channelException(
+ framing::session::DetachCode code, const std::string& msg)
+{
+ if (errorListener) errorListener->channelException(code, msg);
+}
+
+void Bridge::executionException(
+ framing::execution::ErrorCode code, const std::string& msg)
+{
+ if (errorListener) errorListener->executionException(code, msg);
+}
+
+void Bridge::detach() {
detached = true;
+ if (errorListener) errorListener->detach();
+}
+
+std::string Bridge::createName(const std::string& linkName,
+ const std::string& src,
+ const std::string& dest,
+ const std::string& key)
+{
+ std::stringstream keystream;
+ keystream << linkName << "!" << src << "!" << dest << "!" << key;
+ return keystream.str();
}
}}
diff --git a/cpp/src/qpid/broker/Bridge.h b/cpp/src/qpid/broker/Bridge.h
index 32b9fd1781..ee298afd45 100644
--- a/cpp/src/qpid/broker/Bridge.h
+++ b/cpp/src/qpid/broker/Bridge.h
@@ -29,6 +29,7 @@
#include "qpid/framing/FieldTable.h"
#include "qpid/management/Manageable.h"
#include "qpid/broker/Exchange.h"
+#include "qpid/broker/SessionHandler.h"
#include "qmf/org/apache/qpid/broker/ArgsLinkBridge.h"
#include "qmf/org/apache/qpid/broker/Bridge.h"
@@ -43,29 +44,31 @@ class Connection;
class ConnectionState;
class Link;
class LinkRegistry;
-class SessionHandler;
class Bridge : public PersistableConfig,
public management::Manageable,
public Exchange::DynamicBridge,
+ public SessionHandler::ErrorListener,
public boost::enable_shared_from_this<Bridge>
{
-public:
+ public:
typedef boost::shared_ptr<Bridge> shared_ptr;
typedef boost::function<void(Bridge*)> CancellationListener;
typedef boost::function<void(Bridge&, SessionHandler&)> InitializeCallback;
- Bridge(Link* link, framing::ChannelId id, CancellationListener l,
+ Bridge(const std::string& name, Link* link, framing::ChannelId id, CancellationListener l,
const qmf::org::apache::qpid::broker::ArgsLinkBridge& args,
- InitializeCallback init
+ InitializeCallback init, const std::string& queueName="",
+ const std::string& altExchange=""
);
~Bridge();
- void create(Connection& c);
- void cancel(Connection& c);
- void closed();
- void destroy();
+ QPID_BROKER_EXTERN void close();
bool isDurable() { return args.i_durable; }
+ Link *getLink() const { return link; }
+ const std::string getSrc() const { return args.i_src; }
+ const std::string getDest() const { return args.i_dest; }
+ const std::string getKey() const { return args.i_key; }
bool isDetached() const { return detached; }
@@ -80,7 +83,11 @@ public:
uint32_t encodedSize() const;
void encode(framing::Buffer& buffer) const;
const std::string& getName() const { return name; }
+
+ static const std::string ENCODED_IDENTIFIER;
+ static const std::string ENCODED_IDENTIFIER_V1;
static Bridge::shared_ptr decode(LinkRegistry& links, framing::Buffer& buffer);
+ static bool isEncodedBridge(const std::string& key);
// Exchange::DynamicBridge methods
void propagateBinding(const std::string& key, const std::string& tagList, const std::string& op, const std::string& origin, qpid::framing::FieldTable* extra_args=0);
@@ -93,10 +100,20 @@ public:
std::string getQueueName() const { return queueName; }
const qmf::org::apache::qpid::broker::ArgsLinkBridge& getArgs() { return args; }
-private:
- // Callback when the bridge's session is detached.
- void sessionDetached();
+ /** create a name for a bridge (if none supplied by user config) */
+ static std::string createName(const std::string& linkName,
+ const std::string& src,
+ const std::string& dest,
+ const std::string& key);
+
+ // SessionHandler::ErrorListener methods.
+ void connectionException(framing::connection::CloseCode code, const std::string& msg);
+ void channelException(framing::session::DetachCode, const std::string& msg);
+ void executionException(framing::execution::ErrorCode, const std::string& msg);
+ void detach();
+ void setErrorListener(boost::shared_ptr<ErrorListener> e) { errorListener = e; }
+ private:
struct PushHandler : framing::FrameHandler {
PushHandler(Connection* c) { conn = c; }
void handle(framing::AMQFrame& frame);
@@ -108,19 +125,30 @@ private:
std::auto_ptr<framing::AMQP_ServerProxy::Session> session;
std::auto_ptr<framing::AMQP_ServerProxy> peer;
- Link* link;
- framing::ChannelId id;
+ Link* const link;
+ const framing::ChannelId channel;
qmf::org::apache::qpid::broker::ArgsLinkBridge args;
qmf::org::apache::qpid::broker::Bridge* mgmtObject;
CancellationListener listener;
std::string name;
std::string queueName;
+ std::string altEx;
mutable uint64_t persistenceId;
ConnectionState* connState;
Connection* conn;
InitializeCallback initialize;
bool detached; // Set when session is detached.
bool resetProxy();
+
+ // connection Management (called by owning Link)
+ void create(Connection& c);
+ void cancel(Connection& c);
+ void closed();
+ friend class Link; // to call create, cancel, closed()
+ boost::shared_ptr<ErrorListener> errorListener;
+
+ const bool useExistingQueue;
+ const std::string sessionName;
};
diff --git a/cpp/src/qpid/broker/Broker.cpp b/cpp/src/qpid/broker/Broker.cpp
index f20cce18a2..b763dd4119 100644
--- a/cpp/src/qpid/broker/Broker.cpp
+++ b/cpp/src/qpid/broker/Broker.cpp
@@ -108,7 +108,6 @@ Broker::Options::Options(const std::string& name) :
noDataDir(0),
port(DEFAULT_PORT),
workerThreads(5),
- maxConnections(500),
connectionBacklog(10),
enableMgmt(1),
mgmtPublish(1),
@@ -128,8 +127,10 @@ Broker::Options::Options(const std::string& name) :
queueFlowResumeRatio(70),
queueThresholdEventRatio(80),
defaultMsgGroup("qpid.no-group"),
- timestampRcvMsgs(false), // set the 0.10 timestamp delivery property
- linkMaintenanceInterval(2)
+ timestampRcvMsgs(false), // set the 0.10 timestamp delivery property
+ linkMaintenanceInterval(2),
+ linkHeartbeatInterval(120),
+ maxNegotiateTime(2000) // 2s
{
int c = sys::SystemInfo::concurrency();
workerThreads=c+1;
@@ -146,7 +147,6 @@ Broker::Options::Options(const std::string& name) :
("no-data-dir", optValue(noDataDir), "Don't use a data directory. No persistent configuration will be loaded or stored")
("port,p", optValue(port,"PORT"), "Tells the broker to listen on PORT")
("worker-threads", optValue(workerThreads, "N"), "Sets the broker thread pool size")
- ("max-connections", optValue(maxConnections, "N"), "Sets the maximum allowed connections")
("connection-backlog", optValue(connectionBacklog, "N"), "Sets the connection backlog limit for the server socket")
("mgmt-enable,m", optValue(enableMgmt,"yes|no"), "Enable Management")
("mgmt-publish", optValue(mgmtPublish,"yes|no"), "Enable Publish of Management Data ('no' implies query-only)")
@@ -171,6 +171,9 @@ Broker::Options::Options(const std::string& name) :
("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.")
("link-maintenace-interval", optValue(linkMaintenanceInterval, "SECONDS"))
+ ("link-heartbeat-interval", optValue(linkHeartbeatInterval, "SECONDS"))
+ ("max-negotiate-time", optValue(maxNegotiateTime, "MilliSeconds"), "Maximum time a connection can take to send the initial protocol negotiation")
+ ("federation-tag", optValue(fedTag, "NAME"), "Override the federation tag")
;
}
@@ -208,7 +211,6 @@ Broker::Broker(const Broker::Options& conf) :
inCluster(false),
clusterUpdatee(false),
expiryPolicy(new ExpiryPolicy),
- connectionCounter(conf.maxConnections),
getKnownBrokers(boost::bind(&Broker::getKnownBrokersImpl, this)),
deferDelivery(boost::bind(&Broker::deferDeliveryImpl, this, _1, _2))
{
@@ -227,7 +229,6 @@ Broker::Broker(const Broker::Options& conf) :
mgmtObject->set_systemRef(system->GetManagementObject()->getObjectId());
mgmtObject->set_port(conf.port);
mgmtObject->set_workerThreads(conf.workerThreads);
- mgmtObject->set_maxConns(conf.maxConnections);
mgmtObject->set_connBacklog(conf.connectionBacklog);
mgmtObject->set_mgmtPubInterval(conf.mgmtPubInterval);
mgmtObject->set_mgmtPublish(conf.mgmtPublish);
@@ -244,8 +245,11 @@ Broker::Broker(const Broker::Options& conf) :
// management schema correct.
Vhost* vhost = new Vhost(this, this);
vhostObject = Vhost::shared_ptr(vhost);
- framing::Uuid uuid(managementAgent->getUuid());
- federationTag = uuid.str();
+ if (conf.fedTag.empty()) {
+ framing::Uuid uuid(managementAgent->getUuid());
+ federationTag = uuid.str();
+ } else
+ federationTag = conf.fedTag;
vhostObject->setFederationTag(federationTag);
queues.setParent(vhost);
@@ -254,8 +258,11 @@ Broker::Broker(const Broker::Options& conf) :
} else {
// Management is disabled so there is no broker management ID.
// Create a unique uuid to use as the federation tag.
- framing::Uuid uuid(true);
- federationTag = uuid.str();
+ if (conf.fedTag.empty()) {
+ framing::Uuid uuid(true);
+ federationTag = uuid.str();
+ } else
+ federationTag = conf.fedTag;
}
QueuePolicy::setDefaultMaxSize(conf.queueLimit);
@@ -346,7 +353,7 @@ Broker::Broker(const Broker::Options& conf) :
knownBrokers.push_back(Url(conf.knownHosts));
}
- } catch (const std::exception& /*e*/) {
+ } catch (const std::exception&) {
finalize();
throw;
}
@@ -443,7 +450,7 @@ Manageable* Broker::GetVhostObject(void) const
Manageable::status_t Broker::ManagementMethod (uint32_t methodId,
Args& args,
- string&)
+ string& text)
{
Manageable::status_t status = Manageable::STATUS_UNKNOWN_METHOD;
@@ -458,6 +465,14 @@ Manageable::status_t Broker::ManagementMethod (uint32_t methodId,
status = Manageable::STATUS_OK;
break;
case _qmf::Broker::METHOD_CONNECT : {
+ /** Management is creating a Link to a remote broker using the host and port of
+ * the remote. This (old) interface does not allow management to specify a name
+ * for the link, nor does it allow multiple Links to the same remote. Use the
+ * "create()" broker method if these features are needed.
+ * TBD: deprecate this interface.
+ */
+ QPID_LOG(info, "The Broker::connect() method will be removed in a future release of QPID."
+ " Please use the Broker::create() method with type='link' instead.");
_qmf::ArgsBrokerConnect& hp=
dynamic_cast<_qmf::ArgsBrokerConnect&>(args);
@@ -466,13 +481,24 @@ Manageable::status_t Broker::ManagementMethod (uint32_t methodId,
"; durable=" << (hp.i_durable?"T":"F") << "; authMech=\"" << hp.i_authMechanism << "\"");
if (!getProtocolFactory(transport)) {
QPID_LOG(error, "Transport '" << transport << "' not supported");
+ text = "transport type not supported";
return Manageable::STATUS_NOT_IMPLEMENTED;
}
- std::pair<Link::shared_ptr, bool> response =
- links.declare (hp.i_host, hp.i_port, transport, hp.i_durable,
- hp.i_authMechanism, hp.i_username, hp.i_password);
- if (hp.i_durable && response.second)
- store->create(*response.first);
+
+ // Does a link to the remote already exist? If so, re-use the existing link
+ // - this behavior is backward compatible with previous releases.
+ if (!links.getLink(hp.i_host, hp.i_port, transport)) {
+ // new link, need to generate a unique name for it
+ std::pair<Link::shared_ptr, bool> response =
+ links.declare(Link::createName(transport, hp.i_host, hp.i_port),
+ hp.i_host, hp.i_port, transport,
+ hp.i_durable, hp.i_authMechanism, hp.i_username, hp.i_password);
+ if (!response.first) {
+ text = "Unable to create Link";
+ status = Manageable::STATUS_PARAMETER_INVALID;
+ break;
+ }
+ }
status = Manageable::STATUS_OK;
break;
}
@@ -543,6 +569,8 @@ 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 TYPE_LINK("link");
+const std::string TYPE_BRIDGE("bridge");
const std::string DURABLE("durable");
const std::string AUTO_DELETE("auto-delete");
const std::string ALTERNATE_EXCHANGE("alternate-exchange");
@@ -554,6 +582,26 @@ const std::string ATTRIBUTE_TIMESTAMP_0_10("timestamp-0.10");
const std::string _TRUE("true");
const std::string _FALSE("false");
+
+// parameters for creating a Link object, see mgmt schema
+const std::string HOST("host");
+const std::string PORT("port");
+const std::string TRANSPORT("transport");
+const std::string AUTH_MECHANISM("authMechanism");
+const std::string USERNAME("username");
+const std::string PASSWORD("password");
+
+// parameters for creating a Bridge object, see mgmt schema
+const std::string LINK("link");
+const std::string SRC("src");
+const std::string DEST("dest");
+const std::string KEY("key");
+const std::string TAG("tag");
+const std::string EXCLUDES("excludes");
+const std::string SRC_IS_QUEUE("srcIsQueue");
+const std::string SRC_IS_LOCAL("srcIsLocal");
+const std::string DYNAMIC("dynamic");
+const std::string SYNC("sync");
}
struct InvalidBindingIdentifier : public qpid::Exception
@@ -603,6 +651,25 @@ struct UnknownObjectType : public qpid::Exception
std::string getPrefix() const { return "unknown object type"; }
};
+struct ReservedObjectName : public qpid::Exception
+{
+ ReservedObjectName(const std::string& type) : qpid::Exception(type) {}
+ std::string getPrefix() const { return std::string("names prefixed with '")
+ + QPID_NAME_PREFIX + std::string("' are reserved"); }
+};
+
+struct UnsupportedTransport : public qpid::Exception
+{
+ UnsupportedTransport(const std::string& type) : qpid::Exception(type) {}
+ std::string getPrefix() const { return "transport is not supported"; }
+};
+
+struct InvalidParameter : public qpid::Exception
+{
+ InvalidParameter(const std::string& type) : qpid::Exception(type) {}
+ std::string getPrefix() const { return "invalid parameter to method call"; }
+};
+
void Broker::createObject(const std::string& type, const std::string& name,
const Variant::Map& properties, bool /*strict*/, const ConnectionState* context)
{
@@ -674,6 +741,113 @@ void Broker::createObject(const std::string& type, const std::string& name,
amqp_0_10::translate(extensions, arguments);
bind(binding.queue, binding.exchange, binding.key, arguments, userId, connectionId);
+
+ } else if (type == TYPE_LINK) {
+
+ QPID_LOG (debug, "createObject: Link; name=" << name << "; args=" << properties );
+
+ if (name.compare(0, QPID_NAME_PREFIX.length(), QPID_NAME_PREFIX) == 0) {
+ QPID_LOG(error, "Link name='" << name << "' cannot use the reserved prefix '" << QPID_NAME_PREFIX << "'");
+ throw ReservedObjectName(name);
+ }
+
+ std::string host;
+ uint16_t port = 0;
+ std::string transport = TCP_TRANSPORT;
+ bool durable = false;
+ std::string authMech, username, password;
+
+ for (Variant::Map::const_iterator i = properties.begin(); i != properties.end(); ++i) {
+ if (i->first == HOST) host = i->second.asString();
+ else if (i->first == PORT) port = i->second.asUint16();
+ else if (i->first == TRANSPORT) transport = i->second.asString();
+ else if (i->first == DURABLE) durable = bool(i->second);
+ else if (i->first == AUTH_MECHANISM) authMech = i->second.asString();
+ else if (i->first == USERNAME) username = i->second.asString();
+ else if (i->first == PASSWORD) password = i->second.asString();
+ else {
+ // TODO: strict checking here
+ }
+ }
+
+ if (!getProtocolFactory(transport)) {
+ QPID_LOG(error, "Transport '" << transport << "' not supported.");
+ throw UnsupportedTransport(transport);
+ }
+
+ std::pair<boost::shared_ptr<Link>, bool> rc;
+ rc = links.declare(name, host, port, transport, durable, authMech, username, password);
+ if (!rc.first) {
+ QPID_LOG (error, "Failed to create Link object, name=" << name << " remote=" << host << ":" << port <<
+ "; transport=" << transport << "; durable=" << (durable?"T":"F") << "; authMech=\"" << authMech << "\"");
+ throw InvalidParameter(name);
+ }
+ if (!rc.second) {
+ QPID_LOG (error, "Failed to create a new Link object, name=" << name << " already exists.");
+ throw ObjectAlreadyExists(name);
+ }
+
+ } else if (type == TYPE_BRIDGE) {
+
+ QPID_LOG (debug, "createObject: Bridge; name=" << name << "; args=" << properties );
+
+ if (name.compare(0, QPID_NAME_PREFIX.length(), QPID_NAME_PREFIX) == 0) {
+ QPID_LOG(error, "Bridge name='" << name << "' cannot use the reserved prefix '" << QPID_NAME_PREFIX << "'");
+ throw ReservedObjectName(name);
+ }
+
+ std::string linkName;
+ std::string src;
+ std::string dest;
+ std::string key;
+ std::string id;
+ std::string excludes;
+ std::string queueName;
+ bool durable = false;
+ bool srcIsQueue = false;
+ bool srcIsLocal = false;
+ bool dynamic = false;
+ uint16_t sync = 0;
+
+ for (Variant::Map::const_iterator i = properties.begin(); i != properties.end(); ++i) {
+
+ if (i->first == LINK) linkName = i->second.asString();
+ else if (i->first == SRC) src = i->second.asString();
+ else if (i->first == DEST) dest = i->second.asString();
+ else if (i->first == KEY) key = i->second.asString();
+ else if (i->first == TAG) id = i->second.asString();
+ else if (i->first == EXCLUDES) excludes = i->second.asString();
+ else if (i->first == SRC_IS_QUEUE) srcIsQueue = bool(i->second);
+ else if (i->first == SRC_IS_LOCAL) srcIsLocal = bool(i->second);
+ else if (i->first == DYNAMIC) dynamic = bool(i->second);
+ else if (i->first == SYNC) sync = i->second.asUint16();
+ else if (i->first == DURABLE) durable = bool(i->second);
+ else if (i->first == QUEUE_NAME) queueName = i->second.asString();
+ else {
+ // TODO: strict checking here
+ }
+ }
+
+ boost::shared_ptr<Link> link;
+ if (linkName.empty() || !(link = links.getLink(linkName))) {
+ QPID_LOG(error, "Link '" << linkName << "' not found; bridge create failed.");
+ throw InvalidParameter(name);
+ }
+ std::pair<Bridge::shared_ptr, bool> rc =
+ links.declare(name, *link, durable, src, dest, key, srcIsQueue, srcIsLocal, id, excludes,
+ dynamic, sync,
+ 0,
+ queueName);
+
+ if (!rc.first) {
+ QPID_LOG (error, "Failed to create Bridge object, name=" << name << " link=" << linkName <<
+ "; src=" << src << "; dest=" << dest << "; key=" << key);
+ throw InvalidParameter(name);
+ }
+ if (!rc.second) {
+ QPID_LOG (error, "Failed to create a new Bridge object, name=" << name << " already exists.");
+ throw ObjectAlreadyExists(name);
+ }
} else {
throw UnknownObjectType(type);
}
@@ -696,6 +870,16 @@ void Broker::deleteObject(const std::string& type, const std::string& name,
} else if (type == TYPE_BINDING) {
BindingIdentifier binding(name);
unbind(binding.queue, binding.exchange, binding.key, userId, connectionId);
+ } else if (type == TYPE_LINK) {
+ boost::shared_ptr<Link> link = links.getLink(name);
+ if (link) {
+ link->close();
+ }
+ } else if (type == TYPE_BRIDGE) {
+ boost::shared_ptr<Bridge> bridge = links.getBridge(name);
+ if (bridge) {
+ bridge->close();
+ }
} else {
throw UnknownObjectType(type);
}
@@ -920,6 +1104,13 @@ std::pair<boost::shared_ptr<Queue>, bool> Broker::createQueue(
ManagementAgent::toMap(arguments),
"created"));
}
+ QPID_LOG_CAT(debug, model, "Create queue. name:" << name
+ << " user:" << userId
+ << " rhost:" << connectionId
+ << " durable:" << (durable ? "T" : "F")
+ << " owner:" << owner
+ << " autodelete:" << (autodelete ? "T" : "F")
+ << " alternateExchange:" << alternateExchange );
}
return result;
}
@@ -942,6 +1133,10 @@ void Broker::deleteQueue(const std::string& name, const std::string& userId,
if (managementAgent.get())
managementAgent->raiseEvent(_qmf::EventQueueDelete(connectionId, userId, name));
+ QPID_LOG_CAT(debug, model, "Delete queue. name:" << name
+ << " user:" << userId
+ << " rhost:" << connectionId
+ );
}
@@ -993,6 +1188,12 @@ std::pair<Exchange::shared_ptr, bool> Broker::createExchange(
ManagementAgent::toMap(arguments),
"created"));
}
+ QPID_LOG_CAT(debug, model, "Create exchange. name:" << name
+ << " user:" << userId
+ << " rhost:" << connectionId
+ << " type:" << type
+ << " alternateExchange:" << alternateExchange
+ << " durable:" << (durable ? "T" : "F"));
}
return result;
}
@@ -1017,7 +1218,9 @@ void Broker::deleteExchange(const std::string& name, const std::string& userId,
if (managementAgent.get())
managementAgent->raiseEvent(_qmf::EventExchangeDelete(connectionId, userId, name));
-
+ QPID_LOG_CAT(debug, model, "Delete exchange. name:" << name
+ << " user:" << userId
+ << " rhost:" << connectionId);
}
void Broker::bind(const std::string& queueName,
@@ -1047,10 +1250,16 @@ void Broker::bind(const std::string& queueName,
throw framing::NotFoundException(QPID_MSG("Bind failed. No such exchange: " << exchangeName));
} else {
if (queue->bind(exchange, key, arguments)) {
+ getConfigurationObservers().bind(exchange, queue, key, arguments);
if (managementAgent.get()) {
managementAgent->raiseEvent(_qmf::EventBind(connectionId, userId, exchangeName,
queueName, key, ManagementAgent::toMap(arguments)));
}
+ QPID_LOG_CAT(debug, model, "Create binding. exchange:" << exchangeName
+ << " queue:" << queueName
+ << " key:" << key
+ << " user:" << userId
+ << " rhost:" << connectionId);
}
}
}
@@ -1082,12 +1291,33 @@ void Broker::unbind(const std::string& queueName,
if (exchange->isDurable() && queue->isDurable()) {
store->unbind(*exchange, *queue, key, qpid::framing::FieldTable());
}
+ getConfigurationObservers().unbind(
+ exchange, queue, key, framing::FieldTable());
if (managementAgent.get()) {
managementAgent->raiseEvent(_qmf::EventUnbind(connectionId, userId, exchangeName, queueName, key));
}
+ QPID_LOG_CAT(debug, model, "Delete binding. exchange:" << exchangeName
+ << " queue:" << queueName
+ << " key:" << key
+ << " user:" << userId
+ << " rhost:" << connectionId);
}
}
}
+// FIXME aconway 2012-04-27: access to linkClientProperties is
+// not properly thread safe, you could lose fields if 2 threads
+// attempt to add a field concurrently.
+
+framing::FieldTable Broker::getLinkClientProperties() const {
+ sys::Mutex::ScopedLock l(linkClientPropertiesLock);
+ return linkClientProperties;
+}
+
+void Broker::setLinkClientProperties(const framing::FieldTable& ft) {
+ sys::Mutex::ScopedLock l(linkClientPropertiesLock);
+ linkClientProperties = ft;
+}
+
}} // namespace qpid::broker
diff --git a/cpp/src/qpid/broker/Broker.h b/cpp/src/qpid/broker/Broker.h
index 135b9340f9..922d0558e5 100644
--- a/cpp/src/qpid/broker/Broker.h
+++ b/cpp/src/qpid/broker/Broker.h
@@ -40,6 +40,7 @@
#include "qpid/broker/ExpiryPolicy.h"
#include "qpid/broker/ConsumerFactory.h"
#include "qpid/broker/ConnectionObservers.h"
+#include "qpid/broker/ConfigurationObservers.h"
#include "qpid/management/Manageable.h"
#include "qpid/management/ManagementAgent.h"
#include "qmf/org/apache/qpid/broker/Broker.h"
@@ -64,8 +65,8 @@
namespace qpid {
namespace sys {
- class ProtocolFactory;
- class Poller;
+class ProtocolFactory;
+class Poller;
}
struct Url;
@@ -91,7 +92,7 @@ class Broker : public sys::Runnable, public Plugin::Target,
public management::Manageable,
public RefCounted
{
-public:
+ public:
struct Options : public qpid::Options {
static const std::string DEFAULT_DATA_DIR_LOCATION;
@@ -103,7 +104,6 @@ public:
std::string dataDir;
uint16_t port;
int workerThreads;
- int maxConnections;
int connectionBacklog;
bool enableMgmt;
bool mgmtPublish;
@@ -127,31 +127,14 @@ public:
std::string defaultMsgGroup;
bool timestampRcvMsgs;
double linkMaintenanceInterval; // FIXME aconway 2012-02-13: consistent parsing of SECONDS values.
+ uint16_t linkHeartbeatInterval;
+ uint32_t maxNegotiateTime; // Max time in ms for connection with no negotiation
+ std::string fedTag;
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);
- connectionCount++;
- }
- void dec_connectionCount() {
- sys::ScopedLock<sys::Mutex> l(connectionCountLock);
- connectionCount--;
- }
- bool allowConnection() {
- sys::ScopedLock<sys::Mutex> l(connectionCountLock);
- return (maxConnections <= connectionCount);
- }
- };
-
private:
typedef std::map<std::string, boost::shared_ptr<sys::ProtocolFactory> > ProtocolFactoryMap;
@@ -183,6 +166,7 @@ public:
AclModule* acl;
DataDir dataDir;
ConnectionObservers connectionObservers;
+ ConfigurationObservers configurationObservers;
QueueRegistry queues;
ExchangeRegistry exchanges;
@@ -203,9 +187,11 @@ public:
bool recovery;
bool inCluster, clusterUpdatee;
boost::intrusive_ptr<ExpiryPolicy> expiryPolicy;
- ConnectionCounter connectionCounter;
ConsumerFactories consumerFactories;
+ mutable sys::Mutex linkClientPropertiesLock;
+ framing::FieldTable linkClientProperties;
+
public:
QPID_BROKER_EXTERN virtual ~Broker();
@@ -317,8 +303,6 @@ public:
management::ManagementAgent* getManagementAgent() { return managementAgent.get(); }
- ConnectionCounter& getConnectionCounter() {return connectionCounter;}
-
/**
* Never true in a stand-alone broker. In a cluster, return true
* to defer delivery of messages deliveredg in a cluster-unsafe
@@ -377,6 +361,14 @@ public:
ConsumerFactories& getConsumerFactories() { return consumerFactories; }
ConnectionObservers& getConnectionObservers() { return connectionObservers; }
+ ConfigurationObservers& getConfigurationObservers() { return configurationObservers; }
+
+ /** Properties to be set on outgoing link connections */
+ QPID_BROKER_EXTERN framing::FieldTable getLinkClientProperties() const;
+ QPID_BROKER_EXTERN void setLinkClientProperties(const framing::FieldTable&);
+
+ /** Information identifying this system */
+ boost::shared_ptr<const System> getSystem() const { return systemObject; }
};
}}
diff --git a/cpp/src/qpid/broker/ConfigurationObserver.h b/cpp/src/qpid/broker/ConfigurationObserver.h
new file mode 100644
index 0000000000..701043db40
--- /dev/null
+++ b/cpp/src/qpid/broker/ConfigurationObserver.h
@@ -0,0 +1,61 @@
+#ifndef QPID_BROKER_CONFIGURATIONOBSERVER_H
+#define QPID_BROKER_CONFIGURATIONOBSERVER_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 <boost/shared_ptr.hpp>
+#include <string>
+
+namespace qpid {
+
+namespace framing {
+class FieldTable;
+}
+
+namespace broker {
+class Queue;
+class Exchange;
+
+
+/**
+ * Observer for changes to configuration (aka wiring)
+ */
+class ConfigurationObserver
+{
+ public:
+ virtual ~ConfigurationObserver() {}
+ virtual void queueCreate(const boost::shared_ptr<Queue>&) {}
+ virtual void queueDestroy(const boost::shared_ptr<Queue>&) {}
+ virtual void exchangeCreate(const boost::shared_ptr<Exchange>&) {}
+ virtual void exchangeDestroy(const boost::shared_ptr<Exchange>&) {}
+ virtual void bind(const boost::shared_ptr<Exchange>& ,
+ const boost::shared_ptr<Queue>& ,
+ const std::string& /*key*/,
+ const framing::FieldTable& /*args*/) {}
+ virtual void unbind(const boost::shared_ptr<Exchange>&,
+ const boost::shared_ptr<Queue>& ,
+ const std::string& /*key*/,
+ const framing::FieldTable& /*args*/) {}
+};
+}} // namespace qpid::broker
+
+#endif /*!QPID_BROKER_CONFIGURATIONOBSERVER_H*/
diff --git a/cpp/src/qpid/broker/ConfigurationObservers.h b/cpp/src/qpid/broker/ConfigurationObservers.h
new file mode 100644
index 0000000000..4c1159747d
--- /dev/null
+++ b/cpp/src/qpid/broker/ConfigurationObservers.h
@@ -0,0 +1,72 @@
+#ifndef QPID_BROKER_CONFIGURATIONOBSERVERS_H
+#define QPID_BROKER_CONFIGURATIONOBSERVERS_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 "ConfigurationObserver.h"
+#include "Observers.h"
+#include "qpid/sys/Mutex.h"
+
+namespace qpid {
+namespace broker {
+
+/**
+ * A configuration observer that delegates to a collection of
+ * configuration observers.
+ *
+ * THREAD SAFE
+ */
+class ConfigurationObservers : public ConfigurationObserver,
+ public Observers<ConfigurationObserver>
+{
+ public:
+ void queueCreate(const boost::shared_ptr<Queue>& q) {
+ each(boost::bind(&ConfigurationObserver::queueCreate, _1, q));
+ }
+ void queueDestroy(const boost::shared_ptr<Queue>& q) {
+ each(boost::bind(&ConfigurationObserver::queueDestroy, _1, q));
+ }
+ void exchangeCreate(const boost::shared_ptr<Exchange>& e) {
+ each(boost::bind(&ConfigurationObserver::exchangeCreate, _1, e));
+ }
+ void exchangeDestroy(const boost::shared_ptr<Exchange>& e) {
+ each(boost::bind(&ConfigurationObserver::exchangeDestroy, _1, e));
+ }
+ void bind(const boost::shared_ptr<Exchange>& exchange,
+ const boost::shared_ptr<Queue>& queue,
+ const std::string& key,
+ const framing::FieldTable& args) {
+ each(boost::bind(
+ &ConfigurationObserver::bind, _1, exchange, queue, key, args));
+ }
+ void unbind(const boost::shared_ptr<Exchange>& exchange,
+ const boost::shared_ptr<Queue>& queue,
+ const std::string& key,
+ const framing::FieldTable& args) {
+ each(boost::bind(
+ &ConfigurationObserver::unbind, _1, exchange, queue, key, args));
+ }
+};
+
+}} // namespace qpid::broker
+
+#endif /*!QPID_BROKER_CONFIGURATIONOBSERVERS_H*/
diff --git a/cpp/src/qpid/broker/Connection.cpp b/cpp/src/qpid/broker/Connection.cpp
index 5e339cec03..8d250a32e5 100644
--- a/cpp/src/qpid/broker/Connection.cpp
+++ b/cpp/src/qpid/broker/Connection.cpp
@@ -43,7 +43,7 @@
#include <iostream>
#include <assert.h>
-
+using std::string;
using namespace qpid::sys;
using namespace qpid::framing;
@@ -87,10 +87,14 @@ Connection::Connection(ConnectionOutputHandler* out_,
bool link_,
uint64_t objectId_,
bool shadow_,
- bool delayManagement) :
+ bool delayManagement,
+ bool authenticated_
+) :
ConnectionState(out_, broker_),
securitySettings(external),
- adapter(*this, link_, shadow_),
+ shadow(shadow_),
+ authenticated(authenticated_),
+ adapter(*this, link_),
link(link_),
mgmtClosing(false),
mgmtId(mgmtId_),
@@ -100,14 +104,12 @@ Connection::Connection(ConnectionOutputHandler* out_,
timer(broker_.getTimer()),
errorListener(0),
objectId(objectId_),
- shadow(shadow_),
outboundTracker(*this)
{
outboundTracker.wrap(out);
broker.getConnectionObservers().connection(*this);
// In a cluster, allow adding the management object to be delayed.
if (!delayManagement) addManagementObject();
- if (!isShadow()) broker.getConnectionCounter().inc_connectionCount();
}
void Connection::addManagementObject() {
@@ -141,6 +143,8 @@ Connection::~Connection()
// a cluster-unsafe context. Don't raise an event in that case.
if (!link && isClusterSafe())
agent->raiseEvent(_qmf::EventClientDisconnect(mgmtId, ConnectionState::getUserId()));
+ QPID_LOG_CAT(debug, model, "Delete connection. user:" << ConnectionState::getUserId()
+ << " rhost:" << mgmtId );
}
broker.getConnectionObservers().closed(*this);
@@ -148,8 +152,9 @@ Connection::~Connection()
heartbeatTimer->cancel();
if (timeoutTimer)
timeoutTimer->cancel();
-
- if (!isShadow()) broker.getConnectionCounter().dec_connectionCount();
+ if (linkHeartbeatTimer) {
+ linkHeartbeatTimer->cancel();
+ }
}
void Connection::received(framing::AMQFrame& frame) {
@@ -284,6 +289,10 @@ void Connection::raiseConnectEvent() {
mgmtObject->set_authIdentity(userId);
agent->raiseEvent(_qmf::EventClientConnect(mgmtId, userId));
}
+
+ QPID_LOG_CAT(debug, model, "Create connection. user:" << userId
+ << " rhost:" << mgmtId );
+
}
void Connection::setUserProxyAuth(bool b)
@@ -300,6 +309,9 @@ void Connection::close(connection::CloseCode code, const string& text)
heartbeatTimer->cancel();
if (timeoutTimer)
timeoutTimer->cancel();
+ if (linkHeartbeatTimer) {
+ linkHeartbeatTimer->cancel();
+ }
adapter.close(code, text);
//make sure we delete dangling pointers from outputTasks before deleting sessions
outputTasks.removeAll();
@@ -313,6 +325,9 @@ void Connection::sendClose() {
heartbeatTimer->cancel();
if (timeoutTimer)
timeoutTimer->cancel();
+ if (linkHeartbeatTimer) {
+ linkHeartbeatTimer->cancel();
+ }
adapter.close(connection::CLOSE_CODE_NORMAL, "OK");
getOutput().close();
}
@@ -326,6 +341,9 @@ void Connection::closed(){ // Physically closed, suspend open sessions.
heartbeatTimer->cancel();
if (timeoutTimer)
timeoutTimer->cancel();
+ if (linkHeartbeatTimer) {
+ linkHeartbeatTimer->cancel();
+ }
try {
while (!channels.empty())
ptr_map_ptr(channels.begin())->handleDetach();
@@ -435,6 +453,31 @@ struct ConnectionHeartbeatTask : public sys::TimerTask {
}
};
+class LinkHeartbeatTask : public qpid::sys::TimerTask {
+ sys::Timer& timer;
+ Connection& connection;
+ bool heartbeatSeen;
+
+ void fire() {
+ if (!heartbeatSeen) {
+ QPID_LOG(error, "Federation link connection " << connection.getMgmtId() << " missed 2 heartbeats - closing connection");
+ connection.abort();
+ } else {
+ heartbeatSeen = false;
+ // Setup next firing
+ setupNextFire();
+ timer.add(this);
+ }
+ }
+
+public:
+ LinkHeartbeatTask(sys::Timer& t, qpid::sys::Duration period, Connection& c) :
+ TimerTask(period, "LinkHeartbeatTask"), timer(t), connection(c), heartbeatSeen(false) {}
+
+ void heartbeatReceived() { heartbeatSeen = true; }
+};
+
+
void Connection::abort()
{
// Make sure that we don't try to send a heartbeat as we're
@@ -460,10 +503,21 @@ void Connection::setHeartbeatInterval(uint16_t heartbeat)
}
}
+void Connection::startLinkHeartbeatTimeoutTask() {
+ if (!linkHeartbeatTimer && heartbeat > 0) {
+ linkHeartbeatTimer = new LinkHeartbeatTask(timer, 2 * heartbeat * TIME_SEC, *this);
+ timer.add(linkHeartbeatTimer);
+ }
+}
+
void Connection::restartTimeout()
{
if (timeoutTimer)
timeoutTimer->touch();
+
+ if (linkHeartbeatTimer) {
+ static_cast<LinkHeartbeatTask*>(linkHeartbeatTimer.get())->heartbeatReceived();
+ }
}
bool Connection::isOpen() { return adapter.isOpen(); }
diff --git a/cpp/src/qpid/broker/Connection.h b/cpp/src/qpid/broker/Connection.h
index 1b8bd83139..d01599ce54 100644
--- a/cpp/src/qpid/broker/Connection.h
+++ b/cpp/src/qpid/broker/Connection.h
@@ -27,8 +27,7 @@
#include <vector>
#include <queue>
-#include <boost/ptr_container/ptr_map.hpp>
-
+#include "qpid/broker/BrokerImportExport.h"
#include "qpid/broker/ConnectionHandler.h"
#include "qpid/broker/ConnectionState.h"
#include "qpid/broker/SessionHandler.h"
@@ -86,15 +85,22 @@ class Connection : public sys::ConnectionInputHandler,
bool isLink = false,
uint64_t objectId = 0,
bool shadow=false,
- bool delayManagement = false);
+ bool delayManagement = false,
+ bool authenticated=true);
~Connection ();
/** Get the SessionHandler for channel. Create if it does not already exist */
SessionHandler& getChannel(framing::ChannelId channel);
- /** Close the connection */
- void close(framing::connection::CloseCode code, const std::string& text);
+ /** Close the connection. Waits for the client to respond with close-ok
+ * before actually destroying the connection.
+ */
+ QPID_BROKER_EXTERN void close(
+ framing::connection::CloseCode code, const std::string& text);
+
+ /** Abort the connection. Close abruptly and immediately. */
+ QPID_BROKER_EXTERN void abort();
// ConnectionInputHandler methods
void received(framing::AMQFrame& frame);
@@ -138,8 +144,7 @@ class Connection : public sys::ConnectionInputHandler,
void setHeartbeatInterval(uint16_t heartbeat);
void sendHeartbeat();
void restartTimeout();
- void abort();
-
+
template <class F> void eachSessionHandler(F f) {
for (ChannelMap::iterator i = channels.begin(); i != channels.end(); ++i)
f(*ptr_map_ptr(i));
@@ -149,7 +154,10 @@ class Connection : public sys::ConnectionInputHandler,
void setSecureConnection(SecureConnection* secured);
/** True if this is a shadow connection in a cluster. */
- bool isShadow() { return shadow; }
+ bool isShadow() const { return shadow; }
+
+ /** True if this connection is authenticated */
+ bool isAuthenticated() const { return authenticated; }
// Used by cluster to update connection status
sys::AggregateOutput& getOutputTasks() { return outputTasks; }
@@ -166,6 +174,7 @@ class Connection : public sys::ConnectionInputHandler,
bool isOpen();
bool isLink() { return link; }
+ void startLinkHeartbeatTimeoutTask();
// Used by cluster during catch-up, see cluster::OutputInterceptor
void doIoCallbacks();
@@ -179,6 +188,8 @@ class Connection : public sys::ConnectionInputHandler,
ChannelMap channels;
qpid::sys::SecuritySettings securitySettings;
+ bool shadow;
+ bool authenticated;
ConnectionHandler adapter;
const bool link;
bool mgmtClosing;
@@ -189,11 +200,10 @@ class Connection : public sys::ConnectionInputHandler,
LinkRegistry& links;
management::ManagementAgent* agent;
sys::Timer& timer;
- boost::intrusive_ptr<sys::TimerTask> heartbeatTimer;
+ boost::intrusive_ptr<sys::TimerTask> heartbeatTimer, linkHeartbeatTimer;
boost::intrusive_ptr<ConnectionTimeoutTask> timeoutTimer;
ErrorListener* errorListener;
uint64_t objectId;
- bool shadow;
framing::FieldTable clientProperties;
/**
diff --git a/cpp/src/qpid/broker/ConnectionFactory.cpp b/cpp/src/qpid/broker/ConnectionFactory.cpp
index 9e0020812b..d5d24ca629 100644
--- a/cpp/src/qpid/broker/ConnectionFactory.cpp
+++ b/cpp/src/qpid/broker/ConnectionFactory.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
@@ -40,11 +40,6 @@ ConnectionFactory::~ConnectionFactory() {}
sys::ConnectionCodec*
ConnectionFactory::create(ProtocolVersion v, sys::OutputControl& out, const std::string& id,
const SecuritySettings& external) {
- if (broker.getConnectionCounter().allowConnection())
- {
- QPID_LOG(error, "Client max connection count limit exceeded: " << broker.getOptions().maxConnections << " connection refused");
- return 0;
- }
if (v == ProtocolVersion(0, 10)) {
ConnectionPtr c(new amqp_0_10::Connection(out, id, false));
c->setInputHandler(InputPtr(new broker::Connection(c.get(), broker, id, external, false)));
@@ -62,5 +57,5 @@ ConnectionFactory::create(sys::OutputControl& out, const std::string& id,
return c.release();
}
-
+
}} // namespace qpid::broker
diff --git a/cpp/src/qpid/broker/ConnectionHandler.cpp b/cpp/src/qpid/broker/ConnectionHandler.cpp
index 6894324117..06f442a47f 100644
--- a/cpp/src/qpid/broker/ConnectionHandler.cpp
+++ b/cpp/src/qpid/broker/ConnectionHandler.cpp
@@ -36,6 +36,9 @@
using namespace qpid;
using namespace qpid::broker;
+
+using std::string;
+
using namespace qpid::framing;
using qpid::sys::SecurityLayer;
namespace _qmf = qmf::org::apache::qpid::broker;
@@ -103,9 +106,10 @@ void ConnectionHandler::setSecureConnection(SecureConnection* secured)
handler->secured = secured;
}
-ConnectionHandler::ConnectionHandler(Connection& connection, bool isClient, bool isShadow) : handler(new Handler(connection, isClient, isShadow)) {}
+ConnectionHandler::ConnectionHandler(Connection& connection, bool isClient) :
+ handler(new Handler(connection, isClient)) {}
-ConnectionHandler::Handler::Handler(Connection& c, bool isClient, bool isShadow) :
+ConnectionHandler::Handler::Handler(Connection& c, bool isClient) :
proxy(c.getOutput()),
connection(c), serverMode(!isClient), secured(0),
isOpen(false)
@@ -116,14 +120,13 @@ ConnectionHandler::Handler::Handler(Connection& c, bool isClient, bool isShadow)
properties.setString(QPID_FED_TAG, connection.getBroker().getFederationTag());
- authenticator = SaslAuthenticator::createAuthenticator(c, isShadow);
+ authenticator = SaslAuthenticator::createAuthenticator(c);
authenticator->getMechanisms(mechanisms);
Array locales(0x95);
boost::shared_ptr<FieldValue> l(new Str16Value(en_US));
locales.add(l);
proxy.start(properties, mechanisms, locales);
-
}
maxFrameSize = (64 * 1024) - 1;
@@ -149,12 +152,20 @@ void ConnectionHandler::Handler::startOk(const ConnectionStartOkBody& body)
authenticator->start(body.getMechanism(), body.hasResponse() ? &body.getResponse() : 0);
} catch (std::exception& /*e*/) {
management::ManagementAgent* agent = connection.getAgent();
- if (agent) {
+ bool logEnabled;
+ QPID_LOG_TEST_CAT(debug, model, logEnabled);
+ if (logEnabled || agent)
+ {
string error;
string uid;
authenticator->getError(error);
authenticator->getUid(uid);
- agent->raiseEvent(_qmf::EventClientConnectFail(connection.getMgmtId(), uid, error));
+ if (agent) {
+ agent->raiseEvent(_qmf::EventClientConnectFail(connection.getMgmtId(), uid, error));
+ }
+ QPID_LOG_CAT(debug, model, "Failed connection. rhost:" << connection.getMgmtId()
+ << " user:" << uid
+ << " reason:" << error );
}
throw;
}
@@ -169,7 +180,9 @@ void ConnectionHandler::Handler::startOk(const ConnectionStartOkBody& body)
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");
+ proxy.close(framing::connection::CLOSE_CODE_CONNECTION_FORCED,
+ QPID_MSG("ACL denied " << connection.getUserId()
+ << " creating a federation link"));
return;
}
QPID_LOG(info, "Connection is a federation link");
@@ -195,12 +208,20 @@ void ConnectionHandler::Handler::secureOk(const string& response)
authenticator->step(response);
} catch (std::exception& /*e*/) {
management::ManagementAgent* agent = connection.getAgent();
- if (agent) {
+ bool logEnabled;
+ QPID_LOG_TEST_CAT(debug, model, logEnabled);
+ if (logEnabled || agent)
+ {
string error;
string uid;
authenticator->getError(error);
authenticator->getUid(uid);
- agent->raiseEvent(_qmf::EventClientConnectFail(connection.getMgmtId(), uid, error));
+ if (agent) {
+ agent->raiseEvent(_qmf::EventClientConnectFail(connection.getMgmtId(), uid, error));
+ }
+ QPID_LOG_CAT(debug, model, "Failed connection. rhost:" << connection.getMgmtId()
+ << " user:" << uid
+ << " reason:" << error );
}
throw;
}
@@ -278,7 +299,7 @@ void ConnectionHandler::Handler::start(const FieldTable& serverProperties,
service,
host,
0, // TODO -- mgoulish Fri Sep 24 2010
- 256,
+ 256,
false ); // disallow interaction
}
std::string supportedMechanismsList;
@@ -318,7 +339,7 @@ void ConnectionHandler::Handler::start(const FieldTable& serverProperties,
connection.setFederationPeerTag(serverProperties.getAsString(QPID_FED_TAG));
}
- FieldTable ft;
+ FieldTable ft = connection.getBroker().getLinkClientProperties();
ft.setInt(QPID_FED_LINK,1);
ft.setString(QPID_FED_TAG, connection.getBroker().getFederationTag());
@@ -367,8 +388,14 @@ void ConnectionHandler::Handler::tune(uint16_t channelMax,
maxFrameSize = std::min(maxFrameSize, maxFrameSizeProposed);
connection.setFrameMax(maxFrameSize);
- connection.setHeartbeat(heartbeatMax);
- proxy.tuneOk(channelMax, maxFrameSize, heartbeatMax);
+ // this method is only ever called when this Connection
+ // is a federation link where this Broker is acting as
+ // a client to another Broker
+ uint16_t hb = std::min(connection.getBroker().getOptions().linkHeartbeatInterval, heartbeatMax);
+ connection.setHeartbeat(hb);
+ connection.startLinkHeartbeatTimeoutTask();
+
+ proxy.tuneOk(channelMax, maxFrameSize, hb);
proxy.open("/", Array(), true);
}
diff --git a/cpp/src/qpid/broker/ConnectionHandler.h b/cpp/src/qpid/broker/ConnectionHandler.h
index 2e25543308..9346e7b1ac 100644
--- a/cpp/src/qpid/broker/ConnectionHandler.h
+++ b/cpp/src/qpid/broker/ConnectionHandler.h
@@ -61,7 +61,7 @@ class ConnectionHandler : public framing::FrameHandler
SecureConnection* secured;
bool isOpen;
- Handler(Connection& connection, bool isClient, bool isShadow=false);
+ Handler(Connection& connection, bool isClient);
~Handler();
void startOk(const qpid::framing::ConnectionStartOkBody& body);
void startOk(const qpid::framing::FieldTable& clientProperties,
@@ -99,7 +99,7 @@ class ConnectionHandler : public framing::FrameHandler
bool handle(const qpid::framing::AMQMethodBody& method);
public:
- ConnectionHandler(Connection& connection, bool isClient, bool isShadow=false );
+ ConnectionHandler(Connection& connection, bool isClient );
void close(framing::connection::CloseCode code, const std::string& text);
void heartbeat();
void handle(framing::AMQFrame& frame);
diff --git a/cpp/src/qpid/broker/ConnectionObservers.h b/cpp/src/qpid/broker/ConnectionObservers.h
index 07e515f3c9..e9014c80c3 100644
--- a/cpp/src/qpid/broker/ConnectionObservers.h
+++ b/cpp/src/qpid/broker/ConnectionObservers.h
@@ -23,9 +23,7 @@
*/
#include "ConnectionObserver.h"
-#include "qpid/sys/Mutex.h"
-#include <set>
-#include <algorithm>
+#include "Observers.h"
namespace qpid {
namespace broker {
@@ -35,18 +33,10 @@ namespace broker {
* Calling a ConnectionObserver function will call that function on each observer.
* THREAD SAFE.
*/
-class ConnectionObservers : public ConnectionObserver {
+class ConnectionObservers : public ConnectionObserver,
+ public Observers<ConnectionObserver>
+{
public:
- void add(boost::shared_ptr<ConnectionObserver> observer) {
- sys::Mutex::ScopedLock l(lock);
- observers.insert(observer);
- }
-
- void remove(boost::shared_ptr<ConnectionObserver> observer) {
- sys::Mutex::ScopedLock l(lock);
- observers.erase(observer);
- }
-
void connection(Connection& c) {
each(boost::bind(&ConnectionObserver::connection, _1, boost::ref(c)));
}
@@ -62,16 +52,6 @@ class ConnectionObservers : public ConnectionObserver {
void forced(Connection& c, const std::string& text) {
each(boost::bind(&ConnectionObserver::forced, _1, boost::ref(c), text));
}
-
- private:
- typedef std::set<boost::shared_ptr<ConnectionObserver> > Observers;
- sys::Mutex lock;
- Observers observers;
-
- template <class F> void each(F f) {
- sys::Mutex::ScopedLock l(lock);
- std::for_each(observers.begin(), observers.end(), f);
- }
};
}} // namespace qpid::broker
diff --git a/cpp/src/qpid/broker/Consumer.h b/cpp/src/qpid/broker/Consumer.h
index 682c75ed4f..64073621be 100644
--- a/cpp/src/qpid/broker/Consumer.h
+++ b/cpp/src/qpid/broker/Consumer.h
@@ -54,7 +54,9 @@ class Consumer
bool preAcquires() const { return acquires; }
const std::string& getName() const { return name; }
+ /**@return the position of the last message seen by this consumer */
virtual framing::SequenceNumber getPosition() const { return position; }
+
virtual void setPosition(framing::SequenceNumber pos) { position = pos; }
virtual bool deliver(QueuedMessage& msg) = 0;
diff --git a/cpp/src/qpid/broker/Daemon.h b/cpp/src/qpid/broker/Daemon.h
index a9cd98bce2..2bb9fc5577 100644
--- a/cpp/src/qpid/broker/Daemon.h
+++ b/cpp/src/qpid/broker/Daemon.h
@@ -74,7 +74,6 @@ class Daemon : private boost::noncopyable
pid_t pid;
int pipeFds[2];
- int lockFileFd;
std::string lockFile;
std::string pidDir;
};
diff --git a/cpp/src/qpid/broker/DirectExchange.cpp b/cpp/src/qpid/broker/DirectExchange.cpp
index 5d9aea7509..2fa7ce0fc5 100644
--- a/cpp/src/qpid/broker/DirectExchange.cpp
+++ b/cpp/src/qpid/broker/DirectExchange.cpp
@@ -26,6 +26,9 @@
#include <iostream>
using namespace qpid::broker;
+
+using std::string;
+
using namespace qpid::framing;
using namespace qpid::sys;
using qpid::management::Manageable;
diff --git a/cpp/src/qpid/broker/Exchange.cpp b/cpp/src/qpid/broker/Exchange.cpp
index 8d20b0df81..82d4b4df15 100644
--- a/cpp/src/qpid/broker/Exchange.cpp
+++ b/cpp/src/qpid/broker/Exchange.cpp
@@ -35,6 +35,8 @@
namespace qpid {
namespace broker {
+using std::string;
+
using namespace qpid::framing;
using qpid::framing::Buffer;
using qpid::framing::FieldTable;
@@ -167,7 +169,7 @@ void Exchange::routeIVE(){
Exchange::Exchange (const string& _name, Manageable* parent, Broker* b) :
- name(_name), durable(false), persistenceId(0), sequence(false),
+ name(_name), durable(false), alternateUsers(0), persistenceId(0), sequence(false),
sequenceNo(0), ive(false), mgmtExchange(0), brokerMgmtObject(0), broker(b), destroyed(false)
{
if (parent != 0 && broker != 0)
diff --git a/cpp/src/qpid/broker/Exchange.h b/cpp/src/qpid/broker/Exchange.h
index 7376f814ed..fba752210f 100644
--- a/cpp/src/qpid/broker/Exchange.h
+++ b/cpp/src/qpid/broker/Exchange.h
@@ -174,8 +174,9 @@ public:
bool isDurable() { return durable; }
qpid::framing::FieldTable& getArgs() { return args; }
- Exchange::shared_ptr getAlternate() { return alternate; }
- void setAlternate(Exchange::shared_ptr _alternate);
+ QPID_BROKER_EXTERN Exchange::shared_ptr getAlternate() { return alternate; }
+ QPID_BROKER_EXTERN void setAlternate(Exchange::shared_ptr _alternate);
+
void incAlternateUsers() { alternateUsers++; }
void decAlternateUsers() { alternateUsers--; }
bool inUseAsAlternate() { return alternateUsers > 0; }
diff --git a/cpp/src/qpid/broker/ExchangeRegistry.cpp b/cpp/src/qpid/broker/ExchangeRegistry.cpp
index 43d7268dfb..b31c7bd7b8 100644
--- a/cpp/src/qpid/broker/ExchangeRegistry.cpp
+++ b/cpp/src/qpid/broker/ExchangeRegistry.cpp
@@ -19,6 +19,7 @@
*
*/
+#include "qpid/broker/Broker.h"
#include "qpid/broker/ExchangeRegistry.h"
#include "qpid/broker/DirectExchange.h"
#include "qpid/broker/FanOutExchange.h"
@@ -42,38 +43,42 @@ pair<Exchange::shared_ptr, bool> ExchangeRegistry::declare(const string& name, c
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);
- if (i == exchanges.end()) {
- Exchange::shared_ptr exchange;
-
- if (type == TopicExchange::typeName){
- exchange = Exchange::shared_ptr(new TopicExchange(name, durable, args, parent, broker));
- }else if(type == DirectExchange::typeName){
- exchange = Exchange::shared_ptr(new DirectExchange(name, durable, args, parent, broker));
- }else if(type == FanOutExchange::typeName){
- exchange = Exchange::shared_ptr(new FanOutExchange(name, durable, args, parent, broker));
- }else if (type == HeadersExchange::typeName) {
- exchange = Exchange::shared_ptr(new HeadersExchange(name, durable, args, parent, broker));
- }else if (type == ManagementDirectExchange::typeName) {
- exchange = Exchange::shared_ptr(new ManagementDirectExchange(name, durable, args, parent, broker));
- }else if (type == ManagementTopicExchange::typeName) {
- exchange = Exchange::shared_ptr(new ManagementTopicExchange(name, durable, args, parent, broker));
- }else if (type == Link::exchangeTypeName) {
- exchange = Link::linkExchangeFactory(name);
- }else{
- FunctionMap::iterator i = factory.find(type);
- if (i == factory.end()) {
- throw UnknownExchangeTypeException();
- } else {
- exchange = i->second(name, durable, args, parent, broker);
+ Exchange::shared_ptr exchange;
+ std::pair<Exchange::shared_ptr, bool> result;
+ {
+ RWlock::ScopedWlock locker(lock);
+ ExchangeMap::iterator i = exchanges.find(name);
+ if (i == exchanges.end()) {
+ if (type == TopicExchange::typeName){
+ exchange = Exchange::shared_ptr(new TopicExchange(name, durable, args, parent, broker));
+ }else if(type == DirectExchange::typeName){
+ exchange = Exchange::shared_ptr(new DirectExchange(name, durable, args, parent, broker));
+ }else if(type == FanOutExchange::typeName){
+ exchange = Exchange::shared_ptr(new FanOutExchange(name, durable, args, parent, broker));
+ }else if (type == HeadersExchange::typeName) {
+ exchange = Exchange::shared_ptr(new HeadersExchange(name, durable, args, parent, broker));
+ }else if (type == ManagementDirectExchange::typeName) {
+ exchange = Exchange::shared_ptr(new ManagementDirectExchange(name, durable, args, parent, broker));
+ }else if (type == ManagementTopicExchange::typeName) {
+ exchange = Exchange::shared_ptr(new ManagementTopicExchange(name, durable, args, parent, broker));
+ }else if (type == Link::exchangeTypeName) {
+ exchange = Link::linkExchangeFactory(name);
+ }else{
+ FunctionMap::iterator i = factory.find(type);
+ if (i == factory.end()) {
+ throw UnknownExchangeTypeException();
+ } else {
+ exchange = i->second(name, durable, args, parent, broker);
+ }
}
+ exchanges[name] = exchange;
+ result = std::pair<Exchange::shared_ptr, bool>(exchange, true);
+ } else {
+ result = std::pair<Exchange::shared_ptr, bool>(i->second, false);
}
- exchanges[name] = exchange;
- return std::pair<Exchange::shared_ptr, bool>(exchange, true);
- } else {
- return std::pair<Exchange::shared_ptr, bool>(i->second, false);
}
+ if (broker && exchange) broker->getConfigurationObservers().exchangeCreate(exchange);
+ return result;
}
void ExchangeRegistry::destroy(const string& name){
@@ -82,12 +87,17 @@ void ExchangeRegistry::destroy(const string& name){
(name == "amq.direct" || name == "amq.fanout" || name == "amq.topic" || name == "amq.match")) ||
name == "qpid.management")
throw framing::NotAllowedException(QPID_MSG("Cannot delete default exchange: '" << name << "'"));
- RWlock::ScopedWlock locker(lock);
- ExchangeMap::iterator i = exchanges.find(name);
- if (i != exchanges.end()) {
- i->second->destroy();
- exchanges.erase(i);
+ Exchange::shared_ptr exchange;
+ {
+ RWlock::ScopedWlock locker(lock);
+ ExchangeMap::iterator i = exchanges.find(name);
+ if (i != exchanges.end()) {
+ exchange = i->second;
+ i->second->destroy();
+ exchanges.erase(i);
+ }
}
+ if (broker && exchange) broker->getConfigurationObservers().exchangeDestroy(exchange);
}
Exchange::shared_ptr ExchangeRegistry::find(const string& name){
diff --git a/cpp/src/qpid/broker/FanOutExchange.cpp b/cpp/src/qpid/broker/FanOutExchange.cpp
index 2bce99b6fe..56c894c129 100644
--- a/cpp/src/qpid/broker/FanOutExchange.cpp
+++ b/cpp/src/qpid/broker/FanOutExchange.cpp
@@ -24,6 +24,9 @@
#include <algorithm>
using namespace qpid::broker;
+
+using std::string;
+
using namespace qpid::framing;
using namespace qpid::sys;
namespace _qmf = qmf::org::apache::qpid::broker;
diff --git a/cpp/src/qpid/broker/HeadersExchange.cpp b/cpp/src/qpid/broker/HeadersExchange.cpp
index 6648ae0422..9975d26c72 100644
--- a/cpp/src/qpid/broker/HeadersExchange.cpp
+++ b/cpp/src/qpid/broker/HeadersExchange.cpp
@@ -26,6 +26,9 @@
using namespace qpid::broker;
+
+using std::string;
+
using namespace qpid::framing;
using namespace qpid::sys;
namespace _qmf = qmf::org::apache::qpid::broker;
diff --git a/cpp/src/qpid/broker/Link.cpp b/cpp/src/qpid/broker/Link.cpp
index f21c861149..84dd163ac3 100644
--- a/cpp/src/qpid/broker/Link.cpp
+++ b/cpp/src/qpid/broker/Link.cpp
@@ -125,18 +125,20 @@ boost::shared_ptr<Exchange> Link::linkExchangeFactory( const std::string& _name
return Exchange::shared_ptr(new LinkExchange(_name));
}
-Link::Link(LinkRegistry* _links,
- MessageStore* _store,
+Link::Link(const string& _name,
+ LinkRegistry* _links,
const string& _host,
uint16_t _port,
const string& _transport,
+ DestroyedListener l,
bool _durable,
const string& _authMechanism,
const string& _username,
const string& _password,
Broker* _broker,
- Manageable* parent)
- : links(_links), store(_store),
+ Manageable* parent,
+ bool failover_)
+ : name(_name), links(_links),
configuredTransport(_transport), configuredHost(_host), configuredPort(_port),
host(_host), port(_port), transport(_transport),
durable(_durable),
@@ -149,7 +151,9 @@ Link::Link(LinkRegistry* _links,
channelCounter(1),
connection(0),
agent(0),
+ listener(l),
timerTask(new LinkTimerTask(*this, broker->getTimer())),
+ failover(failover_),
failoverChannel(0)
{
if (parent != 0 && broker != 0)
@@ -157,7 +161,10 @@ Link::Link(LinkRegistry* _links,
agent = broker->getManagementAgent();
if (agent != 0)
{
- mgmtObject = new _qmf::Link(agent, this, parent, _host, _port, _transport, _durable);
+ mgmtObject = new _qmf::Link(agent, this, parent, name, durable);
+ mgmtObject->set_host(host);
+ mgmtObject->set_port(port);
+ mgmtObject->set_transport(transport);
agent->addObject(mgmtObject, 0, durable);
}
}
@@ -169,13 +176,15 @@ Link::Link(LinkRegistry* _links,
}
broker->getTimer().add(timerTask);
- stringstream _name;
- _name << "qpid.link." << transport << ":" << host << ":" << port;
- std::pair<Exchange::shared_ptr, bool> rc = broker->getExchanges().declare(_name.str(),
- exchangeTypeName);
- failoverExchange = boost::static_pointer_cast<LinkExchange>(rc.first);
- assert(failoverExchange);
- failoverExchange->setLink(this);
+ if (failover) {
+ stringstream exchangeName;
+ exchangeName << "qpid.link." << name;
+ std::pair<Exchange::shared_ptr, bool> rc =
+ broker->getExchanges().declare(exchangeName.str(), exchangeTypeName);
+ failoverExchange = boost::static_pointer_cast<LinkExchange>(rc.first);
+ assert(failoverExchange);
+ failoverExchange->setLink(this);
+ }
}
Link::~Link ()
@@ -187,7 +196,8 @@ Link::~Link ()
if (mgmtObject != 0)
mgmtObject->resourceDestroy ();
- broker->getExchanges().destroy(failoverExchange->getName());
+ if (failover)
+ broker->getExchanges().destroy(failoverExchange->getName());
}
void Link::setStateLH (int newState)
@@ -239,16 +249,19 @@ void Link::established(Connection* c)
if (!hideManagement() && agent)
agent->raiseEvent(_qmf::EventBrokerLinkUp(addr.str()));
-
- Mutex::ScopedLock mutex(lock);
- setStateLH(STATE_OPERATIONAL);
- currentInterval = 1;
- visitCount = 0;
- connection = c;
- if (closing)
+ bool isClosing = false;
+ {
+ Mutex::ScopedLock mutex(lock);
+ setStateLH(STATE_OPERATIONAL);
+ currentInterval = 1;
+ visitCount = 0;
+ connection = c;
+ isClosing = closing;
+ }
+ if (isClosing)
destroy();
else // Process any IO tasks bridges added before established.
- connection->requestIOProcessing (boost::bind(&Link::ioThreadProcessing, this));
+ c->requestIOProcessing (boost::bind(&Link::ioThreadProcessing, this));
}
@@ -261,16 +274,26 @@ void Link::setUrl(const Url& u) {
namespace {
- /** invoked when session used to subscribe to remote's amq.failover exchange detaches */
- void sessionDetached(Link *link) {
- QPID_LOG(debug, "detached from 'amq.failover' for link: " << link->getName());
- }
+class DetachedCallback : public SessionHandler::ErrorListener {
+ public:
+ DetachedCallback(const Link& link) : name(link.getName()) {}
+ void connectionException(framing::connection::CloseCode, const std::string&) {}
+ void channelException(framing::session::DetachCode, const std::string&) {}
+ void executionException(framing::execution::ErrorCode, const std::string&) {}
+ void detach() {}
+ private:
+ const std::string name;
+};
}
-
void Link::opened() {
Mutex::ScopedLock mutex(lock);
if (!connection) return;
+
+ if (!hideManagement() && connection->GetManagementObject()) {
+ mgmtObject->set_connectionRef(connection->GetManagementObject()->getObjectId());
+ }
+
// Get default URL from known-hosts if not already set
if (url.empty()) {
const std::vector<Url>& known = connection->getKnownHosts();
@@ -282,80 +305,82 @@ void Link::opened() {
QPID_LOG(debug, "Known hosts for peer of inter-broker link: " << url);
}
- //
- // attempt to subscribe to failover exchange for updates from remote
- //
-
- const std::string queueName = "qpid.link." + framing::Uuid(true).str();
- failoverChannel = nextChannel();
-
- SessionHandler& sessionHandler = connection->getChannel(failoverChannel);
- sessionHandler.setDetachedCallback( boost::bind(&sessionDetached, this) );
- failoverSession = queueName;
- sessionHandler.attachAs(failoverSession);
-
- framing::AMQP_ServerProxy remoteBroker(sessionHandler.out);
-
- remoteBroker.getQueue().declare(queueName,
- "", // alt-exchange
- false, // passive
- false, // durable
- true, // exclusive
- true, // auto-delete
- FieldTable());
- remoteBroker.getExchange().bind(queueName,
- FAILOVER_EXCHANGE,
- "", // no key
- FieldTable());
- remoteBroker.getMessage().subscribe(queueName,
- failoverExchange->getName(),
- 1, // implied-accept mode
- 0, // pre-acquire mode
- false, // exclusive
- "", // resume-id
- 0, // resume-ttl
+ if (failover) {
+ //
+ // attempt to subscribe to failover exchange for updates from remote
+ //
+
+ const std::string queueName = "qpid.link." + framing::Uuid(true).str();
+ failoverChannel = nextChannel();
+
+ SessionHandler& sessionHandler = connection->getChannel(failoverChannel);
+ sessionHandler.setErrorListener(
+ boost::shared_ptr<SessionHandler::ErrorListener>(new DetachedCallback(*this)));
+ failoverSession = queueName;
+ sessionHandler.attachAs(failoverSession);
+
+ framing::AMQP_ServerProxy remoteBroker(sessionHandler.out);
+
+ remoteBroker.getQueue().declare(queueName,
+ "", // alt-exchange
+ false, // passive
+ false, // durable
+ true, // exclusive
+ true, // auto-delete
+ FieldTable());
+ remoteBroker.getExchange().bind(queueName,
+ FAILOVER_EXCHANGE,
+ "", // no key
FieldTable());
- remoteBroker.getMessage().flow(failoverExchange->getName(), 0, 0xFFFFFFFF);
- remoteBroker.getMessage().flow(failoverExchange->getName(), 1, 0xFFFFFFFF);
+ remoteBroker.getMessage().subscribe(queueName,
+ failoverExchange->getName(),
+ 1, // implied-accept mode
+ 0, // pre-acquire mode
+ false, // exclusive
+ "", // resume-id
+ 0, // resume-ttl
+ FieldTable());
+ remoteBroker.getMessage().flow(failoverExchange->getName(), 0, 0xFFFFFFFF);
+ remoteBroker.getMessage().flow(failoverExchange->getName(), 1, 0xFFFFFFFF);
+ }
}
void Link::closed(int, std::string text)
{
- bool isClosing = false;
- {
- Mutex::ScopedLock mutex(lock);
- QPID_LOG (info, "Inter-broker link disconnected from " << host << ":" << port << " " << text);
+ Mutex::ScopedLock mutex(lock);
+ QPID_LOG (info, "Inter-broker link disconnected from " << host << ":" << port << " " << text);
- connection = 0;
- if (state == STATE_OPERATIONAL) {
+ connection = 0;
+
+ if (!hideManagement()) {
+ mgmtObject->set_connectionRef(qpid::management::ObjectId());
+ if (state == STATE_OPERATIONAL && agent) {
stringstream addr;
addr << host << ":" << port;
- if (!hideManagement() && agent)
- agent->raiseEvent(_qmf::EventBrokerLinkDown(addr.str()));
+ agent->raiseEvent(_qmf::EventBrokerLinkDown(addr.str()));
}
+ }
- for (Bridges::iterator i = active.begin(); i != active.end(); i++) {
- (*i)->closed();
- created.push_back(*i);
- }
- active.clear();
+ for (Bridges::iterator i = active.begin(); i != active.end(); i++) {
+ (*i)->closed();
+ created.push_back(*i);
+ }
+ active.clear();
- if (state != STATE_FAILED && state != STATE_PASSIVE)
- {
- setStateLH(STATE_WAITING);
- if (!hideManagement())
- mgmtObject->set_lastError (text);
- }
+ if (state != STATE_FAILED && state != STATE_PASSIVE)
+ {
+ setStateLH(STATE_WAITING);
+ if (!hideManagement())
+ mgmtObject->set_lastError (text);
}
- // Call destroy outside of the lock, don't want to be deleted with lock held.
- if (isClosing)
- destroy();
}
-// Called in connection IO thread.
+// Called in connection IO thread, cleans up the connection before destroying Link
void Link::destroy ()
{
Bridges toDelete;
+
+ timerTask->cancel(); // call prior to locking so maintenance visit can finish
{
Mutex::ScopedLock mutex(lock);
@@ -374,14 +399,13 @@ void Link::destroy ()
for (Bridges::iterator i = created.begin(); i != created.end(); i++)
toDelete.push_back(*i);
created.clear();
-
- timerTask->cancel();
}
+
// Now delete all bridges on this link (don't hold the lock for this).
for (Bridges::iterator i = toDelete.begin(); i != toDelete.end(); i++)
- (*i)->destroy();
+ (*i)->close();
toDelete.clear();
- links->destroy (configuredHost, configuredPort);
+ listener(this); // notify LinkRegistry that this Link has been destroyed
}
void Link::add(Bridge::shared_ptr bridge)
@@ -423,7 +447,7 @@ void Link::ioThreadProcessing()
{
Mutex::ScopedLock mutex(lock);
- if (state != STATE_OPERATIONAL)
+ if (state != STATE_OPERATIONAL || closing)
return;
// check for bridge session errors and recover
@@ -460,7 +484,7 @@ void Link::ioThreadProcessing()
void Link::maintenanceVisit ()
{
Mutex::ScopedLock mutex(lock);
-
+ if (closing) return;
if (state == STATE_WAITING)
{
visitCount++;
@@ -476,21 +500,27 @@ void Link::maintenanceVisit ()
}
}
}
- else if (state == STATE_OPERATIONAL && (!active.empty() || !created.empty() || !cancellations.empty()) && connection != 0)
+ else if (state == STATE_OPERATIONAL &&
+ (!active.empty() || !created.empty() || !cancellations.empty()) &&
+ connection && connection->isOpen())
connection->requestIOProcessing (boost::bind(&Link::ioThreadProcessing, this));
- }
+}
void Link::reconnectLH(const Address& a)
{
host = a.host;
port = a.port;
transport = a.protocol;
- startConnectionLH();
+
if (!hideManagement()) {
stringstream errorString;
- errorString << "Failed over to " << a;
+ errorString << "Failing over to " << a;
mgmtObject->set_lastError(errorString.str());
+ mgmtObject->set_host(host);
+ mgmtObject->set_port(port);
+ mgmtObject->set_transport(transport);
}
+ startConnectionLH();
}
bool Link::tryFailoverLH() {
@@ -499,15 +529,14 @@ bool Link::tryFailoverLH() {
if (url.empty()) return false;
Address next = url[reconnectNext++];
if (next.host != host || next.port != port || next.protocol != transport) {
- links->changeAddress(Address(transport, host, port), next);
- QPID_LOG(debug, "Inter-broker link failing over to " << next.host << ":" << next.port);
+ QPID_LOG(notice, "Inter-broker link '" << name << "' failing over to " << next);
reconnectLH(next);
return true;
}
return false;
}
-// Management updates for a linke are inconsistent in a cluster, so they are
+// Management updates for a link are inconsistent in a cluster, so they are
// suppressed.
bool Link::hideManagement() const {
return !mgmtObject || ( broker && broker->isInCluster());
@@ -536,18 +565,34 @@ void Link::setPersistenceId(uint64_t id) const
const string& Link::getName() const
{
- return configuredHost;
+ return name;
+}
+
+const std::string Link::ENCODED_IDENTIFIER("link.v2");
+const std::string Link::ENCODED_IDENTIFIER_V1("link");
+
+bool Link::isEncodedLink(const std::string& key)
+{
+ return key == ENCODED_IDENTIFIER || key == ENCODED_IDENTIFIER_V1;
}
Link::shared_ptr Link::decode(LinkRegistry& links, Buffer& buffer)
{
+ string kind;
+ buffer.getShortString(kind);
+
string host;
uint16_t port;
string transport;
string authMechanism;
string username;
string password;
+ string name;
+ if (kind == ENCODED_IDENTIFIER) {
+ // newer version provides a link name.
+ buffer.getShortString(name);
+ }
buffer.getShortString(host);
port = buffer.getShort();
buffer.getShortString(transport);
@@ -556,12 +601,21 @@ Link::shared_ptr Link::decode(LinkRegistry& links, Buffer& buffer)
buffer.getShortString(username);
buffer.getShortString(password);
- return links.declare(host, port, transport, durable, authMechanism, username, password).first;
+ if (kind == ENCODED_IDENTIFIER_V1) {
+ /** previous versions identified the Link by host:port, there was no name
+ * assigned. So create a name for the new Link.
+ */
+ name = createName(transport, host, port);
+ }
+
+ return links.declare(name, host, port, transport, durable, authMechanism,
+ username, password).first;
}
void Link::encode(Buffer& buffer) const
{
- buffer.putShortString(string("link"));
+ buffer.putShortString(ENCODED_IDENTIFIER);
+ buffer.putShortString(name);
buffer.putShortString(configuredHost);
buffer.putShort(configuredPort);
buffer.putShortString(configuredTransport);
@@ -573,8 +627,9 @@ void Link::encode(Buffer& buffer) const
uint32_t Link::encodedSize() const
{
- return configuredHost.size() + 1 // short-string (host)
- + 5 // short-string ("link")
+ return ENCODED_IDENTIFIER.size() + 1 // +1 byte length
+ + name.size() + 1
+ + configuredHost.size() + 1 // short-string (host)
+ 2 // port
+ configuredTransport.size() + 1 // short-string(transport)
+ 1 // durable
@@ -589,6 +644,7 @@ ManagementObject* Link::GetManagementObject (void) const
}
void Link::close() {
+ QPID_LOG(debug, "Link::close(), link=" << name );
Mutex::ScopedLock mutex(lock);
if (!closing) {
closing = true;
@@ -609,36 +665,31 @@ Manageable::status_t Link::ManagementMethod (uint32_t op, Args& args, string& te
return Manageable::STATUS_OK;
case _qmf::Link::METHOD_BRIDGE :
+ /* TBD: deprecate this interface in favor of the Broker::create() method. The
+ * Broker::create() method allows the user to assign a name to the bridge.
+ */
+ QPID_LOG(info, "The Link::bridge() method will be removed in a future release of QPID."
+ " Please use the Broker::create() method with type='bridge' instead.");
_qmf::ArgsLinkBridge& iargs = (_qmf::ArgsLinkBridge&) args;
- QPID_LOG(debug, "Link::bridge() request received");
-
- // Durable bridges are only valid on durable links
- if (iargs.i_durable && !durable) {
- text = "Can't create a durable route on a non-durable link";
- return Manageable::STATUS_USER;
- }
-
- if (iargs.i_dynamic) {
- Exchange::shared_ptr exchange = getBroker()->getExchanges().get(iargs.i_src);
- if (exchange.get() == 0) {
- text = "Exchange not found";
- return Manageable::STATUS_USER;
- }
- if (!exchange->supportsDynamicBinding()) {
- text = "Exchange type does not support dynamic routing";
- return Manageable::STATUS_USER;
+ QPID_LOG(debug, "Link::bridge() request received; src=" << iargs.i_src <<
+ "; dest=" << iargs.i_dest << "; key=" << iargs.i_key);
+
+ // Does a bridge already exist that has the src/dest/key? If so, re-use the
+ // existing bridge - this behavior is backward compatible with previous releases.
+ Bridge::shared_ptr bridge = links->getBridge(*this, iargs.i_src, iargs.i_dest, iargs.i_key);
+ if (!bridge) {
+ // need to create a new bridge on this link.
+ std::pair<Bridge::shared_ptr, bool> rc =
+ links->declare( Bridge::createName(name, iargs.i_src, iargs.i_dest, iargs.i_key),
+ *this, iargs.i_durable,
+ iargs.i_src, iargs.i_dest, iargs.i_key, iargs.i_srcIsQueue,
+ iargs.i_srcIsLocal, iargs.i_tag, iargs.i_excludes,
+ iargs.i_dynamic, iargs.i_sync);
+ if (!rc.first) {
+ text = "invalid parameters";
+ return Manageable::STATUS_PARAMETER_INVALID;
}
}
-
- std::pair<Bridge::shared_ptr, bool> result =
- links->declare (configuredHost, configuredPort, iargs.i_durable, iargs.i_src,
- iargs.i_dest, iargs.i_key, iargs.i_srcIsQueue,
- iargs.i_srcIsLocal, iargs.i_tag, iargs.i_excludes,
- iargs.i_dynamic, iargs.i_sync);
-
- if (result.second && iargs.i_durable)
- store->create(*result.first);
-
return Manageable::STATUS_OK;
}
@@ -666,11 +717,13 @@ void Link::closeConnection( const std::string& reason)
{
if (connection != 0) {
// cancel our subscription to the failover exchange
- SessionHandler& sessionHandler = connection->getChannel(failoverChannel);
- if (sessionHandler.getSession()) {
- framing::AMQP_ServerProxy remoteBroker(sessionHandler.out);
- remoteBroker.getMessage().cancel(failoverExchange->getName());
- remoteBroker.getSession().detach(failoverSession);
+ if (failover) {
+ SessionHandler& sessionHandler = connection->getChannel(failoverChannel);
+ if (sessionHandler.getSession()) {
+ framing::AMQP_ServerProxy remoteBroker(sessionHandler.out);
+ remoteBroker.getMessage().cancel(failoverExchange->getName());
+ remoteBroker.getSession().detach(failoverSession);
+ }
}
connection->close(CLOSE_CODE_CONNECTION_FORCED, reason);
connection = 0;
@@ -716,6 +769,23 @@ void Link::setState(const framing::FieldTable& state)
}
}
+std::string Link::createName(const std::string& transport,
+ const std::string& host,
+ uint16_t port)
+{
+ stringstream linkName;
+ linkName << QPID_NAME_PREFIX << transport << std::string(":")
+ << host << std::string(":") << port;
+ return linkName.str();
+}
+
+
+bool Link::pendingConnection(const std::string& _host, uint16_t _port) const
+{
+ Mutex::ScopedLock mutex(lock);
+ return (isConnecting() && _port == port && _host == host);
+}
+
const std::string Link::exchangeTypeName("qpid.LinkExchange");
diff --git a/cpp/src/qpid/broker/Link.h b/cpp/src/qpid/broker/Link.h
index a97fa48664..f0cb90e73b 100644
--- a/cpp/src/qpid/broker/Link.h
+++ b/cpp/src/qpid/broker/Link.h
@@ -25,7 +25,6 @@
#include <boost/shared_ptr.hpp>
#include "qpid/Url.h"
#include "qpid/broker/BrokerImportExport.h"
-#include "qpid/broker/MessageStore.h"
#include "qpid/broker/PersistableConfig.h"
#include "qpid/broker/Bridge.h"
#include "qpid/broker/BrokerImportExport.h"
@@ -52,8 +51,8 @@ class LinkExchange;
class Link : public PersistableConfig, public management::Manageable {
private:
mutable sys::Mutex lock;
+ const std::string name;
LinkRegistry* links;
- MessageStore* store;
// these remain constant across failover - used to identify this link
const std::string configuredTransport;
@@ -64,7 +63,8 @@ class Link : public PersistableConfig, public management::Manageable {
uint16_t port;
std::string transport;
- bool durable;
+ bool durable;
+
std::string authMechanism;
std::string username;
std::string password;
@@ -85,8 +85,10 @@ class Link : public PersistableConfig, public management::Manageable {
uint channelCounter;
Connection* connection;
management::ManagementAgent* agent;
+ boost::function<void(Link*)> listener;
boost::intrusive_ptr<sys::TimerTask> timerTask;
boost::shared_ptr<broker::LinkExchange> failoverExchange; // subscribed to remote's amq.failover exchange
+ bool failover; // Do we subscribe to a failover exchange?
uint failoverChannel;
std::string failoverSession;
@@ -101,33 +103,39 @@ class Link : public PersistableConfig, public management::Manageable {
void setStateLH (int newState);
void startConnectionLH(); // Start the IO Connection
- void destroy(); // Called when mgmt deletes this link
+ void destroy(); // Cleanup connection before link goes away
void ioThreadProcessing(); // Called on connection's IO thread by request
bool tryFailoverLH(); // Called during maintenance visit
bool hideManagement() const;
+ void reconnectLH(const Address&); //called by LinkRegistry
- void established(Connection*); // Called when connection is create
+ // connection management (called by LinkRegistry)
+ void established(Connection*); // Called when connection is created
void opened(); // Called when connection is open (after create)
void closed(int, std::string); // Called when connection goes away
- void reconnectLH(const Address&); //called by LinkRegistry
+ void notifyConnectionForced(const std::string text);
void closeConnection(const std::string& reason);
+ bool pendingConnection(const std::string& host, uint16_t port) const; // is Link trying to connect to this remote?
friend class LinkRegistry; // to call established, opened, closed
public:
typedef boost::shared_ptr<Link> shared_ptr;
+ typedef boost::function<void(Link*)> DestroyedListener;
- Link(LinkRegistry* links,
- MessageStore* store,
+ Link(const std::string& name,
+ LinkRegistry* links,
const std::string& host,
uint16_t port,
const std::string& transport,
+ DestroyedListener l,
bool durable,
const std::string& authMechanism,
const std::string& username,
const std::string& password,
Broker* broker,
- management::Manageable* parent = 0);
+ management::Manageable* parent = 0,
+ bool failover=true);
virtual ~Link();
/** these return the *configured* transport/host/port, which does not change over the
@@ -139,7 +147,7 @@ class Link : public PersistableConfig, public management::Manageable {
/** returns the current address of the remote, which may be different from the
configured transport/host/port due to failover. Returns true if connection is
active */
- bool getRemoteAddress(qpid::Address& addr) const;
+ QPID_BROKER_EXTERN bool getRemoteAddress(qpid::Address& addr) const;
bool isDurable() { return durable; }
void maintenanceVisit ();
@@ -148,15 +156,17 @@ class Link : public PersistableConfig, public management::Manageable {
void cancel(Bridge::shared_ptr);
QPID_BROKER_EXTERN void setUrl(const Url&); // Set URL for reconnection.
- QPID_BROKER_EXTERN void close(); // Close the link from within the broker.
+
+ // Close the link.
+ QPID_BROKER_EXTERN void close();
std::string getAuthMechanism() { return authMechanism; }
std::string getUsername() { return username; }
std::string getPassword() { return password; }
Broker* getBroker() { return broker; }
- void notifyConnectionForced(const std::string text);
void setPassive(bool p);
+ bool isConnecting() const { return state == STATE_CONNECTING; }
// PersistableConfig:
void setPersistenceId(uint64_t id) const;
@@ -165,7 +175,10 @@ class Link : public PersistableConfig, public management::Manageable {
void encode(framing::Buffer& buffer) const;
const std::string& getName() const;
+ static const std::string ENCODED_IDENTIFIER;
+ static const std::string ENCODED_IDENTIFIER_V1;
static Link::shared_ptr decode(LinkRegistry& links, framing::Buffer& buffer);
+ static bool isEncodedLink(const std::string& key);
// Manageable entry points
management::ManagementObject* GetManagementObject(void) const;
@@ -178,6 +191,16 @@ class Link : public PersistableConfig, public management::Manageable {
// replicate internal state of this Link for clustering
void getState(framing::FieldTable& state) const;
void setState(const framing::FieldTable& state);
+
+ /** create a name for a link (if none supplied by user config) */
+ static std::string createName(const std::string& transport,
+ const std::string& host,
+ uint16_t port);
+
+ /** The current connction for this link. Note returns 0 if the link is not
+ * presently connected.
+ */
+ Connection* getConnection() { return connection; }
};
}
}
diff --git a/cpp/src/qpid/broker/LinkRegistry.cpp b/cpp/src/qpid/broker/LinkRegistry.cpp
index d89f220d1b..0507fe6521 100644
--- a/cpp/src/qpid/broker/LinkRegistry.cpp
+++ b/cpp/src/qpid/broker/LinkRegistry.cpp
@@ -68,54 +68,92 @@ LinkRegistry::LinkRegistry (Broker* _broker) :
LinkRegistry::~LinkRegistry() {}
+/** find link by the *configured* remote address */
+boost::shared_ptr<Link> LinkRegistry::getLink(const std::string& host,
+ uint16_t port,
+ const std::string& transport)
+{
+ Mutex::ScopedLock locker(lock);
+ for (LinkMap::iterator i = links.begin(); i != links.end(); ++i) {
+ Link::shared_ptr& link = i->second;
+ if (link->getHost() == host &&
+ link->getPort() == port &&
+ (transport.empty() || link->getTransport() == transport))
+ return link;
+ }
+ return boost::shared_ptr<Link>();
+}
-void LinkRegistry::changeAddress(const qpid::Address& oldAddress, const qpid::Address& newAddress)
+/** find link by name */
+boost::shared_ptr<Link> LinkRegistry::getLink(const std::string& name)
{
Mutex::ScopedLock locker(lock);
- std::string oldKey = createKey(oldAddress);
- std::string newKey = createKey(newAddress);
- if (links.find(newKey) != links.end()) {
- QPID_LOG(error, "Attempted to update key from " << oldKey << " to " << newKey << " which is already in use");
- } else {
- LinkMap::iterator i = links.find(oldKey);
- if (i == links.end()) {
- QPID_LOG(error, "Attempted to update key from " << oldKey << " which does not exist, to " << newKey);
- } else {
- links[newKey] = i->second;
- links.erase(oldKey);
- QPID_LOG(info, "Updated link key from " << oldKey << " to " << newKey);
- }
- }
+ LinkMap::iterator l = links.find(name);
+ if (l != links.end())
+ return l->second;
+ return boost::shared_ptr<Link>();
}
-pair<Link::shared_ptr, bool> LinkRegistry::declare(const string& host,
+pair<Link::shared_ptr, bool> LinkRegistry::declare(const string& name,
+ const string& host,
uint16_t port,
const string& transport,
bool durable,
const string& authMechanism,
const string& username,
- const string& password)
+ const string& password,
+ bool failover)
{
Mutex::ScopedLock locker(lock);
- string key = createKey(host, port);
- LinkMap::iterator i = links.find(key);
+ LinkMap::iterator i = links.find(name);
if (i == links.end())
{
Link::shared_ptr link;
- link = Link::shared_ptr (new Link (this, store, host, port, transport, durable,
- authMechanism, username, password,
- broker, parent));
- links[key] = link;
+ link = Link::shared_ptr (
+ new Link (name, this, host, port, transport,
+ boost::bind(&LinkRegistry::linkDestroyed, this, _1),
+ durable, authMechanism, username, password, broker,
+ parent, failover));
+ if (durable && store) store->create(*link);
+ links[name] = link;
+ QPID_LOG(debug, "Creating new link; name=" << name );
return std::pair<Link::shared_ptr, bool>(link, true);
}
return std::pair<Link::shared_ptr, bool>(i->second, false);
}
-pair<Bridge::shared_ptr, bool> LinkRegistry::declare(const std::string& host,
- uint16_t port,
+/** find bridge by link & route info */
+Bridge::shared_ptr LinkRegistry::getBridge(const Link& link,
+ const std::string& src,
+ const std::string& dest,
+ const std::string& key)
+{
+ Mutex::ScopedLock locker(lock);
+ for (BridgeMap::iterator i = bridges.begin(); i != bridges.end(); ++i) {
+ if (i->second->getSrc() == src && i->second->getDest() == dest &&
+ i->second->getKey() == key && i->second->getLink() &&
+ i->second->getLink()->getName() == link.getName()) {
+ return i->second;
+ }
+ }
+ return Bridge::shared_ptr();
+}
+
+/** find bridge by name */
+Bridge::shared_ptr LinkRegistry::getBridge(const std::string& name)
+{
+ Mutex::ScopedLock locker(lock);
+ BridgeMap::iterator b = bridges.find(name);
+ if (b != bridges.end())
+ return b->second;
+ return Bridge::shared_ptr();
+}
+
+pair<Bridge::shared_ptr, bool> LinkRegistry::declare(const std::string& name,
+ Link& link,
bool durable,
const std::string& src,
const std::string& dest,
@@ -126,22 +164,32 @@ pair<Bridge::shared_ptr, bool> LinkRegistry::declare(const std::string& host,
const std::string& excludes,
bool dynamic,
uint16_t sync,
- Bridge::InitializeCallback init
+ Bridge::InitializeCallback init,
+ const std::string& queueName,
+ const std::string& altExchange
)
{
Mutex::ScopedLock locker(lock);
- QPID_LOG(debug, "Bridge declared " << host << ": " << port << " from " << src << " to " << dest << " (" << key << ")");
- string linkKey = createKey(host, port);
- stringstream keystream;
- keystream << linkKey << "!" << src << "!" << dest << "!" << key;
- string bridgeKey = keystream.str();
+ // Durable bridges are only valid on durable links
+ if (durable && !link.isDurable()) {
+ QPID_LOG(error, "Can't create a durable route '" << name << "' on a non-durable link '" << link.getName());
+ return pair<Bridge::shared_ptr, bool>(Bridge::shared_ptr(), false);
+ }
- LinkMap::iterator l = links.find(linkKey);
- if (l == links.end())
- return pair<Bridge::shared_ptr, bool>(Bridge::shared_ptr(), false);
+ if (dynamic) {
+ Exchange::shared_ptr exchange = broker->getExchanges().get(src);
+ if (exchange.get() == 0) {
+ QPID_LOG(error, "Exchange not found, name='" << src << "'" );
+ return pair<Bridge::shared_ptr, bool>(Bridge::shared_ptr(), false);
+ }
+ if (!exchange->supportsDynamicBinding()) {
+ QPID_LOG(error, "Exchange type does not support dynamic routing, name='" << src << "'");
+ return pair<Bridge::shared_ptr, bool>(Bridge::shared_ptr(), false);
+ }
+ }
- BridgeMap::iterator b = bridges.find(bridgeKey);
+ BridgeMap::iterator b = bridges.find(name);
if (b == bridges.end())
{
_qmf::ArgsLinkBridge args;
@@ -159,23 +207,29 @@ pair<Bridge::shared_ptr, bool> LinkRegistry::declare(const std::string& host,
args.i_sync = sync;
bridge = Bridge::shared_ptr
- (new Bridge (l->second.get(), l->second->nextChannel(),
- boost::bind(&LinkRegistry::destroy, this,
- host, port, src, dest, key),
- args, init));
- bridges[bridgeKey] = bridge;
- l->second->add(bridge);
+ (new Bridge (name, &link, link.nextChannel(),
+ boost::bind(&LinkRegistry::destroyBridge, this, _1),
+ args, init, queueName, altExchange));
+ bridges[name] = bridge;
+ link.add(bridge);
+ if (durable && store)
+ store->create(*bridge);
+
+ QPID_LOG(debug, "Bridge '" << name <<"' declared on link '" << link.getName() <<
+ "' from " << src << " to " << dest << " (" << key << ")");
+
return std::pair<Bridge::shared_ptr, bool>(bridge, true);
}
return std::pair<Bridge::shared_ptr, bool>(b->second, false);
}
-void LinkRegistry::destroy(const string& host, const uint16_t port)
+/** called back by the link when it has completed its cleanup and can be removed. */
+void LinkRegistry::linkDestroyed(Link *link)
{
+ QPID_LOG(debug, "LinkRegistry::destroy(); link= " << link->getName());
Mutex::ScopedLock locker(lock);
- string key = createKey(host, port);
- LinkMap::iterator i = links.find(key);
+ LinkMap::iterator i = links.find(link->getName());
if (i != links.end())
{
if (i->second->isDurable() && store)
@@ -184,27 +238,20 @@ void LinkRegistry::destroy(const string& host, const uint16_t port)
}
}
-void LinkRegistry::destroy(const std::string& host,
- const uint16_t port,
- const std::string& src,
- const std::string& dest,
- const std::string& key)
+/** called back by bridge when its destruction has been requested */
+void LinkRegistry::destroyBridge(Bridge *bridge)
{
+ QPID_LOG(debug, "LinkRegistry::destroy(); bridge= " << bridge->getName());
Mutex::ScopedLock locker(lock);
- string linkKey = createKey(host, port);
- stringstream keystream;
- keystream << linkKey << "!" << src << "!" << dest << "!" << key;
- string bridgeKey = keystream.str();
-
- LinkMap::iterator l = links.find(linkKey);
- if (l == links.end())
- return;
- BridgeMap::iterator b = bridges.find(bridgeKey);
+ BridgeMap::iterator b = bridges.find(bridge->getName());
if (b == bridges.end())
return;
- l->second->cancel(b->second);
+ Link *link = b->second->getLink();
+ if (link) {
+ link->cancel(b->second);
+ }
if (b->second->isDurable())
store->destroy(*(b->second));
bridges.erase(b);
@@ -219,26 +266,71 @@ MessageStore* LinkRegistry::getStore() const {
return store;
}
-Link::shared_ptr LinkRegistry::findLink(const std::string& keyOrMgmtId)
-{
- // Convert keyOrMgmtId to a host:port key.
- //
- // TODO aconway 2011-02-01: centralize code that constructs/parses
- // connection management IDs. Currently sys:: protocol factories
- // and IO plugins construct the IDs and LinkRegistry parses them.
- size_t separator = keyOrMgmtId.find('-');
- if (separator == std::string::npos) separator = 0;
- std::string key = keyOrMgmtId.substr(separator+1, std::string::npos);
+namespace {
+ void extractHostPort(const std::string& connId, std::string *host, uint16_t *port)
+ {
+ // Extract host and port of remote broker from connection id string.
+ //
+ // TODO aconway 2011-02-01: centralize code that constructs/parses connection
+ // management IDs. Currently sys:: protocol factories and IO plugins construct the
+ // IDs and LinkRegistry parses them.
+ // KAG: current connection id format assumed:
+ // "localhost:port-remotehost:port". In the case of IpV6, the host addresses are
+ // contained within brackets "[...]", example:
+ // connId="[::1]:36859-[::1]:48603". Liberal use of "asserts" provided to alert us
+ // if this assumption changes!
+ size_t separator = connId.find('-');
+ assert(separator != std::string::npos);
+ std::string remote = connId.substr(separator+1, std::string::npos);
+ separator = remote.rfind(":");
+ assert(separator != std::string::npos);
+ *host = remote.substr(0, separator);
+ // IPv6 - host is bracketed by "[]", strip them
+ if ((*host)[0] == '[' && (*host)[host->length() - 1] == ']') {
+ *host = host->substr(1, host->length() - 2);
+ }
+ try {
+ *port = boost::lexical_cast<uint16_t>(remote.substr(separator+1, std::string::npos));
+ } catch (const boost::bad_lexical_cast&) {
+ QPID_LOG(error, "Invalid format for connection identifier! '" << connId << "'");
+ assert(false);
+ }
+ }
+}
+/** find the Link that corresponds to the given connection */
+Link::shared_ptr LinkRegistry::findLink(const std::string& connId)
+{
Mutex::ScopedLock locker(lock);
- LinkMap::iterator l = links.find(key);
- if (l != links.end()) return l->second;
- else return Link::shared_ptr();
+ ConnectionMap::iterator c = connections.find(connId);
+ if (c != connections.end()) {
+ LinkMap::iterator l = links.find(c->second);
+ if (l != links.end())
+ return l->second;
+ }
+ return Link::shared_ptr();
}
void LinkRegistry::notifyConnection(const std::string& key, Connection* c)
{
- Link::shared_ptr link = findLink(key);
+ // find a link that is attempting to connect to the remote, and
+ // create a mapping from connection id to link
+ QPID_LOG(debug, "LinkRegistry::notifyConnection(); key=" << key );
+ std::string host;
+ uint16_t port = 0;
+ extractHostPort( key, &host, &port );
+ Link::shared_ptr link;
+ {
+ Mutex::ScopedLock locker(lock);
+ for (LinkMap::iterator l = links.begin(); l != links.end(); ++l) {
+ if (l->second->pendingConnection(host, port)) {
+ link = l->second;
+ connections[key] = link->getName();
+ break;
+ }
+ }
+ }
+
if (link) {
link->established(c);
c->setUserId(str(format("%1%@%2%") % link->getUsername() % realm));
@@ -343,20 +435,6 @@ std::string LinkRegistry::getAuthIdentity(const std::string& key)
}
-std::string LinkRegistry::createKey(const qpid::Address& a) {
- // TODO aconway 2010-05-11: key should also include protocol/transport to
- // be unique. Requires refactor of LinkRegistry interface.
- return createKey(a.host, a.port);
-}
-
-std::string LinkRegistry::createKey(const std::string& host, uint16_t port) {
- // TODO aconway 2010-05-11: key should also include protocol/transport to
- // be unique. Requires refactor of LinkRegistry interface.
- stringstream keystream;
- keystream << host << ":" << port;
- return keystream.str();
-}
-
void LinkRegistry::setPassive(bool p)
{
Mutex::ScopedLock locker(lock);
@@ -369,10 +447,12 @@ void LinkRegistry::setPassive(bool p)
}
void LinkRegistry::eachLink(boost::function<void(boost::shared_ptr<Link>)> f) {
+ Mutex::ScopedLock locker(lock);
for (LinkMap::iterator i = links.begin(); i != links.end(); ++i) f(i->second);
}
void LinkRegistry::eachBridge(boost::function<void(boost::shared_ptr<Bridge>)> f) {
+ Mutex::ScopedLock locker(lock);
for (BridgeMap::iterator i = bridges.begin(); i != bridges.end(); ++i) f(i->second);
}
diff --git a/cpp/src/qpid/broker/LinkRegistry.h b/cpp/src/qpid/broker/LinkRegistry.h
index 8e9d2f4b0d..5a39b62bd1 100644
--- a/cpp/src/qpid/broker/LinkRegistry.h
+++ b/cpp/src/qpid/broker/LinkRegistry.h
@@ -42,9 +42,11 @@ namespace broker {
class LinkRegistry {
typedef std::map<std::string, boost::shared_ptr<Link> > LinkMap;
typedef std::map<std::string, Bridge::shared_ptr> BridgeMap;
+ typedef std::map<std::string, std::string> ConnectionMap;
- LinkMap links;
- BridgeMap bridges;
+ LinkMap links; /** indexed by name of Link */
+ BridgeMap bridges; /** indexed by name of Bridge */
+ ConnectionMap connections; /** indexed by connection identifier, gives link name */
qpid::sys::Mutex lock;
Broker* broker;
@@ -54,15 +56,18 @@ namespace broker {
std::string realm;
boost::shared_ptr<Link> findLink(const std::string& key);
- static std::string createKey(const Address& address);
- static std::string createKey(const std::string& host, uint16_t port);
- // Methods called by the connection observer.
+ // Methods called by the connection observer, key is connection identifier
void notifyConnection (const std::string& key, Connection* c);
void notifyOpened (const std::string& key);
void notifyClosed (const std::string& key);
void notifyConnectionForced (const std::string& key, const std::string& text);
- friend class LinkRegistryConnectionObserver;
+ friend class LinkRegistryConnectionObserver;
+
+ /** Notify the registry that a Link has been destroyed */
+ void linkDestroyed(Link*);
+ /** Request to destroy a Bridge */
+ void destroyBridge(Bridge*);
public:
QPID_BROKER_EXTERN LinkRegistry (); // Only used in store tests
@@ -70,17 +75,29 @@ namespace broker {
QPID_BROKER_EXTERN ~LinkRegistry();
QPID_BROKER_EXTERN std::pair<boost::shared_ptr<Link>, bool>
- declare(const std::string& host,
+ declare(const std::string& name,
+ const std::string& host,
uint16_t port,
const std::string& transport,
bool durable,
const std::string& authMechanism,
const std::string& username,
- const std::string& password);
+ const std::string& password,
+ bool failover=true);
+
+ /** determine if Link exists */
+ QPID_BROKER_EXTERN boost::shared_ptr<Link>
+ getLink(const std::string& name);
+ /** host,port,transport will be matched against the configured values, which may
+ be different from the current values due to failover */
+ QPID_BROKER_EXTERN boost::shared_ptr<Link>
+ getLink(const std::string& configHost,
+ uint16_t configPort,
+ const std::string& configTransport = std::string());
QPID_BROKER_EXTERN std::pair<Bridge::shared_ptr, bool>
- declare(const std::string& host,
- uint16_t port,
+ declare(const std::string& name,
+ Link& link,
bool durable,
const std::string& src,
const std::string& dest,
@@ -91,16 +108,18 @@ namespace broker {
const std::string& excludes,
bool dynamic,
uint16_t sync,
- Bridge::InitializeCallback=0
+ Bridge::InitializeCallback=0,
+ const std::string& queueName="",
+ const std::string& altExchange=""
);
-
- QPID_BROKER_EXTERN void destroy(const std::string& host, const uint16_t port);
-
- QPID_BROKER_EXTERN void destroy(const std::string& host,
- const uint16_t port,
- const std::string& src,
- const std::string& dest,
- const std::string& key);
+ /** determine if Bridge exists */
+ QPID_BROKER_EXTERN Bridge::shared_ptr
+ getBridge(const std::string& name);
+ QPID_BROKER_EXTERN Bridge::shared_ptr
+ getBridge(const Link& link,
+ const std::string& src,
+ const std::string& dest,
+ const std::string& key);
/**
* Register the manageable parent for declared queues
@@ -126,11 +145,6 @@ namespace broker {
QPID_BROKER_EXTERN uint16_t getPort (const std::string& key);
/**
- * Called by links failing over to new address
- */
- void changeAddress(const Address& oldAddress, const Address& newAddress);
-
- /**
* Called to alter passive state. In passive state the links
* and bridges managed by a link registry will be recorded and
* updated but links won't actually establish connections and
diff --git a/cpp/src/qpid/broker/Message.cpp b/cpp/src/qpid/broker/Message.cpp
index 40dfba39f4..4dd8a349dd 100644
--- a/cpp/src/qpid/broker/Message.cpp
+++ b/cpp/src/qpid/broker/Message.cpp
@@ -384,6 +384,18 @@ void Message::addTraceId(const std::string& id)
}
}
+void Message::clearTrace()
+{
+ sys::Mutex::ScopedLock l(lock);
+ if (isA<MessageTransferBody>()) {
+ FieldTable& headers = getModifiableProperties<MessageProperties>()->getApplicationHeaders();
+ std::string trace = headers.getAsString(X_QPID_TRACE);
+ if (!trace.empty()) {
+ headers.setString(X_QPID_TRACE, "");
+ }
+ }
+}
+
void Message::setTimestamp()
{
sys::Mutex::ScopedLock l(lock);
diff --git a/cpp/src/qpid/broker/Message.h b/cpp/src/qpid/broker/Message.h
index dda45d73e6..90e4eec889 100644
--- a/cpp/src/qpid/broker/Message.h
+++ b/cpp/src/qpid/broker/Message.h
@@ -161,6 +161,7 @@ public:
bool isExcluded(const std::vector<std::string>& excludes) const;
void addTraceId(const std::string& id);
+ void clearTrace();
void forcePersistent();
bool isForcedPersistent();
diff --git a/cpp/src/qpid/broker/MessageDeque.cpp b/cpp/src/qpid/broker/MessageDeque.cpp
index f70c996975..83c8ca6868 100644
--- a/cpp/src/qpid/broker/MessageDeque.cpp
+++ b/cpp/src/qpid/broker/MessageDeque.cpp
@@ -40,13 +40,16 @@ size_t MessageDeque::index(const framing::SequenceNumber& position)
bool MessageDeque::deleted(const QueuedMessage& m)
{
size_t i = index(m.position);
- if (i < messages.size() && messages[i].status != QueuedMessage::DELETED) {
- messages[i].status = QueuedMessage::DELETED;
- clean();
- return true;
- } else {
- return false;
+ if (i < messages.size()) {
+ QueuedMessage *qm = &messages[i];
+ if (qm->status != QueuedMessage::DELETED) {
+ qm->status = QueuedMessage::DELETED;
+ qm->payload = 0; // message no longer needed
+ clean();
+ return true;
+ }
}
+ return false;
}
size_t MessageDeque::size()
@@ -144,6 +147,7 @@ QueuedMessage* MessageDeque::pushPtr(const QueuedMessage& added) {
messages.back().status = QueuedMessage::AVAILABLE;
if (head >= messages.size()) head = messages.size() - 1;
++available;
+ clean(); // QPID-4046: let producer help clean the backlog of deleted messages
return &messages.back();
}
@@ -173,12 +177,37 @@ void MessageDeque::updateAcquired(const QueuedMessage& acquired)
}
}
+namespace {
+bool isNotDeleted(const QueuedMessage& qm) { return qm.status != QueuedMessage::DELETED; }
+} // namespace
+
+void MessageDeque::setPosition(const framing::SequenceNumber& n) {
+ size_t i = index(n+1);
+ if (i >= messages.size()) return; // Nothing to do.
+
+ // Assertion to verify the precondition: no messaages after n.
+ assert(std::find_if(messages.begin()+i, messages.end(), &isNotDeleted) ==
+ messages.end());
+ messages.erase(messages.begin()+i, messages.end());
+ if (head >= messages.size()) head = messages.size() - 1;
+ // Re-count the available messages
+ available = 0;
+ for (Deque::iterator i = messages.begin(); i != messages.end(); ++i) {
+ if (i->status == QueuedMessage::AVAILABLE) ++available;
+ }
+}
+
void MessageDeque::clean()
{
- while (messages.size() && messages.front().status == QueuedMessage::DELETED) {
+ // QPID-4046: If a queue has multiple consumers, then it is possible for a large
+ // collection of deleted messages to build up. Limit the number of messages cleaned
+ // up on each call to clean().
+ size_t count = 0;
+ while (messages.size() && messages.front().status == QueuedMessage::DELETED && count < 10) {
messages.pop_front();
- if (head) --head;
+ count += 1;
}
+ head = (head > count) ? head - count : 0;
}
void MessageDeque::foreach(Functor f)
diff --git a/cpp/src/qpid/broker/MessageDeque.h b/cpp/src/qpid/broker/MessageDeque.h
index 9b53716d4e..c5670b2a72 100644
--- a/cpp/src/qpid/broker/MessageDeque.h
+++ b/cpp/src/qpid/broker/MessageDeque.h
@@ -44,7 +44,7 @@ class MessageDeque : public Messages
bool consume(QueuedMessage&);
bool push(const QueuedMessage& added, QueuedMessage& removed);
void updateAcquired(const QueuedMessage& acquired);
-
+ void setPosition(const framing::SequenceNumber&);
void foreach(Functor);
void removeIf(Predicate);
diff --git a/cpp/src/qpid/broker/MessageMap.cpp b/cpp/src/qpid/broker/MessageMap.cpp
index 9b164d4e5c..592f3fefde 100644
--- a/cpp/src/qpid/broker/MessageMap.cpp
+++ b/cpp/src/qpid/broker/MessageMap.cpp
@@ -21,6 +21,7 @@
#include "qpid/broker/MessageMap.h"
#include "qpid/broker/QueuedMessage.h"
#include "qpid/log/Statement.h"
+#include <algorithm>
namespace qpid {
namespace broker {
@@ -130,18 +131,24 @@ bool MessageMap::push(const QueuedMessage& added, QueuedMessage& removed)
QueuedMessage& a = messages[added.position];
a = added;
a.status = QueuedMessage::AVAILABLE;
- QPID_LOG(debug, "Added message at " << a.position);
+ QPID_LOG(debug, "Added message " << a);
return false;
} else {
//there is already a message with that key which needs to be replaced
removed = result.first->second;
result.first->second = replace(result.first->second, added);
result.first->second.status = QueuedMessage::AVAILABLE;
- QPID_LOG(debug, "Displaced message at " << removed.position << " with " << result.first->second.position << ": " << result.first->first);
+ QPID_LOG(debug, "Displaced message " << removed << " with " << result.first->second << ": " << result.first->first);
return true;
}
}
+void MessageMap::setPosition(const framing::SequenceNumber& seq) {
+ // Nothing to do, just assert that the precondition is respected and there
+ // are no undeleted messages after seq.
+ (void) seq; assert(messages.empty() || (--messages.end())->first <= seq);
+}
+
void MessageMap::foreach(Functor f)
{
for (Ordering::iterator i = messages.begin(); i != messages.end(); ++i) {
diff --git a/cpp/src/qpid/broker/MessageMap.h b/cpp/src/qpid/broker/MessageMap.h
index a668450250..1f0481cb6b 100644
--- a/cpp/src/qpid/broker/MessageMap.h
+++ b/cpp/src/qpid/broker/MessageMap.h
@@ -6,7 +6,7 @@
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
+o * regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
@@ -50,6 +50,7 @@ class MessageMap : public Messages
virtual bool browse(const framing::SequenceNumber&, QueuedMessage&, bool);
bool consume(QueuedMessage&);
virtual bool push(const QueuedMessage& added, QueuedMessage& removed);
+ void setPosition(const framing::SequenceNumber&);
void foreach(Functor);
virtual void removeIf(Predicate);
diff --git a/cpp/src/qpid/broker/Messages.h b/cpp/src/qpid/broker/Messages.h
index 61e9fa110a..45f5e6cd81 100644
--- a/cpp/src/qpid/broker/Messages.h
+++ b/cpp/src/qpid/broker/Messages.h
@@ -21,6 +21,7 @@
* under the License.
*
*/
+#include "qpid/framing/SequenceNumber.h"
#include <boost/function.hpp>
namespace qpid {
@@ -101,14 +102,22 @@ class Messages
virtual void updateAcquired(const QueuedMessage&) { }
/**
+ * Set the position of the back of the queue. Next message enqueued will be n+1.
+ *@pre Any messages with seq > n must already be dequeued.
+ */
+ virtual void setPosition(const framing::SequenceNumber& /*n*/) = 0;
+
+ /**
* Apply, the functor to each message held
*/
+
virtual void foreach(Functor) = 0;
/**
* Remove every message held that for which the specified
* predicate returns true
*/
virtual void removeIf(Predicate) = 0;
+
private:
};
}} // namespace qpid::broker
diff --git a/cpp/src/qpid/broker/NameGenerator.h b/cpp/src/qpid/broker/NameGenerator.h
index 6ea25c9797..2e9f7febe2 100644
--- a/cpp/src/qpid/broker/NameGenerator.h
+++ b/cpp/src/qpid/broker/NameGenerator.h
@@ -32,6 +32,7 @@ namespace qpid {
NameGenerator(const std::string& base);
std::string generate();
};
+ const std::string QPID_NAME_PREFIX("qpid."); // reserved for private names
}
}
diff --git a/cpp/src/qpid/broker/Observers.h b/cpp/src/qpid/broker/Observers.h
new file mode 100644
index 0000000000..c62f75d6d0
--- /dev/null
+++ b/cpp/src/qpid/broker/Observers.h
@@ -0,0 +1,69 @@
+#ifndef QPID_BROKER_OBSERVERS_H
+#define QPID_BROKER_OBSERVERS_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/Mutex.h"
+#include <boost/shared_ptr.hpp>
+#include <vector>
+#include <algorithm>
+
+namespace qpid {
+namespace broker {
+
+/**
+ * Base class for collections of observers with thread-safe add/remove and traversal.
+ */
+template <class Observer>
+class Observers
+{
+ public:
+ void add(boost::shared_ptr<Observer> observer) {
+ sys::Mutex::ScopedLock l(lock);
+ observers.push_back(observer);
+ }
+
+ void remove(boost::shared_ptr<Observer> observer) {
+ sys::Mutex::ScopedLock l(lock);
+ typename List::iterator i = std::find(observers.begin(), observers.end(), observer);
+ observers.erase(i);
+ }
+
+ protected:
+ typedef std::vector<boost::shared_ptr<Observer> > List;
+
+ sys::Mutex lock;
+ List observers;
+
+ template <class F> void each(F f) {
+ List copy;
+ {
+ sys::Mutex::ScopedLock l(lock);
+ copy = observers;
+ }
+ std::for_each(copy.begin(), copy.end(), f);
+ }
+};
+
+}} // namespace qpid::broker
+
+#endif /*!QPID_BROKER_OBSERVERS_H*/
diff --git a/cpp/src/qpid/broker/PriorityQueue.cpp b/cpp/src/qpid/broker/PriorityQueue.cpp
index ab5ec7235a..9a0fead744 100644
--- a/cpp/src/qpid/broker/PriorityQueue.cpp
+++ b/cpp/src/qpid/broker/PriorityQueue.cpp
@@ -121,6 +121,10 @@ void PriorityQueue::updateAcquired(const QueuedMessage& acquired) {
fifo.updateAcquired(acquired);
}
+void PriorityQueue::setPosition(const framing::SequenceNumber& n) {
+ fifo.setPosition(n);
+}
+
void PriorityQueue::foreach(Functor f)
{
fifo.foreach(f);
diff --git a/cpp/src/qpid/broker/PriorityQueue.h b/cpp/src/qpid/broker/PriorityQueue.h
index 8628745db1..301367358b 100644
--- a/cpp/src/qpid/broker/PriorityQueue.h
+++ b/cpp/src/qpid/broker/PriorityQueue.h
@@ -52,6 +52,7 @@ class PriorityQueue : public Messages
bool consume(QueuedMessage&);
bool push(const QueuedMessage& added, QueuedMessage& removed);
void updateAcquired(const QueuedMessage& acquired);
+ void setPosition(const framing::SequenceNumber&);
void foreach(Functor);
void removeIf(Predicate);
diff --git a/cpp/src/qpid/broker/PrivateImplRef.h b/cpp/src/qpid/broker/PrivateImplRef.h
index 5932ab882b..d20c2f4608 100644
--- a/cpp/src/qpid/broker/PrivateImplRef.h
+++ b/cpp/src/qpid/broker/PrivateImplRef.h
@@ -88,15 +88,15 @@ template <class T> class PrivateImplRef {
/** Set the implementation pointer in a handle */
static void set(T& t, const intrusive_ptr& p) {
if (t.impl == p) return;
- if (t.impl) boost::intrusive_ptr_release(t.impl);
+ if (t.impl) intrusive_ptr_release(t.impl);
t.impl = p.get();
- if (t.impl) boost::intrusive_ptr_add_ref(t.impl);
+ if (t.impl) intrusive_ptr_add_ref(t.impl);
}
// Helper functions to implement the ctor, dtor, copy, assign
- static void ctor(T& t, Impl* p) { t.impl = p; if (p) boost::intrusive_ptr_add_ref(p); }
+ static void ctor(T& t, Impl* p) { t.impl = p; if (p) intrusive_ptr_add_ref(p); }
static void copy(T& t, const T& x) { if (&t == &x) return; t.impl = 0; assign(t, x); }
- static void dtor(T& t) { if(t.impl) boost::intrusive_ptr_release(t.impl); }
+ static void dtor(T& t) { if(t.impl) intrusive_ptr_release(t.impl); }
static T& assign(T& t, const T& x) { set(t, get(x)); return t;}
};
diff --git a/cpp/src/qpid/broker/Queue.cpp b/cpp/src/qpid/broker/Queue.cpp
index e7305c021d..d5267c78dc 100644
--- a/cpp/src/qpid/broker/Queue.cpp
+++ b/cpp/src/qpid/broker/Queue.cpp
@@ -49,6 +49,7 @@
#include "qpid/types/Variant.h"
#include "qmf/org/apache/qpid/broker/ArgsQueuePurge.h"
#include "qmf/org/apache/qpid/broker/ArgsQueueReroute.h"
+#include "qmf/org/apache/qpid/broker/EventQueueDelete.h"
#include <iostream>
#include <algorithm>
@@ -67,6 +68,7 @@ using qpid::management::ManagementAgent;
using qpid::management::ManagementObject;
using qpid::management::Manageable;
using qpid::management::Args;
+using std::string;
using std::for_each;
using std::mem_fun;
namespace _qmf = qmf::org::apache::qpid::broker;
@@ -176,7 +178,8 @@ Queue::Queue(const string& _name, bool _autodelete,
ManagementAgent* agent = broker->getManagementAgent();
if (agent != 0) {
- mgmtObject = new _qmf::Queue(agent, this, parent, _name, _store != 0, _autodelete, _owner != 0);
+ mgmtObject = new _qmf::Queue(agent, this, parent, _name, _store != 0, _autodelete);
+ mgmtObject->set_exclusive(_owner != 0);
agent->addObject(mgmtObject, 0, store != 0);
brokerMgmtObject = (qmf::org::apache::qpid::broker::Broker*) broker->GetManagementObject();
if (brokerMgmtObject)
@@ -587,21 +590,51 @@ QueuedMessage Queue::get(){
return msg;
}
-bool collect_if_expired(std::deque<QueuedMessage>& expired, QueuedMessage& message)
+namespace {
+bool collectIf(QueuedMessage& qm, Messages::Predicate predicate,
+ std::deque<QueuedMessage>& collection)
{
- if (message.payload->hasExpired()) {
- expired.push_back(message);
+ if (predicate(qm)) {
+ collection.push_back(qm);
return true;
} else {
return false;
}
}
+bool isExpired(const QueuedMessage& qm) { return qm.payload->hasExpired(); }
+} // namespace
+
+void Queue::dequeueIf(Messages::Predicate predicate,
+ std::deque<QueuedMessage>& dequeued)
+{
+ {
+ Mutex::ScopedLock locker(messageLock);
+ messages->removeIf(boost::bind(&collectIf, _1, predicate, boost::ref(dequeued)));
+ }
+ if (!dequeued.empty()) {
+ if (mgmtObject) {
+ mgmtObject->inc_acquires(dequeued.size());
+ if (brokerMgmtObject)
+ brokerMgmtObject->inc_acquires(dequeued.size());
+ }
+ for (std::deque<QueuedMessage>::const_iterator i = dequeued.begin();
+ i != dequeued.end(); ++i) {
+ {
+ // KAG: should be safe to retake lock after the removeIf, since
+ // no other thread can touch these messages after the removeIf() call
+ Mutex::ScopedLock locker(messageLock);
+ observeAcquire(*i, locker);
+ }
+ dequeue( 0, *i );
+ }
+ }
+}
+
/**
*@param lapse: time since the last purgeExpired
*/
-void Queue::purgeExpired(qpid::sys::Duration lapse)
-{
+void Queue::purgeExpired(sys::Duration lapse) {
//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.
@@ -609,37 +642,18 @@ void Queue::purgeExpired(qpid::sys::Duration lapse)
dequeueSincePurge -= count;
int seconds = int64_t(lapse)/qpid::sys::TIME_SEC;
if (seconds == 0 || count / seconds < 1) {
- std::deque<QueuedMessage> expired;
- {
- Mutex::ScopedLock locker(messageLock);
- messages->removeIf(boost::bind(&collect_if_expired, boost::ref(expired), _1));
- }
-
- if (!expired.empty()) {
+ std::deque<QueuedMessage> dequeued;
+ dequeueIf(boost::bind(&isExpired, _1), dequeued);
+ if (dequeued.size()) {
if (mgmtObject) {
- mgmtObject->inc_acquires(expired.size());
- mgmtObject->inc_discardsTtl(expired.size());
- if (brokerMgmtObject) {
- brokerMgmtObject->inc_acquires(expired.size());
- brokerMgmtObject->inc_discardsTtl(expired.size());
- }
- }
-
- for (std::deque<QueuedMessage>::const_iterator i = expired.begin();
- i != expired.end(); ++i) {
- {
- // KAG: should be safe to retake lock after the removeIf, since
- // no other thread can touch these messages after the removeIf() call
- Mutex::ScopedLock locker(messageLock);
- observeAcquire(*i, locker);
- }
- dequeue( 0, *i );
+ mgmtObject->inc_discardsTtl(dequeued.size());
+ if (brokerMgmtObject)
+ brokerMgmtObject->inc_discardsTtl(dequeued.size());
}
}
}
}
-
namespace {
// for use with purge/move below - collect messages that match a given filter
//
@@ -797,6 +811,7 @@ uint32_t Queue::purge(const uint32_t purge_request, boost::shared_ptr<Exchange>
// now reroute if necessary
if (dest.get()) {
assert(qmsg->payload);
+ qmsg->payload->clearTrace();
DeliverableMessage dmsg(qmsg->payload);
dest->routeWithAlternate(dmsg);
}
@@ -888,9 +903,10 @@ void Queue::push(boost::intrusive_ptr<Message>& msg, bool isRecovery){
if (mgmtObject) {
mgmtObject->inc_acquires();
mgmtObject->inc_discardsLvq();
- if (brokerMgmtObject)
+ if (brokerMgmtObject) {
brokerMgmtObject->inc_acquires();
brokerMgmtObject->inc_discardsLvq();
+ }
}
if (isRecovery) {
//can't issue new requests for the store until
@@ -1470,12 +1486,18 @@ boost::shared_ptr<Exchange> Queue::getAlternateExchange()
return alternateExchange;
}
-void tryAutoDeleteImpl(Broker& broker, Queue::shared_ptr queue)
+void tryAutoDeleteImpl(Broker& broker, Queue::shared_ptr queue, const std::string& connectionId, const std::string& userId)
{
if (broker.getQueues().destroyIf(queue->getName(),
boost::bind(boost::mem_fn(&Queue::canAutoDelete), queue))) {
QPID_LOG(debug, "Auto-deleting " << queue->getName());
queue->destroyed();
+
+ if (broker.getManagementAgent())
+ broker.getManagementAgent()->raiseEvent(_qmf::EventQueueDelete(connectionId, userId, queue->getName()));
+ QPID_LOG_CAT(debug, model, "Delete queue. name:" << queue->getName()
+ << " user:" << userId
+ << " rhost:" << connectionId );
}
}
@@ -1483,9 +1505,11 @@ struct AutoDeleteTask : qpid::sys::TimerTask
{
Broker& broker;
Queue::shared_ptr queue;
+ std::string connectionId;
+ std::string userId;
- AutoDeleteTask(Broker& b, Queue::shared_ptr q, AbsTime fireTime)
- : qpid::sys::TimerTask(fireTime, "DelayedAutoDeletion:"+q->getName()), broker(b), queue(q) {}
+ AutoDeleteTask(Broker& b, Queue::shared_ptr q, const std::string& cId, const std::string& uId, AbsTime fireTime)
+ : qpid::sys::TimerTask(fireTime, "DelayedAutoDeletion:"+q->getName()), broker(b), queue(q), connectionId(cId), userId(uId) {}
void fire()
{
@@ -1493,19 +1517,19 @@ struct AutoDeleteTask : qpid::sys::TimerTask
//created, but then became unused again before the task fired;
//in this case ignore this request as there will have already
//been a later task added
- tryAutoDeleteImpl(broker, queue);
+ tryAutoDeleteImpl(broker, queue, connectionId, userId);
}
};
-void Queue::tryAutoDelete(Broker& broker, Queue::shared_ptr queue)
+void Queue::tryAutoDelete(Broker& broker, Queue::shared_ptr queue, const std::string& connectionId, const std::string& userId)
{
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));
+ queue->autoDeleteTask = boost::intrusive_ptr<qpid::sys::TimerTask>(new AutoDeleteTask(broker, queue, connectionId, userId, time));
broker.getClusterTimer().add(queue->autoDeleteTask);
QPID_LOG(debug, "Timed auto-delete for " << queue->getName() << " initiated");
} else {
- tryAutoDeleteImpl(broker, queue);
+ tryAutoDeleteImpl(broker, queue, connectionId, userId);
}
}
@@ -1659,13 +1683,28 @@ void Queue::query(qpid::types::Variant::Map& results) const
if (allocator) allocator->query(results);
}
+namespace {
+struct After {
+ framing::SequenceNumber seq;
+ After(framing::SequenceNumber s) : seq(s) {}
+ bool operator()(const QueuedMessage& qm) { return qm.position > seq; }
+};
+} // namespace
+
+
void Queue::setPosition(SequenceNumber n) {
Mutex::ScopedLock locker(messageLock);
+ if (n < sequence) {
+ std::deque<QueuedMessage> dequeued;
+ dequeueIf(After(n), dequeued);
+ messages->setPosition(n);
+ }
sequence = n;
QPID_LOG(trace, "Set position to " << sequence << " on " << getName());
}
SequenceNumber Queue::getPosition() {
+ Mutex::ScopedLock locker(messageLock);
return sequence;
}
diff --git a/cpp/src/qpid/broker/Queue.h b/cpp/src/qpid/broker/Queue.h
index 9869a698c1..a31e0002ea 100644
--- a/cpp/src/qpid/broker/Queue.h
+++ b/cpp/src/qpid/broker/Queue.h
@@ -175,6 +175,7 @@ class Queue : public boost::enable_shared_from_this<Queue>,
void configureImpl(const qpid::framing::FieldTable& settings);
void checkNotDeleted(const Consumer::shared_ptr& c);
void notifyDeleted();
+ void dequeueIf(Messages::Predicate predicate, std::deque<QueuedMessage>& dequeued);
public:
@@ -343,7 +344,7 @@ class Queue : public boost::enable_shared_from_this<Queue>,
* exclusive owner
*/
static Queue::shared_ptr restore(QueueRegistry& queues, framing::Buffer& buffer);
- static void tryAutoDelete(Broker& broker, Queue::shared_ptr);
+ static void tryAutoDelete(Broker& broker, Queue::shared_ptr, const std::string& connectionId, const std::string& userId);
virtual void setExternalQueueStore(ExternalQueueStore* inst);
@@ -375,12 +376,21 @@ class Queue : public boost::enable_shared_from_this<Queue>,
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.
+ /**
+ * Set the sequence number for the back of the queue, the
+ * next message enqueued will be pos+1.
+ * If pos > getPosition() this creates a gap in the sequence numbers.
+ * if pos < getPosition() the back of the queue is reset to pos,
+ *
+ * The _caller_ must ensure that any messages after pos have been dequeued.
+ *
+ * Used by HA/cluster code for queue replication.
*/
QPID_BROKER_EXTERN void setPosition(framing::SequenceNumber pos);
- /** return current position sequence number for the next message on the queue.
+
+ /**
+ *@return sequence number for the back of the queue. The next message pushed
+ * will be at getPosition+1
*/
QPID_BROKER_EXTERN framing::SequenceNumber getPosition();
QPID_BROKER_EXTERN void addObserver(boost::shared_ptr<QueueObserver>);
diff --git a/cpp/src/qpid/broker/QueueFlowLimit.cpp b/cpp/src/qpid/broker/QueueFlowLimit.cpp
index f15bb45c01..14fe5f4022 100644
--- a/cpp/src/qpid/broker/QueueFlowLimit.cpp
+++ b/cpp/src/qpid/broker/QueueFlowLimit.cpp
@@ -75,8 +75,8 @@ namespace {
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>());
+ } else if (v->convertsTo<std::string>()) {
+ std::string s(v->get<std::string>());
QPID_LOG(debug, "Got string value for " << key << ": " << s);
std::istringstream convert(s);
if (convert >> result && result >= 0) return result;
diff --git a/cpp/src/qpid/broker/QueuePolicy.cpp b/cpp/src/qpid/broker/QueuePolicy.cpp
index d5b4c1ae86..3978420f4e 100644
--- a/cpp/src/qpid/broker/QueuePolicy.cpp
+++ b/cpp/src/qpid/broker/QueuePolicy.cpp
@@ -133,8 +133,8 @@ T getCapacity(const FieldTable& settings, const std::string& key, T defaultValue
result = v->get<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>());
+ } else if (v->convertsTo<std::string>()) {
+ std::string s(v->get<std::string>());
QPID_LOG(debug, "Got string value for " << key << ": " << s);
std::istringstream convert(s);
if (convert >> result && result >= 0 && convert.eof()) return result;
diff --git a/cpp/src/qpid/broker/QueueRegistry.cpp b/cpp/src/qpid/broker/QueueRegistry.cpp
index 236d5ae34c..1401356444 100644
--- a/cpp/src/qpid/broker/QueueRegistry.cpp
+++ b/cpp/src/qpid/broker/QueueRegistry.cpp
@@ -18,6 +18,7 @@
* under the License.
*
*/
+#include "qpid/broker/Broker.h"
#include "qpid/broker/Queue.h"
#include "qpid/broker/QueueRegistry.h"
#include "qpid/broker/QueueEvents.h"
@@ -46,40 +47,49 @@ QueueRegistry::declare(const string& declareName, bool durable,
definition from persistente
record*/)
{
- RWlock::ScopedWlock locker(lock);
- string name = declareName.empty() ? generateName() : declareName;
- assert(!name.empty());
- QueueMap::iterator i = queues.find(name);
+ Queue::shared_ptr queue;
+ std::pair<Queue::shared_ptr, bool> result;
+ {
+ RWlock::ScopedWlock locker(lock);
+ string name = declareName.empty() ? generateName() : declareName;
+ assert(!name.empty());
+ QueueMap::iterator i = queues.find(name);
- 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);
+ if (i == queues.end()) {
+ queue.reset(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();
+ result = std::pair<Queue::shared_ptr, bool>(queue, true);
} else {
- //i.e. recovering a queue for which we already have a persistent record
- queue->configure(arguments);
+ result = std::pair<Queue::shared_ptr, bool>(i->second, false);
}
- queues[name] = queue;
- if (lastNode) queue->setLastNodeFailure();
-
- return std::pair<Queue::shared_ptr, bool>(queue, true);
- } else {
- return std::pair<Queue::shared_ptr, bool>(i->second, false);
}
+ if (broker && queue) broker->getConfigurationObservers().queueCreate(queue);
+ return result;
}
-void QueueRegistry::destroyLH (const string& name){
- queues.erase(name);
-}
-
-void QueueRegistry::destroy (const string& name){
- RWlock::ScopedWlock locker(lock);
- destroyLH (name);
+void QueueRegistry::destroy(const string& name) {
+ Queue::shared_ptr q;
+ {
+ qpid::sys::RWlock::ScopedWlock locker(lock);
+ QueueMap::iterator i = queues.find(name);
+ if (i != queues.end()) {
+ Queue::shared_ptr q = i->second;
+ queues.erase(i);
+ }
+ }
+ if (broker && q) broker->getConfigurationObservers().queueDestroy(q);
}
Queue::shared_ptr QueueRegistry::find(const string& name){
diff --git a/cpp/src/qpid/broker/QueueRegistry.h b/cpp/src/qpid/broker/QueueRegistry.h
index f724e6b10c..a354513c5f 100644
--- a/cpp/src/qpid/broker/QueueRegistry.h
+++ b/cpp/src/qpid/broker/QueueRegistry.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
@@ -61,7 +61,7 @@ class QueueRegistry {
QPID_BROKER_EXTERN std::pair<boost::shared_ptr<Queue>, bool> declare(
const std::string& name,
bool durable = false,
- bool autodelete = false,
+ bool autodelete = false,
const OwnershipToken* owner = 0,
boost::shared_ptr<Exchange> alternateExchange = boost::shared_ptr<Exchange>(),
const qpid::framing::FieldTable& args = framing::FieldTable(),
@@ -82,9 +82,8 @@ class QueueRegistry {
QPID_BROKER_EXTERN void destroy(const std::string& name);
template <class Test> bool destroyIf(const std::string& name, Test test)
{
- qpid::sys::RWlock::ScopedWlock locker(lock);
if (test()) {
- destroyLH (name);
+ destroy(name);
return true;
} else {
return false;
@@ -127,13 +126,13 @@ class QueueRegistry {
for (QueueMap::const_iterator i = queues.begin(); i != queues.end(); ++i)
f(i->second);
}
-
+
/**
* Change queue mode when cluster size drops to 1 node, expands again
* in practice allows flow queue to disk when last name to be exectuted
*/
void updateQueueClusterState(bool lastNode);
-
+
private:
typedef std::map<std::string, boost::shared_ptr<Queue> > QueueMap;
QueueMap queues;
@@ -144,12 +143,9 @@ private:
management::Manageable* parent;
bool lastNode; //used to set mode on queue declare
Broker* broker;
-
- //destroy impl that assumes lock is already held:
- void destroyLH (const std::string& name);
};
-
+
}} // namespace qpid::broker
diff --git a/cpp/src/qpid/broker/RecoveryManagerImpl.cpp b/cpp/src/qpid/broker/RecoveryManagerImpl.cpp
index d08409695e..858535637a 100644
--- a/cpp/src/qpid/broker/RecoveryManagerImpl.cpp
+++ b/cpp/src/qpid/broker/RecoveryManagerImpl.cpp
@@ -144,11 +144,13 @@ RecoverableTransaction::shared_ptr RecoveryManagerImpl::recoverTransaction(const
RecoverableConfig::shared_ptr RecoveryManagerImpl::recoverConfig(framing::Buffer& buffer)
{
string kind;
-
+ uint32_t p = buffer.getPosition();
buffer.getShortString (kind);
- if (kind == "link")
+ buffer.setPosition(p);
+
+ if (Link::isEncodedLink(kind))
return RecoverableConfig::shared_ptr(new RecoverableConfigImpl(Link::decode (links, buffer)));
- else if (kind == "bridge")
+ else if (Bridge::isEncodedBridge(kind))
return RecoverableConfig::shared_ptr(new RecoverableConfigImpl(Bridge::decode (links, buffer)));
return RecoverableConfig::shared_ptr(); // TODO: raise an exception instead
diff --git a/cpp/src/qpid/broker/SaslAuthenticator.cpp b/cpp/src/qpid/broker/SaslAuthenticator.cpp
index 80fa5e1c0e..2d7c820b63 100644
--- a/cpp/src/qpid/broker/SaslAuthenticator.cpp
+++ b/cpp/src/qpid/broker/SaslAuthenticator.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,6 +23,7 @@
# include "config.h"
#endif
+#include "qpid/broker/AclModule.h"
#include "qpid/broker/Connection.h"
#include "qpid/log/Statement.h"
#include "qpid/framing/reply_exceptions.h"
@@ -37,6 +38,7 @@
using qpid::sys::cyrus::CyrusSecurityLayer;
#endif
+using std::string;
using namespace qpid::framing;
using qpid::sys::SecurityLayer;
using qpid::sys::SecuritySettings;
@@ -164,13 +166,17 @@ void SaslAuthenticator::fini(void)
#endif
-std::auto_ptr<SaslAuthenticator> SaslAuthenticator::createAuthenticator(Connection& c, bool isShadow )
+std::auto_ptr<SaslAuthenticator> SaslAuthenticator::createAuthenticator(Connection& c )
{
if (c.getBroker().getOptions().auth) {
- if ( isShadow )
- return std::auto_ptr<SaslAuthenticator>(new NullAuthenticator(c, c.getBroker().getOptions().requireEncrypted));
- else
- return std::auto_ptr<SaslAuthenticator>(new CyrusAuthenticator(c, c.getBroker().getOptions().requireEncrypted));
+ // The cluster creates non-authenticated connections for internal shadow connections
+ // that are never connected to an external client.
+ if ( !c.isAuthenticated() )
+ return std::auto_ptr<SaslAuthenticator>(
+ new NullAuthenticator(c, c.getBroker().getOptions().requireEncrypted));
+ else
+ return std::auto_ptr<SaslAuthenticator>(
+ new CyrusAuthenticator(c, c.getBroker().getOptions().requireEncrypted));
} else {
QPID_LOG(debug, "SASL: No Authentication Performed");
return std::auto_ptr<SaslAuthenticator>(new NullAuthenticator(c, c.getBroker().getOptions().requireEncrypted));
@@ -178,7 +184,7 @@ std::auto_ptr<SaslAuthenticator> SaslAuthenticator::createAuthenticator(Connecti
}
-NullAuthenticator::NullAuthenticator(Connection& c, bool e) : connection(c), client(c.getOutput()),
+NullAuthenticator::NullAuthenticator(Connection& c, bool e) : connection(c), client(c.getOutput()),
realm(c.getBroker().getOptions().realm), encrypt(e) {}
NullAuthenticator::~NullAuthenticator() {}
@@ -214,7 +220,7 @@ void NullAuthenticator::start(const string& mechanism, const string* response)
} else if (i != string::npos) {
//authorization id is first null delimited field
uid = response->substr(0, i);
- }//else not a valid SASL PLAIN response, throw error?
+ }//else not a valid SASL PLAIN response, throw error?
if (!uid.empty()) {
//append realm if it has not already been added
i = uid.find(realm);
@@ -226,7 +232,12 @@ void NullAuthenticator::start(const string& mechanism, const string* response)
}
} else {
connection.setUserId("anonymous");
- }
+ }
+ AclModule* acl = connection.getBroker().getAcl();
+ if (acl && !acl->approveConnection(connection))
+ {
+ throw ConnectionForcedException("User connection denied by configured limit");
+ }
client.tune(framing::CHANNEL_MAX, connection.getFrameMax(), 0, connection.getHeartbeatMax());
}
@@ -240,7 +251,7 @@ std::auto_ptr<SecurityLayer> NullAuthenticator::getSecurityLayer(uint16_t)
#if HAVE_SASL
-CyrusAuthenticator::CyrusAuthenticator(Connection& c, bool _encrypt) :
+CyrusAuthenticator::CyrusAuthenticator(Connection& c, bool _encrypt) :
sasl_conn(0), connection(c), client(c.getOutput()), encrypt(_encrypt)
{
init();
@@ -271,17 +282,17 @@ void CyrusAuthenticator::init()
NULL, /* Callbacks */
0, /* Connection flags */
&sasl_conn);
-
+
if (SASL_OK != code) {
QPID_LOG(error, "SASL: Connection creation failed: [" << code << "] " << sasl_errdetail(sasl_conn));
-
+
// TODO: Change this to an exception signaling
// server error, when one is available
throw ConnectionForcedException("Unable to perform authentication");
}
sasl_security_properties_t secprops;
-
+
//TODO: should the actual SSF values be configurable here?
secprops.min_ssf = encrypt ? 10: 0;
secprops.max_ssf = 256;
@@ -319,14 +330,14 @@ void CyrusAuthenticator::init()
secprops.property_values = 0;
secprops.security_flags = 0; /* or SASL_SEC_NOANONYMOUS etc as appropriate */
/*
- * The nodict flag restricts SASL authentication mechanisms
- * to those that are not susceptible to dictionary attacks.
- * They are:
+ * The nodict flag restricts SASL authentication mechanisms
+ * to those that are not susceptible to dictionary attacks.
+ * They are:
* SRP
* PASSDSS-3DES-1
* EXTERNAL
*/
- if (external.nodict) secprops.security_flags |= SASL_SEC_NODICTIONARY;
+ if (external.nodict) secprops.security_flags |= SASL_SEC_NODICTIONARY;
int result = sasl_setprop(sasl_conn, SASL_SEC_PROPS, &secprops);
if (result != SASL_OK) {
throw framing::InternalErrorException(QPID_MSG("SASL error: " << result));
@@ -371,10 +382,10 @@ void CyrusAuthenticator::getMechanisms(Array& mechanisms)
"", separator, "",
&list, &list_len,
&count);
-
+
if (SASL_OK != code) {
QPID_LOG(info, "SASL: Mechanism listing failed: " << sasl_errdetail(sasl_conn));
-
+
// TODO: Change this to an exception signaling
// server error, when one is available
throw ConnectionForcedException("Mechanism listing failed");
@@ -382,17 +393,17 @@ void CyrusAuthenticator::getMechanisms(Array& mechanisms)
string mechanism;
unsigned int start;
unsigned int end;
-
+
QPID_LOG(info, "SASL: Mechanism list: " << list);
-
+
end = 0;
do {
start = end;
-
+
// Seek to end of next mechanism
while (end < list_len && separator[0] != list[end])
end++;
-
+
// Record the mechanism
mechanisms.add(boost::shared_ptr<FieldValue>(new Str16Value(string(list, start, end - start))));
end++;
@@ -404,20 +415,20 @@ 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);
int code = sasl_server_start(sasl_conn,
mechanism.c_str(),
(response ? response->c_str() : 0), (response ? response->size() : 0),
&challenge, &challenge_len);
-
+
processAuthenticationStep(code, challenge, challenge_len);
qmf::org::apache::qpid::broker::Connection* cnxMgmt = connection.getMgmtObject();
- if ( cnxMgmt )
+ if ( cnxMgmt )
cnxMgmt->set_saslMechanism(mechanism);
}
-
+
void CyrusAuthenticator::step(const string& response)
{
const char *challenge;
@@ -439,10 +450,17 @@ void CyrusAuthenticator::processAuthenticationStep(int code, const char *challen
// authentication failure, when one is available
throw ConnectionForcedException("Authenticated username unavailable");
}
- QPID_LOG(info, connection.getMgmtId() << " SASL: Authentication succeeded for: " << uid);
connection.setUserId(uid);
+ AclModule* acl = connection.getBroker().getAcl();
+ if (acl && !acl->approveConnection(connection))
+ {
+ throw ConnectionForcedException("User connection denied by configured limit");
+ }
+
+ QPID_LOG(info, connection.getMgmtId() << " SASL: Authentication succeeded for: " << uid);
+
client.tune(framing::CHANNEL_MAX, connection.getFrameMax(), 0, connection.getHeartbeatMax());
} else if (SASL_CONTINUE == code) {
string challenge_str(challenge, challenge_len);
@@ -490,7 +508,7 @@ std::auto_ptr<SecurityLayer> CyrusAuthenticator::getSecurityLayer(uint16_t maxFr
securityLayer = std::auto_ptr<SecurityLayer>(new CyrusSecurityLayer(sasl_conn, maxFrameSize));
}
qmf::org::apache::qpid::broker::Connection* cnxMgmt = connection.getMgmtObject();
- if ( cnxMgmt )
+ 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..e5ecc9f6ec 100644
--- a/cpp/src/qpid/broker/SaslAuthenticator.h
+++ b/cpp/src/qpid/broker/SaslAuthenticator.h
@@ -54,7 +54,7 @@ public:
static void init(const std::string& saslName, std::string const & saslConfigPath );
static void fini(void);
- static std::auto_ptr<SaslAuthenticator> createAuthenticator(Connection& connection, bool isShadow);
+ static std::auto_ptr<SaslAuthenticator> createAuthenticator(Connection& connection);
virtual void callUserIdCallbacks() { }
};
diff --git a/cpp/src/qpid/broker/SecureConnectionFactory.cpp b/cpp/src/qpid/broker/SecureConnectionFactory.cpp
index 754b443c22..757f6efc59 100644
--- a/cpp/src/qpid/broker/SecureConnectionFactory.cpp
+++ b/cpp/src/qpid/broker/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
@@ -41,11 +41,6 @@ SecureConnectionFactory::SecureConnectionFactory(Broker& b) : broker(b) {}
sys::ConnectionCodec*
SecureConnectionFactory::create(ProtocolVersion v, sys::OutputControl& out, const std::string& id,
const SecuritySettings& external) {
- if (broker.getConnectionCounter().allowConnection())
- {
- QPID_LOG(error, "Client max connection count limit exceeded: " << broker.getOptions().maxConnections << " connection refused");
- return 0;
- }
if (v == ProtocolVersion(0, 10)) {
SecureConnectionPtr sc(new SecureConnection());
CodecPtr c(new amqp_0_10::Connection(out, id, false));
@@ -71,5 +66,5 @@ SecureConnectionFactory::create(sys::OutputControl& out, const std::string& id,
return sc.release();
}
-
+
}} // namespace qpid::broker
diff --git a/cpp/src/qpid/broker/SemanticState.cpp b/cpp/src/qpid/broker/SemanticState.cpp
index 64924bdd4c..9a84db547c 100644
--- a/cpp/src/qpid/broker/SemanticState.cpp
+++ b/cpp/src/qpid/broker/SemanticState.cpp
@@ -72,7 +72,8 @@ SemanticState::SemanticState(DeliveryAdapter& da, SessionContext& ss)
dtxSelected(false),
authMsg(getSession().getBroker().getOptions().auth && !getSession().getConnection().isUserProxyAuth()),
userID(getSession().getConnection().getUserId()),
- closeComplete(false)
+ closeComplete(false),
+ connectionId(getSession().getConnection().getUrl())
{}
SemanticState::~SemanticState() {
@@ -142,6 +143,7 @@ bool SemanticState::cancel(const string& tag)
DeliveryRecords::iterator removed =
remove_if(unacked.begin(), unacked.end(), bind(&DeliveryRecord::isRedundant, _1));
unacked.erase(removed, unacked.end());
+ getSession().setUnackedCount(unacked.size());
return true;
} else {
return false;
@@ -270,6 +272,7 @@ void SemanticState::checkDtxTimeout()
void SemanticState::record(const DeliveryRecord& delivery)
{
unacked.push_back(delivery);
+ getSession().setUnackedCount(unacked.size());
}
const std::string QPID_SYNC_FREQUENCY("qpid.sync_frequency");
@@ -426,7 +429,7 @@ void SemanticState::cancel(ConsumerImpl::shared_ptr c)
if(queue) {
queue->cancel(c);
if (queue->canAutoDelete() && !queue->hasExclusiveOwner()) {
- Queue::tryAutoDelete(session.getBroker(), queue);
+ Queue::tryAutoDelete(session.getBroker(), queue, connectionId, userID);
}
}
c->cancel();
@@ -555,6 +558,7 @@ void SemanticState::recover(bool requeue)
//w.r.t id is lost
sort(unacked.begin(), unacked.end());
}
+ getSession().setUnackedCount(unacked.size());
}
void SemanticState::deliver(DeliveryRecord& msg, bool sync)
@@ -712,6 +716,7 @@ void SemanticState::release(DeliveryId first, DeliveryId last, bool setRedeliver
DeliveryRecords::iterator removed =
remove_if(range.start, range.end, bind(&DeliveryRecord::isRedundant, _1));
unacked.erase(removed, range.end);
+ getSession().setUnackedCount(unacked.size());
}
void SemanticState::reject(DeliveryId first, DeliveryId last)
@@ -723,6 +728,7 @@ void SemanticState::reject(DeliveryId first, DeliveryId last)
if (i->isRedundant()) i = unacked.erase(i);
else i++;
}
+ getSession().setUnackedCount(unacked.size());
}
bool SemanticState::ConsumerImpl::doOutput()
@@ -810,6 +816,7 @@ void SemanticState::accepted(const SequenceSet& commands) {
(TransactionContext*) 0)));
unacked.erase(removed, unacked.end());
}
+ getSession().setUnackedCount(unacked.size());
}
void SemanticState::completed(const SequenceSet& commands) {
@@ -819,6 +826,7 @@ void SemanticState::completed(const SequenceSet& commands) {
bind(&SemanticState::complete, this, _1)));
unacked.erase(removed, unacked.end());
requestDispatch();
+ getSession().setUnackedCount(unacked.size());
}
void SemanticState::attached()
diff --git a/cpp/src/qpid/broker/SemanticState.h b/cpp/src/qpid/broker/SemanticState.h
index e5e1d2da16..15928ce599 100644
--- a/cpp/src/qpid/broker/SemanticState.h
+++ b/cpp/src/qpid/broker/SemanticState.h
@@ -146,6 +146,8 @@ class SemanticState : private boost::noncopyable {
std::string getResumeId() const { return resumeId; };
const std::string& getTag() const { return tag; }
uint64_t getResumeTtl() const { return resumeTtl; }
+ uint32_t getDeliveryCount() const { return deliveryCount; }
+ void setDeliveryCount(uint32_t _deliveryCount) { deliveryCount = _deliveryCount; }
const framing::FieldTable& getArguments() const { return arguments; }
SemanticState& getParent() { return *parent; }
@@ -180,6 +182,8 @@ class SemanticState : private boost::noncopyable {
const bool authMsg;
const std::string userID;
bool closeComplete;
+ //needed for queue delete events in auto-delete:
+ const std::string connectionId;
void route(boost::intrusive_ptr<Message> msg, Deliverable& strategy);
void checkDtxTimeout();
diff --git a/cpp/src/qpid/broker/SessionAdapter.cpp b/cpp/src/qpid/broker/SessionAdapter.cpp
index 78f2e43ce0..ae994a6bd5 100644
--- a/cpp/src/qpid/broker/SessionAdapter.cpp
+++ b/cpp/src/qpid/broker/SessionAdapter.cpp
@@ -41,6 +41,8 @@
namespace qpid {
namespace broker {
+using std::string;
+
using namespace qpid;
using namespace qpid::framing;
using namespace qpid::framing::dtx;
@@ -107,6 +109,12 @@ void SessionAdapter::ExchangeHandlerImpl::declare(const string& exchange, const
false,
ManagementAgent::toMap(args),
"existing"));
+ QPID_LOG_CAT(debug, model, "Create exchange. name:" << exchange
+ << " user:" << getConnection().getUserId()
+ << " rhost:" << getConnection().getUrl()
+ << " type:" << type
+ << " alternateExchange:" << alternateExchange
+ << " durable:" << (durable ? "T" : "F"));
}
}catch(UnknownExchangeTypeException& /*e*/){
throw NotFoundException(QPID_MSG("Exchange type not implemented: " << type));
@@ -204,7 +212,10 @@ ExchangeBoundResult SessionAdapter::ExchangeHandlerImpl::bound(const std::string
}
}
-SessionAdapter::QueueHandlerImpl::QueueHandlerImpl(SemanticState& session) : HandlerHelper(session), broker(getBroker())
+SessionAdapter::QueueHandlerImpl::QueueHandlerImpl(SemanticState& session)
+ : HandlerHelper(session), broker(getBroker()),
+ //record connection id and userid for deleting exclsuive queues after session has ended:
+ connectionId(getConnection().getUrl()), userId(getConnection().getUserId())
{}
@@ -223,7 +234,7 @@ void SessionAdapter::QueueHandlerImpl::destroyExclusiveQueues()
Queue::shared_ptr q(exclusiveQueues.front());
q->releaseExclusiveOwnership();
if (q->canAutoDelete()) {
- Queue::tryAutoDelete(broker, q);
+ Queue::tryAutoDelete(broker, q, connectionId, userId);
}
exclusiveQueues.erase(exclusiveQueues.begin());
}
@@ -307,6 +318,14 @@ void SessionAdapter::QueueHandlerImpl::declare(const string& name, const string&
agent->raiseEvent(_qmf::EventQueueDeclare(getConnection().getUrl(), getConnection().getUserId(),
name, durable, exclusive, autoDelete, alternateExchange, ManagementAgent::toMap(arguments),
"existing"));
+ QPID_LOG_CAT(debug, model, "Create queue. name:" << name
+ << " user:" << getConnection().getUserId()
+ << " rhost:" << getConnection().getUrl()
+ << " durable:" << (durable ? "T" : "F")
+ << " exclusive:" << (exclusive ? "T" : "F")
+ << " autodelete:" << (autoDelete ? "T" : "F")
+ << " alternateExchange:" << alternateExchange
+ );
}
}
@@ -411,6 +430,12 @@ SessionAdapter::MessageHandlerImpl::subscribe(const string& queueName,
if (agent)
agent->raiseEvent(_qmf::EventSubscribe(getConnection().getUrl(), getConnection().getUserId(),
queueName, destination, exclusive, ManagementAgent::toMap(arguments)));
+ QPID_LOG_CAT(debug, model, "Create subscription. queue:" << queueName
+ << " destination:" << destination
+ << " user:" << getConnection().getUserId()
+ << " rhost:" << getConnection().getUrl()
+ << " exclusive:" << (exclusive ? "T" : "F")
+ );
}
void
@@ -423,6 +448,9 @@ SessionAdapter::MessageHandlerImpl::cancel(const string& destination )
ManagementAgent* agent = getBroker().getManagementAgent();
if (agent)
agent->raiseEvent(_qmf::EventUnsubscribe(getConnection().getUrl(), getConnection().getUserId(), destination));
+ QPID_LOG_CAT(debug, model, "Delete subscription. destination:" << destination
+ << " user:" << getConnection().getUserId()
+ << " rhost:" << getConnection().getUrl() );
}
void
diff --git a/cpp/src/qpid/broker/SessionAdapter.h b/cpp/src/qpid/broker/SessionAdapter.h
index bc056538b1..3cc745f96c 100644
--- a/cpp/src/qpid/broker/SessionAdapter.h
+++ b/cpp/src/qpid/broker/SessionAdapter.h
@@ -121,6 +121,9 @@ class Queue;
{
Broker& broker;
std::vector< boost::shared_ptr<Queue> > exclusiveQueues;
+ //connectionId and userId are needed for queue-delete events for auto deleted, exclusive queues
+ std::string connectionId;
+ std::string userId;
public:
QueueHandlerImpl(SemanticState& session);
diff --git a/cpp/src/qpid/broker/SessionContext.h b/cpp/src/qpid/broker/SessionContext.h
index 253ce8dcf2..ee98da1878 100644
--- a/cpp/src/qpid/broker/SessionContext.h
+++ b/cpp/src/qpid/broker/SessionContext.h
@@ -47,6 +47,7 @@ class SessionContext : public OwnershipToken, public sys::OutputControl
virtual uint16_t getChannel() const = 0;
virtual const SessionId& getSessionId() const = 0;
virtual void addPendingExecutionSync() = 0;
+ virtual void setUnackedCount(uint64_t) {}
};
}} // namespace qpid::broker
diff --git a/cpp/src/qpid/broker/SessionHandler.cpp b/cpp/src/qpid/broker/SessionHandler.cpp
index b58c7c01c5..23fa2ee0ca 100644
--- a/cpp/src/qpid/broker/SessionHandler.cpp
+++ b/cpp/src/qpid/broker/SessionHandler.cpp
@@ -35,23 +35,39 @@ SessionHandler::SessionHandler(Connection& c, ChannelId ch)
: amqp_0_10::SessionHandler(&c.getOutput(), ch),
connection(c),
proxy(out),
- clusterOrderProxy(c.getClusterOrderOutput() ? new SetChannelProxy(ch, c.getClusterOrderOutput()) : 0)
+ clusterOrderProxy(c.getClusterOrderOutput() ?
+ new SetChannelProxy(ch, c.getClusterOrderOutput()) : 0)
{}
SessionHandler::~SessionHandler() {}
-void SessionHandler::connectionException(framing::connection::CloseCode code, const std::string& msg) {
+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);
+ if (connection.getErrorListener())
+ connection.getErrorListener()->connectionError(msg);
+ if (errorListener)
+ errorListener->connectionException(code, msg);
connection.close(code, msg);
}
-void SessionHandler::channelException(framing::session::DetachCode, const std::string& msg) {
- if (connection.getErrorListener()) connection.getErrorListener()->sessionError(getChannel(), msg);
+void SessionHandler::channelException(
+ framing::session::DetachCode code, const std::string& msg)
+{
+ if (connection.getErrorListener())
+ connection.getErrorListener()->sessionError(getChannel(), msg);
+ if (errorListener)
+ errorListener->channelException(code, msg);
}
-void SessionHandler::executionException(framing::execution::ErrorCode, const std::string& msg) {
- if (connection.getErrorListener()) connection.getErrorListener()->sessionError(getChannel(), msg);
+void SessionHandler::executionException(
+ framing::execution::ErrorCode code, const std::string& msg)
+{
+ if (connection.getErrorListener())
+ connection.getErrorListener()->sessionError(getChannel(), msg);
+ if (errorListener)
+ errorListener->executionException(code, msg);
}
ConnectionState& SessionHandler::getConnection() { return connection; }
@@ -64,7 +80,7 @@ void SessionHandler::handleDetach() {
if (session.get())
connection.getBroker().getSessionManager().detach(session);
assert(!session.get());
- if (detachedCallback) detachedCallback();
+ if (errorListener) errorListener->detach();
connection.closeChannel(channel.get());
}
@@ -118,8 +134,4 @@ void SessionHandler::attached(const std::string& name)
}
}
-void SessionHandler::setDetachedCallback(boost::function<void()> cb) {
- detachedCallback = cb;
-}
-
}} // namespace qpid::broker
diff --git a/cpp/src/qpid/broker/SessionHandler.h b/cpp/src/qpid/broker/SessionHandler.h
index 4e2cfaa963..ab87cf41a4 100644
--- a/cpp/src/qpid/broker/SessionHandler.h
+++ b/cpp/src/qpid/broker/SessionHandler.h
@@ -25,7 +25,7 @@
#include "qpid/amqp_0_10/SessionHandler.h"
#include "qpid/broker/SessionHandler.h"
#include "qpid/framing/AMQP_ClientProxy.h"
-#include <boost/function.hpp>
+#include <boost/shared_ptr.hpp>
namespace qpid {
class SessionState;
@@ -43,6 +43,21 @@ class SessionState;
*/
class SessionHandler : public amqp_0_10::SessionHandler {
public:
+ class ErrorListener {
+ public:
+ virtual ~ErrorListener() {}
+ virtual void connectionException(
+ framing::connection::CloseCode code, const std::string& msg) = 0;
+ virtual void channelException(
+ framing::session::DetachCode, const std::string& msg) = 0;
+ virtual void executionException(
+ framing::execution::ErrorCode, const std::string& msg) = 0;
+ /** Called when it is safe to delete the ErrorListener. */
+ virtual void detach() = 0;
+ };
+
+ /**
+ *@param e must not be deleted until ErrorListener::detach has been called */
SessionHandler(Connection&, framing::ChannelId);
~SessionHandler();
@@ -71,7 +86,7 @@ class SessionHandler : public amqp_0_10::SessionHandler {
void attached(const std::string& name);//used by 'pushing' inter-broker bridges
void attachAs(const std::string& name);//used by 'pulling' inter-broker bridges
- void setDetachedCallback(boost::function<void()> cb);
+ void setErrorListener(boost::shared_ptr<ErrorListener> e) { errorListener = e; }
protected:
virtual void setState(const std::string& sessionName, bool force);
@@ -94,7 +109,7 @@ class SessionHandler : public amqp_0_10::SessionHandler {
framing::AMQP_ClientProxy proxy;
std::auto_ptr<SessionState> session;
std::auto_ptr<SetChannelProxy> clusterOrderProxy;
- boost::function<void ()> detachedCallback;
+ boost::shared_ptr<ErrorListener> errorListener;
};
}} // namespace qpid::broker
diff --git a/cpp/src/qpid/broker/SessionState.cpp b/cpp/src/qpid/broker/SessionState.cpp
index 99407bc3a6..cc02d9ec94 100644
--- a/cpp/src/qpid/broker/SessionState.cpp
+++ b/cpp/src/qpid/broker/SessionState.cpp
@@ -156,7 +156,7 @@ ManagementObject* SessionState::GetManagementObject (void) const
Manageable::status_t SessionState::ManagementMethod (uint32_t methodId,
Args& /*args*/,
- string& /*text*/)
+ std::string& /*text*/)
{
Manageable::status_t status = Manageable::STATUS_UNKNOWN_METHOD;
diff --git a/cpp/src/qpid/broker/SessionState.h b/cpp/src/qpid/broker/SessionState.h
index 8db232a2d6..a8ff7feff9 100644
--- a/cpp/src/qpid/broker/SessionState.h
+++ b/cpp/src/qpid/broker/SessionState.h
@@ -126,6 +126,11 @@ class SessionState : public qpid::SessionState,
// the SessionState of a received Execution.Sync command.
void addPendingExecutionSync();
+ void setUnackedCount(uint64_t count) {
+ if (mgmtObject)
+ mgmtObject->set_unackedMessages(count);
+ }
+
// Used to delay creation of management object for sessions
// belonging to inter-broker bridges
void addManagementObject();
diff --git a/cpp/src/qpid/broker/System.cpp b/cpp/src/qpid/broker/System.cpp
index 8cd2edda76..fa8df6406b 100644
--- a/cpp/src/qpid/broker/System.cpp
+++ b/cpp/src/qpid/broker/System.cpp
@@ -37,7 +37,6 @@ System::System (string _dataDir, Broker* broker) : mgmtObject(0)
if (agent != 0)
{
- framing::Uuid systemId;
if (_dataDir.empty ())
{
@@ -66,14 +65,13 @@ System::System (string _dataDir, Broker* broker) : mgmtObject(0)
}
mgmtObject = new _qmf::System(agent, this, types::Uuid(systemId.c_array()));
- std::string sysname, nodename, release, version, machine;
- qpid::sys::SystemInfo::getSystemId (sysname,
- nodename,
+ qpid::sys::SystemInfo::getSystemId (osName,
+ nodeName,
release,
version,
machine);
- mgmtObject->set_osName (sysname);
- mgmtObject->set_nodeName (nodename);
+ mgmtObject->set_osName (osName);
+ mgmtObject->set_nodeName (nodeName);
mgmtObject->set_release (release);
mgmtObject->set_version (version);
mgmtObject->set_machine (machine);
diff --git a/cpp/src/qpid/broker/System.h b/cpp/src/qpid/broker/System.h
index 0fc2c2bd88..6847c662ae 100644
--- a/cpp/src/qpid/broker/System.h
+++ b/cpp/src/qpid/broker/System.h
@@ -21,6 +21,7 @@
//
#include "qpid/management/Manageable.h"
+#include "qpid/framing/Uuid.h"
#include "qmf/org/apache/qpid/broker/System.h"
#include <boost/shared_ptr.hpp>
#include <string>
@@ -35,6 +36,8 @@ class System : public management::Manageable
private:
qmf::org::apache::qpid::broker::System* mgmtObject;
+ framing::Uuid systemId;
+ std::string osName, nodeName, release, version, machine;
public:
@@ -44,6 +47,20 @@ class System : public management::Manageable
management::ManagementObject* GetManagementObject (void) const
{ return mgmtObject; }
+
+
+ /** Persistent UUID assigned by the management system to this broker. */
+ framing::Uuid getSystemId() const { return systemId; }
+ /** Returns the OS name; e.g., GNU/Linux or Windows */
+ std::string getOsName() const { return osName; }
+ /** Returns the node name. Usually the same as the host name. */
+ std::string getNodeName() const { return nodeName; }
+ /** Returns the OS release identifier. */
+ std::string getRelease() const { return release; }
+ /** Returns the OS release version (kernel, build, sp, etc.) */
+ std::string getVersion() const { return version; }
+ /** Returns the hardware type. */
+ std::string getMachine() const { return machine; }
};
}}
diff --git a/cpp/src/qpid/broker/TopicExchange.cpp b/cpp/src/qpid/broker/TopicExchange.cpp
index dd3ec13019..c11389bb17 100644
--- a/cpp/src/qpid/broker/TopicExchange.cpp
+++ b/cpp/src/qpid/broker/TopicExchange.cpp
@@ -32,20 +32,8 @@ using namespace qpid::sys;
using namespace std;
namespace _qmf = qmf::org::apache::qpid::broker;
-
-// TODO aconway 2006-09-20: More efficient matching algorithm.
-// Areas for improvement:
-// - excessive string copying: should be 0 copy, match from original buffer.
-// - match/lookup: use descision tree or other more efficient structure.
-
-namespace
-{
-const std::string STAR("*");
-const std::string HASH("#");
-}
-
// iterator for federation ReOrigin bind operation
-class TopicExchange::ReOriginIter : public TopicExchange::BindingNode::TreeIterator {
+class TopicExchange::ReOriginIter : public BindingNode::TreeIterator {
public:
ReOriginIter() {};
~ReOriginIter() {};
@@ -61,7 +49,7 @@ public:
// match iterator used by route(): builds BindingList of all unique queues
// that match the routing key.
-class TopicExchange::BindingsFinderIter : public TopicExchange::BindingNode::TreeIterator {
+class TopicExchange::BindingsFinderIter : public BindingNode::TreeIterator {
public:
BindingsFinderIter(BindingList &bl) : b(bl) {};
~BindingsFinderIter() {};
@@ -85,7 +73,7 @@ public:
// Iterator to visit all bindings until a given queue is found
-class TopicExchange::QueueFinderIter : public TopicExchange::BindingNode::TreeIterator {
+class TopicExchange::QueueFinderIter : public BindingNode::TreeIterator {
public:
QueueFinderIter(Queue::shared_ptr queue) : queue(queue), found(false) {};
~QueueFinderIter() {};
@@ -107,58 +95,7 @@ public:
};
-// Iterate over a string of '.'-separated tokens.
-struct TopicExchange::TokenIterator {
- typedef pair<const char*,const char*> Token;
-
- TokenIterator(const char* b, const char* e) : end(e), token(make_pair(b, find(b,e,'.'))) {}
-
- TokenIterator(const string& key) : end(&key[0]+key.size()), token(make_pair(&key[0], find(&key[0],end,'.'))) {}
-
- bool finished() const { return !token.first; }
-
- void next() {
- if (token.second == end)
- token.first = token.second = 0;
- else {
- token.first=token.second+1;
- token.second=(find(token.first, end, '.'));
- }
- }
-
- void pop(string &top) {
- ptrdiff_t l = len();
- if (l) {
- top.assign(token.first, l);
- } else top.clear();
- next();
- }
-
- bool match1(char c) const {
- return token.second==token.first+1 && *token.first == c;
- }
-
- bool match(const Token& token2) const {
- ptrdiff_t l=len();
- return l == token2.second-token2.first &&
- strncmp(token.first, token2.first, l) == 0;
- }
-
- bool match(const string& str) const {
- ptrdiff_t l=len();
- return l == ptrdiff_t(str.size()) &&
- str.compare(0, l, token.first, l) == 0;
- }
-
- ptrdiff_t len() const { return token.second - token.first; }
-
-
- const char* end;
- Token token;
-};
-
-
-class TopicExchange::Normalizer : public TopicExchange::TokenIterator {
+class TopicExchange::Normalizer : public TokenIterator {
public:
Normalizer(string& p)
: TokenIterator(&p[0], &p[0]+p.size()), pattern(p)
@@ -230,7 +167,7 @@ bool TopicExchange::bind(Queue::shared_ptr queue, const string& routingKey, cons
if (args == 0 || fedOp.empty() || fedOp == fedOpBind) {
RWlock::ScopedWlock l(lock);
- BindingKey *bk = bindingTree.addBindingKey(routingPattern);
+ BindingKey *bk = bindingTree.add(routingPattern);
if (bk) {
Binding::vector& qv(bk->bindingVector);
Binding::vector::iterator q;
@@ -324,7 +261,7 @@ bool TopicExchange::deleteBinding(Queue::shared_ptr queue,
nBindings--;
if(qv.empty()) {
- bindingTree.removeBindingKey(routingKey);
+ bindingTree.remove(routingKey);
}
if (mgmtExchange != 0) {
mgmtExchange->dec_bindingCount();
@@ -340,7 +277,7 @@ bool TopicExchange::deleteBinding(Queue::shared_ptr queue,
TopicExchange::BindingKey *TopicExchange::getQueueBinding(Queue::shared_ptr queue, const string& pattern)
{
// Note well: lock held by caller....
- BindingKey *bk = bindingTree.getBindingKey(pattern); // Exact match against binding pattern
+ BindingKey *bk = bindingTree.get(pattern); // Exact match against binding pattern
if (!bk) return 0;
Binding::vector& qv(bk->bindingVector);
Binding::vector::iterator q;
@@ -385,7 +322,7 @@ bool TopicExchange::isBound(Queue::shared_ptr queue, const string* const routing
} else if (!routingKey && !queue) {
return nBindings > 0;
} else if (routingKey) {
- if (bindingTree.getBindingKey(*routingKey)) {
+ if (bindingTree.get(*routingKey)) {
return true;
}
} else {
@@ -400,294 +337,4 @@ TopicExchange::~TopicExchange() {}
const std::string TopicExchange::typeName("topic");
-//
-// class BindingNode
-//
-
-TopicExchange::BindingNode::~BindingNode()
-{
- childTokens.clear();
-}
-
-
-// Add a binding pattern to the tree. Return a pointer to the binding key
-// of the node that matches the binding pattern.
-TopicExchange::BindingKey*
-TopicExchange::BindingNode::addBindingKey(const std::string& normalizedRoute)
-{
- TokenIterator bKey(normalizedRoute);
- return addBindingKey(bKey, normalizedRoute);
-}
-
-
-// Return a pointer to the binding key of the leaf node that matches the binding pattern.
-TopicExchange::BindingKey*
-TopicExchange::BindingNode::getBindingKey(const std::string& normalizedRoute)
-{
- TokenIterator bKey(normalizedRoute);
- return getBindingKey(bKey);
-}
-
-
-// Delete the binding associated with the given route.
-void TopicExchange::BindingNode::removeBindingKey(const std::string& normalizedRoute)
-{
- TokenIterator bKey2(normalizedRoute);
- removeBindingKey(bKey2, normalizedRoute);
-}
-
-// visit each node in the tree. Note: all nodes are visited,
-// even non-leaf nodes (i.e. nodes without any bindings)
-bool TopicExchange::BindingNode::iterateAll(TopicExchange::BindingNode::TreeIterator& iter)
-{
- if (!iter.visit(*this)) return false;
-
- if (starChild && !starChild->iterateAll(iter)) return false;
-
- if (hashChild && !hashChild->iterateAll(iter)) return false;
-
- for (ChildMap::iterator ptr = childTokens.begin();
- ptr != childTokens.end(); ptr++) {
-
- if (!ptr->second->iterateAll(iter)) return false;
- }
-
- return true;
-}
-
-// applies iter against only matching nodes until iter returns false
-// Note Well: the iter may match against the same node more than once
-// if # wildcards are present!
-bool TopicExchange::BindingNode::iterateMatch(const std::string& routingKey, TreeIterator& iter)
-{
- TopicExchange::TokenIterator rKey(routingKey);
- return iterateMatch( rKey, iter );
-}
-
-
-// recurse over binding using token iterator.
-// Note well: bkey is modified!
-TopicExchange::BindingKey*
-TopicExchange::BindingNode::addBindingKey(TokenIterator &bKey,
- const string& fullPattern)
-{
- if (bKey.finished()) {
- // this node's binding
- if (routePattern.empty()) {
- routePattern = fullPattern;
- } else assert(routePattern == fullPattern);
-
- return &bindings;
-
- } else {
- // pop the topmost token & recurse...
-
- if (bKey.match(STAR)) {
- if (!starChild) {
- starChild.reset(new StarNode());
- }
- bKey.next();
- return starChild->addBindingKey(bKey, fullPattern);
-
- } else if (bKey.match(HASH)) {
- if (!hashChild) {
- hashChild.reset(new HashNode());
- }
- bKey.next();
- return hashChild->addBindingKey(bKey, fullPattern);
-
- } else {
- ChildMap::iterator ptr;
- std::string next_token;
- bKey.pop(next_token);
- ptr = childTokens.find(next_token);
- if (ptr != childTokens.end()) {
- return ptr->second->addBindingKey(bKey, fullPattern);
- } else {
- BindingNode::shared_ptr child(new BindingNode(next_token));
- childTokens[next_token] = child;
- return child->addBindingKey(bKey, fullPattern);
- }
- }
- }
-}
-
-
-// Remove a binding pattern from the tree. Return true if the current
-// node becomes a leaf without any bindings (therefore can be deleted).
-// Note Well: modifies parameter bKey's value!
-bool
-TopicExchange::BindingNode::removeBindingKey(TokenIterator &bKey,
- const string& fullPattern)
-{
- bool remove;
-
- if (!bKey.finished()) {
-
- if (bKey.match(STAR)) {
- bKey.next();
- if (starChild) {
- remove = starChild->removeBindingKey(bKey, fullPattern);
- if (remove) {
- starChild.reset();
- }
- }
- } else if (bKey.match(HASH)) {
- bKey.next();
- if (hashChild) {
- remove = hashChild->removeBindingKey(bKey, fullPattern);
- if (remove) {
- hashChild.reset();
- }
- }
- } else {
- ChildMap::iterator ptr;
- std::string next_token;
- bKey.pop(next_token);
- ptr = childTokens.find(next_token);
- if (ptr != childTokens.end()) {
- remove = ptr->second->removeBindingKey(bKey, fullPattern);
- if (remove) {
- childTokens.erase(ptr);
- }
- }
- }
- }
-
- // no bindings and no children == parent can delete this node.
- return getChildCount() == 0 && bindings.bindingVector.empty();
-}
-
-
-// find the binding key that matches the given binding pattern.
-// Note Well: modifies key parameter!
-TopicExchange::BindingKey*
-TopicExchange::BindingNode::getBindingKey(TokenIterator &key)
-{
- if (key.finished()) {
- return &bindings;
- }
-
- string next_token;
-
- key.pop(next_token);
-
- if (next_token == STAR) {
- if (starChild)
- return starChild->getBindingKey(key);
- } else if (next_token == HASH) {
- if (hashChild)
- return hashChild->getBindingKey(key);
- } else {
- ChildMap::iterator ptr;
- ptr = childTokens.find(next_token);
- if (ptr != childTokens.end()) {
- return ptr->second->getBindingKey(key);
- }
- }
-
- return 0;
-}
-
-
-
-// iterate over all nodes that match the given key. Note well: the set of nodes
-// that are visited includes matching non-leaf nodes.
-// Note well: parameter key is modified!
-bool TopicExchange::BindingNode::iterateMatch(TokenIterator& key, TreeIterator& iter)
-{
- // invariant: key has matched all previous tokens up to this node.
- if (key.finished()) {
- // exact match this node: visit if bound
- if (!bindings.bindingVector.empty())
- if (!iter.visit(*this)) return false;
- }
-
- // check remaining key against children, even if empty.
- return iterateMatchChildren(key, iter);
-}
-
-
-TopicExchange::StarNode::StarNode()
- : BindingNode(STAR) {}
-
-
-// See iterateMatch() above.
-// Special case: this node must verify a token is available (match exactly one).
-bool TopicExchange::StarNode::iterateMatch(TokenIterator& key, TreeIterator& iter)
-{
- // must match one token:
- if (key.finished())
- return true; // match failed, but continue iteration on siblings
-
- // pop the topmost token
- key.next();
-
- if (key.finished()) {
- // exact match this node: visit if bound
- if (!bindings.bindingVector.empty())
- if (!iter.visit(*this)) return false;
- }
-
- return iterateMatchChildren(key, iter);
-}
-
-
-TopicExchange::HashNode::HashNode()
- : BindingNode(HASH) {}
-
-
-// See iterateMatch() above.
-// Special case: can match zero or more tokens at the head of the key.
-bool TopicExchange::HashNode::iterateMatch(TokenIterator& key, TreeIterator& iter)
-{
- // consume each token and look for a match on the
- // remaining key.
- while (!key.finished()) {
- if (!iterateMatchChildren(key, iter)) return false;
- key.next();
- }
-
- if (!bindings.bindingVector.empty())
- return iter.visit(*this);
-
- return true;
-}
-
-
-// helper: iterate over current node's matching children
-bool
-TopicExchange::BindingNode::iterateMatchChildren(const TopicExchange::TokenIterator& key,
- TopicExchange::BindingNode::TreeIterator& iter)
-{
- // always try glob - it can match empty keys
- if (hashChild) {
- TokenIterator tmp(key);
- if (!hashChild->iterateMatch(tmp, iter))
- return false;
- }
-
- if (!key.finished()) {
-
- if (starChild) {
- TokenIterator tmp(key);
- if (!starChild->iterateMatch(tmp, iter))
- return false;
- }
-
- if (!childTokens.empty()) {
- TokenIterator newKey(key);
- std::string next_token;
- newKey.pop(next_token);
-
- ChildMap::iterator ptr = childTokens.find(next_token);
- if (ptr != childTokens.end()) {
- return ptr->second->iterateMatch(newKey, iter);
- }
- }
- }
-
- return true;
-}
-
}} // namespace qpid::broker
diff --git a/cpp/src/qpid/broker/TopicExchange.h b/cpp/src/qpid/broker/TopicExchange.h
index cc24e1411e..46871a1c6b 100644
--- a/cpp/src/qpid/broker/TopicExchange.h
+++ b/cpp/src/qpid/broker/TopicExchange.h
@@ -28,6 +28,7 @@
#include "qpid/framing/FieldTable.h"
#include "qpid/sys/Monitor.h"
#include "qpid/broker/Queue.h"
+#include "qpid/broker/TopicKeyNode.h"
namespace qpid {
@@ -35,7 +36,6 @@ namespace broker {
class TopicExchange : public virtual Exchange {
- struct TokenIterator;
class Normalizer;
struct BindingKey { // binding for this node
@@ -43,129 +43,44 @@ class TopicExchange : public virtual Exchange {
FedBinding fedBinding;
};
- // Binding database:
- // The dotted form of a binding key is broken up and stored in a directed tree graph.
- // Common binding prefix are merged. This allows the route match alogrithm to quickly
- // isolate those sub-trees that match a given routingKey.
- // For example, given the routes:
- // a.b.c.<...>
- // a.b.d.<...>
- // a.x.y.<...>
- // The resulting tree would be:
- // a-->b-->c-->...
- // | +-->d-->...
- // +-->x-->y-->...
- //
- class QPID_BROKER_CLASS_EXTERN BindingNode {
- public:
-
- typedef boost::shared_ptr<BindingNode> shared_ptr;
-
- // for database transversal (visit a node).
- class TreeIterator {
- public:
- TreeIterator() {};
- virtual ~TreeIterator() {};
- virtual bool visit(BindingNode& node) = 0;
- };
-
- BindingNode() {};
- BindingNode(const std::string& token) : token(token) {};
- QPID_BROKER_EXTERN virtual ~BindingNode();
-
- // add normalizedRoute to tree, return associated BindingKey
- QPID_BROKER_EXTERN BindingKey* addBindingKey(const std::string& normalizedRoute);
-
- // return BindingKey associated with normalizedRoute
- QPID_BROKER_EXTERN BindingKey* getBindingKey(const std::string& normalizedRoute);
-
- // remove BindingKey associated with normalizedRoute
- QPID_BROKER_EXTERN void removeBindingKey(const std::string& normalizedRoute);
-
- // applies iter against each node in tree until iter returns false
- QPID_BROKER_EXTERN bool iterateAll(TreeIterator& iter);
-
- // applies iter against only matching nodes until iter returns false
- QPID_BROKER_EXTERN bool iterateMatch(const std::string& routingKey, TreeIterator& iter);
-
- std::string routePattern; // normalized binding that matches this node
- BindingKey bindings; // for matches against this node
-
- protected:
-
- std::string token; // portion of pattern represented by this node
-
- // children
- typedef std::map<const std::string, BindingNode::shared_ptr> ChildMap;
- ChildMap childTokens;
- BindingNode::shared_ptr starChild; // "*" subtree
- BindingNode::shared_ptr hashChild; // "#" subtree
-
- unsigned int getChildCount() { return childTokens.size() +
- (starChild ? 1 : 0) + (hashChild ? 1 : 0); }
- BindingKey* addBindingKey(TokenIterator& bKey,
- const std::string& fullPattern);
- bool removeBindingKey(TokenIterator& bKey,
- const std::string& fullPattern);
- BindingKey* getBindingKey(TokenIterator& bKey);
- QPID_BROKER_EXTERN virtual bool iterateMatch(TokenIterator& rKey, TreeIterator& iter);
- bool iterateMatchChildren(const TokenIterator& key, TreeIterator& iter);
- };
-
- // Special case: ("*" token) Node in the tree for a match exactly one wildcard
- class StarNode : public BindingNode {
- public:
- StarNode();
- ~StarNode() {};
-
- protected:
- virtual bool iterateMatch(TokenIterator& key, TreeIterator& iter);
- };
+ typedef TopicKeyNode<BindingKey> BindingNode;
- // Special case: ("#" token) Node in the tree for a match zero or more
- class HashNode : public BindingNode {
- public:
- HashNode();
- ~HashNode() {};
+ BindingKey *getQueueBinding(Queue::shared_ptr queue, const std::string& pattern);
+ bool deleteBinding(Queue::shared_ptr queue,
+ const std::string& routingKey,
+ BindingKey *bk);
- protected:
- virtual bool iterateMatch(TokenIterator& key, TreeIterator& iter);
- };
+ class ReOriginIter;
+ class BindingsFinderIter;
+ class QueueFinderIter;
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;
+ bool cleared;
public:
- ClearCache(qpid::sys::RWlock* l, std::map<std::string, BindingList>* bc): cacheLock(l),
- bindingCache(bc),cleared(false) {};
+ 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;
- }
+ qpid::sys::RWlock::ScopedWlock l(*cacheLock);
+ if (!cleared) {
+ bindingCache->clear();
+ cleared =true;
+ }
};
~ClearCache(){
- clearCache();
+ clearCache();
};
};
- BindingKey *getQueueBinding(Queue::shared_ptr queue, const std::string& pattern);
- bool deleteBinding(Queue::shared_ptr queue,
- const std::string& routingKey,
- BindingKey *bk);
- class ReOriginIter;
- class BindingsFinderIter;
- class QueueFinderIter;
-
- public:
+public:
static const std::string typeName;
static QPID_BROKER_EXTERN std::string normalize(const std::string& pattern);
@@ -199,7 +114,6 @@ class TopicExchange : public virtual Exchange {
};
-
}
}
diff --git a/cpp/src/qpid/broker/TopicKeyNode.h b/cpp/src/qpid/broker/TopicKeyNode.h
new file mode 100644
index 0000000000..7671ed069d
--- /dev/null
+++ b/cpp/src/qpid/broker/TopicKeyNode.h
@@ -0,0 +1,371 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT 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 _QPID_BROKER_TOPIC_KEY_NODE_
+#define _QPID_BROKER_TOPIC_KEY_NODE_
+
+#include "qpid/broker/BrokerImportExport.h"
+#include <boost/shared_ptr.hpp>
+#include <map>
+#include <string>
+#include <string.h>
+
+
+namespace qpid {
+namespace broker {
+
+static const std::string STAR("*");
+static const std::string HASH("#");
+
+
+// Iterate over a string of '.'-separated tokens.
+struct TokenIterator {
+ typedef std::pair<const char*,const char*> Token;
+
+ TokenIterator(const char* b, const char* e) : end(e), token(std::make_pair(b, std::find(b,e,'.'))) {}
+
+ TokenIterator(const std::string& key) : end(&key[0]+key.size()), token(std::make_pair(&key[0], std::find(&key[0],end,'.'))) {}
+
+ bool finished() const { return !token.first; }
+
+ void next() {
+ if (token.second == end)
+ token.first = token.second = 0;
+ else {
+ token.first=token.second+1;
+ token.second=(std::find(token.first, end, '.'));
+ }
+ }
+
+ void pop(std::string &top) {
+ ptrdiff_t l = len();
+ if (l) {
+ top.assign(token.first, l);
+ } else top.clear();
+ next();
+ }
+
+ bool match1(char c) const {
+ return token.second==token.first+1 && *token.first == c;
+ }
+
+ bool match(const Token& token2) const {
+ ptrdiff_t l=len();
+ return l == token2.second-token2.first &&
+ strncmp(token.first, token2.first, l) == 0;
+ }
+
+ bool match(const std::string& str) const {
+ ptrdiff_t l=len();
+ return l == ptrdiff_t(str.size()) &&
+ str.compare(0, l, token.first, l) == 0;
+ }
+
+ ptrdiff_t len() const { return token.second - token.first; }
+
+
+ const char* end;
+ Token token;
+};
+
+
+// Binding database:
+// The dotted form of a binding key is broken up and stored in a directed tree graph.
+// Common binding prefix are merged. This allows the route match alogrithm to quickly
+// isolate those sub-trees that match a given routingKey.
+// For example, given the routes:
+// a.b.c.<...>
+// a.b.d.<...>
+// a.x.y.<...>
+// The resulting tree would be:
+// a-->b-->c-->...
+// | +-->d-->...
+// +-->x-->y-->...
+//
+template <class T>
+class QPID_BROKER_CLASS_EXTERN TopicKeyNode {
+
+ public:
+
+ typedef boost::shared_ptr<TopicKeyNode> shared_ptr;
+
+ // for database transversal (visit a node).
+ class TreeIterator {
+ public:
+ TreeIterator() {};
+ virtual ~TreeIterator() {};
+ virtual bool visit(TopicKeyNode& node) = 0;
+ };
+
+ TopicKeyNode() : isStar(false), isHash(false) {}
+ TopicKeyNode(const std::string& _t) : token(_t), isStar(_t == STAR), isHash(_t == HASH) {}
+ QPID_BROKER_EXTERN virtual ~TopicKeyNode() {
+ childTokens.clear();
+ }
+
+ // add normalizedRoute to tree, return associated T
+ QPID_BROKER_EXTERN T* add(const std::string& normalizedRoute) {
+ TokenIterator bKey(normalizedRoute);
+ return add(bKey, normalizedRoute);
+ }
+
+ // return T associated with normalizedRoute
+ QPID_BROKER_EXTERN T* get(const std::string& normalizedRoute) {
+ TokenIterator bKey(normalizedRoute);
+ return get(bKey);
+ }
+
+ // remove T associated with normalizedRoute
+ QPID_BROKER_EXTERN void remove(const std::string& normalizedRoute) {
+ TokenIterator bKey2(normalizedRoute);
+ remove(bKey2, normalizedRoute);
+ }
+
+ // applies iter against each node in tree until iter returns false
+ QPID_BROKER_EXTERN bool iterateAll(TreeIterator& iter) {
+ if (!iter.visit(*this)) return false;
+ if (starChild && !starChild->iterateAll(iter)) return false;
+ if (hashChild && !hashChild->iterateAll(iter)) return false;
+ for (typename ChildMap::iterator ptr = childTokens.begin();
+ ptr != childTokens.end(); ptr++) {
+ if (!ptr->second->iterateAll(iter)) return false;
+ }
+ return true;
+ }
+
+ // applies iter against only matching nodes until iter returns false
+ QPID_BROKER_EXTERN bool iterateMatch(const std::string& routingKey, TreeIterator& iter) {
+ TokenIterator rKey(routingKey);
+ return iterateMatch( rKey, iter );
+ }
+
+ std::string routePattern; // normalized binding that matches this node
+ T bindings; // for matches against this node
+
+ private:
+
+ std::string token; // portion of pattern represented by this node
+ bool isStar;
+ bool isHash;
+
+ // children
+ typedef std::map<const std::string, typename TopicKeyNode::shared_ptr> ChildMap;
+ ChildMap childTokens;
+ typename TopicKeyNode::shared_ptr starChild; // "*" subtree
+ typename TopicKeyNode::shared_ptr hashChild; // "#" subtree
+
+ unsigned int getChildCount() { return childTokens.size() +
+ (starChild ? 1 : 0) + (hashChild ? 1 : 0); }
+
+ T* add(TokenIterator& bKey, const std::string& fullPattern){
+ if (bKey.finished()) {
+ // this node's binding
+ if (routePattern.empty()) {
+ routePattern = fullPattern;
+ } else assert(routePattern == fullPattern);
+
+ return &bindings;
+
+ } else {
+ // pop the topmost token & recurse...
+
+ if (bKey.match(STAR)) {
+ if (!starChild) {
+ starChild.reset(new TopicKeyNode<T>(STAR));
+ }
+ bKey.next();
+ return starChild->add(bKey, fullPattern);
+
+ } else if (bKey.match(HASH)) {
+ if (!hashChild) {
+ hashChild.reset(new TopicKeyNode<T>(HASH));
+ }
+ bKey.next();
+ return hashChild->add(bKey, fullPattern);
+
+ } else {
+ typename ChildMap::iterator ptr;
+ std::string next_token;
+ bKey.pop(next_token);
+ ptr = childTokens.find(next_token);
+ if (ptr != childTokens.end()) {
+ return ptr->second->add(bKey, fullPattern);
+ } else {
+ typename TopicKeyNode::shared_ptr child(new TopicKeyNode<T>(next_token));
+ childTokens[next_token] = child;
+ return child->add(bKey, fullPattern);
+ }
+ }
+ }
+ }
+
+
+ bool remove(TokenIterator& bKey, const std::string& fullPattern) {
+ bool remove;
+ if (!bKey.finished()) {
+ if (bKey.match(STAR)) {
+ bKey.next();
+ if (starChild) {
+ remove = starChild->remove(bKey, fullPattern);
+ if (remove) {
+ starChild.reset();
+ }
+ }
+ } else if (bKey.match(HASH)) {
+ bKey.next();
+ if (hashChild) {
+ remove = hashChild->remove(bKey, fullPattern);
+ if (remove) {
+ hashChild.reset();
+ }
+ }
+ } else {
+ typename ChildMap::iterator ptr;
+ std::string next_token;
+ bKey.pop(next_token);
+ ptr = childTokens.find(next_token);
+ if (ptr != childTokens.end()) {
+ remove = ptr->second->remove(bKey, fullPattern);
+ if (remove) {
+ childTokens.erase(ptr);
+ }
+ }
+ }
+ }
+
+ // no bindings and no children == parent can delete this node.
+ return getChildCount() == 0 && bindings.bindingVector.empty();
+ }
+
+
+ T* get(TokenIterator& bKey) {
+ if (bKey.finished()) {
+ return &bindings;
+ }
+
+ std::string next_token;
+ bKey.pop(next_token);
+
+ if (next_token == STAR) {
+ if (starChild)
+ return starChild->get(bKey);
+ } else if (next_token == HASH) {
+ if (hashChild)
+ return hashChild->get(bKey);
+ } else {
+ typename ChildMap::iterator ptr;
+ ptr = childTokens.find(next_token);
+ if (ptr != childTokens.end()) {
+ return ptr->second->get(bKey);
+ }
+ }
+
+ return 0;
+ }
+
+
+ bool iterateMatch(TokenIterator& rKey, TreeIterator& iter) {
+ if (isStar) return iterateMatchStar(rKey, iter);
+ if (isHash) return iterateMatchHash(rKey, iter);
+ return iterateMatchString(rKey, iter);
+ }
+
+
+ bool iterateMatchString(TokenIterator& rKey, TreeIterator& iter){
+ // invariant: key has matched all previous tokens up to this node.
+ if (rKey.finished()) {
+ // exact match this node: visit if bound
+ if (!bindings.bindingVector.empty())
+ if (!iter.visit(*this)) return false;
+ }
+
+ // check remaining key against children, even if empty.
+ return iterateMatchChildren(rKey, iter);
+ }
+
+
+ bool iterateMatchStar(TokenIterator& rKey, TreeIterator& iter) {
+ // must match one token:
+ if (rKey.finished())
+ return true; // match failed, but continue iteration on siblings
+
+ // pop the topmost token
+ rKey.next();
+
+ if (rKey.finished()) {
+ // exact match this node: visit if bound
+ if (!bindings.bindingVector.empty())
+ if (!iter.visit(*this)) return false;
+ }
+
+ return iterateMatchChildren(rKey, iter);
+ }
+
+
+ bool iterateMatchHash(TokenIterator& rKey, TreeIterator& iter) {
+ // consume each token and look for a match on the
+ // remaining key.
+ while (!rKey.finished()) {
+ if (!iterateMatchChildren(rKey, iter)) return false;
+ rKey.next();
+ }
+
+ if (!bindings.bindingVector.empty())
+ return iter.visit(*this);
+
+ return true;
+ }
+
+
+ bool iterateMatchChildren(const TokenIterator& key, TreeIterator& iter) {
+ // always try glob - it can match empty keys
+ if (hashChild) {
+ TokenIterator tmp(key);
+ if (!hashChild->iterateMatch(tmp, iter))
+ return false;
+ }
+
+ if (!key.finished()) {
+ if (starChild) {
+ TokenIterator tmp(key);
+ if (!starChild->iterateMatch(tmp, iter))
+ return false;
+ }
+
+ if (!childTokens.empty()) {
+ TokenIterator newKey(key);
+ std::string next_token;
+ newKey.pop(next_token);
+
+ typename ChildMap::iterator ptr = childTokens.find(next_token);
+ if (ptr != childTokens.end()) {
+ return ptr->second->iterateMatch(newKey, iter);
+ }
+ }
+ }
+
+ return true;
+ }
+};
+
+}
+}
+
+#endif
diff --git a/cpp/src/qpid/broker/windows/SaslAuthenticator.cpp b/cpp/src/qpid/broker/windows/SaslAuthenticator.cpp
index a38e6ac12a..40e74be018 100644
--- a/cpp/src/qpid/broker/windows/SaslAuthenticator.cpp
+++ b/cpp/src/qpid/broker/windows/SaslAuthenticator.cpp
@@ -32,6 +32,8 @@
using namespace qpid::framing;
using qpid::sys::SecurityLayer;
+using std::string;
+
namespace qpid {
namespace broker {
@@ -79,7 +81,7 @@ void SaslAuthenticator::fini(void)
return;
}
-std::auto_ptr<SaslAuthenticator> SaslAuthenticator::createAuthenticator(Connection& c, bool)
+std::auto_ptr<SaslAuthenticator> SaslAuthenticator::createAuthenticator(Connection& c)
{
if (c.getBroker().getOptions().auth) {
return std::auto_ptr<SaslAuthenticator>(new SspiAuthenticator(c));
diff --git a/cpp/src/qpid/broker/windows/SslProtocolFactory.cpp b/cpp/src/qpid/broker/windows/SslProtocolFactory.cpp
index 1dff1ddc8f..fb59d058f8 100644
--- a/cpp/src/qpid/broker/windows/SslProtocolFactory.cpp
+++ b/cpp/src/qpid/broker/windows/SslProtocolFactory.cpp
@@ -44,26 +44,34 @@
namespace qpid {
namespace sys {
+
+class Timer;
+
namespace windows {
struct SslServerOptions : qpid::Options
{
std::string certStore;
+ std::string certStoreLocation;
std::string certName;
uint16_t port;
bool clientAuth;
SslServerOptions() : qpid::Options("SSL Options"),
- certStore("My"), port(5671), clientAuth(false)
+ certStore("My"),
+ certStoreLocation("CurrentUser"),
+ certName("localhost"),
+ port(5671),
+ clientAuth(false)
{
qpid::Address me;
if (qpid::sys::SystemInfo::getLocalHostname(me))
certName = me.host;
- else
- certName = "localhost";
addOptions()
("ssl-cert-store", optValue(certStore, "NAME"), "Local store name from which to obtain certificate")
+ ("ssl-cert-store-location", optValue(certStoreLocation, "NAME"),
+ "Local store name location for certificates ( CurrentUser | LocalMachine | CurrentService )")
("ssl-cert-name", optValue(certName, "NAME"), "Name of the certificate to use")
("ssl-port", optValue(port, "PORT"), "Port on which to listen for SSL connections")
("ssl-require-client-authentication", optValue(clientAuth),
@@ -72,10 +80,12 @@ struct SslServerOptions : qpid::Options
};
class SslProtocolFactory : public qpid::sys::ProtocolFactory {
- const bool tcpNoDelay;
boost::ptr_vector<Socket> listeners;
boost::ptr_vector<AsynchAcceptor> acceptors;
+ Timer& brokerTimer;
+ uint32_t maxNegotiateTime;
uint16_t listeningPort;
+ const bool tcpNoDelay;
std::string brokerHost;
const bool clientAuthSelected;
std::auto_ptr<qpid::sys::AsynchAcceptor> acceptor;
@@ -83,7 +93,9 @@ 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&, const std::string& host, const std::string& port,
+ int backlog, bool nodelay,
+ Timer& timer, uint32_t maxTime);
~SslProtocolFactory();
void accept(sys::Poller::shared_ptr, sys::ConnectionCodec::Factory*);
void connect(sys::Poller::shared_ptr, const std::string& host, const std::string& port,
@@ -120,8 +132,8 @@ static struct SslPlugin : public Plugin {
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));
+ opts.connectionBacklog, opts.tcpNoDelay,
+ broker->getTimer(), opts.maxNegotiateTime));
QPID_LOG(notice, "Listening for SSL connections on TCP port " << protocol->getPort());
broker->registerProtocolFactory("ssl", protocol);
} catch (const std::exception& e) {
@@ -132,9 +144,12 @@ static struct SslPlugin : public Plugin {
} sslPlugin;
SslProtocolFactory::SslProtocolFactory(const SslServerOptions& options,
- const std::string& host, const std::string& port, int backlog,
- bool nodelay)
- : tcpNoDelay(nodelay),
+ const std::string& host, const std::string& port,
+ int backlog, bool nodelay,
+ Timer& timer, uint32_t maxTime)
+ : brokerTimer(timer),
+ maxNegotiateTime(maxTime),
+ tcpNoDelay(nodelay),
clientAuthSelected(options.clientAuth) {
// Make sure that certificate store is good before listening to sockets
@@ -142,11 +157,25 @@ SslProtocolFactory::SslProtocolFactory(const SslServerOptions& options,
SecInvalidateHandle(&credHandle);
// Get the certificate for this server.
+ DWORD flags = 0;
+ std::string certStoreLocation = options.certStoreLocation;
+ std::transform(certStoreLocation.begin(), certStoreLocation.end(), certStoreLocation.begin(), ::tolower);
+ if (certStoreLocation == "currentuser") {
+ flags = CERT_SYSTEM_STORE_CURRENT_USER;
+ } else if (certStoreLocation == "localmachine") {
+ flags = CERT_SYSTEM_STORE_LOCAL_MACHINE;
+ } else if (certStoreLocation == "currentservice") {
+ flags = CERT_SYSTEM_STORE_CURRENT_SERVICE;
+ } else {
+ QPID_LOG(error, "Unrecognised SSL certificate store location: " << options.certStoreLocation
+ << " - Using default location");
+ }
HCERTSTORE certStoreHandle;
certStoreHandle = ::CertOpenStore(CERT_STORE_PROV_SYSTEM_A,
X509_ASN_ENCODING,
0,
- CERT_SYSTEM_STORE_LOCAL_MACHINE,
+ flags |
+ CERT_STORE_READONLY_FLAG,
options.certStore.c_str());
if (!certStoreHandle)
throw qpid::Exception(QPID_MSG("Opening store " << options.certStore << " " << qpid::sys::strError(GetLastError())));
@@ -252,7 +281,7 @@ void SslProtocolFactory::established(sys::Poller::shared_ptr poller,
boost::bind(&AsynchIOHandler::idle, async, _1));
}
- async->init(aio, 4);
+ async->init(aio, brokerTimer, maxNegotiateTime, 4);
aio->start(poller);
}
diff --git a/cpp/src/qpid/client/Connection.cpp b/cpp/src/qpid/client/Connection.cpp
index 83a4a35b53..8b4eafccaa 100644
--- a/cpp/src/qpid/client/Connection.cpp
+++ b/cpp/src/qpid/client/Connection.cpp
@@ -136,7 +136,7 @@ const ConnectionSettings& Connection::getNegotiatedSettings()
Session Connection::newSession(const std::string& name, uint32_t timeout) {
if (!isOpen())
- throw Exception(QPID_MSG("Connection has not yet been opened"));
+ throw TransportFailure("Can't create session, connection is not open");
Session s;
SessionBase_0_10Access(s).set(impl->newSession(name, timeout));
return s;
diff --git a/cpp/src/qpid/client/ConnectionHandler.cpp b/cpp/src/qpid/client/ConnectionHandler.cpp
index 94561f8079..91838d8e8b 100644
--- a/cpp/src/qpid/client/ConnectionHandler.cpp
+++ b/cpp/src/qpid/client/ConnectionHandler.cpp
@@ -258,7 +258,7 @@ void ConnectionHandler::start(const FieldTable& /*serverProps*/, const Array& me
}
if (sasl.get()) {
- string response;
+ std::string response;
if (sasl->start(join(mechlist), response, getSecuritySettings ? getSecuritySettings() : 0)) {
proxy.startOk(properties, sasl->getMechanism(), response, locale);
} else {
@@ -272,7 +272,7 @@ void ConnectionHandler::start(const FieldTable& /*serverProps*/, const Array& me
}
} else {
//TODO: verify that desired mechanism and locale are supported
- string response = ((char)0) + username + ((char)0) + password;
+ std::string response = ((char)0) + username + ((char)0) + password;
proxy.startOk(properties, mechanism, response, locale);
}
}
@@ -280,7 +280,7 @@ void ConnectionHandler::start(const FieldTable& /*serverProps*/, const Array& me
void ConnectionHandler::secure(const std::string& challenge)
{
if (sasl.get()) {
- string response = sasl->step(challenge);
+ std::string response = sasl->step(challenge);
proxy.secureOk(response);
} else {
throw NotImplementedException("Challenge-response cycle not yet implemented in client");
diff --git a/cpp/src/qpid/client/PrivateImplRef.h b/cpp/src/qpid/client/PrivateImplRef.h
index 503a383c31..fa89b1bfa0 100644
--- a/cpp/src/qpid/client/PrivateImplRef.h
+++ b/cpp/src/qpid/client/PrivateImplRef.h
@@ -77,15 +77,15 @@ template <class T> class PrivateImplRef {
static void set(T& t, const intrusive_ptr& p) {
if (t.impl == p) return;
- if (t.impl) boost::intrusive_ptr_release(t.impl);
+ if (t.impl) intrusive_ptr_release(t.impl);
t.impl = p.get();
- if (t.impl) boost::intrusive_ptr_add_ref(t.impl);
+ if (t.impl) intrusive_ptr_add_ref(t.impl);
}
// Helper functions to implement the ctor, dtor, copy, assign
- static void ctor(T& t, Impl* p) { t.impl = p; if (p) boost::intrusive_ptr_add_ref(p); }
+ static void ctor(T& t, Impl* p) { t.impl = p; if (p) intrusive_ptr_add_ref(p); }
static void copy(T& t, const T& x) { if (&t == &x) return; t.impl = 0; assign(t, x); }
- static void dtor(T& t) { if(t.impl) boost::intrusive_ptr_release(t.impl); }
+ static void dtor(T& t) { if(t.impl) intrusive_ptr_release(t.impl); }
static T& assign(T& t, const T& x) { set(t, get(x)); return t;}
};
diff --git a/cpp/src/qpid/client/SessionImpl.cpp b/cpp/src/qpid/client/SessionImpl.cpp
index 3f3ad617f4..91e728d5ae 100644
--- a/cpp/src/qpid/client/SessionImpl.cpp
+++ b/cpp/src/qpid/client/SessionImpl.cpp
@@ -426,7 +426,7 @@ void SessionImpl::sendContent(const MethodContent& content)
uint32_t remaining = data_length - offset;
while (remaining > 0) {
uint32_t length = remaining > frag_size ? frag_size : remaining;
- string frag(content.getData().substr(offset, length));
+ std::string frag(content.getData().substr(offset, length));
AMQFrame frame((AMQContentBody(frag)));
frame.setFirstSegment(false);
frame.setLastSegment(true);
diff --git a/cpp/src/qpid/client/SslConnector.cpp b/cpp/src/qpid/client/SslConnector.cpp
index ab0c5c4957..4c6fadd28a 100644
--- a/cpp/src/qpid/client/SslConnector.cpp
+++ b/cpp/src/qpid/client/SslConnector.cpp
@@ -94,8 +94,6 @@ class SslConnector : public Connector
sys::ShutdownHandler* shutdownHandler;
framing::InputHandler* input;
- framing::InitiationHandler* initialiser;
- framing::OutputHandler* output;
Writer writer;
@@ -176,6 +174,7 @@ SslConnector::SslConnector(Poller::shared_ptr p,
initiated(false),
closed(true),
shutdownHandler(0),
+ input(0),
writer(maxFrameSize, cimpl),
aio(0),
poller(p)
diff --git a/cpp/src/qpid/client/SubscriptionManagerImpl.cpp b/cpp/src/qpid/client/SubscriptionManagerImpl.cpp
index a558d90be8..7dead112e5 100644
--- a/cpp/src/qpid/client/SubscriptionManagerImpl.cpp
+++ b/cpp/src/qpid/client/SubscriptionManagerImpl.cpp
@@ -39,6 +39,16 @@ SubscriptionManagerImpl::SubscriptionManagerImpl(const Session& s)
: dispatcher(s), session(s), autoStop(true)
{}
+SubscriptionManagerImpl::~SubscriptionManagerImpl()
+{
+ sys::Mutex::ScopedLock l(lock);
+ for (std::map<std::string, Subscription>::iterator i = subscriptions.begin(); i != subscriptions.end(); ++i) {
+ boost::intrusive_ptr<SubscriptionImpl> s = PrivateImplRef<Subscription>::get(i->second);
+ if (s) s->cancelDiversion();
+ }
+ subscriptions.clear();
+}
+
Subscription SubscriptionManagerImpl::subscribe(
MessageListener& listener, const std::string& q, const SubscriptionSettings& ss, const std::string& n)
{
diff --git a/cpp/src/qpid/client/SubscriptionManagerImpl.h b/cpp/src/qpid/client/SubscriptionManagerImpl.h
index 6376a05c45..64d922e387 100644
--- a/cpp/src/qpid/client/SubscriptionManagerImpl.h
+++ b/cpp/src/qpid/client/SubscriptionManagerImpl.h
@@ -99,7 +99,8 @@ class SubscriptionManagerImpl : public sys::Runnable, public RefCounted
public:
/** Create a new SubscriptionManagerImpl associated with a session */
SubscriptionManagerImpl(const Session& session);
-
+ ~SubscriptionManagerImpl();
+
/**
* Subscribe a MessagesListener to receive messages from queue.
*
diff --git a/cpp/src/qpid/client/TCPConnector.cpp b/cpp/src/qpid/client/TCPConnector.cpp
index 4660a41c07..1dd951d339 100644
--- a/cpp/src/qpid/client/TCPConnector.cpp
+++ b/cpp/src/qpid/client/TCPConnector.cpp
@@ -76,6 +76,7 @@ TCPConnector::TCPConnector(Poller::shared_ptr p,
initiated(false),
closed(true),
shutdownHandler(0),
+ input(0),
connector(0),
aio(0),
poller(p)
@@ -265,7 +266,7 @@ size_t TCPConnector::encode(const char* buffer, size_t size)
return bytesWritten;
}
-bool TCPConnector::readbuff(AsynchIO& aio, AsynchIO::BufferBase* buff)
+void TCPConnector::readbuff(AsynchIO& aio, AsynchIO::BufferBase* buff)
{
Codec* codec = securityLayer.get() ? (Codec*) securityLayer.get() : (Codec*) this;
int32_t decoded = codec->decode(buff->bytes+buff->dataStart, buff->dataCount);
@@ -280,10 +281,9 @@ bool TCPConnector::readbuff(AsynchIO& aio, AsynchIO::BufferBase* buff)
// Give whole buffer back to aio subsystem
aio.queueReadBuffer(buff);
}
- return true;
}
-size_t TCPConnector::decode(const char* buffer, size_t size)
+size_t TCPConnector::decode(const char* buffer, size_t size)
{
framing::Buffer in(const_cast<char*>(buffer), size);
if (!initiated) {
diff --git a/cpp/src/qpid/client/TCPConnector.h b/cpp/src/qpid/client/TCPConnector.h
index eb3f696013..c87d544816 100644
--- a/cpp/src/qpid/client/TCPConnector.h
+++ b/cpp/src/qpid/client/TCPConnector.h
@@ -66,8 +66,6 @@ class TCPConnector : public Connector, public sys::Codec
sys::ShutdownHandler* shutdownHandler;
framing::InputHandler* input;
- framing::InitiationHandler* initialiser;
- framing::OutputHandler* output;
sys::Socket socket;
@@ -102,7 +100,7 @@ protected:
void start(sys::AsynchIO* aio_);
void initAmqp();
virtual void connectFailed(const std::string& msg);
- bool readbuff(qpid::sys::AsynchIO&, qpid::sys::AsynchIOBufferBase*);
+ void readbuff(qpid::sys::AsynchIO&, qpid::sys::AsynchIOBufferBase*);
void writebuff(qpid::sys::AsynchIO&);
void eof(qpid::sys::AsynchIO&);
void disconnected(qpid::sys::AsynchIO&);
diff --git a/cpp/src/qpid/client/amqp0_10/AddressResolution.cpp b/cpp/src/qpid/client/amqp0_10/AddressResolution.cpp
index a8f4fb5237..2627c178f9 100644
--- a/cpp/src/qpid/client/amqp0_10/AddressResolution.cpp
+++ b/cpp/src/qpid/client/amqp0_10/AddressResolution.cpp
@@ -241,6 +241,7 @@ class Subscription : public Exchange, public MessageSource
const std::string actualType;
const bool exclusiveQueue;
const bool exclusiveSubscription;
+ const std::string alternateExchange;
FieldTable queueOptions;
FieldTable subscriptionOptions;
Bindings bindings;
@@ -507,7 +508,8 @@ Subscription::Subscription(const Address& address, const std::string& type)
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))
+ exclusiveSubscription((Opt(address)/LINK/X_SUBSCRIBE/EXCLUSIVE).asBool(exclusiveQueue)),
+ alternateExchange((Opt(address)/LINK/X_DECLARE/ALTERNATE_EXCHANGE).str())
{
(Opt(address)/LINK/X_DECLARE/ARGUMENTS).collect(queueOptions);
(Opt(address)/LINK/X_SUBSCRIBE/ARGUMENTS).collect(subscriptionOptions);
@@ -568,7 +570,9 @@ void Subscription::subscribe(qpid::client::AsyncSession& session, const std::str
//create subscription queue:
session.queueDeclare(arg::queue=queue, arg::exclusive=exclusiveQueue,
- arg::autoDelete=!reliable, arg::durable=durable, arg::arguments=queueOptions);
+ arg::autoDelete=!reliable, arg::durable=durable,
+ arg::alternateExchange=alternateExchange,
+ arg::arguments=queueOptions);
//'default' binding:
bindings.bind(session);
//any explicit bindings:
diff --git a/cpp/src/qpid/client/amqp0_10/ConnectionImpl.cpp b/cpp/src/qpid/client/amqp0_10/ConnectionImpl.cpp
index 2ea4dc0c61..aaebec0720 100644
--- a/cpp/src/qpid/client/amqp0_10/ConnectionImpl.cpp
+++ b/cpp/src/qpid/client/amqp0_10/ConnectionImpl.cpp
@@ -78,7 +78,7 @@ bool expired(const sys::AbsTime& start, double timeout)
if (timeout == 0) return true;
if (timeout == FOREVER) return false;
sys::Duration used(start, sys::now());
- sys::Duration allowed(int64_t(timeout*sys::TIME_SEC));
+ sys::Duration allowed((int64_t)(timeout*sys::TIME_SEC));
return allowed < used;
}
diff --git a/cpp/src/qpid/client/amqp0_10/OutgoingMessage.cpp b/cpp/src/qpid/client/amqp0_10/OutgoingMessage.cpp
index d93416da75..dd14d11c4c 100644
--- a/cpp/src/qpid/client/amqp0_10/OutgoingMessage.cpp
+++ b/cpp/src/qpid/client/amqp0_10/OutgoingMessage.cpp
@@ -58,7 +58,12 @@ void OutgoingMessage::convert(const qpid::messaging::Message& from)
if (address) {
message.getMessageProperties().setReplyTo(AddressResolution::convert(address));
}
- translate(from.getProperties(), message.getMessageProperties().getApplicationHeaders());
+ if (!subject.empty()) {
+ Variant v(subject); v.setEncoding("utf8");
+ translate(from.getProperties(), SUBJECT, v, message.getMessageProperties().getApplicationHeaders());
+ } else {
+ translate(from.getProperties(), message.getMessageProperties().getApplicationHeaders());
+ }
if (from.getTtl().getMilliseconds()) {
message.getDeliveryProperties().setTtl(from.getTtl().getMilliseconds());
}
@@ -89,16 +94,14 @@ void OutgoingMessage::convert(const qpid::messaging::Message& from)
}
}
-void OutgoingMessage::setSubject(const std::string& subject)
+void OutgoingMessage::setSubject(const std::string& s)
{
- if (!subject.empty()) {
- message.getMessageProperties().getApplicationHeaders().setString(SUBJECT, subject);
- }
+ subject = s;
}
std::string OutgoingMessage::getSubject() const
{
- return message.getMessageProperties().getApplicationHeaders().getAsString(SUBJECT);
+ return subject;
}
}}} // namespace qpid::client::amqp0_10
diff --git a/cpp/src/qpid/client/amqp0_10/OutgoingMessage.h b/cpp/src/qpid/client/amqp0_10/OutgoingMessage.h
index 0cdd2a2336..2191f45546 100644
--- a/cpp/src/qpid/client/amqp0_10/OutgoingMessage.h
+++ b/cpp/src/qpid/client/amqp0_10/OutgoingMessage.h
@@ -35,6 +35,7 @@ struct OutgoingMessage
{
qpid::client::Message message;
qpid::client::Completion status;
+ std::string subject;
void convert(const qpid::messaging::Message&);
void setSubject(const std::string& subject);
diff --git a/cpp/src/qpid/client/amqp0_10/ReceiverImpl.h b/cpp/src/qpid/client/amqp0_10/ReceiverImpl.h
index 5693b7b71f..76da4f31a9 100644
--- a/cpp/src/qpid/client/amqp0_10/ReceiverImpl.h
+++ b/cpp/src/qpid/client/amqp0_10/ReceiverImpl.h
@@ -78,7 +78,6 @@ class ReceiverImpl : public qpid::messaging::ReceiverImpl
std::auto_ptr<MessageSource> source;
uint32_t capacity;
qpid::client::AsyncSession session;
- qpid::messaging::MessageListener* listener;
uint32_t window;
void startFlow(const sys::Mutex::ScopedLock&); // Dummy param, call with lock held
diff --git a/cpp/src/qpid/client/amqp0_10/SenderImpl.cpp b/cpp/src/qpid/client/amqp0_10/SenderImpl.cpp
index f2f0f1a9e5..b275db38d7 100644
--- a/cpp/src/qpid/client/amqp0_10/SenderImpl.cpp
+++ b/cpp/src/qpid/client/amqp0_10/SenderImpl.cpp
@@ -37,10 +37,10 @@ SenderImpl::SenderImpl(SessionImpl& _parent, const std::string& _name,
void SenderImpl::send(const qpid::messaging::Message& message, bool sync)
{
if (unreliable) { // immutable, don't need lock
- UnreliableSend f(*this, &message);
+ UnreliableSend f(*this, message);
parent->execute(f);
} else {
- Send f(*this, &message);
+ Send f(*this, message);
while (f.repeat) parent->execute(f);
}
if (sync) parent->sync(true);
@@ -117,8 +117,8 @@ void SenderImpl::sendImpl(const qpid::messaging::Message& m)
{
sys::Mutex::ScopedLock l(lock);
std::auto_ptr<OutgoingMessage> msg(new OutgoingMessage());
- msg->convert(m);
msg->setSubject(m.getSubject().empty() ? address.getSubject() : m.getSubject());
+ msg->convert(m);
outgoing.push_back(msg.release());
sink->send(session, name, outgoing.back());
}
@@ -127,8 +127,8 @@ void SenderImpl::sendUnreliable(const qpid::messaging::Message& m)
{
sys::Mutex::ScopedLock l(lock);
OutgoingMessage msg;
- msg.convert(m);
msg.setSubject(m.getSubject().empty() ? address.getSubject() : m.getSubject());
+ msg.convert(m);
sink->send(session, name, msg);
}
diff --git a/cpp/src/qpid/client/amqp0_10/SenderImpl.h b/cpp/src/qpid/client/amqp0_10/SenderImpl.h
index c10c77ae18..d75863c743 100644
--- a/cpp/src/qpid/client/amqp0_10/SenderImpl.h
+++ b/cpp/src/qpid/client/amqp0_10/SenderImpl.h
@@ -99,32 +99,32 @@ class SenderImpl : public qpid::messaging::SenderImpl
struct Send : Command
{
- const qpid::messaging::Message* message;
+ const qpid::messaging::Message& message;
bool repeat;
- Send(SenderImpl& i, const qpid::messaging::Message* m) : Command(i), message(m), repeat(true) {}
+ Send(SenderImpl& i, const qpid::messaging::Message& m) : Command(i), message(m), repeat(true) {}
void operator()()
{
impl.waitForCapacity();
//from this point message will be recorded if there is any
//failure (and replayed) so need not repeat the call
repeat = false;
- impl.sendImpl(*message);
+ impl.sendImpl(message);
}
};
struct UnreliableSend : Command
{
- const qpid::messaging::Message* message;
+ const qpid::messaging::Message& message;
- UnreliableSend(SenderImpl& i, const qpid::messaging::Message* m) : Command(i), message(m) {}
+ UnreliableSend(SenderImpl& i, const qpid::messaging::Message& m) : Command(i), message(m) {}
void operator()()
{
//TODO: ideally want to put messages on the outbound
//queue and pull them off in io thread, but the old
//0-10 client doesn't support that option so for now
//we simply don't queue unreliable messages
- impl.sendUnreliable(*message);
+ impl.sendUnreliable(message);
}
};
diff --git a/cpp/src/qpid/client/windows/SslConnector.cpp b/cpp/src/qpid/client/windows/SslConnector.cpp
index 785c817928..2aa31e8202 100644
--- a/cpp/src/qpid/client/windows/SslConnector.cpp
+++ b/cpp/src/qpid/client/windows/SslConnector.cpp
@@ -68,7 +68,7 @@ class SslConnector : public qpid::client::TCPConnector
// A number of AsynchIO callbacks go right through to TCPConnector, but
// we can't boost::bind to a protected ancestor, so these methods redirect
// to those TCPConnector methods.
- bool redirectReadbuff(qpid::sys::AsynchIO&, qpid::sys::AsynchIOBufferBase*);
+ void redirectReadbuff(qpid::sys::AsynchIO&, qpid::sys::AsynchIOBufferBase*);
void redirectWritebuff(qpid::sys::AsynchIO&);
void redirectEof(qpid::sys::AsynchIO&);
@@ -111,9 +111,9 @@ void SslConnector::negotiationDone(SECURITY_STATUS status)
connectFailed(QPID_MSG(qpid::sys::strError(status)));
}
-bool SslConnector::redirectReadbuff(qpid::sys::AsynchIO& a,
+void SslConnector::redirectReadbuff(qpid::sys::AsynchIO& a,
qpid::sys::AsynchIOBufferBase* b) {
- return readbuff(a, b);
+ readbuff(a, b);
}
void SslConnector::redirectWritebuff(qpid::sys::AsynchIO& a) {
diff --git a/cpp/src/qpid/cluster/Connection.cpp b/cpp/src/qpid/cluster/Connection.cpp
index 512e0f03cb..ff855eef18 100644
--- a/cpp/src/qpid/cluster/Connection.cpp
+++ b/cpp/src/qpid/cluster/Connection.cpp
@@ -58,6 +58,8 @@
namespace qpid {
namespace cluster {
+using std::string;
+
using namespace framing;
using namespace framing::cluster;
using amqp_0_10::ListCodec;
@@ -83,7 +85,9 @@ 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),
- connectionCtor(&output, cluster.getBroker(), mgmtId, external, false, 0, true),
+ connectionCtor(&output, cluster.getBroker(), mgmtId, external,
+ false/*isLink*/, 0/*objectId*/, true/*shadow*/, false/*delayManagement*/,
+ false/*authenticated*/),
expectProtocolHeader(false),
mcastFrameHandler(cluster.getMulticast(), self),
updateIn(c.getUpdateReceiver()),
@@ -100,9 +104,10 @@ Connection::Connection(Cluster& c, sys::ConnectionOutputHandler& out,
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),
+ // The first catch-up connection is not a shadow
+ isCatchUp && self.second > 1,
+ false, // delayManagement
+ true), // catch up connecytions are authenticated
expectProtocolHeader(isLink),
mcastFrameHandler(cluster.getMulticast(), self),
updateIn(c.getUpdateReceiver()),
@@ -272,6 +277,8 @@ void Connection::closed() {
if (announced)
cluster.getMulticast().mcastControl(
ClusterConnectionDeliverCloseBody(), self);
+ else
+ close();
}
}
catch (const std::exception& e) {
@@ -404,11 +411,12 @@ void Connection::shadowSetUser(const std::string& userId) {
}
void Connection::consumerState(const string& name, bool blocked, bool notifyEnabled, const SequenceNumber& position,
- uint32_t usedMsgCredit, uint32_t usedByteCredit)
+ uint32_t usedMsgCredit, uint32_t usedByteCredit, const uint32_t deliveryCount)
{
broker::SemanticState::ConsumerImpl::shared_ptr c = semanticState().find(name);
c->setPosition(position);
c->setBlocked(blocked);
+ c->setDeliveryCount(deliveryCount);
if (c->getCredit().isWindowMode()) c->getCredit().consume(usedMsgCredit, usedByteCredit);
if (notifyEnabled) c->enableNotify(); else c->disableNotify();
updateIn.consumerNumbering.add(c);
@@ -522,6 +530,7 @@ broker::QueuedMessage Connection::getUpdateMessage() {
boost::shared_ptr<broker::Queue> updateq = findQueue(UpdateClient::UPDATE);
assert(!updateq->isDurable());
broker::QueuedMessage m = updateq->get();
+ updateq->dequeue(0, m);
if (!m.payload) throw Exception(QPID_MSG(cluster << " empty update queue"));
return m;
}
@@ -782,16 +791,18 @@ void Connection::managementSetupState(
void Connection::config(const std::string& encoded) {
Buffer buf(const_cast<char*>(encoded.data()), encoded.size());
string kind;
+ uint32_t p = buf.getPosition();
buf.getShortString (kind);
- if (kind == "link") {
+ buf.setPosition(p);
+ if (broker::Link::isEncodedLink(kind)) {
broker::Link::shared_ptr link =
- broker::Link::decode(cluster.getBroker().getLinks(), buf);
+ broker::Link::decode(cluster.getBroker().getLinks(), buf);
QPID_LOG(debug, cluster << " updated link "
<< link->getHost() << ":" << link->getPort());
}
- else if (kind == "bridge") {
+ else if (broker::Bridge::isEncodedBridge(kind)) {
broker::Bridge::shared_ptr bridge =
- broker::Bridge::decode(cluster.getBroker().getLinks(), buf);
+ broker::Bridge::decode(cluster.getBroker().getLinks(), buf);
QPID_LOG(debug, cluster << " updated bridge " << bridge->getName());
}
else throw Exception(QPID_MSG("Update failed, invalid kind of config: " << kind));
diff --git a/cpp/src/qpid/cluster/Connection.h b/cpp/src/qpid/cluster/Connection.h
index 26514c76e2..b0e7b3bd9e 100644
--- a/cpp/src/qpid/cluster/Connection.h
+++ b/cpp/src/qpid/cluster/Connection.h
@@ -110,7 +110,7 @@ class Connection :
void deliveredFrame(const EventFrame&);
void consumerState(const std::string& name, bool blocked, bool notifyEnabled, const qpid::framing::SequenceNumber& position,
- uint32_t usedMsgCredit, uint32_t usedByteCredit);
+ uint32_t usedMsgCredit, uint32_t usedByteCredit, const uint32_t deliveryCount);
// ==== Used in catch-up mode to build initial state.
//
@@ -228,6 +228,7 @@ class Connection :
uint64_t objectId;
bool shadow;
bool delayManagement;
+ bool authenticated;
ConnectionCtor(
sys::ConnectionOutputHandler* out_,
@@ -237,17 +238,18 @@ class Connection :
bool isLink_=false,
uint64_t objectId_=0,
bool shadow_=false,
- bool delayManagement_=false
+ bool delayManagement_=false,
+ bool authenticated_=true
) : out(out_), broker(broker_), mgmtId(mgmtId_), external(external_),
isLink(isLink_), objectId(objectId_), shadow(shadow_),
- delayManagement(delayManagement_)
+ delayManagement(delayManagement_), authenticated(authenticated_)
{}
std::auto_ptr<broker::Connection> construct() {
return std::auto_ptr<broker::Connection>(
new broker::Connection(
out, broker, mgmtId, external, isLink, objectId,
- shadow, delayManagement)
+ shadow, delayManagement, authenticated)
);
}
};
diff --git a/cpp/src/qpid/cluster/ConnectionCodec.cpp b/cpp/src/qpid/cluster/ConnectionCodec.cpp
index d0ba8abfb3..54327fbfe2 100644
--- a/cpp/src/qpid/cluster/ConnectionCodec.cpp
+++ b/cpp/src/qpid/cluster/ConnectionCodec.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
@@ -22,6 +22,7 @@
#include "qpid/cluster/Connection.h"
#include "qpid/cluster/Cluster.h"
#include "qpid/cluster/ProxyInputHandler.h"
+#include "qpid/broker/AclModule.h"
#include "qpid/broker/Connection.h"
#include "qpid/framing/ConnectionCloseBody.h"
#include "qpid/framing/ConnectionCloseOkBody.h"
@@ -40,17 +41,10 @@ ConnectionCodec::Factory::create(ProtocolVersion v, sys::OutputControl& out,
const std::string& id,
const qpid::sys::SecuritySettings& external)
{
- broker::Broker& broker = cluster.getBroker();
- if (broker.getConnectionCounter().allowConnection())
- {
- QPID_LOG(error, "Client max connection count limit exceeded: "
- << broker.getOptions().maxConnections << " connection refused");
- return 0;
- }
if (v == ProtocolVersion(0, 10))
return new ConnectionCodec(v, out, id, cluster, false, false, external);
else if (v == ProtocolVersion(0x80 + 0, 0x80 + 10)) // Catch-up connection
- return new ConnectionCodec(v, out, id, cluster, true, false, external);
+ return new ConnectionCodec(v, out, id, cluster, true, false, external);
return 0;
}
diff --git a/cpp/src/qpid/cluster/Cpg.cpp b/cpp/src/qpid/cluster/Cpg.cpp
index 0856bcd824..6e9e22a42f 100644
--- a/cpp/src/qpid/cluster/Cpg.cpp
+++ b/cpp/src/qpid/cluster/Cpg.cpp
@@ -32,7 +32,7 @@
// This is a macro instead of a function because we don't want to
// evaluate the MSG argument unless there is an error.
#define CPG_CHECK(RESULT, MSG) \
- if ((RESULT) != CPG_OK) throw Exception(errorStr((RESULT), (MSG)))
+ if ((RESULT) != CS_OK) throw Exception(errorStr((RESULT), (MSG)))
namespace qpid {
namespace cluster {
@@ -50,13 +50,13 @@ Cpg* Cpg::cpgFromHandle(cpg_handle_t handle) {
// Applies the same retry-logic to all cpg calls that need it.
void Cpg::callCpg ( CpgOp & c ) {
- cpg_error_t result;
+ cs_error_t result;
unsigned int snooze = 10;
for ( unsigned int nth_try = 0; nth_try < cpgRetries; ++ nth_try ) {
- if ( CPG_OK == (result = c.op(handle, & group))) {
+ if ( CS_OK == (result = c.op(handle, & group))) {
break;
}
- else if ( result == CPG_ERR_TRY_AGAIN ) {
+ else if ( result == CS_ERR_TRY_AGAIN ) {
QPID_LOG(info, "Retrying " << c.opName );
sys::usleep ( snooze );
snooze *= 10;
@@ -65,7 +65,7 @@ void Cpg::callCpg ( CpgOp & c ) {
else break; // Don't retry unless CPG tells us to.
}
- if ( result != CPG_OK )
+ if ( result != CS_OK )
CPG_CHECK(result, c.msg(group));
}
@@ -127,9 +127,9 @@ Cpg::Cpg(Handler& h) : IOHandle(new sys::IOHandlePrivate), handler(h), isShutdow
callbacks.cpg_confchg_fn = &globalConfigChange;
QPID_LOG(notice, "Initializing CPG");
- cpg_error_t err = cpg_initialize(&handle, &callbacks);
+ cs_error_t err = cpg_initialize(&handle, &callbacks);
int retries = 6; // FIXME aconway 2009-08-06: make this configurable.
- while (err == CPG_ERR_TRY_AGAIN && --retries) {
+ while (err == CS_ERR_TRY_AGAIN && --retries) {
QPID_LOG(notice, "Re-trying CPG initialization.");
sys::sleep(5);
err = cpg_initialize(&handle, &callbacks);
@@ -169,11 +169,11 @@ bool Cpg::mcast(const iovec* iov, int iovLen) {
if (flowState == CPG_FLOW_CONTROL_ENABLED)
return false;
- cpg_error_t result;
+ cs_error_t result;
do {
result = cpg_mcast_joined(handle, CPG_TYPE_AGREED, const_cast<iovec*>(iov), iovLen);
- if (result != CPG_ERR_TRY_AGAIN) CPG_CHECK(result, cantMcastMsg(group));
- } while(result == CPG_ERR_TRY_AGAIN);
+ if (result != CS_ERR_TRY_AGAIN) CPG_CHECK(result, cantMcastMsg(group));
+ } while(result == CS_ERR_TRY_AGAIN);
return true;
}
@@ -187,34 +187,34 @@ void Cpg::shutdown() {
}
void Cpg::dispatchOne() {
- CPG_CHECK(cpg_dispatch(handle,CPG_DISPATCH_ONE), "Error in CPG dispatch");
+ CPG_CHECK(cpg_dispatch(handle,CS_DISPATCH_ONE), "Error in CPG dispatch");
}
void Cpg::dispatchAll() {
- CPG_CHECK(cpg_dispatch(handle,CPG_DISPATCH_ALL), "Error in CPG dispatch");
+ CPG_CHECK(cpg_dispatch(handle,CS_DISPATCH_ALL), "Error in CPG dispatch");
}
void Cpg::dispatchBlocking() {
- CPG_CHECK(cpg_dispatch(handle,CPG_DISPATCH_BLOCKING), "Error in CPG dispatch");
+ CPG_CHECK(cpg_dispatch(handle,CS_DISPATCH_BLOCKING), "Error in CPG dispatch");
}
-string Cpg::errorStr(cpg_error_t err, const std::string& msg) {
+string Cpg::errorStr(cs_error_t err, const std::string& msg) {
std::ostringstream os;
os << msg << ": ";
switch (err) {
- case CPG_OK: os << "ok"; break;
- case CPG_ERR_LIBRARY: os << "library"; break;
- case CPG_ERR_TIMEOUT: os << "timeout"; break;
- case CPG_ERR_TRY_AGAIN: os << "try again"; break;
- case CPG_ERR_INVALID_PARAM: os << "invalid param"; break;
- case CPG_ERR_NO_MEMORY: os << "no memory"; break;
- case CPG_ERR_BAD_HANDLE: os << "bad handle"; break;
- case CPG_ERR_ACCESS: os << "access denied. You may need to set your group ID to 'ais'"; break;
- case CPG_ERR_NOT_EXIST: os << "not exist"; break;
- case CPG_ERR_EXIST: os << "exist"; break;
- case CPG_ERR_NOT_SUPPORTED: os << "not supported"; break;
- case CPG_ERR_SECURITY: os << "security"; break;
- case CPG_ERR_TOO_MANY_GROUPS: os << "too many groups"; break;
+ case CS_OK: os << "ok"; break;
+ case CS_ERR_LIBRARY: os << "library"; break;
+ case CS_ERR_TIMEOUT: os << "timeout"; break;
+ case CS_ERR_TRY_AGAIN: os << "try again"; break;
+ case CS_ERR_INVALID_PARAM: os << "invalid param"; break;
+ case CS_ERR_NO_MEMORY: os << "no memory"; break;
+ case CS_ERR_BAD_HANDLE: os << "bad handle"; break;
+ case CS_ERR_ACCESS: os << "access denied. You may need to set your group ID to 'ais'"; break;
+ case CS_ERR_NOT_EXIST: os << "not exist"; break;
+ case CS_ERR_EXIST: os << "exist"; break;
+ case CS_ERR_NOT_SUPPORTED: os << "not supported"; break;
+ case CS_ERR_SECURITY: os << "security"; break;
+ case CS_ERR_TOO_MANY_GROUPS: os << "too many groups"; break;
default: os << ": unknown cpg error " << err;
};
os << " (" << err << ")";
diff --git a/cpp/src/qpid/cluster/Cpg.h b/cpp/src/qpid/cluster/Cpg.h
index 6b81c602bd..1afbce8d75 100644
--- a/cpp/src/qpid/cluster/Cpg.h
+++ b/cpp/src/qpid/cluster/Cpg.h
@@ -131,7 +131,7 @@ class Cpg : public sys::IOHandle {
CpgOp ( std::string opName )
: opName(opName) { }
- virtual cpg_error_t op ( cpg_handle_t handle, struct cpg_name * ) = 0;
+ virtual cs_error_t op ( cpg_handle_t handle, struct cpg_name * ) = 0;
virtual std::string msg(const Name&) = 0;
virtual ~CpgOp ( ) { }
};
@@ -141,7 +141,7 @@ class Cpg : public sys::IOHandle {
CpgJoinOp ( )
: CpgOp ( std::string("cpg_join") ) { }
- cpg_error_t op(cpg_handle_t handle, struct cpg_name * group) {
+ cs_error_t op(cpg_handle_t handle, struct cpg_name * group) {
return cpg_join ( handle, group );
}
@@ -152,7 +152,7 @@ class Cpg : public sys::IOHandle {
CpgLeaveOp ( )
: CpgOp ( std::string("cpg_leave") ) { }
- cpg_error_t op(cpg_handle_t handle, struct cpg_name * group) {
+ cs_error_t op(cpg_handle_t handle, struct cpg_name * group) {
return cpg_leave ( handle, group );
}
@@ -163,7 +163,7 @@ class Cpg : public sys::IOHandle {
CpgFinalizeOp ( )
: CpgOp ( std::string("cpg_finalize") ) { }
- cpg_error_t op(cpg_handle_t handle, struct cpg_name *) {
+ cs_error_t op(cpg_handle_t handle, struct cpg_name *) {
return cpg_finalize ( handle );
}
@@ -177,7 +177,7 @@ class Cpg : public sys::IOHandle {
CpgLeaveOp cpgLeaveOp;
CpgFinalizeOp cpgFinalizeOp;
- static std::string errorStr(cpg_error_t err, const std::string& msg);
+ static std::string errorStr(cs_error_t err, const std::string& msg);
static std::string cantJoinMsg(const Name&);
static std::string cantLeaveMsg(const Name&);
static std::string cantMcastMsg(const Name&);
diff --git a/cpp/src/qpid/cluster/UpdateClient.cpp b/cpp/src/qpid/cluster/UpdateClient.cpp
index 20684fd8a7..8737418570 100644
--- a/cpp/src/qpid/cluster/UpdateClient.cpp
+++ b/cpp/src/qpid/cluster/UpdateClient.cpp
@@ -74,6 +74,8 @@
namespace qpid {
namespace cluster {
+using std::string;
+
using amqp_0_10::ListCodec;
using broker::Broker;
using broker::Exchange;
@@ -87,6 +89,8 @@ using namespace framing;
namespace arg=client::arg;
using client::SessionBase_0_10Access;
+namespace _qmf = qmf::org::apache::qpid::broker;
+
// 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.
@@ -226,14 +230,6 @@ template <class T> std::string encode(const T& t) {
t.encode(buf);
return encoded;
}
-
-template <class T> std::string encode(const T& t, bool encodeKind) {
- std::string encoded;
- encoded.resize(t.encodedSize());
- framing::Buffer buf(const_cast<char*>(encoded.data()), encoded.size());
- t.encode(buf, encodeKind);
- return encoded;
-}
} // namespace
@@ -377,13 +373,14 @@ class MessageUpdater {
void UpdateClient::updateQueue(client::AsyncSession& s, const boost::shared_ptr<Queue>& q) {
broker::Exchange::shared_ptr alternateExchange = q->getAlternateExchange();
+ _qmf::Queue* mgmtQueue = dynamic_cast<_qmf::Queue*>(q->GetManagementObject());
s.queueDeclare(
arg::queue = q->getName(),
arg::durable = q->isDurable(),
arg::autoDelete = q->isAutoDelete(),
arg::alternateExchange = alternateExchange ? alternateExchange->getName() : "",
arg::arguments = q->getSettings(),
- arg::exclusive = q->hasExclusiveOwner()
+ arg::exclusive = mgmtQueue && mgmtQueue->get_exclusive()
);
MessageUpdater updater(q->getName(), s, expiry);
q->eachMessage(boost::bind(&MessageUpdater::updateQueuedMessage, &updater, _1));
@@ -545,7 +542,8 @@ void UpdateClient::updateConsumer(
ci->isNotifyEnabled(),
ci->getPosition(),
ci->getCredit().used().messages,
- ci->getCredit().used().bytes
+ ci->getCredit().used().bytes,
+ ci->getDeliveryCount()
);
consumerNumbering.add(ci.get());
diff --git a/cpp/src/qpid/cluster/types.h b/cpp/src/qpid/cluster/types.h
index bfb4fd5b9e..c8ffb0b804 100644
--- a/cpp/src/qpid/cluster/types.h
+++ b/cpp/src/qpid/cluster/types.h
@@ -34,6 +34,29 @@
extern "C" {
#if defined (HAVE_OPENAIS_CPG_H)
# include <openais/cpg.h>
+
+// Provide translations back to the deprecated definitions in openais
+typedef cpg_error_t cs_error_t;
+#define CS_DISPATCH_ONE CPG_DISPATCH_ONE
+#define CS_DISPATCH_ALL CPG_DISPATCH_ALL
+#define CS_DISPATCH_BLOCKING CPG_DISPATCH_BLOCKING
+#define CS_FLOW_CONTROL_DISABLED CPG_FLOW_CONTROL_DISABLED
+#define CS_FLOW_CONTROL_ENABLED CPG_FLOW_CONTROL_ENABLED
+#define CS_OK CPG_OK
+#define CS_ERR_LIBRARY CPG_ERR_LIBRARY
+#define CS_ERR_TIMEOUT CPG_ERR_TIMEOUT
+#define CS_ERR_TRY_AGAIN CPG_ERR_TRY_AGAIN
+#define CS_ERR_INVALID_PARAM CPG_ERR_INVALID_PARAM
+#define CS_ERR_NO_MEMORY CPG_ERR_NO_MEMORY
+#define CS_ERR_BAD_HANDLE CPG_ERR_BAD_HANDLE
+#define CS_ERR_BUSY CPG_ERR_BUSY
+#define CS_ERR_ACCESS CPG_ERR_ACCESS
+#define CS_ERR_NOT_EXIST CPG_ERR_NOT_EXIST
+#define CS_ERR_EXIST CPG_ERR_EXIST
+#define CS_ERR_NOT_SUPPORTED CPG_ERR_NOT_SUPPORTED
+#define CS_ERR_SECURITY CPG_ERR_SECURITY
+#define CS_ERR_TOO_MANY_GROUPS CPG_ERR_TOO_MANY_GROUPS
+
#elif defined (HAVE_COROSYNC_CPG_H)
# include <corosync/cpg.h>
#else
diff --git a/cpp/src/qpid/console/ClassKey.cpp b/cpp/src/qpid/console/ClassKey.cpp
index 7a16113bae..d4b59fc413 100644
--- a/cpp/src/qpid/console/ClassKey.cpp
+++ b/cpp/src/qpid/console/ClassKey.cpp
@@ -21,6 +21,7 @@
#include "qpid/console/ClassKey.h"
#include <string.h>
+#include <iostream>
#include <cstdio>
using namespace std;
diff --git a/cpp/src/qpid/framing/AMQCommandControlBody.h b/cpp/src/qpid/framing/AMQCommandControlBody.h
deleted file mode 100644
index d12b70a168..0000000000
--- a/cpp/src/qpid/framing/AMQCommandControlBody.h
+++ /dev/null
@@ -1,70 +0,0 @@
-#ifndef QPID_FRAMING_AMQCOMMANDCONTROLBODY_H
-#define QPID_FRAMING_AMQCOMMANDCONTROLBODY_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/amqp_0_10/helpers.h"
-#include "qpid/framing/AMQBody.h"
-
-namespace qpid {
-namespace framing {
-
-/**
- * AMQBody wrapper for Command and Control.
- * Temporary measure to fit with old code.
- */
-template <class T> class AMQCommandControlBody : public AMQBody, public T
-{
- public:
- virtual uint8_t type() const { return 100+T::SEGMENT_TYPE; }
-
- virtual void encode(Buffer& buffer) const {
- Codec::encode(buffer.getIterator(), static_cast<const T&>(*this));
- }
- virtual void decode(Buffer& buffer, uint32_t=0) {
- Codec::decode(buffer.getIterator(), static_cast<T&>(*this));
- }
- virtual uint32_t encodedSize() const {
- Codec::size(buffer.getIterator(), static_cast<const T&>(*this));
- }
-
- virtual void print(std::ostream& out) const {
- out << static_cast<const T&>(*this) << endl;
- }
- virtual void AMQBody::accept(AMQBodyConstVisitor&) const { assert(0); }
-};
-
-class CommandBody : public AMQCommandControlBody<amqp_0_10::Command> {
- using Command::accept; // Hide AMQBody::accept
- virtual Command* getCommand() { return this; }
- virtual const Command* getCommand() const { return this; }
-};
-
-class ControlBody : public AMQCommandControlBody<amqp_0_10::Control> {
- using Control::accept; // Hide AMQBody::accept
- virtual Control* getControl() { return this; }
- virtual const Control* getControl() const { return this; }
-};
-
-}} // namespace qpid::framing
-
-#endif /*!QPID_FRAMING_AMQCOMMANDCONTROLBODY_H*/
diff --git a/cpp/src/qpid/framing/AMQContentBody.cpp b/cpp/src/qpid/framing/AMQContentBody.cpp
index 72f7d9978e..18f6994f8f 100644
--- a/cpp/src/qpid/framing/AMQContentBody.cpp
+++ b/cpp/src/qpid/framing/AMQContentBody.cpp
@@ -24,7 +24,7 @@
qpid::framing::AMQContentBody::AMQContentBody(){
}
-qpid::framing::AMQContentBody::AMQContentBody(const string& _data) : data(_data){
+qpid::framing::AMQContentBody::AMQContentBody(const std::string& _data) : data(_data){
}
uint32_t qpid::framing::AMQContentBody::encodedSize() const{
diff --git a/cpp/src/qpid/framing/AMQContentBody.h b/cpp/src/qpid/framing/AMQContentBody.h
index e25451e354..148b293a2f 100644
--- a/cpp/src/qpid/framing/AMQContentBody.h
+++ b/cpp/src/qpid/framing/AMQContentBody.h
@@ -31,15 +31,15 @@ namespace framing {
class QPID_COMMON_CLASS_EXTERN AMQContentBody : public AMQBody
{
- string data;
+ std::string data;
public:
QPID_COMMON_EXTERN AMQContentBody();
- QPID_COMMON_EXTERN AMQContentBody(const string& data);
+ QPID_COMMON_EXTERN AMQContentBody(const std::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; }
+ inline const std::string& getData() const { return data; }
+ inline std::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);
diff --git a/cpp/src/qpid/framing/AMQFrame.cpp b/cpp/src/qpid/framing/AMQFrame.cpp
index 5b9673f0d0..5e065d598c 100644
--- a/cpp/src/qpid/framing/AMQFrame.cpp
+++ b/cpp/src/qpid/framing/AMQFrame.cpp
@@ -85,7 +85,7 @@ bool AMQFrame::decode(Buffer& buffer)
{
if(buffer.available() < frameOverhead())
return false;
- buffer.record();
+ uint32_t pos = buffer.getPosition();
uint8_t flags = buffer.getOctet();
uint8_t framing_version = (flags & 0xc0) >> 6;
@@ -115,7 +115,7 @@ bool AMQFrame::decode(Buffer& buffer)
// B,E,b,e flags
uint16_t body_size = frame_size - frameOverhead();
if (buffer.available() < body_size){
- buffer.restore();
+ buffer.setPosition(pos);
return false;
}
diff --git a/cpp/src/qpid/framing/Buffer.cpp b/cpp/src/qpid/framing/Buffer.cpp
index 5a5bc0325e..b71915aeb7 100644
--- a/cpp/src/qpid/framing/Buffer.cpp
+++ b/cpp/src/qpid/framing/Buffer.cpp
@@ -23,27 +23,17 @@
#include "qpid/Msg.h"
#include <string.h>
#include <boost/format.hpp>
+
namespace qpid {
namespace framing {
+using std::string;
+
Buffer::Buffer(char* _data, uint32_t _size)
: size(_size), data(_data), position(0) {
}
-void Buffer::record(){
- r_position = position;
-}
-
-void Buffer::restore(bool reRecord){
- uint32_t savedPosition = position;
-
- position = r_position;
-
- if (reRecord)
- r_position = savedPosition;
-}
-
void Buffer::reset(){
position = 0;
}
diff --git a/cpp/src/qpid/framing/FieldTable.cpp b/cpp/src/qpid/framing/FieldTable.cpp
index 0f7140b627..cd38db1ee8 100644
--- a/cpp/src/qpid/framing/FieldTable.cpp
+++ b/cpp/src/qpid/framing/FieldTable.cpp
@@ -196,7 +196,7 @@ void FieldTable::setFloat(const std::string& name, const float value){
flushRawCache();
}
-void FieldTable::setDouble(const std::string& name, double value){
+void FieldTable::setDouble(const std::string& name, const double value){
realDecode();
values[name] = ValuePtr(new DoubleValue(value));
flushRawCache();
diff --git a/cpp/src/qpid/framing/ProtocolInitiation.cpp b/cpp/src/qpid/framing/ProtocolInitiation.cpp
index e617015d64..00ddb55a3b 100644
--- a/cpp/src/qpid/framing/ProtocolInitiation.cpp
+++ b/cpp/src/qpid/framing/ProtocolInitiation.cpp
@@ -20,6 +20,8 @@
*/
#include "qpid/framing/ProtocolInitiation.h"
+#include <iostream>
+
namespace qpid {
namespace framing {
diff --git a/cpp/src/qpid/framing/Uuid.cpp b/cpp/src/qpid/framing/Uuid.cpp
index b3d1e2e1e4..e377c1172d 100644
--- a/cpp/src/qpid/framing/Uuid.cpp
+++ b/cpp/src/qpid/framing/Uuid.cpp
@@ -43,6 +43,13 @@ Uuid::Uuid(const uint8_t* data) {
assign(data);
}
+Uuid::Uuid(const std::string& s) {
+ if (s.size() != UNPARSED_SIZE)
+ throw IllegalArgumentException(QPID_MSG("Invalid UUID: " << s));
+ if (uuid_parse(const_cast<char *>(&s[0]), c_array()) != 0)
+ throw IllegalArgumentException(QPID_MSG("Invalid UUID: " << s));
+}
+
void Uuid::assign(const uint8_t* data) {
// This const cast is for Solaris which has a
// uuid_copy that takes a non const 2nd argument
diff --git a/cpp/src/qpid/ha/AlternateExchangeSetter.h b/cpp/src/qpid/ha/AlternateExchangeSetter.h
new file mode 100644
index 0000000000..08690e68bc
--- /dev/null
+++ b/cpp/src/qpid/ha/AlternateExchangeSetter.h
@@ -0,0 +1,73 @@
+#ifndef QPID_HA_ALTERNATEEXCHANGESETTER_H
+#define QPID_HA_ALTERNATEEXCHANGESETTER_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/log/Statement.h"
+#include "qpid/broker/Exchange.h"
+#include "qpid/broker/ExchangeRegistry.h"
+#include "boost/function.hpp"
+#include <map>
+
+namespace qpid {
+namespace ha {
+
+/**
+ * Sets the alternate exchange on queues and exchanges.
+ * Holds onto queues/exchanges if necessary till the alternate exchange is available.
+ * THREAD UNSAFE
+ */
+class AlternateExchangeSetter
+{
+ public:
+ typedef boost::function<void(boost::shared_ptr<broker::Exchange>)> SetFunction;
+
+ AlternateExchangeSetter(broker::ExchangeRegistry& er) : exchanges(er) {}
+
+ void setAlternate(const std::string& altEx, const SetFunction& setter) {
+ broker::Exchange::shared_ptr ex = exchanges.find(altEx);
+ if (ex) setter(ex); // Set immediately.
+ else setters.insert(Setters::value_type(altEx, setter)); // Save for later.
+ }
+
+ void addExchange(boost::shared_ptr<broker::Exchange> exchange) {
+ // Update the setters for this exchange
+ std::pair<Setters::iterator, Setters::iterator> range = setters.equal_range(exchange->getName());
+ for (Setters::iterator i = range.first; i != range.second; ++i)
+ i->second(exchange);
+ setters.erase(range.first, range.second);
+ }
+
+ void clear() {
+ if (!setters.empty())
+ QPID_LOG(warning, "Some alternate exchanges were not resolved.");
+ setters.clear();
+ }
+
+ private:
+ typedef std::multimap<std::string, SetFunction> Setters;
+ broker::ExchangeRegistry& exchanges;
+ Setters setters;
+};
+}} // namespace qpid::ha
+
+#endif /*!QPID_HA_ALTERNATEEXCHANGESETTER_H*/
diff --git a/cpp/src/qpid/ha/Backup.cpp b/cpp/src/qpid/ha/Backup.cpp
index 3f3fa87a01..bac6fd23c8 100644
--- a/cpp/src/qpid/ha/Backup.cpp
+++ b/cpp/src/qpid/ha/Backup.cpp
@@ -20,7 +20,6 @@
*/
#include "Backup.h"
#include "BrokerReplicator.h"
-#include "ConnectionExcluder.h"
#include "HaBroker.h"
#include "ReplicatingSubscription.h"
#include "Settings.h"
@@ -34,6 +33,7 @@
#include "qpid/framing/AMQFrame.h"
#include "qpid/framing/FieldTable.h"
#include "qpid/framing/MessageTransferBody.h"
+#include "qpid/sys/SystemInfo.h"
#include "qpid/types/Variant.h"
namespace qpid {
@@ -45,47 +45,85 @@ using types::Variant;
using std::string;
Backup::Backup(HaBroker& hb, const Settings& s) :
- haBroker(hb), broker(hb.getBroker()), settings(s), excluder(new ConnectionExcluder())
+ logPrefix("Backup: "), haBroker(hb), broker(hb.getBroker()), settings(s)
{
- // Exclude client connections before starting the link to avoid self-connection.
- broker.getConnectionObservers().add(excluder);
- // Empty brokerUrl means delay initialization until setUrl() is called.
+ // Empty brokerUrl means delay initialization until seBrokertUrl() is called.
if (!s.brokerUrl.empty()) initialize(Url(s.brokerUrl));
}
-void Backup::initialize(const Url& url) {
- if (url.empty()) throw Url::Invalid("HA broker URL is empty");
- QPID_LOG(notice, "HA: Backup initialized: " << url);
+bool Backup::isSelf(const Address& a) const {
+ return sys::SystemInfo::isLocalHost(a.host) &&
+ a.port == haBroker.getBroker().getPort(a.protocol);
+}
+
+// Remove my own address from the URL if possible.
+// This isn't 100% reliable given the many ways to specify a host,
+// but should work in most cases. We have additional measures to prevent
+// self-connection in ConnectionObserver
+Url Backup::removeSelf(const Url& brokers) const {
+ Url url;
+ for (Url::const_iterator i = brokers.begin(); i != brokers.end(); ++i)
+ if (!isSelf(*i)) url.push_back(*i);
+ if (url.empty())
+ throw Url::Invalid(logPrefix+"Failover URL is empty");
+ QPID_LOG(debug, logPrefix << "Failover URL (excluding self): " << url);
+ return url;
+}
+
+void Backup::initialize(const Url& brokers) {
+ if (brokers.empty()) throw Url::Invalid("HA broker URL is empty");
+ QPID_LOG(info, logPrefix << "Connecting to cluster, broker URL: " << brokers);
+ Url url = removeSelf(brokers);
string protocol = url[0].protocol.empty() ? "tcp" : url[0].protocol;
+ types::Uuid uuid(true);
// Declare the link
std::pair<Link::shared_ptr, bool> result = broker.getLinks().declare(
+ broker::QPID_NAME_PREFIX + string("ha.link.") + uuid.str(),
url[0].host, url[0].port, protocol,
- false, // durable
- settings.mechanism, settings.username, settings.password);
- link = result.first;
- link->setUrl(url);
- replicator.reset(new BrokerReplicator(haBroker, link));
- broker.getExchanges().registerExchange(replicator);
+ false, // durable
+ settings.mechanism, settings.username, settings.password,
+ false); // no amq.failover - don't want to use client URL.
+ {
+ sys::Mutex::ScopedLock l(lock);
+ link = result.first;
+ replicator.reset(new BrokerReplicator(haBroker, link));
+ replicator->initialize();
+ broker.getExchanges().registerExchange(replicator);
+ }
+ link->setUrl(url); // Outside the lock, once set link doesn't change.
}
Backup::~Backup() {
if (link) link->close();
if (replicator.get()) broker.getExchanges().destroy(replicator->getName());
- replicator.reset();
- broker.getConnectionObservers().remove(excluder); // This allows client connections.
}
-
+// Called via management.
void Backup::setBrokerUrl(const Url& url) {
// Ignore empty URLs seen during start-up for some tests.
if (url.empty()) return;
- sys::Mutex::ScopedLock l(lock);
- if (link) { // URL changed after we initialized.
- QPID_LOG(info, "HA: Backup broker URL set to " << url);
- link->setUrl(url);
+ bool linkSet = false;
+ {
+ sys::Mutex::ScopedLock l(lock);
+ linkSet = link;
+ }
+ if (linkSet) {
+ QPID_LOG(info, logPrefix << "Broker URL set to: " << url);
+ link->setUrl(removeSelf(url)); // Outside lock, once set link doesn't change
}
- else {
+ else
initialize(url); // Deferred initialization
+}
+
+void Backup::setStatus(BrokerStatus status) {
+ switch (status) {
+ case READY:
+ QPID_LOG(notice, logPrefix << "Ready to become primary.");
+ break;
+ case CATCHUP:
+ QPID_LOG(notice, logPrefix << "Catching up on primary, cannot be promoted.");
+ default:
+ assert(0);
}
}
diff --git a/cpp/src/qpid/ha/Backup.h b/cpp/src/qpid/ha/Backup.h
index 6c36996914..1233a473ec 100644
--- a/cpp/src/qpid/ha/Backup.h
+++ b/cpp/src/qpid/ha/Backup.h
@@ -36,7 +36,6 @@ class Link;
namespace ha {
class Settings;
-class ConnectionExcluder;
class BrokerReplicator;
class HaBroker;
@@ -51,9 +50,13 @@ class Backup
Backup(HaBroker&, const Settings&);
~Backup();
void setBrokerUrl(const Url&);
+ void setStatus(BrokerStatus);
private:
+ bool isSelf(const Address& a) const;
+ Url removeSelf(const Url&) const;
void initialize(const Url&);
+ std::string logPrefix;
sys::Mutex lock;
HaBroker& haBroker;
@@ -61,7 +64,6 @@ class Backup
Settings settings;
boost::shared_ptr<broker::Link> link;
boost::shared_ptr<BrokerReplicator> replicator;
- boost::shared_ptr<ConnectionExcluder> excluder;
};
}} // namespace qpid::ha
diff --git a/cpp/src/qpid/ha/ConnectionExcluder.h b/cpp/src/qpid/ha/BackupConnectionExcluder.h
index f8f2843a0c..ef537ab90a 100644
--- a/cpp/src/qpid/ha/ConnectionExcluder.h
+++ b/cpp/src/qpid/ha/BackupConnectionExcluder.h
@@ -1,5 +1,5 @@
-#ifndef QPID_HA_CONNECTIONEXCLUDER_H
-#define QPID_HA_CONNECTIONEXCLUDER_H
+#ifndef QPID_HA_BACKUPCONNECTIONEXCLUDER_H
+#define QPID_HA_BACKUPCONNECTIONEXCLUDER_H
/*
*
@@ -23,32 +23,26 @@
*/
#include "qpid/broker/ConnectionObserver.h"
-#include <boost/function.hpp>
+#include "qpid/broker/Connection.h"
+#include "qpid/log/Statement.h"
namespace qpid {
-
-namespace broker {
-class Connection;
-}
-
namespace ha {
/**
- * Exclude normal connections to a backup broker.
- * Admin connections are identified by a special flag in client-properties
- * during connection negotiation.
+ * Exclude connections to a backup broker.
*/
-class ConnectionExcluder : public broker::ConnectionObserver
+class BackupConnectionExcluder : public broker::ConnectionObserver
{
public:
- ConnectionExcluder();
-
- void opened(broker::Connection& connection);
+ void opened(broker::Connection& connection) {
+ QPID_LOG(debug, "Backup broker rejected connection "+connection.getMgmtId());
+ connection.abort();
+ }
- private:
- static const std::string ADMIN_TAG;
+ void closed(broker::Connection&) {}
};
}} // namespace qpid::ha
-#endif /*!QPID_HA_CONNECTIONEXCLUDER_H*/
+#endif /*!QPID_HA_BACKUPCONNECTIONEXCLUDER_H*/
diff --git a/cpp/src/qpid/ha/BrokerInfo.cpp b/cpp/src/qpid/ha/BrokerInfo.cpp
new file mode 100644
index 0000000000..c8bd1a14be
--- /dev/null
+++ b/cpp/src/qpid/ha/BrokerInfo.cpp
@@ -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.
+ *
+ */
+
+#include "BrokerInfo.h"
+#include "qpid/amqp_0_10/Codecs.h"
+#include "qpid/Exception.h"
+#include "qpid/log/Statement.h"
+#include "qpid/framing/FieldTable.h"
+#include "qpid/framing/FieldValue.h"
+#include <iostream>
+#include <iterator>
+#include <sstream>
+
+namespace qpid {
+namespace ha {
+
+namespace {
+std::string SYSTEM_ID="system-id";
+std::string HOST_NAME="host-name";
+std::string PORT="port";
+std::string STATUS="status";
+}
+
+using types::Uuid;
+using types::Variant;
+using framing::FieldTable;
+
+BrokerInfo::BrokerInfo(const std::string& host, uint16_t port_, const types::Uuid& id) :
+ hostName(host), port(port_), systemId(id)
+{
+ updateLogId();
+}
+
+void BrokerInfo::updateLogId() {
+ std::ostringstream o;
+ o << hostName << ":" << port;
+ logId = o.str();
+}
+
+FieldTable BrokerInfo::asFieldTable() const {
+ Variant::Map m = asMap();
+ FieldTable ft;
+ amqp_0_10::translate(m, ft);
+ return ft;
+}
+
+Variant::Map BrokerInfo::asMap() const {
+ Variant::Map m;
+ m[SYSTEM_ID] = systemId;
+ m[HOST_NAME] = hostName;
+ m[PORT] = port;
+ m[STATUS] = status;
+ return m;
+}
+
+void BrokerInfo::assign(const FieldTable& ft) {
+ Variant::Map m;
+ amqp_0_10::translate(ft, m);
+ assign(m);
+}
+
+namespace {
+const Variant& get(const Variant::Map& m, const std::string& k) {
+ Variant::Map::const_iterator i = m.find(k);
+ if (i == m.end()) throw Exception(
+ QPID_MSG("Missing field '" << k << "' in broker information"));
+ return i->second;
+}
+}
+
+void BrokerInfo::assign(const Variant::Map& m) {
+ systemId = get(m, SYSTEM_ID).asUuid();
+ hostName = get(m, HOST_NAME).asString();
+ port = get(m, PORT).asUint16();
+ status = BrokerStatus(get(m, STATUS).asUint8());
+ updateLogId();
+}
+
+std::ostream& operator<<(std::ostream& o, const BrokerInfo& b) {
+ return o << b.getHostName() << ":" << b.getPort() << "("
+ << printable(b.getStatus()) << ")";
+}
+
+std::ostream& operator<<(std::ostream& o, const BrokerInfo::Set& infos) {
+ std::ostream_iterator<BrokerInfo> out(o, " ");
+ copy(infos.begin(), infos.end(), out);
+ return o;
+}
+
+std::ostream& operator<<(std::ostream& o, const BrokerInfo::Map::value_type& v) {
+ return o << v.second;
+}
+
+std::ostream& operator<<(std::ostream& o, const BrokerInfo::Map& infos) {
+ std::ostream_iterator<BrokerInfo::Map::value_type> out(o, " ");
+ copy(infos.begin(), infos.end(), out);
+ return o;
+}
+
+}}
diff --git a/cpp/src/qpid/ha/BrokerInfo.h b/cpp/src/qpid/ha/BrokerInfo.h
new file mode 100644
index 0000000000..642f7c1361
--- /dev/null
+++ b/cpp/src/qpid/ha/BrokerInfo.h
@@ -0,0 +1,84 @@
+#ifndef QPID_HA_BROKERINFO_H
+#define QPID_HA_BROKERINFO_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 "types.h"
+#include "qpid/Url.h"
+#include "qpid/framing/FieldTable.h"
+#include "qpid/types/Uuid.h"
+#include "qpid/types/Variant.h"
+#include <string>
+#include <iosfwd>
+#include <vector>
+
+namespace qpid {
+namespace ha {
+
+/**
+ * Information about a cluster broker, maintained by the cluster primary.
+ */
+class BrokerInfo
+{
+ public:
+ typedef std::set<BrokerInfo> Set;
+ typedef std::map<types::Uuid, BrokerInfo> Map;
+
+ BrokerInfo() {}
+ BrokerInfo(const std::string& host, uint16_t port_, const types::Uuid& id);
+ BrokerInfo(const framing::FieldTable& ft) { assign(ft); }
+ BrokerInfo(const types::Variant::Map& m) { assign(m); }
+
+ types::Uuid getSystemId() const { return systemId; }
+ std::string getHostName() const { return hostName; }
+ BrokerStatus getStatus() const { return status; }
+ uint16_t getPort() const { return port; }
+ std::string getLogId() const { return logId; }
+
+ void setStatus(BrokerStatus s) { status = s; }
+
+ framing::FieldTable asFieldTable() const;
+ types::Variant::Map asMap() const;
+
+ void assign(const framing::FieldTable&);
+ void assign(const types::Variant::Map&);
+
+ // So it can be put in a set.
+ bool operator<(const BrokerInfo x) const { return systemId < x.systemId; }
+
+ private:
+ void updateLogId();
+ std::string logId;
+ std::string hostName;
+ uint16_t port;
+ types::Uuid systemId;
+ BrokerStatus status;
+};
+
+std::ostream& operator<<(std::ostream&, const BrokerInfo&);
+std::ostream& operator<<(std::ostream&, const BrokerInfo::Set&);
+std::ostream& operator<<(std::ostream&, const BrokerInfo::Map::value_type&);
+std::ostream& operator<<(std::ostream&, const BrokerInfo::Map&);
+
+}} // namespace qpid::ha
+
+#endif /*!QPID_HA_BROKERINFO_H*/
diff --git a/cpp/src/qpid/ha/BrokerReplicator.cpp b/cpp/src/qpid/ha/BrokerReplicator.cpp
index d0c99cbdb6..c8c4a42d72 100644
--- a/cpp/src/qpid/ha/BrokerReplicator.cpp
+++ b/cpp/src/qpid/ha/BrokerReplicator.cpp
@@ -22,6 +22,7 @@
#include "HaBroker.h"
#include "QueueReplicator.h"
#include "qpid/broker/Broker.h"
+#include "qpid/broker/Connection.h"
#include "qpid/broker/Queue.h"
#include "qpid/broker/Link.h"
#include "qpid/framing/FieldTable.h"
@@ -37,8 +38,11 @@
#include "qmf/org/apache/qpid/broker/EventQueueDeclare.h"
#include "qmf/org/apache/qpid/broker/EventQueueDelete.h"
#include "qmf/org/apache/qpid/broker/EventSubscribe.h"
+#include "qmf/org/apache/qpid/ha/EventMembersUpdate.h"
#include <algorithm>
#include <sstream>
+#include <iostream>
+#include <assert.h>
namespace qpid {
namespace ha {
@@ -50,15 +54,16 @@ using qmf::org::apache::qpid::broker::EventExchangeDelete;
using qmf::org::apache::qpid::broker::EventQueueDeclare;
using qmf::org::apache::qpid::broker::EventQueueDelete;
using qmf::org::apache::qpid::broker::EventSubscribe;
+using qmf::org::apache::qpid::ha::EventMembersUpdate;
using namespace framing;
using std::string;
+using std::ostream;
using types::Variant;
using namespace broker;
namespace {
const string QPID_CONFIGURATION_REPLICATOR("qpid.configuration-replicator");
-const string QPID_REPLICATE("qpid.replicate");
const string CLASS_NAME("_class_name");
const string EVENT("_event");
@@ -69,10 +74,13 @@ const string SCHEMA_ID("_schema_id");
const string VALUES("_values");
const string ALTEX("altEx");
+const string ALTEXCHANGE("altExchange");
const string ARGS("args");
const string ARGUMENTS("arguments");
const string AUTODEL("autoDel");
const string AUTODELETE("autoDelete");
+const string EXCL("excl");
+const string EXCLUSIVE("exclusive");
const string BIND("bind");
const string UNBIND("unbind");
const string BINDING("binding");
@@ -86,12 +94,12 @@ const string KEY("key");
const string NAME("name");
const string QNAME("qName");
const string QUEUE("queue");
-const string RHOST("rhost");
const string TYPE("type");
-const string USER("user");
const string HA_BROKER("habroker");
+const string PARTIAL("partial");
-const string AGENT_IND_EVENT_ORG_APACHE_QPID_BROKER("agent.ind.event.org_apache_qpid_broker.#");
+const string AGENT_EVENT_BROKER("agent.ind.event.org_apache_qpid_broker.#");
+const string AGENT_EVENT_HA("agent.ind.event.org_apache_qpid_ha.#");
const string QMF2("qmf2");
const string QMF_CONTENT("qmf.content");
const string QMF_DEFAULT_TOPIC("qmf.default.topic");
@@ -107,6 +115,7 @@ const string ORG_APACHE_QPID_HA("org.apache.qpid.ha");
const string QMF_DEFAULT_DIRECT("qmf.default.direct");
const string _QUERY_REQUEST("_query_request");
const string BROKER("broker");
+const string MEMBERS("members");
bool isQMFv2(const Message& message) {
const framing::MessageProperties* props = message.getProperties<framing::MessageProperties>();
@@ -117,7 +126,9 @@ template <class T> bool match(Variant::Map& schema) {
return T::match(schema[CLASS_NAME], schema[PACKAGE_NAME]);
}
-void sendQuery(const string& packageName, const string& className, const string& queueName, SessionHandler& sessionHandler) {
+void sendQuery(const string& packageName, const string& className, const string& queueName,
+ SessionHandler& sessionHandler)
+{
framing::AMQP_ServerProxy peer(sessionHandler.out);
Variant::Map request;
request[_WHAT] = OBJECT;
@@ -137,6 +148,7 @@ void sendQuery(const string& packageName, const string& className, const string&
props->setAppId(QMF2);
props->getApplicationHeaders().setString(QMF_OPCODE, _QUERY_REQUEST);
headerBody.get<qpid::framing::DeliveryProperties>(true)->setRoutingKey(BROKER);
+ headerBody.get<qpid::framing::MessageProperties>(true)->setCorrelationId(className);
AMQFrame header(headerBody);
header.setBof(false);
header.setEof(false);
@@ -159,39 +171,23 @@ Variant::Map asMapVoid(const Variant& value) {
if (!value.isVoid()) return value.asMap();
else return Variant::Map();
}
-
} // namespace
-
-ReplicateLevel BrokerReplicator::replicateLevel(const std::string& str) {
- ReplicateLevel rl;
- if (qpid::ha::replicateLevel(str, rl)) return rl;
- else return haBroker.getSettings().replicateDefault;
-}
-
-ReplicateLevel BrokerReplicator::replicateLevel(const framing::FieldTable& f) {
- if (f.isSet(QPID_REPLICATE))
- return replicateLevel(f.getAsString(QPID_REPLICATE));
- else
- return haBroker.getSettings().replicateDefault;
-}
-
-ReplicateLevel BrokerReplicator::replicateLevel(const Variant::Map& m) {
- Variant::Map::const_iterator i = m.find(QPID_REPLICATE);
- if (i != m.end())
- return replicateLevel(i->second.asString());
- else
- return haBroker.getSettings().replicateDefault;
-}
-
-BrokerReplicator::~BrokerReplicator() {}
-
BrokerReplicator::BrokerReplicator(HaBroker& hb, const boost::shared_ptr<Link>& l)
: Exchange(QPID_CONFIGURATION_REPLICATOR),
- haBroker(hb), broker(hb.getBroker()), link(l)
-{
+ logPrefix("Backup: "), replicationTest(hb.getReplicationTest()),
+ haBroker(hb), broker(hb.getBroker()), link(l),
+ initialized(false),
+ alternates(hb.getBroker().getExchanges())
+{}
+
+void BrokerReplicator::initialize() {
+ // Can't do this in the constructor because we need a shared_ptr to this.
+ types::Uuid uuid(true);
+ const std::string name(QPID_CONFIGURATION_REPLICATOR + ".bridge." + uuid.str());
broker.getLinks().declare(
- link->getHost(), link->getPort(),
+ name, // name for bridge
+ *link, // parent
false, // durable
QPID_CONFIGURATION_REPLICATOR, // src
QPID_CONFIGURATION_REPLICATOR, // dest
@@ -202,21 +198,41 @@ BrokerReplicator::BrokerReplicator(HaBroker& hb, const boost::shared_ptr<Link>&
"", // excludes
false, // dynamic
0, // sync?
- boost::bind(&BrokerReplicator::initializeBridge, this, _1, _2)
+ // shared_ptr keeps this in memory until outstanding initializeBridge
+ // calls are run.
+ boost::bind(&BrokerReplicator::initializeBridge, shared_from_this(), _1, _2)
);
}
+BrokerReplicator::~BrokerReplicator() { }
+
// This is called in the connection IO thread when the bridge is started.
void BrokerReplicator::initializeBridge(Bridge& bridge, SessionHandler& sessionHandler) {
- framing::AMQP_ServerProxy peer(sessionHandler.out);
+ // Use the credentials of the outgoing Link connection for creating queues,
+ // exchanges etc. We know link->getConnection() is non-zero because we are
+ // being called in the connections thread context.
+ //
+ assert(link->getConnection());
+ userId = link->getConnection()->getUserId();
+ remoteHost = link->getConnection()->getUrl();
+
+ link->getRemoteAddress(primary);
string queueName = bridge.getQueueName();
+
+ QPID_LOG(info, logPrefix << (initialized ? "Connecting" : "Failing over")
+ << " to primary " << primary
+ << " status:" << printable(haBroker.getStatus()));
+ initialized = true;
+
+ framing::AMQP_ServerProxy peer(sessionHandler.out);
const qmf::org::apache::qpid::broker::ArgsLinkBridge& args(bridge.getArgs());
//declare and bind an event queue
FieldTable declareArgs;
- declareArgs.setString(QPID_REPLICATE, str(RL_NONE));
+ declareArgs.setString(QPID_REPLICATE, printable(NONE).str());
peer.getQueue().declare(queueName, "", false, false, true, true, declareArgs);
- peer.getExchange().bind(queueName, QMF_DEFAULT_TOPIC, AGENT_IND_EVENT_ORG_APACHE_QPID_BROKER, FieldTable());
+ peer.getExchange().bind(queueName, QMF_DEFAULT_TOPIC, AGENT_EVENT_BROKER, FieldTable());
+ peer.getExchange().bind(queueName, QMF_DEFAULT_TOPIC, AGENT_EVENT_HA, FieldTable());
//subscribe to the queue
peer.getMessage().subscribe(queueName, args.i_dest, 1, 0, false, "", 0, FieldTable());
peer.getMessage().flow(args.i_dest, 0, 0xFFFFFFFF);
@@ -228,23 +244,30 @@ void BrokerReplicator::initializeBridge(Bridge& bridge, SessionHandler& sessionH
sendQuery(ORG_APACHE_QPID_BROKER, QUEUE, queueName, sessionHandler);
sendQuery(ORG_APACHE_QPID_BROKER, EXCHANGE, queueName, sessionHandler);
sendQuery(ORG_APACHE_QPID_BROKER, BINDING, queueName, sessionHandler);
- QPID_LOG(debug, "HA: Backup configuration bridge: " << queueName);
}
void BrokerReplicator::route(Deliverable& msg) {
+ // We transition from JOINING->CATCHUP on the first message received from the primary.
+ // Until now we couldn't be sure if we had a good connection to the primary.
+ if (haBroker.getStatus() == JOINING) {
+ haBroker.setStatus(CATCHUP);
+ QPID_LOG(notice, logPrefix << "Connected to primary " << primary);
+ }
+
const framing::FieldTable* headers = msg.getMessage().getApplicationHeaders();
+ const MessageProperties* messageProperties = msg.getMessage().getProperties<MessageProperties>();
Variant::List list;
try {
- if (!isQMFv2(msg.getMessage()) || !headers)
+ if (!isQMFv2(msg.getMessage()) || !headers || !messageProperties)
throw Exception("Unexpected message, not QMF2 event or query response.");
// decode as list
string content = msg.getMessage().getFrames().getContent();
amqp_0_10::ListCodec::decode(content, list);
-
+ QPID_LOG(trace, "Broker replicator received: " << *messageProperties);
if (headers->getAsString(QMF_CONTENT) == EVENT) {
for (Variant::List::iterator i = list.begin(); i != list.end(); ++i) {
Variant::Map& map = i->asMap();
- QPID_LOG(trace, "HA: Backup received event: " << map);
+ QPID_LOG(trace, "Broker replicator event: " << map);
Variant::Map& schema = map[SCHEMA_ID].asMap();
Variant::Map& values = map[VALUES].asMap();
if (match<EventQueueDeclare>(schema)) doEventQueueDeclare(values);
@@ -253,12 +276,13 @@ void BrokerReplicator::route(Deliverable& msg) {
else if (match<EventExchangeDelete>(schema)) doEventExchangeDelete(values);
else if (match<EventBind>(schema)) doEventBind(values);
else if (match<EventUnbind>(schema)) doEventUnbind(values);
+ else if (match<EventMembersUpdate>(schema)) doEventMembersUpdate(values);
}
} else if (headers->getAsString(QMF_OPCODE) == QUERY_RESPONSE) {
for (Variant::List::iterator i = list.begin(); i != list.end(); ++i) {
Variant::Map& map = i->asMap();
- QPID_LOG(trace, "HA: Backup received event: " << map);
- string type = map[SCHEMA_ID].asMap()[CLASS_NAME];
+ QPID_LOG(trace, "Broker replicator response: " << map);
+ string type = map[SCHEMA_ID].asMap()[CLASS_NAME].asString();
Variant::Map& values = map[VALUES].asMap();
framing::FieldTable args;
amqp_0_10::translate(asMapVoid(values[ARGUMENTS]), args);
@@ -267,85 +291,82 @@ void BrokerReplicator::route(Deliverable& msg) {
else if (type == BINDING) doResponseBind(values);
else if (type == HA_BROKER) doResponseHaBroker(values);
}
+ if (messageProperties->getCorrelationId() == EXCHANGE && !headers->isSet(PARTIAL)) {
+ // We have received all of the exchange response.
+ alternates.clear();
+ }
}
} catch (const std::exception& e) {
- QPID_LOG(critical, "HA: Backup configuration failed: " << e.what()
+ QPID_LOG(critical, logPrefix << "Configuration failed: " << e.what()
<< ": while handling: " << list);
+ haBroker.shutdown();
throw;
}
}
+
void BrokerReplicator::doEventQueueDeclare(Variant::Map& values) {
- string name = values[QNAME].asString();
Variant::Map argsMap = asMapVoid(values[ARGS]);
- if (values[DISP] == CREATED && replicateLevel(argsMap)) {
+ bool autoDel = values[AUTODEL].asBool();
+ bool excl = values[EXCL].asBool();
+ if (values[DISP] == CREATED &&
+ replicationTest.isReplicated(CONFIGURATION, argsMap, autoDel, excl))
+ {
+ string name = values[QNAME].asString();
+ QPID_LOG(debug, logPrefix << "Queue declare event: " << name);
framing::FieldTable args;
amqp_0_10::translate(argsMap, args);
- std::pair<boost::shared_ptr<Queue>, bool> result =
- broker.createQueue(
- name,
- values[DURABLE].asBool(),
- values[AUTODEL].asBool(),
- 0 /*i.e. no owner regardless of exclusivity on master*/,
- values[ALTEX].asString(),
- args,
- values[USER].asString(),
- values[RHOST].asString());
- if (result.second) {
- QPID_LOG(debug, "HA: Backup queue declare event: " << name);
- startQueueReplicator(result.first);
- } else {
- // FIXME aconway 2011-12-02: what's the right way to handle this?
- // Should we delete the old & re-create form the event? Responses
- // may be old but events are always up-to-date.
- QPID_LOG(warning, "HA: Backup queue declare event, already exists: " << name);
+ // If we already have a queue with this name, replace it.
+ // The queue was definitely created on the primary.
+ if (broker.getQueues().find(name)) {
+ QPID_LOG(warning, logPrefix << "Replacing exsiting queue: " << name);
+ broker.getQueues().destroy(name);
+ stopQueueReplicator(name);
}
+ boost::shared_ptr<Queue> queue = createQueue(
+ name, values[DURABLE].asBool(), autoDel, args, values[ALTEX].asString());
+ assert(queue); // Should be created since we destroed the previous queue above.
+ if (queue) startQueueReplicator(queue);
}
}
+boost::shared_ptr<QueueReplicator> BrokerReplicator::findQueueReplicator(
+ const std::string& qname)
+{
+ string rname = QueueReplicator::replicatorName(qname);
+ boost::shared_ptr<broker::Exchange> ex = broker.getExchanges().find(rname);
+ return boost::dynamic_pointer_cast<QueueReplicator>(ex);
+}
+
void BrokerReplicator::doEventQueueDelete(Variant::Map& values) {
// The remote queue has already been deleted so replicator
// sessions may be closed by a "queue deleted" exception.
string name = values[QNAME].asString();
boost::shared_ptr<Queue> queue = broker.getQueues().find(name);
- if (!queue) {
- QPID_LOG(warning, "HA: Backup queue delete event, does not exist: " << name);
- } else if (!replicateLevel(queue->getSettings())) {
- QPID_LOG(warning, "HA: Backup queue delete event, not replicated: " << name);
- } else {
- string rname = QueueReplicator::replicatorName(name);
- boost::shared_ptr<broker::Exchange> ex = broker.getExchanges().find(rname);
- boost::shared_ptr<QueueReplicator> qr = boost::dynamic_pointer_cast<QueueReplicator>(ex);
- if (qr) qr->deactivate();
- // QueueReplicator's bridge is now queued for destruction but may not
- // actually be destroyed, deleting the exhange
- broker.getExchanges().destroy(rname);
- broker.deleteQueue(name, values[USER].asString(), values[RHOST].asString());
- QPID_LOG(debug, "HA: Backup queue delete event: " << name);
+ if (queue && replicationTest.replicateLevel(queue->getSettings())) {
+ QPID_LOG(debug, logPrefix << "Queue delete event: " << name);
+ stopQueueReplicator(name);
+ broker.deleteQueue(name, userId, remoteHost);
}
}
void BrokerReplicator::doEventExchangeDeclare(Variant::Map& values) {
Variant::Map argsMap(asMapVoid(values[ARGS]));
- if (values[DISP] == CREATED && replicateLevel(argsMap)) {
+ if (!replicationTest.replicateLevel(argsMap)) return; // Not a replicated exchange.
+ if (values[DISP] == CREATED && replicationTest.replicateLevel(argsMap)) {
string name = values[EXNAME].asString();
+ QPID_LOG(debug, logPrefix << "Exchange declare event: " << name);
framing::FieldTable args;
amqp_0_10::translate(argsMap, args);
- if (broker.createExchange(
- name,
- values[EXTYPE].asString(),
- values[DURABLE].asBool(),
- values[ALTEX].asString(),
- args,
- values[USER].asString(),
- values[RHOST].asString()).second)
- {
- QPID_LOG(debug, "HA: Backup exchange declare event: " << name);
- } else {
- // FIXME aconway 2011-11-22: should delete pre-existing exchange
- // and re-create from event. See comment in doEventQueueDeclare.
- QPID_LOG(debug, "HA: Backup exchange declare event, already exists: " << name);
+ // If we already have a exchange with this name, replace it.
+ // The exchange was definitely created on the primary.
+ if (broker.getExchanges().find(name)) {
+ broker.getExchanges().destroy(name);
+ QPID_LOG(warning, logPrefix << "Replaced exsiting exchange: " << name);
}
+ boost::shared_ptr<Exchange> exchange =
+ createExchange(name, values[EXTYPE].asString(), values[DURABLE].asBool(), args, values[ALTEX].asString());
+ assert(exchange);
}
}
@@ -353,15 +374,12 @@ void BrokerReplicator::doEventExchangeDelete(Variant::Map& values) {
string name = values[EXNAME].asString();
boost::shared_ptr<Exchange> exchange = broker.getExchanges().find(name);
if (!exchange) {
- QPID_LOG(warning, "HA: Backup exchange delete event, does not exist: " << name);
- } else if (!replicateLevel(exchange->getArgs())) {
- QPID_LOG(warning, "HA: Backup exchange delete event, not replicated: " << name);
+ QPID_LOG(warning, logPrefix << "Exchange delete event, does not exist: " << name);
+ } else if (!replicationTest.replicateLevel(exchange->getArgs())) {
+ QPID_LOG(warning, logPrefix << "Exchange delete event, not replicated: " << name);
} else {
- QPID_LOG(debug, "HA: Backup exchange delete event:" << name);
- broker.deleteExchange(
- name,
- values[USER].asString(),
- values[RHOST].asString());
+ QPID_LOG(debug, logPrefix << "Exchange delete event:" << name);
+ broker.deleteExchange(name, userId, remoteHost);
}
}
@@ -372,16 +390,16 @@ void BrokerReplicator::doEventBind(Variant::Map& values) {
broker.getQueues().find(values[QNAME].asString());
// We only replicate binds for a replicated queue to replicated
// exchange that both exist locally.
- if (exchange && replicateLevel(exchange->getArgs()) &&
- queue && replicateLevel(queue->getSettings()))
+ if (exchange && replicationTest.replicateLevel(exchange->getArgs()) &&
+ queue && replicationTest.replicateLevel(queue->getSettings()))
{
framing::FieldTable args;
amqp_0_10::translate(asMapVoid(values[ARGS]), args);
string key = values[KEY].asString();
- exchange->bind(queue, key, &args);
- QPID_LOG(debug, "HA: Backup bind event: exchange=" << exchange->getName()
+ QPID_LOG(debug, logPrefix << "Bind event: exchange=" << exchange->getName()
<< " queue=" << queue->getName()
<< " key=" << key);
+ exchange->bind(queue, key, &args);
}
}
@@ -392,64 +410,71 @@ void BrokerReplicator::doEventUnbind(Variant::Map& values) {
broker.getQueues().find(values[QNAME].asString());
// We only replicate unbinds for a replicated queue to replicated
// exchange that both exist locally.
- if (exchange && replicateLevel(exchange->getArgs()) &&
- queue && replicateLevel(queue->getSettings()))
+ if (exchange && replicationTest.replicateLevel(exchange->getArgs()) &&
+ queue && replicationTest.replicateLevel(queue->getSettings()))
{
framing::FieldTable args;
amqp_0_10::translate(asMapVoid(values[ARGS]), args);
string key = values[KEY].asString();
- exchange->unbind(queue, key, &args);
- QPID_LOG(debug, "HA: Backup unbind event: exchange=" << exchange->getName()
+ QPID_LOG(debug, logPrefix << "Unbind event: exchange=" << exchange->getName()
<< " queue=" << queue->getName()
<< " key=" << key);
+ exchange->unbind(queue, key, &args);
}
}
+void BrokerReplicator::doEventMembersUpdate(Variant::Map& values) {
+ Variant::List members = values[MEMBERS].asList();
+ haBroker.setMembership(members);
+}
+
+namespace {
+
+// Get the alternate exchange from the exchange field of a queue or exchange response.
+static const string EXCHANGE_KEY_PREFIX("org.apache.qpid.broker:exchange:");
+
+string getAltExchange(const types::Variant& var) {
+ if (!var.isVoid()) {
+ management::ObjectId oid(var);
+ string key = oid.getV2Key();
+ if (key.find(EXCHANGE_KEY_PREFIX) != 0) throw Exception("Invalid exchange reference: "+key);
+ return key.substr(EXCHANGE_KEY_PREFIX.size());
+ }
+ else return string();
+}
+}
+
void BrokerReplicator::doResponseQueue(Variant::Map& values) {
Variant::Map argsMap(asMapVoid(values[ARGUMENTS]));
- if (!replicateLevel(argsMap)) return;
+ if (!replicationTest.isReplicated(
+ CONFIGURATION,
+ values[ARGUMENTS].asMap(),
+ values[AUTODELETE].asBool(),
+ values[EXCLUSIVE].asBool()))
+ return;
+ string name(values[NAME].asString());
+ QPID_LOG(debug, logPrefix << "Queue response: " << name);
framing::FieldTable args;
amqp_0_10::translate(argsMap, args);
- string name(values[NAME].asString());
- std::pair<boost::shared_ptr<Queue>, bool> result =
- broker.createQueue(
- name,
- values[DURABLE].asBool(),
- values[AUTODELETE].asBool(),
- 0 /*i.e. no owner regardless of exclusivity on master*/,
- ""/*TODO: need to include alternate-exchange*/,
- args,
- ""/*TODO: who is the user?*/,
- ""/*TODO: what should we use as connection id?*/);
- if (result.second) {
- QPID_LOG(debug, "HA: Backup queue response: " << name);
- startQueueReplicator(result.first);
- } else {
- // FIXME aconway 2011-11-22: Normal to find queue already
- // exists if we're failing over.
- QPID_LOG(warning, "HA: Backup queue response, already exists: " << name);
- }
+ boost::shared_ptr<Queue> queue =
+ createQueue(name, values[DURABLE].asBool(), values[AUTODELETE].asBool(), args,
+ getAltExchange(values[ALTEXCHANGE]));
+ // It is normal for the queue to already exist if we are failing over.
+ if (queue) startQueueReplicator(queue);
+ else QPID_LOG(debug, logPrefix << "Queue already replicated: " << name);
}
void BrokerReplicator::doResponseExchange(Variant::Map& values) {
Variant::Map argsMap(asMapVoid(values[ARGUMENTS]));
- if (!replicateLevel(argsMap)) return;
+ if (!replicationTest.replicateLevel(argsMap)) return;
+ string name = values[NAME].asString();
+ QPID_LOG(debug, logPrefix << "Exchange response: " << name);
framing::FieldTable args;
amqp_0_10::translate(argsMap, args);
- if (broker.createExchange(
- values[NAME].asString(),
- values[TYPE].asString(),
- values[DURABLE].asBool(),
- ""/*TODO: need to include alternate-exchange*/,
- args,
- ""/*TODO: who is the user?*/,
- ""/*TODO: what should we use as connection id?*/).second)
- {
- QPID_LOG(debug, "HA: Backup exchange response: " << values[NAME].asString());
- } else {
- QPID_LOG(warning, "HA: Backup exchange query, already exists: " <<
- values[QNAME].asString());
- }
+ boost::shared_ptr<Exchange> exchange = createExchange(
+ name, values[TYPE].asString(), values[DURABLE].asBool(), args,
+ getAltExchange(values[ALTEXCHANGE]));
+ QPID_LOG_IF(debug, !exchange, logPrefix << "Exchange already exists: " << name);
}
namespace {
@@ -480,16 +505,16 @@ void BrokerReplicator::doResponseBind(Variant::Map& values) {
boost::shared_ptr<Queue> queue = broker.getQueues().find(qName);
// Automatically replicate binding if queue and exchange exist and are replicated
- if (exchange && replicateLevel(exchange->getArgs()) &&
- queue && replicateLevel(queue->getSettings()))
+ if (exchange && replicationTest.replicateLevel(exchange->getArgs()) &&
+ queue && replicationTest.replicateLevel(queue->getSettings()))
{
+ string key = values[KEY].asString();
+ QPID_LOG(debug, logPrefix << "Bind response: exchange:" << exName
+ << " queue:" << qName
+ << " key:" << key);
framing::FieldTable args;
amqp_0_10::translate(asMapVoid(values[ARGUMENTS]), args);
- string key = values[KEY].asString();
exchange->bind(queue, key, &args);
- QPID_LOG(debug, "HA: Backup bind response: exchange=" << exchange->getName()
- << " queue=" << queue->getName()
- << " key=" << key);
}
}
@@ -500,30 +525,97 @@ const string REPLICATE_DEFAULT="replicateDefault";
// Received the ha-broker configuration object for the primary broker.
void BrokerReplicator::doResponseHaBroker(Variant::Map& values) {
try {
- ReplicateLevel mine = haBroker.getSettings().replicateDefault;
- ReplicateLevel primary = replicateLevel(values[REPLICATE_DEFAULT].asString());
- if (mine != primary) {
- std::ostringstream os;
- os << "Replicate default on backup (" << mine
- << ") does not match primary (" << primary << ")";
- haBroker.shutdown(os.str());
- }
+ QPID_LOG(trace, logPrefix << "HA Broker response: " << values);
+ ReplicateLevel mine = haBroker.getSettings().replicateDefault.get();
+ ReplicateLevel primary = replicationTest.replicateLevel(
+ values[REPLICATE_DEFAULT].asString());
+ if (mine != primary)
+ throw Exception(QPID_MSG("Replicate default on backup (" << mine
+ << ") does not match primary (" << primary << ")"));
+ haBroker.setMembership(values[MEMBERS].asList());
} catch (const std::exception& e) {
- std::ostringstream os;
- os << "Received invalid replicate default from primary: " << e.what();
- haBroker.shutdown(os.str());
+ QPID_LOG(critical, logPrefix << "Invalid HA Broker response: " << e.what()
+ << ": " << values);
+ haBroker.shutdown();
+ throw;
}
}
-void BrokerReplicator::startQueueReplicator(const boost::shared_ptr<Queue>& queue) {
- if (replicateLevel(queue->getSettings()) == RL_ALL) {
- boost::shared_ptr<QueueReplicator> qr(new QueueReplicator(queue, link));
+void BrokerReplicator::startQueueReplicator(const boost::shared_ptr<Queue>& queue)
+{
+ if (replicationTest.replicateLevel(queue->getSettings()) == ALL) {
+ boost::shared_ptr<QueueReplicator> qr(
+ new QueueReplicator(haBroker, queue, link));
if (!broker.getExchanges().registerExchange(qr))
throw Exception(QPID_MSG("Duplicate queue replicator " << qr->getName()));
qr->activate();
}
}
+void BrokerReplicator::stopQueueReplicator(const std::string& name) {
+ boost::shared_ptr<QueueReplicator> qr = findQueueReplicator(name);
+ if (qr) {
+ qr->deactivate();
+ // QueueReplicator's bridge is now queued for destruction but may not
+ // actually be destroyed.
+ broker.getExchanges().destroy(qr->getName());
+ }
+}
+
+boost::shared_ptr<Queue> BrokerReplicator::createQueue(
+ const std::string& name,
+ bool durable,
+ bool autodelete,
+ const qpid::framing::FieldTable& arguments,
+ const std::string& alternateExchange)
+{
+ std::pair<boost::shared_ptr<Queue>, bool> result =
+ broker.createQueue(
+ name,
+ durable,
+ autodelete,
+ 0, // no owner regardless of exclusivity on primary
+ string(), // Set alternate exchange below
+ arguments,
+ userId,
+ remoteHost);
+ if (result.second) {
+ if (!alternateExchange.empty()) {
+ alternates.setAlternate(
+ alternateExchange, boost::bind(&Queue::setAlternateExchange, result.first, _1));
+ }
+ return result.first;
+ }
+ else return boost::shared_ptr<Queue>();
+}
+
+boost::shared_ptr<Exchange> BrokerReplicator::createExchange(
+ const std::string& name,
+ const std::string& type,
+ bool durable,
+ const qpid::framing::FieldTable& args,
+ const std::string& alternateExchange)
+{
+ std::pair<boost::shared_ptr<Exchange>, bool> result =
+ broker.createExchange(
+ name,
+ type,
+ durable,
+ string(), // Set alternate exchange below
+ args,
+ userId,
+ remoteHost);
+ if (result.second) {
+ alternates.addExchange(result.first);
+ if (!alternateExchange.empty()) {
+ alternates.setAlternate(
+ alternateExchange, boost::bind(&Exchange::setAlternate, result.first, _1));
+ }
+ return result.first;
+ }
+ else return boost::shared_ptr<Exchange>();
+}
+
bool BrokerReplicator::bind(boost::shared_ptr<Queue>, const string&, const framing::FieldTable*) { return false; }
bool BrokerReplicator::unbind(boost::shared_ptr<Queue>, const string&, const framing::FieldTable*) { return false; }
bool BrokerReplicator::isBound(boost::shared_ptr<Queue>, const string* const, const framing::FieldTable* const) { return false; }
diff --git a/cpp/src/qpid/ha/BrokerReplicator.h b/cpp/src/qpid/ha/BrokerReplicator.h
index c9d7b9f74c..69653b876a 100644
--- a/cpp/src/qpid/ha/BrokerReplicator.h
+++ b/cpp/src/qpid/ha/BrokerReplicator.h
@@ -22,10 +22,15 @@
*
*/
-#include "ReplicateLevel.h"
+#include "types.h"
+#include "ReplicationTest.h"
+#include "AlternateExchangeSetter.h"
+#include "qpid/Address.h"
#include "qpid/broker/Exchange.h"
#include "qpid/types/Variant.h"
+#include "qpid/management/ManagementObject.h"
#include <boost/shared_ptr.hpp>
+#include <boost/enable_shared_from_this.hpp>
namespace qpid {
@@ -42,6 +47,7 @@ class FieldTable;
namespace ha {
class HaBroker;
+class QueueReplicator;
/**
* Replicate configuration on a backup broker.
@@ -51,28 +57,29 @@ class HaBroker;
* exchanges and bindings to replicate the primary.
* It also creates QueueReplicators for newly replicated queues.
*
- * THREAD SAFE: Has no mutable state.
+ * THREAD UNSAFE: Only called in Link connection thread, no need for locking.
*
*/
-class BrokerReplicator : public broker::Exchange
+class BrokerReplicator : public broker::Exchange,
+ public boost::enable_shared_from_this<BrokerReplicator>
{
public:
BrokerReplicator(HaBroker&, const boost::shared_ptr<broker::Link>&);
~BrokerReplicator();
- std::string getType() const;
+
+ void initialize();
// Exchange methods
+ std::string getType() const;
bool bind(boost::shared_ptr<broker::Queue>, const std::string&, const framing::FieldTable*);
bool unbind(boost::shared_ptr<broker::Queue>, const std::string&, const framing::FieldTable*);
void route(broker::Deliverable&);
bool isBound(boost::shared_ptr<broker::Queue>, const std::string* const, const framing::FieldTable* const);
private:
- void initializeBridge(broker::Bridge&, broker::SessionHandler&);
+ typedef boost::shared_ptr<QueueReplicator> QueueReplicatorPtr;
- ReplicateLevel replicateLevel(const std::string&);
- ReplicateLevel replicateLevel(const framing::FieldTable& args);
- ReplicateLevel replicateLevel(const types::Variant::Map& args);
+ void initializeBridge(broker::Bridge&, broker::SessionHandler&);
void doEventQueueDeclare(types::Variant::Map& values);
void doEventQueueDelete(types::Variant::Map& values);
@@ -80,17 +87,40 @@ class BrokerReplicator : public broker::Exchange
void doEventExchangeDelete(types::Variant::Map& values);
void doEventBind(types::Variant::Map&);
void doEventUnbind(types::Variant::Map&);
+ void doEventMembersUpdate(types::Variant::Map&);
void doResponseQueue(types::Variant::Map& values);
void doResponseExchange(types::Variant::Map& values);
void doResponseBind(types::Variant::Map& values);
void doResponseHaBroker(types::Variant::Map& values);
+ QueueReplicatorPtr findQueueReplicator(const std::string& qname);
void startQueueReplicator(const boost::shared_ptr<broker::Queue>&);
+ void stopQueueReplicator(const std::string& name);
+
+ boost::shared_ptr<broker::Queue> createQueue(
+ const std::string& name,
+ bool durable,
+ bool autodelete,
+ const qpid::framing::FieldTable& arguments,
+ const std::string& alternateExchange);
+
+ boost::shared_ptr<broker::Exchange> createExchange(
+ const std::string& name,
+ const std::string& type,
+ bool durable,
+ const qpid::framing::FieldTable& args,
+ const std::string& alternateExchange);
+ std::string logPrefix;
+ std::string userId, remoteHost;
+ ReplicationTest replicationTest;
HaBroker& haBroker;
broker::Broker& broker;
boost::shared_ptr<broker::Link> link;
+ bool initialized;
+ AlternateExchangeSetter alternates;
+ qpid::Address primary;
};
}} // namespace qpid::broker
diff --git a/cpp/src/qpid/ha/ConnectionExcluder.cpp b/cpp/src/qpid/ha/ConnectionExcluder.cpp
deleted file mode 100644
index 67ad7202d6..0000000000
--- a/cpp/src/qpid/ha/ConnectionExcluder.cpp
+++ /dev/null
@@ -1,40 +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 "ConnectionExcluder.h"
-#include "qpid/broker/Connection.h"
-#include <boost/function.hpp>
-#include <sstream>
-
-namespace qpid {
-namespace ha {
-
-ConnectionExcluder::ConnectionExcluder() {}
-
-void ConnectionExcluder::opened(broker::Connection& connection) {
- if (!connection.isLink() && !connection.getClientProperties().isSet(ADMIN_TAG))
- throw Exception(
- QPID_MSG("HA: Backup broker rejected connection " << connection.getMgmtId()));
-}
-
-const std::string ConnectionExcluder::ADMIN_TAG="qpid.ha-admin";
-
-}} // namespace qpid::ha
diff --git a/cpp/src/qpid/ha/ConnectionObserver.cpp b/cpp/src/qpid/ha/ConnectionObserver.cpp
new file mode 100644
index 0000000000..3f7a1710d9
--- /dev/null
+++ b/cpp/src/qpid/ha/ConnectionObserver.cpp
@@ -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.
+ *
+ */
+
+#include "ConnectionObserver.h"
+#include "BrokerInfo.h"
+#include "HaBroker.h"
+#include "qpid/framing/FieldTable.h"
+#include "qpid/broker/Connection.h"
+#include "qpid/log/Statement.h"
+
+namespace qpid {
+namespace ha {
+
+ConnectionObserver::ConnectionObserver(HaBroker& hb, const types::Uuid& uuid)
+ : haBroker(hb), logPrefix("Connections: "), self(uuid) {}
+
+bool ConnectionObserver::getBrokerInfo(broker::Connection& connection, BrokerInfo& info) {
+ framing::FieldTable ft;
+ if (connection.getClientProperties().getTable(ConnectionObserver::BACKUP_TAG, ft)) {
+ info = BrokerInfo(ft);
+ return true;
+ }
+ return false;
+}
+
+void ConnectionObserver::setObserver(const ObserverPtr& o){
+ sys::Mutex::ScopedLock l(lock);
+ observer = o;
+}
+
+ConnectionObserver::ObserverPtr ConnectionObserver::getObserver() {
+ sys::Mutex::ScopedLock l(lock);
+ return observer;
+}
+
+void ConnectionObserver::opened(broker::Connection& connection) {
+ try {
+ if (connection.isLink()) return; // Allow outgoing links.
+ if (connection.getClientProperties().isSet(ADMIN_TAG)) {
+ QPID_LOG(debug, logPrefix << "Allowing admin connection: "
+ << connection.getMgmtId());
+ return; // No need to call observer, always allow admins.
+ }
+ BrokerInfo info; // Avoid self connections.
+ if (getBrokerInfo(connection, info)) {
+ if (info.getSystemId() == self) {
+ QPID_LOG(debug, "HA broker rejected self connection "+connection.getMgmtId());
+ connection.abort();
+ }
+
+ }
+ ObserverPtr o(getObserver());
+ if (o) o->opened(connection);
+ }
+ catch (const std::exception& e) {
+ QPID_LOG(error, logPrefix << "Open error: " << e.what());
+ throw;
+ }
+}
+
+void ConnectionObserver::closed(broker::Connection& connection) {
+ try {
+ BrokerInfo info;
+ ObserverPtr o(getObserver());
+ if (o) o->closed(connection);
+ }
+ catch (const std::exception& e) {
+ QPID_LOG(error, logPrefix << "Close error: " << e.what());
+ throw;
+ }
+}
+
+const std::string ConnectionObserver::ADMIN_TAG="qpid.ha-admin";
+const std::string ConnectionObserver::BACKUP_TAG="qpid.ha-backup";
+
+}} // namespace qpid::ha
diff --git a/cpp/src/qpid/ha/ConnectionObserver.h b/cpp/src/qpid/ha/ConnectionObserver.h
new file mode 100644
index 0000000000..5c1dabe8f8
--- /dev/null
+++ b/cpp/src/qpid/ha/ConnectionObserver.h
@@ -0,0 +1,74 @@
+#ifndef QPID_HA_CONNECTIONOBSERVER_H
+#define QPID_HA_CONNECTIONOBSERVER_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 "types.h"
+#include "qpid/broker/ConnectionObserver.h"
+#include "qpid/types/Uuid.h"
+#include "qpid/sys/Mutex.h"
+#include "boost/shared_ptr.hpp"
+
+namespace qpid {
+namespace ha {
+class BrokerInfo;
+class HaBroker;
+
+/**
+ * Observes connections, delegates to another ConnectionObserver for
+ * actions specific to primary or backup.
+ *
+ * THREAD SAFE: called in arbitrary connection threads.
+ *
+ * Main role of this class is to provide a continuous observer object
+ * on the connection so we can't lose observations between removing
+ * one observer and adding another.
+ */
+class ConnectionObserver : public broker::ConnectionObserver
+{
+ public:
+ typedef boost::shared_ptr<broker::ConnectionObserver> ObserverPtr;
+
+ static const std::string ADMIN_TAG;
+ static const std::string BACKUP_TAG;
+
+ static bool getBrokerInfo(broker::Connection& connection, BrokerInfo& info);
+
+ ConnectionObserver(HaBroker& haBroker, const types::Uuid& self);
+
+ void setObserver(const ObserverPtr&);
+ ObserverPtr getObserver();
+
+ void opened(broker::Connection& connection);
+ void closed(broker::Connection& connection);
+
+ private:
+ sys::Mutex lock;
+ HaBroker& haBroker;
+ std::string logPrefix;
+ ObserverPtr observer;
+ types::Uuid self;
+};
+
+}} // namespace qpid::ha
+
+#endif /*!QPID_HA_CONNECTIONOBSERVER_H*/
diff --git a/cpp/src/qpid/ha/HaBroker.cpp b/cpp/src/qpid/ha/HaBroker.cpp
index 7d82fb63bd..d126639813 100644
--- a/cpp/src/qpid/ha/HaBroker.cpp
+++ b/cpp/src/qpid/ha/HaBroker.cpp
@@ -19,22 +19,31 @@
*
*/
#include "Backup.h"
-#include "ConnectionExcluder.h"
+#include "BackupConnectionExcluder.h"
+#include "ConnectionObserver.h"
#include "HaBroker.h"
-#include "Settings.h"
+#include "Primary.h"
+#include "QueueReplicator.h"
#include "ReplicatingSubscription.h"
+#include "Settings.h"
+#include "qpid/amqp_0_10/Codecs.h"
#include "qpid/Exception.h"
#include "qpid/broker/Broker.h"
#include "qpid/broker/Link.h"
#include "qpid/broker/Queue.h"
#include "qpid/broker/SignalHandler.h"
+#include "qpid/framing/FieldTable.h"
#include "qpid/management/ManagementAgent.h"
+#include "qpid/sys/SystemInfo.h"
+#include "qpid/types/Uuid.h"
+#include "qpid/framing/Uuid.h"
#include "qmf/org/apache/qpid/ha/Package.h"
#include "qmf/org/apache/qpid/ha/ArgsHaBrokerReplicate.h"
-#include "qmf/org/apache/qpid/ha/ArgsHaBrokerSetBrokers.h"
-#include "qmf/org/apache/qpid/ha/ArgsHaBrokerSetPublicBrokers.h"
-#include "qmf/org/apache/qpid/ha/ArgsHaBrokerSetExpectedBackups.h"
+#include "qmf/org/apache/qpid/ha/ArgsHaBrokerSetBrokersUrl.h"
+#include "qmf/org/apache/qpid/ha/ArgsHaBrokerSetPublicUrl.h"
+#include "qmf/org/apache/qpid/ha/EventMembersUpdate.h"
#include "qpid/log/Statement.h"
+#include <boost/shared_ptr.hpp>
namespace qpid {
namespace ha {
@@ -42,91 +51,149 @@ namespace ha {
namespace _qmf = ::qmf::org::apache::qpid::ha;
using namespace management;
using namespace std;
+using types::Variant;
+using types::Uuid;
+using sys::Mutex;
-namespace {
-
-const std::string STANDALONE="standalone";
-const std::string CATCH_UP="catch-up";
-const std::string BACKUP="backup";
-const std::string PRIMARY="primary";
-
-} // namespace
-
-
+// Called in Plugin::earlyInitialize
HaBroker::HaBroker(broker::Broker& b, const Settings& s)
- : broker(b),
+ : logPrefix("Broker: "),
+ broker(b),
+ systemId(broker.getSystem()->getSystemId().data()),
settings(s),
- mgmtObject(0)
+ observer(new ConnectionObserver(*this, systemId)),
+ mgmtObject(0),
+ status(STANDALONE),
+ membership(systemId),
+ replicationTest(s.replicateDefault.get())
{
- // Register a factory for replicating subscriptions.
- broker.getConsumerFactories().add(
- boost::shared_ptr<ReplicatingSubscription::Factory>(
- new ReplicatingSubscription::Factory()));
+ // If we are joining a cluster we must start excluding clients now,
+ // otherwise there's a window for a client to connect before we get to
+ // initialize()
+ if (settings.cluster) {
+ QPID_LOG(debug, logPrefix << "Rejecting client connections.");
+ observer->setObserver(boost::shared_ptr<broker::ConnectionObserver>(
+ new BackupConnectionExcluder));
+ broker.getConnectionObservers().add(observer);
+ }
+}
- broker.getKnownBrokers = boost::bind(&HaBroker::getKnownBrokers, this);
+// Called in Plugin::initialize
+void HaBroker::initialize() {
+ // FIXME aconway 2012-07-19: assumes there's a TCP transport with a meaningful port.
+ brokerInfo = BrokerInfo(
+ broker.getSystem()->getNodeName(), broker.getPort(broker::Broker::TCP_TRANSPORT), systemId);
+
+ // Set up the management object.
ManagementAgent* ma = broker.getManagementAgent();
- if (!ma)
+ if (settings.cluster && !ma)
throw Exception("Cannot start HA: management is disabled");
_qmf::Package packageInit(ma);
mgmtObject = new _qmf::HaBroker(ma, this, "ha-broker");
- mgmtObject->set_status(settings.cluster ? BACKUP : STANDALONE);
- mgmtObject->set_replicateDefault(str(settings.replicateDefault));
+ mgmtObject->set_replicateDefault(settings.replicateDefault.str());
+ mgmtObject->set_systemId(systemId);
ma->addObject(mgmtObject);
- // NOTE: lock is not needed in a constructor but we created it just to pass
- // to the set functions.
- sys::Mutex::ScopedLock l(lock);
- if (!settings.clientUrl.empty()) setClientUrl(Url(settings.clientUrl), l);
- if (!settings.brokerUrl.empty()) setBrokerUrl(Url(settings.brokerUrl), l);
+ // Register a factory for replicating subscriptions.
+ broker.getConsumerFactories().add(
+ boost::shared_ptr<ReplicatingSubscription::Factory>(
+ new ReplicatingSubscription::Factory()));
+
+ // If we are in a cluster, start as backup in joining state.
+ if (settings.cluster) {
+ status = JOINING;
+ backup.reset(new Backup(*this, settings));
+ broker.getKnownBrokers = boost::bind(&HaBroker::getKnownBrokers, this);
+ }
+
+ if (!settings.clientUrl.empty()) setClientUrl(Url(settings.clientUrl));
+ if (!settings.brokerUrl.empty()) setBrokerUrl(Url(settings.brokerUrl));
+
+
+ QPID_LOG(notice, logPrefix << "Initializing: " << brokerInfo);
- // If we are in a cluster, we start in backup mode.
- if (settings.cluster) backup.reset(new Backup(*this, s));
+ // NOTE: lock is not needed in a constructor, but create one
+ // to pass to functions that have a ScopedLock parameter.
+ Mutex::ScopedLock l(lock);
+ statusChanged(l);
}
-HaBroker::~HaBroker() {}
+HaBroker::~HaBroker() {
+ QPID_LOG(notice, logPrefix << "Shut down: " << brokerInfo);
+ broker.getConnectionObservers().remove(observer);
+}
+
+void HaBroker::recover() {
+ auto_ptr<Backup> b;
+ {
+ Mutex::ScopedLock l(lock);
+ // No longer replicating, close link. Note: link must be closed before we
+ // setStatus(RECOVERING) as that will remove our broker info from the
+ // outgoing link properties so we won't recognize self-connects.
+ b = backup;
+ }
+ b.reset(); // Call destructor outside of lock.
+ BrokerInfo::Set backups;
+ {
+ Mutex::ScopedLock l(lock);
+ setStatus(RECOVERING, l);
+ backups = membership.otherBackups();
+ membership.reset(brokerInfo);
+ // Drop the lock, new Primary may call back on activate.
+ }
+ // Outside of lock, may call back on activate()
+ primary.reset(new Primary(*this, backups)); // Starts primary-ready check.
+}
+
+// Called back from Primary active check.
+void HaBroker::activate() { setStatus(ACTIVE); }
Manageable::status_t HaBroker::ManagementMethod (uint32_t methodId, Args& args, string&) {
- sys::Mutex::ScopedLock l(lock);
switch (methodId) {
case _qmf::HaBroker::METHOD_PROMOTE: {
- if (backup.get()) { // I am a backup
- // NOTE: resetting backup allows client connections, so any
- // primary state should be set up here before backup.reset()
- backup.reset();
- QPID_LOG(notice, "HA: Promoted to primary");
- mgmtObject->set_status(PRIMARY);
+ switch (getStatus()) {
+ case JOINING: recover(); break;
+ case CATCHUP:
+ QPID_LOG(error, logPrefix << "Still catching up, cannot be promoted.");
+ throw Exception("Still catching up, cannot be promoted.");
+ break;
+ case READY: recover(); break;
+ case RECOVERING: break;
+ case ACTIVE: break;
+ case STANDALONE: break;
}
break;
}
- case _qmf::HaBroker::METHOD_SETBROKERS: {
- setBrokerUrl(Url(dynamic_cast<_qmf::ArgsHaBrokerSetBrokers&>(args).i_url), l);
+ case _qmf::HaBroker::METHOD_SETBROKERSURL: {
+ setBrokerUrl(Url(dynamic_cast<_qmf::ArgsHaBrokerSetBrokersUrl&>(args).i_url));
break;
}
- case _qmf::HaBroker::METHOD_SETPUBLICBROKERS: {
- setClientUrl(Url(dynamic_cast<_qmf::ArgsHaBrokerSetPublicBrokers&>(args).i_url), l);
+ case _qmf::HaBroker::METHOD_SETPUBLICURL: {
+ setClientUrl(Url(dynamic_cast<_qmf::ArgsHaBrokerSetPublicUrl&>(args).i_url));
break;
}
- case _qmf::HaBroker::METHOD_SETEXPECTEDBACKUPS: {
- setExpectedBackups(dynamic_cast<_qmf::ArgsHaBrokerSetExpectedBackups&>(args).i_expectedBackups, l);
- break;
- }
case _qmf::HaBroker::METHOD_REPLICATE: {
_qmf::ArgsHaBrokerReplicate& bq_args =
dynamic_cast<_qmf::ArgsHaBrokerReplicate&>(args);
- QPID_LOG(debug, "HA replicating individual queue "<< bq_args.i_queue << " from " << bq_args.i_broker);
+ QPID_LOG(debug, logPrefix << "Replicate individual queue "
+ << bq_args.i_queue << " from " << bq_args.i_broker);
boost::shared_ptr<broker::Queue> queue = broker.getQueues().get(bq_args.i_queue);
Url url(bq_args.i_broker);
string protocol = url[0].protocol.empty() ? "tcp" : url[0].protocol;
+ Uuid uuid(true);
std::pair<broker::Link::shared_ptr, bool> result = broker.getLinks().declare(
+ broker::QPID_NAME_PREFIX + string("ha.link.") + uuid.str(),
url[0].host, url[0].port, protocol,
false, // durable
- settings.mechanism, settings.username, settings.password);
+ settings.mechanism, settings.username, settings.password,
+ false); // no amq.failover - don't want to use client URL.
boost::shared_ptr<broker::Link> link = result.first;
link->setUrl(url);
// Create a queue replicator
- boost::shared_ptr<QueueReplicator> qr(new QueueReplicator(queue, link));
+ boost::shared_ptr<QueueReplicator> qr(
+ new QueueReplicator(*this, queue, link));
qr->activate();
broker.getExchanges().registerExchange(qr);
break;
@@ -138,43 +205,146 @@ Manageable::status_t HaBroker::ManagementMethod (uint32_t methodId, Args& args,
return Manageable::STATUS_OK;
}
-void HaBroker::setClientUrl(const Url& url, const sys::Mutex::ScopedLock& l) {
+void HaBroker::setClientUrl(const Url& url) {
+ Mutex::ScopedLock l(lock);
if (url.empty()) throw Exception("Invalid empty URL for HA client failover");
clientUrl = url;
updateClientUrl(l);
}
-void HaBroker::updateClientUrl(const sys::Mutex::ScopedLock&) {
+void HaBroker::updateClientUrl(Mutex::ScopedLock&) {
Url url = clientUrl.empty() ? brokerUrl : clientUrl;
if (url.empty()) throw Url::Invalid("HA client URL is empty");
- mgmtObject->set_publicBrokers(url.str());
+ mgmtObject->set_publicUrl(url.str());
knownBrokers.clear();
knownBrokers.push_back(url);
- QPID_LOG(debug, "HA: Setting client URL to: " << url);
+ QPID_LOG(debug, logPrefix << "Setting client URL to: " << url);
}
-void HaBroker::setBrokerUrl(const Url& url, const sys::Mutex::ScopedLock& l) {
+void HaBroker::setBrokerUrl(const Url& url) {
+ Mutex::ScopedLock l(lock);
if (url.empty()) throw Url::Invalid("HA broker URL is empty");
- QPID_LOG(debug, "HA: Setting broker URL to: " << url);
brokerUrl = url;
- mgmtObject->set_brokers(brokerUrl.str());
+ mgmtObject->set_brokersUrl(brokerUrl.str());
if (backup.get()) backup->setBrokerUrl(brokerUrl);
// Updating broker URL also updates defaulted client URL:
if (clientUrl.empty()) updateClientUrl(l);
}
-void HaBroker::setExpectedBackups(size_t n, const sys::Mutex::ScopedLock&) {
- expectedBackups = n;
- mgmtObject->set_expectedBackups(n);
-}
-
std::vector<Url> HaBroker::getKnownBrokers() const {
+ Mutex::ScopedLock l(lock);
return knownBrokers;
}
-void HaBroker::shutdown(const std::string& message) {
- QPID_LOG(critical, "Shutting down: " << message);
+void HaBroker::shutdown() {
+ QPID_LOG(critical, logPrefix << "Critical error, shutting down.");
broker.shutdown();
}
+BrokerStatus HaBroker::getStatus() const {
+ Mutex::ScopedLock l(lock);
+ return status;
+}
+
+void HaBroker::setStatus(BrokerStatus newStatus) {
+ Mutex::ScopedLock l(lock);
+ setStatus(newStatus, l);
+}
+
+namespace {
+bool checkTransition(BrokerStatus from, BrokerStatus to) {
+ // Legal state transitions. Initial state is JOINING, ACTIVE is terminal.
+ static const BrokerStatus TRANSITIONS[][2] = {
+ { JOINING, CATCHUP }, // Connected to primary
+ { JOINING, RECOVERING }, // Chosen as initial primary.
+ { CATCHUP, READY }, // Caught up all queues, ready to take over.
+ { READY, RECOVERING }, // Chosen as new primary
+ { READY, CATCHUP }, // Timed out failing over, demoted to catch-up.
+ { RECOVERING, ACTIVE } // All expected backups are ready
+ };
+ static const size_t N = sizeof(TRANSITIONS)/sizeof(TRANSITIONS[0]);
+ for (size_t i = 0; i < N; ++i) {
+ if (TRANSITIONS[i][0] == from && TRANSITIONS[i][1] == to)
+ return true;
+ }
+ return false;
+}
+} // namespace
+
+void HaBroker::setStatus(BrokerStatus newStatus, Mutex::ScopedLock& l) {
+ QPID_LOG(info, logPrefix << "Status change: "
+ << printable(status) << " -> " << printable(newStatus));
+ bool legal = checkTransition(status, newStatus);
+ assert(legal);
+ if (!legal) {
+ QPID_LOG(critical, logPrefix << "Illegal state transition: "
+ << printable(status) << " -> " << printable(newStatus));
+ shutdown();
+ }
+ status = newStatus;
+ statusChanged(l);
+}
+
+void HaBroker::statusChanged(Mutex::ScopedLock& l) {
+ mgmtObject->set_status(printable(status).str());
+ brokerInfo.setStatus(status);
+ setLinkProperties(l);
+}
+
+void HaBroker::membershipUpdated(Mutex::ScopedLock&) {
+ Variant::List brokers = membership.asList();
+ mgmtObject->set_members(brokers);
+ broker.getManagementAgent()->raiseEvent(_qmf::EventMembersUpdate(brokers));
+}
+
+void HaBroker::setMembership(const Variant::List& brokers) {
+ Mutex::ScopedLock l(lock);
+ membership.assign(brokers);
+ QPID_LOG(info, logPrefix << "Membership update: " << membership);
+ BrokerInfo info;
+ // Update my status to what the primary says it is. The primary can toggle
+ // status between READY and CATCHUP based on the state of our subscriptions.
+ if (membership.get(systemId, info) && status != info.getStatus()) {
+ setStatus(info.getStatus(), l);
+ if (backup.get()) backup->setStatus(status);
+ }
+ membershipUpdated(l);
+}
+
+void HaBroker::resetMembership(const BrokerInfo& b) {
+ Mutex::ScopedLock l(lock);
+ membership.reset(b);
+ QPID_LOG(debug, logPrefix << "Membership reset to: " << membership);
+ membershipUpdated(l);
+}
+
+void HaBroker::addBroker(const BrokerInfo& b) {
+ Mutex::ScopedLock l(lock);
+ membership.add(b);
+ QPID_LOG(debug, logPrefix << "Membership add: " << b << " now: " << membership);
+ membershipUpdated(l);
+}
+
+void HaBroker::removeBroker(const Uuid& id) {
+ Mutex::ScopedLock l(lock);
+ membership.remove(id);
+ QPID_LOG(debug, logPrefix << "Membership remove: " << id << " now: " << membership);
+ membershipUpdated(l);
+}
+
+void HaBroker::setLinkProperties(Mutex::ScopedLock&) {
+ framing::FieldTable linkProperties = broker.getLinkClientProperties();
+ if (isBackup(status)) {
+ // If this is a backup then any outgoing links are backup
+ // links and need to be tagged.
+ linkProperties.setTable(ConnectionObserver::BACKUP_TAG, brokerInfo.asFieldTable());
+ }
+ else {
+ // If this is a primary then any outgoing links are federation links
+ // and should not be tagged.
+ linkProperties.erase(ConnectionObserver::BACKUP_TAG);
+ }
+ broker.setLinkClientProperties(linkProperties);
+}
+
}} // namespace qpid::ha
diff --git a/cpp/src/qpid/ha/HaBroker.h b/cpp/src/qpid/ha/HaBroker.h
index 99b30fd36b..0ffc152097 100644
--- a/cpp/src/qpid/ha/HaBroker.h
+++ b/cpp/src/qpid/ha/HaBroker.h
@@ -22,31 +22,54 @@
*
*/
+#include "BrokerInfo.h"
+#include "Membership.h"
+#include "types.h"
+#include "ReplicationTest.h"
#include "Settings.h"
#include "qpid/Url.h"
#include "qpid/sys/Mutex.h"
#include "qmf/org/apache/qpid/ha/HaBroker.h"
#include "qpid/management/Manageable.h"
+#include "qpid/types/Variant.h"
#include <memory>
+#include <set>
+#include <boost/shared_ptr.hpp>
namespace qpid {
+
+namespace types {
+class Variant;
+}
+
namespace broker {
class Broker;
+class Queue;
+}
+namespace framing {
+class FieldTable;
}
+
namespace ha {
class Backup;
+class ConnectionObserver;
+class Primary;
/**
- * HA state and actions associated with a broker.
+ * HA state and actions associated with a HA broker. Holds all the management info.
*
* THREAD SAFE: may be called in arbitrary broker IO or timer threads.
*/
class HaBroker : public management::Manageable
{
public:
+ /** HaBroker is constructed during earlyInitialize */
HaBroker(broker::Broker&, const Settings&);
~HaBroker();
+ /** Called during plugin initialization */
+ void initialize();
+
// Implement Manageable.
qpid::management::ManagementObject* GetManagementObject() const { return mgmtObject; }
management::Manageable::status_t ManagementMethod (
@@ -55,26 +78,57 @@ class HaBroker : public management::Manageable
broker::Broker& getBroker() { return broker; }
const Settings& getSettings() const { return settings; }
- // Log a critical error message and shut down the broker.
- void shutdown(const std::string& message);
+ /** Shut down the broker. Caller should log a critical error message. */
+ void shutdown();
+
+ BrokerStatus getStatus() const;
+ void setStatus(BrokerStatus);
+ void activate();
+
+ Backup* getBackup() { return backup.get(); }
+ ReplicationTest getReplicationTest() const { return replicationTest; }
+
+ boost::shared_ptr<ConnectionObserver> getObserver() { return observer; }
+
+ const BrokerInfo& getBrokerInfo() const { return brokerInfo; }
+
+ void setMembership(const types::Variant::List&); // Set membership from list.
+ void resetMembership(const BrokerInfo& b); // Reset to contain just one member.
+ void addBroker(const BrokerInfo& b); // Add a broker to the membership.
+ void removeBroker(const types::Uuid& id); // Remove a broker from membership.
private:
- void setClientUrl(const Url&, const sys::Mutex::ScopedLock&);
- void setBrokerUrl(const Url&, const sys::Mutex::ScopedLock&);
- void setExpectedBackups(size_t, const sys::Mutex::ScopedLock&);
- void updateClientUrl(const sys::Mutex::ScopedLock&);
- bool isPrimary(const sys::Mutex::ScopedLock&) { return !backup.get(); }
+ void setClientUrl(const Url&);
+ void setBrokerUrl(const Url&);
+ void updateClientUrl(sys::Mutex::ScopedLock&);
+
+ bool isPrimary(sys::Mutex::ScopedLock&) { return !backup.get(); }
+
+ void setStatus(BrokerStatus, sys::Mutex::ScopedLock&);
+ void recover();
+ void statusChanged(sys::Mutex::ScopedLock&);
+ void setLinkProperties(sys::Mutex::ScopedLock&);
+
std::vector<Url> getKnownBrokers() const;
+ void membershipUpdated(sys::Mutex::ScopedLock&);
+
+ std::string logPrefix;
broker::Broker& broker;
+ types::Uuid systemId;
const Settings settings;
- sys::Mutex lock;
+ mutable sys::Mutex lock;
+ boost::shared_ptr<ConnectionObserver> observer; // Used by Backup and Primary
std::auto_ptr<Backup> backup;
+ std::auto_ptr<Primary> primary;
qmf::org::apache::qpid::ha::HaBroker* mgmtObject;
Url clientUrl, brokerUrl;
std::vector<Url> knownBrokers;
- size_t expectedBackups;
+ BrokerStatus status;
+ BrokerInfo brokerInfo;
+ Membership membership;
+ ReplicationTest replicationTest;
};
}} // namespace qpid::ha
diff --git a/cpp/src/qpid/ha/HaPlugin.cpp b/cpp/src/qpid/ha/HaPlugin.cpp
index 4da3b0d7d2..f7fe553d9b 100644
--- a/cpp/src/qpid/ha/HaPlugin.cpp
+++ b/cpp/src/qpid/ha/HaPlugin.cpp
@@ -20,7 +20,7 @@
#include "qpid/Plugin.h"
#include "qpid/Options.h"
#include "qpid/broker/Broker.h"
-
+#include <boost/bind.hpp>
namespace qpid {
namespace ha {
@@ -33,21 +33,21 @@ struct Options : public qpid::Options {
addOptions()
("ha-cluster", optValue(settings.cluster, "yes|no"),
"Join a HA active/passive cluster.")
- ("ha-brokers", optValue(settings.brokerUrl,"URL"),
- "URL that backup brokers use to connect and fail over.")
- ("ha-public-brokers", optValue(settings.clientUrl,"URL"),
- "URL that clients use to connect and fail over, defaults to ha-brokers.")
+ ("ha-brokers-url", optValue(settings.brokerUrl,"URL"),
+ "URL with address of each broker in the cluster.")
+ ("ha-public-url", optValue(settings.clientUrl,"URL"),
+ "URL advertized to clients to connect to the cluster.")
("ha-replicate",
optValue(settings.replicateDefault, "LEVEL"),
"Replication level for creating queues and exchanges if there is no qpid.replicate argument supplied. LEVEL is 'none', 'configuration' or 'all'")
- ("ha-expected-backups", optValue(settings.expectedBackups, "N"),
- "Number of backups expected to be active in the HA cluster.")
("ha-username", optValue(settings.username, "USER"),
"Username for connections between HA brokers")
("ha-password", optValue(settings.password, "PASS"),
"Password for connections between HA brokers")
("ha-mechanism", optValue(settings.mechanism, "MECH"),
"Authentication mechanism for connections between HA brokers")
+ ("ha-backup-timeout", optValue(settings.backupTimeout, "SECONDS"),
+ "Maximum time to wait for an expected backup to connect and become ready.")
;
}
};
@@ -62,14 +62,26 @@ struct HaPlugin : public Plugin {
Options* getOptions() { return &options; }
- void earlyInitialize(Plugin::Target& ) {}
+ void earlyInitialize(Plugin::Target& target) {
+ broker::Broker* broker = dynamic_cast<broker::Broker*>(&target);
+ if (broker) {
+ // Must create the HaBroker in earlyInitialize so it can set up its
+ // connection observer before clients start connecting.
+ haBroker.reset(new ha::HaBroker(*broker, settings));
+ broker->addFinalizer(boost::bind(&HaPlugin::finalize, this));
+ }
+ }
void initialize(Plugin::Target& target) {
broker::Broker* broker = dynamic_cast<broker::Broker*>(&target);
- if (broker) haBroker.reset(new ha::HaBroker(*broker, settings));
+ if (broker) haBroker->initialize();
+ }
+
+ void finalize() {
+ haBroker.reset();
}
};
-static HaPlugin instance; // Static initialization.
+HaPlugin instance; // Static initialization.
}} // namespace qpid::ha
diff --git a/cpp/src/qpid/ha/Membership.cpp b/cpp/src/qpid/ha/Membership.cpp
new file mode 100644
index 0000000000..cc2906dd8f
--- /dev/null
+++ b/cpp/src/qpid/ha/Membership.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 "Membership.h"
+#include <boost/bind.hpp>
+#include <iostream>
+#include <iterator>
+
+namespace qpid {
+namespace ha {
+
+
+void Membership::reset(const BrokerInfo& b) {
+ brokers.clear();
+ brokers[b.getSystemId()] = b;
+}
+
+void Membership::add(const BrokerInfo& b) {
+ brokers[b.getSystemId()] = b;
+}
+
+
+void Membership::remove(const types::Uuid& id) {
+ BrokerInfo::Map::iterator i = brokers.find(id);
+ if (i != brokers.end()) {
+ brokers.erase(i);
+ }
+}
+
+bool Membership::contains(const types::Uuid& id) {
+ return brokers.find(id) != brokers.end();
+}
+
+void Membership::assign(const types::Variant::List& list) {
+ brokers.clear();
+ for (types::Variant::List::const_iterator i = list.begin(); i != list.end(); ++i) {
+ BrokerInfo b(i->asMap());
+ brokers[b.getSystemId()] = b;
+ }
+}
+
+types::Variant::List Membership::asList() const {
+ types::Variant::List list;
+ for (BrokerInfo::Map::const_iterator i = brokers.begin(); i != brokers.end(); ++i)
+ list.push_back(i->second.asMap());
+ return list;
+}
+
+BrokerInfo::Set Membership::otherBackups() const {
+ BrokerInfo::Set result;
+ for (BrokerInfo::Map::const_iterator i = brokers.begin(); i != brokers.end(); ++i)
+ if (isBackup(i->second.getStatus()) && i->second.getSystemId() != self)
+ result.insert(i->second);
+ return result;
+}
+
+bool Membership::get(const types::Uuid& id, BrokerInfo& result) {
+ BrokerInfo::Map::iterator i = brokers.find(id);
+ if (i == brokers.end()) return false;
+ result = i->second;
+ return true;
+}
+
+std::ostream& operator<<(std::ostream& o, const Membership& members) {
+ return o << members.brokers;
+}
+
+}} // namespace qpid::ha
diff --git a/cpp/src/qpid/ha/Membership.h b/cpp/src/qpid/ha/Membership.h
new file mode 100644
index 0000000000..3bd8653a64
--- /dev/null
+++ b/cpp/src/qpid/ha/Membership.h
@@ -0,0 +1,68 @@
+#ifndef QPID_HA_MEMBERSHIP_H
+#define QPID_HA_MEMBERSHIP_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 "BrokerInfo.h"
+#include "types.h"
+#include "qpid/framing/Uuid.h"
+#include "qpid/log/Statement.h"
+#include "qpid/types/Variant.h"
+#include <boost/function.hpp>
+#include <set>
+#include <vector>
+#include <iosfwd>
+namespace qpid {
+namespace ha {
+
+/**
+ * Keep track of the brokers in the membership.
+ * THREAD UNSAFE: caller must serialize
+ */
+class Membership
+{
+ public:
+ Membership(const types::Uuid& self_) : self(self_) {}
+
+ void reset(const BrokerInfo& b); ///< Reset to contain just one member.
+ void add(const BrokerInfo& b);
+ void remove(const types::Uuid& id);
+ bool contains(const types::Uuid& id);
+ /** Return IDs of all backups other than self */
+ BrokerInfo::Set otherBackups() const;
+
+ void assign(const types::Variant::List&);
+ types::Variant::List asList() const;
+
+ bool get(const types::Uuid& id, BrokerInfo& result);
+
+ private:
+ types::Uuid self;
+ BrokerInfo::Map brokers;
+ friend std::ostream& operator<<(std::ostream&, const Membership&);
+};
+
+std::ostream& operator<<(std::ostream&, const Membership&);
+
+}} // namespace qpid::ha
+
+#endif /*!QPID_HA_MEMBERSHIP_H*/
diff --git a/cpp/src/qpid/ha/Primary.cpp b/cpp/src/qpid/ha/Primary.cpp
new file mode 100644
index 0000000000..69c94bfc7d
--- /dev/null
+++ b/cpp/src/qpid/ha/Primary.cpp
@@ -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.
+ *
+ */
+#include "Backup.h"
+#include "HaBroker.h"
+#include "Primary.h"
+#include "ReplicationTest.h"
+#include "ReplicatingSubscription.h"
+#include "RemoteBackup.h"
+#include "ConnectionObserver.h"
+#include "qpid/assert.h"
+#include "qpid/broker/Broker.h"
+#include "qpid/broker/ConfigurationObserver.h"
+#include "qpid/broker/Connection.h"
+#include "qpid/broker/Queue.h"
+#include "qpid/framing/FieldTable.h"
+#include "qpid/log/Statement.h"
+#include "qpid/sys/Timer.h"
+#include <boost/bind.hpp>
+
+namespace qpid {
+namespace ha {
+
+using sys::Mutex;
+
+namespace {
+
+class PrimaryConnectionObserver : public broker::ConnectionObserver
+{
+ public:
+ PrimaryConnectionObserver(Primary& p) : primary(p) {}
+ void opened(broker::Connection& c) { primary.opened(c); }
+ void closed(broker::Connection& c) { primary.closed(c); }
+ private:
+ Primary& primary;
+};
+
+class PrimaryConfigurationObserver : public broker::ConfigurationObserver
+{
+ public:
+ PrimaryConfigurationObserver(Primary& p) : primary(p) {}
+ void queueCreate(const Primary::QueuePtr& q) { primary.queueCreate(q); }
+ void queueDestroy(const Primary::QueuePtr& q) { primary.queueDestroy(q); }
+ private:
+ Primary& primary;
+};
+
+class ExpectedBackupTimerTask : public sys::TimerTask {
+ public:
+ ExpectedBackupTimerTask(Primary& p, sys::AbsTime deadline)
+ : TimerTask(deadline, "ExpectedBackupTimerTask"), primary(p) {}
+ void fire() { primary.timeoutExpectedBackups(); }
+ private:
+ Primary& primary;
+};
+
+} // namespace
+
+Primary* Primary::instance = 0;
+
+Primary::Primary(HaBroker& hb, const BrokerInfo::Set& expect) :
+ haBroker(hb), logPrefix("Primary: "), active(false)
+{
+ assert(instance == 0);
+ instance = this; // Let queue replicators find us.
+ if (expect.empty()) {
+ QPID_LOG(notice, logPrefix << "Promoted to primary. No expected backups.");
+ }
+ else {
+ // NOTE: RemoteBackups must be created before we set the ConfigurationObserver
+ // or ConnectionObserver so that there is no client activity while
+ // the QueueGuards are created.
+ QPID_LOG(notice, logPrefix << "Promoted to primary. Expected backups: " << expect);
+ for (BrokerInfo::Set::const_iterator i = expect.begin(); i != expect.end(); ++i) {
+ boost::shared_ptr<RemoteBackup> backup(
+ new RemoteBackup(*i, haBroker.getReplicationTest(), false));
+ backups[i->getSystemId()] = backup;
+ if (!backup->isReady()) expectedBackups.insert(backup);
+ backup->setInitialQueues(hb.getBroker().getQueues(), true); // Create guards
+ }
+ // Set timeout for expected brokers to connect and become ready.
+ sys::Duration timeout(int64_t(hb.getSettings().backupTimeout*sys::TIME_SEC));
+ sys::AbsTime deadline(sys::now(), timeout);
+ timerTask = new ExpectedBackupTimerTask(*this, deadline);
+ hb.getBroker().getTimer().add(timerTask);
+ }
+
+ configurationObserver.reset(new PrimaryConfigurationObserver(*this));
+ haBroker.getBroker().getConfigurationObservers().add(configurationObserver);
+
+ Mutex::ScopedLock l(lock); // We are now active as a configurationObserver
+ checkReady(l);
+ // Allow client connections
+ connectionObserver.reset(new PrimaryConnectionObserver(*this));
+ haBroker.getObserver()->setObserver(connectionObserver);
+}
+
+Primary::~Primary() {
+ if (timerTask) timerTask->cancel();
+ haBroker.getBroker().getConfigurationObservers().remove(configurationObserver);
+}
+
+void Primary::checkReady(Mutex::ScopedLock&) {
+ if (!active && expectedBackups.empty()) {
+ active = true;
+ Mutex::ScopedUnlock u(lock); // Don't hold lock across callback
+ QPID_LOG(notice, logPrefix << "Finished waiting for backups, primary is active.");
+ haBroker.activate();
+ }
+}
+
+void Primary::checkReady(BackupMap::iterator i, Mutex::ScopedLock& l) {
+ if (i != backups.end() && i->second->reportReady()) {
+ BrokerInfo info = i->second->getBrokerInfo();
+ info.setStatus(READY);
+ haBroker.addBroker(info);
+ if (expectedBackups.erase(i->second)) {
+ QPID_LOG(info, logPrefix << "Expected backup is ready: " << info);
+ checkReady(l);
+ }
+ else
+ QPID_LOG(info, logPrefix << "New backup is ready: " << info);
+ }
+}
+
+void Primary::timeoutExpectedBackups() {
+ try {
+ sys::Mutex::ScopedLock l(lock);
+ if (active) return; // Already activated
+ // Remove records for any expectedBackups that are not yet connected
+ // Allow backups that are connected to continue becoming ready.
+ for (BackupSet::iterator i = expectedBackups.begin(); i != expectedBackups.end();)
+ {
+ boost::shared_ptr<RemoteBackup> rb = *i;
+ if (!rb->isConnected()) {
+ BrokerInfo info = rb->getBrokerInfo();
+ QPID_LOG(error, logPrefix << "Expected backup timed out: " << info);
+ expectedBackups.erase(i++);
+ backups.erase(info.getSystemId());
+ rb->cancel();
+ // Downgrade the broker to CATCHUP
+ info.setStatus(CATCHUP);
+ haBroker.addBroker(info);
+ }
+ else ++i;
+ }
+ checkReady(l);
+ }
+ catch(const std::exception& e) {
+ QPID_LOG(error, logPrefix << "Error timing out backups: " << e.what());
+ // No-where for this exception to go.
+ }
+}
+
+void Primary::readyReplica(const ReplicatingSubscription& rs) {
+ sys::Mutex::ScopedLock l(lock);
+ BackupMap::iterator i = backups.find(rs.getBrokerInfo().getSystemId());
+ if (i != backups.end()) {
+ i->second->ready(rs.getQueue());
+ checkReady(i, l);
+ }
+}
+
+void Primary::queueCreate(const QueuePtr& q) {
+ // Throw if there is an invalid replication level in the queue settings.
+ haBroker.getReplicationTest().replicateLevel(q->getSettings());
+ Mutex::ScopedLock l(lock);
+ for (BackupMap::iterator i = backups.begin(); i != backups.end(); ++i) {
+ i->second->queueCreate(q);
+ checkReady(i, l);
+ }
+}
+
+void Primary::queueDestroy(const QueuePtr& q) {
+ Mutex::ScopedLock l(lock);
+ for (BackupMap::iterator i = backups.begin(); i != backups.end(); ++i)
+ i->second->queueDestroy(q);
+ checkReady(l);
+}
+
+void Primary::opened(broker::Connection& connection) {
+ BrokerInfo info;
+ if (ha::ConnectionObserver::getBrokerInfo(connection, info)) {
+ Mutex::ScopedLock l(lock);
+ BackupMap::iterator i = backups.find(info.getSystemId());
+ if (i == backups.end()) {
+ boost::shared_ptr<RemoteBackup> backup(
+ new RemoteBackup(info, haBroker.getReplicationTest(), true));
+ {
+ // Avoid deadlock with queue registry lock.
+ Mutex::ScopedUnlock u(lock);
+ backup->setInitialQueues(haBroker.getBroker().getQueues(), false);
+ }
+ backups[info.getSystemId()] = backup;
+ QPID_LOG(debug, logPrefix << "New backup connected: " << info);
+ }
+ else {
+ QPID_LOG(debug, logPrefix << "Known backup connected: " << info);
+ i->second->setConnected(true);
+ checkReady(i, l);
+ }
+ if (info.getStatus() == JOINING) info.setStatus(CATCHUP);
+ haBroker.addBroker(info);
+ }
+ else
+ QPID_LOG(debug, logPrefix << "Accepted client connection "
+ << connection.getMgmtId());
+}
+
+void Primary::closed(broker::Connection& connection) {
+ Mutex::ScopedLock l(lock);
+ BrokerInfo info;
+ if (ha::ConnectionObserver::getBrokerInfo(connection, info)) {
+ QPID_LOG(debug, logPrefix << "Backup disconnected: " << info);
+ haBroker.removeBroker(info.getSystemId());
+ BackupMap::iterator i = backups.find(info.getSystemId());
+ if (i != backups.end()) i->second->setConnected(false);
+ }
+ // NOTE: we do not remove from the backups map here, the backups map holds
+ // all the backups we know about whether connected or not.
+ //
+ // It is possible for a backup connection to be rejected while we are a backup,
+ // but the closed is seen after we have become primary. Removing the entry
+ // from backups in this case would be incorrect.
+}
+
+
+boost::shared_ptr<QueueGuard> Primary::getGuard(const QueuePtr& q, const BrokerInfo& info)
+{
+ Mutex::ScopedLock l(lock);
+ BackupMap::iterator i = backups.find(info.getSystemId());
+ return i == backups.end() ? boost::shared_ptr<QueueGuard>() : i->second->guard(q);
+}
+
+}} // namespace qpid::ha
diff --git a/cpp/src/qpid/ha/Primary.h b/cpp/src/qpid/ha/Primary.h
new file mode 100644
index 0000000000..26883f4416
--- /dev/null
+++ b/cpp/src/qpid/ha/Primary.h
@@ -0,0 +1,115 @@
+#ifndef QPID_HA_PRIMARY_H
+#define QPID_HA_PRIMARY_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 "types.h"
+#include "BrokerInfo.h"
+#include "qpid/sys/Mutex.h"
+#include <boost/shared_ptr.hpp>
+#include <boost/intrusive_ptr.hpp>
+#include <map>
+#include <string>
+
+namespace qpid {
+
+namespace broker {
+class Queue;
+class Connection;
+class ConnectionObserver;
+class ConfigurationObserver;
+}
+
+namespace sys {
+class TimerTask;
+}
+
+namespace ha {
+class HaBroker;
+class ReplicatingSubscription;
+class RemoteBackup;
+class QueueGuard;
+
+/**
+ * State associated with a primary broker:
+ * - sets queue guards and tracks readiness of initial backups till active.
+ * - sets queue guards on new queues for each backup.
+ *
+ * THREAD SAFE: called concurrently in arbitrary connection threads.
+ */
+class Primary
+{
+ public:
+ typedef boost::shared_ptr<broker::Queue> QueuePtr;
+
+ static Primary* get() { return instance; }
+
+ Primary(HaBroker& hb, const BrokerInfo::Set& expectedBackups);
+ ~Primary();
+
+ void readyReplica(const ReplicatingSubscription&);
+ void removeReplica(const std::string& q);
+
+ // Called via ConfigurationObserver
+ void queueCreate(const QueuePtr&);
+ void queueDestroy(const QueuePtr&);
+
+ // Called via ConnectionObserver
+ void opened(broker::Connection& connection);
+ void closed(broker::Connection& connection);
+
+ boost::shared_ptr<QueueGuard> getGuard(const QueuePtr& q, const BrokerInfo&);
+
+ // Called in timer thread when the deadline for expected backups expires.
+ void timeoutExpectedBackups();
+
+ private:
+ typedef std::map<types::Uuid, boost::shared_ptr<RemoteBackup> > BackupMap;
+ typedef std::set<boost::shared_ptr<RemoteBackup> > BackupSet;
+
+ void checkReady(sys::Mutex::ScopedLock&);
+ void checkReady(BackupMap::iterator, sys::Mutex::ScopedLock&);
+
+ sys::Mutex lock;
+ HaBroker& haBroker;
+ std::string logPrefix;
+ bool active;
+ /**
+ * Set of expected backups that must be ready before we declare ourselves
+ * active
+ */
+ BackupSet expectedBackups;
+ /**
+ * Map of all the remote backups we know about: any expected backups plus
+ * all actual backups that have connected. We do not remove entries when a
+ * backup disconnects. @see Primary::closed()
+ */
+ BackupMap backups;
+ boost::shared_ptr<broker::ConnectionObserver> connectionObserver;
+ boost::shared_ptr<broker::ConfigurationObserver> configurationObserver;
+ boost::intrusive_ptr<sys::TimerTask> timerTask;
+
+ static Primary* instance;
+};
+}} // namespace qpid::ha
+
+#endif /*!QPID_HA_PRIMARY_H*/
diff --git a/cpp/src/qpid/ha/QueueGuard.cpp b/cpp/src/qpid/ha/QueueGuard.cpp
new file mode 100644
index 0000000000..a30ab1f73c
--- /dev/null
+++ b/cpp/src/qpid/ha/QueueGuard.cpp
@@ -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.
+ *
+ */
+#include "QueueGuard.h"
+#include "ReplicatingSubscription.h"
+#include "qpid/broker/Queue.h"
+#include "qpid/broker/QueuedMessage.h"
+#include "qpid/broker/QueueObserver.h"
+#include "qpid/log/Statement.h"
+#include <boost/bind.hpp>
+#include <sstream>
+
+namespace qpid {
+namespace ha {
+
+using namespace broker;
+using sys::Mutex;
+using framing::SequenceNumber;
+using framing::SequenceSet;
+
+class QueueGuard::QueueObserver : public broker::QueueObserver
+{
+ public:
+ QueueObserver(QueueGuard& g) : guard(g) {}
+ void enqueued(const broker::QueuedMessage& qm) { guard.enqueued(qm); }
+ void dequeued(const broker::QueuedMessage& qm) { guard.dequeued(qm); }
+ void acquired(const broker::QueuedMessage&) {}
+ void requeued(const broker::QueuedMessage&) {}
+ private:
+ QueueGuard& guard;
+};
+
+
+
+QueueGuard::QueueGuard(broker::Queue& q, const BrokerInfo& info)
+ : queue(q), subscription(0)
+{
+ std::ostringstream os;
+ os << "Primary guard " << queue.getName() << "@" << info.getLogId() << ": ";
+ logPrefix = os.str();
+ observer.reset(new QueueObserver(*this));
+ queue.addObserver(observer);
+ // Set range after addObserver so we know that range.back+1 is a guarded position.
+ range = QueueRange(q);
+}
+
+QueueGuard::~QueueGuard() { cancel(); }
+
+// NOTE: Called with message lock held.
+void QueueGuard::enqueued(const QueuedMessage& qm) {
+ assert(qm.queue == &queue);
+ // Delay completion
+ QPID_LOG(trace, logPrefix << "Delayed completion of " << qm);
+ qm.payload->getIngressCompletion().startCompleter();
+ {
+ Mutex::ScopedLock l(lock);
+ assert(!delayed.contains(qm.position));
+ delayed += qm.position;
+ }
+}
+
+// NOTE: Called with message lock held.
+void QueueGuard::dequeued(const QueuedMessage& qm) {
+ assert(qm.queue == &queue);
+ QPID_LOG(trace, logPrefix << "Dequeued " << qm);
+ ReplicatingSubscription* rs=0;
+ {
+ Mutex::ScopedLock l(lock);
+ rs = subscription;
+ }
+ if (rs) rs->dequeued(qm);
+ complete(qm);
+}
+
+void QueueGuard::cancel() {
+ queue.removeObserver(observer);
+ {
+ Mutex::ScopedLock l(lock);
+ if (delayed.empty()) return; // No need if no delayed messages.
+ }
+ // FIXME aconway 2012-06-15: optimize, only messages in delayed set.
+ queue.eachMessage(boost::bind(&QueueGuard::complete, this, _1));
+}
+
+void QueueGuard::attach(ReplicatingSubscription& rs) {
+ Mutex::ScopedLock l(lock);
+ subscription = &rs;
+}
+
+namespace {
+void completeBefore(QueueGuard* guard, SequenceNumber position, const QueuedMessage& qm) {
+ if (qm.position <= position) guard->complete(qm);
+}
+}
+
+bool QueueGuard::subscriptionStart(SequenceNumber position) {
+ // Complete any messages before or at the ReplicatingSubscription start position.
+ // Those messages are already on the backup.
+ if (!delayed.empty() && delayed.front() <= position) {
+ // FIXME aconway 2012-06-15: queue iteration, only messages in delayed
+ queue.eachMessage(boost::bind(&completeBefore, this, position, _1));
+ }
+ return position >= range.back;
+}
+
+void QueueGuard::complete(const QueuedMessage& qm) {
+ assert(qm.queue == &queue);
+ {
+ Mutex::ScopedLock l(lock);
+ // The same message can be completed twice, by
+ // ReplicatingSubscription::acknowledged and dequeued. Remove it
+ // from the set so we only call finishCompleter() once
+ if (delayed.contains(qm.position))
+ delayed -= qm.position;
+ else
+ return;
+ }
+ QPID_LOG(trace, logPrefix << "Completed " << qm);
+ qm.payload->getIngressCompletion().finishCompleter();
+}
+
+}} // namespaces qpid::ha
diff --git a/cpp/src/qpid/ha/QueueGuard.h b/cpp/src/qpid/ha/QueueGuard.h
new file mode 100644
index 0000000000..bc8f40b65f
--- /dev/null
+++ b/cpp/src/qpid/ha/QueueGuard.h
@@ -0,0 +1,118 @@
+#ifndef QPID_HA_QUEUEGUARD_H
+#define QPID_HA_QUEUEGUARD_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 "types.h"
+#include "QueueRange.h"
+#include "qpid/framing/SequenceNumber.h"
+#include "qpid/framing/SequenceSet.h"
+#include "qpid/types/Uuid.h"
+#include "qpid/sys/Mutex.h"
+#include <boost/shared_ptr.hpp>
+#include <deque>
+#include <set>
+
+namespace qpid {
+namespace broker {
+class Queue;
+struct QueuedMessage;
+class Message;
+}
+
+namespace ha {
+class BrokerInfo;
+class ReplicatingSubscription;
+
+/**
+ * A queue guard is a QueueObserver that delays completion of new messages
+ * arriving on a queue. It works as part of a ReplicatingSubscription to ensure
+ * messages are not acknowledged till they have been replicated.
+ *
+ * The guard can be created before the ReplicatingSubscription to protect
+ * messages arriving before the creation of the subscription.
+ *
+ * THREAD SAFE: Concurrent calls:
+ * - enqueued() via QueueObserver in arbitrary connection threads.
+ * - attach(), cancel(), complete() from ReplicatingSubscription in subscription thread.
+ */
+class QueueGuard {
+ public:
+ QueueGuard(broker::Queue& q, const BrokerInfo&);
+ ~QueueGuard();
+
+ /** QueueObserver override. Delay completion of the message.
+ * NOTE: Called under the queues message lock.
+ */
+ void enqueued(const broker::QueuedMessage&);
+
+ /** QueueObserver override: Complete a delayed message.
+ * NOTE: Called under the queues message lock.
+ */
+ void dequeued(const broker::QueuedMessage&);
+
+ /** Complete a delayed message. */
+ void complete(const broker::QueuedMessage&);
+
+ /** Complete all delayed messages. */
+ void cancel();
+
+ void attach(ReplicatingSubscription&);
+
+ /**
+ * Return the un-guarded queue range at the time the QueueGuard was created.
+ *
+ * The first position guaranteed to be protected by the guard is
+ * getRange().getBack()+1. It is possible that the guard has protected some
+ * messages before that point. Any such messages are dealt with in subscriptionStart
+ *
+ * The QueueGuard is created in 3 situations
+ * - when a backup is promoted, guards are created for expected backups.
+ * - when a new queue is created on the primary
+ * - when a new backup joins.
+ *
+ * In the last situation the queue is active while the guard is being
+ * created.
+ *
+ */
+ const QueueRange& getRange() const { return range; } // range is immutable, no lock needed.
+
+ /** Inform the guard of the stating position for the attached subscription.
+ * Complete messages that will not be seen by the subscription.
+ *@return true if the subscription has already advanced to a guarded position.
+ */
+ bool subscriptionStart(framing::SequenceNumber position);
+
+ private:
+ class QueueObserver;
+
+ sys::Mutex lock;
+ std::string logPrefix;
+ broker::Queue& queue;
+ framing::SequenceSet delayed;
+ ReplicatingSubscription* subscription;
+ boost::shared_ptr<QueueObserver> observer;
+ QueueRange range;
+};
+}} // namespace qpid::ha
+
+#endif /*!QPID_HA_QUEUEGUARD_H*/
diff --git a/cpp/src/qpid/ha/QueueRange.h b/cpp/src/qpid/ha/QueueRange.h
new file mode 100644
index 0000000000..d734326910
--- /dev/null
+++ b/cpp/src/qpid/ha/QueueRange.h
@@ -0,0 +1,85 @@
+#ifndef QPID_HA_QUEUERANGE_H
+#define QPID_HA_QUEUERANGE_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 "ReplicatingSubscription.h"
+#include "qpid/broker/Queue.h"
+#include "qpid/framing/FieldTable.h"
+#include "qpid/framing/SequenceNumber.h"
+#include <iostream>
+
+namespace qpid {
+namespace ha {
+
+/**
+ * Get the front/back range of a queue or from a ReplicatingSubscription arguments table.
+ *
+ * The *back* of the queue is the position of the latest (most recently pushed)
+ * message on the queue or, if the queue is empty, the back is n-1 where n is
+ * the position that will be assigned to the next message pushed onto the queue.
+ *
+ * The *front* of the queue is the position of the oldest (next to be consumed) message
+ * on the queue or, if the queue is empty, it is the position that will be occupied
+ * by the next message pushed onto the queue.
+ *
+ * This leads to the slightly surprising conclusion that for an empty queue
+ * front = back+1
+ */
+struct QueueRange {
+ public:
+ framing::SequenceNumber front, back;
+
+ QueueRange() : front(1), back(0) { } // Empty range.
+
+ QueueRange(broker::Queue& q) {
+ if (ReplicatingSubscription::getFront(q, front))
+ back = q.getPosition();
+ else {
+ back = q.getPosition();
+ front = back+1; // empty
+ }
+ assert(front <= back + 1);
+ }
+
+ QueueRange(const framing::FieldTable& args) {
+ back = args.getAsInt(ReplicatingSubscription::QPID_BACK);
+ front = back+1;
+ if (args.isSet(ReplicatingSubscription::QPID_FRONT))
+ front = args.getAsInt(ReplicatingSubscription::QPID_FRONT);
+ if (back+1 < front)
+ throw Exception(QPID_MSG("Invalid range [" << front << "," << back <<"]"));
+ }
+
+ bool empty() const { return front == back+1; }
+};
+
+
+inline std::ostream& operator<<(std::ostream& o, const QueueRange& qr) {
+ if (qr.front > qr.back) return o << "[-," << qr.back << "]";
+ else return o << "[" << qr.front << "," << qr.back << "]";
+}
+
+
+}} // namespace qpid::ha
+
+#endif /*!QPID_HA_QUEUERANGE_H*/
diff --git a/cpp/src/qpid/ha/QueueReplicator.cpp b/cpp/src/qpid/ha/QueueReplicator.cpp
index 633619be13..be910a087f 100644
--- a/cpp/src/qpid/ha/QueueReplicator.cpp
+++ b/cpp/src/qpid/ha/QueueReplicator.cpp
@@ -19,6 +19,7 @@
*
*/
+#include "HaBroker.h"
#include "QueueReplicator.h"
#include "ReplicatingSubscription.h"
#include "qpid/broker/Bridge.h"
@@ -44,25 +45,39 @@ namespace ha {
using namespace broker;
using namespace framing;
-const std::string QueueReplicator::DEQUEUE_EVENT_KEY("qpid.dequeue-event");
-const std::string QueueReplicator::POSITION_EVENT_KEY("qpid.position-event");
+const std::string QPID_HA_EVENT_PREFIX("qpid.ha-event:");
+const std::string QueueReplicator::DEQUEUE_EVENT_KEY(QPID_HA_EVENT_PREFIX+"dequeue");
+const std::string QueueReplicator::POSITION_EVENT_KEY(QPID_HA_EVENT_PREFIX+"position");
std::string QueueReplicator::replicatorName(const std::string& queueName) {
return QPID_REPLICATOR_ + queueName;
}
-QueueReplicator::QueueReplicator(boost::shared_ptr<Queue> q, boost::shared_ptr<Link> l)
- : Exchange(replicatorName(q->getName()), 0, q->getBroker()), queue(q), link(l)
+bool QueueReplicator::isEventKey(const std::string key) {
+ const std::string& prefix = QPID_HA_EVENT_PREFIX;
+ bool ret = key.size() > prefix.size() && key.compare(0, prefix.size(), prefix) == 0;
+ return ret;
+}
+
+QueueReplicator::QueueReplicator(HaBroker& hb,
+ boost::shared_ptr<Queue> q,
+ boost::shared_ptr<Link> l)
+ : Exchange(replicatorName(q->getName()), 0, q->getBroker()),
+ haBroker(hb),
+ logPrefix("Backup queue "+q->getName()+": "),
+ queue(q), link(l), brokerInfo(hb.getBrokerInfo())
{
- logPrefix = "HA: Backup of " + queue->getName() + ": ";
- QPID_LOG(info, logPrefix << "Created");
+ Uuid uuid(true);
+ bridgeName = replicatorName(q->getName()) + std::string(".") + uuid.str();
}
// This must be separate from the constructor so we can call shared_from_this.
void QueueReplicator::activate() {
- // Note this may create a new bridge or use an existing one.
+ sys::Mutex::ScopedLock l(lock);
+ std::pair<Bridge::shared_ptr, bool> result =
queue->getBroker()->getLinks().declare(
- link->getHost(), link->getPort(),
+ bridgeName,
+ *link,
false, // durable
queue->getName(), // src
getName(), // dest
@@ -77,43 +92,47 @@ void QueueReplicator::activate() {
// before initializeBridge is called.
boost::bind(&QueueReplicator::initializeBridge, shared_from_this(), _1, _2)
);
+ bridge = result.first;
}
-QueueReplicator::~QueueReplicator() {}
+QueueReplicator::~QueueReplicator() { deactivate(); }
void QueueReplicator::deactivate() {
+ // destroy the route
sys::Mutex::ScopedLock l(lock);
- queue->getBroker()->getLinks().destroy(
- link->getHost(), link->getPort(), queue->getName(), getName(), string());
- QPID_LOG(debug, logPrefix << "Deactivated bridge " << bridgeName);
+ if (bridge) {
+ bridge->close();
+ bridge.reset();
+ QPID_LOG(debug, logPrefix << "Deactivated bridge " << bridgeName);
+ }
}
// Called in a broker connection thread when the bridge is created.
void QueueReplicator::initializeBridge(Bridge& bridge, SessionHandler& sessionHandler) {
sys::Mutex::ScopedLock l(lock);
- bridgeName = bridge.getName();
- framing::AMQP_ServerProxy peer(sessionHandler.out);
+ AMQP_ServerProxy peer(sessionHandler.out);
const qmf::org::apache::qpid::broker::ArgsLinkBridge& args(bridge.getArgs());
- framing::FieldTable settings;
-
- // FIXME aconway 2011-12-09: Failover optimization removed.
- // There was code here to re-use messages already on the backup
- // during fail-over. This optimization was removed to simplify
- // the logic till we get the basic replication stable, it
- // can be re-introduced later. Last revision with the optimization:
- // r1213258 | QPID-3603: Fix QueueReplicator subscription parameters.
-
- // Clear out any old messages, reset the queue to start replicating fresh.
- queue->purge();
- queue->setPosition(0);
-
+ FieldTable settings;
settings.setInt(ReplicatingSubscription::QPID_REPLICATING_SUBSCRIPTION, 1);
- // TODO aconway 2011-12-19: optimize.
- settings.setInt(QPID_SYNC_FREQUENCY, 1);
- peer.getMessage().subscribe(args.i_src, args.i_dest, 0/*accept-explicit*/, 1/*not-acquired*/, false/*exclusive*/, "", 0, settings);
+ settings.setInt(QPID_SYNC_FREQUENCY, 1); // FIXME aconway 2012-05-22: optimize?
+ settings.setInt(ReplicatingSubscription::QPID_BACK,
+ queue->getPosition());
+ settings.setTable(ReplicatingSubscription::QPID_BROKER_INFO,
+ brokerInfo.asFieldTable());
+ SequenceNumber front;
+ if (ReplicatingSubscription::getFront(*queue, front))
+ settings.setInt(ReplicatingSubscription::QPID_FRONT, front);
+ peer.getMessage().subscribe(
+ args.i_src, args.i_dest, 0/*accept-explicit*/, 1/*not-acquired*/,
+ false/*exclusive*/, "", 0, settings);
+ // FIXME aconway 2012-05-22: use a finite credit window?
peer.getMessage().flow(getName(), 0, 0xFFFFFFFF);
peer.getMessage().flow(getName(), 1, 0xFFFFFFFF);
- QPID_LOG(debug, logPrefix << "Activated bridge " << bridgeName);
+
+ qpid::Address primary;
+ link->getRemoteAddress(primary);
+ QPID_LOG(info, logPrefix << "Connected to " << primary << "(" << bridgeName << ")");
+ QPID_LOG(trace, logPrefix << "Subscription settings: " << settings);
}
namespace {
@@ -127,13 +146,11 @@ template <class T> T decodeContent(Message& m) {
}
}
-void QueueReplicator::dequeue(SequenceNumber n, const sys::Mutex::ScopedLock&) {
+void QueueReplicator::dequeue(SequenceNumber n, sys::Mutex::ScopedLock&) {
// Thread safe: only calls thread safe Queue functions.
- if (queue->getPosition() >= n) { // Ignore messages we haven't reached yet
- QueuedMessage message;
- if (queue->acquireMessageAt(n, message))
- queue->dequeue(0, message);
- }
+ QueuedMessage message;
+ if (queue->acquireMessageAt(n, message))
+ queue->dequeue(0, message);
}
// Called in connection thread of the queues bridge to primary.
@@ -142,29 +159,33 @@ void QueueReplicator::route(Deliverable& msg)
try {
const std::string& key = msg.getMessage().getRoutingKey();
sys::Mutex::ScopedLock l(lock);
- if (key == DEQUEUE_EVENT_KEY) {
+ if (!isEventKey(key)) {
+ msg.deliverTo(queue);
+ // We are on a backup so the queue is not modified except via this.
+ QPID_LOG(trace, logPrefix << "Enqueued message " << queue->getPosition());
+ }
+ else if (key == DEQUEUE_EVENT_KEY) {
SequenceSet dequeues = decodeContent<SequenceSet>(msg.getMessage());
QPID_LOG(trace, logPrefix << "Dequeue: " << dequeues);
//TODO: should be able to optimise the following
for (SequenceSet::iterator i = dequeues.begin(); i != dequeues.end(); i++)
dequeue(*i, l);
- } else if (key == POSITION_EVENT_KEY) {
+ }
+ else if (key == POSITION_EVENT_KEY) {
SequenceNumber position = decodeContent<SequenceNumber>(msg.getMessage());
QPID_LOG(trace, logPrefix << "Position moved from " << queue->getPosition()
<< " to " << position);
- if (queue->getPosition() > position) {
- throw Exception(
- QPID_MSG(logPrefix << "Invalid position update from "
- << queue->getPosition() << " to " << position));
- }
+ // Verify that there are no messages after the new position in the queue.
+ SequenceNumber next;
+ if (ReplicatingSubscription::getNext(*queue, position, next))
+ throw Exception("Invalid position move, preceeds messages");
queue->setPosition(position);
- } else {
- msg.deliverTo(queue);
- QPID_LOG(trace, logPrefix << "Enqueued message " << queue->getPosition());
}
+ // Ignore unknown event keys, may be introduced in later versions.
}
catch (const std::exception& e) {
QPID_LOG(critical, logPrefix << "Replication failed: " << e.what());
+ haBroker.shutdown();
throw;
}
}
diff --git a/cpp/src/qpid/ha/QueueReplicator.h b/cpp/src/qpid/ha/QueueReplicator.h
index bcbac988fa..f8a68ea38f 100644
--- a/cpp/src/qpid/ha/QueueReplicator.h
+++ b/cpp/src/qpid/ha/QueueReplicator.h
@@ -21,6 +21,8 @@
* under the License.
*
*/
+
+#include "BrokerInfo.h"
#include "qpid/broker/Exchange.h"
#include "qpid/framing/SequenceSet.h"
#include <boost/enable_shared_from_this.hpp>
@@ -38,6 +40,7 @@ class Deliverable;
}
namespace ha {
+class HaBroker;
/**
* Exchange created on a backup broker to replicate a queue on the primary.
@@ -55,8 +58,13 @@ class QueueReplicator : public broker::Exchange,
static const std::string DEQUEUE_EVENT_KEY;
static const std::string POSITION_EVENT_KEY;
static std::string replicatorName(const std::string& queueName);
+ /** Test if a string is an event key */
+ static bool isEventKey(const std::string key);
+
+ QueueReplicator(HaBroker&,
+ boost::shared_ptr<broker::Queue> q,
+ boost::shared_ptr<broker::Link> l);
- QueueReplicator(boost::shared_ptr<broker::Queue> q, boost::shared_ptr<broker::Link> l);
~QueueReplicator();
void activate(); // Call after ctor
@@ -71,13 +79,16 @@ class QueueReplicator : public broker::Exchange,
private:
void initializeBridge(broker::Bridge& bridge, broker::SessionHandler& sessionHandler);
- void dequeue(framing::SequenceNumber, const sys::Mutex::ScopedLock&);
+ void dequeue(framing::SequenceNumber, sys::Mutex::ScopedLock&);
+ HaBroker& haBroker;
std::string logPrefix;
std::string bridgeName;
sys::Mutex lock;
boost::shared_ptr<broker::Queue> queue;
boost::shared_ptr<broker::Link> link;
+ boost::shared_ptr<broker::Bridge> bridge;
+ BrokerInfo brokerInfo;
};
}} // namespace qpid::ha
diff --git a/cpp/src/qpid/ha/RemoteBackup.cpp b/cpp/src/qpid/ha/RemoteBackup.cpp
new file mode 100644
index 0000000000..a5693fd14e
--- /dev/null
+++ b/cpp/src/qpid/ha/RemoteBackup.cpp
@@ -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.
+ *
+ */
+#include "RemoteBackup.h"
+#include "QueueGuard.h"
+#include "qpid/broker/Broker.h"
+#include "qpid/broker/Queue.h"
+#include "qpid/broker/QueueRegistry.h"
+#include <boost/bind.hpp>
+
+namespace qpid {
+namespace ha {
+
+using sys::Mutex;
+using boost::bind;
+
+RemoteBackup::RemoteBackup(const BrokerInfo& info, ReplicationTest rt, bool con) :
+ logPrefix("Primary remote backup "+info.getLogId()+": "),
+ brokerInfo(info), replicationTest(rt), connected(con), reportedReady(false)
+{}
+
+void RemoteBackup::setInitialQueues(broker::QueueRegistry& queues, bool createGuards)
+{
+ QPID_LOG(debug, logPrefix << "Setting initial queues" << (createGuards ? " and guards" : ""));
+ queues.eachQueue(boost::bind(&RemoteBackup::initialQueue, this, _1, createGuards));
+}
+
+RemoteBackup::~RemoteBackup() { cancel(); }
+
+void RemoteBackup::cancel() {
+ for (GuardMap::iterator i = guards.begin(); i != guards.end(); ++i)
+ i->second->cancel();
+ guards.clear();
+}
+
+bool RemoteBackup::isReady() {
+ return connected && initialQueues.empty();
+}
+
+void RemoteBackup::initialQueue(const QueuePtr& q, bool createGuard) {
+ if (replicationTest.isReplicated(ALL, *q)) {
+ initialQueues.insert(q);
+ if (createGuard) guards[q].reset(new QueueGuard(*q, brokerInfo));
+ }
+}
+
+RemoteBackup::GuardPtr RemoteBackup::guard(const QueuePtr& q) {
+ GuardMap::iterator i = guards.find(q);
+ GuardPtr guard;
+ if (i != guards.end()) {
+ guard = i->second;
+ guards.erase(i);
+ }
+ return guard;
+}
+
+namespace {
+typedef std::set<boost::shared_ptr<broker::Queue> > QS;
+struct QueueSetPrinter {
+ const QS& qs;
+ std::string prefix;
+ QueueSetPrinter(const std::string& p, const QS& q) : qs(q), prefix(p) {}
+};
+std::ostream& operator<<(std::ostream& o, const QueueSetPrinter& qp) {
+ if (!qp.qs.empty()) o << qp.prefix;
+ for (QS::const_iterator i = qp.qs.begin(); i != qp.qs.end(); ++i)
+ o << (*i)->getName() << " ";
+ return o;
+}
+}
+
+void RemoteBackup::ready(const QueuePtr& q) {
+ initialQueues.erase(q);
+ QPID_LOG(debug, logPrefix << "Queue ready: " << q->getName()
+ << QueueSetPrinter(", waiting for: ", initialQueues));
+ if (isReady()) QPID_LOG(debug, logPrefix << "All queues ready");
+}
+
+// Called via ConfigurationObserver::queueCreate and from initialQueue
+void RemoteBackup::queueCreate(const QueuePtr& q) {
+ if (replicationTest.isReplicated(ALL, *q))
+ guards[q].reset(new QueueGuard(*q, brokerInfo));
+}
+
+// Called via ConfigurationObserver
+void RemoteBackup::queueDestroy(const QueuePtr& q) {
+ initialQueues.erase(q);
+ GuardMap::iterator i = guards.find(q);
+ if (i != guards.end()) {
+ i->second->cancel();
+ guards.erase(i);
+ }
+}
+
+bool RemoteBackup::reportReady() {
+ if (!reportedReady && isReady()) {
+ reportedReady = true;
+ return true;
+ }
+ return false;
+}
+
+}} // namespace qpid::ha
diff --git a/cpp/src/qpid/ha/RemoteBackup.h b/cpp/src/qpid/ha/RemoteBackup.h
new file mode 100644
index 0000000000..8ee776e90b
--- /dev/null
+++ b/cpp/src/qpid/ha/RemoteBackup.h
@@ -0,0 +1,111 @@
+#ifndef QPID_HA_REMOTEBACKUP_H
+#define QPID_HA_REMOTEBACKUP_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 "ReplicationTest.h"
+#include "BrokerInfo.h"
+#include "types.h"
+#include <set>
+#include <map>
+
+namespace qpid {
+
+namespace broker {
+class Queue;
+class QueueRegistry;
+}
+
+namespace ha {
+class QueueGuard;
+
+/**
+ * Track readiness for a remote broker.
+ * Creates queue guards on behalf of the remote broker to keep
+ * queues safe till the ReplicatingSubscription is ready.
+ *
+ * THREAD UNSAFE: Caller must serialize.
+ */
+class RemoteBackup
+{
+ public:
+ typedef boost::shared_ptr<QueueGuard> GuardPtr;
+ typedef boost::shared_ptr<broker::Queue> QueuePtr;
+
+ /** Note: isReady() can be true after construction
+ *@param connected true if the backup is already connected.
+ */
+ RemoteBackup(const BrokerInfo& info, ReplicationTest, bool connected);
+ ~RemoteBackup();
+
+ /** Set the initial queues for all queues in the registry.
+ *@createGuards if true create guards also, if false guards will be created on demand.
+ */
+ void setInitialQueues(broker::QueueRegistry&, bool createGuards);
+
+ /** Return guard associated with a queue. Used to create ReplicatingSubscription. */
+ GuardPtr guard(const QueuePtr&);
+
+ /** Is the remote backup connected? */
+ void setConnected(bool b) { connected=b; }
+ bool isConnected() const { return connected; }
+
+ /** ReplicatingSubscription associated with queue is ready.
+ * Note: may set isReady()
+ */
+ void ready(const QueuePtr& queue);
+
+ /** Called via ConfigurationObserver */
+ void queueCreate(const QueuePtr&);
+
+ /** Called via ConfigurationObserver. Note: may set isReady() */
+ void queueDestroy(const QueuePtr&);
+
+ /**@return true when all initial queues for this backup are ready. */
+ bool isReady();
+
+ /**@return true if isReady() and this is the first call to reportReady */
+ bool reportReady();
+
+ /**Cancel all queue guards, called if we are timed out. */
+ void cancel();
+
+ BrokerInfo getBrokerInfo() const { return brokerInfo; }
+ private:
+ typedef std::map<QueuePtr, GuardPtr> GuardMap;
+ typedef std::set<QueuePtr> QueueSet;
+
+ /** Add queue to guard as an initial queue */
+ void initialQueue(const QueuePtr&, bool createGuard);
+
+ std::string logPrefix;
+ BrokerInfo brokerInfo;
+ ReplicationTest replicationTest;
+ GuardMap guards;
+ QueueSet initialQueues;
+ bool connected;
+ bool reportedReady;
+};
+
+}} // namespace qpid::ha
+
+#endif /*!QPID_HA_REMOTEBACKUP_H*/
diff --git a/cpp/src/qpid/ha/ReplicateLevel.cpp b/cpp/src/qpid/ha/ReplicateLevel.cpp
deleted file mode 100644
index 4981577225..0000000000
--- a/cpp/src/qpid/ha/ReplicateLevel.cpp
+++ /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.
- *
- */
-#include "ReplicateLevel.h"
-#include "qpid/Exception.h"
-#include "qpid/Msg.h"
-#include <iostream>
-#include <assert.h>
-
-namespace qpid {
-namespace ha {
-
-using namespace std;
-
-// Note replicateLevel is called during plugin-initialization which
-// happens in the static construction phase so these constants need
-// to be POD, they can't be class objects
-//
-namespace {
-const char* S_NONE="none";
-const char* S_CONFIGURATION="configuration";
-const char* S_ALL="all";
-}
-
-bool replicateLevel(const string& level, ReplicateLevel& out) {
- if (level == S_NONE) { out = RL_NONE; return true; }
- if (level == S_CONFIGURATION) { out = RL_CONFIGURATION; return true; }
- if (level == S_ALL) { out = RL_ALL; return true; }
- return false;
-}
-
-ReplicateLevel replicateLevel(const string& level) {
- ReplicateLevel rl;
- if (!replicateLevel(level, rl))
- throw Exception("Invalid value for replication level: "+level);
- return rl;
-}
-
-string str(ReplicateLevel l) {
- const char* names[] = { S_NONE, S_CONFIGURATION, S_ALL };
- if (l > RL_ALL)
- throw Exception(QPID_MSG("Invalid value for replication level: " << l));
- return names[l];
-}
-
-ostream& operator<<(ostream& o, ReplicateLevel rl) { return o << str(rl); }
-
-istream& operator>>(istream& i, ReplicateLevel& rl) {
- string str;
- i >> str;
- rl = replicateLevel(str);
- return i;
-}
-
-}} // namespace qpid::ha
diff --git a/cpp/src/qpid/ha/ReplicateLevel.h b/cpp/src/qpid/ha/ReplicateLevel.h
deleted file mode 100644
index c11e03f0ce..0000000000
--- a/cpp/src/qpid/ha/ReplicateLevel.h
+++ /dev/null
@@ -1,52 +0,0 @@
-#ifndef QPID_HA_REPLICATELEVEL_H
-#define QPID_HA_REPLICATELEVEL_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>
-#include <iosfwd>
-
-namespace qpid {
-namespace ha {
-
-enum ReplicateLevel { RL_NONE, RL_CONFIGURATION, RL_ALL };
-
-/**
- * If str is a valid replicate level, set out and return true.
- */
-bool replicateLevel(const std::string& str, ReplicateLevel& out);
-
-/**
- *@return enum corresponding to string level.
- *@throw qpid::Exception if level is not a valid replication level.
- */
-ReplicateLevel replicateLevel(const std::string& level);
-
-/**@return string form of replicate level */
-std::string str(ReplicateLevel l);
-
-std::ostream& operator<<(std::ostream&, ReplicateLevel);
-std::istream& operator>>(std::istream&, ReplicateLevel&);
-
-}} // namespaces qpid::ha
-
-#endif /*!QPID_HA_REPLICATELEVEL_H*/
diff --git a/cpp/src/qpid/ha/ReplicatingSubscription.cpp b/cpp/src/qpid/ha/ReplicatingSubscription.cpp
index 91a4538bc4..c960758eaf 100644
--- a/cpp/src/qpid/ha/ReplicatingSubscription.cpp
+++ b/cpp/src/qpid/ha/ReplicatingSubscription.cpp
@@ -19,13 +19,18 @@
*
*/
+#include "QueueGuard.h"
+#include "QueueRange.h"
+#include "QueueReplicator.h"
#include "ReplicatingSubscription.h"
+#include "Primary.h"
#include "qpid/broker/Queue.h"
#include "qpid/broker/SessionContext.h"
#include "qpid/broker/ConnectionState.h"
#include "qpid/framing/AMQFrame.h"
#include "qpid/framing/MessageTransferBody.h"
#include "qpid/log/Statement.h"
+#include "qpid/types/Uuid.h"
#include <sstream>
namespace qpid {
@@ -34,19 +39,90 @@ namespace ha {
using namespace framing;
using namespace broker;
using namespace std;
+using sys::Mutex;
-const string ReplicatingSubscription::QPID_REPLICATING_SUBSCRIPTION("qpid.replicating-subscription");
+const string ReplicatingSubscription::QPID_REPLICATING_SUBSCRIPTION("qpid.ha-replicating-subscription");
+const string ReplicatingSubscription::QPID_BACK("qpid.ha-back");
+const string ReplicatingSubscription::QPID_FRONT("qpid.ha-front");
+const string ReplicatingSubscription::QPID_BROKER_INFO("qpid.ha-broker-info");
namespace {
const string DOLLAR("$");
const string INTERNAL("-internal");
} // namespace
+// Scan the queue for gaps and add them to the subscriptions dequed set.
+class DequeueScanner
+{
+ public:
+ DequeueScanner(
+ ReplicatingSubscription& rs,
+ SequenceNumber front_,
+ SequenceNumber back_ // Inclusive
+ ) : subscription(rs), front(front_), back(back_)
+ {
+ assert(front <= back);
+ // INVARIANT deques have been added for positions <= at.
+ at = front - 1;
+ }
+
+ void operator()(const QueuedMessage& qm) {
+ if (qm.position >= front && qm.position <= back) {
+ if (qm.position > at+1) subscription.dequeued(at+1, qm.position-1);
+ at = qm.position;
+ }
+ }
+
+ // Must call after scanning the queue.
+ void finish() {
+ if (at < back) subscription.dequeued(at+1, back);
+ }
+
+ private:
+ ReplicatingSubscription& subscription;
+ SequenceNumber front;
+ SequenceNumber back;
+ SequenceNumber at;
+};
+
string mask(const string& in)
{
return DOLLAR + in + INTERNAL;
}
+
+/** Dummy consumer used to get the front position on the queue */
+class GetPositionConsumer : public Consumer
+{
+ public:
+ GetPositionConsumer() :
+ Consumer("ha.GetPositionConsumer."+types::Uuid(true).str(), false) {}
+ bool deliver(broker::QueuedMessage& ) { return true; }
+ void notify() {}
+ bool filter(boost::intrusive_ptr<broker::Message>) { return true; }
+ bool accept(boost::intrusive_ptr<broker::Message>) { return true; }
+ void cancel() {}
+ void acknowledged(const broker::QueuedMessage&) {}
+ bool browseAcquired() const { return true; }
+ broker::OwnershipToken* getSession() { return 0; }
+};
+
+
+bool ReplicatingSubscription::getNext(
+ broker::Queue& q, SequenceNumber from, SequenceNumber& result)
+{
+ boost::shared_ptr<Consumer> c(new GetPositionConsumer);
+ c->setPosition(from);
+ if (!q.dispatch(c)) return false;
+ result = c->getPosition();
+ return true;
+}
+
+bool ReplicatingSubscription::getFront(broker::Queue& q, SequenceNumber& front) {
+ // FIXME aconway 2012-05-23: won't wrap, assumes 0 is < all messages in queue.
+ return getNext(q, 0, front);
+}
+
/* Called by SemanticState::consume to create a consumer */
boost::shared_ptr<broker::SemanticState::ConsumerImpl>
ReplicatingSubscription::Factory::create(
@@ -66,7 +142,7 @@ ReplicatingSubscription::Factory::create(
rs.reset(new ReplicatingSubscription(
parent, name, queue, ack, acquire, exclusive, tag,
resumeId, resumeTtl, arguments));
- queue->addObserver(rs);
+ rs->initialize();
}
return rs;
}
@@ -84,179 +160,223 @@ ReplicatingSubscription::ReplicatingSubscription(
const framing::FieldTable& arguments
) : ConsumerImpl(parent, name, queue, ack, acquire, exclusive, tag,
resumeId, resumeTtl, arguments),
- events(new Queue(mask(name))),
- consumer(new DelegatingConsumer(*this))
+ dummy(new Queue(mask(name))),
+ ready(false)
{
- // Separate the remote part from a "local-remote" address.
- string address = parent->getSession().getConnection().getUrl();
- size_t i = address.find('-');
- if (i != string::npos) address = address.substr(i+1);
- logPrefix = "HA: Primary ";
- stringstream ss;
- logSuffix = " (" + address + ")";
-
- // FIXME aconway 2011-12-09: Failover optimization removed.
- // There was code here to re-use messages already on the backup
- // during fail-over. This optimization was removed to simplify
- // the logic till we get the basic replication stable, it
- // can be re-introduced later. Last revision with the optimization:
- // r1213258 | QPID-3603: Fix QueueReplicator subscription parameters.
-
- QPID_LOG(debug, logPrefix << "created backup subscription " << getName() << logSuffix);
-
- // FIXME aconway 2011-12-15: ConsumerImpl::position is left at 0
- // so we will start consuming from the lowest numbered message.
- // This is incorrect if the sequence number wraps around, but
- // this is what all consumers currently do.
-}
-
-// Message is delivered in the subscription's connection thread.
-bool ReplicatingSubscription::deliver(QueuedMessage& m) {
try {
- // Add position events for the subscribed queue, not for the internal event queue.
- if (m.queue && m.queue == getQueue().get()) {
- sys::Mutex::ScopedLock l(lock);
- if (position != m.position)
- throw Exception(
- QPID_MSG("Expected position " << position
- << " but got " << m.position));
- // m.position is the position of the newly enqueued m on the local queue.
- // backupPosition is latest position on the backup queue (before enqueueing m.)
- if (m.position <= backupPosition)
- throw Exception(
- QPID_MSG("Expected position > " << backupPosition
- << " but got " << m.position));
-
- if (m.position - backupPosition > 1) {
- // Position has advanced because of messages dequeued ahead of us.
- SequenceNumber send(m.position);
- --send; // Send the position before m was enqueued.
- sendPositionEvent(send, l);
+ FieldTable ft;
+ if (!arguments.getTable(ReplicatingSubscription::QPID_BROKER_INFO, ft))
+ throw Exception("Replicating subscription does not have broker info: " + tag);
+ info.assign(ft);
+
+ // Set a log prefix message that identifies the remote broker.
+ ostringstream os;
+ os << "Primary " << queue->getName() << "@" << info.getLogId() << ": ";
+ logPrefix = os.str();
+
+ // NOTE: Once the guard is attached we can have concurrent
+ // calls to dequeued so we need to lock use of this->dequeues.
+ //
+ // However we must attach the guard _before_ we scan for
+ // initial dequeues to be sure we don't miss any dequeues
+ // between the scan and attaching the guard.
+ if (Primary::get()) guard = Primary::get()->getGuard(queue, info);
+ if (!guard) guard.reset(new QueueGuard(*queue, info));
+ guard->attach(*this);
+
+ QueueRange backup(arguments); // Remote backup range.
+ QueueRange primary(guard->getRange()); // Unguarded range when the guard was set.
+ backupPosition = backup.back;
+
+ // Sync backup and primary queues, don't send messages already on the backup
+
+ if (backup.front > primary.front || // Missing messages at front
+ backup.back < primary.front || // No overlap
+ primary.empty() || backup.empty()) // Empty
+ {
+ // No useful overlap - erase backup and start from the beginning
+ if (!backup.empty()) dequeued(backup.front, backup.back);
+ position = primary.front-1;
+ }
+ else { // backup and primary do overlap.
+ // Remove messages from backup that are not in primary.
+ if (primary.back < backup.back) {
+ dequeued(primary.back+1, backup.back); // Trim excess messages at back
+ backup.back = primary.back;
}
- backupPosition = m.position;
- QPID_LOG(trace, logPrefix << "replicating " << m << logSuffix);
+ if (backup.front < primary.front) {
+ dequeued(backup.front, primary.front-1); // Trim excess messages at front
+ backup.front = primary.front;
+ }
+ DequeueScanner scan(*this, backup.front, backup.back);
+ // FIXME aconway 2012-06-15: Optimize queue traversal, only in range.
+ queue->eachMessage(boost::ref(scan)); // Remove missing messages in between.
+ scan.finish();
+ position = backup.back;
}
- return ConsumerImpl::deliver(m);
- } catch (const std::exception& e) {
- QPID_LOG(critical, logPrefix << "error replicating " << getQueue()->getName()
- << logSuffix << ": " << e.what());
+ // NOTE: we are assuming that the messages that are on the backup are
+ // consistent with those on the primary. If the backup is a replica
+ // queue and hasn't been tampered with then that will be the case.
+
+ QPID_LOG(debug, logPrefix << "Subscribed:"
+ << " backup:" << backup
+ << " primary:" << primary
+ << " catch-up: " << position << "-" << primary.back
+ << "(" << primary.back-position << ")");
+
+ // Check if we are ready yet.
+ if (guard->subscriptionStart(position)) setReady();
+ }
+ catch (const std::exception& e) {
+ QPID_LOG(error, logPrefix << "Creation error: " << e.what()
+ << ": arguments=" << getArguments());
throw;
}
}
-ReplicatingSubscription::~ReplicatingSubscription() {}
-
+ReplicatingSubscription::~ReplicatingSubscription() {
+ QPID_LOG(debug, logPrefix << "Detroyed replicating subscription");
+}
-// INVARIANT: delayed contains msg <=> we have outstanding startCompletion on msg
+// Called in subscription's connection thread when the subscription is created.
+// Called separate from ctor because sending events requires
+// shared_from_this
+//
+void ReplicatingSubscription::initialize() {
+ try {
+ Mutex::ScopedLock l(lock); // Note dequeued() can be called concurrently.
-// Mark a message completed. May be called by acknowledge or dequeued
-void ReplicatingSubscription::complete(
- const QueuedMessage& qm, const sys::Mutex::ScopedLock&)
-{
- // Handle completions for the subscribed queue, not the internal event queue.
- if (qm.queue && qm.queue == getQueue().get()) {
- QPID_LOG(trace, logPrefix << "completed " << qm << logSuffix);
- Delayed::iterator i= delayed.find(qm.position);
- // The same message can be completed twice, by acknowledged and
- // dequeued, remove it from the set so it only gets completed
- // once.
- if (i != delayed.end()) {
- assert(i->second.payload == qm.payload);
- qm.payload->getIngressCompletion().finishCompleter();
- delayed.erase(i);
- }
+ // Send initial dequeues and position to the backup.
+ // There must be a shared_ptr(this) when sending.
+ sendDequeueEvent(l);
+ sendPositionEvent(position, l);
+ backupPosition = position;
+ }
+ catch (const std::exception& e) {
+ QPID_LOG(error, logPrefix << "Initialization error: " << e.what()
+ << ": arguments=" << getArguments());
+ throw;
}
}
-// Called before we get notified of the message being available and
-// under the message lock in the queue. Called in arbitrary connection thread.
-void ReplicatingSubscription::enqueued(const QueuedMessage& qm) {
- sys::Mutex::ScopedLock l(lock);
- // Delay completion
- QPID_LOG(trace, logPrefix << "delaying completion of " << qm << logSuffix);
- qm.payload->getIngressCompletion().startCompleter();
- assert(delayed.find(qm.position) == delayed.end());
- delayed[qm.position] = qm;
+// Message is delivered in the subscription's connection thread.
+bool ReplicatingSubscription::deliver(QueuedMessage& qm) {
+ try {
+ // Add position events for the subscribed queue, not the internal event queue.
+ if (qm.queue == getQueue().get()) {
+ QPID_LOG(trace, logPrefix << "Replicating " << qm);
+ {
+ Mutex::ScopedLock l(lock);
+ assert(position == qm.position);
+ // qm.position is the position of the newly enqueued qm on local queue.
+ // backupPosition is latest position on backup queue before enqueueing
+ if (qm.position <= backupPosition)
+ throw Exception(
+ QPID_MSG("Expected position > " << backupPosition
+ << " but got " << qm.position));
+ if (qm.position - backupPosition > 1) {
+ // Position has advanced because of messages dequeued ahead of us.
+ // Send the position before qm was enqueued.
+ sendPositionEvent(qm.position-1, l);
+ }
+ // Backup will automatically advance by 1 on delivery of message.
+ backupPosition = qm.position;
+ }
+ }
+ return ConsumerImpl::deliver(qm);
+ } catch (const std::exception& e) {
+ QPID_LOG(critical, logPrefix << "Error replicating " << qm
+ << ": " << e.what());
+ throw;
+ }
}
-
-// Function to complete a delayed message, called by cancel()
-void ReplicatingSubscription::cancelComplete(
- const Delayed::value_type& v, const sys::Mutex::ScopedLock&)
-{
- QPID_LOG(trace, logPrefix << "cancel completed " << v.second << logSuffix);
- v.second.payload->getIngressCompletion().finishCompleter();
+void ReplicatingSubscription::setReady() {
+ {
+ Mutex::ScopedLock l(lock);
+ if (ready) return;
+ ready = true;
+ }
+ // Notify Primary that a subscription is ready.
+ QPID_LOG(debug, logPrefix << "Caught up");
+ if (Primary::get()) Primary::get()->readyReplica(*this);
}
// Called in the subscription's connection thread.
void ReplicatingSubscription::cancel()
{
- getQueue()->removeObserver(
- boost::dynamic_pointer_cast<QueueObserver>(shared_from_this()));
- {
- sys::Mutex::ScopedLock l(lock);
- QPID_LOG(debug, logPrefix << "cancel backup subscription " << getName() << logSuffix);
- for_each(delayed.begin(), delayed.end(),
- boost::bind(&ReplicatingSubscription::cancelComplete, this, _1, boost::ref(l)));
- delayed.clear();
- }
+ guard->cancel();
ConsumerImpl::cancel();
}
-// Called on primary in the backups IO thread.
-void ReplicatingSubscription::acknowledged(const QueuedMessage& msg) {
- sys::Mutex::ScopedLock l(lock);
- // Finish completion of message, it has been acknowledged by the backup.
- complete(msg, l);
+// Consumer override, called on primary in the backup's IO thread.
+void ReplicatingSubscription::acknowledged(const QueuedMessage& qm) {
+ if (qm.queue == getQueue().get()) { // Don't complete messages on the internal queue
+ // Finish completion of message, it has been acknowledged by the backup.
+ QPID_LOG(trace, logPrefix << "Acknowledged " << qm);
+ guard->complete(qm);
+ // If next message is protected by the guard then we are ready
+ if (qm.position >= guard->getRange().back) setReady();
+ }
+ ConsumerImpl::acknowledged(qm);
}
-// Hide the "queue deleted" error for a ReplicatingSubscription when a
-// queue is deleted, this is normal and not an error.
-bool ReplicatingSubscription::hideDeletedError() { return true; }
-
// Called with lock held. Called in subscription's connection thread.
-void ReplicatingSubscription::sendDequeueEvent(const sys::Mutex::ScopedLock& l)
+void ReplicatingSubscription::sendDequeueEvent(Mutex::ScopedLock&)
{
- QPID_LOG(trace, logPrefix << "sending dequeues " << dequeues
- << " from " << getQueue()->getName() << logSuffix);
+ if (dequeues.empty()) return;
+ QPID_LOG(trace, logPrefix << "Sending dequeues " << dequeues);
string buf(dequeues.encodedSize(),'\0');
framing::Buffer buffer(&buf[0], buf.size());
dequeues.encode(buffer);
dequeues.clear();
buffer.reset();
- sendEvent(QueueReplicator::DEQUEUE_EVENT_KEY, buffer, l);
+ {
+ Mutex::ScopedUnlock u(lock);
+ sendEvent(QueueReplicator::DEQUEUE_EVENT_KEY, buffer);
+ }
}
-// Called after the message has been removed from the deque and under
-// the messageLock in the queue. Called in arbitrary connection threads.
+// Called via QueueObserver::dequeued override on guard.
+// Called after the message has been removed
+// from the deque and under the messageLock in the queue. Called in
+// arbitrary connection threads.
void ReplicatingSubscription::dequeued(const QueuedMessage& qm)
{
+ assert (qm.queue == getQueue().get());
+ QPID_LOG(trace, logPrefix << "Dequeued " << qm);
{
- sys::Mutex::ScopedLock l(lock);
- QPID_LOG(trace, logPrefix << "dequeued " << qm << logSuffix);
+ Mutex::ScopedLock l(lock);
dequeues.add(qm.position);
- // If we have not yet sent this message to the backup, then
- // complete it now as it will never be accepted.
- if (qm.position > position) complete(qm, l);
}
notify(); // Ensure a call to doDispatch
}
+// Called during construction while scanning for initial dequeues.
+void ReplicatingSubscription::dequeued(SequenceNumber first, SequenceNumber last) {
+ QPID_LOG(trace, logPrefix << "Initial dequeue [" << first << ", " << last << "]");
+ {
+ Mutex::ScopedLock l(lock);
+ dequeues.add(first,last);
+ }
+}
+
// Called with lock held. Called in subscription's connection thread.
-void ReplicatingSubscription::sendPositionEvent(
- SequenceNumber position, const sys::Mutex::ScopedLock&l )
+void ReplicatingSubscription::sendPositionEvent(SequenceNumber pos, Mutex::ScopedLock&)
{
- QPID_LOG(trace, logPrefix << "sending position " << position
- << ", was " << backupPosition << logSuffix);
- string buf(backupPosition.encodedSize(),'\0');
+ if (pos == backupPosition) return; // No need to send.
+ QPID_LOG(trace, logPrefix << "Sending position " << pos << ", was " << backupPosition);
+ string buf(pos.encodedSize(),'\0');
framing::Buffer buffer(&buf[0], buf.size());
- position.encode(buffer);
+ pos.encode(buffer);
buffer.reset();
- sendEvent(QueueReplicator::POSITION_EVENT_KEY, buffer, l);
+ {
+ Mutex::ScopedUnlock u(lock);
+ sendEvent(QueueReplicator::POSITION_EVENT_KEY, buffer);
+ }
}
-void ReplicatingSubscription::sendEvent(const std::string& key, framing::Buffer& buffer,
- const sys::Mutex::ScopedLock&)
+void ReplicatingSubscription::sendEvent(const std::string& key, framing::Buffer& buffer)
{
//generate event message
boost::intrusive_ptr<Message> event = new Message();
@@ -276,15 +396,14 @@ void ReplicatingSubscription::sendEvent(const std::string& key, framing::Buffer&
event->getFrames().append(header);
event->getFrames().append(content);
- DeliveryProperties* props = event->getFrames().getHeaders()->get<DeliveryProperties>(true);
+ DeliveryProperties* props =
+ event->getFrames().getHeaders()->get<DeliveryProperties>(true);
props->setRoutingKey(key);
- // Send the event using the events queue. Consumer is a
- // DelegatingConsumer that delegates to *this for everything but
- // has an independnet position. We put an event on events and
- // dispatch it through ourselves to send it in line with the
- // normal browsing messages.
- events->deliver(event);
- events->dispatch(consumer);
+ // Send the event directly to the base consumer implementation.
+ // We don't really need a queue here but we pass a dummy queue
+ // to conform to the consumer API.
+ QueuedMessage qm(dummy.get(), event);
+ ConsumerImpl::deliver(qm);
}
@@ -292,19 +411,10 @@ void ReplicatingSubscription::sendEvent(const std::string& key, framing::Buffer&
bool ReplicatingSubscription::doDispatch()
{
{
- sys::Mutex::ScopedLock l(lock);
+ Mutex::ScopedLock l(lock);
if (!dequeues.empty()) sendDequeueEvent(l);
}
return ConsumerImpl::doDispatch();
}
-ReplicatingSubscription::DelegatingConsumer::DelegatingConsumer(ReplicatingSubscription& c) : Consumer(c.getName(), true), delegate(c) {}
-ReplicatingSubscription::DelegatingConsumer::~DelegatingConsumer() {}
-bool ReplicatingSubscription::DelegatingConsumer::deliver(QueuedMessage& m) { return delegate.deliver(m); }
-void ReplicatingSubscription::DelegatingConsumer::notify() { delegate.notify(); }
-bool ReplicatingSubscription::DelegatingConsumer::filter(boost::intrusive_ptr<Message> msg) { return delegate.filter(msg); }
-bool ReplicatingSubscription::DelegatingConsumer::accept(boost::intrusive_ptr<Message> msg) { return delegate.accept(msg); }
-bool ReplicatingSubscription::DelegatingConsumer::browseAcquired() const { return delegate.browseAcquired(); }
-OwnershipToken* ReplicatingSubscription::DelegatingConsumer::getSession() { return delegate.getSession(); }
-
}} // namespace qpid::ha
diff --git a/cpp/src/qpid/ha/ReplicatingSubscription.h b/cpp/src/qpid/ha/ReplicatingSubscription.h
index f9176915f6..a80141a6c2 100644
--- a/cpp/src/qpid/ha/ReplicatingSubscription.h
+++ b/cpp/src/qpid/ha/ReplicatingSubscription.h
@@ -22,10 +22,10 @@
*
*/
-#include "QueueReplicator.h" // For DEQUEUE_EVENT_KEY
+#include "BrokerInfo.h"
#include "qpid/broker/SemanticState.h"
-#include "qpid/broker/QueueObserver.h"
#include "qpid/broker/ConsumerFactory.h"
+#include "qpid/types/Uuid.h"
#include <iosfwd>
namespace qpid {
@@ -42,18 +42,27 @@ class Buffer;
}
namespace ha {
+class QueueGuard;
/**
- * A susbcription that represents a backup replicating a queue.
+ * A susbcription that replicates to a remote backup.
*
- * Runs on the primary. Delays completion of messages till the backup
- * has acknowledged, informs backup of locally dequeued messages.
+ * Runs on the primary. In conjunction with a QueueGuard, delays completion of
+ * messages till the backup has acknowledged, informs backup of locally dequeued
+ * messages.
+ *
+ * A ReplicatingSubscription is "ready" when all the messages on the queue have
+ * either been acknowledged by the backup, or are protected by the queue guard.
+ * On a primary broker the ReplicatingSubscription calls Primary::readyReplica
+ * when it is ready.
+ *
+ * THREAD SAFE: Called in subscription's connection thread but also in arbitrary
+ * connection threads via dequeued.
+ *
+ * Lifecycle: broker::Queue holds shared_ptrs to this as a consumer.
*
- * THREAD SAFE: Used as a consumer in subscription's connection
- * thread, and as a QueueObserver in arbitrary connection threads.
*/
-class ReplicatingSubscription : public broker::SemanticState::ConsumerImpl,
- public broker::QueueObserver
+class ReplicatingSubscription : public broker::SemanticState::ConsumerImpl
{
public:
struct Factory : public broker::ConsumerFactory {
@@ -67,6 +76,20 @@ class ReplicatingSubscription : public broker::SemanticState::ConsumerImpl,
// Argument names for consume command.
static const std::string QPID_REPLICATING_SUBSCRIPTION;
+ static const std::string QPID_BACK;
+ static const std::string QPID_FRONT;
+ static const std::string QPID_BROKER_INFO;
+
+ // TODO aconway 2012-05-23: these don't belong on ReplicatingSubscription
+ /** Get position of front message on queue.
+ *@return false if queue is empty.
+ */
+ static bool getFront(broker::Queue&, framing::SequenceNumber& result);
+ /** Get next message after from in queue.
+ *@return false if none found.
+ */
+ static bool getNext(broker::Queue&, framing::SequenceNumber from,
+ framing::SequenceNumber& result);
ReplicatingSubscription(broker::SemanticState* parent,
const std::string& name, boost::shared_ptr<broker::Queue> ,
@@ -76,56 +99,46 @@ class ReplicatingSubscription : public broker::SemanticState::ConsumerImpl,
~ReplicatingSubscription();
- // QueueObserver overrides.
- bool deliver(broker::QueuedMessage& msg);
- void enqueued(const broker::QueuedMessage&);
- void dequeued(const broker::QueuedMessage&);
- void acquired(const broker::QueuedMessage&) {}
- void requeued(const broker::QueuedMessage&) {}
+ // Called via QueueGuard::dequeued.
+ //@return true if the message requires completion.
+ void dequeued(const broker::QueuedMessage& qm);
+
+ // Called during initial scan for dequeues.
+ void dequeued(framing::SequenceNumber first, framing::SequenceNumber last);
// Consumer overrides.
+ bool deliver(broker::QueuedMessage& msg);
void cancel();
void acknowledged(const broker::QueuedMessage&);
bool browseAcquired() const { return true; }
+ // Hide the "queue deleted" error for a ReplicatingSubscription when a
+ // queue is deleted, this is normal and not an error.
+ bool hideDeletedError() { return true; }
+
+ /** Initialization that must be done separately from construction
+ * because it requires a shared_ptr to this to exist.
+ */
+ void initialize();
- bool hideDeletedError();
+ BrokerInfo getBrokerInfo() const { return info; }
protected:
bool doDispatch();
+
private:
- typedef std::map<framing::SequenceNumber, broker::QueuedMessage> Delayed;
- std::string logPrefix, logSuffix;
- boost::shared_ptr<broker::Queue> events;
- boost::shared_ptr<broker::Consumer> consumer;
- Delayed delayed;
+ std::string logPrefix;
+ boost::shared_ptr<broker::Queue> dummy; // Used to send event messages
framing::SequenceSet dequeues;
framing::SequenceNumber backupPosition;
-
- void complete(const broker::QueuedMessage&, const sys::Mutex::ScopedLock&);
- void cancelComplete(const Delayed::value_type& v, const sys::Mutex::ScopedLock&);
- void sendDequeueEvent(const sys::Mutex::ScopedLock&);
- void sendPositionEvent(framing::SequenceNumber, const sys::Mutex::ScopedLock&);
- void sendEvent(const std::string& key, framing::Buffer&,
- const sys::Mutex::ScopedLock&);
-
- class DelegatingConsumer : public Consumer
- {
- public:
- DelegatingConsumer(ReplicatingSubscription&);
- ~DelegatingConsumer();
- bool deliver(broker::QueuedMessage& msg);
- void notify();
- bool filter(boost::intrusive_ptr<broker::Message>);
- bool accept(boost::intrusive_ptr<broker::Message>);
- void cancel() {}
- void acknowledged(const broker::QueuedMessage&) {}
- bool browseAcquired() const;
-
- broker::OwnershipToken* getSession();
-
- private:
- ReplicatingSubscription& delegate;
- };
+ bool ready;
+ BrokerInfo info;
+ boost::shared_ptr<QueueGuard> guard;
+
+ void sendDequeueEvent(sys::Mutex::ScopedLock&);
+ void sendPositionEvent(framing::SequenceNumber, sys::Mutex::ScopedLock&);
+ void setReady();
+ void sendEvent(const std::string& key, framing::Buffer&);
+ friend struct Factory;
};
diff --git a/cpp/src/qpid/ha/ReplicationTest.cpp b/cpp/src/qpid/ha/ReplicationTest.cpp
new file mode 100644
index 0000000000..18e0953930
--- /dev/null
+++ b/cpp/src/qpid/ha/ReplicationTest.cpp
@@ -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.
+ *
+ */
+#include "ReplicationTest.h"
+#include "qpid/broker/Queue.h"
+#include "qpid/framing/FieldTable.h"
+
+namespace qpid {
+namespace ha {
+
+using types::Variant;
+
+ReplicateLevel ReplicationTest::replicateLevel(const std::string& str) {
+ Enum<ReplicateLevel> rl(replicateDefault);
+ if (!str.empty()) rl.parse(str);
+ return rl.get();
+}
+
+ReplicateLevel ReplicationTest::replicateLevel(const framing::FieldTable& f) {
+ if (f.isSet(QPID_REPLICATE))
+ return replicateLevel(f.getAsString(QPID_REPLICATE));
+ else
+ return replicateDefault;
+}
+
+ReplicateLevel ReplicationTest::replicateLevel(const Variant::Map& m) {
+ Variant::Map::const_iterator i = m.find(QPID_REPLICATE);
+ if (i != m.end())
+ return replicateLevel(i->second.asString());
+ else
+ return replicateDefault;
+}
+
+namespace {
+const std::string AUTO_DELETE_TIMEOUT("qpid.auto_delete_timeout");
+}
+
+bool ReplicationTest::isReplicated(
+ ReplicateLevel level, const Variant::Map& args, bool autodelete, bool exclusive)
+{
+ bool ignore = autodelete && exclusive && args.find(AUTO_DELETE_TIMEOUT) == args.end();
+ return !ignore && replicateLevel(args) >= level;
+}
+
+bool ReplicationTest::isReplicated(
+ ReplicateLevel level, const framing::FieldTable& args, bool autodelete, bool exclusive)
+{
+ bool ignore = autodelete && exclusive && !args.isSet(AUTO_DELETE_TIMEOUT);
+ return !ignore && replicateLevel(args) >= level;
+}
+
+bool ReplicationTest::isReplicated(ReplicateLevel level, const broker::Queue& q)
+{
+ return isReplicated(level, q.getSettings(), q.isAutoDelete(), q.hasExclusiveOwner());
+}
+
+
+}} // namespace qpid::ha
diff --git a/cpp/src/qpid/ha/ReplicationTest.h b/cpp/src/qpid/ha/ReplicationTest.h
new file mode 100644
index 0000000000..9f6976a8e4
--- /dev/null
+++ b/cpp/src/qpid/ha/ReplicationTest.h
@@ -0,0 +1,67 @@
+#ifndef QPID_HA_REPLICATIONTEST_H
+#define QPID_HA_REPLICATIONTEST_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 "types.h"
+#include "qpid/types/Variant.h"
+#include <string>
+
+namespace qpid {
+
+namespace broker {
+class Queue;
+}
+
+namespace framing {
+class FieldTable;
+}
+
+namespace ha {
+/**
+ * Test whether something is replicated, taking into account the
+ * default replication level.
+ */
+class ReplicationTest
+{
+ public:
+ ReplicationTest(ReplicateLevel replicateDefault_) :
+ replicateDefault(replicateDefault_) {}
+
+ // Return the simple replication level, accounting for defaults.
+ ReplicateLevel replicateLevel(const std::string& str);
+ ReplicateLevel replicateLevel(const framing::FieldTable& f);
+ ReplicateLevel replicateLevel(const types::Variant::Map& m);
+
+ // Return true if replication for a queue is enabled at level or higher,
+ // taking account of default level and queue settings.
+ bool isReplicated(ReplicateLevel level,
+ const types::Variant::Map& args, bool autodelete, bool exclusive);
+ bool isReplicated(ReplicateLevel level,
+ const framing::FieldTable& args, bool autodelete, bool exclusive);
+ bool isReplicated(ReplicateLevel level, const broker::Queue&);
+ private:
+ ReplicateLevel replicateDefault;
+};
+}} // namespace qpid::ha
+
+#endif /*!QPID_HA_REPLICATIONTEST_H*/
diff --git a/cpp/src/qpid/ha/Settings.h b/cpp/src/qpid/ha/Settings.h
index bf70c3f3f7..37235b5c79 100644
--- a/cpp/src/qpid/ha/Settings.h
+++ b/cpp/src/qpid/ha/Settings.h
@@ -22,7 +22,7 @@
*
*/
-#include "ReplicateLevel.h"
+#include "types.h"
#include <string>
namespace qpid {
@@ -34,13 +34,15 @@ namespace ha {
class Settings
{
public:
- Settings() : cluster(false), expectedBackups(0), replicateDefault(RL_NONE) {}
+ Settings() : cluster(false), replicateDefault(NONE), backupTimeout(5)
+ {}
+
bool cluster; // True if we are a cluster member.
std::string clientUrl;
std::string brokerUrl;
- size_t expectedBackups;
- ReplicateLevel replicateDefault;
+ Enum<ReplicateLevel> replicateDefault;
std::string username, password, mechanism;
+ double backupTimeout;
private:
};
}} // namespace qpid::ha
diff --git a/cpp/src/qpid/ha/management-schema.xml b/cpp/src/qpid/ha/management-schema.xml
index 363dff61fb..3da482e732 100644
--- a/cpp/src/qpid/ha/management-schema.xml
+++ b/cpp/src/qpid/ha/management-schema.xml
@@ -25,37 +25,39 @@
<property name="status" type="sstr" desc="HA status: primary or backup"/>
- <property name="brokers" type="sstr"
- desc="Multiple-address URL used by HA brokers to connect to each other."/>
+ <property name="brokersUrl" type="sstr"
+ desc="URL with address of each broker in the cluster."/>
- <property name="publicBrokers" type="sstr"
- desc="Multiple-address URL used by clients to connect to the HA brokers."/>
+ <property name="publicUrl" type="sstr"
+ desc="URL advertized to clients to connect to the cluster."/>
- <property name="expectedBackups" type="uint16"
- desc="Number of HA backup brokers expected."/>
+ <property name="replicateDefault" type="sstr"
+ desc="Replication for queues/exchanges with no qpid.replicate argument"/>
- <property
- name="replicateDefault" type="sstr"
- desc="Replicate value for queues/exchanges without a qpid.replicate argument"/>
+ <property name="members" type="list" desc="List of brokers in the cluster"/>
+
+ <property name="systemId" type="uuid" desc="Identifies the system."/>
<method name="promote" desc="Promote a backup broker to primary."/>
- <method name="setBrokers" desc="Set URL for HA brokers to connect to each other.">
+ <method name="setBrokersUrl" desc="URL listing each broker in the cluster.">
<arg name="url" type="sstr" dir="I"/>
</method>
- <method name="setPublicBrokers" desc="Set URL for clients to connect to HA brokers">
+ <method name="setPublicUrl" desc="URL advertized to clients.">
<arg name="url" type="sstr" dir="I"/>
</method>
- <method name="setExpectedBackups" desc="Set number of backups expected">
- <arg name="expectedBackups" type="uint16" dir="I"/>
- </method>
-
<method name="replicate" desc="Replicate individual queue from remote broker.">
<arg name="broker" type="sstr" dir="I"/>
<arg name="queue" type="sstr" dir="I"/>
</method>
</class>
+ <eventArguments>
+ <arg name="members" type="list" desc="List of broker information maps"/>
+ </eventArguments>
+
+ <event name="membersUpdate" sev="inform" args="members"/>
+
</schema>
diff --git a/cpp/src/qpid/ha/types.cpp b/cpp/src/qpid/ha/types.cpp
new file mode 100644
index 0000000000..53e2056213
--- /dev/null
+++ b/cpp/src/qpid/ha/types.cpp
@@ -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.
+ *
+ */
+
+#include "types.h"
+#include "qpid/Msg.h"
+#include "qpid/Exception.h"
+#include <algorithm>
+#include <iostream>
+#include <iterator>
+#include <assert.h>
+
+namespace qpid {
+namespace ha {
+
+using namespace std;
+
+const string QPID_REPLICATE("qpid.replicate");
+
+string EnumBase::str() const {
+ assert(value < count);
+ return names[value];
+}
+
+void EnumBase::parse(const string& s) {
+ if (!parseNoThrow(s))
+ throw Exception(QPID_MSG("Invalid " << name << " value: " << s));
+}
+
+bool EnumBase::parseNoThrow(const string& s) {
+ const char** i = find(names, names+count, s);
+ value = i - names;
+ return value < count;
+}
+
+template <> const char* Enum<ReplicateLevel>::NAME = "replication";
+template <> const char* Enum<ReplicateLevel>::NAMES[] = { "none", "configuration", "all" };
+template <> const size_t Enum<ReplicateLevel>::N = 3;
+
+template <> const char* Enum<BrokerStatus>::NAME = "HA broker status";
+template <> const char* Enum<BrokerStatus>::NAMES[] = {
+ "joining", "catchup", "ready", "recovering", "active", "standalone"
+};
+template <> const size_t Enum<BrokerStatus>::N = 6;
+
+ostream& operator<<(ostream& o, EnumBase e) {
+ return o << e.str();
+}
+
+istream& operator>>(istream& i, EnumBase& e) {
+ string s;
+ i >> s;
+ e.parse(s);
+ return i;
+}
+
+ostream& operator<<(ostream& o, const IdSet& ids) {
+ ostream_iterator<qpid::types::Uuid> out(o, " ");
+ copy(ids.begin(), ids.end(), out);
+ return o;
+}
+
+}} // namespace qpid::ha
diff --git a/cpp/src/qpid/ha/types.h b/cpp/src/qpid/ha/types.h
new file mode 100644
index 0000000000..35faf9f624
--- /dev/null
+++ b/cpp/src/qpid/ha/types.h
@@ -0,0 +1,109 @@
+#ifndef QPID_HA_ENUM_H
+#define QPID_HA_ENUM_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/types/Variant.h"
+#include "qpid/types/Uuid.h"
+#include <string>
+#include <set>
+#include <iosfwd>
+
+namespace qpid {
+
+namespace framing {
+class FieldTable;
+}
+
+namespace ha {
+
+/** Base class for enums with string conversion */
+class EnumBase {
+ public:
+ EnumBase(const char* name_, const char* names_[], size_t count_, unsigned value)
+ : name(name_), names(names_), count(count_), value(value) {}
+
+ /** Convert to string */
+ std::string str() const;
+ /** Parse from string, throw if unsuccessful */
+ void parse(const std::string&);
+ /** Parse from string, return false if unsuccessful. */
+ bool parseNoThrow(const std::string&);
+
+ protected:
+ const char* name;
+ const char** names;
+ size_t count;
+ unsigned value;
+};
+
+std::ostream& operator<<(std::ostream&, EnumBase);
+std::istream& operator>>(std::istream&, EnumBase&);
+
+/** Wrapper template for enums with string conversion */
+template <class T> class Enum : public EnumBase {
+ public:
+ Enum(T x=T()) : EnumBase(NAME, NAMES, N, x) {}
+ T get() const { return T(value); }
+ void operator=(T x) { value = x; }
+
+ private:
+ static const size_t N; // Number of enum values.
+ static const char* NAMES[]; // Names of enum values.
+ static const char* NAME; // Descriptive name for the enum type.
+};
+
+/** To print an enum x: o << printable(x) */
+template <class T> Enum<T> printable(T x) { return Enum<T>(x); }
+
+enum ReplicateLevel {
+ NONE, ///< Nothing is replicated
+ CONFIGURATION, ///< Wiring is replicated but not messages
+ ALL ///< Everything is replicated
+};
+
+/** State of a broker: see HaBroker::setStatus for state diagram */
+enum BrokerStatus {
+ JOINING, ///< New broker, looking for primary
+ CATCHUP, ///< Backup: Connected to primary, catching up on state.
+ READY, ///< Backup: Caught up, ready to take over.
+ RECOVERING, ///< Primary: waiting for backups to connect & sync
+ ACTIVE, ///< Primary: actively serving clients.
+ STANDALONE ///< Not part of a cluster.
+};
+
+inline bool isPrimary(BrokerStatus s) {
+ return s == RECOVERING || s == ACTIVE || s == STANDALONE;
+}
+
+inline bool isBackup(BrokerStatus s) { return !isPrimary(s); }
+
+// String constants.
+extern const std::string QPID_REPLICATE;
+
+/** Define IdSet type, not a typedef so we can overload operator << */
+class IdSet : public std::set<types::Uuid> {};
+
+std::ostream& operator<<(std::ostream& o, const IdSet& ids);
+
+}} // qpid::ha
+#endif /*!QPID_HA_ENUM_H*/
diff --git a/cpp/src/qpid/log/Logger.cpp b/cpp/src/qpid/log/Logger.cpp
index 800881c077..7c2e807ca9 100644
--- a/cpp/src/qpid/log/Logger.cpp
+++ b/cpp/src/qpid/log/Logger.cpp
@@ -47,7 +47,7 @@ using namespace std;
typedef sys::Mutex::ScopedLock ScopedLock;
inline void Logger::enable_unlocked(Statement* s) {
- s->enabled=selector.isEnabled(s->level, s->function);
+ s->enabled=selector.isEnabled(s->level, s->function, s->category);
}
Logger& Logger::instance() {
@@ -95,6 +95,8 @@ void Logger::log(const Statement& s, const std::string& msg) {
else
qpid::sys::outputFormattedNow(os);
}
+ if (flags&CATEGORY)
+ os << "[" << CategoryTraits::name(s.category) << "] ";
if (flags&LEVEL)
os << LevelTraits::name(s.level) << " ";
if (flags&THREAD)
@@ -144,7 +146,8 @@ int Logger::format(const Options& opts) {
bitIf(opts.source, (FILE|LINE)) |
bitIf(opts.function, FUNCTION) |
bitIf(opts.thread, THREAD) |
- bitIf(opts.hiresTs, HIRES);
+ bitIf(opts.hiresTs, HIRES) |
+ bitIf(opts.category, CATEGORY);
format(flags);
return flags;
}
diff --git a/cpp/src/qpid/log/Options.cpp b/cpp/src/qpid/log/Options.cpp
index 1259244297..10422bbb1e 100644
--- a/cpp/src/qpid/log/Options.cpp
+++ b/cpp/src/qpid/log/Options.cpp
@@ -39,6 +39,7 @@ Options::Options(const std::string& argv0_, const std::string& name_) :
source(false),
function(false),
hiresTs(false),
+ category(true),
trace(false),
sinkOptions (SinkOptions::create(argv0_))
{
@@ -49,15 +50,23 @@ Options::Options(const std::string& argv0_, const std::string& name_) :
for (int i = 1; i < LevelTraits::COUNT; ++i)
levels << " " << LevelTraits::name(Level(i));
+ ostringstream categories;
+ categories << CategoryTraits::name(Category(0));
+ for (int i = 1; i < CategoryTraits::COUNT; ++i)
+ categories << " " << CategoryTraits::name(Category(i));
+
addOptions()
("trace,t", optValue(trace), "Enables all logging" )
("log-enable", optValue(selectors, "RULE"),
- ("Enables logging for selected levels and components. "
+ ("Enables logging for selected levels and components. "
"RULE is in the form 'LEVEL[+][:PATTERN]' "
- "Levels are one of: \n\t "+levels.str()+"\n"
+ "LEVEL is one of: \n\t "+levels.str()+"\n"
+ "PATTERN is a function name or a catogory: \n\t "+categories.str()+"\n"
"For example:\n"
"\t'--log-enable warning+' "
"logs all warning, error and critical messages.\n"
+ "\t'--log-enable trace+:Broker' "
+ "logs all category 'Broker' messages.\n"
"\t'--log-enable debug:framing' "
"logs debug messages from the framing namespace. "
"This option can be used multiple times").c_str())
@@ -67,6 +76,7 @@ Options::Options(const std::string& argv0_, const std::string& name_) :
("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 hi-resolution timestamps in log messages")
+ ("log-category", optValue(category,"yes|no"), "Include category in log messages")
("log-prefix", optValue(prefix,"STRING"), "Prefix to append to all log messages")
;
add(*sinkOptions);
@@ -83,6 +93,7 @@ Options::Options(const Options &o) :
source(o.source),
function(o.function),
hiresTs(o.hiresTs),
+ category(o.category),
trace(o.trace),
prefix(o.prefix),
sinkOptions (SinkOptions::create(o.argv0))
@@ -101,11 +112,12 @@ Options& Options::operator=(const Options& x) {
source = x.source;
function = x.function;
hiresTs = x.hiresTs;
+ category = x.category;
trace = x.trace;
prefix = x.prefix;
*sinkOptions = *x.sinkOptions;
}
return *this;
}
-
+
}} // namespace qpid::log
diff --git a/cpp/src/qpid/log/Selector.cpp b/cpp/src/qpid/log/Selector.cpp
index a4bc580470..8757486d88 100644
--- a/cpp/src/qpid/log/Selector.cpp
+++ b/cpp/src/qpid/log/Selector.cpp
@@ -37,18 +37,29 @@ void Selector::enable(const string& enableStr) {
level=enableStr.substr(0,c);
pattern=enableStr.substr(c+1);
}
+ bool isCat = CategoryTraits::isCategory(pattern);
if (!level.empty() && level[level.size()-1]=='+') {
for (int i = LevelTraits::level(level.substr(0,level.size()-1));
i < LevelTraits::COUNT;
- ++i)
- enable(Level(i), pattern);
+ ++i) {
+ if (isCat) {
+ enable(Level(i), CategoryTraits::category(pattern));
+ } else {
+ enable(Level(i), pattern);
+ }
+ }
}
else {
- enable(LevelTraits::level(level), pattern);
+ if (isCat) {
+ enable(LevelTraits::level(level), CategoryTraits::category(pattern));
+ } else {
+ enable(LevelTraits::level(level), pattern);
+ }
}
}
Selector::Selector(const Options& opt){
+ reset();
for_each(opt.selectors.begin(), opt.selectors.end(),
boost::bind(&Selector::enable, this, _1));
}
@@ -58,11 +69,17 @@ bool Selector::isEnabled(Level level, const char* function) {
for (std::vector<std::string>::iterator i=substrings[level].begin();
i != substrings[level].end();
++i)
- {
- if (std::search(function, functionEnd, i->begin(), i->end()) != functionEnd)
- return true;
- }
+ {
+ if (std::search(function, functionEnd, i->begin(), i->end()) != functionEnd)
+ return true;
+ }
return false;
}
+bool Selector::isEnabled(Level level, const char* function, Category category) {
+ if (catFlags[level][category])
+ return true;
+ return isEnabled(level, function);
+}
+
}} // namespace qpid::log
diff --git a/cpp/src/qpid/log/Statement.cpp b/cpp/src/qpid/log/Statement.cpp
index 79f7a28100..09ef458547 100644
--- a/cpp/src/qpid/log/Statement.cpp
+++ b/cpp/src/qpid/log/Statement.cpp
@@ -36,7 +36,7 @@ std::string quote(const std::string& str) {
size_t n = std::count_if(str.begin(), str.end(), nonPrint);
if (n==0) return str;
std::string ret;
- ret.reserve(str.size()+2*n); // Avoid extra allocations.
+ ret.reserve(str.size()+3*n); // Avoid extra allocations.
for (std::string::const_iterator i = str.begin(); i != str.end(); ++i) {
if (nonPrint(*i)) {
ret.push_back('\\');
@@ -50,10 +50,42 @@ std::string quote(const std::string& str) {
}
}
+//
+// Instance of name hints
+//
+static CategoryFileNameHints filenameHints;
+
+
+Category CategoryFileNameHints::categoryOf(const char* const fName) {
+ for (std::list<std::pair<const char* const, Category> >::iterator
+ it = filenameHints.hintList.begin();
+ it != filenameHints.hintList.end();
+ ++it) {
+ if (strstr(fName, (const char* const)it->first) != 0) {
+ return it->second;
+ }
+ }
+ return unspecified;
+}
+
+
+void Statement::categorize(Statement& s) {
+ // given a statement and it's category
+ // if the category is Unspecified then try to find a
+ // better category based on the path and file name.
+ if (s.category == log::unspecified) {
+ s.category = CategoryFileNameHints::categoryOf(s.file);
+ } else {
+ // already has a category so leave it alone
+ }
+}
+
+
void Statement::log(const std::string& message) {
Logger::instance().log(*this, quote(message));
}
+
Statement::Initializer::Initializer(Statement& s) : statement(s) {
// QPID-3891
// From the given BOOST_CURRENT_FUNCTION name extract only the
@@ -99,16 +131,22 @@ Statement::Initializer::Initializer(Statement& s) : statement(s) {
// no function-name pointer to process
}
+ Statement::categorize(s);
Logger::instance().add(s);
}
+
namespace {
const char* names[LevelTraits::COUNT] = {
"trace", "debug", "info", "notice", "warning", "error", "critical"
};
-} // namespace
+const char* catNames[CategoryTraits::COUNT] = {
+ "Security", "Broker", "Management", "Protocol", "System", "HA", "Messaging",
+ "Store", "Network", "Test", "Client", "Model", "Unspecified"
+};
+} // namespace
Level LevelTraits::level(const char* name) {
for (int i =0; i < LevelTraits::COUNT; ++i) {
if (strcmp(names[i], name)==0)
@@ -121,4 +159,23 @@ const char* LevelTraits::name(Level l) {
return names[l];
}
+bool CategoryTraits::isCategory(const std::string& name) {
+ for (int i =0; i < CategoryTraits::COUNT; ++i) {
+ if (strcmp(catNames[i], name.c_str())==0)
+ return true;
+ }
+ return false;
+}
+
+Category CategoryTraits::category(const char* name) {
+ for (int i =0; i < CategoryTraits::COUNT; ++i) {
+ if (strcmp(catNames[i], name)==0)
+ return Category(i);
+ }
+ throw std::runtime_error(std::string("Invalid log category name: ")+name);
+}
+
+const char* CategoryTraits::name(Category c) {
+ return catNames[c];
+}
}} // namespace qpid::log
diff --git a/cpp/src/qpid/log/posix/SinkOptions.cpp b/cpp/src/qpid/log/posix/SinkOptions.cpp
index 8459938e5c..d3db5f3cdf 100644
--- a/cpp/src/qpid/log/posix/SinkOptions.cpp
+++ b/cpp/src/qpid/log/posix/SinkOptions.cpp
@@ -22,11 +22,14 @@
#include "qpid/log/OstreamOutput.h"
#include "qpid/memory.h"
#include "qpid/Exception.h"
+
#include <iostream>
#include <map>
#include <string>
#include <syslog.h>
+#include <boost/lexical_cast.hpp>
+
using std::string;
using qpid::Exception;
@@ -90,7 +93,7 @@ public:
string name(int value) const {
ByValue::const_iterator i = byValue.find(value);
if (i == byValue.end())
- throw Exception("Not a valid syslog value: " + value);
+ throw Exception("Not a valid syslog value: " + boost::lexical_cast<string>(value));
return i->second;
}
diff --git a/cpp/src/qpid/management/Buffer.cpp b/cpp/src/qpid/management/Buffer.cpp
index 7556b2a243..0ad6e9a851 100644
--- a/cpp/src/qpid/management/Buffer.cpp
+++ b/cpp/src/qpid/management/Buffer.cpp
@@ -29,12 +29,11 @@ namespace management {
Buffer::Buffer(char* data, uint32_t size) : impl(new framing::Buffer(data, size)) {}
Buffer::~Buffer() { delete impl; }
-void Buffer::record() { impl->record(); }
-void Buffer::restore(bool reRecord) { impl->restore(reRecord); }
void Buffer::reset() { impl->reset(); }
uint32_t Buffer::available() { return impl->available(); }
uint32_t Buffer::getSize() { return impl->getSize(); }
uint32_t Buffer::getPosition() { return impl->getPosition(); }
+void Buffer::setPosition(uint32_t p) { impl->setPosition(p); }
char* Buffer::getPointer() { return impl->getPointer(); }
void Buffer::putOctet(uint8_t i) { impl->putOctet(i); }
void Buffer::putShort(uint16_t i) { impl->putShort(i); }
diff --git a/cpp/src/qpid/management/ManagementAgent.cpp b/cpp/src/qpid/management/ManagementAgent.cpp
index 062a530706..7d90ed99d0 100644
--- a/cpp/src/qpid/management/ManagementAgent.cpp
+++ b/cpp/src/qpid/management/ManagementAgent.cpp
@@ -1344,18 +1344,19 @@ void ManagementAgent::handleMethodRequestLH(Buffer& inBuffer, const string& repl
outBuffer.putLong (Manageable::STATUS_PARAMETER_INVALID);
outBuffer.putMediumString(Manageable::StatusText (Manageable::STATUS_PARAMETER_INVALID));
}
- else
+ else {
+ uint32_t pos = outBuffer.getPosition();
try {
- outBuffer.record();
sys::Mutex::ScopedUnlock u(userLock);
string outBuf;
iter->second->doMethod(methodName, inArgs, outBuf, userId);
outBuffer.putRawData(outBuf);
} catch(exception& e) {
- outBuffer.restore();
+ outBuffer.setPosition(pos);;
outBuffer.putLong(Manageable::STATUS_EXCEPTION);
outBuffer.putMediumString(e.what());
}
+ }
}
outLen = MA_BUFFER_SIZE - outBuffer.available();
@@ -1662,11 +1663,11 @@ void ManagementAgent::handleSchemaResponseLH(Buffer& inBuffer, const string& /*r
string packageName;
SchemaClassKey key;
- inBuffer.record();
+ uint32_t pos = inBuffer.getPosition();
inBuffer.getOctet();
inBuffer.getShortString(packageName);
key.decode(inBuffer);
- inBuffer.restore();
+ inBuffer.setPosition(pos);;
QPID_LOG(debug, "RECV SchemaResponse class=" << packageName << ":" << key.name << "(" << Uuid(key.hash) << ")" << " seq=" << sequence);
@@ -2426,7 +2427,6 @@ size_t ManagementAgent::validateTableSchema(Buffer& inBuffer)
uint8_t hash[16];
try {
- inBuffer.record();
uint8_t kind = inBuffer.getOctet();
if (kind != ManagementItem::CLASS_KIND_TABLE)
return 0;
@@ -2468,7 +2468,7 @@ size_t ManagementAgent::validateTableSchema(Buffer& inBuffer)
}
end = inBuffer.getPosition();
- inBuffer.restore(); // restore original position
+ inBuffer.setPosition(start); // restore original position
return end - start;
}
@@ -2480,7 +2480,6 @@ size_t ManagementAgent::validateEventSchema(Buffer& inBuffer)
uint8_t hash[16];
try {
- inBuffer.record();
uint8_t kind = inBuffer.getOctet();
if (kind != ManagementItem::CLASS_KIND_EVENT)
return 0;
@@ -2507,7 +2506,7 @@ size_t ManagementAgent::validateEventSchema(Buffer& inBuffer)
}
end = inBuffer.getPosition();
- inBuffer.restore(); // restore original position
+ inBuffer.setPosition(start); // restore original position
return end - start;
}
diff --git a/cpp/src/qpid/management/ManagementDirectExchange.cpp b/cpp/src/qpid/management/ManagementDirectExchange.cpp
index 312eacf462..9432a21b3a 100644
--- a/cpp/src/qpid/management/ManagementDirectExchange.cpp
+++ b/cpp/src/qpid/management/ManagementDirectExchange.cpp
@@ -28,7 +28,7 @@ using namespace qpid::broker;
using namespace qpid::framing;
using namespace qpid::sys;
-ManagementDirectExchange::ManagementDirectExchange(const string& _name, Manageable* _parent, Broker* b) :
+ManagementDirectExchange::ManagementDirectExchange(const std::string& _name, Manageable* _parent, Broker* b) :
Exchange (_name, _parent, b),
DirectExchange(_name, _parent, b),
managementAgent(0) {}
@@ -43,7 +43,7 @@ ManagementDirectExchange::ManagementDirectExchange(const std::string& _name,
void ManagementDirectExchange::route(Deliverable& msg)
{
bool routeIt = true;
- const string& routingKey = msg.getMessage().getRoutingKey();
+ const std::string& routingKey = msg.getMessage().getRoutingKey();
const FieldTable* args = msg.getMessage().getApplicationHeaders();
if (managementAgent)
diff --git a/cpp/src/qpid/management/ManagementTopicExchange.cpp b/cpp/src/qpid/management/ManagementTopicExchange.cpp
index 587cc660df..e5b659f217 100644
--- a/cpp/src/qpid/management/ManagementTopicExchange.cpp
+++ b/cpp/src/qpid/management/ManagementTopicExchange.cpp
@@ -27,7 +27,7 @@ using namespace qpid::broker;
using namespace qpid::framing;
using namespace qpid::sys;
-ManagementTopicExchange::ManagementTopicExchange(const string& _name, Manageable* _parent, Broker* b) :
+ManagementTopicExchange::ManagementTopicExchange(const std::string& _name, Manageable* _parent, Broker* b) :
Exchange (_name, _parent, b),
TopicExchange(_name, _parent, b),
managementAgent(0) {}
@@ -42,7 +42,7 @@ ManagementTopicExchange::ManagementTopicExchange(const std::string& _name,
void ManagementTopicExchange::route(Deliverable& msg)
{
bool routeIt = true;
- const string& routingKey = msg.getMessage().getRoutingKey();
+ const std::string& routingKey = msg.getMessage().getRoutingKey();
const FieldTable* args = msg.getMessage().getApplicationHeaders();
// Intercept management agent commands
@@ -54,7 +54,7 @@ void ManagementTopicExchange::route(Deliverable& msg)
}
bool ManagementTopicExchange::bind(Queue::shared_ptr queue,
- const string& routingKey,
+ const std::string& routingKey,
const qpid::framing::FieldTable* args)
{
if (qmfVersion == 1)
diff --git a/cpp/src/qpid/messaging/PrivateImplRef.h b/cpp/src/qpid/messaging/PrivateImplRef.h
index 718faef475..47afe30919 100644
--- a/cpp/src/qpid/messaging/PrivateImplRef.h
+++ b/cpp/src/qpid/messaging/PrivateImplRef.h
@@ -77,15 +77,15 @@ template <class T> class PrivateImplRef {
/** Set the implementation pointer in a handle */
static void set(T& t, const intrusive_ptr& p) {
if (t.impl == p) return;
- if (t.impl) boost::intrusive_ptr_release(t.impl);
+ if (t.impl) intrusive_ptr_release(t.impl);
t.impl = p.get();
- if (t.impl) boost::intrusive_ptr_add_ref(t.impl);
+ if (t.impl) intrusive_ptr_add_ref(t.impl);
}
// Helper functions to implement the ctor, dtor, copy, assign
- static void ctor(T& t, Impl* p) { t.impl = p; if (p) boost::intrusive_ptr_add_ref(p); }
+ static void ctor(T& t, Impl* p) { t.impl = p; if (p) intrusive_ptr_add_ref(p); }
static void copy(T& t, const T& x) { if (&t == &x) return; t.impl = 0; assign(t, x); }
- static void dtor(T& t) { if(t.impl) boost::intrusive_ptr_release(t.impl); }
+ static void dtor(T& t) { if(t.impl) intrusive_ptr_release(t.impl); }
static T& assign(T& t, const T& x) { set(t, get(x)); return t;}
};
diff --git a/cpp/src/qpid/replication/ReplicationExchange.cpp b/cpp/src/qpid/replication/ReplicationExchange.cpp
index 66f4f14d0c..bcb7c7f293 100644
--- a/cpp/src/qpid/replication/ReplicationExchange.cpp
+++ b/cpp/src/qpid/replication/ReplicationExchange.cpp
@@ -184,7 +184,7 @@ bool ReplicationExchange::unbind(Queue::shared_ptr /*queue*/, const std::string&
throw NotImplementedException("Replication exchange does not support unbind operation");
}
-bool ReplicationExchange::isBound(Queue::shared_ptr /*queue*/, const string* const /*routingKey*/, const FieldTable* const /*args*/)
+bool ReplicationExchange::isBound(Queue::shared_ptr /*queue*/, const std::string* const /*routingKey*/, const FieldTable* const /*args*/)
{
return false;
}
diff --git a/cpp/src/qpid/sys/AsynchIOHandler.cpp b/cpp/src/qpid/sys/AsynchIOHandler.cpp
index 5233002850..8a485db72d 100644
--- a/cpp/src/qpid/sys/AsynchIOHandler.cpp
+++ b/cpp/src/qpid/sys/AsynchIOHandler.cpp
@@ -23,6 +23,7 @@
#include "qpid/sys/AsynchIO.h"
#include "qpid/sys/Socket.h"
#include "qpid/sys/SecuritySettings.h"
+#include "qpid/sys/Timer.h"
#include "qpid/framing/AMQP_HighestVersion.h"
#include "qpid/framing/ProtocolInitiation.h"
#include "qpid/log/Statement.h"
@@ -41,11 +42,30 @@ struct Buff : public AsynchIO::BufferBase {
{ delete [] bytes;}
};
-AsynchIOHandler::AsynchIOHandler(std::string id, ConnectionCodec::Factory* f) :
+struct ProtocolTimeoutTask : public sys::TimerTask {
+ AsynchIOHandler& handler;
+ std::string id;
+
+ ProtocolTimeoutTask(const std::string& i, const Duration& timeout, AsynchIOHandler& h) :
+ TimerTask(timeout, "ProtocolTimeout"),
+ handler(h),
+ id(i)
+ {}
+
+ void fire() {
+ // If this fires it means that we didn't negotiate the connection in the timeout period
+ // Schedule closing the connection for the io thread
+ QPID_LOG(error, "Connection " << id << " No protocol received closing");
+ handler.abort();
+ }
+};
+
+AsynchIOHandler::AsynchIOHandler(const std::string& id, ConnectionCodec::Factory* f) :
identifier(id),
aio(0),
factory(f),
codec(0),
+ reads(0),
readError(false),
isClient(false),
readCredit(InfiniteCredit)
@@ -54,12 +74,18 @@ AsynchIOHandler::AsynchIOHandler(std::string id, ConnectionCodec::Factory* f) :
AsynchIOHandler::~AsynchIOHandler() {
if (codec)
codec->closed();
+ if (timeoutTimerTask)
+ timeoutTimerTask->cancel();
delete codec;
}
-void AsynchIOHandler::init(AsynchIO* a, int numBuffs) {
+void AsynchIOHandler::init(qpid::sys::AsynchIO* a, qpid::sys::Timer& timer, uint32_t maxTime, int numBuffs) {
aio = a;
+ // Start timer for this connection
+ timeoutTimerTask = new ProtocolTimeoutTask(identifier, maxTime*TIME_MSEC, *this);
+ timer.add(timeoutTimerTask);
+
// Give connection some buffers to use
for (int i = 0; i < numBuffs; i++) {
aio->queueReadBuffer(new Buff);
@@ -129,10 +155,18 @@ void AsynchIOHandler::readbuff(AsynchIO& , AsynchIO::BufferBase* buff) {
}
}
+ ++reads;
size_t decoded = 0;
if (codec) { // Already initiated
try {
decoded = codec->decode(buff->bytes+buff->dataStart, buff->dataCount);
+ // When we've decoded 3 reads (probably frames) we will have authenticated and
+ // started heartbeats, if specified, in many (but not all) cases so now we will cancel
+ // the idle connection timeout - this is really hacky, and would be better implemented
+ // in the connection, but that isn't actually created until the first decode.
+ if (reads == 3) {
+ timeoutTimerTask->cancel();
+ }
}catch(const std::exception& e){
QPID_LOG(error, e.what());
readError = true;
@@ -143,6 +177,7 @@ void AsynchIOHandler::readbuff(AsynchIO& , AsynchIO::BufferBase* buff) {
framing::ProtocolInitiation protocolInit;
if (protocolInit.decode(in)) {
decoded = in.getPosition();
+
QPID_LOG(debug, "RECV [" << identifier << "]: INIT(" << protocolInit << ")");
try {
codec = factory->create(protocolInit.getVersion(), *this, identifier, SecuritySettings());
@@ -202,6 +237,10 @@ void AsynchIOHandler::idle(AsynchIO&){
if (isClient && codec == 0) {
codec = factory->create(*this, identifier, SecuritySettings());
write(framing::ProtocolInitiation(codec->getVersion()));
+ // We've just sent the protocol negotiation so we can cancel the timeout for that
+ // This is not ideal, because we've not received anything yet, but heartbeats will
+ // be active soon
+ timeoutTimerTask->cancel();
return;
}
if (codec == 0) return;
diff --git a/cpp/src/qpid/sys/AsynchIOHandler.h b/cpp/src/qpid/sys/AsynchIOHandler.h
index b9867606c4..307aad5b85 100644
--- a/cpp/src/qpid/sys/AsynchIOHandler.h
+++ b/cpp/src/qpid/sys/AsynchIOHandler.h
@@ -27,6 +27,8 @@
#include "qpid/sys/Mutex.h"
#include "qpid/CommonImportExport.h"
+#include <boost/intrusive_ptr.hpp>
+
namespace qpid {
namespace framing {
@@ -38,24 +40,28 @@ namespace sys {
class AsynchIO;
struct AsynchIOBufferBase;
class Socket;
+class Timer;
+class TimerTask;
class AsynchIOHandler : public OutputControl {
std::string identifier;
AsynchIO* aio;
ConnectionCodec::Factory* factory;
ConnectionCodec* codec;
+ uint32_t reads;
bool readError;
bool isClient;
AtomicValue<int32_t> readCredit;
static const int32_t InfiniteCredit = -1;
Mutex creditLock;
+ boost::intrusive_ptr<sys::TimerTask> timeoutTimerTask;
void write(const framing::ProtocolInitiation&);
public:
- QPID_COMMON_EXTERN AsynchIOHandler(std::string id, ConnectionCodec::Factory* f);
+ QPID_COMMON_EXTERN AsynchIOHandler(const std::string& id, qpid::sys::ConnectionCodec::Factory* f );
QPID_COMMON_EXTERN ~AsynchIOHandler();
- QPID_COMMON_EXTERN void init(AsynchIO* a, int numBuffs);
+ QPID_COMMON_EXTERN void init(AsynchIO* a, Timer& timer, uint32_t maxTime, int numBuffs);
QPID_COMMON_INLINE_EXTERN void setClient() { isClient = true; }
diff --git a/cpp/src/qpid/sys/windows/MemStat.cpp b/cpp/src/qpid/sys/MemStat.cpp
index b1d25c5fc5..c71fba785c 100644
--- a/cpp/src/qpid/sys/windows/MemStat.cpp
+++ b/cpp/src/qpid/sys/MemStat.cpp
@@ -21,9 +21,11 @@
#include "qpid/sys/MemStat.h"
+// Null memory stats provider:
+// This is for platforms that do not have a way to get allocated
+// memory status
void qpid::sys::MemStat::loadMemInfo(qmf::org::apache::qpid::broker::Memory*)
{
- // TODO: Add Windows-specific memory stats to the object and load them here.
}
diff --git a/cpp/src/qpid/sys/SslPlugin.cpp b/cpp/src/qpid/sys/SslPlugin.cpp
index 48baef9042..3b50527c0a 100644
--- a/cpp/src/qpid/sys/SslPlugin.cpp
+++ b/cpp/src/qpid/sys/SslPlugin.cpp
@@ -39,6 +39,8 @@
namespace qpid {
namespace sys {
+class Timer;
+
using namespace qpid::sys::ssl;
struct SslServerOptions : ssl::SslOptions
@@ -68,6 +70,8 @@ class SslProtocolFactoryTmpl : public ProtocolFactory {
typedef SslAcceptorTmpl<T> SslAcceptor;
+ Timer& brokerTimer;
+ uint32_t maxNegotiateTime;
const bool tcpNoDelay;
T listener;
const uint16_t listeningPort;
@@ -75,7 +79,7 @@ class SslProtocolFactoryTmpl : public ProtocolFactory {
bool nodict;
public:
- SslProtocolFactoryTmpl(const SslServerOptions&, int backlog, bool nodelay);
+ SslProtocolFactoryTmpl(const SslServerOptions&, int backlog, bool nodelay, Timer& timer, uint32_t maxTime);
void accept(Poller::shared_ptr, ConnectionCodec::Factory*);
void connect(Poller::shared_ptr, const std::string& host, const std::string& port,
ConnectionCodec::Factory*,
@@ -132,16 +136,18 @@ static struct SslPlugin : public Plugin {
try {
ssl::initNSS(options, true);
nssInitialized = true;
-
+
const broker::Broker::Options& opts = broker->getOptions();
ProtocolFactory::shared_ptr protocol(options.multiplex ?
static_cast<ProtocolFactory*>(new SslMuxProtocolFactory(options,
opts.connectionBacklog,
- opts.tcpNoDelay)) :
+ opts.tcpNoDelay,
+ broker->getTimer(), opts.maxNegotiateTime)) :
static_cast<ProtocolFactory*>(new SslProtocolFactory(options,
opts.connectionBacklog,
- opts.tcpNoDelay)));
+ opts.tcpNoDelay,
+ broker->getTimer(), opts.maxNegotiateTime)));
QPID_LOG(notice, "Listening for " <<
(options.multiplex ? "SSL or TCP" : "SSL") <<
" connections on TCP port " <<
@@ -156,14 +162,16 @@ static struct SslPlugin : public Plugin {
} sslPlugin;
template <class T>
-SslProtocolFactoryTmpl<T>::SslProtocolFactoryTmpl(const SslServerOptions& options, int backlog, bool nodelay) :
+SslProtocolFactoryTmpl<T>::SslProtocolFactoryTmpl(const SslServerOptions& options, int backlog, bool nodelay, Timer& timer, uint32_t maxTime) :
+ brokerTimer(timer),
+ maxNegotiateTime(maxTime),
tcpNoDelay(nodelay), listeningPort(listener.listen(options.port, backlog, options.certName, options.clientAuth)),
nodict(options.nodict)
{}
void SslEstablished(Poller::shared_ptr poller, const qpid::sys::SslSocket& s,
ConnectionCodec::Factory* f, bool isClient,
- bool tcpNoDelay, bool nodict) {
+ Timer& timer, uint32_t maxTime, bool tcpNoDelay, bool nodict) {
qpid::sys::ssl::SslHandler* async = new qpid::sys::ssl::SslHandler(s.getFullAddress(), f, nodict);
if (tcpNoDelay) {
@@ -183,7 +191,7 @@ void SslEstablished(Poller::shared_ptr poller, const qpid::sys::SslSocket& s,
boost::bind(&qpid::sys::ssl::SslHandler::nobuffs, async, _1),
boost::bind(&qpid::sys::ssl::SslHandler::idle, async, _1));
- async->init(aio, 4);
+ async->init(aio,timer, maxTime, 4);
aio->start(poller);
}
@@ -192,7 +200,7 @@ void SslProtocolFactory::established(Poller::shared_ptr poller, const Socket& s,
ConnectionCodec::Factory* f, bool isClient) {
const SslSocket *sslSock = dynamic_cast<const SslSocket*>(&s);
- SslEstablished(poller, *sslSock, f, isClient, tcpNoDelay, nodict);
+ SslEstablished(poller, *sslSock, f, isClient, brokerTimer, maxNegotiateTime, tcpNoDelay, nodict);
}
template <class T>
@@ -216,7 +224,7 @@ void SslMuxProtocolFactory::established(Poller::shared_ptr poller, const Socket&
const SslSocket *sslSock = dynamic_cast<const SslSocket*>(&s);
if (sslSock) {
- SslEstablished(poller, *sslSock, f, isClient, tcpNoDelay, nodict);
+ SslEstablished(poller, *sslSock, f, isClient, brokerTimer, maxNegotiateTime, tcpNoDelay, nodict);
return;
}
@@ -239,7 +247,7 @@ void SslMuxProtocolFactory::established(Poller::shared_ptr poller, const Socket&
boost::bind(&AsynchIOHandler::nobuffs, async, _1),
boost::bind(&AsynchIOHandler::idle, async, _1));
- async->init(aio, 4);
+ async->init(aio, brokerTimer, maxNegotiateTime, 4);
aio->start(poller);
}
diff --git a/cpp/src/qpid/sys/TCPIOPlugin.cpp b/cpp/src/qpid/sys/TCPIOPlugin.cpp
index bd10a5555a..551440f954 100644
--- a/cpp/src/qpid/sys/TCPIOPlugin.cpp
+++ b/cpp/src/qpid/sys/TCPIOPlugin.cpp
@@ -36,14 +36,21 @@
namespace qpid {
namespace sys {
+class Timer;
+
class AsynchIOProtocolFactory : public ProtocolFactory {
- const bool tcpNoDelay;
boost::ptr_vector<Socket> listeners;
boost::ptr_vector<AsynchAcceptor> acceptors;
+ Timer& brokerTimer;
+ uint32_t maxNegotiateTime;
uint16_t listeningPort;
+ const bool tcpNoDelay;
public:
- AsynchIOProtocolFactory(const std::string& host, const std::string& port, int backlog, bool nodelay, bool shouldListen);
+ AsynchIOProtocolFactory(const std::string& host, const std::string& port,
+ int backlog, bool nodelay,
+ Timer& timer, uint32_t maxTime,
+ bool shouldListen);
void accept(Poller::shared_ptr, ConnectionCodec::Factory*);
void connect(Poller::shared_ptr, const std::string& host, const std::string& port,
ConnectionCodec::Factory*,
@@ -90,6 +97,7 @@ static class TCPIOPlugin : public Plugin {
"", boost::lexical_cast<std::string>(opts.port),
opts.connectionBacklog,
opts.tcpNoDelay,
+ broker->getTimer(), opts.maxNegotiateTime,
shouldListen));
if (shouldListen) {
@@ -101,7 +109,12 @@ static class TCPIOPlugin : public Plugin {
}
} tcpPlugin;
-AsynchIOProtocolFactory::AsynchIOProtocolFactory(const std::string& host, const std::string& port, int backlog, bool nodelay, bool shouldListen) :
+AsynchIOProtocolFactory::AsynchIOProtocolFactory(const std::string& host, const std::string& port,
+ int backlog, bool nodelay,
+ Timer& timer, uint32_t maxTime,
+ bool shouldListen) :
+ brokerTimer(timer),
+ maxNegotiateTime(maxTime),
tcpNoDelay(nodelay)
{
if (!shouldListen) {
@@ -153,7 +166,7 @@ void AsynchIOProtocolFactory::established(Poller::shared_ptr poller, const Socke
boost::bind(&AsynchIOHandler::nobuffs, async, _1),
boost::bind(&AsynchIOHandler::idle, async, _1));
- async->init(aio, 4);
+ async->init(aio, brokerTimer, maxNegotiateTime, 4);
aio->start(poller);
}
diff --git a/cpp/src/qpid/sys/Timer.cpp b/cpp/src/qpid/sys/Timer.cpp
index 47752e4584..973c6bd8b7 100644
--- a/cpp/src/qpid/sys/Timer.cpp
+++ b/cpp/src/qpid/sys/Timer.cpp
@@ -35,7 +35,7 @@ TimerTask::TimerTask(Duration timeout, const std::string& n) :
sortTime(AbsTime::FarFuture()),
period(timeout),
nextFireTime(AbsTime::now(), timeout),
- cancelled(false)
+ state(WAITING)
{}
TimerTask::TimerTask(AbsTime time, const std::string& n) :
@@ -43,7 +43,7 @@ TimerTask::TimerTask(AbsTime time, const std::string& n) :
sortTime(AbsTime::FarFuture()),
period(0),
nextFireTime(time),
- cancelled(false)
+ state(WAITING)
{}
TimerTask::~TimerTask() {}
@@ -52,27 +52,48 @@ bool TimerTask::readyToFire() const {
return !(nextFireTime > AbsTime::now());
}
+bool TimerTask::prepareToFire() {
+ Monitor::ScopedLock l(stateMonitor);
+ if (state != CANCELLED) {
+ state = CALLING;
+ return true;
+ } else {
+ return false;
+ }
+}
+
void TimerTask::fireTask() {
- cancelled = true;
fire();
}
+void TimerTask::finishFiring() {
+ Monitor::ScopedLock l(stateMonitor);
+ if (state != CANCELLED) {
+ state = WAITING;
+ stateMonitor.notifyAll();
+ }
+}
+
// This can only be used to setup the next fire time. After the Timer has already fired
void TimerTask::setupNextFire() {
if (period && readyToFire()) {
nextFireTime = max(AbsTime::now(), AbsTime(nextFireTime, period));
- cancelled = false;
} else {
QPID_LOG(error, name << " couldn't setup next timer firing: " << Duration(nextFireTime, AbsTime::now()) << "[" << period << "]");
}
}
// Only allow tasks to be delayed
-void TimerTask::restart() { nextFireTime = max(nextFireTime, AbsTime(AbsTime::now(), period)); }
+void TimerTask::restart() {
+ nextFireTime = max(nextFireTime, AbsTime(AbsTime::now(), period));
+}
void TimerTask::cancel() {
- ScopedLock<Mutex> l(callbackLock);
- cancelled = true;
+ Monitor::ScopedLock l(stateMonitor);
+ while (state == CALLING) {
+ stateMonitor.wait();
+ }
+ state = CANCELLED;
}
void TimerTask::setFired() {
@@ -96,6 +117,22 @@ Timer::~Timer()
stop();
}
+class TimerTaskCallbackScope {
+ TimerTask& tt;
+public:
+ explicit TimerTaskCallbackScope(TimerTask& t) :
+ tt(t)
+ {}
+
+ operator bool() {
+ return !tt.prepareToFire();
+ }
+
+ ~TimerTaskCallbackScope() {
+ tt.finishFiring();
+ }
+};
+
// TODO AStitcher 21/08/09 The threshholds for emitting warnings are a little arbitrary
void Timer::run()
{
@@ -112,8 +149,8 @@ void Timer::run()
AbsTime start(AbsTime::now());
Duration delay(t->sortTime, start);
{
- ScopedLock<Mutex> l(t->callbackLock);
- if (t->cancelled) {
+ TimerTaskCallbackScope s(*t);
+ if (s) {
{
Monitor::ScopedUnlock u(monitor);
drop(t);
diff --git a/cpp/src/qpid/sys/Timer.h b/cpp/src/qpid/sys/Timer.h
index fccb17dbc2..5731b8d977 100644
--- a/cpp/src/qpid/sys/Timer.h
+++ b/cpp/src/qpid/sys/Timer.h
@@ -40,6 +40,7 @@ class Timer;
class TimerTask : public RefCounted {
friend class Timer;
+ friend class TimerTaskCallbackScope;
friend bool operator<(const boost::intrusive_ptr<TimerTask>&,
const boost::intrusive_ptr<TimerTask>&);
@@ -47,9 +48,11 @@ class TimerTask : public RefCounted {
AbsTime sortTime;
Duration period;
AbsTime nextFireTime;
- Mutex callbackLock;
- volatile bool cancelled;
+ qpid::sys::Monitor stateMonitor;
+ enum {WAITING, CALLING, CANCELLED} state;
+ bool prepareToFire();
+ void finishFiring();
bool readyToFire() const;
void fireTask();
diff --git a/cpp/src/qpid/sys/cyrus/CyrusSecurityLayer.cpp b/cpp/src/qpid/sys/cyrus/CyrusSecurityLayer.cpp
index 249b769051..29b91f3e7a 100644
--- a/cpp/src/qpid/sys/cyrus/CyrusSecurityLayer.cpp
+++ b/cpp/src/qpid/sys/cyrus/CyrusSecurityLayer.cpp
@@ -18,6 +18,7 @@
* under the License.
*
*/
+#include <unistd.h>
#include "qpid/sys/cyrus/CyrusSecurityLayer.h"
#include <algorithm>
#include "qpid/framing/reply_exceptions.h"
diff --git a/cpp/src/qpid/sys/posix/LockFile.cpp b/cpp/src/qpid/sys/posix/LockFile.cpp
index c1f1c37b47..9fdf83f1bd 100755
--- a/cpp/src/qpid/sys/posix/LockFile.cpp
+++ b/cpp/src/qpid/sys/posix/LockFile.cpp
@@ -46,7 +46,7 @@ LockFile::LockFile(const std::string& path_, bool create)
errno = 0;
int flags=create ? O_WRONLY|O_CREAT|O_NOFOLLOW : O_RDWR;
int fd = ::open(path.c_str(), flags, 0644);
- if (fd < 0) throw ErrnoException("Cannot open " + path, errno);
+ if (fd < 0) throw ErrnoException("Cannot open lock file " + path, errno);
if (::lockf(fd, F_TLOCK, 0) < 0) {
::close(fd);
throw ErrnoException("Cannot lock " + path, errno);
diff --git a/cpp/src/qpid/sys/posix/MemStat.cpp b/cpp/src/qpid/sys/posix/MemStat.cpp
index 72c53e5886..2fbf119cab 100644
--- a/cpp/src/qpid/sys/posix/MemStat.cpp
+++ b/cpp/src/qpid/sys/posix/MemStat.cpp
@@ -20,6 +20,7 @@
*/
#include "qpid/sys/MemStat.h"
+
#include <malloc.h>
void qpid::sys::MemStat::loadMemInfo(qmf::org::apache::qpid::broker::Memory* object)
@@ -35,4 +36,3 @@ void qpid::sys::MemStat::loadMemInfo(qmf::org::apache::qpid::broker::Memory* obj
object->set_malloc_keepcost(info.keepcost);
}
-
diff --git a/cpp/src/qpid/sys/posix/SocketAddress.cpp b/cpp/src/qpid/sys/posix/SocketAddress.cpp
index a7049c1851..344bd28669 100644
--- a/cpp/src/qpid/sys/posix/SocketAddress.cpp
+++ b/cpp/src/qpid/sys/posix/SocketAddress.cpp
@@ -35,14 +35,16 @@ namespace sys {
SocketAddress::SocketAddress(const std::string& host0, const std::string& port0) :
host(host0),
port(port0),
- addrInfo(0)
+ addrInfo(0),
+ currentAddrInfo(0)
{
}
SocketAddress::SocketAddress(const SocketAddress& sa) :
host(sa.host),
port(sa.port),
- addrInfo(0)
+ addrInfo(0),
+ currentAddrInfo(0)
{
}
diff --git a/cpp/src/qpid/sys/posix/SystemInfo.cpp b/cpp/src/qpid/sys/posix/SystemInfo.cpp
index 540cc8bc91..2b1bbb97df 100755
--- a/cpp/src/qpid/sys/posix/SystemInfo.cpp
+++ b/cpp/src/qpid/sys/posix/SystemInfo.cpp
@@ -18,10 +18,11 @@
*
*/
+#include "qpid/log/Statement.h"
#include "qpid/sys/SystemInfo.h"
-
#include "qpid/sys/posix/check.h"
-
+#include <set>
+#include <arpa/inet.h>
#include <sys/ioctl.h>
#include <sys/utsname.h>
#include <sys/types.h> // For FreeBSD
@@ -33,6 +34,7 @@
#include <fstream>
#include <sstream>
#include <netdb.h>
+#include <string.h>
#ifndef HOST_NAME_MAX
# define HOST_NAME_MAX 256
@@ -59,48 +61,100 @@ bool SystemInfo::getLocalHostname (Address &address) {
return true;
}
-static const string LOCALHOST("127.0.0.1");
+static const string LOOPBACK("127.0.0.1");
static const string TCP("tcp");
+// Test IPv4 address for loopback
+inline bool IN_IS_ADDR_LOOPBACK(const ::in_addr* a) {
+ return ((ntohl(a->s_addr) & 0xff000000) == 0x7f000000);
+}
+
+inline bool isLoopback(const ::sockaddr* addr) {
+ switch (addr->sa_family) {
+ case AF_INET: return IN_IS_ADDR_LOOPBACK(&((const ::sockaddr_in*)(const void*)addr)->sin_addr);
+ case AF_INET6: return IN6_IS_ADDR_LOOPBACK(&((const ::sockaddr_in6*)(const void*)addr)->sin6_addr);
+ default: return false;
+ }
+}
+
void SystemInfo::getLocalIpAddresses (uint16_t port,
std::vector<Address> &addrList) {
::ifaddrs* ifaddr = 0;
QPID_POSIX_CHECK(::getifaddrs(&ifaddr));
for (::ifaddrs* ifap = ifaddr; ifap != 0; ifap = ifap->ifa_next) {
if (ifap->ifa_addr == 0) continue;
-
+ if (isLoopback(ifap->ifa_addr)) continue;
int family = ifap->ifa_addr->sa_family;
switch (family) {
- case AF_INET: {
- char dispName[NI_MAXHOST];
- int rc = ::getnameinfo(
- ifap->ifa_addr,
- (family == AF_INET)
- ? sizeof(struct sockaddr_in)
- : sizeof(struct sockaddr_in6),
- dispName, sizeof(dispName),
- 0, 0, NI_NUMERICHOST);
- if (rc != 0) {
- throw QPID_POSIX_ERROR(rc);
+ case AF_INET6: {
+ // Ignore link local addresses as:
+ // * The scope id is illegal in URL syntax
+ // * Clients won't be able to use a link local address
+ // without adding their own (potentially different) scope id
+ sockaddr_in6* sa6 = (sockaddr_in6*)(ifap->ifa_addr);
+ if (IN6_IS_ADDR_LINKLOCAL(&sa6->sin6_addr)) break;
+ // Fallthrough
}
- string addr(dispName);
- if (addr != LOCALHOST) {
- addrList.push_back(Address(TCP, addr, port));
- }
- break;
- }
- // TODO: Url parsing currently can't cope with IPv6 addresses so don't return them
- // when it can cope move this line to above "case AF_INET:"
- case AF_INET6:
- default:
+ case AF_INET: {
+ char dispName[NI_MAXHOST];
+ int rc = ::getnameinfo(
+ ifap->ifa_addr,
+ (family == AF_INET)
+ ? sizeof(struct sockaddr_in)
+ : sizeof(struct sockaddr_in6),
+ dispName, sizeof(dispName),
+ 0, 0, NI_NUMERICHOST);
+ if (rc != 0) {
+ throw QPID_POSIX_ERROR(rc);
+ }
+ string addr(dispName);
+ addrList.push_back(Address(TCP, addr, port));
+ break;
+ }
+ default:
continue;
}
}
- freeifaddrs(ifaddr);
+ ::freeifaddrs(ifaddr);
if (addrList.empty()) {
- addrList.push_back(Address(TCP, LOCALHOST, port));
+ addrList.push_back(Address(TCP, LOOPBACK, port));
+ }
+}
+
+namespace {
+struct AddrInfo {
+ struct addrinfo* ptr;
+ AddrInfo(const std::string& host) : ptr(0) {
+ ::addrinfo hints;
+ ::memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_UNSPEC; // Allow both IPv4 and IPv6
+ if (::getaddrinfo(host.c_str(), NULL, &hints, &ptr) != 0)
+ ptr = 0;
+ }
+ ~AddrInfo() { if (ptr) ::freeaddrinfo(ptr); }
+};
+}
+
+bool SystemInfo::isLocalHost(const std::string& host) {
+ std::vector<Address> myAddrs;
+ getLocalIpAddresses(0, myAddrs);
+ std::set<string> localHosts;
+ for (std::vector<Address>::const_iterator i = myAddrs.begin(); i != myAddrs.end(); ++i)
+ localHosts.insert(i->host);
+ // Resolve host
+ AddrInfo ai(host);
+ if (!ai.ptr) return false;
+ for (struct addrinfo *res = ai.ptr; res != NULL; res = res->ai_next) {
+ if (isLoopback(res->ai_addr)) return true;
+ // Get string form of IP addr
+ char addr[NI_MAXHOST] = "";
+ int error = ::getnameinfo(res->ai_addr, res->ai_addrlen, addr, NI_MAXHOST, NULL, 0,
+ NI_NUMERICHOST | NI_NUMERICSERV);
+ if (error) return false;
+ if (localHosts.find(addr) != localHosts.end()) return true;
}
+ return false;
}
void SystemInfo::getSystemId (std::string &osName,
diff --git a/cpp/src/qpid/sys/ssl/SslHandler.cpp b/cpp/src/qpid/sys/ssl/SslHandler.cpp
index 67bf4ea893..8613059f28 100644
--- a/cpp/src/qpid/sys/ssl/SslHandler.cpp
+++ b/cpp/src/qpid/sys/ssl/SslHandler.cpp
@@ -19,9 +19,9 @@
*
*/
#include "qpid/sys/ssl/SslHandler.h"
-
#include "qpid/sys/ssl/SslIo.h"
#include "qpid/sys/ssl/SslSocket.h"
+#include "qpid/sys/Timer.h"
#include "qpid/framing/AMQP_HighestVersion.h"
#include "qpid/framing/ProtocolInitiation.h"
#include "qpid/log/Statement.h"
@@ -42,6 +42,24 @@ struct Buff : public SslIO::BufferBase {
{ delete [] bytes;}
};
+struct ProtocolTimeoutTask : public sys::TimerTask {
+ SslHandler& handler;
+ std::string id;
+
+ ProtocolTimeoutTask(const std::string& i, const Duration& timeout, SslHandler& h) :
+ TimerTask(timeout, "ProtocolTimeout"),
+ handler(h),
+ id(i)
+ {}
+
+ void fire() {
+ // If this fires it means that we didn't negotiate the connection in the timeout period
+ // Schedule closing the connection for the io thread
+ QPID_LOG(error, "Connection " << id << " No protocol received closing");
+ handler.abort();
+ }
+};
+
SslHandler::SslHandler(std::string id, ConnectionCodec::Factory* f, bool _nodict) :
identifier(id),
aio(0),
@@ -55,12 +73,18 @@ SslHandler::SslHandler(std::string id, ConnectionCodec::Factory* f, bool _nodict
SslHandler::~SslHandler() {
if (codec)
codec->closed();
+ if (timeoutTimerTask)
+ timeoutTimerTask->cancel();
delete codec;
}
-void SslHandler::init(SslIO* a, int numBuffs) {
+void SslHandler::init(SslIO* a, Timer& timer, uint32_t maxTime, int numBuffs) {
aio = a;
+ // Start timer for this connection
+ timeoutTimerTask = new ProtocolTimeoutTask(identifier, maxTime*TIME_MSEC, *this);
+ timer.add(timeoutTimerTask);
+
// Give connection some buffers to use
for (int i = 0; i < numBuffs; i++) {
aio->queueReadBuffer(new Buff);
@@ -80,8 +104,10 @@ void SslHandler::write(const framing::ProtocolInitiation& data)
}
void SslHandler::abort() {
- // TODO: can't implement currently as underlying functionality not implemented
- // aio->requestCallback(boost::bind(&SslHandler::eof, this, _1));
+ // Don't disconnect if we're already disconnecting
+ if (!readError) {
+ aio->requestCallback(boost::bind(&SslHandler::eof, this, _1));
+ }
}
void SslHandler::activateOutput() {
aio->notifyPendingWrite();
@@ -109,6 +135,9 @@ void SslHandler::readbuff(SslIO& , SslIO::BufferBase* buff) {
framing::Buffer in(buff->bytes+buff->dataStart, buff->dataCount);
framing::ProtocolInitiation protocolInit;
if (protocolInit.decode(in)) {
+ // We've just got the protocol negotiation so we can cancel the timeout for that
+ timeoutTimerTask->cancel();
+
decoded = in.getPosition();
QPID_LOG(debug, "RECV [" << identifier << "]: INIT(" << protocolInit << ")");
try {
@@ -169,6 +198,10 @@ void SslHandler::idle(SslIO&){
if (isClient && codec == 0) {
codec = factory->create(*this, identifier, getSecuritySettings(aio));
write(framing::ProtocolInitiation(codec->getVersion()));
+ // We've just sent the protocol negotiation so we can cancel the timeout for that
+ // This is not ideal, because we've not received anything yet, but heartbeats will
+ // be active soon
+ timeoutTimerTask->cancel();
return;
}
if (codec == 0) return;
diff --git a/cpp/src/qpid/sys/ssl/SslHandler.h b/cpp/src/qpid/sys/ssl/SslHandler.h
index 400fa317fd..74df2b7fb0 100644
--- a/cpp/src/qpid/sys/ssl/SslHandler.h
+++ b/cpp/src/qpid/sys/ssl/SslHandler.h
@@ -25,6 +25,8 @@
#include "qpid/sys/ConnectionCodec.h"
#include "qpid/sys/OutputControl.h"
+#include <boost/intrusive_ptr.hpp>
+
namespace qpid {
namespace framing {
@@ -32,6 +34,10 @@ namespace framing {
}
namespace sys {
+
+class Timer;
+class TimerTask;
+
namespace ssl {
class SslIO;
@@ -46,6 +52,7 @@ class SslHandler : public OutputControl {
bool readError;
bool isClient;
bool nodict;
+ boost::intrusive_ptr<sys::TimerTask> timeoutTimerTask;
void write(const framing::ProtocolInitiation&);
qpid::sys::SecuritySettings getSecuritySettings(SslIO* aio);
@@ -53,7 +60,7 @@ class SslHandler : public OutputControl {
public:
SslHandler(std::string id, ConnectionCodec::Factory* f, bool nodict);
~SslHandler();
- void init(SslIO* a, int numBuffs);
+ void init(SslIO* a, Timer& timer, uint32_t maxTime, int numBuffs);
void setClient() { isClient = true; }
diff --git a/cpp/src/qpid/sys/ssl/SslIo.cpp b/cpp/src/qpid/sys/ssl/SslIo.cpp
index 2a7cf16923..789c205ead 100644
--- a/cpp/src/qpid/sys/ssl/SslIo.cpp
+++ b/cpp/src/qpid/sys/ssl/SslIo.cpp
@@ -257,6 +257,18 @@ void SslIO::queueWriteClose() {
DispatchHandle::rewatchWrite();
}
+void SslIO::requestCallback(RequestCallback callback) {
+ // TODO creating a function object every time isn't all that
+ // efficient - if this becomes heavily used do something better (what?)
+ assert(callback);
+ DispatchHandle::call(boost::bind(&SslIO::requestedCall, this, callback));
+}
+
+void SslIO::requestedCall(RequestCallback callback) {
+ assert(callback);
+ callback(*this);
+}
+
/** Return a queued buffer if there are enough
* to spare
*/
diff --git a/cpp/src/qpid/sys/ssl/SslIo.h b/cpp/src/qpid/sys/ssl/SslIo.h
index c980d73831..b795594cd9 100644
--- a/cpp/src/qpid/sys/ssl/SslIo.h
+++ b/cpp/src/qpid/sys/ssl/SslIo.h
@@ -125,6 +125,7 @@ public:
typedef boost::function2<void, SslIO&, const SslSocket&> ClosedCallback;
typedef boost::function1<void, SslIO&> BuffersEmptyCallback;
typedef boost::function1<void, SslIO&> IdleCallback;
+ typedef boost::function1<void, SslIO&> RequestCallback;
private:
@@ -159,6 +160,7 @@ public:
void notifyPendingWrite();
void queueWriteClose();
bool writeQueueEmpty() { return writeQueue.empty(); }
+ void requestCallback(RequestCallback);
BufferBase* getQueuedBuffer();
qpid::sys::SecuritySettings getSecuritySettings();
@@ -168,6 +170,7 @@ private:
void readable(qpid::sys::DispatchHandle& handle);
void writeable(qpid::sys::DispatchHandle& handle);
void disconnected(qpid::sys::DispatchHandle& handle);
+ void requestedCall(RequestCallback);
void close(qpid::sys::DispatchHandle& handle);
};
diff --git a/cpp/src/qpid/sys/unordered_map.h b/cpp/src/qpid/sys/unordered_map.h
index 5f7f9567c5..7ae71c3daa 100644
--- a/cpp/src/qpid/sys/unordered_map.h
+++ b/cpp/src/qpid/sys/unordered_map.h
@@ -23,6 +23,8 @@
#ifdef _MSC_VER
# include <unordered_map>
+#elif defined(__SUNPRO_CC)
+# include <boost/tr1/unordered_map.hpp>
#else
# include <tr1/unordered_map>
#endif /* _MSC_VER */
diff --git a/cpp/src/qpid/sys/windows/IocpPoller.cpp b/cpp/src/qpid/sys/windows/IocpPoller.cpp
index 1805dd2cd8..c81cef87b0 100755
--- a/cpp/src/qpid/sys/windows/IocpPoller.cpp
+++ b/cpp/src/qpid/sys/windows/IocpPoller.cpp
@@ -96,6 +96,7 @@ void Poller::shutdown() {
// Allow sloppy code to shut us down more than once.
if (impl->isShutdown)
return;
+ impl->isShutdown = true;
ULONG_PTR key = 1; // Tell wait() it's a shutdown, not I/O
PostQueuedCompletionStatus(impl->iocp, 0, key, 0);
}
@@ -110,7 +111,7 @@ bool Poller::interrupt(PollerHandle&) {
}
void Poller::run() {
- do {
+ while (!impl->isShutdown) {
Poller::Event event = this->wait();
// Handle shutdown
@@ -124,7 +125,7 @@ void Poller::run() {
// This should be impossible
assert(false);
}
- } while (true);
+ }
}
void Poller::monitorHandle(PollerHandle& handle, Direction dir) {
diff --git a/cpp/src/qpid/sys/windows/Socket.cpp b/cpp/src/qpid/sys/windows/Socket.cpp
index b085f67539..a4374260cc 100644
--- a/cpp/src/qpid/sys/windows/Socket.cpp
+++ b/cpp/src/qpid/sys/windows/Socket.cpp
@@ -266,14 +266,17 @@ int Socket::getError() const
void Socket::setTcpNoDelay() const
{
- int flag = 1;
- int result = setsockopt(impl->fd,
- IPPROTO_TCP,
- TCP_NODELAY,
- (char *)&flag,
- sizeof(flag));
- QPID_WINSOCK_CHECK(result);
+ SOCKET& socket = impl->fd;
nodelay = true;
+ if (socket != INVALID_SOCKET) {
+ int flag = 1;
+ int result = setsockopt(impl->fd,
+ IPPROTO_TCP,
+ TCP_NODELAY,
+ (char *)&flag,
+ sizeof(flag));
+ QPID_WINSOCK_CHECK(result);
+ }
}
inline IOHandlePrivate* IOHandlePrivate::getImpl(const qpid::sys::IOHandle &h)
diff --git a/cpp/src/qpid/sys/windows/SystemInfo.cpp b/cpp/src/qpid/sys/windows/SystemInfo.cpp
index 4da440bdd4..cef78dcc60 100755
--- a/cpp/src/qpid/sys/windows/SystemInfo.cpp
+++ b/cpp/src/qpid/sys/windows/SystemInfo.cpp
@@ -23,9 +23,11 @@
# define _WIN32_WINNT 0x0501
#endif
-#include "qpid/sys/IntegerTypes.h"
#include "qpid/sys/SystemInfo.h"
+#include "qpid/sys/IntegerTypes.h"
+#include "qpid/Exception.h"
+#include <assert.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <windows.h>
@@ -93,6 +95,12 @@ void SystemInfo::getLocalIpAddresses (uint16_t port,
}
}
+bool SystemInfo::isLocalHost(const std::string& candidateHost) {
+ // FIXME aconway 2012-05-03: not implemented.
+ assert(0);
+ throw Exception("Not implemented: isLocalHost");
+}
+
void SystemInfo::getSystemId (std::string &osName,
std::string &nodeName,
std::string &release,
diff --git a/cpp/src/qpid/types/Variant.cpp b/cpp/src/qpid/types/Variant.cpp
index 6af06ede5d..d332fffa5e 100644
--- a/cpp/src/qpid/types/Variant.cpp
+++ b/cpp/src/qpid/types/Variant.cpp
@@ -103,31 +103,27 @@ class VariantImpl
int64_t i64;
float f;
double d;
- void* v;//variable width data
+ Uuid* uuid;
+ Variant::Map* map;
+ Variant::List* list;
+ std::string* string;
} value;
std::string encoding;//optional encoding for variable length data
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) {
+ const std::string& s = *value.string;
+ try {
+ T r = boost::lexical_cast<T>(s);
//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
+ //So check that and allow special case of negative zero
+ //else its a non-zero negative number so throw exception at end of function
+ if (std::numeric_limits<T>::is_signed || s.find('-') != 0 || r == 0) {
+ return r;
}
+ } catch(const boost::bad_lexical_cast&) {
}
- throw InvalidConversion(QPID_MSG("Cannot convert " << *s));
+ throw InvalidConversion(QPID_MSG("Cannot convert " << s));
}
};
@@ -145,24 +141,24 @@ VariantImpl::VariantImpl(int64_t i) : type(VAR_INT64) { value.i64 = i; }
VariantImpl::VariantImpl(float f) : type(VAR_FLOAT) { value.f = f; }
VariantImpl::VariantImpl(double d) : type(VAR_DOUBLE) { value.d = d; }
VariantImpl::VariantImpl(const std::string& s, const std::string& e)
- : type(VAR_STRING), encoding(e) { value.v = new std::string(s); }
-VariantImpl::VariantImpl(const Variant::Map& m) : type(VAR_MAP) { value.v = new Variant::Map(m); }
-VariantImpl::VariantImpl(const Variant::List& l) : type(VAR_LIST) { value.v = new Variant::List(l); }
-VariantImpl::VariantImpl(const Uuid& u) : type(VAR_UUID) { value.v = new Uuid(u); }
+ : type(VAR_STRING), encoding(e) { value.string = new std::string(s); }
+VariantImpl::VariantImpl(const Variant::Map& m) : type(VAR_MAP) { value.map = new Variant::Map(m); }
+VariantImpl::VariantImpl(const Variant::List& l) : type(VAR_LIST) { value.list = new Variant::List(l); }
+VariantImpl::VariantImpl(const Uuid& u) : type(VAR_UUID) { value.uuid = new Uuid(u); }
VariantImpl::~VariantImpl() {
switch (type) {
case VAR_STRING:
- delete reinterpret_cast<std::string*>(value.v);
+ delete value.string;
break;
case VAR_MAP:
- delete reinterpret_cast<Variant::Map*>(value.v);
+ delete value.map;
break;
case VAR_LIST:
- delete reinterpret_cast<Variant::List*>(value.v);
+ delete value.list;
break;
case VAR_UUID:
- delete reinterpret_cast<Uuid*>(value.v);
+ delete value.uuid;
break;
default:
break;
@@ -221,7 +217,7 @@ bool VariantImpl::asBool() const
case VAR_INT16: return value.i16;
case VAR_INT32: return value.i32;
case VAR_INT64: return value.i64;
- case VAR_STRING: return toBool(*reinterpret_cast<std::string*>(value.v));
+ case VAR_STRING: return toBool(*value.string);
default: throw InvalidConversion(QPID_MSG("Cannot convert from " << getTypeName(type) << " to " << getTypeName(VAR_BOOL)));
}
}
@@ -500,8 +496,8 @@ std::string VariantImpl::asString() const
case VAR_INT64: return boost::lexical_cast<std::string>(value.i64);
case VAR_DOUBLE: return boost::lexical_cast<std::string>(value.d);
case VAR_FLOAT: return boost::lexical_cast<std::string>(value.f);
- case VAR_STRING: return *reinterpret_cast<std::string*>(value.v);
- case VAR_UUID: return reinterpret_cast<Uuid*>(value.v)->str();
+ case VAR_STRING: return *value.string;
+ case VAR_UUID: return value.uuid->str();
case VAR_LIST: return toString(asList());
case VAR_MAP: return toString(asMap());
default: throw InvalidConversion(QPID_MSG("Cannot convert from " << getTypeName(type) << " to " << getTypeName(VAR_STRING)));
@@ -510,7 +506,7 @@ std::string VariantImpl::asString() const
Uuid VariantImpl::asUuid() const
{
switch(type) {
- case VAR_UUID: return *reinterpret_cast<Uuid*>(value.v);
+ case VAR_UUID: return *value.uuid;
default: throw InvalidConversion(QPID_MSG("Cannot convert from " << getTypeName(type) << " to " << getTypeName(VAR_UUID)));
}
}
@@ -531,10 +527,8 @@ bool VariantImpl::isEqualTo(VariantImpl& other) const
case VAR_INT64: return value.i64 == other.value.i64;
case VAR_DOUBLE: return value.d == other.value.d;
case VAR_FLOAT: return value.f == other.value.f;
- case VAR_STRING: return *reinterpret_cast<std::string*>(value.v)
- == *reinterpret_cast<std::string*>(other.value.v);
- case VAR_UUID: return *reinterpret_cast<Uuid*>(value.v)
- == *reinterpret_cast<Uuid*>(other.value.v);
+ case VAR_STRING: return *value.string == *other.value.string;
+ case VAR_UUID: return *value.uuid == *other.value.uuid;
case VAR_LIST: return equal(asList(), other.asList());
case VAR_MAP: return equal(asMap(), other.asMap());
}
@@ -545,7 +539,7 @@ bool VariantImpl::isEqualTo(VariantImpl& other) const
const Variant::Map& VariantImpl::asMap() const
{
switch(type) {
- case VAR_MAP: return *reinterpret_cast<Variant::Map*>(value.v);
+ case VAR_MAP: return *value.map;
default: throw InvalidConversion(QPID_MSG("Cannot convert from " << getTypeName(type) << " to " << getTypeName(VAR_MAP)));
}
}
@@ -553,7 +547,7 @@ const Variant::Map& VariantImpl::asMap() const
Variant::Map& VariantImpl::asMap()
{
switch(type) {
- case VAR_MAP: return *reinterpret_cast<Variant::Map*>(value.v);
+ case VAR_MAP: return *value.map;
default: throw InvalidConversion(QPID_MSG("Cannot convert from " << getTypeName(type) << " to " << getTypeName(VAR_MAP)));
}
}
@@ -561,7 +555,7 @@ Variant::Map& VariantImpl::asMap()
const Variant::List& VariantImpl::asList() const
{
switch(type) {
- case VAR_LIST: return *reinterpret_cast<Variant::List*>(value.v);
+ case VAR_LIST: return *value.list;
default: throw InvalidConversion(QPID_MSG("Cannot convert from " << getTypeName(type) << " to " << getTypeName(VAR_LIST)));
}
}
@@ -569,7 +563,7 @@ const Variant::List& VariantImpl::asList() const
Variant::List& VariantImpl::asList()
{
switch(type) {
- case VAR_LIST: return *reinterpret_cast<Variant::List*>(value.v);
+ case VAR_LIST: return *value.list;
default: throw InvalidConversion(QPID_MSG("Cannot convert from " << getTypeName(type) << " to " << getTypeName(VAR_LIST)));
}
}
@@ -577,7 +571,7 @@ Variant::List& VariantImpl::asList()
std::string& VariantImpl::getString()
{
switch(type) {
- case VAR_STRING: return *reinterpret_cast<std::string*>(value.v);
+ case VAR_STRING: return *value.string;
default: throw InvalidConversion(QPID_MSG("Variant is not a string; use asString() if conversion is required."));
}
}
@@ -585,7 +579,7 @@ std::string& VariantImpl::getString()
const std::string& VariantImpl::getString() const
{
switch(type) {
- case VAR_STRING: return *reinterpret_cast<std::string*>(value.v);
+ case VAR_STRING: return *value.string;
default: throw InvalidConversion(QPID_MSG("Variant is not a string; use asString() if conversion is required."));
}
}
diff --git a/cpp/src/qpid/xml/XmlExchange.cpp b/cpp/src/qpid/xml/XmlExchange.cpp
index 01770e22a6..3fb11394d0 100644
--- a/cpp/src/qpid/xml/XmlExchange.cpp
+++ b/cpp/src/qpid/xml/XmlExchange.cpp
@@ -101,7 +101,7 @@ XmlBinding::XmlBinding(const std::string& key, const Queue::shared_ptr queue, co
}
-XmlExchange::XmlExchange(const string& _name, Manageable* _parent, Broker* b) : Exchange(_name, _parent, b)
+XmlExchange::XmlExchange(const std::string& _name, Manageable* _parent, Broker* b) : Exchange(_name, _parent, b)
{
if (mgmtExchange != 0)
mgmtExchange->set_type (typeName);
@@ -115,7 +115,7 @@ XmlExchange::XmlExchange(const std::string& _name, bool _durable,
mgmtExchange->set_type (typeName);
}
-bool XmlExchange::bind(Queue::shared_ptr queue, const string& bindingKey, const FieldTable* args)
+bool XmlExchange::bind(Queue::shared_ptr queue, const std::string& bindingKey, const FieldTable* args)
{
// Federation uses bind for unbind and reorigin comands as well as for binds.
@@ -123,9 +123,9 @@ bool XmlExchange::bind(Queue::shared_ptr queue, const string& bindingKey, const
// Both federated and local binds are done in this method. Other
// federated requests are done by calling the relevent methods.
- string fedOp;
- string fedTags;
- string fedOrigin;
+ std::string fedOp;
+ std::string fedTags;
+ std::string fedOrigin;
if (args)
fedOp = args->getAsString(qpidFedOp);
@@ -146,7 +146,7 @@ bool XmlExchange::bind(Queue::shared_ptr queue, const string& bindingKey, const
else if (fedOp.empty() || fedOp == fedOpBind) {
- string queryText = args->getAsString("xquery");
+ std::string queryText = args->getAsString("xquery");
RWlock::ScopedWlock l(lock);
@@ -175,7 +175,7 @@ bool XmlExchange::bind(Queue::shared_ptr queue, const string& bindingKey, const
return true;
}
-bool XmlExchange::unbind(Queue::shared_ptr queue, const string& bindingKey, const FieldTable* args)
+bool XmlExchange::unbind(Queue::shared_ptr queue, const std::string& bindingKey, const FieldTable* args)
{
/*
* When called directly, no qpidFedOrigin argument will be
@@ -184,7 +184,7 @@ bool XmlExchange::unbind(Queue::shared_ptr queue, const string& bindingKey, cons
* This is a bit of a hack - the binding needs the origin, but
* this interface, as originally defined, would not supply one.
*/
- string fedOrigin;
+ std::string fedOrigin;
if (args) fedOrigin = args->getAsString(qpidFedOrigin);
RWlock::ScopedWlock l(lock);
@@ -200,7 +200,7 @@ bool XmlExchange::unbind(Queue::shared_ptr queue, const string& bindingKey, cons
bool XmlExchange::matches(Query& query, Deliverable& msg, const qpid::framing::FieldTable* args, bool parse_message_content)
{
- string msgContent;
+ std::string msgContent;
try {
QPID_LOG(trace, "matches: query is [" << UTF8(query->getQueryText()) << "]");
@@ -285,7 +285,7 @@ bool XmlExchange::matches(Query& query, Deliverable& msg, const qpid::framing::F
void XmlExchange::route(Deliverable& msg)
{
- const string& routingKey = msg.getMessage().getRoutingKey();
+ const std::string& routingKey = msg.getMessage().getRoutingKey();
const FieldTable* args = msg.getMessage().getApplicationHeaders();
PreRoute pr(msg, this);
try {
@@ -309,7 +309,7 @@ void XmlExchange::route(Deliverable& msg)
}
-bool XmlExchange::isBound(Queue::shared_ptr queue, const string* const bindingKey, const FieldTable* const)
+bool XmlExchange::isBound(Queue::shared_ptr queue, const std::string* const bindingKey, const FieldTable* const)
{
RWlock::ScopedRlock l(lock);
if (bindingKey) {
@@ -345,7 +345,7 @@ void XmlExchange::propagateFedOp(const std::string& bindingKey, const std::strin
if (args) {
for (qpid::framing::FieldTable::ValueMap::const_iterator i=args->begin(); i != args->end(); ++i) {
- const string& name(i->first);
+ const std::string& name(i->first);
if (name != qpidFedOp &&
name != qpidFedTags &&
name != qpidFedOrigin) {
@@ -358,7 +358,7 @@ void XmlExchange::propagateFedOp(const std::string& bindingKey, const std::strin
Exchange::propagateFedOp(bindingKey, fedTags, fedOp, fedOrigin, propArgs);
}
-bool XmlExchange::fedUnbind(const string& fedOrigin, const string& fedTags, Queue::shared_ptr queue, const string& bindingKey, const FieldTable* args)
+bool XmlExchange::fedUnbind(const std::string& fedOrigin, const std::string& fedTags, Queue::shared_ptr queue, const std::string& bindingKey, const FieldTable* args)
{
RWlock::ScopedRlock l(lock);
@@ -376,19 +376,19 @@ void XmlExchange::fedReorigin()
RWlock::ScopedRlock l(lock);
for (XmlBindingsMap::iterator i = bindingsMap.begin(); i != bindingsMap.end(); ++i) {
XmlBinding::vector::ConstPtr p = i->second.snapshot();
- if (std::find_if(p->begin(), p->end(), MatchOrigin(string())) != p->end()) {
+ if (std::find_if(p->begin(), p->end(), MatchOrigin(std::string())) != p->end()) {
keys2prop.push_back(i->first);
}
}
} /* lock dropped */
for (std::vector<std::string>::const_iterator key = keys2prop.begin();
key != keys2prop.end(); key++) {
- propagateFedOp( *key, string(), fedOpBind, string());
+ propagateFedOp( *key, std::string(), fedOpBind, std::string());
}
}
-XmlExchange::MatchOrigin::MatchOrigin(const string& _origin) : origin(_origin) {}
+XmlExchange::MatchOrigin::MatchOrigin(const std::string& _origin) : origin(_origin) {}
bool XmlExchange::MatchOrigin::operator()(XmlBinding::shared_ptr b)
{
@@ -396,7 +396,7 @@ bool XmlExchange::MatchOrigin::operator()(XmlBinding::shared_ptr b)
}
-XmlExchange::MatchQueueAndOrigin::MatchQueueAndOrigin(Queue::shared_ptr _queue, const string& _origin) : queue(_queue), origin(_origin) {}
+XmlExchange::MatchQueueAndOrigin::MatchQueueAndOrigin(Queue::shared_ptr _queue, const std::string& _origin) : queue(_queue), origin(_origin) {}
bool XmlExchange::MatchQueueAndOrigin::operator()(XmlBinding::shared_ptr b)
{
diff --git a/cpp/src/qpid/xml/XmlExchange.h b/cpp/src/qpid/xml/XmlExchange.h
index 9ef389d9bf..1d4723f9c4 100644
--- a/cpp/src/qpid/xml/XmlExchange.h
+++ b/cpp/src/qpid/xml/XmlExchange.h
@@ -35,8 +35,6 @@
#include <vector>
#include <string>
-using namespace std;
-
namespace qpid {
namespace broker {
@@ -62,7 +60,7 @@ struct XmlBinding : public Exchange::Binding {
class XmlExchange : public virtual Exchange {
- typedef std::map<string, XmlBinding::vector> XmlBindingsMap;
+ typedef std::map<std::string, XmlBinding::vector> XmlBindingsMap;
XmlBindingsMap bindingsMap;
qpid::sys::RWlock lock;
diff --git a/cpp/src/tests/CMakeLists.txt b/cpp/src/tests/CMakeLists.txt
index 637442e128..29dfe3634f 100644
--- a/cpp/src/tests/CMakeLists.txt
+++ b/cpp/src/tests/CMakeLists.txt
@@ -149,6 +149,7 @@ set(unit_tests_to_build
PollableCondition
Variant
ClientMessage
+ SystemInfo
${xml_tests}
CACHE STRING "Which unit tests to build"
)
diff --git a/cpp/src/tests/ExchangeTest.cpp b/cpp/src/tests/ExchangeTest.cpp
index 2fb284741a..66a16b9178 100644
--- a/cpp/src/tests/ExchangeTest.cpp
+++ b/cpp/src/tests/ExchangeTest.cpp
@@ -33,6 +33,8 @@
#include <iostream>
#include "MessageUtils.h"
+using std::string;
+
using boost::intrusive_ptr;
using namespace qpid::broker;
using namespace qpid::framing;
diff --git a/cpp/src/tests/FieldTable.cpp b/cpp/src/tests/FieldTable.cpp
index c79d110ae4..8aeeb031b3 100644
--- a/cpp/src/tests/FieldTable.cpp
+++ b/cpp/src/tests/FieldTable.cpp
@@ -20,6 +20,7 @@
*/
#include <iostream>
#include <algorithm>
+#include "qpid/sys/alloca.h"
#include "qpid/framing/Array.h"
#include "qpid/framing/FieldTable.h"
#include "qpid/framing/FieldValue.h"
@@ -29,6 +30,8 @@
using namespace qpid::framing;
+using std::string;
+
namespace qpid {
namespace tests {
@@ -73,11 +76,11 @@ QPID_AUTO_TEST_CASE(testAssignment)
FieldTable c;
c = a;
- char* buff = static_cast<char*>(::alloca(c.encodedSize()));
- Buffer wbuffer(buff, c.encodedSize());
+ std::vector<char> buff(c.encodedSize());
+ Buffer wbuffer(&buff[0], c.encodedSize());
wbuffer.put(c);
- Buffer rbuffer(buff, c.encodedSize());
+ Buffer rbuffer(&buff[0], c.encodedSize());
rbuffer.get(d);
BOOST_CHECK_EQUAL(c, d);
BOOST_CHECK(string("CCCC") == c.getAsString("A"));
diff --git a/cpp/src/tests/Makefile.am b/cpp/src/tests/Makefile.am
index 66d2cdd5d5..cdc7429f3b 100644
--- a/cpp/src/tests/Makefile.am
+++ b/cpp/src/tests/Makefile.am
@@ -67,7 +67,7 @@ tmodule_LTLIBRARIES=
TESTS+=unit_test
check_PROGRAMS+=unit_test
-unit_test_LDADD=-lboost_unit_test_framework \
+unit_test_LDADD=-lboost_unit_test_framework -lpthread \
$(lib_messaging) $(lib_broker) $(lib_console) $(lib_qmf2)
unit_test_SOURCES= unit_test.cpp unit_test.h \
@@ -124,7 +124,8 @@ unit_test_SOURCES= unit_test.cpp unit_test.h \
Address.cpp \
ClientMessage.cpp \
Qmf2.cpp \
- BrokerOptions.cpp
+ BrokerOptions.cpp \
+ SystemInfo.cpp
if HAVE_XML
unit_test_SOURCES+= XmlClientSessionTest.cpp
@@ -150,7 +151,7 @@ endif
# Test programs that are installed and therefore built as part of make, not make check
qpidexectest_SCRIPTS += qpid-cpp-benchmark qpid-cluster-benchmark install_env.sh
-EXTRA_DIST += qpid-cpp-benchmark install_env.sh
+EXTRA_DIST += qpid-cpp-benchmark qpid-cluster-benchmark install_env.sh
qpidexectest_PROGRAMS += receiver
receiver_SOURCES = \
@@ -305,7 +306,7 @@ TESTS_ENVIRONMENT = \
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 \
- ha_tests.py run_federation_tests run_federation_sys_tests \
+ run_ha_tests 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
@@ -352,7 +353,8 @@ EXTRA_DIST += \
run_queue_flow_limit_tests \
run_msg_group_tests \
ipv6_test \
- ha_tests.py \
+ run_ha_tests \
+ ha_tests.py \
test_env.ps1.in
check_LTLIBRARIES += libdlclose_noop.la
diff --git a/cpp/src/tests/MessageBuilderTest.cpp b/cpp/src/tests/MessageBuilderTest.cpp
index c3d40ed88a..9adb133d40 100644
--- a/cpp/src/tests/MessageBuilderTest.cpp
+++ b/cpp/src/tests/MessageBuilderTest.cpp
@@ -40,7 +40,7 @@ class MockMessageStore : public NullMessageStore
uint64_t id;
boost::intrusive_ptr<PersistableMessage> expectedMsg;
- string expectedData;
+ std::string expectedData;
std::list<Op> ops;
void checkExpectation(Op actual)
@@ -58,7 +58,7 @@ class MockMessageStore : public NullMessageStore
ops.push_back(STAGE);
}
- void expectAppendContent(PersistableMessage& msg, const string& data)
+ void expectAppendContent(PersistableMessage& msg, const std::string& data)
{
expectedMsg = &msg;
expectedData = data;
@@ -73,7 +73,7 @@ class MockMessageStore : public NullMessageStore
}
void appendContent(const boost::intrusive_ptr<const PersistableMessage>& msg,
- const string& data)
+ const std::string& data)
{
checkExpectation(APPEND);
BOOST_CHECK_EQUAL(boost::static_pointer_cast<const PersistableMessage>(expectedMsg), msg);
diff --git a/cpp/src/tests/MessageTest.cpp b/cpp/src/tests/MessageTest.cpp
index 7d67c92b37..3a3ed061f9 100644
--- a/cpp/src/tests/MessageTest.cpp
+++ b/cpp/src/tests/MessageTest.cpp
@@ -24,7 +24,6 @@
#include "qpid/framing/MessageTransferBody.h"
#include "qpid/framing/FieldValue.h"
#include "qpid/framing/Uuid.h"
-#include "qpid/sys/alloca.h"
#include "unit_test.h"
@@ -33,6 +32,8 @@
using namespace qpid::broker;
using namespace qpid::framing;
+using std::string;
+
namespace qpid {
namespace tests {
@@ -69,11 +70,11 @@ QPID_AUTO_TEST_CASE(testEncodeDecode)
dProps->setDeliveryMode(PERSISTENT);
BOOST_CHECK(msg->isPersistent());
- char* buff = static_cast<char*>(::alloca(msg->encodedSize()));
- Buffer wbuffer(buff, msg->encodedSize());
+ std::vector<char> buff(msg->encodedSize());
+ Buffer wbuffer(&buff[0], msg->encodedSize());
msg->encode(wbuffer);
- Buffer rbuffer(buff, msg->encodedSize());
+ Buffer rbuffer(&buff[0], msg->encodedSize());
msg = new Message();
msg->decodeHeader(rbuffer);
msg->decodeContent(rbuffer);
diff --git a/cpp/src/tests/MessageUtils.h b/cpp/src/tests/MessageUtils.h
index a1b140d484..991e2a2714 100644
--- a/cpp/src/tests/MessageUtils.h
+++ b/cpp/src/tests/MessageUtils.h
@@ -33,7 +33,7 @@ namespace tests {
struct MessageUtils
{
- static boost::intrusive_ptr<Message> createMessage(const string& exchange="", const string& routingKey="",
+ static boost::intrusive_ptr<Message> createMessage(const std::string& exchange="", const std::string& routingKey="",
const bool durable = false, const Uuid& messageId=Uuid(true),
uint64_t contentSize = 0)
{
@@ -53,7 +53,7 @@ struct MessageUtils
return msg;
}
- static void addContent(boost::intrusive_ptr<Message> msg, const string& data)
+ static void addContent(boost::intrusive_ptr<Message> msg, const std::string& data)
{
AMQFrame content((AMQContentBody(data)));
msg->getFrames().append(content);
diff --git a/cpp/src/tests/MessagingSessionTests.cpp b/cpp/src/tests/MessagingSessionTests.cpp
index 968d55fd45..c8ee3aa401 100644
--- a/cpp/src/tests/MessagingSessionTests.cpp
+++ b/cpp/src/tests/MessagingSessionTests.cpp
@@ -1146,6 +1146,24 @@ QPID_AUTO_TEST_CASE(testLargeRoutingKey)
BOOST_CHECK_THROW(fix.session.createReceiver(address), qpid::messaging::MessagingException);
}
+QPID_AUTO_TEST_CASE(testAlternateExchangeInLinkDeclare)
+{
+ MessagingFixture fix;
+ Sender s = fix.session.createSender("amq.direct/key");
+ Receiver r1 = fix.session.createReceiver("amq.direct/key;{link:{x-declare:{alternate-exchange:'amq.fanout'}}}");
+ Receiver r2 = fix.session.createReceiver("amq.fanout");
+
+ for (uint i = 0; i < 10; ++i) {
+ s.send(Message((boost::format("Message_%1%") % (i+1)).str()), true);
+ }
+ r1.close();//orphans all messages in subscription queue, which should then be routed through alternate exchange
+ for (uint i = 0; i < 10; ++i) {
+ Message received;
+ BOOST_CHECK(r2.fetch(received, Duration::SECOND));
+ BOOST_CHECK_EQUAL(received.getContent(), (boost::format("Message_%1%") % (i+1)).str());
+ }
+}
+
QPID_AUTO_TEST_SUITE_END()
}} // namespace qpid::tests
diff --git a/cpp/src/tests/QueueTest.cpp b/cpp/src/tests/QueueTest.cpp
index fb429ca981..3b4f74620f 100644
--- a/cpp/src/tests/QueueTest.cpp
+++ b/cpp/src/tests/QueueTest.cpp
@@ -31,6 +31,8 @@
#include "qpid/broker/QueueRegistry.h"
#include "qpid/broker/NullMessageStore.h"
#include "qpid/broker/ExpiryPolicy.h"
+#include "qpid/framing/DeliveryProperties.h"
+#include "qpid/framing/FieldTable.h"
#include "qpid/framing/MessageTransferBody.h"
#include "qpid/client/QueueOptions.h"
#include "qpid/framing/AMQFrame.h"
@@ -40,8 +42,11 @@
#include "qpid/broker/QueueFlowLimit.h"
#include <iostream>
-#include "boost/format.hpp"
+#include <vector>
+#include <boost/format.hpp>
+#include <boost/lexical_cast.hpp>
+using namespace std;
using boost::intrusive_ptr;
using namespace qpid;
using namespace qpid::broker;
@@ -83,7 +88,7 @@ public:
Message& getMessage() { return *(msg.get()); }
};
-intrusive_ptr<Message> create_message(std::string exchange, std::string routingKey, uint64_t ttl = 0) {
+intrusive_ptr<Message> createMessage(std::string exchange, std::string routingKey, uint64_t ttl = 0) {
intrusive_ptr<Message> msg(new Message());
AMQFrame method((MessageTransferBody(ProtocolVersion(), exchange, 0, 0)));
AMQFrame header((AMQHeaderBody()));
@@ -94,6 +99,16 @@ intrusive_ptr<Message> create_message(std::string exchange, std::string routingK
return msg;
}
+intrusive_ptr<Message> contentMessage(string content) {
+ intrusive_ptr<Message> m(MessageUtils::createMessage());
+ MessageUtils::addContent(m, content);
+ return m;
+}
+
+string getContent(intrusive_ptr<Message> m) {
+ return m->getFrames().getContent();
+}
+
QPID_AUTO_TEST_SUITE(QueueTestSuite)
QPID_AUTO_TEST_CASE(testAsyncMessage) {
@@ -105,7 +120,7 @@ QPID_AUTO_TEST_CASE(testAsyncMessage) {
//Test basic delivery:
- intrusive_ptr<Message> msg1 = create_message("e", "A");
+ intrusive_ptr<Message> msg1 = createMessage("e", "A");
msg1->enqueueAsync(queue, (MessageStore*)0);//this is done on enqueue which is not called from process
queue->process(msg1);
sleep(2);
@@ -120,7 +135,7 @@ QPID_AUTO_TEST_CASE(testAsyncMessage) {
QPID_AUTO_TEST_CASE(testAsyncMessageCount){
Queue::shared_ptr queue(new Queue("my_test_queue", true));
- intrusive_ptr<Message> msg1 = create_message("e", "A");
+ intrusive_ptr<Message> msg1 = createMessage("e", "A");
msg1->enqueueAsync(queue, (MessageStore*)0);//this is done on enqueue which is not called from process
queue->process(msg1);
@@ -145,9 +160,9 @@ QPID_AUTO_TEST_CASE(testConsumers){
BOOST_CHECK_EQUAL(uint32_t(2), queue->getConsumerCount());
//Test basic delivery:
- intrusive_ptr<Message> msg1 = create_message("e", "A");
- intrusive_ptr<Message> msg2 = create_message("e", "B");
- intrusive_ptr<Message> msg3 = create_message("e", "C");
+ intrusive_ptr<Message> msg1 = createMessage("e", "A");
+ intrusive_ptr<Message> msg2 = createMessage("e", "B");
+ intrusive_ptr<Message> msg3 = createMessage("e", "C");
queue->deliver(msg1);
BOOST_CHECK(queue->dispatch(c1));
@@ -191,9 +206,9 @@ QPID_AUTO_TEST_CASE(testRegistry){
QPID_AUTO_TEST_CASE(testDequeue){
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");
+ intrusive_ptr<Message> msg1 = createMessage("e", "A");
+ intrusive_ptr<Message> msg2 = createMessage("e", "B");
+ intrusive_ptr<Message> msg3 = createMessage("e", "C");
intrusive_ptr<Message> received;
queue->deliver(msg1);
@@ -265,9 +280,9 @@ QPID_AUTO_TEST_CASE(testPersistLastNodeStanding){
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");
+ intrusive_ptr<Message> msg1 = createMessage("e", "A");
+ intrusive_ptr<Message> msg2 = createMessage("e", "B");
+ intrusive_ptr<Message> msg3 = createMessage("e", "C");
//enqueue 2 messages
queue->deliver(msg1);
@@ -291,9 +306,9 @@ QPID_AUTO_TEST_CASE(testSeek){
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");
+ intrusive_ptr<Message> msg1 = createMessage("e", "A");
+ intrusive_ptr<Message> msg2 = createMessage("e", "B");
+ intrusive_ptr<Message> msg3 = createMessage("e", "C");
//enqueue 2 messages
queue->deliver(msg1);
@@ -317,9 +332,9 @@ QPID_AUTO_TEST_CASE(testSearch){
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");
+ intrusive_ptr<Message> msg1 = createMessage("e", "A");
+ intrusive_ptr<Message> msg2 = createMessage("e", "B");
+ intrusive_ptr<Message> msg3 = createMessage("e", "C");
//enqueue 2 messages
queue->deliver(msg1);
@@ -431,10 +446,10 @@ QPID_AUTO_TEST_CASE(testLVQOrdering){
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");
- intrusive_ptr<Message> msg4 = create_message("e", "D");
+ intrusive_ptr<Message> msg1 = createMessage("e", "A");
+ intrusive_ptr<Message> msg2 = createMessage("e", "B");
+ intrusive_ptr<Message> msg3 = createMessage("e", "C");
+ intrusive_ptr<Message> msg4 = createMessage("e", "D");
intrusive_ptr<Message> received;
//set deliever match for LVQ a,b,c,a
@@ -466,9 +481,9 @@ QPID_AUTO_TEST_CASE(testLVQOrdering){
received = queue->get().payload;
BOOST_CHECK_EQUAL(msg3.get(), received.get());
- intrusive_ptr<Message> msg5 = create_message("e", "A");
- intrusive_ptr<Message> msg6 = create_message("e", "B");
- intrusive_ptr<Message> msg7 = create_message("e", "C");
+ intrusive_ptr<Message> msg5 = createMessage("e", "A");
+ intrusive_ptr<Message> msg6 = createMessage("e", "B");
+ intrusive_ptr<Message> msg7 = createMessage("e", "C");
msg5->insertCustomProperty(key,"a");
msg6->insertCustomProperty(key,"b");
msg7->insertCustomProperty(key,"c");
@@ -498,8 +513,8 @@ QPID_AUTO_TEST_CASE(testLVQEmptyKey){
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> msg1 = createMessage("e", "A");
+ intrusive_ptr<Message> msg2 = createMessage("e", "B");
string key;
args.getLVQKey(key);
@@ -524,12 +539,12 @@ QPID_AUTO_TEST_CASE(testLVQAcquire){
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");
- intrusive_ptr<Message> msg4 = create_message("e", "D");
- intrusive_ptr<Message> msg5 = create_message("e", "F");
- intrusive_ptr<Message> msg6 = create_message("e", "G");
+ intrusive_ptr<Message> msg1 = createMessage("e", "A");
+ intrusive_ptr<Message> msg2 = createMessage("e", "B");
+ intrusive_ptr<Message> msg3 = createMessage("e", "C");
+ intrusive_ptr<Message> msg4 = createMessage("e", "D");
+ intrusive_ptr<Message> msg5 = createMessage("e", "F");
+ intrusive_ptr<Message> msg6 = createMessage("e", "G");
//set deliever match for LVQ a,b,c,a
@@ -601,8 +616,8 @@ QPID_AUTO_TEST_CASE(testLVQMultiQueue){
queue1->configure(args);
queue2->configure(args);
- intrusive_ptr<Message> msg1 = create_message("e", "A");
- intrusive_ptr<Message> msg2 = create_message("e", "A");
+ intrusive_ptr<Message> msg1 = createMessage("e", "A");
+ intrusive_ptr<Message> msg2 = createMessage("e", "A");
string key;
args.getLVQKey(key);
@@ -645,8 +660,8 @@ QPID_AUTO_TEST_CASE(testLVQRecover){
intrusive_ptr<Message> received;
queue1->create(args);
- intrusive_ptr<Message> msg1 = create_message("e", "A");
- intrusive_ptr<Message> msg2 = create_message("e", "A");
+ intrusive_ptr<Message> msg1 = createMessage("e", "A");
+ intrusive_ptr<Message> msg2 = createMessage("e", "A");
// 2
string key;
args.getLVQKey(key);
@@ -673,7 +688,7 @@ 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);
+ intrusive_ptr<Message> m = createMessage("exchange", "key", i % 2 ? oddTtl : evenTtl);
m->computeExpiration(new broker::ExpiryPolicy);
queue.deliver(m);
}
@@ -736,7 +751,7 @@ QPID_AUTO_TEST_CASE(testGroupsMultiConsumer) {
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");
+ intrusive_ptr<Message> msg = createMessage("e", "A");
msg->insertCustomProperty("GROUP-ID", groups[i]);
msg->insertCustomProperty("MY-ID", i);
queue->deliver(msg);
@@ -883,7 +898,7 @@ QPID_AUTO_TEST_CASE(testGroupsMultiConsumer) {
// Queue = a-2,
// Owners= ^C3,
- intrusive_ptr<Message> msg = create_message("e", "A");
+ intrusive_ptr<Message> msg = createMessage("e", "A");
msg->insertCustomProperty("GROUP-ID", "a");
msg->insertCustomProperty("MY-ID", 9);
queue->deliver(msg);
@@ -894,7 +909,7 @@ QPID_AUTO_TEST_CASE(testGroupsMultiConsumer) {
gotOne = queue->dispatch(c2);
BOOST_CHECK( !gotOne );
- msg = create_message("e", "A");
+ msg = createMessage("e", "A");
msg->insertCustomProperty("GROUP-ID", "b");
msg->insertCustomProperty("MY-ID", 10);
queue->deliver(msg);
@@ -925,7 +940,7 @@ QPID_AUTO_TEST_CASE(testGroupsMultiConsumerDefaults) {
queue->configure(args);
for (int i = 0; i < 3; ++i) {
- intrusive_ptr<Message> msg = create_message("e", "A");
+ intrusive_ptr<Message> msg = createMessage("e", "A");
// no "GROUP-ID" header
msg->insertCustomProperty("MY-ID", i);
queue->deliver(msg);
@@ -988,7 +1003,7 @@ QPID_AUTO_TEST_CASE(testMultiQueueLastNode){
Queue::shared_ptr queue2(new Queue("queue2", true, &testStore ));
queue2->create(args);
- intrusive_ptr<Message> msg1 = create_message("e", "A");
+ intrusive_ptr<Message> msg1 = createMessage("e", "A");
queue1->deliver(msg1);
queue2->deliver(msg1);
@@ -1004,7 +1019,7 @@ QPID_AUTO_TEST_CASE(testMultiQueueLastNode){
queue2->setLastNodeFailure();
BOOST_CHECK_EQUAL(testStore.enqCnt, 2u);
- intrusive_ptr<Message> msg2 = create_message("e", "B");
+ intrusive_ptr<Message> msg2 = createMessage("e", "B");
queue1->deliver(msg2);
queue2->deliver(msg2);
@@ -1019,7 +1034,7 @@ QPID_AUTO_TEST_CASE(testMultiQueueLastNode){
queue1->clearLastNodeFailure();
queue2->clearLastNodeFailure();
- intrusive_ptr<Message> msg3 = create_message("e", "B");
+ intrusive_ptr<Message> msg3 = createMessage("e", "B");
queue1->deliver(msg3);
queue2->deliver(msg3);
BOOST_CHECK_EQUAL(testStore.enqCnt, 4u);
@@ -1033,8 +1048,8 @@ QPID_AUTO_TEST_CASE(testMultiQueueLastNode){
* internal details not part of the queue abstraction.
// check requeue 1
- intrusive_ptr<Message> msg4 = create_message("e", "C");
- intrusive_ptr<Message> msg5 = create_message("e", "D");
+ intrusive_ptr<Message> msg4 = createMessage("e", "C");
+ intrusive_ptr<Message> msg5 = createMessage("e", "D");
framing::SequenceNumber sequence(1);
QueuedMessage qmsg1(queue1.get(), msg4, sequence);
@@ -1081,8 +1096,8 @@ not requeued to the store.
queue1->create(args);
// check requeue 1
- intrusive_ptr<Message> msg1 = create_message("e", "C");
- intrusive_ptr<Message> msg2 = create_message("e", "D");
+ intrusive_ptr<Message> msg1 = createMessage("e", "C");
+ intrusive_ptr<Message> msg2 = createMessage("e", "D");
queue1->recover(msg1);
@@ -1114,7 +1129,7 @@ simulate store exception going into last node standing
queue1->configure(args);
// check requeue 1
- intrusive_ptr<Message> msg1 = create_message("e", "C");
+ intrusive_ptr<Message> msg1 = createMessage("e", "C");
queue1->deliver(msg1);
testStore.createError();
@@ -1401,6 +1416,133 @@ QPID_AUTO_TEST_CASE(testFlowToDiskBlocking){
BOOST_CHECK_EQUAL(5u, tq9->getMessageCount());
}
+QPID_AUTO_TEST_CASE(testSetPositionFifo) {
+ Queue::shared_ptr q(new Queue("my-queue", true));
+ BOOST_CHECK_EQUAL(q->getPosition(), SequenceNumber(0));
+ for (int i = 0; i < 10; ++i)
+ q->deliver(contentMessage(boost::lexical_cast<string>(i+1)));
+
+ // Verify the front of the queue
+ TestConsumer::shared_ptr c(new TestConsumer("test", false)); // Don't acquire
+ BOOST_CHECK(q->dispatch(c));
+ BOOST_CHECK_EQUAL(1u, c->last.position); // Numbered from 1
+ BOOST_CHECK_EQUAL("1", getContent(c->last.payload));
+ // Verify the back of the queue
+ QueuedMessage qm;
+ BOOST_CHECK_EQUAL(10u, q->getPosition());
+ BOOST_CHECK(q->find(q->getPosition(), qm)); // Back of the queue
+ BOOST_CHECK_EQUAL("10", getContent(qm.payload));
+ BOOST_CHECK_EQUAL(10u, q->getMessageCount());
+
+ // Using setPosition to introduce a gap in sequence numbers.
+ q->setPosition(15);
+ BOOST_CHECK_EQUAL(10u, q->getMessageCount());
+ BOOST_CHECK_EQUAL(15u, q->getPosition());
+ BOOST_CHECK(q->find(10, qm)); // Back of the queue
+ BOOST_CHECK_EQUAL("10", getContent(qm.payload));
+ q->deliver(contentMessage("16"));
+ c->setPosition(9);
+ BOOST_CHECK(q->dispatch(c));
+ BOOST_CHECK_EQUAL(10u, c->last.position);
+ BOOST_CHECK_EQUAL("10", getContent(c->last.payload));
+ BOOST_CHECK(q->dispatch(c));
+ BOOST_CHECK_EQUAL(16u, c->last.position);
+ BOOST_CHECK_EQUAL("16", getContent(c->last.payload));
+
+ // Using setPosition to trunkcate the queue
+ q->setPosition(5);
+ BOOST_CHECK_EQUAL(5u, q->getMessageCount());
+ q->deliver(contentMessage("6a"));
+ c->setPosition(4);
+ BOOST_CHECK(q->dispatch(c));
+ BOOST_CHECK_EQUAL(5u, c->last.position);
+ BOOST_CHECK_EQUAL("5", getContent(c->last.payload));
+ BOOST_CHECK(q->dispatch(c));
+ BOOST_CHECK_EQUAL(6u, c->last.position);
+ BOOST_CHECK_EQUAL("6a", getContent(c->last.payload));
+ BOOST_CHECK(!q->dispatch(c)); // No more messages.
+}
+
+QPID_AUTO_TEST_CASE(testSetPositionLvq) {
+ Queue::shared_ptr q(new Queue("my-queue", true));
+ string key="key";
+ framing::FieldTable args;
+ args.setString("qpid.last_value_queue_key", "key");
+ q->configure(args);
+
+ const char* values[] = { "a", "b", "c", "a", "b", "c" };
+ for (size_t i = 0; i < sizeof(values)/sizeof(values[0]); ++i) {
+ intrusive_ptr<Message> m = contentMessage(boost::lexical_cast<string>(i+1));
+ m->insertCustomProperty(key, values[i]);
+ q->deliver(m);
+ }
+ BOOST_CHECK_EQUAL(3u, q->getMessageCount());
+ // Verify the front of the queue
+ TestConsumer::shared_ptr c(new TestConsumer("test", false)); // Don't acquire
+ BOOST_CHECK(q->dispatch(c));
+ BOOST_CHECK_EQUAL(4u, c->last.position); // Numbered from 1
+ BOOST_CHECK_EQUAL("4", getContent(c->last.payload));
+ // Verify the back of the queue
+ QueuedMessage qm;
+ BOOST_CHECK_EQUAL(6u, q->getPosition());
+ BOOST_CHECK(q->find(q->getPosition(), qm)); // Back of the queue
+ BOOST_CHECK_EQUAL("6", getContent(qm.payload));
+
+ q->setPosition(5);
+ c->setPosition(4);
+ BOOST_CHECK(q->dispatch(c));
+ BOOST_CHECK_EQUAL(5u, c->last.position); // Numbered from 1
+ BOOST_CHECK(!q->dispatch(c));
+}
+
+QPID_AUTO_TEST_CASE(testSetPositionPriority) {
+ Queue::shared_ptr q(new Queue("my-queue", true));
+ framing::FieldTable args;
+ args.setInt("qpid.priorities", 10);
+ q->configure(args);
+
+ const int priorities[] = { 1, 2, 3, 2, 1, 3 };
+ for (size_t i = 0; i < sizeof(priorities)/sizeof(priorities[0]); ++i) {
+ intrusive_ptr<Message> m = contentMessage(boost::lexical_cast<string>(i+1));
+ m->getFrames().getHeaders()->get<DeliveryProperties>(true)
+ ->setPriority(priorities[i]);
+ q->deliver(m);
+ }
+
+ // Truncation removes messages in fifo order, not priority order.
+ q->setPosition(3);
+ TestConsumer::shared_ptr c(new TestConsumer("test", false)); // Browse in FIFO order
+ BOOST_CHECK(q->dispatch(c));
+ BOOST_CHECK_EQUAL(1u, c->last.position);
+ BOOST_CHECK(q->dispatch(c));
+ BOOST_CHECK_EQUAL(2u, c->last.position);
+ BOOST_CHECK(q->dispatch(c));
+ BOOST_CHECK_EQUAL(3u, c->last.position);
+ BOOST_CHECK(!q->dispatch(c));
+
+ intrusive_ptr<Message> m = contentMessage("4a");
+ m->getFrames().getHeaders()->get<DeliveryProperties>(true)
+ ->setPriority(4);
+ q->deliver(m);
+ BOOST_CHECK(q->dispatch(c));
+ BOOST_CHECK_EQUAL(4u, c->last.position);
+ BOOST_CHECK_EQUAL("4a", getContent(c->last.payload));
+
+ // But consumers see priority order
+ c.reset(new TestConsumer("test", true));
+ BOOST_CHECK(q->dispatch(c));
+ BOOST_CHECK_EQUAL(4u, c->last.position);
+ BOOST_CHECK_EQUAL("4a", getContent(c->last.payload));
+ BOOST_CHECK(q->dispatch(c));
+ BOOST_CHECK_EQUAL(3u, c->last.position);
+ BOOST_CHECK_EQUAL("3", getContent(c->last.payload));
+ BOOST_CHECK(q->dispatch(c));
+ BOOST_CHECK_EQUAL(2u, c->last.position);
+ BOOST_CHECK_EQUAL("2", getContent(c->last.payload));
+ BOOST_CHECK(q->dispatch(c));
+ BOOST_CHECK_EQUAL(1u, c->last.position);
+ BOOST_CHECK_EQUAL("1", getContent(c->last.payload));
+}
QPID_AUTO_TEST_SUITE_END()
diff --git a/cpp/src/tests/RangeSet.cpp b/cpp/src/tests/RangeSet.cpp
index db3a964086..285f432bf7 100644
--- a/cpp/src/tests/RangeSet.cpp
+++ b/cpp/src/tests/RangeSet.cpp
@@ -29,63 +29,71 @@ namespace tests {
QPID_AUTO_TEST_SUITE(RangeSetTestSuite)
-typedef qpid::Range<int> TestRange;
-typedef qpid::RangeSet<int> TestRangeSet;
+typedef qpid::Range<int> TR; // Test Range
+typedef RangeSet<int> TRSet;
QPID_AUTO_TEST_CASE(testEmptyRange) {
- TestRange r;
+ TR r;
+ BOOST_CHECK_EQUAL(r, TR(0,0));
BOOST_CHECK(r.empty());
BOOST_CHECK(!r.contains(0));
- // BOOST_CHECK(r.contiguous(0));
}
QPID_AUTO_TEST_CASE(testRangeSetAddPoint) {
- TestRangeSet r;
+ TRSet r;
BOOST_CHECK(r.empty());
r += 3;
BOOST_CHECK_MESSAGE(r.contains(3), r);
- BOOST_CHECK_MESSAGE(r.contains(TestRange(3,4)), r);
+ BOOST_CHECK_MESSAGE(r.contains(TR(3,4)), r);
BOOST_CHECK(!r.empty());
r += 5;
BOOST_CHECK_MESSAGE(r.contains(5), r);
- BOOST_CHECK_MESSAGE(r.contains(TestRange(5,6)), r);
- BOOST_CHECK_MESSAGE(!r.contains(TestRange(3,6)), r);
+ BOOST_CHECK_MESSAGE(r.contains(TR(5,6)), r);
+ BOOST_CHECK_MESSAGE(!r.contains(TR(3,6)), r);
r += 4;
- BOOST_CHECK_MESSAGE(r.contains(TestRange(3,6)), r);
+ BOOST_CHECK_MESSAGE(r.contains(TR(3,6)), r);
}
QPID_AUTO_TEST_CASE(testRangeSetAddRange) {
- TestRangeSet r;
- r += TestRange(0,3);
- BOOST_CHECK(r.contains(TestRange(0,3)));
- r += TestRange(4,6);
- BOOST_CHECK_MESSAGE(r.contains(TestRange(4,6)), r);
+ TRSet r;
+ r += TR(0,3);
+ BOOST_CHECK(r.contains(TR(0,3)));
+ BOOST_CHECK(r.contiguous());
+ r += TR(4,6);
+ BOOST_CHECK(!r.contiguous());
+ BOOST_CHECK_MESSAGE(r.contains(TR(4,6)), r);
r += 3;
- BOOST_CHECK_MESSAGE(r.contains(TestRange(0,6)), r);
+ BOOST_CHECK_MESSAGE(r.contains(TR(0,6)), r);
BOOST_CHECK(r.front() == 0);
BOOST_CHECK(r.back() == 6);
+
+ // Merging additions
+ r = TRSet(0,3)+TR(5,6);
+ TRSet e(0,6);
+ BOOST_CHECK_EQUAL(r + TR(3,5), e);
+ BOOST_CHECK(e.contiguous());
+ r = TRSet(0,5)+TR(10,15)+TR(20,25)+TR(30,35)+TR(40,45);
+ BOOST_CHECK_EQUAL(r + TR(11,37), TRSet(0,5)+TR(11,37)+TR(40,45));
}
QPID_AUTO_TEST_CASE(testRangeSetAddSet) {
- TestRangeSet r;
- TestRangeSet s = TestRangeSet(0,3)+TestRange(5,10);
+ TRSet r;
+ TRSet s = TRSet(0,3)+TR(5,10);
r += s;
BOOST_CHECK_EQUAL(r,s);
- r += TestRangeSet(3,5) + TestRange(7,12) + 15;
- BOOST_CHECK_EQUAL(r, TestRangeSet(0,12) + 15);
+ r += TRSet(3,5) + TR(7,12) + 15;
+ BOOST_CHECK_EQUAL(r, TRSet(0,12) + 15);
r.clear();
BOOST_CHECK(r.empty());
- r += TestRange::makeClosed(6,10);
- BOOST_CHECK_EQUAL(r, TestRangeSet(6,11));
- r += TestRangeSet(2,6)+8;
- BOOST_CHECK_EQUAL(r, TestRangeSet(2,11));
+ r += TR::makeClosed(6,10);
+ BOOST_CHECK_EQUAL(r, TRSet(6,11));
+ r += TRSet(2,6)+8;
+ BOOST_CHECK_EQUAL(r, TRSet(2,11));
}
QPID_AUTO_TEST_CASE(testRangeSetIterate) {
- TestRangeSet r;
- (((r += 1) += 10) += TestRange(4,7)) += 2;
- BOOST_MESSAGE(r);
+ TRSet r = TRSet(1,3)+TR(4,7)+TR(10,11);
std::vector<int> actual;
std::copy(r.begin(), r.end(), std::back_inserter(actual));
std::vector<int> expect = boost::assign::list_of(1)(2)(4)(5)(6)(10);
@@ -94,51 +102,51 @@ QPID_AUTO_TEST_CASE(testRangeSetIterate) {
QPID_AUTO_TEST_CASE(testRangeSetRemove) {
// points
- BOOST_CHECK_EQUAL(TestRangeSet(0,5)-3, TestRangeSet(0,3)+TestRange(4,5));
- BOOST_CHECK_EQUAL(TestRangeSet(1,5)-5, TestRangeSet(1,5));
- BOOST_CHECK_EQUAL(TestRangeSet(1,5)-0, TestRangeSet(1,5));
+ BOOST_CHECK_EQUAL(TRSet(0,5)-3, TRSet(0,3)+TR(4,5));
+ BOOST_CHECK_EQUAL(TRSet(1,5)-5, TRSet(1,5));
+ BOOST_CHECK_EQUAL(TRSet(1,5)-0, TRSet(1,5));
- TestRangeSet r(TestRangeSet(0,5)+TestRange(10,15)+TestRange(20,25));
+ TRSet r(TRSet(0,5)+TR(10,15)+TR(20,25));
- // TestRanges
- BOOST_CHECK_EQUAL(r-TestRange(0,5), TestRangeSet(10,15)+TestRange(20,25));
- BOOST_CHECK_EQUAL(r-TestRange(10,15), TestRangeSet(0,5)+TestRange(20,25));
- BOOST_CHECK_EQUAL(r-TestRange(20,25), TestRangeSet(0,5)+TestRange(10,15));
+ // TRs
+ BOOST_CHECK_EQUAL(r-TR(0,5), TRSet(10,15)+TR(20,25));
+ BOOST_CHECK_EQUAL(r-TR(10,15), TRSet(0,5)+TR(20,25));
+ BOOST_CHECK_EQUAL(r-TR(20,25), TRSet(0,5)+TR(10,15));
- BOOST_CHECK_EQUAL(r-TestRange(-5, 30), TestRangeSet());
+ BOOST_CHECK_EQUAL(r-TR(-5, 30), TRSet());
- BOOST_CHECK_EQUAL(r-TestRange(-5, 7), TestRangeSet(10,15)+TestRange(20,25));
- BOOST_CHECK_EQUAL(r-TestRange(8,19), TestRangeSet(0,5)+TestRange(20,25));
- BOOST_CHECK_EQUAL(r-TestRange(17,30), TestRangeSet(0,5)+TestRange(10,15));
- BOOST_CHECK_EQUAL(r-TestRange(17,30), TestRangeSet(0,5)+TestRange(10,15));
+ BOOST_CHECK_EQUAL(r-TR(-5, 7), TRSet(10,15)+TR(20,25));
+ BOOST_CHECK_EQUAL(r-TR(8,19), TRSet(0,5)+TR(20,25));
+ BOOST_CHECK_EQUAL(r-TR(17,30), TRSet(0,5)+TR(10,15));
- BOOST_CHECK_EQUAL(r-TestRange(-5, 5), TestRangeSet(10,15)+TestRange(20,25));
- BOOST_CHECK_EQUAL(r-TestRange(10,19), TestRangeSet(0,5)+TestRange(20,25));
- BOOST_CHECK_EQUAL(r-TestRange(18,25), TestRangeSet(0,5)+TestRange(10,15));
- BOOST_CHECK_EQUAL(r-TestRange(23,25), TestRangeSet(0,5)+TestRange(10,15)+TestRange(20,23));
+ BOOST_CHECK_EQUAL(r-TR(-5, 5), TRSet(10,15)+TR(20,25));
+ BOOST_CHECK_EQUAL(r-TR(10,19), TRSet(0,5)+TR(20,25));
+ BOOST_CHECK_EQUAL(r-TR(18,25), TRSet(0,5)+TR(10,15));
+ BOOST_CHECK_EQUAL(r-TR(23,25), TRSet(0,5)+TR(10,15)+TR(20,23));
- BOOST_CHECK_EQUAL(r-TestRange(-3, 3), TestRangeSet(3,5)+TestRange(10,15)+TestRange(20,25));
- BOOST_CHECK_EQUAL(r-TestRange(3, 7), TestRangeSet(0,2)+TestRange(10,15)+TestRange(20,25));
- BOOST_CHECK_EQUAL(r-TestRange(3, 12), TestRangeSet(0,3)+TestRange(12,15)+TestRange(20,25));
- BOOST_CHECK_EQUAL(r-TestRange(3, 22), TestRangeSet(12,15)+TestRange(22,25));
- BOOST_CHECK_EQUAL(r-TestRange(12, 22), TestRangeSet(0,5)+TestRange(10,11)+TestRange(22,25));
+ BOOST_CHECK_EQUAL(r-TR(-3, 3), TRSet(3,5)+TR(10,15)+TR(20,25));
+ BOOST_CHECK_EQUAL(r-TR(3, 7), TRSet(0,2)+TR(10,15)+TR(20,25));
+ BOOST_CHECK_EQUAL(r-TR(3, 12), TRSet(0,3)+TR(12,15)+TR(20,25));
+ BOOST_CHECK_EQUAL(r-TR(3, 22), TRSet(12,15)+TR(22,25));
+ BOOST_CHECK_EQUAL(r-TR(12, 22), TRSet(0,5)+TR(10,11)+TR(22,25));
// Sets
- BOOST_CHECK_EQUAL(r-(TestRangeSet(-1,6)+TestRange(11,14)+TestRange(23,25)),
- TestRangeSet(10,11)+TestRange(14,15)+TestRange(20,23));
-}
-
-QPID_AUTO_TEST_CASE(testRangeContaining) {
- TestRangeSet r;
- (((r += 1) += TestRange(3,5)) += 7);
- BOOST_CHECK_EQUAL(r.rangeContaining(0), TestRange(0,0));
- BOOST_CHECK_EQUAL(r.rangeContaining(1), TestRange(1,2));
- BOOST_CHECK_EQUAL(r.rangeContaining(2), TestRange(2,2));
- BOOST_CHECK_EQUAL(r.rangeContaining(3), TestRange(3,5));
- BOOST_CHECK_EQUAL(r.rangeContaining(4), TestRange(3,5));
- BOOST_CHECK_EQUAL(r.rangeContaining(5), TestRange(5,5));
- BOOST_CHECK_EQUAL(r.rangeContaining(6), TestRange(6,6));
- BOOST_CHECK_EQUAL(r.rangeContaining(7), TestRange(7,8));
+ BOOST_CHECK_EQUAL(r-(TRSet(-1,6)+TR(11,14)+TR(23,25)),
+ TRSet(10,11)+TR(14,15)+TR(20,23));
+ // Split the ranges
+ BOOST_CHECK_EQUAL(r-(TRSet(2,3)+TR(11,13)+TR(21,23)),
+ TRSet(0,2)+TR(4,5)+
+ TR(10,11)+TR(14,15)+
+ TR(20,21)+TR(23,25));
+ // Truncate the ranges
+ BOOST_CHECK_EQUAL(r-(TRSet(0,3)+TR(13,15)+TR(19,23)),
+ TRSet(3,5)+TR(10,13)+TR(20,23));
+ // Remove multiple ranges with truncation
+ BOOST_CHECK_EQUAL(r-(TRSet(3,23)), TRSet(0,3)+TR(23,25));
+ // Remove multiple ranges in middle
+ TRSet r2 = TRSet(0,5)+TR(10,15)+TR(20,25)+TR(30,35);
+ BOOST_CHECK_EQUAL(r2-TRSet(11,24),
+ TRSet(0,5)+TR(10,11)+TR(24,25)+TR(30,35));
}
QPID_AUTO_TEST_SUITE_END()
diff --git a/cpp/src/tests/ReplicationTest.cpp b/cpp/src/tests/ReplicationTest.cpp
index 1219a6b59e..055f06579f 100644
--- a/cpp/src/tests/ReplicationTest.cpp
+++ b/cpp/src/tests/ReplicationTest.cpp
@@ -62,7 +62,7 @@ qpid::sys::Shlib plugin(getLibPath("REPLICATING_LISTENER_LIB", default_shlib));
qpid::broker::Broker::Options getBrokerOpts(const std::vector<std::string>& args)
{
std::vector<const char*> argv(args.size());
- transform(args.begin(), args.end(), argv.begin(), boost::bind(&string::c_str, _1));
+ transform(args.begin(), args.end(), argv.begin(), boost::bind(&std::string::c_str, _1));
qpid::broker::Broker::Options opts;
qpid::Plugin::addOptions(opts);
@@ -72,7 +72,7 @@ qpid::broker::Broker::Options getBrokerOpts(const std::vector<std::string>& args
QPID_AUTO_TEST_CASE(testReplicationExchange)
{
- qpid::broker::Broker::Options brokerOpts(getBrokerOpts(list_of<string>("qpidd")
+ qpid::broker::Broker::Options brokerOpts(getBrokerOpts(list_of<std::string>("qpidd")
("--replication-exchange-name=qpid.replication")));
SessionFixture f(brokerOpts);
diff --git a/cpp/src/tests/SystemInfo.cpp b/cpp/src/tests/SystemInfo.cpp
new file mode 100644
index 0000000000..12d8d3dba8
--- /dev/null
+++ b/cpp/src/tests/SystemInfo.cpp
@@ -0,0 +1,52 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+
+#include "unit_test.h"
+#include "test_tools.h"
+#include "qpid/sys/SystemInfo.h"
+#include <boost/assign.hpp>
+
+using namespace std;
+using namespace qpid::sys;
+using namespace boost::assign;
+
+namespace qpid {
+namespace tests {
+
+QPID_AUTO_TEST_SUITE(SystemInfoTestSuite)
+
+QPID_AUTO_TEST_CASE(TestIsLocalHost) {
+ // Test that local hostname and addresses are considered local
+ Address a;
+ BOOST_ASSERT(SystemInfo::getLocalHostname(a));
+ BOOST_ASSERT(SystemInfo::isLocalHost(a.host));
+ std::vector<Address> addrs;
+ SystemInfo::getLocalIpAddresses(0, addrs);
+ for (std::vector<Address>::iterator i = addrs.begin(); i != addrs.end(); ++i)
+ BOOST_ASSERT(SystemInfo::isLocalHost(i->host));
+ // Check some non-local addresses
+ BOOST_ASSERT(!SystemInfo::isLocalHost("123.4.5.6"));
+ BOOST_ASSERT(!SystemInfo::isLocalHost("nosuchhost"));
+ BOOST_ASSERT(SystemInfo::isLocalHost("127.0.0.1"));
+ BOOST_ASSERT(SystemInfo::isLocalHost("::1"));
+}
+
+QPID_AUTO_TEST_SUITE_END()
+
+}} // namespace qpid::tests
diff --git a/cpp/src/tests/TestMessageStore.h b/cpp/src/tests/TestMessageStore.h
index 20e0b755b2..0b63bc9c15 100644
--- a/cpp/src/tests/TestMessageStore.h
+++ b/cpp/src/tests/TestMessageStore.h
@@ -31,7 +31,7 @@ using namespace qpid::framing;
namespace qpid {
namespace tests {
-typedef std::pair<string, boost::intrusive_ptr<PersistableMessage> > msg_queue_pair;
+typedef std::pair<std::string, boost::intrusive_ptr<PersistableMessage> > msg_queue_pair;
class TestMessageStore : public NullMessageStore
{
diff --git a/cpp/src/tests/TimerTest.cpp b/cpp/src/tests/TimerTest.cpp
index 6a0a196f4e..fc5004dcb0 100644
--- a/cpp/src/tests/TimerTest.cpp
+++ b/cpp/src/tests/TimerTest.cpp
@@ -81,6 +81,8 @@ class TestTask : public TimerTask
uint64_t difference = _abs64(expected - actual);
#elif defined(_WIN32)
uint64_t difference = labs(expected - actual);
+#elif defined(__SUNPRO_CC)
+ uint64_t difference = llabs(expected - actual);
#else
uint64_t difference = abs(expected - actual);
#endif
diff --git a/cpp/src/tests/TopicExchangeTest.cpp b/cpp/src/tests/TopicExchangeTest.cpp
index ff8931f9c9..d57951ea3f 100644
--- a/cpp/src/tests/TopicExchangeTest.cpp
+++ b/cpp/src/tests/TopicExchangeTest.cpp
@@ -16,6 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
+#include "qpid/broker/TopicKeyNode.h"
#include "qpid/broker/TopicExchange.h"
#include "unit_test.h"
#include "test_tools.h"
@@ -32,14 +33,15 @@ class TopicExchange::TopicExchangeTester {
public:
typedef std::vector<std::string> BindingVec;
+ typedef TopicKeyNode<TopicExchange::BindingKey> TestBindingNode;
private:
// binding node iterator that collects all routes that are bound
- class TestFinder : public TopicExchange::BindingNode::TreeIterator {
+ class TestFinder : public TestBindingNode::TreeIterator {
public:
TestFinder(BindingVec& m) : bv(m) {};
~TestFinder() {};
- bool visit(BindingNode& node) {
+ bool visit(TestBindingNode& node) {
if (!node.bindings.bindingVector.empty())
bv.push_back(node.routePattern);
return true;
@@ -53,7 +55,7 @@ public:
~TopicExchangeTester() {};
bool addBindingKey(const std::string& bKey) {
string routingPattern = normalize(bKey);
- BindingKey *bk = bindingTree.addBindingKey(routingPattern);
+ BindingKey *bk = bindingTree.add(routingPattern);
if (bk) {
// push a dummy binding to mark this node as "non-leaf"
bk->bindingVector.push_back(Binding::shared_ptr());
@@ -64,12 +66,12 @@ public:
bool removeBindingKey(const std::string& bKey){
string routingPattern = normalize(bKey);
- BindingKey *bk = bindingTree.getBindingKey(routingPattern);
+ BindingKey *bk = bindingTree.get(routingPattern);
if (bk) {
bk->bindingVector.pop_back();
if (bk->bindingVector.empty()) {
// no more bindings - remove this node
- bindingTree.removeBindingKey(routingPattern);
+ bindingTree.remove(routingPattern);
}
return true;
}
@@ -87,7 +89,7 @@ public:
}
private:
- TopicExchange::BindingNode bindingTree;
+ TestBindingNode bindingTree;
};
} // namespace broker
diff --git a/cpp/src/tests/TxPublishTest.cpp b/cpp/src/tests/TxPublishTest.cpp
index 152581e4ba..a636646035 100644
--- a/cpp/src/tests/TxPublishTest.cpp
+++ b/cpp/src/tests/TxPublishTest.cpp
@@ -69,9 +69,9 @@ QPID_AUTO_TEST_CASE(testPrepare)
//ensure messages are enqueued in store
t.op.prepare(0);
BOOST_CHECK_EQUAL((size_t) 2, t.store.enqueued.size());
- BOOST_CHECK_EQUAL(string("queue1"), t.store.enqueued[0].first);
+ BOOST_CHECK_EQUAL(std::string("queue1"), t.store.enqueued[0].first);
BOOST_CHECK_EQUAL(pmsg, t.store.enqueued[0].second);
- BOOST_CHECK_EQUAL(string("queue2"), t.store.enqueued[1].first);
+ BOOST_CHECK_EQUAL(std::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());
}
diff --git a/cpp/src/tests/Uuid.cpp b/cpp/src/tests/Uuid.cpp
index f85a297adc..aa9580e25e 100644
--- a/cpp/src/tests/Uuid.cpp
+++ b/cpp/src/tests/Uuid.cpp
@@ -19,7 +19,6 @@
#include "qpid/framing/Uuid.h"
#include "qpid/framing/Buffer.h"
#include "qpid/types/Uuid.h"
-#include "qpid/sys/alloca.h"
#include "unit_test.h"
@@ -52,6 +51,11 @@ boost::array<uint8_t, 16> sample = {{0x1b, 0x4e, 0x28, 0xba, 0x2f, 0xa1, 0x11,
const string sampleStr("1b4e28ba-2fa1-11d2-883f-b9a761bde3fb");
const string zeroStr("00000000-0000-0000-0000-000000000000");
+QPID_AUTO_TEST_CASE(testUuidStr) {
+ Uuid uuid(sampleStr);
+ BOOST_CHECK(uuid == sample);
+}
+
QPID_AUTO_TEST_CASE(testUuidIstream) {
Uuid uuid;
istringstream in(sampleStr);
@@ -92,12 +96,12 @@ QPID_AUTO_TEST_CASE(testUuidIOstream) {
}
QPID_AUTO_TEST_CASE(testUuidEncodeDecode) {
- char* buff = static_cast<char*>(::alloca(Uuid::size()));
- Buffer wbuf(buff, Uuid::size());
+ std::vector<char> buff(Uuid::size());
+ Buffer wbuf(&buff[0], Uuid::size());
Uuid uuid(sample.c_array());
uuid.encode(wbuf);
- Buffer rbuf(buff, Uuid::size());
+ Buffer rbuf(&buff[0], Uuid::size());
Uuid decoded;
decoded.decode(rbuf);
BOOST_CHECK_EQUAL(string(sample.begin(), sample.end()),
diff --git a/cpp/src/tests/acl.py b/cpp/src/tests/acl.py
index 720b3b4216..0e096a6f5b 100755
--- a/cpp/src/tests/acl.py
+++ b/cpp/src/tests/acl.py
@@ -285,10 +285,38 @@ class ACLTests(TestBase010):
if (result):
self.fail(result)
+ def test_nested_groups(self):
+ """
+ Test nested groups
+ """
+
+ aclf = self.get_acl_file()
+ aclf.write('group user-consume martin@QPID ted@QPID\n')
+ aclf.write('group group2 kim@QPID user-consume rob@QPID \n')
+ aclf.write('acl allow anonymous all all \n')
+ aclf.write('acl allow group2 create queue \n')
+ aclf.write('acl deny all all')
+ aclf.close()
+
+ result = self.reload_acl()
+ if (result):
+ self.fail(result)
+
+ session = self.get_session('rob','rob')
+ try:
+ session.queue_declare(queue="rob_queue")
+ except qpid.session.SessionException, e:
+ if (403 == e.args[0].error_code):
+ self.fail("ACL should allow queue create request");
+ self.fail("Error during queue create request");
+
+
+
def test_user_realm(self):
"""
Test a user defined without a realm
Ex. group admin rajith
+ Note: a user name without a realm is interpreted as a group name
"""
aclf = self.get_acl_file()
aclf.write('group admin bob\n') # shouldn't be allowed
@@ -297,7 +325,7 @@ class ACLTests(TestBase010):
aclf.close()
result = self.reload_acl()
- if (result.find("Username 'bob' must contain a realm",0,len(result)) == -1):
+ if (result.find("not defined yet.",0,len(result)) == -1):
self.fail(result)
def test_allowed_chars_for_username(self):
@@ -1509,6 +1537,124 @@ class ACLTests(TestBase010):
#=====================================
+ # QMF Topic Exchange tests
+ #=====================================
+
+ def test_qmf_topic_exchange_tests(self):
+ """
+ Test using QMF method hooks into ACL logic
+ """
+ aclf = self.get_acl_file()
+ aclf.write('# begin hack alert: allow anonymous to access the lookup debug functions\n')
+ aclf.write('acl allow-log anonymous create queue\n')
+ aclf.write('acl allow-log anonymous all exchange name=qmf.*\n')
+ aclf.write('acl allow-log anonymous all exchange name=amq.direct\n')
+ aclf.write('acl allow-log anonymous all exchange name=qpid.management\n')
+ aclf.write('acl allow-log anonymous access method name=*\n')
+ aclf.write('# end hack alert\n')
+ aclf.write('acl allow-log uPlain1@COMPANY publish exchange name=X routingkey=ab.cd.e\n')
+ aclf.write('acl allow-log uPlain2@COMPANY publish exchange name=X routingkey=.\n')
+ aclf.write('acl allow-log uStar1@COMPANY publish exchange name=X routingkey=a.*.b\n')
+ aclf.write('acl allow-log uStar2@COMPANY publish exchange name=X routingkey=*.x\n')
+ aclf.write('acl allow-log uStar3@COMPANY publish exchange name=X routingkey=x.x.*\n')
+ aclf.write('acl allow-log uHash1@COMPANY publish exchange name=X routingkey=a.#.b\n')
+ aclf.write('acl allow-log uHash2@COMPANY publish exchange name=X routingkey=a.#\n')
+ aclf.write('acl allow-log uHash3@COMPANY publish exchange name=X routingkey=#.a\n')
+ aclf.write('acl allow-log uHash4@COMPANY publish exchange name=X routingkey=a.#.b.#.c\n')
+ aclf.write('acl allow-log uMixed1@COMPANY publish exchange name=X routingkey=*.x.#.y\n')
+ aclf.write('acl allow-log uMixed2@COMPANY publish exchange name=X routingkey=a.#.b.*\n')
+ aclf.write('acl allow-log uMixed3@COMPANY publish exchange name=X routingkey=*.*.*.#\n')
+
+ aclf.write('acl allow-log all publish exchange name=X routingkey=MN.OP.Q\n')
+ aclf.write('acl allow-log all publish exchange name=X routingkey=M.*.N\n')
+ aclf.write('acl allow-log all publish exchange name=X routingkey=M.#.N\n')
+ aclf.write('acl allow-log all publish exchange name=X routingkey=*.M.#.N\n')
+
+ aclf.write('acl deny-log all all\n')
+ aclf.close()
+
+ result = self.reload_acl()
+ if (result):
+ self.fail(result)
+
+ # aclKey: "ab.cd.e"
+ self.LookupPublish("uPlain1@COMPANY", "X", "ab.cd.e", "allow-log")
+ self.LookupPublish("uPlain1@COMPANY", "X", "abx.cd.e", "deny-log")
+ self.LookupPublish("uPlain1@COMPANY", "X", "ab.cd", "deny-log")
+ self.LookupPublish("uPlain1@COMPANY", "X", "ab.cd..e.", "deny-log")
+ self.LookupPublish("uPlain1@COMPANY", "X", "ab.cd.e.", "deny-log")
+ self.LookupPublish("uPlain1@COMPANY", "X", ".ab.cd.e", "deny-log")
+ # aclKey: "."
+ self.LookupPublish("uPlain2@COMPANY", "X", ".", "allow-log")
+
+ # aclKey: "a.*.b"
+ self.LookupPublish("uStar1@COMPANY", "X", "a.xx.b", "allow-log")
+ self.LookupPublish("uStar1@COMPANY", "X", "a.b", "deny-log")
+ # aclKey: "*.x"
+ self.LookupPublish("uStar2@COMPANY", "X", "y.x", "allow-log")
+ self.LookupPublish("uStar2@COMPANY", "X", ".x", "allow-log")
+ self.LookupPublish("uStar2@COMPANY", "X", "x", "deny-log")
+ # aclKey: "x.x.*"
+ self.LookupPublish("uStar3@COMPANY", "X", "x.x.y", "allow-log")
+ self.LookupPublish("uStar3@COMPANY", "X", "x.x.", "allow-log")
+ self.LookupPublish("uStar3@COMPANY", "X", "x.x", "deny-log")
+ self.LookupPublish("uStar3@COMPANY", "X", "q.x.y", "deny-log")
+
+ # aclKey: "a.#.b"
+ self.LookupPublish("uHash1@COMPANY", "X", "a.b", "allow-log")
+ self.LookupPublish("uHash1@COMPANY", "X", "a.x.b", "allow-log")
+ self.LookupPublish("uHash1@COMPANY", "X", "a..x.y.zz.b", "allow-log")
+ self.LookupPublish("uHash1@COMPANY", "X", "a.b.", "deny-log")
+ self.LookupPublish("uHash1@COMPANY", "X", "q.x.b", "deny-log")
+
+ # aclKey: "a.#"
+ self.LookupPublish("uHash2@COMPANY", "X", "a", "allow-log")
+ self.LookupPublish("uHash2@COMPANY", "X", "a.b", "allow-log")
+ self.LookupPublish("uHash2@COMPANY", "X", "a.b.c", "allow-log")
+
+ # aclKey: "#.a"
+ self.LookupPublish("uHash3@COMPANY", "X", "a", "allow-log")
+ self.LookupPublish("uHash3@COMPANY", "X", "x.y.a", "allow-log")
+
+ # aclKey: "a.#.b.#.c"
+ self.LookupPublish("uHash4@COMPANY", "X", "a.b.c", "allow-log")
+ self.LookupPublish("uHash4@COMPANY", "X", "a.x.b.y.c", "allow-log")
+ self.LookupPublish("uHash4@COMPANY", "X", "a.x.x.b.y.y.c", "allow-log")
+
+ # aclKey: "*.x.#.y"
+ self.LookupPublish("uMixed1@COMPANY", "X", "a.x.y", "allow-log")
+ self.LookupPublish("uMixed1@COMPANY", "X", "a.x.p.qq.y", "allow-log")
+ self.LookupPublish("uMixed1@COMPANY", "X", "a.a.x.y", "deny-log")
+ self.LookupPublish("uMixed1@COMPANY", "X", "aa.x.b.c", "deny-log")
+
+ # aclKey: "a.#.b.*"
+ self.LookupPublish("uMixed2@COMPANY", "X", "a.b.x", "allow-log")
+ self.LookupPublish("uMixed2@COMPANY", "X", "a.x.x.x.b.x", "allow-log")
+
+ # aclKey: "*.*.*.#"
+ self.LookupPublish("uMixed3@COMPANY", "X", "x.y.z", "allow-log")
+ self.LookupPublish("uMixed3@COMPANY", "X", "x.y.z.a.b.c", "allow-log")
+ self.LookupPublish("uMixed3@COMPANY", "X", "x.y", "deny-log")
+ self.LookupPublish("uMixed3@COMPANY", "X", "x", "deny-log")
+
+ # Repeat the keys with wildcard user spec
+ self.LookupPublish("uPlain1@COMPANY", "X", "MN.OP.Q", "allow-log")
+ self.LookupPublish("uStar1@COMPANY" , "X", "M.xx.N", "allow-log")
+ self.LookupPublish("uHash1@COMPANY" , "X", "M.N", "allow-log")
+ self.LookupPublish("uHash1@COMPANY" , "X", "M.x.N", "allow-log")
+ self.LookupPublish("uHash1@COMPANY" , "X", "M..x.y.zz.N", "allow-log")
+ self.LookupPublish("uMixed1@COMPANY", "X", "a.M.N", "allow-log")
+ self.LookupPublish("uMixed1@COMPANY", "X", "a.M.p.qq.N", "allow-log")
+
+ self.LookupPublish("dev@QPID", "X", "MN.OP.Q", "allow-log")
+ self.LookupPublish("dev@QPID", "X", "M.xx.N", "allow-log")
+ self.LookupPublish("dev@QPID", "X", "M.N", "allow-log")
+ self.LookupPublish("dev@QPID", "X", "M.x.N", "allow-log")
+ self.LookupPublish("dev@QPID", "X", "M..x.y.zz.N", "allow-log")
+ self.LookupPublish("dev@QPID", "X", "a.M.N", "allow-log")
+ self.LookupPublish("dev@QPID", "X", "a.M.p.qq.N", "allow-log")
+
+ #=====================================
# Connection limits
#=====================================
diff --git a/cpp/src/tests/asyncstore.cmake b/cpp/src/tests/asyncstore.cmake
index 795ea55cf7..51efa88bd3 100644
--- a/cpp/src/tests/asyncstore.cmake
+++ b/cpp/src/tests/asyncstore.cmake
@@ -45,7 +45,7 @@ if (UNIX)
qpidbroker
rt
)
- add_test (Store_Perftools_Smoke_Test ${CMAKE_CURRENT_SOURCE_DIR}/storePerftools/storePerftoolsSmokeTest.sh)
+ add_test (jrnl2Perf_smoke_test ${CMAKE_CURRENT_SOURCE_DIR}/storePerftools/jrnl2Perf_smoke_test.sh)
endif (UNIX)
# Async store perf test (asyncPerf)
@@ -77,4 +77,5 @@ if (UNIX)
qpidtypes
rt
)
+ add_test (asyncStorePerf_smoke_test ${CMAKE_CURRENT_SOURCE_DIR}/storePerftools/asyncStorePerf_smoke_test.sh)
endif (UNIX)
diff --git a/cpp/src/tests/brokertest.py b/cpp/src/tests/brokertest.py
index 8255fbe9ac..aea4460e5a 100644
--- a/cpp/src/tests/brokertest.py
+++ b/cpp/src/tests/brokertest.py
@@ -76,18 +76,20 @@ def error_line(filename, n=1):
except: return ""
return ":\n" + "".join(result)
-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."""
+def retry(function, timeout=10, delay=.01, max_delay=1):
+ """Call function until it returns a true value or timeout expires.
+ Double the delay for each retry up to max_delay.
+ Returns what function returns if true, None if timeout expires."""
deadline = time.time() + timeout
- while not function():
+ ret = None
+ while True:
+ ret = function()
+ if ret: return ret
remaining = deadline - time.time()
if remaining <= 0: return False
delay = min(delay, remaining)
time.sleep(delay)
- delay *= 2
- return True
+ delay = min(delay*2, max_delay)
class AtomicCounter:
def __init__(self):
@@ -239,15 +241,13 @@ def find_in_file(str, filename):
class Broker(Popen):
"A broker process. Takes care of start, stop and logging."
_broker_count = 0
+ _log_count = 0
- def __str__(self): return "Broker<%s %s>"%(self.name, self.pname)
+ def __str__(self): return "Broker<%s %s :%d>"%(self.log, self.pname, self.port())
def find_log(self):
- self.log = "%s.log" % self.name
- i = 1
- while (os.path.exists(self.log)):
- self.log = "%s-%d.log" % (self.name, i)
- i += 1
+ self.log = "%03d:%s.log" % (Broker._log_count, self.name)
+ Broker._log_count += 1
def get_log(self):
return os.path.abspath(self.log)
@@ -298,9 +298,9 @@ class Broker(Popen):
# Read port from broker process stdout if not already read.
if (self._port == 0):
try: self._port = int(self.stdout.readline())
- except ValueError:
- raise Exception("Can't get port for broker %s (%s)%s" %
- (self.name, self.pname, error_line(self.log,5)))
+ except ValueError, e:
+ raise Exception("Can't get port for broker %s (%s)%s: %s" %
+ (self.name, self.pname, error_line(self.log,5), e))
return self._port
def unexpected(self,msg):
@@ -572,7 +572,7 @@ class NumberedSender(Thread):
"""
Thread.__init__(self)
cmd = ["qpid-send",
- "--broker", url or broker.host_port(),
+ "--broker", url or broker.host_port(),
"--address", "%s;{create:always}"%queue,
"--connection-options", "{%s}"%(connection_options),
"--content-stdin"
@@ -647,6 +647,7 @@ class NumberedReceiver(Thread):
self.error = None
self.sender = sender
self.received = 0
+ self.queue = queue
def read_message(self):
n = int(self.receiver.stdout.readline())
@@ -657,7 +658,7 @@ class NumberedReceiver(Thread):
m = self.read_message()
while m != -1:
self.receiver.assert_running()
- assert(m <= self.received) # Check for missing messages
+ assert m <= self.received, "%s missing message %s>%s"%(self.queue, m, self.received)
if (m == self.received): # Ignore duplicates
self.received += 1
if self.sender:
diff --git a/cpp/src/tests/cluster_test_logs.py b/cpp/src/tests/cluster_test_logs.py
index 003d82c619..22f2470590 100755
--- a/cpp/src/tests/cluster_test_logs.py
+++ b/cpp/src/tests/cluster_test_logs.py
@@ -66,7 +66,8 @@ def filter_log(log):
'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
- "org.apache.qpid.broker:bridge:" # ignore bridge index
+ "org.apache.qpid.broker:bridge:", # ignore bridge index
+ "closed connection"
])
# 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'
diff --git a/cpp/src/tests/cluster_tests.py b/cpp/src/tests/cluster_tests.py
index 8952f5de7b..3c96b252df 100755
--- a/cpp/src/tests/cluster_tests.py
+++ b/cpp/src/tests/cluster_tests.py
@@ -227,6 +227,18 @@ acl deny all all
self.assertEqual("x", cluster[0].get_message("q").content)
self.assertEqual("y", cluster[1].get_message("q").content)
+ def test_other_mech(self):
+ """Test using a mechanism other than PLAIN/ANONYMOUS for cluster update authentication.
+ Regression test for https://issues.apache.org/jira/browse/QPID-3849"""
+ sasl_config=os.path.join(self.rootdir, "sasl_config")
+ cluster = self.cluster(2, args=["--auth", "yes", "--sasl-config", sasl_config,
+ "--cluster-username=zig",
+ "--cluster-password=zig",
+ "--cluster-mechanism=DIGEST-MD5"])
+ cluster[0].connect()
+ cluster.start() # Before the fix this broker falied to join the cluster.
+ cluster[2].connect()
+
def test_link_events(self):
"""Regression test for https://bugzilla.redhat.com/show_bug.cgi?id=611543"""
args = ["--mgmt-pub-interval", 1] # Publish management information every second.
@@ -768,6 +780,35 @@ acl deny all all
fetch(cluster[2])
+ def _verify_federation(self, src_broker, src, dst_broker, dst, timeout=30):
+ """ Prove that traffic can pass between two federated brokers.
+ """
+ tot_time = 0
+ active = False
+ send_session = src_broker.connect().session()
+ sender = send_session.sender(src)
+ receive_session = dst_broker.connect().session()
+ receiver = receive_session.receiver(dst)
+ while not active and tot_time < timeout:
+ sender.send(Message("Hello from Source!"))
+ try:
+ receiver.fetch(timeout = 1)
+ receive_session.acknowledge()
+ # Get this far without Empty exception, and the link is good!
+ active = True
+ while True:
+ # Keep receiving msgs, as several may have accumulated
+ receiver.fetch(timeout = 1)
+ receive_session.acknowledge()
+ except Empty:
+ if not active:
+ tot_time += 1
+ receiver.close()
+ receive_session.close()
+ sender.close()
+ send_session.close()
+ return active
+
def test_federation_failover(self):
"""
Verify that federation operates across failures occuring in a cluster.
@@ -778,38 +819,6 @@ acl deny all all
cluster to newly-added members
"""
- TIMEOUT = 30
- def verify(src_broker, src, dst_broker, dst, timeout=TIMEOUT):
- """ Prove that traffic can pass from source fed broker to
- destination fed broker
- """
- tot_time = 0
- active = False
- send_session = src_broker.connect().session()
- sender = send_session.sender(src)
- receive_session = dst_broker.connect().session()
- receiver = receive_session.receiver(dst)
- while not active and tot_time < timeout:
- sender.send(Message("Hello from Source!"))
- try:
- receiver.fetch(timeout = 1)
- receive_session.acknowledge()
- # Get this far without Empty exception, and the link is good!
- active = True
- while True:
- # Keep receiving msgs, as several may have accumulated
- receiver.fetch(timeout = 1)
- receive_session.acknowledge()
- except Empty:
- if not active:
- tot_time += 1
- receiver.close()
- receive_session.close()
- sender.close()
- send_session.close()
- self.assertTrue(active, "Bridge failed to become active")
-
-
# 2 node cluster source, 2 node cluster destination
src_cluster = self.cluster(2, expect=EXPECT_EXIT_FAIL)
src_cluster.ready();
@@ -848,43 +857,145 @@ acl deny all all
self.assertEqual(result.status, 0, result)
# check that traffic passes
- verify(src_cluster[0], "srcQ", dst_cluster[0], "destQ")
+ assert self._verify_federation(src_cluster[0], "srcQ", dst_cluster[0], "destQ")
# add src[2] broker to source cluster
src_cluster.start(expect=EXPECT_EXIT_FAIL);
src_cluster.ready();
- verify(src_cluster[2], "srcQ", dst_cluster[0], "destQ")
+ assert self._verify_federation(src_cluster[2], "srcQ", dst_cluster[0], "destQ")
# Kill src[0]. dst[0] should fail over to src[1]
src_cluster[0].kill()
for b in src_cluster[1:]: b.ready()
- verify(src_cluster[1], "srcQ", dst_cluster[0], "destQ")
+ assert self._verify_federation(src_cluster[1], "srcQ", dst_cluster[0], "destQ")
# Kill src[1], dst[0] should fail over to src[2]
src_cluster[1].kill()
for b in src_cluster[2:]: b.ready()
- verify(src_cluster[2], "srcQ", dst_cluster[0], "destQ")
+ assert self._verify_federation(src_cluster[2], "srcQ", dst_cluster[0], "destQ")
# Kill dest[0], force failover to dest[1]
dst_cluster[0].kill()
for b in dst_cluster[1:]: b.ready()
- verify(src_cluster[2], "srcQ", dst_cluster[1], "destQ")
+ assert self._verify_federation(src_cluster[2], "srcQ", dst_cluster[1], "destQ")
# Add dest[2]
# dest[1] syncs dest[2] to current remote state
dst_cluster.start(expect=EXPECT_EXIT_FAIL);
for b in dst_cluster[1:]: b.ready()
- verify(src_cluster[2], "srcQ", dst_cluster[1], "destQ")
+ assert self._verify_federation(src_cluster[2], "srcQ", dst_cluster[1], "destQ")
# Kill dest[1], force failover to dest[2]
dst_cluster[1].kill()
for b in dst_cluster[2:]: b.ready()
- verify(src_cluster[2], "srcQ", dst_cluster[2], "destQ")
+ assert self._verify_federation(src_cluster[2], "srcQ", dst_cluster[2], "destQ")
for i in range(2, len(src_cluster)): src_cluster[i].kill()
for i in range(2, len(dst_cluster)): dst_cluster[i].kill()
+ def test_federation_multilink_failover(self):
+ """
+ Verify that multi-link federation operates across failures occuring in
+ a cluster.
+ """
+
+ # 1 node cluster source, 1 node cluster destination
+ src_cluster = self.cluster(1, expect=EXPECT_EXIT_FAIL)
+ src_cluster.ready();
+ dst_cluster = self.cluster(1, expect=EXPECT_EXIT_FAIL)
+ dst_cluster.ready();
+
+ # federate a direct binding across two separate links
+
+ # first, create a direct exchange bound to two queues using different
+ # bindings
+ cmd = self.popen(["qpid-config",
+ "--broker", src_cluster[0].host_port(),
+ "add", "exchange", "direct", "FedX"],
+ EXPECT_EXIT_OK)
+ cmd.wait()
+
+ cmd = self.popen(["qpid-config",
+ "--broker", dst_cluster[0].host_port(),
+ "add", "exchange", "direct", "FedX"],
+ EXPECT_EXIT_OK)
+ cmd.wait()
+
+ cmd = self.popen(["qpid-config",
+ "--broker", dst_cluster[0].host_port(),
+ "add", "queue", "destQ1"],
+ EXPECT_EXIT_OK)
+ cmd.wait()
+
+ cmd = self.popen(["qpid-config",
+ "--broker", dst_cluster[0].host_port(),
+ "bind", "FedX", "destQ1", "one"],
+ EXPECT_EXIT_OK)
+ cmd.wait()
+
+ cmd = self.popen(["qpid-config",
+ "--broker", dst_cluster[0].host_port(),
+ "add", "queue", "destQ2"],
+ EXPECT_EXIT_OK)
+ cmd.wait()
+
+ cmd = self.popen(["qpid-config",
+ "--broker", dst_cluster[0].host_port(),
+ "bind", "FedX", "destQ2", "two"],
+ EXPECT_EXIT_OK)
+ cmd.wait()
+
+ # Create two separate links between the dst and source brokers, bind
+ # each to different keys
+ dst_cluster[0].startQmf()
+ dst_broker = dst_cluster[0].qmf_session.getObjects(_class="broker")[0]
+
+ for _l in [("link1", "bridge1", "one"),
+ ("link2", "bridge2", "two")]:
+ result = dst_broker.create("link", _l[0],
+ {"host":src_cluster[0].host(),
+ "port":src_cluster[0].port()},
+ False)
+ self.assertEqual(result.status, 0, result);
+ result = dst_broker.create("bridge", _l[1],
+ {"link":_l[0],
+ "src":"FedX",
+ "dest":"FedX",
+ "key":_l[2]}, False)
+ self.assertEqual(result.status, 0);
+
+ # check that traffic passes
+ assert self._verify_federation(src_cluster[0], "FedX/one", dst_cluster[0], "destQ1")
+ assert self._verify_federation(src_cluster[0], "FedX/two", dst_cluster[0], "destQ2")
+
+ # add new member, verify traffic
+ src_cluster.start(expect=EXPECT_EXIT_FAIL);
+ src_cluster.ready();
+
+ dst_cluster.start(expect=EXPECT_EXIT_FAIL);
+ dst_cluster.ready();
+
+ assert self._verify_federation(src_cluster[0], "FedX/one", dst_cluster[0], "destQ1")
+ assert self._verify_federation(src_cluster[0], "FedX/two", dst_cluster[0], "destQ2")
+
+ src_cluster[0].kill()
+ for b in src_cluster[1:]: b.ready()
+
+ assert self._verify_federation(src_cluster[1], "FedX/one", dst_cluster[0], "destQ1")
+ assert self._verify_federation(src_cluster[1], "FedX/two", dst_cluster[0], "destQ2")
+
+ dst_cluster[0].kill()
+ for b in dst_cluster[1:]: b.ready()
+
+ assert self._verify_federation(src_cluster[1], "FedX/one", dst_cluster[1], "destQ1")
+ assert self._verify_federation(src_cluster[1], "FedX/two", dst_cluster[1], "destQ2")
+
+ for i in range(1, len(src_cluster)): src_cluster[i].kill()
+ for i in range(1, len(dst_cluster)): dst_cluster[i].kill()
+
+
+
# Some utility code for transaction tests
XA_RBROLLBACK = 1
XA_RBTIMEOUT = 2
diff --git a/cpp/src/tests/federation.py b/cpp/src/tests/federation.py
index 7d613b98ce..dcd074eda9 100755
--- a/cpp/src/tests/federation.py
+++ b/cpp/src/tests/federation.py
@@ -23,6 +23,7 @@ from qpid.testlib import TestBase010
from qpid.datatypes import Message
from qpid.queue import Empty
from qpid.util import URL
+import qpid.messaging
from time import sleep, time
@@ -94,6 +95,11 @@ class FederationTests(TestBase010):
break
self._brokers.append(_b)
+ # add a new-style messaging connection to each broker
+ for _b in self._brokers:
+ _b.connection = qpid.messaging.Connection(_b.url)
+ _b.connection.open()
+
def _teardown_brokers(self):
""" Un-does _setup_brokers()
"""
@@ -103,7 +109,7 @@ class FederationTests(TestBase010):
if not _b.client_session.error():
_b.client_session.close(timeout=10)
_b.client_conn.close(timeout=10)
-
+ _b.connection.close()
def test_bridge_create_and_close(self):
self.startQmf();
@@ -127,18 +133,28 @@ class FederationTests(TestBase010):
self.verify_cleanup()
def test_pull_from_exchange(self):
+ """ This test uses an alternative method to manage links and bridges
+ via the broker object.
+ """
session = self.session
-
+
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, "amq.direct", "amq.fanout", "my-key", "", "", False, False, False, 0)
+ # create link
+ link_args = {"host":self.remote_host(), "port":self.remote_port(), "durable":False,
+ "authMechanism":"PLAIN", "username":"guest", "password":"guest",
+ "transport":"tcp"}
+ result = broker.create("link", "test-link-1", link_args, False)
self.assertEqual(result.status, 0, result)
+ link = qmf.getObjects(_class="link")[0]
+ # create bridge
+ bridge_args = {"link":"test-link-1", "src":"amq.direct", "dest":"amq.fanout",
+ "key":"my-key"}
+ result = broker.create("bridge", "test-bridge-1", bridge_args, False);
+ self.assertEqual(result.status, 0, result)
bridge = qmf.getObjects(_class="bridge")[0]
#setup queue to receive messages from local broker
@@ -164,9 +180,11 @@ class FederationTests(TestBase010):
self.fail("Got unexpected message in queue: " + extra.body)
except Empty: None
- result = bridge.close()
+
+ result = broker.delete("bridge", "test-bridge-1", {})
self.assertEqual(result.status, 0, result)
- result = link.close()
+
+ result = broker.delete("link", "test-link-1", {})
self.assertEqual(result.status, 0, result)
self.verify_cleanup()
@@ -376,6 +394,9 @@ class FederationTests(TestBase010):
for i in range(1, 11):
try:
msg = queue.get(timeout=5)
+ mp = msg.get("message_properties").application_headers
+ self.assertEqual(mp.__class__, dict)
+ self.assertEqual(mp['x-qpid.trace'], 'REMOTE') # check that the federation-tag override works
self.assertEqual("Message %d" % i, msg.body)
except Empty:
self.fail("Failed to find expected message containing 'Message %d'" % i)
@@ -2153,3 +2174,433 @@ class FederationTests(TestBase010):
self.verify_cleanup()
+ def test_multilink_direct(self):
+ """ Verify that two distinct links can be created between federated
+ brokers.
+ """
+ self.startQmf()
+ qmf = self.qmf
+ self._setup_brokers()
+ src_broker = self._brokers[0]
+ dst_broker = self._brokers[1]
+
+ # create a direct exchange on each broker
+ for _b in [src_broker, dst_broker]:
+ _b.client_session.exchange_declare(exchange="fedX.direct", type="direct")
+ self.assertEqual(_b.client_session.exchange_query(name="fedX.direct").type,
+ "direct", "exchange_declare failed!")
+
+ # create destination queues
+ for _q in [("HiQ", "high"), ("MedQ", "medium"), ("LoQ", "low")]:
+ dst_broker.client_session.queue_declare(queue=_q[0], auto_delete=True)
+ dst_broker.client_session.exchange_bind(queue=_q[0], exchange="fedX.direct", binding_key=_q[1])
+
+ # create two connections, one for high priority traffic
+ for _q in ["HiPri", "Traffic"]:
+ result = dst_broker.qmf_object.create("link", _q,
+ {"host":src_broker.host,
+ "port":src_broker.port},
+ False)
+ self.assertEqual(result.status, 0);
+
+ links = qmf.getObjects(_broker=dst_broker.qmf_broker, _class="link")
+ for _l in links:
+ if _l.name == "HiPri":
+ hi_link = _l
+ elif _l.name == "Traffic":
+ data_link = _l
+ else:
+ self.fail("Unexpected Link found: " + _l.name)
+
+ # now create a route for messages sent with key "high" to use the
+ # hi_link
+ result = dst_broker.qmf_object.create("bridge", "HiPriBridge",
+ {"link":hi_link.name,
+ "src":"fedX.direct",
+ "dest":"fedX.direct",
+ "key":"high"}, False)
+ self.assertEqual(result.status, 0);
+
+
+ # create routes for the "medium" and "low" links to use the normal
+ # data_link
+ for _b in [("MediumBridge", "medium"), ("LowBridge", "low")]:
+ result = dst_broker.qmf_object.create("bridge", _b[0],
+ {"link":data_link.name,
+ "src":"fedX.direct",
+ "dest":"fedX.direct",
+ "key":_b[1]}, False)
+ self.assertEqual(result.status, 0);
+
+ # now wait for the links to become operational
+ for _l in [hi_link, data_link]:
+ expire_time = time() + 30
+ while _l.state != "Operational" and time() < expire_time:
+ _l.update()
+ self.assertEqual(_l.state, "Operational", "Link failed to become operational")
+
+ # verify each link uses a different connection
+ self.assertNotEqual(hi_link.connectionRef, data_link.connectionRef,
+ "Different links using the same connection")
+
+ hi_conn = qmf.getObjects(_broker=dst_broker.qmf_broker,
+ _objectId=hi_link.connectionRef)[0]
+ data_conn = qmf.getObjects(_broker=dst_broker.qmf_broker,
+ _objectId=data_link.connectionRef)[0]
+
+
+ # send hi data, verify only goes over hi link
+
+ r_ssn = dst_broker.connection.session()
+ hi_receiver = r_ssn.receiver("HiQ");
+ med_receiver = r_ssn.receiver("MedQ");
+ low_receiver = r_ssn.receiver("LoQ");
+
+ for _c in [hi_conn, data_conn]:
+ _c.update()
+ self.assertEqual(_c.msgsToClient, 0, "Unexpected messages received")
+
+ s_ssn = src_broker.connection.session()
+ hi_sender = s_ssn.sender("fedX.direct/high")
+ med_sender = s_ssn.sender("fedX.direct/medium")
+ low_sender = s_ssn.sender("fedX.direct/low")
+
+ try:
+ hi_sender.send(qpid.messaging.Message(content="hi priority"))
+ msg = hi_receiver.fetch(timeout=10)
+ r_ssn.acknowledge()
+ self.assertEqual(msg.content, "hi priority");
+ except:
+ self.fail("Hi Pri message failure")
+
+ hi_conn.update()
+ data_conn.update()
+ self.assertEqual(hi_conn.msgsToClient, 1, "Expected 1 hi pri message")
+ self.assertEqual(data_conn.msgsToClient, 0, "Expected 0 data messages")
+
+ # send low and medium, verify it does not go over hi link
+
+ try:
+ med_sender.send(qpid.messaging.Message(content="medium priority"))
+ msg = med_receiver.fetch(timeout=10)
+ r_ssn.acknowledge()
+ self.assertEqual(msg.content, "medium priority");
+ except:
+ self.fail("Medium Pri message failure")
+
+ hi_conn.update()
+ data_conn.update()
+ self.assertEqual(hi_conn.msgsToClient, 1, "Expected 1 hi pri message")
+ self.assertEqual(data_conn.msgsToClient, 1, "Expected 1 data message")
+
+ try:
+ low_sender.send(qpid.messaging.Message(content="low priority"))
+ msg = low_receiver.fetch(timeout=10)
+ r_ssn.acknowledge()
+ self.assertEqual(msg.content, "low priority");
+ except:
+ self.fail("Low Pri message failure")
+
+ hi_conn.update()
+ data_conn.update()
+ self.assertEqual(hi_conn.msgsToClient, 1, "Expected 1 hi pri message")
+ self.assertEqual(data_conn.msgsToClient, 2, "Expected 2 data message")
+
+ # cleanup
+
+ for _b in qmf.getObjects(_broker=dst_broker.qmf_broker,_class="bridge"):
+ result = _b.close()
+ self.assertEqual(result.status, 0)
+
+ for _l in qmf.getObjects(_broker=dst_broker.qmf_broker,_class="link"):
+ result = _l.close()
+ self.assertEqual(result.status, 0)
+
+ for _q in [("HiQ", "high"), ("MedQ", "medium"), ("LoQ", "low")]:
+ dst_broker.client_session.exchange_unbind(queue=_q[0], exchange="fedX.direct", binding_key=_q[1])
+ dst_broker.client_session.queue_delete(queue=_q[0])
+
+ for _b in [src_broker, dst_broker]:
+ _b.client_session.exchange_delete(exchange="fedX.direct")
+
+ self._teardown_brokers()
+
+ self.verify_cleanup()
+
+
+ def test_multilink_shared_queue(self):
+ """ Verify that two distinct links can be created between federated
+ brokers.
+ """
+ self.startQmf()
+ qmf = self.qmf
+ self._setup_brokers()
+ src_broker = self._brokers[0]
+ dst_broker = self._brokers[1]
+
+ # create a topic exchange on the destination broker
+ dst_broker.client_session.exchange_declare(exchange="fedX.topic", type="topic")
+ self.assertEqual(dst_broker.client_session.exchange_query(name="fedX.topic").type,
+ "topic", "exchange_declare failed!")
+
+ # create a destination queue
+ dst_broker.client_session.queue_declare(queue="destQ", auto_delete=True)
+ dst_broker.client_session.exchange_bind(queue="destQ", exchange="fedX.topic", binding_key="srcQ")
+
+ # create a single source queue
+ src_broker.client_session.queue_declare(queue="srcQ", auto_delete=True)
+
+ # create two connections
+ for _q in ["Link1", "Link2"]:
+ result = dst_broker.qmf_object.create("link", _q,
+ {"host":src_broker.host,
+ "port":src_broker.port},
+ False)
+ self.assertEqual(result.status, 0);
+
+ links = qmf.getObjects(_broker=dst_broker.qmf_broker, _class="link")
+ self.assertEqual(len(links), 2)
+
+ # now create two "parallel" queue routes from the source queue to the
+ # destination exchange.
+ result = dst_broker.qmf_object.create("bridge", "Bridge1",
+ {"link":"Link1",
+ "src":"srcQ",
+ "dest":"fedX.topic",
+ "srcIsQueue": True},
+ False)
+ self.assertEqual(result.status, 0);
+ result = dst_broker.qmf_object.create("bridge", "Bridge2",
+ {"link":"Link2",
+ "src":"srcQ",
+ "dest":"fedX.topic",
+ "srcIsQueue": True},
+ False)
+ self.assertEqual(result.status, 0);
+
+
+ # now wait for the links to become operational
+ for _l in links:
+ expire_time = time() + 30
+ while _l.state != "Operational" and time() < expire_time:
+ _l.update()
+ self.assertEqual(_l.state, "Operational", "Link failed to become operational")
+
+ # verify each link uses a different connection
+ self.assertNotEqual(links[0].connectionRef, links[1].connectionRef,
+ "Different links using the same connection")
+
+ conn1 = qmf.getObjects(_broker=dst_broker.qmf_broker,
+ _objectId=links[0].connectionRef)[0]
+ conn2 = qmf.getObjects(_broker=dst_broker.qmf_broker,
+ _objectId=links[1].connectionRef)[0]
+
+ # verify messages sent to the queue are pulled by each connection
+
+ r_ssn = dst_broker.connection.session()
+ receiver = r_ssn.receiver("destQ");
+
+ for _c in [conn1, conn2]:
+ _c.update()
+ self.assertEqual(_c.msgsToClient, 0, "Unexpected messages received")
+
+ s_ssn = src_broker.connection.session()
+ sender = s_ssn.sender("srcQ")
+
+ try:
+ for x in range(5):
+ sender.send(qpid.messaging.Message(content="hello"))
+ for x in range(5):
+ msg = receiver.fetch(timeout=10)
+ self.assertEqual(msg.content, "hello");
+ r_ssn.acknowledge()
+ except:
+ self.fail("Message failure")
+
+ # expect messages to be split over each connection.
+ conn1.update()
+ conn2.update()
+ self.assertNotEqual(conn1.msgsToClient, 0, "No messages sent")
+ self.assertNotEqual(conn2.msgsToClient, 0, "No messages sent")
+ self.assertEqual(conn2.msgsToClient + conn1.msgsToClient, 5,
+ "Expected 5 messages total")
+
+ for _b in qmf.getObjects(_broker=dst_broker.qmf_broker,_class="bridge"):
+ result = _b.close()
+ self.assertEqual(result.status, 0)
+
+ for _l in qmf.getObjects(_broker=dst_broker.qmf_broker,_class="link"):
+ result = _l.close()
+ self.assertEqual(result.status, 0)
+
+ dst_broker.client_session.exchange_unbind(queue="destQ", exchange="fedX.topic", binding_key="srcQ")
+ dst_broker.client_session.exchange_delete(exchange="fedX.topic")
+
+ self._teardown_brokers()
+
+ self.verify_cleanup()
+
+
+ def test_dynamic_direct_shared_queue(self):
+ """
+ Route Topology:
+
+ +<--- B1
+ B0 <---+<--- B2
+ +<--- B3
+ """
+ session = self.session
+
+ # create the federation
+
+ self.startQmf()
+ qmf = self.qmf
+
+ self._setup_brokers()
+
+ # create direct exchange on each broker, and retrieve the corresponding
+ # management object for that exchange
+
+ exchanges=[]
+ for _b in self._brokers:
+ _b.client_session.exchange_declare(exchange="fedX.direct", type="direct")
+ self.assertEqual(_b.client_session.exchange_query(name="fedX.direct").type,
+ "direct", "exchange_declare failed!")
+ # pull the exchange out of qmf...
+ retries = 0
+ my_exchange = None
+ while my_exchange is None:
+ objs = qmf.getObjects(_broker=_b.qmf_broker, _class="exchange")
+ for ooo in objs:
+ if ooo.name == "fedX.direct":
+ my_exchange = ooo
+ break
+ if my_exchange is None:
+ retries += 1
+ self.failIfEqual(retries, 10,
+ "QMF failed to find new exchange!")
+ sleep(1)
+ exchanges.append(my_exchange)
+
+ self.assertEqual(len(exchanges), len(self._brokers), "Exchange creation failed!")
+
+ # Create 2 links per each source broker (1,2,3) to the downstream
+ # broker 0:
+ for _b in range(1,4):
+ for _l in ["dynamic", "queue"]:
+ result = self._brokers[0].qmf_object.create( "link",
+ "Link-%d-%s" % (_b, _l),
+ {"host":self._brokers[_b].host,
+ "port":self._brokers[_b].port}, False)
+ self.assertEqual(result.status, 0)
+
+ # create queue on source brokers for use by the dynamic route
+ self._brokers[_b].client_session.queue_declare(queue="fedSrcQ", exclusive=False, auto_delete=True)
+
+ for _l in range(1,4):
+ # for each dynamic link, create a dynamic bridge for the "fedX.direct"
+ # exchanges, using the fedSrcQ on each upstream source broker
+ result = self._brokers[0].qmf_object.create("bridge",
+ "Bridge-%d-dynamic" % _l,
+ {"link":"Link-%d-dynamic" % _l,
+ "src":"fedX.direct",
+ "dest":"fedX.direct",
+ "dynamic":True,
+ "queue":"fedSrcQ"}, False)
+ self.assertEqual(result.status, 0)
+
+ # create a queue route that shares the queue used by the dynamic route
+ result = self._brokers[0].qmf_object.create("bridge",
+ "Bridge-%d-queue" % _l,
+ {"link":"Link-%d-queue" % _l,
+ "src":"fedSrcQ",
+ "dest":"fedX.direct",
+ "srcIsQueue":True}, False)
+ self.assertEqual(result.status, 0)
+
+
+ # wait for the inter-broker links to become operational
+ retries = 0
+ operational = False
+ while not operational:
+ 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
+ if not operational:
+ retries += 1
+ self.failIfEqual(retries, 10,
+ "inter-broker links failed to become operational.")
+ sleep(1)
+
+ # @todo - There is no way to determine when the bridge objects become
+ # active. Hopefully, this is long enough!
+ sleep(6)
+
+ # create a queue on B0, bound to "spudboy"
+ self._brokers[0].client_session.queue_declare(queue="DestQ", exclusive=True, auto_delete=True)
+ self._brokers[0].client_session.exchange_bind(queue="DestQ", exchange="fedX.direct", binding_key="spudboy")
+
+ # subscribe to messages arriving on B2's queue
+ self.subscribe(self._brokers[0].client_session, queue="DestQ", destination="f1")
+ queue = self._brokers[0].client_session.incoming("f1")
+
+ # wait until the binding key has propagated to each broker
+
+ binding_counts = [1, 1, 1, 1]
+ self.assertEqual(len(binding_counts), len(exchanges), "Update Test!")
+ for i in range(3,-1,-1):
+ retries = 0
+ exchanges[i].update()
+ while exchanges[i].bindingCount < binding_counts[i]:
+ retries += 1
+ self.failIfEqual(retries, 10,
+ "binding failed to propagate to broker %d"
+ % i)
+ sleep(3)
+ exchanges[i].update()
+
+ for _b in range(1,4):
+ # send 3 msgs from each source broker
+ for i in range(3):
+ dp = self._brokers[_b].client_session.delivery_properties(routing_key="spudboy")
+ self._brokers[_b].client_session.message_transfer(destination="fedX.direct", message=Message(dp, "Message_drp %d" % i))
+
+ # get exactly 9 (3 per broker) on B0
+ for i in range(9):
+ msg = queue.get(timeout=5)
+
+ try:
+ extra = queue.get(timeout=1)
+ self.fail("Got unexpected message in queue: " + extra.body)
+ except Empty: None
+
+ # verify that messages went across every link
+ for _l in qmf.getObjects(_broker=self._brokers[0].qmf_broker,
+ _class="link"):
+ for _c in qmf.getObjects(_broker=self._brokers[0].qmf_broker,
+ _objectId=_l.connectionRef):
+ self.assertNotEqual(_c.msgsToClient, 0, "Messages did not pass over link as expected.")
+
+ # cleanup
+
+ self._brokers[0].client_session.exchange_unbind(queue="DestQ", exchange="fedX.direct", binding_key="spudboy")
+ self._brokers[0].client_session.message_cancel(destination="f1")
+ self._brokers[0].client_session.queue_delete(queue="DestQ")
+
+ 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:
+ _b.client_session.exchange_delete(exchange="fedX.direct")
+
+ self._teardown_brokers()
+
+ self.verify_cleanup()
+
diff --git a/cpp/src/tests/ha_tests.py b/cpp/src/tests/ha_tests.py
index 827cb7dca9..d25281eed5 100755
--- a/cpp/src/tests/ha_tests.py
+++ b/cpp/src/tests/ha_tests.py
@@ -18,59 +18,123 @@
# under the License.
#
-import os, signal, sys, time, imp, re, subprocess, glob, random, logging, shutil, math
-from qpid.messaging import Message, NotFound, ConnectionError, ReceiverError, Connection
+import os, signal, sys, time, imp, re, subprocess, glob, random, logging, shutil, math, unittest
+import traceback
+from qpid.messaging import Message, NotFound, ConnectionError, ReceiverError, Connection, Timeout, Disposition, REJECTED
from qpid.datatypes import uuid4
from brokertest import *
from threading import Thread, Lock, Condition
-from logging import getLogger, WARN, ERROR, DEBUG
+from logging import getLogger, WARN, ERROR, DEBUG, INFO
from qpidtoollibs import BrokerAgent
+from uuid import UUID
log = getLogger(__name__)
+class QmfAgent(object):
+ """Access to a QMF broker agent."""
+ def __init__(self, address, **kwargs):
+ self._connection = Connection.establish(
+ address, client_properties={"qpid.ha-admin":1}, **kwargs)
+ self._agent = BrokerAgent(self._connection)
+ assert self._agent.getHaBroker(), "HA module not loaded in broker at: %s"%(address)
+
+ def __getattr__(self, name):
+ a = getattr(self._agent, name)
+ return a
+
+class Credentials(object):
+ """SASL credentials: username, password, and mechanism"""
+ def __init__(self, username, password, mechanism):
+ (self.username, self.password, self.mechanism) = (username, password, mechanism)
+
+ def __str__(self): return "Credentials%s"%(self.tuple(),)
+
+ def tuple(self): return (self.username, self.password, self.mechanism)
+
+ def add_user(self, url): return "%s/%s@%s"%(self.username, self.password, url)
+
class HaBroker(Broker):
- def __init__(self, test, args=[], broker_url=None, ha_cluster=True,
- ha_replicate="all", **kwargs):
+ """Start a broker with HA enabled
+ @param client_cred: (user, password, mechanism) for admin clients started by the HaBroker.
+ """
+ def __init__(self, test, args=[], brokers_url=None, ha_cluster=True, ha_replicate="all",
+ client_credentials=None, **kwargs):
assert BrokerTest.ha_lib, "Cannot locate HA plug-in"
args = copy(args)
args += ["--load-module", BrokerTest.ha_lib,
- "--log-enable=info+", "--log-enable=debug+:ha::",
+ "--log-enable=debug+:ha::",
# FIXME aconway 2012-02-13: workaround slow link failover.
"--link-maintenace-interval=0.1",
"--ha-cluster=%s"%ha_cluster]
if ha_replicate is not None:
args += [ "--ha-replicate=%s"%ha_replicate ]
- if broker_url: args.extend([ "--ha-brokers", broker_url ])
+ if brokers_url: args += [ "--ha-brokers-url", brokers_url ]
Broker.__init__(self, test, args, **kwargs)
- self.commands=os.getenv("PYTHON_COMMANDS")
- assert os.path.isdir(self.commands)
+ self.qpid_ha_path=os.path.join(os.getenv("PYTHON_COMMANDS"), "qpid-ha")
+ assert os.path.exists(self.qpid_ha_path)
+ self.qpid_config_path=os.path.join(os.getenv("PYTHON_COMMANDS"), "qpid-config")
+ assert os.path.exists(self.qpid_config_path)
getLogger().setLevel(ERROR) # Hide expected WARNING log messages from failover.
-
- def promote(self):
- assert os.system("%s/qpid-ha promote -b %s"%(self.commands, self.host_port())) == 0
-
- def set_client_url(self, url):
- assert os.system(
- "%s/qpid-ha set --public-brokers=%s -b %s"%(self.commands, url,self.host_port())) == 0
-
- def set_broker_url(self, url):
- assert os.system(
- "%s/qpid-ha set --brokers=%s -b %s"%(self.commands, url, self.host_port())) == 0
-
- def replicate(self, from_broker, queue):
- assert os.system(
- "%s/qpid-ha replicate -b %s %s %s"%(self.commands, self.host_port(), from_broker, queue)) == 0
+ self.qpid_ha_script=import_script(self.qpid_ha_path)
+ self._agent = None
+ self.client_credentials = client_credentials
+
+ def __str__(self): return Broker.__str__(self)
+
+ def qpid_ha(self, args):
+ cred = self.client_credentials
+ url = self.host_port()
+ if cred:
+ url =cred.add_user(url)
+ args = args + ["--sasl-mechanism", cred.mechanism]
+ self.qpid_ha_script.main_except(["", "-b", url]+args)
+
+ def promote(self): self.qpid_ha(["promote"])
+ def set_client_url(self, url): self.qpid_ha(["set", "--public-url", url])
+ def set_brokers_url(self, url): self.qpid_ha(["set", "--brokers-url", url])
+ def replicate(self, from_broker, queue): self.qpid_ha(["replicate", from_broker, queue])
+
+ def agent(self):
+ if not self._agent:
+ cred = self.client_credentials
+ if cred:
+ self._agent = QmfAgent(cred.add_user(self.host_port()), sasl_mechanisms=cred.mechanism)
+ else:
+ self._agent = QmfAgent(self.host_port())
+ return self._agent
+
+ def ha_status(self):
+ hb = self.agent().getHaBroker()
+ hb.update()
+ return hb.status
+
+ def wait_status(self, status):
+ def try_get_status():
+ # Ignore ConnectionError, the broker may not be up yet.
+ try: return self.ha_status() == status;
+ except ConnectionError: return False
+ assert retry(try_get_status, timeout=20), "%s status != %r"%(self, status)
+
+ # FIXME aconway 2012-05-01: do direct python call to qpid-config code.
+ def qpid_config(self, args):
+ assert subprocess.call(
+ [self.qpid_config_path, "--broker", self.host_port()]+args) == 0
def config_replicate(self, from_broker, queue):
- assert os.system(
- "%s/qpid-config --broker=%s add queue --start-replica %s %s"%(self.commands, self.host_port(), from_broker, queue)) == 0
+ self.qpid_config(["add", "queue", "--start-replica", from_broker, queue])
def config_declare(self, queue, replication):
- assert os.system(
- "%s/qpid-config --broker=%s add queue %s --replicate %s"%(self.commands, self.host_port(), queue, replication)) == 0
+ self.qpid_config(["add", "queue", queue, "--replicate", replication])
def connect_admin(self, **kwargs):
- return Broker.connect(self, client_properties={"qpid.ha-admin":1}, **kwargs)
+ cred = self.client_credentials
+ if cred:
+ return Broker.connect(
+ self, client_properties={"qpid.ha-admin":1},
+ username=cred.username, password=cred.password, sasl_mechanisms=cred.mechanism,
+ **kwargs)
+ else:
+ return Broker.connect(self, client_properties={"qpid.ha-admin":1}, **kwargs)
def wait_backup(self, address):
"""Wait for address to become valid on a backup broker."""
@@ -78,6 +142,14 @@ class HaBroker(Broker):
try: wait_address(bs, address)
finally: bs.connection.close()
+ def assert_browse(self, queue, expected, **kwargs):
+ """Verify queue contents by browsing."""
+ bs = self.connect().session()
+ try:
+ wait_address(bs, queue)
+ assert_browse_retry(bs, queue, expected, **kwargs)
+ finally: bs.connection.close()
+
def assert_browse_backup(self, queue, expected, **kwargs):
"""Combines wait_backup and assert_browse_retry."""
bs = self.connect_admin().session()
@@ -86,33 +158,70 @@ class HaBroker(Broker):
assert_browse_retry(bs, queue, expected, **kwargs)
finally: bs.connection.close()
+ def assert_connect_fail(self):
+ try:
+ self.connect()
+ self.test.fail("Expected ConnectionError")
+ except ConnectionError: pass
+
+ def try_connect(self):
+ try: return self.connect()
+ except ConnectionError: return None
+
class HaCluster(object):
_cluster_count = 0
- def __init__(self, test, n, **kwargs):
+ def __init__(self, test, n, promote=True, **kwargs):
"""Start a cluster of n brokers"""
self.test = test
- self._brokers = [ HaBroker(test, name="broker%s-%s"%(HaCluster._cluster_count, i), **kwargs) for i in xrange(n)]
+ self.kwargs = kwargs
+ self._brokers = []
+ self.id = HaCluster._cluster_count
+ self.broker_id = 0
HaCluster._cluster_count += 1
- self.url = ",".join([b.host_port() for b in self])
- for b in self: b.set_broker_url(self.url)
+ for i in xrange(n): self.start(False)
+ self.update_urls()
self[0].promote()
+ def next_name(self):
+ name="cluster%s-%s"%(self.id, self.broker_id)
+ self.broker_id += 1
+ return name
+
+ def start(self, update_urls=True, args=[]):
+ """Start a new broker in the cluster"""
+ b = HaBroker(self.test, name=self.next_name(), **self.kwargs)
+ self._brokers.append(b)
+ if update_urls: self.update_urls()
+ return b
+
+ def update_urls(self):
+ self.url = ",".join([b.host_port() for b in self])
+ if len(self) > 1: # No failover addresses on a 1 cluster.
+ for b in self: b.set_brokers_url(self.url)
+
def connect(self, i):
"""Connect with reconnect_urls"""
return self[i].connect(reconnect=True, reconnect_urls=self.url.split(","))
- def kill(self, i):
+ def kill(self, i, promote_next=True):
"""Kill broker i, promote broker i+1"""
- self[i].kill()
self[i].expect = EXPECT_EXIT_FAIL
- self[(i+1) % len(self)].promote()
+ self[i].kill()
+ if promote_next: self[(i+1) % len(self)].promote()
+
+ def restart(self, i):
+ """Start a broker with the same port, name and data directory. It will get
+ a separate log file: foo.n.log"""
+ b = self._brokers[i]
+ self._brokers[i] = HaBroker(
+ self.test, name=b.name, port=b.port(), brokers_url=self.url,
+ **self.kwargs)
- def bounce(self, i):
+ def bounce(self, i, promote_next=True):
"""Stop and restart a broker in a cluster."""
- self.kill(i)
- b = self[i]
- self._brokers[i] = HaBroker(self.test, name=b.name, port=b.port(), broker_url=self.url)
+ self.kill(i, promote_next)
+ self.restart(i)
# Behave like a list of brokers.
def __len__(self): return len(self._brokers)
@@ -128,12 +237,12 @@ def wait_address(session, address):
except NotFound: return False
assert retry(check), "Timed out waiting for address %s"%(address)
-def assert_missing(session, address):
- """Assert that the address is _not_ valid"""
+def valid_address(session, address):
+ """Test if an address is valid"""
try:
session.receiver(address)
- self.fail("Expected NotFound: %s"%(address))
- except NotFound: pass
+ return True
+ except NotFound: return False
class ReplicationTests(BrokerTest):
"""Correctness tests for HA replication."""
@@ -180,7 +289,7 @@ class ReplicationTests(BrokerTest):
self.assert_browse_retry(b, prefix+"q1", ["1", "4"])
self.assert_browse_retry(b, prefix+"q2", []) # configuration only
- assert_missing(b, prefix+"q3")
+ assert not valid_address(b, prefix+"q3")
b.sender(prefix+"e1").send(Message(prefix+"e1")) # Verify binds with replicate=all
self.assert_browse_retry(b, prefix+"q1", ["1", "4", prefix+"e1"])
b.sender(prefix+"e2").send(Message(prefix+"e2")) # Verify binds with replicate=configuration
@@ -195,7 +304,7 @@ class ReplicationTests(BrokerTest):
# Create config, send messages before starting the backup, to test catch-up replication.
setup(p, "1", primary)
- backup = HaBroker(self, name="backup", broker_url=primary.host_port())
+ backup = HaBroker(self, name="backup", brokers_url=primary.host_port())
# Create config, send messages after starting the backup, to test steady-state replication.
setup(p, "2", primary)
@@ -233,10 +342,10 @@ class ReplicationTests(BrokerTest):
s = p.sender("q;{create:always}")
for m in [str(i) for i in range(0,10)]: s.send(m)
s.sync()
- backup1 = HaBroker(self, name="backup1", broker_url=primary.host_port())
+ backup1 = HaBroker(self, name="backup1", brokers_url=primary.host_port())
for m in [str(i) for i in range(10,20)]: s.send(m)
s.sync()
- backup2 = HaBroker(self, name="backup2", broker_url=primary.host_port())
+ backup2 = HaBroker(self, name="backup2", brokers_url=primary.host_port())
for m in [str(i) for i in range(20,30)]: s.send(m)
s.sync()
@@ -276,7 +385,7 @@ class ReplicationTests(BrokerTest):
"""Verify that backups rejects connections and that fail-over works in python client"""
primary = HaBroker(self, name="primary", expect=EXPECT_EXIT_FAIL)
primary.promote()
- backup = HaBroker(self, name="backup", broker_url=primary.host_port())
+ backup = HaBroker(self, name="backup", brokers_url=primary.host_port())
# Check that backup rejects normal connections
try:
backup.connect().session()
@@ -294,14 +403,15 @@ class ReplicationTests(BrokerTest):
primary.kill()
assert retry(lambda: not is_running(primary.pid))
backup.promote()
- self.assert_browse_retry(s, "q", ["foo"])
+ sender.send("bar")
+ self.assert_browse_retry(s, "q", ["foo", "bar"])
c.close()
def test_failover_cpp(self):
"""Verify that failover works in the C++ client."""
primary = HaBroker(self, name="primary", expect=EXPECT_EXIT_FAIL)
primary.promote()
- backup = HaBroker(self, name="backup", broker_url=primary.host_port())
+ backup = HaBroker(self, name="backup", brokers_url=primary.host_port())
url="%s,%s"%(primary.host_port(), backup.host_port())
primary.connect().session().sender("q;{create:always}")
backup.wait_backup("q")
@@ -344,6 +454,7 @@ class ReplicationTests(BrokerTest):
def test_standalone_queue_replica(self):
"""Test replication of individual queues outside of cluster mode"""
+ getLogger().setLevel(ERROR) # Hide expected WARNING log messages from failover.
primary = HaBroker(self, name="primary", ha_cluster=False)
pc = primary.connect()
ps = pc.session().sender("q;{create:always}")
@@ -393,7 +504,7 @@ class ReplicationTests(BrokerTest):
"""Verify that we replicate to an LVQ correctly"""
primary = HaBroker(self, name="primary")
primary.promote()
- backup = HaBroker(self, name="backup", broker_url=primary.host_port())
+ backup = HaBroker(self, name="backup", brokers_url=primary.host_port())
s = primary.connect().session().sender("lvq; {create:always, node:{x-declare:{arguments:{'qpid.last_value_queue_key':lvq-key}}}}")
def send(key,value): s.send(Message(content=value,properties={"lvq-key":key}))
for kv in [("a","a-1"),("b","b-1"),("a","a-2"),("a","a-3"),("c","c-1"),("c","c-2")]:
@@ -410,7 +521,7 @@ class ReplicationTests(BrokerTest):
"""Test replication with the ring queue policy"""
primary = HaBroker(self, name="primary")
primary.promote()
- backup = HaBroker(self, name="backup", broker_url=primary.host_port())
+ backup = HaBroker(self, name="backup", brokers_url=primary.host_port())
s = primary.connect().session().sender("q; {create:always, node:{x-declare:{arguments:{'qpid.policy_type':ring, 'qpid.max_count':5}}}}")
for i in range(10): s.send(Message(str(i)))
backup.assert_browse_backup("q", [str(i) for i in range(5,10)])
@@ -419,18 +530,20 @@ class ReplicationTests(BrokerTest):
"""Test replication with the reject queue policy"""
primary = HaBroker(self, name="primary")
primary.promote()
- backup = HaBroker(self, name="backup", broker_url=primary.host_port())
+ backup = HaBroker(self, name="backup", brokers_url=primary.host_port())
s = primary.connect().session().sender("q; {create:always, node:{x-declare:{arguments:{'qpid.policy_type':reject, 'qpid.max_count':5}}}}")
try:
for i in range(10): s.send(Message(str(i)), sync=False)
except qpid.messaging.exceptions.TargetCapacityExceeded: pass
backup.assert_browse_backup("q", [str(i) for i in range(0,5)])
+ # Detach, don't close as there is a broken session
+ s.session.connection.detach()
def test_priority(self):
"""Verify priority queues replicate correctly"""
primary = HaBroker(self, name="primary")
primary.promote()
- backup = HaBroker(self, name="backup", broker_url=primary.host_port())
+ backup = HaBroker(self, name="backup", brokers_url=primary.host_port())
session = primary.connect().session()
s = session.sender("priority-queue; {create:always, node:{x-declare:{arguments:{'qpid.priorities':10}}}}")
priorities = [8,9,5,1,2,2,3,4,9,7,8,9,9,2]
@@ -445,7 +558,7 @@ class ReplicationTests(BrokerTest):
"""Verify priority queues replicate correctly"""
primary = HaBroker(self, name="primary")
primary.promote()
- backup = HaBroker(self, name="backup", broker_url=primary.host_port())
+ backup = HaBroker(self, name="backup", brokers_url=primary.host_port())
session = primary.connect().session()
levels = 8
priorities = [4,5,3,7,8,8,2,8,2,8,8,16,6,6,6,6,6,6,8,3,5,8,3,5,5,3,3,8,8,3,7,3,7,7,7,8,8,8,2,3]
@@ -464,7 +577,7 @@ class ReplicationTests(BrokerTest):
def test_priority_ring(self):
primary = HaBroker(self, name="primary")
primary.promote()
- backup = HaBroker(self, name="backup", broker_url=primary.host_port())
+ backup = HaBroker(self, name="backup", brokers_url=primary.host_port())
s = primary.connect().session().sender("q; {create:always, node:{x-declare:{arguments:{'qpid.policy_type':ring, 'qpid.max_count':5, 'qpid.priorities':10}}}}")
priorities = [8,9,5,1,2,2,3,4,9,7,8,9,9,2]
for p in priorities: s.send(Message(priority=p))
@@ -475,8 +588,10 @@ class ReplicationTests(BrokerTest):
# correct result, the uncommented one is for the actualy buggy
# result. See https://issues.apache.org/jira/browse/QPID-3866
#
- # backup.assert_browse_backup("q", sorted(priorities,reverse=True)[0:5], transform=lambda m: m.priority)
- backup.assert_browse_backup("q", [9,9,9,9,2], transform=lambda m: m.priority)
+ # expect = sorted(priorities,reverse=True)[0:5]
+ expect = [9,9,9,9,2]
+ primary.assert_browse("q", expect, transform=lambda m: m.priority)
+ backup.assert_browse_backup("q", expect, transform=lambda m: m.priority)
def test_backup_acquired(self):
"""Verify that acquired messages are backed up, for all queue types."""
@@ -509,11 +624,11 @@ class ReplicationTests(BrokerTest):
primary = HaBroker(self, name="primary")
primary.promote()
- backup1 = HaBroker(self, name="backup1", broker_url=primary.host_port())
+ backup1 = HaBroker(self, name="backup1", brokers_url=primary.host_port())
c = primary.connect()
for t in tests: t.send(c) # Send messages, leave one unacknowledged.
- backup2 = HaBroker(self, name="backup2", broker_url=primary.host_port())
+ backup2 = HaBroker(self, name="backup2", brokers_url=primary.host_port())
# Wait for backups to catch up.
for t in tests:
t.wait(self, backup1)
@@ -538,11 +653,13 @@ class ReplicationTests(BrokerTest):
self.fail("Excpected no-such-queue exception")
except NotFound: pass
- def test_invalid_default(self):
- """Verify that a queue with an invalid qpid.replicate gets default treatment"""
- cluster = HaCluster(self, 2, ha_replicate="all")
- c = cluster[0].connect().session().sender("q;{create:always, node:{x-declare:{arguments:{'qpid.replicate':XXinvalidXX}}}}")
- cluster[1].wait_backup("q")
+ def test_invalid_replication(self):
+ """Verify that we reject an attempt to declare a queue with invalid replication value."""
+ cluster = HaCluster(self, 1, ha_replicate="all")
+ try:
+ c = cluster[0].connect().session().sender("q;{create:always, node:{x-declare:{arguments:{'qpid.replicate':XXinvalidXX}}}}")
+ self.fail("Expected ConnectionError")
+ except ConnectionError: pass
def test_exclusive_queue(self):
"""Ensure that we can back-up exclusive queues, i.e. the replicating
@@ -559,6 +676,136 @@ class ReplicationTests(BrokerTest):
test("excl_sub;{create:always, link:{x-subscribe:{exclusive:True}}}");
test("excl_queue;{create:always, node:{x-declare:{exclusive:True}}}")
+ def test_auto_delete_exclusive(self):
+ """Verify that we ignore auto-delete, exclusive, non-auto-delete-timeout queues"""
+ cluster = HaCluster(self,2)
+ s = cluster[0].connect().session()
+ s.receiver("exad;{create:always,node:{x-declare:{exclusive:True,auto-delete:True}}}")
+ s.receiver("ex;{create:always,node:{x-declare:{exclusive:True}}}")
+ s.receiver("ad;{create:always,node:{x-declare:{auto-delete:True}}}")
+ s.receiver("time;{create:always,node:{x-declare:{exclusive:True,auto-delete:True,arguments:{'qpid.auto_delete_timeout':1}}}}")
+ s.receiver("q;{create:always}")
+
+ s = cluster[1].connect_admin().session()
+ cluster[1].wait_backup("q")
+ assert not valid_address(s, "exad")
+ assert valid_address(s, "ex")
+ assert valid_address(s, "ad")
+ assert valid_address(s, "time")
+
+ def test_broker_info(self):
+ """Check that broker information is correctly published via management"""
+ cluster = HaCluster(self, 3)
+
+ for broker in cluster: # Make sure HA system-id matches broker's
+ qmf = broker.agent().getHaBroker()
+ self.assertEqual(qmf.systemId, UUID(broker.agent().getBroker().systemRef))
+
+ cluster_ports = map(lambda b: b.port(), cluster)
+ cluster_ports.sort()
+ def ports(qmf):
+ qmf.update()
+ return sorted(map(lambda b: b["port"], qmf.members))
+ # Check that all brokers have the same membership as the cluster
+ for broker in cluster:
+ qmf = broker.agent().getHaBroker()
+ assert retry(lambda: cluster_ports == ports(qmf), 1), "%s != %s on %s"%(cluster_ports, ports(qmf), broker)
+ # Add a new broker, check it is updated everywhere
+ b = cluster.start()
+ cluster_ports.append(b.port())
+ cluster_ports.sort()
+ for broker in cluster:
+ qmf = broker.agent().getHaBroker()
+ assert retry(lambda: cluster_ports == ports(qmf), 1), "%s != %s"%(cluster_ports, ports(qmf))
+
+ def test_auth(self):
+ """Verify that authentication does not interfere with replication."""
+ # FIXME aconway 2012-07-09: generate test sasl config portably for cmake
+ sasl_config=os.path.join(self.rootdir, "sasl_config")
+ if not os.path.exists(sasl_config):
+ print "WARNING: Skipping test, SASL test configuration %s not found."%sasl_config
+ return
+ acl=os.path.join(os.getcwd(), "policy.acl")
+ aclf=file(acl,"w")
+ # Verify that replication works with auth=yes and HA user has at least the following
+ # privileges:
+ aclf.write("""
+acl allow zag@QPID access queue
+acl allow zag@QPID create queue
+acl allow zag@QPID consume queue
+acl allow zag@QPID delete queue
+acl allow zag@QPID access exchange
+acl allow zag@QPID create exchange
+acl allow zag@QPID bind exchange
+acl allow zag@QPID publish exchange
+acl allow zag@QPID delete exchange
+acl allow zag@QPID access method
+acl allow zag@QPID create link
+acl deny all all
+ """)
+ aclf.close()
+ cluster = HaCluster(
+ self, 2,
+ args=["--auth", "yes", "--sasl-config", sasl_config,
+ "--acl-file", acl, "--load-module", os.getenv("ACL_LIB"),
+ "--ha-username=zag", "--ha-password=zag", "--ha-mechanism=PLAIN"
+ ],
+ client_credentials=Credentials("zag", "zag", "PLAIN"))
+ s0 = cluster[0].connect(username="zag", password="zag").session();
+ s0.receiver("q;{create:always}")
+ s0.receiver("ex;{create:always,node:{type:topic,x-declare:{type:'fanout'},x-bindings:[{exchange:'ex',queue:'q'}]}}")
+ cluster[1].wait_backup("q")
+ cluster[1].wait_backup("ex")
+ s1 = cluster[1].connect_admin().session(); # Uses Credentials above.
+ s1.sender("ex").send("foo");
+ self.assertEqual(s1.receiver("q").fetch().content, "foo")
+
+ def test_alternate_exchange(self):
+ """Verify that alternate-exchange on exchanges and queues is propagated
+ to new members of a cluster. """
+ cluster = HaCluster(self, 2)
+ s = cluster[0].connect().session()
+ # altex exchange: acts as alternate exchange
+ s.sender("altex;{create:always,node:{type:topic,x-declare:{type:'fanout'}}}")
+ # altq queue bound to altex, collect re-routed messages.
+ s.sender("altq;{create:always,node:{x-bindings:[{exchange:'altex',queue:altq}]}}")
+ # 0ex exchange with alternate-exchange altex and no queues bound
+ s.sender("0ex;{create:always,node:{type:topic, x-declare:{type:'direct', alternate-exchange:'altex'}}}")
+ # create queue q with alternate-exchange altex
+ s.sender("q;{create:always,node:{type:queue, x-declare:{alternate-exchange:'altex'}}}")
+ # create a bunch of exchanges to ensure we don't clean up prematurely if the
+ # response comes in multiple fragments.
+ for i in xrange(200): s.sender("00ex%s;{create:always,node:{type:topic}}"%i)
+
+ def verify(broker):
+ s = broker.connect().session()
+ # Verify unmatched message goes to ex's alternate.
+ s.sender("0ex").send("foo")
+ altq = s.receiver("altq")
+ self.assertEqual("foo", altq.fetch(timeout=0).content)
+ s.acknowledge()
+ # 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", altq.fetch(timeout=0).content)
+ s.acknowledge()
+
+ # Sanity check: alternate exchanges on original broker
+ verify(cluster[0])
+ # Check backup that was connected during setup.
+ cluster[1].wait_backup("0ex")
+ cluster[1].wait_backup("q")
+ cluster.bounce(0)
+ verify(cluster[1])
+ # Check a newly started backup.
+ cluster.start()
+ cluster[2].wait_backup("0ex")
+ cluster[2].wait_backup("q")
+ cluster.bounce(1)
+ verify(cluster[2])
+
def fairshare(msgs, limit, levels):
"""
Generator to return prioritised messages in expected order for a given fairshare limit
@@ -601,49 +848,135 @@ class LongTests(BrokerTest):
if d: return float(d)*60
else: return 3 # Default is to be quick
-
- def disable_test_failover(self):
+ def test_failover_send_receive(self):
"""Test failover with continuous send-receive"""
- # FIXME aconway 2012-02-03: fails due to dropped messages,
- # known issue: sending messages to new primary before
- # backups are ready. Enable when fixed.
-
- # Start a cluster, all members will be killed during the test.
- brokers = [ HaBroker(self, name=name, expect=EXPECT_EXIT_FAIL)
- for name in ["ha0","ha1","ha2"] ]
- url = ",".join([b.host_port() for b in brokers])
- for b in brokers: b.set_broker_url(url)
- brokers[0].promote()
+ brokers = HaCluster(self, 3)
# Start sender and receiver threads
- sender = NumberedSender(brokers[0], max_depth=1000, failover_updates=False)
- receiver = NumberedReceiver(brokers[0], sender=sender, failover_updates=False)
- receiver.start()
- sender.start()
- # Wait for sender & receiver to get up and running
- assert retry(lambda: receiver.received > 100)
+ n = 10
+ senders = [NumberedSender(brokers[0], max_depth=1024, failover_updates=False,
+ queue="test%s"%(i)) for i in xrange(n)]
+ receivers = [NumberedReceiver(brokers[0], sender=senders[i],
+ failover_updates=False,
+ queue="test%s"%(i)) for i in xrange(n)]
+ for r in receivers: r.start()
+ for s in senders: s.start()
+
+ def wait_passed(r, n):
+ """Wait for receiver r to pass n"""
+ def check():
+ r.check() # Verify no exceptions
+ return r.received > n
+ assert retry(check), "Stalled %s at %s"%(r.queue, n)
+
+ for r in receivers: wait_passed(r, 0)
+
# Kill and restart brokers in a cycle:
endtime = time.time() + self.duration()
i = 0
- while time.time() < endtime or i < 3: # At least 3 iterations
- sender.sender.assert_running()
- receiver.receiver.assert_running()
- port = brokers[i].port()
- brokers[i].kill()
- brokers.append(
- HaBroker(self, name="ha%d"%(i+3), broker_url=url, port=port,
- expect=EXPECT_EXIT_FAIL))
- i += 1
- brokers[i].promote()
- n = receiver.received # Verify we're still running
- def enough():
- receiver.check() # Verify no exceptions
- return receiver.received > n + 100
- assert retry(enough, timeout=5)
-
- sender.stop()
- receiver.stop()
- for b in brokers[i:]: b.kill()
+ try:
+ while time.time() < endtime or i < 3: # At least 3 iterations
+ for s in senders: s.sender.assert_running()
+ for r in receivers: r.receiver.assert_running()
+ checkpoint = [ r.received for r in receivers ]
+ # Don't kill primary till it is active and the next
+ # backup is ready, otherwise we can lose messages.
+ brokers[i%3].wait_status("active")
+ brokers[(i+1)%3].wait_status("ready")
+ brokers.bounce(i%3)
+ i += 1
+ map(wait_passed, receivers, checkpoint) # Wait for all receivers
+ except:
+ traceback.print_exc()
+ raise
+ finally:
+ for s in senders: s.stop()
+ for r in receivers: r.stop()
+ dead = []
+ for i in xrange(3):
+ if not brokers[i].is_running(): dead.append(i)
+ brokers.kill(i, False)
+ if dead: raise Exception("Brokers not running: %s"%dead)
+
+class RecoveryTests(BrokerTest):
+ """Tests for recovery after a failure."""
+
+ def test_queue_hold(self):
+ """Verify that the broker holds queues without sufficient backup,
+ i.e. does not complete messages sent to those queues."""
+
+ # We don't want backups to time out for this test, set long timeout.
+ cluster = HaCluster(self, 4, args=["--ha-backup-timeout=100000"]);
+ # Wait for the primary to be ready
+ cluster[0].wait_status("active")
+ # Create a queue before the failure.
+ s1 = cluster.connect(0).session().sender("q1;{create:always}")
+ for b in cluster: b.wait_backup("q1")
+ for i in xrange(100): s1.send(str(i))
+ # Kill primary and 2 backups
+ for i in [0,1,2]: cluster.kill(i, False)
+ cluster[3].promote() # New primary, backups will be 1 and 2
+ cluster[3].wait_status("recovering")
+
+ def assertSyncTimeout(s):
+ try:
+ s.sync(timeout=.01)
+ self.fail("Expected Timeout exception")
+ except Timeout: pass
+
+ # Create a queue after the failure
+ s2 = cluster.connect(3).session().sender("q2;{create:always}")
+
+ # Verify that messages sent are not completed
+ for i in xrange(100,200): s1.send(str(i), sync=False); s2.send(str(i), sync=False)
+ assertSyncTimeout(s1)
+ self.assertEqual(s1.unsettled(), 100)
+ assertSyncTimeout(s2)
+ self.assertEqual(s2.unsettled(), 100)
+
+ # Verify we can receive even if sending is on hold:
+ cluster[3].assert_browse("q1", [str(i) for i in range(100)+range(100,200)])
+
+ # Restart backups, verify queues are released only when both backups are up
+ cluster.restart(1)
+ assertSyncTimeout(s1)
+ self.assertEqual(s1.unsettled(), 100)
+ assertSyncTimeout(s2)
+ self.assertEqual(s2.unsettled(), 100)
+ self.assertEqual(cluster[3].ha_status(), "recovering")
+ cluster.restart(2)
+
+ # Verify everything is up to date and active
+ def settled(sender): sender.sync(); return sender.unsettled() == 0;
+ assert retry(lambda: settled(s1)), "Unsetttled=%s"%(s1.unsettled())
+ assert retry(lambda: settled(s2)), "Unsetttled=%s"%(s2.unsettled())
+ cluster[1].assert_browse_backup("q1", [str(i) for i in range(100)+range(100,200)])
+ cluster[1].assert_browse_backup("q2", [str(i) for i in range(100,200)])
+ cluster[3].wait_status("active"),
+ s1.session.connection.close()
+ s2.session.connection.close()
+
+ def test_expected_backup_timeout(self):
+ """Verify that we time-out expected backups and release held queues
+ after a configured interval. Verify backup is demoted to catch-up,
+ but can still rejoin.
+ """
+ cluster = HaCluster(self, 3, args=["--ha-backup-timeout=0.5"]);
+ cluster[0].wait_status("active") # Primary ready
+ for b in cluster[1:4]: b.wait_status("ready") # Backups ready
+ for i in [0,1]: cluster.kill(i, False)
+ cluster[2].promote() # New primary, backups will be 1 and 2
+ cluster[2].wait_status("recovering")
+ # Should not go active till the expected backup connects or times out.
+ self.assertEqual(cluster[2].ha_status(), "recovering")
+ # Messages should be held expected backup times out
+ s = cluster[2].connect().session().sender("q;{create:always}")
+ for i in xrange(100): s.send(str(i), sync=False)
+ # Verify message held initially.
+ try: s.sync(timeout=.01); self.fail("Expected Timeout exception")
+ except Timeout: pass
+ s.sync(timeout=1) # And released after the timeout.
+ self.assertEqual(cluster[2].ha_status(), "active")
if __name__ == "__main__":
shutil.rmtree("brokertest.tmp", True)
diff --git a/cpp/src/tests/ipv6_test b/cpp/src/tests/ipv6_test
index 6becfd8c96..9d1cb2acdd 100755
--- a/cpp/src/tests/ipv6_test
+++ b/cpp/src/tests/ipv6_test
@@ -19,6 +19,19 @@
# under the License.
#
+# Check whether we have any globally configured IPv6 addresses
+# - if not then we can't run the tests because ipv6 lookups won't
+# work within the qpid code. This is a deliberate feature to avoid
+# getting addresses that can't be routed by the machine.
+
+if ip -f inet6 -o addr | cut -f 9 -s -d' ' | grep global > /dev/null ; then
+ echo "IPv6 addresses configured continuing"
+else
+ echo "No global IPv6 addresses configured - skipping test"
+ exit 0
+fi
+
+
# Run a simple test over IPv6
source ./test_env.sh
diff --git a/cpp/src/tests/logging.cpp b/cpp/src/tests/logging.cpp
index 5d5bb1feef..a29714c002 100644
--- a/cpp/src/tests/logging.cpp
+++ b/cpp/src/tests/logging.cpp
@@ -258,7 +258,7 @@ QPID_AUTO_TEST_CASE(testOverhead) {
Statement statement(
Level level, const char* file="", int line=0, const char* fn=0)
{
- Statement s={0, file, line, fn, level};
+ Statement s={0, file, line, fn, level, ::qpid::log::unspecified};
return s;
}
@@ -347,11 +347,11 @@ QPID_AUTO_TEST_CASE(testLoggerStateure) {
};
opts.parse(ARGC(argv), const_cast<char**>(argv));
l.configure(opts);
- QPID_LOG(critical, "foo"); int srcline=__LINE__;
+ QPID_LOG_CAT(critical, test, "foo"); int srcline=__LINE__;
ifstream log("logging.tmp");
string line;
getline(log, line);
- string expect=(format("critical %s:%d: foo")%__FILE__%srcline).str();
+ string expect=(format("[Test] critical %s:%d: foo")%__FILE__%srcline).str();
BOOST_CHECK_EQUAL(expect, line);
log.close();
unlink("logging.tmp");
@@ -375,11 +375,11 @@ QPID_AUTO_TEST_CASE(testQuoteNonPrintable) {
char s[] = "null\0tab\tspace newline\nret\r\x80\x99\xff";
string str(s, sizeof(s));
- QPID_LOG(critical, str);
+ QPID_LOG_CAT(critical, test, str);
ifstream log("logging.tmp");
string line;
getline(log, line, '\0');
- string expect="critical null\\x00tab\tspace newline\nret\r\\x80\\x99\\xFF\\x00\n";
+ string expect="[Test] critical null\\x00tab\tspace newline\nret\r\\x80\\x99\\xFF\\x00\n";
BOOST_CHECK_EQUAL(expect, line);
log.close();
unlink("logging.tmp");
diff --git a/cpp/src/tests/ping_broker b/cpp/src/tests/ping_broker
new file mode 100755
index 0000000000..6c391027a3
--- /dev/null
+++ b/cpp/src/tests/ping_broker
@@ -0,0 +1,127 @@
+#!/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
+from optparse import OptionParser, OptionGroup
+import sys
+import locale
+import socket
+import re
+from qpid.messaging import Connection
+
+home = os.environ.get("QPID_TOOLS_HOME", os.path.normpath("/usr/share/qpid-tools"))
+sys.path.append(os.path.join(home, "python"))
+
+from qpidtoollibs import BrokerAgent
+from qpidtoollibs import Display, Header, Sorter, YN, Commas, TimeLong
+
+
+class Config:
+ def __init__(self):
+ self._host = "localhost"
+ self._connTimeout = 10
+
+config = Config()
+conn_options = {}
+
+def OptionsAndArguments(argv):
+ """ Set global variables for options, return arguments """
+
+ global config
+ global conn_options
+
+ usage = "%prog [options]"
+
+ parser = OptionParser(usage=usage)
+
+ parser.add_option("-b", "--broker", action="store", type="string", default="localhost", metavar="<url>",
+ help="URL of the broker to query")
+ parser.add_option("-t", "--timeout", action="store", type="int", default=10, metavar="<secs>",
+ help="Maximum time to wait for broker connection (in seconds)")
+ 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). SASL automatically picks the most secure available mechanism - use this option to override.")
+ parser.add_option("--ssl-certificate", action="store", type="string", metavar="<cert>", help="Client SSL certificate (PEM Format)")
+ parser.add_option("--ssl-key", action="store", type="string", metavar="<key>", help="Client SSL private key (PEM Format)")
+ parser.add_option("--ha-admin", action="store_true", help="Allow connection to a HA backup broker.")
+
+ opts, args = parser.parse_args(args=argv)
+
+ config._host = opts.broker
+ config._connTimeout = opts.timeout
+
+ if opts.sasl_mechanism:
+ conn_options['sasl_mechanisms'] = opts.sasl_mechanism
+ if opts.ssl_certificate:
+ conn_options['ssl_certfile'] = opts.ssl_certificate
+ if opts.ssl_key:
+ conn_options['ssl_key'] = opts.ssl_key
+ if opts.ha_admin:
+ conn_options['client_properties'] = {'qpid.ha-admin' : 1}
+ return args
+
+class BrokerManager:
+ def __init__(self):
+ self.brokerName = None
+ self.connection = None
+ self.broker = None
+ self.cluster = None
+
+ def SetBroker(self, brokerUrl):
+ self.url = brokerUrl
+ self.connection = Connection.establish(self.url, **conn_options)
+ self.broker = BrokerAgent(self.connection)
+
+ def Disconnect(self):
+ """ Release any allocated brokers. Ignore any failures as the tool is
+ shutting down.
+ """
+ try:
+ connection.close()
+ except:
+ pass
+
+ def Ping(self, args):
+ for sequence in range(10):
+ result = self.broker.echo(sequence, "ECHO BODY")
+ if result['sequence'] != sequence:
+ raise Exception("Invalid Sequence")
+
+
+def main(argv=None):
+
+ args = OptionsAndArguments(argv)
+ bm = BrokerManager()
+
+ try:
+ bm.SetBroker(config._host)
+ bm.Ping(args)
+ bm.Disconnect()
+ return 0
+ except KeyboardInterrupt:
+ print
+ except Exception,e:
+ print "Failed: %s - %s" % (e.__class__.__name__, e)
+
+ bm.Disconnect() # try to deallocate brokers
+ return 1
+
+if __name__ == "__main__":
+ sys.exit(main())
diff --git a/cpp/src/tests/qpid-latency-test.cpp b/cpp/src/tests/qpid-latency-test.cpp
index 20eb4568f3..2343cb1d77 100644
--- a/cpp/src/tests/qpid-latency-test.cpp
+++ b/cpp/src/tests/qpid-latency-test.cpp
@@ -359,19 +359,29 @@ void Sender::sendByRate()
}
uint64_t interval = TIME_SEC/opts.rate;
int64_t timeLimit = opts.timeLimit * TIME_SEC;
- uint64_t sent = 0, missedRate = 0;
+ uint64_t sent = 0;
AbsTime start = now();
+ AbsTime last = start;
while (true) {
AbsTime sentAt=now();
msg.getDeliveryProperties().setTimestamp(Duration(EPOCH, sentAt));
async(session).messageTransfer(arg::content=msg, arg::acceptMode=1);
if (opts.sync) session.sync();
++sent;
+ if (Duration(last, sentAt) > TIME_SEC*2) {
+ Duration t(start, now());
+ //check rate actually achieved thus far
+ uint actualRate = sent / (t/TIME_SEC);
+ //report inability to stay within 1% of desired rate
+ if (actualRate < opts.rate && opts.rate - actualRate > opts.rate/100) {
+ std::cerr << "WARNING: Desired send rate: " << opts.rate << ", actual send rate: " << actualRate << std::endl;
+ }
+ last = sentAt;
+ }
+
AbsTime waitTill(start, sent*interval);
Duration delay(sentAt, waitTill);
- if (delay < 0)
- ++missedRate;
- else
+ if (delay > 0)
sys::usleep(delay / TIME_USEC);
if (timeLimit != 0 && Duration(start, now()) > timeLimit) {
session.sync();
diff --git a/cpp/src/tests/qpid-receive.cpp b/cpp/src/tests/qpid-receive.cpp
index 6deeb566dc..7a02b871db 100644
--- a/cpp/src/tests/qpid-receive.cpp
+++ b/cpp/src/tests/qpid-receive.cpp
@@ -68,6 +68,7 @@ struct Options : public qpid::Options
bool reportHeader;
string readyAddress;
uint receiveRate;
+ std::string replyto;
Options(const std::string& argv0=std::string())
: qpid::Options("Options"),
@@ -114,6 +115,7 @@ struct Options : public qpid::Options
("report-header", qpid::optValue(reportHeader, "yes|no"), "Headers on report.")
("ready-address", qpid::optValue(readyAddress, "ADDRESS"), "send a message to this address when ready to receive")
("receive-rate", qpid::optValue(receiveRate,"N"), "Receive at rate of N messages/second. 0 means receive as fast as possible.")
+ ("reply-to", qpid::optValue(replyto, "REPLY-TO"), "specify reply-to address on response messages")
("help", qpid::optValue(help), "print this usage statement");
add(log);
}
@@ -246,6 +248,9 @@ int main(int argc, char ** argv)
s = session.createSender(msg.getReplyTo());
s.setCapacity(opts.capacity);
}
+ if (!opts.replyto.empty()) {
+ msg.setReplyTo(Address(opts.replyto));
+ }
s.send(msg);
}
if (opts.receiveRate) {
diff --git a/cpp/src/tests/run_acl_tests b/cpp/src/tests/run_acl_tests
index 3a8c03eda6..25241ad75e 100755
--- a/cpp/src/tests/run_acl_tests
+++ b/cpp/src/tests/run_acl_tests
@@ -30,9 +30,9 @@ trap stop_brokers INT TERM QUIT
start_brokers() {
../qpidd --daemon --port 0 --no-module-dir --data-dir $DATA_DIR --load-module $ACL_LIB --acl-file policy.acl --auth no --log-to-file local.log > qpidd.port
LOCAL_PORT=`cat qpidd.port`
- ../qpidd --daemon --port 0 --no-module-dir --data-dir $DATA_DIRI --load-module $ACL_LIB --acl-file policy.acl --auth no --acl-max-connect-per-ip 2 --log-to-file locali.log > qpiddi.port
+ ../qpidd --daemon --port 0 --no-module-dir --data-dir $DATA_DIRI --load-module $ACL_LIB --acl-file policy.acl --auth no --max-connections-per-ip 2 --log-to-file locali.log > qpiddi.port
LOCAL_PORTI=`cat qpiddi.port`
- ../qpidd --daemon --port 0 --no-module-dir --data-dir $DATA_DIRU --load-module $ACL_LIB --acl-file policy.acl --auth no --acl-max-connect-per-user 2 --log-to-file localu.log > qpiddu.port
+ ../qpidd --daemon --port 0 --no-module-dir --data-dir $DATA_DIRU --load-module $ACL_LIB --acl-file policy.acl --auth no --max-connections-per-user 2 --log-to-file localu.log > qpiddu.port
LOCAL_PORTU=`cat qpiddu.port`
}
diff --git a/cpp/src/tests/run_federation_tests b/cpp/src/tests/run_federation_tests
index 7735b559cf..c2ee550226 100755
--- a/cpp/src/tests/run_federation_tests
+++ b/cpp/src/tests/run_federation_tests
@@ -36,10 +36,10 @@ fi
QPIDD_CMD="../qpidd --daemon --port 0 --no-data-dir $MODULES --auth no --log-enable=info+ --log-enable=debug+:Bridge --log-to-file"
start_brokers() {
rm -f fed_local.log fed_remote.log fed_b1.log fed_b2.log
- LOCAL_PORT=$($QPIDD_CMD fed_local.log)
- REMOTE_PORT=$($QPIDD_CMD fed_remote.log)
- REMOTE_B1=$($QPIDD_CMD fed_b1.log)
- REMOTE_B2=$($QPIDD_CMD fed_b2.log)
+ LOCAL_PORT=$($QPIDD_CMD fed_local.log --federation-tag LOCAL)
+ REMOTE_PORT=$($QPIDD_CMD fed_remote.log --federation-tag REMOTE)
+ REMOTE_B1=$($QPIDD_CMD fed_b1.log --federation-tag B1)
+ REMOTE_B2=$($QPIDD_CMD fed_b2.log --federation-tag B2)
}
stop_brokers() {
diff --git a/java/management/eclipse-plugin/build-release-common.properties b/cpp/src/tests/run_ha_tests
index 7ccbd750cf..1a469646c9 100644..100755
--- a/java/management/eclipse-plugin/build-release-common.properties
+++ b/cpp/src/tests/run_ha_tests
@@ -1,5 +1,6 @@
+#!/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
@@ -16,18 +17,13 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
-#
#
-app.namever=jmx-management-console-${project.version}
-
-artifact.id=org.apache.qpid.management.ui
-mcplugin.version=${project.version}.0
-mcplugin.filename=${artifact.id}_${mcplugin.version}
-
-mcplugin.contents.dir=${module.classes}
-mcplugin.manifest=${module.manifest}
+# Make sure the python tools are available. They will be if we are building in
+# a checkoug, they may not be in a distribution.
+test -d $PYTHON_COMMANDS -a -x $PYTHON_COMMANDS/qpid-ha -a -x $PYTHON_COMMANDS/qpid-config || { echo "Skipping HA tests, qpid-ha or qpid-config not available."; exit 0; }
-jmxremote.sasl.manifest=src/main/resources/jmxremote.sasl-plugin/MANIFEST.MF
+srcdir=`dirname $0`
+$srcdir/ha_tests.py
diff --git a/cpp/src/tests/sasl_test_setup.sh b/cpp/src/tests/sasl_test_setup.sh
index 3e69c0f02b..3947986517 100755
--- a/cpp/src/tests/sasl_test_setup.sh
+++ b/cpp/src/tests/sasl_test_setup.sh
@@ -30,7 +30,7 @@ pwcheck_method: auxprop
auxprop_plugin: sasldb
sasldb_path: $PWD/sasl_config/qpidd.sasldb
sql_select: dummy select
-mech_list: ANONYMOUS PLAIN DIGEST-MD5 EXTERNAL
+mech_list: ANONYMOUS PLAIN DIGEST-MD5 EXTERNAL CRAM-MD5
EOF
# Populate temporary sasl db.
diff --git a/cpp/src/tests/ssl_test b/cpp/src/tests/ssl_test
index 91ff8eec1e..19a316a483 100755
--- a/cpp/src/tests/ssl_test
+++ b/cpp/src/tests/ssl_test
@@ -148,6 +148,11 @@ URL=$TEST_HOSTNAME:$PORT
MSG=`./qpid-receive -b $URL --connection-options '{transport:ssl,heartbeat:2}' -a "foo;{create:always}" --messages 1`
test "$MSG" = "hello again" || { echo "receive failed '$MSG' != 'hello again'"; exit 1; }
+## Test using the Python client
+echo "Testing Non-Authenticating with Python Client..."
+URL=amqps://$TEST_HOSTNAME:$PORT
+if `$top_srcdir/src/tests/ping_broker -b $URL`; then echo " Passed"; else { echo " Failed"; exit 1; }; fi
+
#### Client Authentication tests
start_authenticating_broker
diff --git a/cpp/src/tests/storePerftools/storePerftoolsSmokeTest.sh b/cpp/src/tests/storePerftools/asyncStorePerf_smoke_test.sh
index 592e1e60a0..9e8880e128 100755
--- a/cpp/src/tests/storePerftools/storePerftoolsSmokeTest.sh
+++ b/cpp/src/tests/storePerftools/asyncStorePerf_smoke_test.sh
@@ -9,11 +9,16 @@ run_test() {
fi
}
-NUM_MSGS=1000
+NUM_MSGS=10000
TEST_PROG="./asyncStorePerf"
+# Default (no args)
run_test "${TEST_PROG}"
+
+# Help
run_test "${TEST_PROG} --help"
+
+# Limited combinations of major params
for q in 1 2; do
for p in 1 2; do
for c in 1 2; do
@@ -27,25 +32,3 @@ for q in 1 2; do
done
done
done
-
-
-NUM_MSGS=1000
-TEST_PROG="./jrnl2Perf"
-
-
-run_test "${TEST_PROG}"
-
-# This test returns 1, don't use run_test until this is fixed.
-cmd="${TEST_PROG} --help"
-echo $cmd
-$cmd
-
-for q in 1 2; do
- for p in 1 2; do
- for c in 1; do # BUG - this will fail for c > 1
- run_test "./jrnl2Perf --num_queues $q --num_msgs ${NUM_MSGS} --num_enq_threads_per_queue $p --num_deq_threads_per_queue $c"
- done
- done
-done
-
-#exit 0
diff --git a/cpp/src/tests/storePerftools/jrnl2Perf_smoke_test.sh b/cpp/src/tests/storePerftools/jrnl2Perf_smoke_test.sh
new file mode 100755
index 0000000000..23fe0fea9b
--- /dev/null
+++ b/cpp/src/tests/storePerftools/jrnl2Perf_smoke_test.sh
@@ -0,0 +1,33 @@
+#!/bin/bash
+
+run_test() {
+ local cmd=$1
+ echo $cmd
+ $cmd
+ if (( $? != 0 )); then
+ exit 1
+ fi
+}
+
+NUM_MSGS=10000
+TEST_PROG="./jrnl2Perf"
+
+# Default (no args)
+run_test "${TEST_PROG}"
+
+# Help
+# This test returns 1, don't use run_test until this is fixed.
+cmd="${TEST_PROG} --help"
+echo $cmd
+$cmd
+
+# Limited combinations of major params
+for q in 1 2; do
+ for p in 1 2; do
+ for c in 1; do # BUG - this will fail for c > 1
+ run_test "./jrnl2Perf --num_queues $q --num_msgs ${NUM_MSGS} --num_enq_threads_per_queue $p --num_deq_threads_per_queue $c"
+ done
+ done
+done
+
+#exit 0
diff --git a/cpp/src/tests/txjob.cpp b/cpp/src/tests/txjob.cpp
index a7a905c1b7..29394c3415 100644
--- a/cpp/src/tests/txjob.cpp
+++ b/cpp/src/tests/txjob.cpp
@@ -38,9 +38,9 @@ namespace tests {
struct Args : public qpid::TestOptions
{
- string workQueue;
- string source;
- string dest;
+ std::string workQueue;
+ std::string source;
+ std::string dest;
uint messages;
uint jobs;
bool quit;
diff --git a/cpp/src/tests/txshift.cpp b/cpp/src/tests/txshift.cpp
index 882d3716d8..bf85bee986 100644
--- a/cpp/src/tests/txshift.cpp
+++ b/cpp/src/tests/txshift.cpp
@@ -39,7 +39,7 @@ namespace tests {
struct Args : public qpid::TestOptions
{
- string workQueue;
+ std::string workQueue;
size_t workers;
Args() : workQueue("txshift-control"), workers(1)
diff --git a/cpp/xml/cluster.xml b/cpp/xml/cluster.xml
index f9b8caf185..09434ea37b 100644
--- a/cpp/xml/cluster.xml
+++ b/cpp/xml/cluster.xml
@@ -179,6 +179,7 @@
<field name="position" type="sequence-no"/>
<field name="used-msg-credit" type="uint32"/>
<field name="used-byte-credit" type="uint32"/>
+ <field name="deliveryCount" type="uint32"/>
</control>
<!-- Delivery-record for outgoing messages sent but not yet accepted. -->
diff --git a/doc/book/src/cpp-broker/.gitignore b/doc/book/src/cpp-broker/.gitignore
new file mode 100644
index 0000000000..1f57b975cd
--- /dev/null
+++ b/doc/book/src/cpp-broker/.gitignore
@@ -0,0 +1 @@
+/output
diff --git a/doc/book/src/cpp-broker/Active-Passive-Cluster.xml b/doc/book/src/cpp-broker/Active-Passive-Cluster.xml
index 5f5823bdd2..805ceb06e0 100644
--- a/doc/book/src/cpp-broker/Active-Passive-Cluster.xml
+++ b/doc/book/src/cpp-broker/Active-Passive-Cluster.xml
@@ -22,42 +22,124 @@ under the License.
<section id="chap-Messaging_User_Guide-Active_Passive_Cluster">
- <title>Active-passive Messaging Clusters (Preview)</title>
+ <title>Active-passive Messaging Clusters</title>
<section>
<title>Overview</title>
<para>
- This release provides a preview of a new module for High Availability (HA). The new module is
- not yet complete or ready for production use. It being made available so that users can
- experiment with the new approach and provide feedback early in the development process.
- Feedback should go to <ulink url="mailto:user@qpid.apache.org">dev@qpid.apache.org</ulink>.
+
+ The High Availability (HA) module provides
+ <firstterm>active-passive</firstterm>, <firstterm>hot-standby</firstterm>
+ messaging clusters to provide fault tolerant message delivery.
</para>
<para>
- The old cluster module takes an <firstterm>active-active</firstterm> approach, i.e. all the
- brokers in a cluster are able to handle client requests simultaneously. The new HA module
- takes an <firstterm>active-passive</firstterm>, <firstterm>hot-standby</firstterm> approach.
+ In an active-passive cluster only one broker, known as the
+ <firstterm>primary</firstterm>, is active and serving clients at a time. The other
+ brokers are standing by as <firstterm>backups</firstterm>. Changes on the primary
+ are replicated to all the backups so they are always up-to-date or "hot". Backup
+ brokers reject client connection attempts, to enforce the requirement that clients
+ only connect to the primary.
</para>
<para>
- In an active-passive cluster only one broker, known as the <firstterm>primary</firstterm>, is
- active and serving clients at a time. The other brokers are standing by as
- <firstterm>backups</firstterm>. Changes on the primary are immediately replicated to all the
- backups so they are always up-to-date or "hot". If the primary fails, one of the backups is
- promoted to take over as the new primary. Clients fail-over to the new primary
- automatically. If there are multiple backups, the backups also fail-over to become backups of
- the new primary. Backup brokers reject connection attempts, to enforce the requirement that
- only the primary be active.
+ If the primary fails, one of the backups is promoted to take over as the new
+ primary. Clients fail-over to the new primary automatically. If there are multiple
+ backups, the other backups also fail-over to become backups of the new primary.
</para>
<para>
- This approach depends on an external <firstterm>cluster resource manager</firstterm> to detect
- failures and choose the primary. <ulink
+ This approach relies on an external <firstterm>cluster resource manager</firstterm>
+ to detect failures, choose the new primary and handle network partitions. <ulink
url="https://fedorahosted.org/cluster/wiki/RGManager">Rgmanager</ulink> is supported
initially, but others may be supported in the future.
</para>
<section>
- <title>Why the new approach?</title>
+ <title>Avoiding message loss</title>
+ <para>
+ In order to avoid message loss, the primary broker <emphasis>delays
+ acknowledgment</emphasis> of messages received from clients until the
+ message has been replicated to and acknowledged by all of the back-up
+ brokers.
+ </para>
+ <para>
+ Clients buffer unacknowledged messages and re-send them in the event of
+ a fail-over.
+ <footnote>
+ <para>
+ Clients must use "at-least-once" reliability to enable re-send of unacknowledged
+ messages. This is the default behavior, no options need be set to enable it. For
+ details of client addressing options see &#34;Using the Qpid Messaging API&#34;
+ in <citetitle>Programming in Apache Qpid</citetitle>
+ </para>
+ </footnote>
+ If the primary crashes before a message is replicated to
+ all the backups, the client will re-send the message when it fails over
+ to the new primary.
+ </para>
+ <para>
+ Note that this means it is possible for messages to be
+ <emphasis>duplicated</emphasis>. In the event of a failure it is
+ possible for a message to be both received by the backup that becomes
+ the new primary <emphasis>and</emphasis> re-sent by the client.
+ </para>
+ <para>
+ When a new primary is promoted after a fail-over it is initially in
+ "recovering" mode. In this mode, it delays acknowledgment of messages
+ on behalf of all the backups that were connected to the previous
+ primary. This protects those messages against a failure of the new
+ primary until the backups have a chance to connect and catch up.
+ </para>
+ <variablelist>
+ <title>Status of a HA broker</title>
+ <varlistentry>
+ <term>Joining</term>
+ <listitem>
+ <para>
+ Initial status of a new broker that has not yet connected to the primary.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>Catch-up</term>
+ <listitem>
+ <para>
+ A backup broker that is connected to the primary and catching up
+ on queues and messages.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>Ready</term>
+ <listitem>
+ <para>
+ A backup broker that is fully caught-up and ready to take over as
+ primary.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>Recovering</term>
+ <listitem>
+ <para>
+ The newly-promoted primary, waiting for backups to connect and catch up.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>Active</term>
+ <listitem>
+ <para>
+ The active primary broker with all backups connected and caught-up.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </section>
+ <section>
+ <title>Replacing the old cluster module</title>
<para>
- The new active-passive approach has several advantages compared to the
- existing active-active cluster module.
+ The High Availability (HA) module replaces the previous
+ <firstterm>active-active</firstterm> cluster module. The new active-passive
+ approach has several advantages compared to the existing active-active cluster
+ module.
<itemizedlist>
<listitem>
It does not depend directly on openais or corosync. It does not use multicast
@@ -77,69 +159,42 @@ under the License.
virtual IP addresses.
</listitem>
<listitem>
- Improved performance and scalability due to better use of multiple CPU s
+ Improved performance and scalability due to better use of multiple CPUs
</listitem>
</itemizedlist>
</para>
</section>
<section>
<title>Limitations</title>
-
- <para>
- There are a number of known limitations in the current preview implementation. These
- will be fixed in the production versions.
- </para>
-
<itemizedlist>
<listitem>
- Transactional changes to queue state are not replicated atomically. If the primary crashes
- during a transaction, it is possible that the backup could contain only part of the
- changes introduced by a transaction.
- </listitem>
- <listitem>
- During a fail-over one backup is promoted to primary and any other backups switch to
- the new primary. Messages sent to the new primary before all the backups have
- switched could be lost if the new primary itself fails before all the backups have
- switched.
- </listitem>
- <listitem>
- Acknowledgments are confirmed to clients before the message has been dequeued
- from replicas or indeed from the local store if that is asynchronous.
- </listitem>
- <listitem>
- When used with a persistent store: if the entire cluster fails, there are no tools to help
- identify the most recent store.
+ Transactional changes to queue state are not replicated atomically. If the
+ primary crashes during a transaction, it is possible that the backup could
+ contain only part of the changes introduced by a transaction.
</listitem>
<listitem>
- A persistent broker must have its store erased before joining an existing cluster.
- In the production version a persistent broker will be able to load its store and
- avoid downloading messages that are in the store from the primary.
+ Not yet integrated with the persistent store. A persistent broker must have its
+ store erased before joining an existing cluster. If the entire cluster fails,
+ there are no tools to help identify the most recent store. In the future a
+ persistent broker will be able to use its stored messages to avoid downloading
+ messages from the primary when joining a cluster.
</listitem>
<listitem>
Configuration changes (creating or deleting queues, exchanges and bindings) are
- replicated asynchronously. Management tools used to make changes will consider the
- change complete when it is complete on the primary, it may not yet be replicated
- to all the backups.
- </listitem>
- <listitem>
- Deletions made immediately after a failure (before all the backups are ready) may
- be lost on a backup. Queues, exchange or bindings that were deleted on the primary could
- re-appear if that backup is promoted to primary on a subsequent failure.
- </listitem>
- <listitem>
- Better control is needed over which queues/exchanges are replicated and which are not.
- </listitem>
- <listitem>
- There are some known issues affecting performance, both the throughput of
- replication and the time taken for backups to fail-over. Performance will improve
- in the production version.
+ replicated asynchronously. Management tools used to make changes will consider
+ the change complete when it is complete on the primary, it may not yet be
+ replicated to all the backups.
</listitem>
<listitem>
- Federated links from the primary will be lost in fail over, they will not be
- re-connected on the new primary. Federation links to the primary can fail over.
+ Deletions made immediately after a failure (before all the backups are ready)
+ may be lost on a backup. Queues, exchange or bindings that were deleted on the
+ primary could re-appear if that backup is promoted to primary on a subsequent
+ failure.
</listitem>
<listitem>
- Only plain FIFO queues can be replicated. LVQ and ring queues are not yet supported.
+ Federated links <emphasis>from</emphasis> the primary will be lost in fail over,
+ they will not be re-connected to the new primary. Federation links
+ <emphasis>to</emphasis> the primary can fail over.
</listitem>
</itemizedlist>
</section>
@@ -162,7 +217,7 @@ under the License.
virtual IP addresses for clients or brokers.
</para>
</section>
-
+
<section>
<title>Configuring the Brokers</title>
<para>
@@ -170,10 +225,10 @@ under the License.
default. The following broker options are available for the HA module.
</para>
<table frame="all" id="ha-broker-options">
- <title>Options for High Availability Messaging Cluster</title>
+ <title>Broker Options for High Availability Messaging Cluster</title>
<tgroup align="left" cols="2" colsep="1" rowsep="1">
- <colspec colname="c1" colwidth="1*"/>
- <colspec colname="c2" colwidth="3*"/>
+ <colspec colname="c1"/>
+ <colspec colname="c2"/>
<thead>
<row>
<entry align="center" nameend="c2" namest="c1">
@@ -184,7 +239,7 @@ under the License.
<tbody>
<row>
<entry>
- <literal>--ha-cluster <replaceable>yes|no</replaceable></literal>
+ <literal>ha-cluster <replaceable>yes|no</replaceable></literal>
</entry>
<entry>
Set to "yes" to have the broker join a cluster.
@@ -192,7 +247,7 @@ under the License.
</row>
<row>
<entry>
- <literal>--ha-brokers <replaceable>URL</replaceable></literal>
+ <literal>ha-brokers-url <replaceable>URL</replaceable></literal>
</entry>
<entry>
<para>
@@ -201,54 +256,78 @@ under the License.
<para>
The full format of the URL is given by this grammar:
<programlisting>
- url = ["amqp:"][ user ["/" password] "@" ] addr ("," addr)*
- addr = tcp_addr / rmda_addr / ssl_addr / ...
- tcp_addr = ["tcp:"] host [":" port]
- rdma_addr = "rdma:" host [":" port]
- ssl_addr = "ssl:" host [":" port]'
+url = ["amqp:"][ user ["/" password] "@" ] addr ("," addr)*
+addr = tcp_addr / rmda_addr / ssl_addr / ...
+tcp_addr = ["tcp:"] host [":" port]
+rdma_addr = "rdma:" host [":" port]
+ssl_addr = "ssl:" host [":" port]'
</programlisting>
</para>
</footnote>
- used by brokers to connect to each other. If you use a virtual IP address
- then this is a single address, for example
- <literal>amqp:20.0.20.200</literal>. If you do not use a virtual IP
- address then the URL must list all the addresses of brokers in the
- cluster, for example <literal>amqp:node1,node2,node3</literal>
+ used by cluster brokers to connect to each other. The URL can
+ contain a list of all the broker addresses or it can contain a single
+ virtual IP address. If a list is used it is comma separated, for example
+ <literal>amqp:node1.exaple.com,node2.exaple.com,node3.exaple.com</literal>
</para>
</entry>
</row>
<row>
- <entry><literal>--ha-public-brokers <replaceable>URL</replaceable></literal> </entry>
+ <entry><literal>ha-public-url <replaceable>URL</replaceable></literal> </entry>
<entry>
<para>
- The URL used by clients to connect to the brokers. This has the same
- format as the <literal>--ha-brokers</literal> URL above.
+ The URL that is advertised to clients. This defaults to the
+ <literal>ha-brokers-url</literal> URL above, and has the same format. A
+ virtual IP address is recommended for the public URL as it simplifies
+ deployment and hides changes to the cluster membership from clients.
</para>
<para>
- If this option is not set, clients will use the same URL as brokers.
This option allows you to put client traffic on a different network from
broker traffic, which is recommended.
</para>
</entry>
</row>
<row>
- <entry><literal>--ha-replicate</literal></entry>
+ <entry><literal>ha-replicate </literal><replaceable>VALUE</replaceable></entry>
<foo/>
<entry>
- <para>
+ <para>
Specifies whether queues and exchanges are replicated by default.
- For details see <xref linkend="creating-replicated"/>
+ <replaceable>VALUE</replaceable> is one of: <literal>none</literal>,
+ <literal>configuration</literal>, <literal>all</literal>.
+ For details see <xref linkend="ha-creating-replicated"/>.
</para>
</entry>
</row>
<row>
<entry>
- <para><literal>--ha-username <replaceable>USER</replaceable></literal></para>
- <para><literal>--ha-password <replaceable>PASS</replaceable></literal></para>
- <para><literal>--ha-mechanism <replaceable>MECH</replaceable></literal></para>
+ <para><literal>ha-username <replaceable>USER</replaceable></literal></para>
+ <para><literal>ha-password <replaceable>PASS</replaceable></literal></para>
+ <para><literal>ha-mechanism <replaceable>MECH</replaceable></literal></para>
+ </entry>
+ <entry>
+ Authentication settings used by HA brokers to connect to each other.
+ If you are using authorization
+ (<xref linkend="sect-Messaging_User_Guide-Security-Authorization"/>)
+ then this user must have all permissions.
+ </entry>
+ </row>
+ <row>
+ <entry><literal>ha-backup-timeout <replaceable>SECONDS</replaceable></literal> </entry>
+ <entry>
+ <para>
+ Maximum time that a recovering primary will wait for an expected
+ backup to connect and become ready.
+ </para>
</entry>
+ </row>
+ <row>
+ <entry><literal>link-maintenance-interval <replaceable>SECONDS</replaceable></literal></entry>
<entry>
- Authentication settings used by brokers to connect to each other.
+ <para>
+ Interval for the broker to check link health and re-connect links if need
+ be. If you want brokers to fail over quickly you can set this to a
+ fraction of a second, for example: 0.1.
+ </para>
</entry>
</row>
</tbody>
@@ -256,7 +335,7 @@ under the License.
</table>
<para>
To configure a HA cluster you must set at least <literal>ha-cluster</literal> and
- <literal>ha-brokers</literal>.
+ <literal>ha-brokers-url</literal>.
</para>
</section>
@@ -270,9 +349,9 @@ under the License.
</para>
<para>
The resource manager is responsible for starting the <command>qpidd</command> broker
- on each node in the cluster. The resource manager <firstterm>promotes</firstterm>
+ on each node in the cluster. The resource manager then <firstterm>promotes</firstterm>
one of the brokers to be the primary. The other brokers connect to the primary as
- backups, using the URL provided in the <literal>ha-brokers</literal> configuration
+ backups, using the URL provided in the <literal>ha-brokers-url</literal> configuration
option.
</para>
<para>
@@ -303,7 +382,7 @@ under the License.
clustered services using <command>cman</command> and
<command>rgmanager</command>. It will show you how to configure an active-passive,
hot-standby <command>qpidd</command> HA cluster with <command>rgmanager</command>.
- </para>
+ </para>
<para>
You must provide a <literal>cluster.conf</literal> file to configure
<command>cman</command> and <command>rgmanager</command>. Here is
@@ -398,7 +477,7 @@ NOTE: fencing is not shown, you must configure fencing appropriately for your cl
<para>
The <literal>resources</literal> section also defines a pair of virtual IP
addresses on different sub-nets. One will be used for broker-to-broker
- communication, the other for client-to-broker.
+ communication, the other for client-to-broker.
</para>
<para>
To take advantage of the virtual IP addresses, <filename>qpidd.conf</filename>
@@ -406,8 +485,8 @@ NOTE: fencing is not shown, you must configure fencing appropriately for your cl
</para>
<programlisting>
ha-cluster=yes
- ha-brokers=20.0.20.200
- ha-public-brokers=20.0.10.200
+ ha-brokers-url=20.0.20.200
+ ha-public-url=20.0.10.200
</programlisting>
<para>
This configuration specifies that backup brokers will use 20.0.20.200
@@ -436,21 +515,22 @@ NOTE: fencing is not shown, you must configure fencing appropriately for your cl
<section>
<title>Broker Administration Tools</title>
<para>
- Normally, clients are not allowed to connect to a backup broker. However management tools are
- allowed to connect to a backup brokers. If you use these tools you <emphasis>must
- not</emphasis> add or remove messages from replicated queues, or delete replicated queues or
- exchanges as this will corrupt the replication process and may cause message loss.
+ Normally, clients are not allowed to connect to a backup broker. However
+ management tools are allowed to connect to a backup brokers. If you use
+ these tools you <emphasis>must not</emphasis> add or remove messages from
+ replicated queues, nor create or delete replicated queues or exchanges as
+ this will disrupt the replication process and may cause message loss.
</para>
<para>
<command>qpid-ha</command> allows you to view and change HA configuration settings.
</para>
<para>
The tools <command>qpid-config</command>, <command>qpid-route</command> and
- <command>qpid-stat</command> will connect to a backup if you pass the flag <command>--ha-admin</command> on the
+ <command>qpid-stat</command> will connect to a backup if you pass the flag <command>ha-admin</command> on the
command line.
</para>
</section>
-
+
<section id="ha-creating-replicated">
<title>Creating replicated queues and exchanges</title>
<para>
@@ -459,7 +539,8 @@ NOTE: fencing is not shown, you must configure fencing appropriately for your cl
option. It has one of the following values:
<itemizedlist>
<listitem>
- <firstterm>all</firstterm>: Replicate everything automatically: queues, exchanges, bindings and messages.
+ <firstterm>all</firstterm>: Replicate everything automatically: queues,
+ exchanges, bindings and messages.
</listitem>
<listitem>
<firstterm>configuration</firstterm>: Replicate the existence of queues,
@@ -541,10 +622,12 @@ NOTE: fencing is not shown, you must configure fencing appropriately for your cl
membership.
</para>
<para>
- Suppose your cluster has 3 nodes: <literal>node1</literal>, <literal>node2</literal>
- and <literal>node3</literal> all using the default AMQP port. To connect a client you
- need to specify the address(es) and set the <literal>reconnect</literal> property to
- <literal>true</literal>. Here's how to connect each type of client:
+ Suppose your cluster has 3 nodes: <literal>node1</literal>,
+ <literal>node2</literal> and <literal>node3</literal> all using the
+ default AMQP port, and you are not using a virtual IP address. To connect
+ a client you need to specify the address(es) and set the
+ <literal>reconnect</literal> property to <literal>true</literal>. The
+ following sub-sections show how to connect each type of client.
</para>
<section>
<title>C++ clients</title>
@@ -655,6 +738,89 @@ NOTE: fencing is not shown, you must configure fencing appropriately for your cl
</screen>
</section>
</section>
+
+ <section>
+ <title>Security.</title>
+ <para>
+ You can secure your cluster using the authentication and authorization features
+ described in <xref linkend="chap-Messaging_User_Guide-Security"/>.
+ </para>
+ <para>
+ Backup brokers connect to the primary broker and subscribe for management
+ events and queue contents. You can specify the identity used to connect
+ to the primary with the following options:
+ </para>
+ <table frame="all" id="ha-broker-security-options">
+ <title>Security options for High Availability Messaging Cluster</title>
+ <tgroup align="left" cols="2" colsep="1" rowsep="1">
+ <colspec colname="c1" colwidth="1*"/>
+ <colspec colname="c2" colwidth="3*"/>
+ <thead>
+ <row>
+ <entry align="center" nameend="c2" namest="c1">
+ Security options for High Availability Messaging Cluster
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para><literal>ha-username <replaceable>USER</replaceable></literal></para>
+ <para><literal>ha-password <replaceable>PASS</replaceable></literal></para>
+ <para><literal>ha-mechanism <replaceable>MECH</replaceable></literal></para>
+ </entry>
+ <entry>
+ Authentication settings used by HA brokers to connect to each other.
+ If you are using authorization
+ (<xref linkend="sect-Messaging_User_Guide-Security-Authorization"/>)
+ then this user must have all permissions.
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <para>
+ This identity is also used to authorize actions taken on the backup broker to replicate
+ from the primary, for example to create queues or exchanges.
+ </para>
+ </section>
+
+ <section>
+ <title>Integrating with other Cluster Resource Managers</title>
+ <para>
+ To integrate with a different resource manager you must configure it to:
+ <itemizedlist>
+ <listitem>Start a qpidd process on each node of the cluster.</listitem>
+ <listitem>Restart qpidd if it crashes.</listitem>
+ <listitem>Promote exactly one of the brokers to primary.</listitem>
+ <listitem>Detect a failure and promote a new primary.</listitem>
+ </itemizedlist>
+ </para>
+ <para>
+ The <command>qpid-ha</command> command allows you to check if a broker is primary,
+ and to promote a backup to primary.
+ </para>
+ <para>
+ To test if a broker is the primary:
+ <programlisting>
+ qpid-ha -b <replaceable>broker-address</replaceable> status --expect=primary
+ </programlisting>
+ This command will return 0 if the broker at <replaceable>broker-address</replaceable>
+ is the primary, non-0 otherwise.
+ </para>
+ <para>
+ To promote a broker to primary:
+ <programlisting>
+ qpid-ha -b <replaceable>broker-address</replaceable> promote
+ </programlisting>
+ </para>
+ <para>
+ <command>qpid-ha --help</command> gives information on other commands and options available.
+ You can also use <command>qpid-ha</command> to manually examine and promote brokers. This
+ can be useful for testing failover scenarios without having to set up a full resource manager,
+ or to simulate a cluster on a single node. For deployment, a resource manager is required.
+ </para>
+ </section>
</section>
<!-- LocalWords: scalability rgmanager multicast RGManager mailto LVQ qpidd IP dequeued Transactional username
diff --git a/doc/book/src/cpp-broker/Cheat-Sheet-for-configuring-Queue-Options.xml b/doc/book/src/cpp-broker/Cheat-Sheet-for-configuring-Queue-Options.xml
index d50948e0cc..78272b7ef4 100644
--- a/doc/book/src/cpp-broker/Cheat-Sheet-for-configuring-Queue-Options.xml
+++ b/doc/book/src/cpp-broker/Cheat-Sheet-for-configuring-Queue-Options.xml
@@ -176,7 +176,7 @@
ignored.
</para></listitem>
</itemizedlist><para>
- A fully worked <xref linkend="LVQ-Examplesource"/> can be found here
+ A fully worked <xref linkend="LVQ-Example"/> can be found here
</para>
<!--h3--></section>
<section role="h3" id="CheatSheetforconfiguringQueueOptions-Settingadditionalbehaviors"><title>
diff --git a/doc/book/src/java-broker/AMQP-Messaging-Broker-Java-Book.xml b/doc/book/src/java-broker/AMQP-Messaging-Broker-Java-Book.xml
index 0bb40052cd..54c2984d0a 100644
--- a/doc/book/src/java-broker/AMQP-Messaging-Broker-Java-Book.xml
+++ b/doc/book/src/java-broker/AMQP-Messaging-Broker-Java-Book.xml
@@ -1,6 +1,6 @@
<?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
@@ -31,7 +31,7 @@
<listitem><para>Implemented in Java - Fully JMS compliant, runs on any Java platform.</para></listitem>
</itemizedlist>
- <para>Both AMQP messaging brokers support clients in multiple languages, as long as the messaging client and the messaging broker use the same version of AMQP. See <link linkend="AMQP-Compatibility"/> to see which messaging clients work with each broker.</para>
+ <para>Both AMQP messaging brokers support clients in multiple languages, as long as the messaging client and the messaging broker use the same version of AMQP.</para>
<para>This manual contains information specific to the broker that is implemented in Java.</para>
</preface>
@@ -44,6 +44,7 @@
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="Java-Environment-Variables.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="Qpid-Troubleshooting-Guide.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="Broker-Configuration-Guide.xml"/>
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="HA-Guide.xml"/>
</chapter>
<chapter id="Qpid-Java-Broker-HowTos">
@@ -58,8 +59,8 @@
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="Debug-using-log4j.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="How-to-Tune-M3-Java-Broker-Performance.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="Qpid-Java-Build-How-To.xml"/>
- <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="Use-Priority-Queues.xml"/>
- <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="How-to-Use-SlowConsumerDisconnect.xml"/>
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="OtherQueueTypes.xml"/>
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="How-to-Use-SlowConsumerDisconnect.xml"/>
</chapter>
@@ -67,7 +68,6 @@
<chapter id="QpidJavaBroker-ManagementTools">
<title>Management Tools</title>
- <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="MessageStore-Tool.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="Qpid-Java-Broker-Management-CLI.xml"/>
</chapter>
</book>
diff --git a/doc/book/src/java-broker/Broker-Configuration-Guide.xml b/doc/book/src/java-broker/Broker-Configuration-Guide.xml
index 28a2e9f2d3..558d17c63c 100644
--- a/doc/book/src/java-broker/Broker-Configuration-Guide.xml
+++ b/doc/book/src/java-broker/Broker-Configuration-Guide.xml
@@ -23,6 +23,6 @@
<section id="Java-Broker-Configuration-Guide">
<title>Broker Configuration Guide </title>
- <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
- href="Topic-Configuration.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="Topic-Configuration.xml"/>
</section>
diff --git a/doc/book/src/java-broker/HA-Guide.xml b/doc/book/src/java-broker/HA-Guide.xml
new file mode 100644
index 0000000000..429f2f76c2
--- /dev/null
+++ b/doc/book/src/java-broker/HA-Guide.xml
@@ -0,0 +1,990 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE urls [
+<!ENTITY oracleBdbProductOverviewUrl "http://www.oracle.com/technetwork/products/berkeleydb/overview/index-093405.html">
+<!ENTITY oracleBdbProductVersion "5.0.48">
+<!ENTITY oracleBdbRepGuideUrl "http://oracle.com/cd/E17277_02/html/ReplicationGuide/">
+<!ENTITY oracleBdbJavaDocUrl "http://docs.oracle.com/cd/E17277_02/html/java/">
+<!ENTITY oracleJdkDocUrl "http://oracle.com/javase/6/docs/api/">
+]>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT 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>
+ <title>High Availability</title>
+ <section role="h3" id="HAGeneralIntroduction">
+ <title>General Introduction</title>
+ <para>The term High Availability (HA) usually refers to having a number of instances of a service such as a Message Broker
+ available so that should a service unexpectedly fail, or requires to be shutdown for maintenance, users may quickly connect
+ to another instance and continue their work with minimal interuption. HA is one way to make a overall system more resilient
+ by eliminating a single point of failure from a system.</para>
+ <para>HA offerings are usually categorised as <emphasis role="bold">Active/Active</emphasis> or <emphasis role="bold">Active/Passive</emphasis>.
+ An Active/Active system is one where all nodes within the cluster are usuaully available for use by clients all of the time. In an
+ Active/Passive system, one only node within the cluster is available for use by clients at any one time, whilst the others are in
+ some kind of standby state, awaiting to quickly step-in in the event the active node becomes unavailable.
+ </para>
+ </section>
+ <section role="h3" id="HAOfferingsOfJavaBroker">
+ <title>HA offerings of the Java Broker</title>
+ <para>The Java Broker's HA offering became available at release <emphasis role="bold">0.18</emphasis>. HA is provided by way of the HA
+ features built into the <ulink url="&oracleBdbProductOverviewUrl;">Java Edition of the Berkley Database (BDB JE)</ulink> and as such
+ is currently only available to Java Broker users who use the optional BDB JE based persistence store. This
+ <emphasis role="bold">optional</emphasis> store requires the use of BDB JE which is licensed under the Sleepycat Licence, which is
+ not compatible with the Apache Licence and thus BDB JE is not distributed with Qpid. Users who elect to use this optional store for
+ the broker have to provide this dependency.</para>
+ <para>HA in the Java Broker provides an <emphasis role="bold">Active/Passive</emphasis> mode of operation with Virtual hosts being
+ the unit of replication. The Active node (referred to as the <emphasis role="bold">Master</emphasis>) accepts all work from all the clients.
+ The Passive nodes (referred to as <emphasis role="bold">Replicas</emphasis>) are unavailable for work: the only task they must perform is
+ to remain in synch with the Master node by consuming a replication stream containing all data and state.</para>
+ <para>If the Master node fails, a Replica node is elected to become the new Master node. All clients automatically failover
+ <footnote><para>The automatic failover feature is available only for AMQP connections from the Java client. Management connections (JMX)
+ do not current offer this feature.</para></footnote> to the new Master and continue their work.</para>
+ <para>The Java Broker HA solution is incompatible with the HA solution offered by the CPP Broker. It is not possible to co-locate Java and CPP
+ Brokers within the same cluster.</para>
+ <para>HA is not currently available for those using the the <emphasis role="bold">Derby Store</emphasis> or <emphasis role="bold">Memory
+ Message Store</emphasis>.</para>
+ </section>
+ <section role="h3" id="HATwoNodeCluster">
+ <title>Two Node Cluster</title>
+ <section role="h4">
+ <title>Overview</title>
+ <para>In this HA solution, a cluster is formed with two nodes. one node serves as
+ <emphasis role="bold">master</emphasis> and the other is a <emphasis role="bold">replica</emphasis>.
+ </para>
+ <para>All data and state required for the operation of the virtual host is automatically sent from the
+ master to the replica. This is called the replication stream. The master virtual host confirms each
+ message is on the replica before the client transaction completes. The exact way the client awaits
+ for the master and replica is gorverned by the <link linkend="HADurabilityGuarantee">durability</link>
+ configuration, which is discussed later. In this way, the replica remains ready to take over the
+ role of the master if the master becomes unavailable.
+ </para>
+ <para>It is important to note that there is an inherent limitation of two node clusters is that
+ the replica node cannot make itself master automatically in the event of master failure. This
+ is because the replica has no way to distinguish between a network partition (with potentially
+ the master still alive on the other side of the partition) and the case of genuine master failure.
+ (If the replica were to elect itself as master, the cluster would run the risk of a
+ <ulink url="http://en.wikipedia.org/wiki/Split-brain_(computing)">split-brain</ulink> scenario).
+ In the event of a master failure, a third party must designate the replica as primary. This process
+ is described in more detail later.
+ </para>
+ <para>Clients connect to the cluster using a <link linkend="HAClientFailover">failover url</link>.
+ This allows the client to maintain a connection to the master in a way that is transparent
+ to the client application.</para>
+ </section>
+ <section role="h4">
+ <title>Depictions of cluster operation</title>
+ <para>In this section, the operation of the cluster is depicted through a series of figures
+ supported by explanatory text.</para>
+ <figure>
+ <title>Key for figures</title>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/HA-2N-Key.png" format="PNG" scalefit="1"/>
+ </imageobject>
+ <textobject>
+ <phrase>Key to figures</phrase>
+ </textobject>
+ </mediaobject>
+ </figure>
+ <section role="h5" id="HATwoNodeNormalOperation">
+ <title>Normal Operation</title>
+ <para>The figure below illustrates normal operation. Clients connecting to the cluster by way
+ of the failover URL achieve a connection to the master. As clients perform work (message
+ production, consumption, queue creation etc), the master additionally sends this data to the
+ replica over the network.</para>
+ <figure>
+ <title>Normal operation of a two-node cluster</title>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/HA-2N-Normal.png" format="PNG" scalefit="1"/>
+ </imageobject>
+ <textobject>
+ <phrase>Normal operation</phrase>
+ </textobject>
+ </mediaobject>
+ </figure>
+ </section>
+ <section role="h5" id="HATwoNodeMasterFailure">
+ <title>Master Failure and Recovery</title>
+ <para>The figure below illustrates a sequence of events whereby the master suffers a failure
+ and the replica is made the master to allow the clients to continue to work. Later the
+ old master is repaired and comes back on-line in replica role.</para>
+ <para>The item numbers in this list apply to the numbered boxes in the figure below.</para>
+ <orderedlist>
+ <listitem>
+ <para>System operating normally</para>
+ </listitem>
+ <listitem>
+ <para>Master suffers a failure and disconnects all clients. Replica realises that it is no
+ longer in contact with master. Clients begin to try to reconnect to the cluster, although these
+ connection attempts will fail at this point.</para>
+ </listitem>
+ <listitem>
+ <para>A third-party (an operator, a script or a combination of the two) verifies that the master has truely
+ failed <emphasis role="bold">and is no longer running</emphasis>. If it has truely failed, the decision is made
+ to designate the replica as primary, allowing it to assume the role of master despite the other node being down.
+ This primary designation is performed using <link linkend="HAJMXAPI">JMX</link>.</para>
+ </listitem>
+ <listitem>
+ <para>Client connections to the new master succeed and the <emphasis role="bold">service is restored
+ </emphasis>, albeit without a replica.</para>
+ </listitem>
+ <listitem>
+ <para>The old master is repaired and brought back on-line. It automatically rejoins the cluster
+ in the <emphasis role="bold">replica</emphasis> role.</para>
+ </listitem>
+ </orderedlist>
+ <figure>
+ <title>Failure of master and recovery sequence</title>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/HA-2N-MasterFail.png" format="PNG" scalefit="1"/>
+ </imageobject>
+ <textobject>
+ <phrase>Failure of master and subsequent recovery sequence</phrase>
+ </textobject>
+ </mediaobject>
+ </figure>
+ </section>
+ <section role="h5" id="HATwoNodeReplicaFailure">
+ <title>Replica Failure and Recovery</title>
+ <para>The figure that follows illustrates a sequence of events whereby the replica suffers a failure
+ leaving the master to continue processing alone. Later the replica is repaired and is restarted.
+ It rejoins the cluster so that it is once again ready to take over in the event of master failure.</para>
+ <para>The behavior of the replica failure case is governed by the <varname>designatedPrimary</varname>
+ configuration item. If set true on the master, the master will continue to operate solo without outside
+ intervention when the replica fails. If false, a third-party must designate the master as primary in order
+ for it to continue solo.</para>
+ <para>The item numbers in this list apply to the numbered boxes in the figure below. This example assumes
+ that <varname>designatedPrimary</varname> is true on the original master node.</para>
+ <orderedlist>
+ <listitem>
+ <para>System operating normally</para>
+ </listitem>
+ <listitem>
+ <para>Replica suffers a failure. Master realises that replica longer in contact but as
+ <varname>designatedPrimary</varname> is true, master continues processing solo and thus client
+ connections are uninterrupted by the loss of the replica. System continues operating normally, albeit
+ with a single node.</para>
+ </listitem>
+ <listitem>
+ <para>Replica is repaired.</para>
+ </listitem>
+ <listitem>
+ <para>After catching up with missed work, replica is once again ready to take over in the event of master failure.</para>
+ </listitem>
+ </orderedlist>
+ <figure>
+ <title>Failure of replica and subsequent recovery sequence</title>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/HA-2N-ReplicaFail.png" format="PNG" scalefit="1"/>
+ </imageobject>
+ <textobject>
+ <phrase>Failure of replica and subsequent recovery sequence</phrase>
+ </textobject>
+ </mediaobject>
+ </figure>
+ </section>
+ <section role="h5" id="HATwoNodeNetworkPartition">
+ <title>Network Partition and Recovery</title>
+ <para>The figure below illustrates the sequence of events that would occur if the network between
+ master and replica were to suffer a partition, and the nodes were out of contact with one and other.</para>
+ <para>As with <link linkend="HATwoNodeReplicaFailure">Replica Failure and Recovery</link>, the
+ behaviour is governed by the <varname>designatedPrimary</varname>.
+ Only if <varname>designatedPrimary</varname> is true on the master, will the master continue solo.</para>
+ <para>The item numbers in this list apply to the numbered boxes in the figure below. This example assumes
+ that <varname>designatedPrimary</varname> is true on the original master node.</para>
+ <orderedlist>
+ <listitem>
+ <para>System operating normally</para>
+ </listitem>
+ <listitem>
+ <para>Network suffers a failure. Master realises that replica longer in contact but as
+ <varname>designatedPrimary</varname> is true, master continues processing solo and thus client
+ connections are uninterrupted by the network partition between master and replica.</para>
+ </listitem>
+ <listitem>
+ <para>Network is repaired.</para>
+ </listitem>
+ <listitem>
+ <para>After catching up with missed work, replica is once again ready to take over in the event of master failure.
+ System operating normally again.</para>
+ </listitem>
+ </orderedlist>
+ <figure>
+ <title>Partition of the network separating master and replica</title>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/HA-2N-NetworkPartition.png" format="PNG" scalefit="1"/>
+ </imageobject>
+ <textobject>
+ <phrase>Network Partition and Recovery</phrase>
+ </textobject>
+ </mediaobject>
+ </figure>
+ </section>
+ <section role="h5" id="HATwoNodeSplitBrain">
+ <title>Split Brain</title>
+ <para>A <ulink url="http://en.wikipedia.org/wiki/Split-brain_(computing)">split-brain</ulink>
+ is a situation where the two node cluster has two masters. BDB normally strives to prevent
+ this situation arising by preventing two nodes in a cluster being master at the same time.
+ However, if the network suffers a partition, and the third-party intervenes incorrectly
+ and makes the replica a second master a split-brain will be formed and both masters will
+ proceed to perform work <emphasis role="bold">independently</emphasis> of one and other.</para>
+ <para>There is no automatic recovery from a split-brain.</para>
+ <para>Manual intervention will be required to choose which store will be retained as master
+ and which will be discarded. Manual intervention will be required to identify and repeat the
+ lost business transactions.</para>
+ <para>The item numbers in this list apply to the numbered boxes in the figure below.</para>
+ <orderedlist>
+ <listitem>
+ <para>System operating normally</para>
+ </listitem>
+ <listitem>
+ <para>Network suffers a failure. Master realises that replica longer in contact but as
+ <varname>designatedPrimary</varname> is true, master continues processing solo. Client
+ connections are uninterrupted by the network partition.</para>
+ <para>A third-party <emphasis role="bold">erroneously</emphasis> designates the replica as primary while the
+ original master continues running (now solo).</para>
+ </listitem>
+ <listitem>
+ <para>As the nodes cannot see one and other, both behave as masters. Clients may perform work against
+ both master nodes.</para>
+ </listitem>
+ </orderedlist>
+ <figure>
+ <title>Split Brain</title>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/HA-2N-SplitBrain.png" format="PNG" scalefit="1"/>
+ </imageobject>
+ <textobject>
+ <phrase>Split Brain</phrase>
+ </textobject>
+ </mediaobject>
+ </figure>
+ </section>
+ </section>
+ </section>
+ <section role="h3" id="HAMultiNodeCluster">
+ <title>Multi Node Cluster</title>
+ <para>Multi node clusters, that is clusters where the number of nodes is three or more, are not yet
+ ready for use.</para>
+ </section>
+ <section role="h3" id="HAConfiguration">
+ <title>Configuring a Virtual Host to be a node</title>
+ <para>To configure a virtualhost as a cluster node, configure the virtualhost.xml in the following manner:</para>
+ <para>
+ <programlisting language="xml"><![CDATA[
+<virtualhost>
+ <name>myhost</name>
+ <myvhost>
+ <store>
+ <class>org.apache.qpid.server.store.berkeleydb.BDBHAMessageStore</class>
+ <environment-path>${work}/bdbhastore</environment-path>
+ <highAvailability>
+ <groupName>myclustername</groupName>
+ <nodeName>mynode1</nodeName>
+ <nodeHostPort>node1host:port</nodeHostPort>
+ <helperHostPort>node1host:port</helperHostPort>
+ <durability>NO_SYNC\,NO_SYNC\,SIMPLE_MAJORITY</durability>
+ <coalescingSync>true|false</coalescingSync>
+ <designatedPrimary>true|false</designatedPrimary>
+ </highAvailability>
+ </store>
+ ...
+ </myvhost>
+</virtualhost>]]></programlisting>
+ </para>
+ <para>The <varname>groupName</varname> is the name of logical name of the cluster. All nodes within the
+ cluster must use the same <varname>groupName</varname> in order to be considered part of the cluster.</para>
+ <para>The <varname>nodeName</varname> is the logical name of the node. All nodes within the cluster must have a
+ unique name. It is recommended that the node name should be chosen from a different nomenclature from that of
+ the servers on which they are hosted, in case the need arises to move node to a new server in the future.</para>
+ <para>The <varname>nodeHostPort</varname> is the hostname and port number used by this node to communicate with the
+ the other nodes in the cluster. For the hostname, an IP address, hostname or fully qualified hostname may be used.
+ For the port number, any free port can be used. It is important that this address is stable over time, as BDB
+ records and uses this address internally.</para>
+ <para>The <varname>helperHostPort</varname> is the hostname and port number that new nodes use to discover other
+ nodes within the cluster when they are newly introduced to the cluster. When configuring the first node, set the
+ <varname>helperHostPort</varname> to its own <varname>nodeHostPort</varname>. For the second and subsequent nodes,
+ set their <varname>helperHostPort</varname> to that of the first node.</para>
+ <para><varname>durability</varname> controls the <link linkend="HADurabilityGuarantee">durability</link>
+ guarantees made by the cluster. It is important that all nodes use the same value for this property. The default value is
+ NO_SYNC\,NO_SYNC\,SIMPLE_MAJORITY. Owing to the internal use of Apache Commons Config, it is currently necessary
+ to escape the commas within the durability string.</para>
+ <para><varname>coalescingSync</varname> controls the <link linkend="HADurabilityGuarantee_CoalescingSync">coalescing-sync</link>
+ mode of Qpid. It is important that all nodes use the same value. If omitted, it defaults to true.</para>
+ <para>The <varname>designatedPrimary</varname> is applicable only to the <link linkend="HATwoNodeCluster">two-node
+ case.</link> It governs the behaviour of a node when the other node fails or becomes uncontactable. If true,
+ the node will be designated as primary at startup and will be able to continue operating as a single node master.
+ If false, the node will transition to an unavailable state until a third-party manually designates the node as
+ primary or the other node is restored. It is suggested that the node that normally fulfils the role of master is
+ set true in config file and the node that is normally replica is set false. Be aware that setting both nodes to
+ true will lead to a failure to start up, as both cannot be designated at the point of contact. Designating both
+ nodes as primary at runtime (using the JMX interface) will lead to a <link linkend="HATwoNodeSplitBrain">split-brain</link>
+ in the case of network partition and must be avoided.</para>
+ <note><para>Usage of domain names in <varname>helperHostPort</varname> and <varname>nodeHostPort</varname> is more preferebale
+ over IP addresses due to the tendency of more frequent changes of the last over the former.
+ If server IP address changes but domain name remains the same the HA cluster can continue working as normal
+ in case when domain names are used in cluster configuration. In case when IP addresses are used and they are changed with the time
+ than Qpid <link linkend="HAJMXAPI">JMX API for HA</link> can be used to change the addresses or remove the nodes from the cluster.</para></note>
+
+ <section role="h4" id="HAConfiguration_BDBEnvVars">
+ <title>Passing BDB environment and replication configuration options</title>
+ <para>It is possible to pass BDB <ulink url="&oracleBdbJavaDocUrl;com/sleepycat/je/EnvironmentConfig.html">
+ environment</ulink> and <ulink url="&oracleBdbJavaDocUrl;com/sleepycat/je/rep/ReplicationConfig.html">
+ replication</ulink> configuration options from the virtualhost.xml. Environment configuration options are passed using
+ the <varname>envConfig</varname> element, and replication config using <varname>repConfig</varname>.</para>
+ <para>For example, to override the BDB environment configuration options <varname>je.cleaner.threads</varname> and
+ <varname>je.txn.timeout</varname></para>
+ <programlisting language="xml"><![CDATA[
+ ...
+ </highAvailability>
+ <envConfig>
+ <name>je.cleaner.threads</name>
+ <value>2</value>
+ </envConfig>
+ <envConfig>
+ <name>je.txn.timeout</name>
+ <value>15 min</value>
+ </envConfig>
+ ...
+ </store>]]></programlisting>
+ <para>And to override the BDB replication configuration options <varname>je.rep.insufficientReplicasTimeout</varname>.</para>
+ <programlisting language="xml"><![CDATA[
+ ...
+ </highAvailability>
+ ...
+ <repConfig>
+ <name>je.rep.insufficientReplicasTimeout</name>
+ <value>2</value>
+ </envConfig>
+ <envConfig>
+ <name>je.txn.timeout</name>
+ <value>10 s</value>
+ </envConfig>
+ ...
+ </store>]]></programlisting>
+ </section>
+ </section>
+ <section role="h3" id="HADurabilityGuarantee">
+ <title>Durability Guarantees</title>
+ <para>The term <ulink url="http://en.wikipedia.org/wiki/ACID#Durability">durability</ulink> is used to mean that once a
+ transaction is committed, it remains committed regardless of subsequent failures. A highly durable system is one where
+ loss of a committed transaction is extermely unlikely, whereas with a less durable system loss of a transaction is likely
+ in a greater number of scenarios. Typically, the more highly durable a system the slower and more costly it will be.</para>
+ <para>Qpid exposes the all the
+ <ulink url="&oracleBdbRepGuideUrl;txn-management.html#durabilitycontrols">durability controls</ulink>
+ offered by by BDB JE JA and a Qpid specific optimisation called <emphasis role="bold">coalescing-sync</emphasis> which defaults
+ to enabled.</para>
+ <section role="h4" id="HADurabilityGuarantee_BDBControls">
+ <title>BDB Durability Controls</title>
+ <para>BDB expresses durability as a triplet with the following form:</para>
+ <programlisting><![CDATA[<master sync policy>,<replica sync policy>,<replica acknowledgement policy>]]></programlisting>
+ <para>The sync polices controls whether the thread performing the committing thread awaits the successful completion of the
+ write, or the write and sync before continuing. The master sync policy and replica sync policy need not be the same.</para>
+ <para>For master and replic sync policies, the available values are:
+ <ulink url="&oracleBdbJavaDocUrl;com/sleepycat/je/Durability.SyncPolicy.html#SYNC">SYNC</ulink>,
+ <ulink url="&oracleBdbJavaDocUrl;com/sleepycat/je/Durability.SyncPolicy.html#WRITE_NO_SYNC">WRITE_NO_SYNC</ulink>,
+ <ulink url="&oracleBdbJavaDocUrl;com/sleepycat/je/Durability.SyncPolicy.html#NO_SYNC">NO_SYNC</ulink>. SYNC
+ is offers the highest durability whereas NO_SYNC the lowest.</para>
+ <para>Note: the combination of a master sync policy of SYNC and <link linkend="HADurabilityGuarantee_CoalescingSync">coalescing-sync</link>
+ true would result in poor performance with no corresponding increase in durability guarantee. It cannot not be used.</para>
+ <para>The acknowledgement policy defines whether when a master commits a transaction, it also awaits for the replica(s) to
+ commit the same transaction before continuing. For the two-node case, ALL and SIMPLE_MAJORITY are equal.</para>
+ <para>For acknowledgement policy, the available value are:
+ <ulink url="&oracleBdbJavaDocUrl;com/sleepycat/je/Durability.ReplicaAckPolicy.html#ALL">ALL</ulink>,
+ <ulink url="&oracleBdbJavaDocUrl;com/sleepycat/je/Durability.ReplicaAckPolicy.html#SIMPLE_MAJORITY">SIMPLE_MAJORITY</ulink>
+ <ulink url="&oracleBdbJavaDocUrl;com/sleepycat/je/Durability.ReplicaAckPolicy.html#NONE">NONE</ulink>.</para>
+ </section>
+ <section role="h4" id="HADurabilityGuarantee_CoalescingSync">
+ <title>Coalescing-sync</title>
+ <para>If enabled (the default) Qpid works to reduce the number of separate
+ <ulink url="&oracleJdkDocUrl;java/io/FileDescriptor.html#sync()">file-system sync</ulink> operations
+ performed by the <emphasis role="bold">master</emphasis> on the underlying storage device thus improving performance. It does
+ this coalescing separate sync operations arising from the different client commits operations occuring at approximately the same time.
+ It does this in such a manner not to reduce the ACID guarantees of the system.</para>
+ <para>Coalescing-sync has no effect on the behaviour of the replicas.</para>
+ </section>
+ <section role="h4" id="HADurabilityGuarantee_Default">
+ <title>Default</title>
+ <para>The default durability guarantee is <constant>NO_SYNC, NO_SYNC, SIMPLE_MAJORITY</constant> with coalescing-sync enabled. The effect
+ of this combination is described in the table below. It offers a good compromise between durability guarantee and performance
+ with writes being guaranteed on the master and the additional guarantee that a majority of replicas have received the
+ transaction.</para>
+ </section>
+ <section role="h4" id="HADurabilityGuarantee_Examples">
+ <title>Examples</title>
+ <para>Here are some examples illustrating the effects of the durability and coalescing-sync settings.</para>
+ <para>
+ <table>
+ <title>Effect of different durability guarantees</title>
+ <tgroup cols="4">
+ <thead>
+ <row>
+ <entry/>
+ <entry>Durability</entry>
+ <entry>Coalescing-sync</entry>
+ <entry>Description</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>1</entry>
+ <entry>NO_SYNC, NO_SYNC, SIMPLE_MAJORITY</entry>
+ <entry>true</entry>
+ <entry>Before the commit returns to the client, the transaction will be written/sync'd to the Master's disk (effect of
+ coalescing-sync) and a majority of the replica(s) will have acknowledged the <emphasis role="bold">receipt</emphasis>
+ of the transaction. The replicas will write and sync the transaction to their disk at a point in the future governed by
+ <ulink url="&oracleBdbJavaDocUrl;com/sleepycat/je/rep/ReplicationMutableConfig.html#LOG_FLUSH_TASK_INTERVAL">ReplicationMutableConfig#LOG_FLUSH_INTERVAL</ulink>.
+ </entry>
+ </row>
+ <row>
+ <entry>2</entry>
+ <entry>NO_SYNC, WRITE_NO_SYNC, SIMPLE_MAJORITY</entry>
+ <entry>true</entry>
+ <entry>Before the commit returns to the client, the transaction will be written/sync'd to the Master's disk (effect of
+ coalescing-sync and a majority of the replica(s) will have acknowledged the <emphasis role="bold">write</emphasis> of
+ the transaction to their disk. The replicas will sync the transaction to disk at a point in the future with an upper bound governed by
+ ReplicationMutableConfig#LOG_FLUSH_INTERVAL.</entry>
+ </row>
+ <row>
+ <entry>3</entry>
+ <entry>NO_SYNC, NO_SYNC, NONE</entry>
+ <entry>false</entry>
+ <entry>After the commit returns to the client, the transaction is neither guaranteed to be written to the disk of the master
+ nor received by any of the replicas. The master and replicas will write and sync the transaction to their disk at a point
+ in the future with an upper bound governed by ReplicationMutableConfig#LOG_FLUSH_INTERVAL. This offers the weakest durability guarantee.</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </para>
+ </section>
+ </section>
+ <section id="HAClientFailover">
+ <title>Client failover configuration</title>
+ <para>The details about format of Qpid connection URLs can be found at section
+ <ulink url="../../Programming-In-Apache-Qpid/html/QpidJNDI.html">Connection URLs</ulink>
+ of book <ulink url="../../Programming-In-Apache-Qpid/html/">Programming In Apache Qpid</ulink>.</para>
+ <para>The failover policy option in the connection URL for the HA Cluster should be set to <emphasis>roundrobin</emphasis>.
+ The Master broker should be put into a first place in <emphasis>brokerlist</emphasis> URL option.
+ The recommended value for <emphasis>connectdelay</emphasis> option in broker URL should be set to
+ the value greater than 1000 milliseconds. If it is desired that clients re-connect automatically after a
+ master to replica failure, <varname>cyclecount</varname> should be tuned so that the retry period is longer than
+ the expected length of time to perform the failover.</para>
+ <example><title>Example of connection URL for the HA Cluster</title><![CDATA[
+amqp://guest:guest@clientid/test?brokerlist='tcp://localhost:5672?connectdelay='2000'&retries='3';tcp://localhost:5671?connectdelay='2000'&retries='3';tcp://localhost:5673?connectdelay='2000'&retries='3''&failover='roundrobin?cyclecount='30''
+ ]]></example>
+ </section>
+ <section role="h3" id="HAJMXAPI">
+ <title>Qpid JMX API for HA</title>
+ <para>Qpid exposes the BDB HA store information via its JMX interface and provides APIs to remove a Node from
+ the group, update a Node IP address, and assign a Node as the designated primary.</para>
+ <para>An instance of the <classname>BDBHAMessageStore</classname> MBean is instantiated by the broker for the each virtualhost using the HA store.</para>
+ <para>The reference to this MBean can be obtained via JMX API using an ObjectName like <emphasis>org.apache.qpid:type=BDBHAMessageStore,name=&lt;virtualhost name&gt;</emphasis>
+ where &lt;virtualhost name&gt; is the name of a specific virtualhost on the broker.</para>
+ <table border="1">
+ <title>Mbean <classname>BDBHAMessageStore</classname> attributes</title>
+ <thead>
+ <tr>
+ <td>Name</td>
+ <td>Type</td>
+ <td>Accessibility</td>
+ <td>Description</td>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td>GroupName</td>
+ <td>String</td>
+ <td>Read only</td>
+ <td>Name identifying the group</td>
+ </tr>
+ <tr>
+ <td>NodeName</td>
+ <td>String</td>
+ <td>Read only</td>
+ <td>Unique name identifying the node within the group</td>
+ </tr>
+ <tr>
+ <td>NodeHostPort</td>
+ <td>String</td>
+ <td>Read only</td>
+ <td>Host/port used to replicate data between this node and others in the group</td>
+ </tr>
+ <tr>
+ <td>HelperHostPort</td>
+ <td>String</td>
+ <td>Read only</td>
+ <td>Host/port used to allow a new node to discover other group members</td>
+ </tr>
+ <tr>
+ <td>NodeState</td>
+ <td>String</td>
+ <td>Read only</td>
+ <td>Current state of the node</td>
+ </tr>
+ <tr>
+ <td>ReplicationPolicy</td>
+ <td>String</td>
+ <td>Read only</td>
+ <td>Node replication durability</td>
+ </tr>
+ <tr id="JMXDesignatedPrimary">
+ <td>DesignatedPrimary</td>
+ <td>boolean</td>
+ <td>Read/Write</td>
+ <td>Designated primary flag. Applicable to the two node case.</td>
+ </tr>
+ <tr>
+ <td>CoalescingSync</td>
+ <td>boolean</td>
+ <td>Read only</td>
+ <td>Coalescing sync flag. Applicable to the master sync policies NO_SYNC and WRITE_NO_SYNC only.</td>
+ </tr>
+ <tr>
+ <td>getAllNodesInGroup</td>
+ <td>TabularData</td>
+ <td>Read only</td>
+ <td>Get all nodes within the group, regardless of whether currently attached or not</td>
+ </tr>
+ </tbody>
+ </table>
+ <table border="1">
+ <title>Mbean <classname>BDBHAMessageStore</classname> operations</title>
+ <thead>
+ <tr>
+ <td>Operation</td>
+ <td>Parameters</td>
+ <td>Returns</td>
+ <td>Description</td>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td>removeNodeFromGroup</td>
+ <td>
+ <para><emphasis>nodeName</emphasis>, name of node, string</para>
+ </td>
+ <td>void</td>
+ <td>Remove an existing node from the group</td>
+ </tr>
+ <tr>
+ <td>updateAddress</td>
+ <td>
+ <itemizedlist>
+ <itemizedlist>
+ <para><emphasis>nodeName</emphasis>, name of node, string</para>
+ </itemizedlist>
+ <itemizedlist>
+ <para><emphasis>newHostName</emphasis>, new host name, string</para>
+ </itemizedlist>
+ <itemizedlist>
+ <para><emphasis>newPort</emphasis>, new port number, int</para>
+ </itemizedlist>
+ </itemizedlist>
+ </td>
+ <td>void</td>
+ <td>Update the address of another node. The node must be in a STOPPED state.</td>
+ </tr>
+ </tbody>
+ </table>
+ <figure>
+ <title>BDBHAMessageStore view from jconsole.</title>
+ <graphic fileref="images/HA-BDBHAMessageStore-MBean-jconsole.png"/>
+ </figure>
+ <example>
+ <title>Example of java code to get the node state value</title>
+ <programlisting language="java"><![CDATA[
+Map<String, Object> environment = new HashMap<String, Object>();
+
+// credentials: user name and password
+environment.put(JMXConnector.CREDENTIALS, new String[] {"admin","admin"});
+JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:9001/jmxrmi");
+JMXConnector jmxConnector = JMXConnectorFactory.connect(url, environment);
+MBeanServerConnection mbsc = jmxConnector.getMBeanServerConnection();
+
+ObjectName queueObjectName = new ObjectName("org.apache.qpid:type=BDBHAMessageStore,name=test");
+String state = (String)mbsc.getAttribute(queueObjectName, "NodeState");
+
+System.out.println("Node state:" + state);
+ ]]></programlisting>
+ <para>Example system output:</para>
+ <screen><![CDATA[Node state:MASTER]]></screen>
+ </example>
+ </section>
+ <section id="BDB-HA-Monitoring-cluster">
+ <title>Monitoring cluster</title>
+ <para>In order to discover potential issues with HA Cluster early, all nodes in the Cluster should be monitored on regular basis
+ using the following techniques:</para>
+ <itemizedlist>
+ <listitem>
+ <para>Broker log files scrapping for WARN or ERROR entries and operational log entries like:</para>
+ <itemizedlist>
+ <listitem>
+ <para><emphasis>MST-1007 :</emphasis> Store Passivated. It can indicate that Master virtual host has gone down.</para>
+ </listitem>
+ <listitem>
+ <para><emphasis>MST-1006 :</emphasis> Recovery Complete. It can indicate that a former Replica virtual host is up and became the Master.</para>
+ </listitem>
+ </itemizedlist>
+ </listitem>
+ <listitem>
+ <para>Disk space usage and system load using system tools.</para>
+ </listitem>
+ <listitem>
+ <para>Berkeley HA node status using <ulink url="&oracleBdbJavaDocUrl;com/sleepycat/je/rep/util/DbPing.html"><classname>DbPing</classname></ulink> utility.</para>
+ <example><title>Using <classname>DbPing</classname> utility for monitoring HA nodes.</title><command>
+java -jar je-&oracleBdbProductVersion;.jar DbPing -groupName TestClusterGroup -nodeName Node-5001 -nodeHost localhost:5001 -socketTimeout 10000
+</command><screen>
+Current state of node: Node-5001 from group: TestClusterGroup
+ Current state: MASTER
+ Current master: Node-5001
+ Current JE version: &oracleBdbProductVersion;
+ Current log version: 8
+ Current transaction end (abort or commit) VLSN: 165
+ Current master transaction end (abort or commit) VLSN: 0
+ Current active feeders on node: 0
+ Current system load average: 0.35
+</screen></example>
+ <para>In the example above <classname>DbPing</classname> utility requested status of Cluster node with name
+ <emphasis>Node-5001</emphasis> from replication group <emphasis>TestClusterGroup</emphasis> running on host <emphasis>localhost:5001</emphasis>.
+ The state of the node was reported into a system output.
+ </para>
+ </listitem>
+ <listitem>
+ <para>Using Qpid broker JMX interfaces.</para>
+ <para>Mbean <classname>BDBHAMessageStore</classname> can be used to request the following node information:</para>
+ <itemizedlist>
+ <listitem>
+ <para><emphasis>NodeState</emphasis> indicates whether node is a Master or Replica.</para>
+ </listitem>
+ <listitem>
+ <para><emphasis>Durability</emphasis> replication durability.</para>
+ </listitem>
+ <listitem>
+ <para><emphasis>DesignatedPrimary</emphasis> indicates whether Master node is designated primary.</para>
+ </listitem>
+ <listitem>
+ <para><emphasis>GroupName</emphasis> replication group name.</para>
+ </listitem>
+ <listitem>
+ <para><emphasis>NodeName</emphasis> node name.</para>
+ </listitem>
+ <listitem>
+ <para><emphasis>NodeHostPort</emphasis> node host and port.</para>
+ </listitem>
+ <listitem>
+ <para><emphasis>HelperHostPort</emphasis> helper host and port.</para>
+ </listitem>
+ <listitem>
+ <para><emphasis>AllNodesInGroup</emphasis> lists of all nodes in the replication group including their names, hosts and ports.</para>
+ </listitem>
+ </itemizedlist>
+ <para>For more details about <classname>BDBHAMessageStore</classname> MBean please refer section <link linkend="HAJMXAPI">Qpid JMX API for HA</link></para>
+ </listitem>
+ </itemizedlist>
+ </section>
+ <section id="HADiskSpace">
+ <title>Disk space requirements</title>
+ <para>Disk space is a critical resource for the HA Qpid broker.</para>
+ <para>In case when a Replica goes down (or falls behind the Master in 2 node cluster where the Master is designated primary)
+ and the Master continues running, the non-replicated store files are kept on the Masters disk for the period of time
+ as specified in <emphasis>je.rep.repStreamTimeout</emphasis> JE setting in order to replicate this data later
+ when the Replica is back. This setting is set to 1 hour by default by the broker. The setting can be overridden as described in
+ <xref linkend="HAConfiguration_BDBEnvVars"/>.</para>
+ <para>Depending from the application publishing/consuming rates and message sizes,
+ the disk space might become overfull during this period of time due to preserved logs.
+ Please, make sure to allocate enough space on your disk to avoid this from happening.
+ </para>
+ </section>
+ <section id="BDB-HA-Network-Requirements">
+ <title>Network Requirements</title>
+ <para>The HA Cluster performance depends on the network bandwidth, its use by existing traffic, and quality of service.</para>
+ <para>In order to achieve the best performance it is recommended to use a separate network infrastructure for the Qpid HA Nodes
+ which might include installation of dedicated network hardware on Broker hosts, assigning a higher priority to replication ports,
+ installing a cluster in a separate network not impacted by any other traffic.</para>
+ </section>
+ <section id="BDB-HA-Security">
+ <title>Security</title>
+ <para>At the moment Berkeley replication API supports only TCP/IP protocol to transfer replication data between Master and Replicas.</para>
+ <para>As result, the replicated data is unprotected and can be intercepted by anyone having access to the replication network.</para>
+ <para>Also, anyone who can access to this network can introduce a new node and therefore receive a copy of the data.</para>
+ <para>In order to reduce the security risks the entire HA cluster is recommended to run in a separate network protected from general access.</para>
+ </section>
+ <section id="BDB-HA-Backup">
+ <title>Backups</title>
+ <para>In order to protect the entire cluster from some cataclysms which might destroy all cluster nodes,
+ backups of the Master store should be taken on a regular basis.</para>
+ <para>Qpid Broker distribution includes the "hot" backup utility <emphasis>backup.sh</emphasis> which can be found at broker bin folder.
+ This utility can perform the backup when broker is running.</para>
+ <para><emphasis>backup.sh</emphasis> script invokes <classname>org.apache.qpid.server.store.berkeleydb.BDBBackup</classname> to do the job.</para>
+ <para>You can also run this class from command line like in an example below:</para>
+ <example><title>Performing store backup by using <classname>BDBBackup</classname> class directly</title><command>
+ java -cp qpid-bdbstore-0.18.jar org.apache.qpid.server.store.berkeleydb.BDBBackup -fromdir path/to/store/folder -todir path/to/backup/foldeAr</command>
+ </example>
+ <para>In the example above BDBBackup utility is called from qpid-bdbstore-0.18.jar to backup the store at <emphasis>path/to/store/folder</emphasis> and copy store logs into <emphasis>path/to/backup/folder</emphasis>.</para>
+ <para>Linux and Unix users can take advantage of <emphasis>backup.sh</emphasis> bash script by running this script in a similar way.</para>
+ <example><title>Performing store backup by using <classname>backup.sh</classname> bash script</title>
+ <command>backup.sh -fromdir path/to/store/folder -todir path/to/backup/folder</command>
+ </example>
+ <note>
+ <para>Do not forget to ensure that the Master store is being backed up, in the event the Node elected Master changes during
+ the lifecycle of the cluster.</para>
+ </note>
+ </section>
+ <section id="HAMigrationFromNonHA">
+ <title>Migration of a non-HA store to HA</title>
+ <para>Non HA stores starting from schema version 4 (0.14 Qpid release) can be automatically converted into HA store on broker startup if replication is first enabled with the <ulink url="&oracleBdbJavaDocUrl;com/sleepycat/je/rep/util/DbEnableReplication.html"><classname>DbEnableReplication</classname></ulink> utility from the BDB JE jar.</para>
+ <para>DbEnableReplication converts a non HA store into an HA store and can be used as follows:</para>
+ <example><title>Enabling replication</title><command>
+java -jar je-&oracleBdbProductVersion;.jar DbEnableReplication -h /path/to/store -groupName MyReplicationGroup -nodeName MyNode1 -nodeHostPort localhost:5001
+ </command></example>
+ <para>In the examples above, je jar of version &oracleBdbProductVersion; is used to convert store at <emphasis>/path/to/store</emphasis> into HA store having replication group name <emphasis>MyReplicationGroup</emphasis>, node name <emphasis>MyNode1</emphasis> and running on host <emphasis>localhost</emphasis> and port <emphasis>5001</emphasis>.</para>
+ <para>After running DbEnableReplication and updating the virtual host store to configuration to be an HA message store, like in example below,
+ on broker start up the store schema will be upgraded to the most recent version and the broker can be used as normal.</para>
+ <example>
+ <title>Example of XML configuration for HA message store</title>
+ <programlisting language="xml"><![CDATA[
+<store>
+ <class>org.apache.qpid.server.store.berkeleydb.BDBHAMessageStore</class>
+ <environment-path>/path/to/store</environment-path>
+ <highAvailability>
+ <groupName>MyReplicationGroup</groupName>
+ <nodeName>MyNode1</nodeName>
+ <nodeHostPort>localhost:5001</nodeHostPort>
+ <helperHostPort>localhost:5001</helperHostPort>
+ </highAvailability>
+</store>]]></programlisting>
+ </example>
+ <para>The Replica nodes can be started with empty stores. The data will be automatically copied from Master to Replica on Replica start-up.
+ This will take a period of time determined by the size of the Masters store and the network bandwidth between the nodes.</para>
+ <note>
+ <para>Due to existing caveats in Berkeley JE with copying of data from Master into Replica it is recommended to restart the Master node after store schema upgrade is finished before starting the Replica nodes.</para>
+ </note>
+ </section>
+ <section id="HADisasterRecovery">
+ <title>Disaster Recovery</title>
+ <para>This section describes the steps required to restore HA broker cluster from backup.</para>
+ <para>The detailed instructions how to perform backup on replicated environment can be found <link linkend="BDB-HA-Backup">here</link>.</para>
+ <para>At this point we assume that backups are collected on regular basis from Master node.</para>
+ <para>Replication configuration of a cluster is stored internally in HA message store.
+ This information includes IP addresses of the nodes.
+ In case when HA message store needs to be restored on a different host with a different IP address
+ the cluster replication configuration should be reseted in this case</para>
+ <para>Oracle provides a command line utility <ulink url="&oracleBdbJavaDocUrl;com/sleepycat/je/rep/util/DbResetRepGroup.html"><classname>DbResetRepGroup</classname></ulink>
+ to reset the members of a replication group and replace the group with a new group consisting of a single new member
+ as described by the arguments supplied to the utility</para>
+ <para>Cluster can be restored with the following steps:</para>
+ <itemizedlist>
+ <listitem><para>Copy log files into the store folder from backup</para></listitem>
+ <listitem>
+ <para>Use <classname>DbResetRepGroup</classname> to reset an existing environment. See an example below</para>
+ <example>
+ <title>Reseting of replication group with <classname>DbResetRepGroup</classname></title><command>
+java -cp je-&oracleBdbProductVersion;.jar com.sleepycat.je.rep.util.DbResetRepGroup -h ha-work/Node-5001/bdbstore -groupName TestClusterGroup -nodeName Node-5001 -nodeHostPort localhost:5001</command>
+ </example>
+ <para>In the example above <classname>DbResetRepGroup</classname> utility from Berkeley JE of version &oracleBdbProductVersion; is used to reset the store
+ at location <emphasis>ha-work/Node-5001/bdbstore</emphasis> and set a replication group to <emphasis>TestClusterGroup</emphasis>
+ having a node <emphasis>Node-5001</emphasis> which runs at <emphasis>localhost:5001</emphasis>.</para>
+ </listitem>
+ <listitem><para>Start a broker with HA store configured as specified on running of <classname>DbResetRepGroup</classname> utility.</para></listitem>
+ <listitem><para>Start replica nodes having the same replication group and a helper host port pointing to a new master. The store content will be copied into Replicas from Master on their start up.</para></listitem>
+ </itemizedlist>
+ </section>
+
+ <section id="HAPerformance">
+ <title>Performance</title>
+ <para>The aim of this section is not to provide exact performance metrics relating to HA, as this depends heavily on the test
+ environment, but rather showing an impact of HA on Qpid broker performance in comparison with the Non HA case.</para>
+ <para>For testing of impact of HA on a broker performance a special test script was written using Qpid performance test framework.
+ The script opened a number of connections to the Qpid broker, created producers and consumers on separate connections,
+ and published test messages with concurrent producers into a test queue and consumed them with concurrent consumers.
+ The table below shows the number of producers/consumers used in the tests.
+ The overall throughput was collected for each configuration.
+ </para>
+ <table border="1">
+ <title>Number of producers/consumers in performance tests</title>
+ <thead>
+ <tr>
+ <th>Test</th>
+ <th>Number of producers</th>
+ <th>Number of consumers</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td>1</td>
+ <td>1</td>
+ <td>1</td>
+ </tr>
+ <tr>
+ <td>2</td>
+ <td>2</td>
+ <td>2</td>
+ </tr>
+ <tr>
+ <td>3</td>
+ <td>4</td>
+ <td>4</td>
+ </tr>
+ <tr>
+ <td>4</td>
+ <td>8</td>
+ <td>8</td>
+ </tr>
+ <tr>
+ <td>5</td>
+ <td>16</td>
+ <td>16</td>
+ </tr>
+ <tr>
+ <td>6</td>
+ <td>32</td>
+ <td>32</td>
+ </tr>
+ <tr>
+ <td>7</td>
+ <td>64</td>
+ <td>64</td>
+ </tr>
+ </tbody>
+ </table>
+ <para>The test was run against the following Qpid Broker configurations</para>
+ <itemizedlist>
+ <listitem>
+ <para>Non HA Broker</para>
+ </listitem>
+ <listitem>
+ <para>HA 2 Nodes Cluster with durability <emphasis>SYNC,SYNC,ALL</emphasis></para>
+ </listitem>
+ <listitem>
+ <para>HA 2 Nodes Cluster with durability <emphasis>WRITE_NO_SYNC,WRITE_NO_SYNC,ALL</emphasis></para>
+ </listitem>
+ <listitem>
+ <para>HA 2 Nodes Cluster with durability <emphasis>WRITE_NO_SYNC,WRITE_NO_SYNC,ALL</emphasis> and <emphasis>coalescing-sync</emphasis> Qpid mode</para>
+ </listitem>
+ <listitem>
+ <para>HA 2 Nodes Cluster with durability <emphasis>WRITE_NO_SYNC,NO_SYNC,ALL</emphasis> and <emphasis>coalescing-sync</emphasis> Qpid mode</para>
+ </listitem>
+ <listitem>
+ <para>HA 2 Nodes Cluster with durability <emphasis>NO_SYNC,NO_SYNC,ALL</emphasis> and <emphasis>coalescing-sync</emphasis> Qpid option</para>
+ </listitem>
+ </itemizedlist>
+ <para>The evironment used in testing consisted of 2 servers with 4 CPU cores (2x Intel(r) Xeon(R) CPU 5150@2.66GHz), 4GB of RAM
+ and running under OS Red Hat Enterprise Linux AS release 4 (Nahant Update 4). Network bandwidth was 1Gbit.
+ </para>
+ <para>We ran Master node on the first server and Replica and clients(both consumers and producers) on the second server.</para>
+ <para>In non-HA case Qpid Broker was run on a first server and clients were run on a second server.</para>
+ <para>The table below contains the test results we measured on this environment for different Broker configurations.</para>
+ <para>Each result is represented by throughput value in KB/second and difference in % between HA configuration and non HA case for the same number of clients.</para>
+ <table border="1">
+ <title>Performance Comparison</title>
+ <thead>
+ <tr>
+ <td>Test/Broker</td>
+ <td>No HA</td>
+ <td>SYNC, SYNC, ALL</td>
+ <td>WRITE_NO_SYNC, WRITE_NO_SYNC, ALL</td>
+ <td>WRITE_NO_SYNC, WRITE_NO_SYNC, ALL - coalescing-sync</td>
+ <td>WRITE_NO_SYNC, NO_SYNC,ALL - coalescing-sync</td>
+ <td>NO_SYNC, NO_SYNC, ALL - coalescing-sync</td>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td>1 (1/1)</td>
+ <td>0.0%</td>
+ <td>-61.4%</td>
+ <td>117.0%</td>
+ <td>-16.02%</td>
+ <td>-9.58%</td>
+ <td>-25.47%</td>
+ </tr>
+ <tr>
+ <td>2 (2/2)</td>
+ <td>0.0%</td>
+ <td>-75.43%</td>
+ <td>67.87%</td>
+ <td>-66.6%</td>
+ <td>-69.02%</td>
+ <td>-30.43%</td>
+ </tr>
+ <tr>
+ <td>3 (4/4)</td>
+ <td>0.0%</td>
+ <td>-84.89%</td>
+ <td>24.19%</td>
+ <td>-71.02%</td>
+ <td>-69.37%</td>
+ <td>-43.67%</td>
+ </tr>
+ <tr>
+ <td>4 (8/8)</td>
+ <td>0.0%</td>
+ <td>-91.17%</td>
+ <td>-22.97%</td>
+ <td>-82.32%</td>
+ <td>-83.42%</td>
+ <td>-55.5%</td>
+ </tr>
+ <tr>
+ <td>5 (16/16)</td>
+ <td>0.0%</td>
+ <td>-91.16%</td>
+ <td>-21.42%</td>
+ <td>-86.6%</td>
+ <td>-86.37%</td>
+ <td>-46.99%</td>
+ </tr>
+ <tr>
+ <td>6 (32/32)</td>
+ <td>0.0%</td>
+ <td>-94.83%</td>
+ <td>-51.51%</td>
+ <td>-92.15%</td>
+ <td>-92.02%</td>
+ <td>-57.59%</td>
+ </tr>
+ <tr>
+ <td>7 (64/64)</td>
+ <td>0.0%</td>
+ <td>-94.2%</td>
+ <td>-41.84%</td>
+ <td>-89.55%</td>
+ <td>-89.55%</td>
+ <td>-50.54%</td>
+ </tr>
+ </tbody>
+ </table>
+ <para>The figure below depicts the graphs for the performance test results</para>
+ <figure>
+ <title>Test results</title>
+ <graphic fileref="images/HA-perftests-results.png"/>
+ </figure>
+ <para>On using durability <emphasis>SYNC,SYNC,ALL</emphasis> (without coalescing-sync) the performance drops significantly (by 62-95%) in comparison with non HA broker.</para>
+ <para>Whilst, on using durability <emphasis>WRITE_NO_SYNC,WRITE_NO_SYNC,ALL</emphasis> (without coalescing-sync) the performance drops by only half, but with loss of durability guarantee, so is not recommended.</para>
+ <para>In order to have better performance with HA, Qpid Broker comes up with the special mode called <link linkend="HADurabilityGuarantee_CoalescingSync">coalescing-sync</link>,
+ With this mode enabled, Qpid broker batches the concurrent transaction commits and syncs transaction data into Master disk in one go.
+ As result, the HA performance only drops by 25-60% for durability <emphasis>NO_SYNC,NO_SYNC,ALL</emphasis> and by 10-90% for <emphasis>WRITE_NO_SYNC,WRITE_NO_SYNC,ALL</emphasis>.</para>
+ </section>
+</section>
diff --git a/doc/book/src/java-broker/MessageStore-Tool.xml b/doc/book/src/java-broker/MessageStore-Tool.xml
deleted file mode 100644
index fdcb3cd560..0000000000
--- a/doc/book/src/java-broker/MessageStore-Tool.xml
+++ /dev/null
@@ -1,150 +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><title>
- MessageStore Tool
- </title><section role="h2" id="MessageStoreTool-MessageStoreTool"><title>
- MessageStore Tool
- </title>
-
- <para>
- We have a number of implementations of the Qpid MessageStore
- interface. This tool allows the interrogation of these stores
- while the broker is offline.
- </para>
-
- <section role="h3" id="MessageStoreTool-MessageStoreImplementations"><title>
- MessageStore
- Implementations
- </title>
-
- <itemizedlist>
- <listitem><para>
- <xref linkend="qpid_BDBMessageStore--3rd-Party-"/>
- </para></listitem>
- <listitem><para>
- <xref linkend="qpid_JDBCStore"/>
- </para></listitem>
- <listitem><para>
- <xref linkend="qpid_MemoryMessageStore"/>
- </para></listitem>
- </itemizedlist>
-<!--h3--></section>
-
- <section role="h3" id="MessageStoreTool-Introduction"><title>
- Introduction
- </title>
-
- <para>
- Each of the MessageStore implementations provide different back
- end storage for their messages and so would need a different tool
- to be able to interrogate their contents at the back end.
- </para><para>
- What this tool does is to utilise the Java broker code base to
- access the contents of the storage providing the user with a
- consistent means to inspect the storage contents in broker
- memory. The tool allows the current messages in the store to be
- inspected and copied/moved between queues. The tool uses the
- message instance in memory for all its access paths, but changes
- made will be reflected in the physical store (if one exists).
- </para>
-<!--h3--></section>
-
- <section role="h3" id="MessageStoreTool-Usage"><title>
- Usage
- </title>
-
- <para>
- The tools-distribution currently includes a unix shell command
- 'msTool.sh' this script will launch the java tool.
- </para><para>
- The tool loads $QPID_HOME/etc/config.xml by default. If an
- alternative broker configuration is required this should be
- provided on the command line as would be done for the broker.
- </para>
- <programlisting>
-msTool.sh -c &lt;path to different config.xml&gt;
-</programlisting>
- <para>
- On startup the user is present with a command prompt
- </para>
- <programlisting>
-$ msTool.sh
-MessageStoreTool - for examining Persistent Qpid Broker MessageStore instances
-bdb$
-</programlisting>
-<!--h3--></section>
-
- <section role="h3" id="MessageStoreTool-AvailableCommands"><title>
- Available
- Commands
- </title>
-
- <para>
- The available commands in the tool can be seen through the use of
- the 'help' command.
- </para>
- <programlisting>
-bdb$ help
-+----------------------------------------------------------------+
-| Available Commands |
-+----------------------------------------------------------------+
-| Command | Description |
-+----------------------------------------------------------------+
-| quit | Quit the tool. |
-| list | list available items. |
-| dump | Dump selected message content. Default: show=content |
-| load | Loads specified broker configuration file. |
-| clear | Clears any selection. |
-| show | Shows the messages headers. |
-| select | Perform a selection. |
-| help | Provides detailed help on commands. |
-+----------------------------------------------------------------+
-bdb$
-</programlisting>
- <para>
- A brief description is displayed and further usage information is
- shown with 'help &lt;command&gt;'
- </para>
- <programlisting>
-bdb$ help list
-list availble items.
-Usage:list queues [&lt;exchange&gt;] | exchanges | bindings [&lt;exchange&gt;] | all
-bdb$
-</programlisting>
-<!--h3--></section>
-
-
- <section role="h3" id="MessageStoreTool-FutureWork"><title>
- Future Work
- </title>
-
- <para>
- Currently the tool only works whilst the broker is offline i.e.
- it is up, but not accepting AMQP connections. This requires a
- stop/start of the broker. If this functionality was incorporated
- into the broker then a telnet functionality could be provided
- allowing online management.
- </para>
-<!--h3--></section>
-<!--h2--></section>
-</section>
diff --git a/doc/book/src/java-broker/OtherQueueTypes.xml b/doc/book/src/java-broker/OtherQueueTypes.xml
new file mode 100644
index 0000000000..d42e4e62cb
--- /dev/null
+++ b/doc/book/src/java-broker/OtherQueueTypes.xml
@@ -0,0 +1,274 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE urls [
+<!ENTITY oracleJeeDocUrl "http://docs.oracle.com/javaee/6/api/">
+]>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT 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="OtherQueueTypes">
+ <title>Other Queue Types</title>
+
+ <section role="h2" id="OtherQueueTypes-Introduction">
+ <title>Introduction</title>
+ <para> In addition to the standard queue type where messages are delivered in the same order
+ that they were sent, the Java Broker supports three additional queue types which allows for
+ alternative delivery behaviours. These are <link linkend="OtherQueueTypes-Priority"
+ >priority-queues</link>, <link linkend="OtherQueueTypes-Sorted">sorted-queues</link>-, and
+ <link linkend="OtherQueueTypes-LVQ">last-value-queues</link> (LVQs). </para>
+ <para> In the following sections, the semantics of each queue type is described, followed by a
+ description of how instances of these queue can be created via <link
+ linkend="OtherQueueTypes-CreateUsingConfig">configuration</link> or <link
+ linkend="OtherQueueTypes-CreateUsingJmsOrJmx">programmatically</link>. </para>
+ <para>The final section discusses the importance of using a <link
+ linkend="OtherQueueTypes-SetLowPrefetch">low client pre-fetch</link> with these queued.
+ </para>
+ </section>
+
+ <section role="h2" id="OtherQueueTypes-Priority">
+ <title>Priority Queues</title>
+ <para>In a priority queue, messages on the queue are delivered in an order determined by the
+ <ulink url="&oracleJeeDocUrl;javax/jms/Message.html#getJMSPriority()">JMS priority message
+ header</ulink> within the message. By default Qpid supports the 10 priority levels mandated
+ by JMS, with priority value 0 as the lowest priority and 9 as the highest. </para>
+ <para>It is possible to reduce the effective number of priorities if desired.</para>
+ <para>JMS defines the <ulink url="&oracleJeeDocUrl;javax/jms/Message.html#DEFAULT_PRIORITY">
+ default message priority</ulink> as 4. Messages sent without a specified priority use this
+ default. </para>
+ </section>
+ <section role="h2" id="OtherQueueTypes-Sorted">
+ <title>Sorted Queues</title>
+ <para>Sorted queues allow the message delivery order to be determined by value of an arbitrary
+ <ulink url="&oracleJeeDocUrl;javax/jms/Message.html#getStringProperty()">JMS message
+ property</ulink>. Sort order is alpha-numeric and the property value must have a type
+ java.lang.String.</para>
+ <para>Messages sent to a sorted queue without the specified JMS message property will be
+ inserted into the 'last' position in the queue.</para>
+ </section>
+ <section role="h2" id="OtherQueueTypes-LVQ">
+ <title>Last Value Queues (LVQ)</title>
+ <para>LVQs (or conflation queues) are special queues that automatically discard any message when
+ a newer message arrives with the same key value. The key is specified by arbitrary <ulink
+ url="&oracleJeeDocUrl;javax/jms/Message.html#getPropertyNames()">JMS message
+ property</ulink>.</para>
+ <para>An example of an LVQ might be where a queue represents prices on a stock exchange: when
+ you first consume from the queue you get the latest quote for each stock, and then as new
+ prices come in you are sent only these updates. </para>
+ <para>Like other queues, LVQs can either be browsed or consumed from. When browsing an
+ individual subscriber does not remove the message from the queue when receiving it. This
+ allows for many subscriptions to browse the same LVQ (i.e. you do not need to create and bind
+ a separate LVQ for each subscriber who wishes to receive the contents of the LVQ).</para>
+ <para>Messages sent to an LVQ without the specified property will be delivered as normal and
+ will never be "replaced".</para>
+ </section>
+ <section role="h2" id="OtherQueueTypes-Create">
+ <title>Creating a Priority, Sorted or LVQ Queue</title>
+ <para>To create a priority, sorted or LVQ queue, it can be defined in the virtualhost
+ configuration file, or the queue can be created programmtically from a client via AMQP (using
+ an extension to JMS), or using JMX. These methods are described below. </para>
+ <para>Once a queue is created you cannot change its type (without deleting it and re-creating).
+ Also note you cannot currently mix the natures of these queue types, for instance, you cannot
+ define a queue which it both an LVQ and a priority-queue.</para>
+ <section role="h2" id="OtherQueueTypes-CreateUsingConfig">
+ <title>Using configuration</title>
+ <para>To create a priority, sorted or LVQ queue within configuration, add the appropriate xml
+ to the virtualhost.xml configuration file within the <varname>queues</varname>
+ element.</para>
+ <section role="h3" id="OtherQueueTypes-CreateUsingConfig-Priority">
+ <title>Priority</title>
+ <para> To defining a priority queue, add a &lt;priority&gt;true&lt;/priority&gt; element. By
+ default the queue will have 10 distinct priorities. </para>
+ <example>
+ <title>Configuring a priority queue</title>
+ <programlisting><![CDATA[<queue>
+ <name>myqueue</name>
+ <myqueue>
+ <exchange>amq.direct</exchange>
+ <priority>true</priority>
+ </myqueue>
+</queue>]]></programlisting>
+ </example>
+ <para> If you require fewer priorities, it is possible to specify a
+ <varname>priorities</varname> element (whose value is a integer value between 2 and 10
+ inclusive) which will give the queue that number of distinct priorities. When messages are
+ sent to that queue, their effective priority will be calculated by partitioning the
+ priority space. If the number of effective priorities is 2, then messages with priority
+ 0-4 are treated the same as "lower priority" and messages with priority 5-9 are treated
+ equivalently as "higher priority". </para>
+ <example>
+ <title>Configuring a priority queue with fewer priorities</title>
+ <programlisting><![CDATA[<queue>
+ <name>myqueue</name>
+ <myqueue>
+ <exchange>amq.direct</exchange>
+ <priority>true</priority>
+ <priorities>4</priorities>
+ </myqueue>
+</queue>]]></programlisting>
+ </example>
+ </section>
+ <section role="h3" id="OtherQueueTypes-CreateUsingConfig-Sorted">
+ <title>Sorted</title>
+ <para> To define a sorted queue, add a <varname>sortKey</varname> element. The value of the
+ <varname>sortKey</varname> element defines the message property to use the value of when
+ sorting the messages put onto the queue. </para>
+ <example>
+ <title>Configuring a sorted queue</title>
+ <programlisting><![CDATA[<queue>
+ <name>myqueue</name>
+ <myqueue>
+ <exchange>amq.direct</exchange>
+ <sortKey>message-property-to-sort-by</sortKey>
+ </myqueue>
+</queue>]]></programlisting>
+ </example>
+ </section>
+ <section role="h3" id="OtherQueueTypes-CreateUsingConfig-LVQ">
+ <title>LVQ</title>
+ <para> To define a LVQ, add a <varname>lvq</varname> element with the value
+ <constant>true</constant>. Without any further configuration this will define an LVQ
+ which uses the JMS message property <constant>qpid.LVQ_key</constant> as the key for
+ replacement. </para>
+ <example>
+ <title>Configuring a LVQ queue</title>
+ <programlisting><![CDATA[<queue>
+ <name>myqueue</name>
+ <myqueue>
+ <exchange>amq.direct</exchange>
+ <lvq>true</lvq>
+ </myqueue>
+</queue>]]></programlisting>
+ </example>
+ <para> If you wish to define your own property then you can do so using the
+ <varname>lvqKey</varname> element.</para>
+ <example>
+ <title>Configuring a LVQ queue with custom message property name</title>
+ <programlisting><![CDATA[<queue>
+ <name>myqueue</name>
+ <myqueue>
+ <exchange>amq.direct</exchange>
+ <lvq>true</lvq>
+ <lvqKey>ISIN</lvqKey>
+ </myqueue>
+</queue>]]></programlisting>
+ </example>
+ </section>
+ </section>
+ <section role="h2" id="OtherQueueTypes-CreateUsingJmsOrJmx">
+ <title>Using JMS or AMQP</title>
+ <para>To create a priority, sorted or LVQ queue programmatically from JMX or using a Qpid
+ extension to JMS, pass the appropriate queue-declare arguments.</para>
+ <table>
+ <tgroup cols="4">
+ <thead>
+ <row>
+ <entry>Queue type</entry>
+ <entry>Argument name</entry>
+ <entry>Argument name</entry>
+ <entry>Argument Description</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>priority</entry>
+ <entry>priorities</entry>
+ <entry>java.lang.Integer</entry>
+ <entry>Specifies a priority queue with given number priorities</entry>
+ </row>
+ <row>
+ <entry>sorted</entry>
+ <entry>qpid.queue_sort_key</entry>
+ <entry>java.lang.String</entry>
+ <entry>Specifies sorted queue with given message property used to sort the
+ entries</entry>
+ </row>
+ <row>
+ <entry>lvq</entry>
+ <entry>qpid.last_value_queue_key</entry>
+ <entry>java.lang.String</entry>
+ <entry>Specifies lvq queue with given message property used to conflate the
+ entries</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <para>The following example illustrates the creation of the a LVQ queue from a
+ javax.jms.Session object. Note that this utilises a Qpid specific extension to JMS and
+ involves casting the session object back to its Qpid base-class.</para>
+ <example>
+ <title>Creation of an LVQ using the Qpid extension to JMS</title>
+ <programlisting><![CDATA[Map<String,Object> arguments = new HashMap<String, Object>();
+arguments.put("qpid.last_value_queue_key","ISIN");
+((AMQSession<?,?>) session).createQueue(queueName, autoDelete, durable, exclusive, arguments);]]></programlisting>
+
+ </example>
+ <para> The following example illustrates the creation of the sorted queue from a the JMX
+ interface using the ManagedBroker interface. </para>
+ <example>
+ <title>Creation of a sorted queue using JMX</title>
+ <programlisting><![CDATA[Map<String, Object> environment = new HashMap<String, Object>();
+environment.put(JMXConnector.CREDENTIALS, new String[] {"admin","password"});
+// Connect to service
+JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:8999/jmxrmi");
+JMXConnector jmxConnector = JMXConnectorFactory.connect(url, environment);
+MBeanServerConnection mbsc = jmxConnector.getMBeanServerConnection();
+// Object name for ManagedBroker for virtualhost myvhost
+ObjectName objectName = new ObjectName("org.apache.qpid:type=VirtualHost.VirtualHostManager,VirtualHost=myvhost");
+// Get the ManagedBroker object
+ManagedBroker managedBroker = JMX.newMBeanProxy(mbsc, objectName, ManagedBroker.class);;
+
+// Create the queue passing arguments
+Map<String,Object> arguments = new HashMap<String, Object>();
+arguments.put("qpid.queue_sort_key","myheader");
+managedBroker.createNewQueue("myqueue", null, true, arguments);]]></programlisting>
+ </example>
+ </section>
+ </section>
+
+ <section role="h2" id="OtherQueueTypes-SetLowPrefetch">
+ <title>Low pre-fetch</title>
+ <para>Qpid clients receive buffered messages in batches, sized according to the pre-fetch value.
+ The current default is 500. </para>
+ <para>However, if you use the default value you will probably <emphasis>not</emphasis> see
+ desirable behaviour when using priority, sorted or lvq queues. Once the broker has sent a
+ message to the client its delivery order is then fixed, regardless of the special behaviour of
+ the queue. </para>
+ <para>For example, if using a priority queue and a prefetch of 100, and 100 messages arrive with
+ priority 2, the broker will send these messages to the client. If then a new message arrives
+ will priority 1, the broker cannot leap frog messages of lower priority. The priority 1 will
+ be delivered at the front of the next batch of messages to be sent to the client.</para>
+ <para> So, you need to set the prefetch values for your client (consumer) to make this sensible.
+ To do this set the Java system property <varname>max_prefetch</varname> on the client
+ environment (using -D) before creating your consumer. </para>
+ <para>A default for all client connections can be set via a system property: </para>
+ <programlisting>
+-Dmax_prefetch=1
+</programlisting>
+ <para> The prefetch can be also be adjusted on a per connection basis by adding a
+ <varname>maxprefetch</varname> value to the <ulink url="../../Programming-In-Apache-Qpid/html/QpidJNDI.html#section-jms-connection-url">Connection URLs</ulink>
+ </para>
+ <programlisting>
+amqp://guest:guest@client1/development?maxprefetch='1'&amp;brokerlist='tcp://localhost:5672'
+</programlisting>
+ <para>Setting the Qpid pre-fetch to 1 will give exact queue-type semantics as perceived by the
+ client however, this brings a performance cost. You could test with a slightly higher
+ pre-fetch to trade-off between throughput and exact semantics.</para>
+ </section>
+</section>
diff --git a/doc/book/src/java-broker/Producer-Flow-Control.xml b/doc/book/src/java-broker/Producer-Flow-Control.xml
new file mode 100644
index 0000000000..262279510e
--- /dev/null
+++ b/doc/book/src/java-broker/Producer-Flow-Control.xml
@@ -0,0 +1,217 @@
+<?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="Qpid-Producer-Flow-Control">
+ <title>Producer Flow Control</title>
+
+ <section role="h2" id="QpidProducerFlowControlGeneralInformation">
+ <title>General Information</title>
+ <para>
+ The Qpid 0.6 release introduced a simplistic producer-side flow control mechanism
+ into the Java Messaging Broker, causing producers to be flow-controlled when they
+ attempt to send messages to an overfull queue. Qpid 0.18 introduced a similar
+ mechanism triggered by an overfull persistent message store on a virtual host.
+ </para>
+ </section>
+ <section role="h2" id="QpidProducerFlowControlServerConfiguration">
+ <title>Server Configuration</title>
+ <section role="h3">
+ <title>Configuring a Queue to use flow control</title>
+ <para>
+ Flow control is enabled on a producer when it sends a message to a Queue
+ which is "overfull". The producer flow control will be rescinded when all
+ Queues on which a producer is blocking become "underfull". A Queue is defined
+ as overfull when the size (in bytes) of the messages on the queue exceeds the
+ "capacity" of the Queue. A Queue becomes "underfull" when its size becomes
+ less than the "flowResumeCapacity".
+
+ <programlisting>
+ <![CDATA[
+<queue>
+ <name>test</name>
+ <test>
+ <exchange>amq.direct</exchange>
+ <capacity>10485760</capacity> <!-- set the queue capacity to 10Mb -->
+ <flowResumeCapacity>8388608</flowResumeCapacity> <!-- set the resume capacity to 8Mb -->
+ </test>
+</queue>
+ ]]>
+ </programlisting>
+
+ The default for all queues on a virtual host can also be set
+
+ <programlisting>
+ <![CDATA[
+<virtualhosts>
+ <virtualhost>
+ <name>localhost</name>
+ <localhost>
+ <capacity>10485760</capacity> <!-- set the queue capacity to 10Mb -->
+ <flowResumeCapacity>8388608</flowResumeCapacity> <!-- set the resume capacity to 8Mb -->
+ </localhost>
+ </virtualhost>
+</virtualhosts>
+ ]]>
+ </programlisting>
+
+ Where no flowResumeCapacity is set, the flowResumeCapacity is set to be equal
+ to the capacity. Where no capacity is set, capacity is defaulted to 0 meaning
+ there is no capacity limit.
+ </para>
+ <section role="h4">
+ <title>Broker Log Messages</title>
+ <para>
+ There are four new Broker log messages that may occur if flow control through queue capacity limits is enabled.
+ Firstly, when a capacity limited queue becomes overfull, a log message similar to the following is produced
+ </para>
+ <programlisting>
+MESSAGE [vh(/test)/qu(MyQueue)] [vh(/test)/qu(MyQueue)] QUE-1003 : Overfull : Size : 1,200 bytes, Capacity : 1,000
+ </programlisting>
+ <para>Then for each channel which becomes blocked upon the overful queue a log message similar to the following is produced:</para>
+ <programlisting>
+MESSAGE [con:2(guest@anonymous(713889609)/test)/ch:1] [con:2(guest@anonymous(713889609)/test)/ch:1] CHN-1005 : Flow Control Enforced (Queue MyQueue)
+ </programlisting>
+ <para>When enough messages have been consumed from the queue that it becomes underfull, then the following log is generated: </para>
+ <programlisting>
+MESSAGE [vh(/test)/qu(MyQueue)] [vh(/test)/qu(MyQueue)] QUE-1004 : Underfull : Size : 600 bytes, Resume Capacity : 800
+ </programlisting>
+ <para>And for every channel which becomes unblocked you will see a message similar to: </para>
+ <programlisting>
+MESSAGE [con:2(guest@anonymous(713889609)/test)/ch:1] [con:2(guest@anonymous(713889609)/test)/ch:1] CHN-1006 : Flow Control Removed
+ </programlisting>
+ <para>Obviously the details of connection, virtual host, queue, size, capacity, etc would depend on the configuration in use.</para>
+
+
+ </section><!-- Broker Log Messages -->
+ </section><!-- Configuring a Queue to use flow control -->
+
+ <section role="h3">
+ <title>Disk quota-based flow control</title>
+ <para>
+ Since version 0.18 of Qpid Broker, flow control can be triggered when a
+ configured disk quota is exceeded. This is supported by the BDB and Derby message stores.
+ </para>
+ <para>
+ This functionality blocks all producers on reaching the disk overflow limit. When consumers
+ consume the messages, causing disk space usage to falls below the underflow limit, the
+ producers are unblocked and continue working as normal.
+ </para>
+ <para>
+ Two limits can be configured:
+ </para>
+ <para>
+ overfull limit - the maximum space on disk (in bytes) which can be used by store.
+ </para>
+ <para>
+ underfull limit - when the space on disk drops below this limit, producers are allowed to resume publishing.
+ </para>
+ <para>
+ An example of quota configuration for the BDB message store is provided below.
+ </para>
+ <programlisting>
+ <![CDATA[
+<store>
+ <class>org.apache.qpid.server.store.berkeleydb.BDBMessageStore</class>
+ <environment-path>${work}/bdbstore/test</environment-path>
+ <overfull-size>50000000</overfull-size>
+ <underfull-size>45000000</underfull-size>
+</store>
+ ]]>
+ </programlisting>
+ <para>
+ The disk quota functionality is based on "best effort" principle. This means the broker
+ cannot guarantee that the disk space limit will not be exceeded. If several concurrent
+ transactions are started before the limit is reached, which collectively cause the limit
+ to be exceeded, the broker may allow all of them to be committed.
+ </para>
+
+ <section role="h4">
+ <title>Broker Log Messages for quota flow control</title>
+ <para>
+ There are 2 new broker log messages that may occur if flow control through disk quota limits is enabled.
+ When the virtual host is blocked due to exceeding of the disk quota limit the following message
+ appears in the broker log
+ <programlisting>
+[vh(/test)/ms(BDBMessageStore)] MST-1008 : Store overfull, flow control will be enforced
+ </programlisting>
+ When virtual host is unblocked after cleaning the disk space the following message appears in the broker log
+ <programlisting>
+[vh(/test)/ms(BDBMessageStore)] MST-1009 : Store overfull condition cleared
+ </programlisting>
+ </para>
+ </section>
+ </section><!-- Disk quota-based flow control -->
+ </section><!-- Server configuration -->
+
+
+ <section role="h2" id="QpidProducerFlowControlClientImpact">
+ <title>Client impact and configuration</title>
+ <para>
+ If a producer sends to a queue which is overfull, the broker will respond by
+ instructing the client not to send any more messages. The impact of this is
+ that any future attempts to send will block until the broker rescinds the flow control order.
+ </para>
+ <para>
+ While blocking the client will periodically log the fact that it is blocked waiting on flow control.
+ </para>
+ <programlisting>
+WARN Message send delayed by 5s due to broker enforced flow control
+WARN Message send delayed by 10s due to broker enforced flow control
+ </programlisting>
+ <para>
+ After a set period the send will timeout and throw a JMSException to the calling code.
+ </para>
+ <para>
+ If such a JMSException is thrown, the message will not be sent to the broker,
+ however the underlying Session may still be active - in particular if the
+ Session is transactional then the current transaction will not be automatically
+ rolled back. Users may choose to either attempt to resend the message, or to
+ roll back any transactional work and close the Session.
+ </para>
+ <para>
+ Both the timeout delay and the periodicity of the warning messages can be set
+ using Java system properties.
+ </para>
+ <para>
+ The amount of time (in milliseconds) to wait before timing out
+ is controlled by the property qpid.flow_control_wait_failure.
+ </para>
+ <para>
+ The frequency at which the log message informing that the producer is flow
+ controlled is sent is controlled by the system property qpid.flow_control_wait_notify_period.
+ </para>
+ <para>
+ Adding the following to the command line to start the client would result in a timeout of one minute,
+ with warning messages every ten seconds:
+ </para>
+ <programlisting>
+-Dqpid.flow_control_wait_failure=60000
+-Dqpid.flow_control_wait_notify_period=10000
+ </programlisting>
+ <section role="h3">
+ <title>Older Clients</title>
+ <para>
+ The flow control feature was first added to the Java broker/client in the 0.6 release. If an older client connects to the broker then the flow control commands will be ignored by it and it will not be blocked. So to fully benefit from this feature both Client and Broker need to be at least version 0.6.
+ </para>
+ </section>
+ </section> <!-- Client impact and configuration -->
+</section>
diff --git a/doc/book/src/java-broker/Qpid-Java-FAQ.xml b/doc/book/src/java-broker/Qpid-Java-FAQ.xml
index 845c343350..2940e58138 100644
--- a/doc/book/src/java-broker/Qpid-Java-FAQ.xml
+++ b/doc/book/src/java-broker/Qpid-Java-FAQ.xml
@@ -742,15 +742,9 @@ amqj.logging.level
</title>
<para>
- There are two possibilities here:
- </para><para>
- 1) The management console can be used to interogate an active
+ The management console can be used to interogate an active
broker and browse the contents of a queue.See the <xref linkend="qpid_Qpid-JMX-Management-Console"/>
page for further details.
- </para><para>
- 2) The <xref linkend="qpid_MessageStore-Tool"/> can be used to inspect
- the contents of a persistent message store. Note: this can
- currently only be used when the broker is offline.
</para>
<!--h3--></section>
@@ -773,13 +767,14 @@ amqj.logging.level
</title>
<para>
- The Java broker does not currently implement producer flow
- control. Publishes are currently asynchronous, so there is no
- ability to rate limit this automatically. While this is something
- which will be addressed in the future, it is currently up to
- applications to ensure that they do not publish faster than the
- messages are being consumed for signifcant periods of time.
- </para>
+ Switch on producer flow control to prevent temporary spikes in
+ message production over-filling the broker.
+
+ Of course, if the long-term rate of message production exceeds
+ the rate of message
+ consumption then that is an architectural problem that can only
+ be temporarily mitigated by producer flow control.
+ </para>
<!--h3--></section>
<section role="h3" id="QpidJavaFAQ-ThebrokerkeepsthrowinganOutOfMemoryexception-3F"><title>
diff --git a/doc/book/src/java-broker/Use-Priority-Queues.xml b/doc/book/src/java-broker/Use-Priority-Queues.xml
deleted file mode 100644
index 466d958d43..0000000000
--- a/doc/book/src/java-broker/Use-Priority-Queues.xml
+++ /dev/null
@@ -1,138 +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="Priority-Queues"><title>
- Use Priority Queues
- </title>
-
-
- <section role="h2" id="UsePriorityQueues-GeneralInformation"><title>
- General
- Information
- </title>
- <para>
- The Qpid M3 release introduces priority queues into the Java
- Messaging Broker, supporting JMS clients who wish to make use of
- priorities in their messaging implementation.
- </para><para>
- There are some key points around the use of priority queues in
- Qpid, discussed in the sections below.
- </para>
-<!--h2--></section>
- <section role="h2" id="UsePriorityQueues-DefiningPriorityQueues"><title>
- Defining
- Priority Queues
- </title>
- <para>
- You must define a priority queue specifically before you start to
- use it. You cannot subsequently change a queue to/from a priority
- queue (without deleting it and re-creating).
- </para><para>
- You define a queue as a priority queue in the virtualhost
- configuration file, which the broker loads at startup. When
- defining the queue, add a &lt;priority&gt;true&lt;/priority&gt;
- element. This will ensure that the queue has 10 distinct
- priorities, which is the number supported by JMS.
- </para><para>
- If you require fewer priorities, it is possible to specify a
- &lt;priorities&gt;int&lt;/priorities&gt; element (where int is a
- valid integer value between 2 and 10 inclusive) which will give
- the queue that number of distinct priorities. When messages are
- sent to that queue, their effective priority will be calculated
- by partitioning the priority space. If the number of effective
- priorities is 2, then messages with priority 0-4 are treated the
- same as "lower priority" and messages with priority 5-9 are
- treated equivalently as "higher priority".
- </para>
- <programlisting>
-&lt;queue&gt;
- &lt;name&gt;test&lt;/name&gt;
- &lt;test&gt;
- &lt;exchange&gt;amq.direct&lt;/exchange&gt;
- &lt;priority&gt;true&lt;/priority&gt;
- &lt;/test&gt;
-&lt;/queue&gt;
-</programlisting>
-<!--h2--></section>
-
- <section role="h2" id="UsePriorityQueues-Clientconfiguration-2Fmessagingmodelforpriorityqueues"><title>
- Client configuration/messaging model for priority queues
- </title>
- <para>
- There are some other configuration &amp; paradigm changes which
- are required in order that priority queues work as expected.
- </para>
- <section role="h3" id="UsePriorityQueues-Setlowprefetch"><title>
- Set low pre-fetch
- </title>
- <para>
- Qpid clients receive buffered messages in batches, sized
- according to the pre-fetch value. The current default is 5000.
- </para><para>
- However, if you use the default value you will probably
- <emphasis>not</emphasis> see desirable behaviour with messages of different
- priority. This is because a message arriving after the pre-fetch
- buffer has filled will not leap frog messages of lower priority.
- It will be delivered at the front of the next batch of buffered
- messages (if that is appropriate), but this is most likely NOT
- what you need.
- </para><para>
- So, you need to set the prefetch values for your client
- (consumer) to make this sensible. To do this set the java system
- property max_prefetch on the client environment (using -D) before
- creating your consumer.
- </para><para>
- Setting the Qpid pre-fetch to 1 for your client means that
- message priority will be honoured by the Qpid broker as it
- dispatches messages to your client. A default for all client
- connections can be set via a system property:
- </para>
- <programlisting>
--Dmax_prefetch=1
-</programlisting>
- <para>
- The prefetch can be also be adjusted on a per connection basis by
- adding a 'maxprefetch' value to the <xref linkend="Connection-URL-Format"/>
- </para>
- <programlisting>
-amqp://guest:guest@client1/development?maxprefetch='1'&amp;brokerlist='tcp://localhost:5672'
-</programlisting>
- <para>
- There is a slight performance cost here if using the receive()
- method and you could test with a slightly higher pre-fetch (up to
- 10) if the trade-off between throughput and prioritisation is
- weighted towards the former for your application. (If you're
- using OnMessage() then this is not a concern.)
- </para>
-<!--h3--></section>
- <section role="h3" id="UsePriorityQueues-Singleconsumerpersession"><title>
- Single
- consumer per session
- </title>
- <para>
- If you are using the receive() method to consume messages then
- you should also only use one consumer per session with priority
- queues. If you're using OnMessage() then this is not a concern.
- </para>
-<!--h3--></section>
-<!--h2--></section>
-</section>
diff --git a/doc/book/src/java-broker/images/HA-2N-Key.png b/doc/book/src/java-broker/images/HA-2N-Key.png
new file mode 100644
index 0000000000..3c1856d496
--- /dev/null
+++ b/doc/book/src/java-broker/images/HA-2N-Key.png
Binary files differ
diff --git a/doc/book/src/java-broker/images/HA-2N-Key.svg b/doc/book/src/java-broker/images/HA-2N-Key.svg
new file mode 100644
index 0000000000..9567f385d5
--- /dev/null
+++ b/doc/book/src/java-broker/images/HA-2N-Key.svg
@@ -0,0 +1,3 @@
+<?xml version="1.0"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xl="http://www.w3.org/1999/xlink" version="1.1" viewBox="-7 -3 435 195" width="435pt" height="195pt"><metadata xmlns:dc="http://purl.org/dc/elements/1.1/"><dc:date>2012-05-31 06:19Z</dc:date><!-- Produced by OmniGraffle Professional 5.3.6 --></metadata><defs><filter id="Shadow" filterUnits="userSpaceOnUse"><feGaussianBlur in="SourceAlpha" result="blur" stdDeviation="3.488"/><feOffset in="blur" result="offset" dx="0" dy="4"/><feFlood flood-color="black" flood-opacity=".75" result="flood"/><feComposite in="flood" in2="offset" operator="in"/></filter><linearGradient x1="0" x2="1" id="Gradient" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="white"/><stop offset="1" stop-color="#2824aa"/></linearGradient><linearGradient id="Obj_Gradient" xl:href="#Gradient" gradientTransform="translate(52.803375 70.5) rotate(90) scale(24)"/><font-face font-family="Helvetica" font-size="12" units-per-em="1000" underline-position="-75.683594" underline-thickness="49.316406" slope="0" x-height="522.94922" cap-height="717.28516" ascent="770.01953" descent="-229.98047" font-weight="500"><font-face-src><font-face-name name="Helvetica"/></font-face-src></font-face><linearGradient x1="0" x2="1" id="Gradient_2" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="white"/><stop offset="1" stop-color="#0caa25"/></linearGradient><linearGradient id="Obj_Gradient_2" xl:href="#Gradient_2" gradientTransform="translate(127.99037 28.999998) rotate(90) scale(25.5938)"/><linearGradient x1="0" x2="1" id="Gradient_3" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="white"/><stop offset="1" stop-color="#aa172d"/></linearGradient><linearGradient id="Obj_Gradient_3" xl:href="#Gradient_3" gradientTransform="translate(160.86441 28.999998) rotate(90) scale(25.5938)"/><linearGradient x1="0" x2="1" id="Gradient_4" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="white"/><stop offset="1" stop-color="#6923aa"/></linearGradient><linearGradient id="Obj_Gradient_4" xl:href="#Gradient_4" gradientTransform="translate(52.803375 107.5) rotate(90) scale(24)"/><radialGradient cx="0" cy="0" r="1" id="Gradient_5" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="white"/><stop offset=".5" stop-color="#b5d0ea"/><stop offset="1" stop-color="#aaa"/></radialGradient><radialGradient id="Obj_Gradient_5" xl:href="#Gradient_5" gradientTransform="translate(56.678375 41.796898) scale(37.736065)"/><marker orient="auto" overflow="visible" markerUnits="strokeWidth" id="Arrow_Marker" viewBox="-1 -4 10 8" markerWidth="10" markerHeight="8" color="black"><g><path d="M 8 0 L 0 -3 L 0 3 Z" fill="none" stroke="currentColor" stroke-width="1"/></g></marker><marker orient="auto" overflow="visible" markerUnits="strokeWidth" id="FilledArrow_Marker" viewBox="-1 -3 6 6" markerWidth="6" markerHeight="6" color="black"><g><path d="M 3.7333333 0 L 0 -1.4 L 0 1.4 Z" fill="currentColor" stroke="currentColor" stroke-width="1"/></g></marker><linearGradient x1="0" x2="1" id="Gradient_6" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="white"/><stop offset="1" stop-color="#b5011d"/></linearGradient><linearGradient id="Obj_Gradient_6" xl:href="#Gradient_6" gradientTransform="translate(287.5 113.94637) rotate(90) scale(26.035202)"/><radialGradient cx="0" cy="0" r="1" id="Gradient_7" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="white"/><stop offset=".5" stop-color="#ea061f"/><stop offset="1" stop-color="#aaa"/></radialGradient><radialGradient id="Obj_Gradient_7" xl:href="#Gradient_7" gradientTransform="translate(280 41) scale(26.907248)"/><font-face font-family="Arial Unicode MS" font-size="36" panose-1="2 11 6 4 2 2 2 2 2 4" units-per-em="1000" underline-position="-100.097656" underline-thickness="49.804688" slope="0" x-height="529.78516" cap-height="728.02734" ascent="1068.84766" descent="-270.9961" font-weight="500"><font-face-src><font-face-name name="ArialUnicodeMS"/></font-face-src></font-face></defs><g stroke="none" stroke-opacity="1" stroke-dasharray="none" fill="none" fill-opacity="1"><title>Canvas 7</title><g><title>Layer 1</title><g><use xl:href="#id240_Graphic" filter="url(#Shadow)"/><use xl:href="#id239_Graphic" filter="url(#Shadow)"/><use xl:href="#id238_Graphic" filter="url(#Shadow)"/><use xl:href="#id237_Graphic" filter="url(#Shadow)"/><use xl:href="#id236_Graphic" filter="url(#Shadow)"/><use xl:href="#id235_Graphic" filter="url(#Shadow)"/><use xl:href="#id229_Graphic" filter="url(#Shadow)"/><use xl:href="#id227_Graphic" filter="url(#Shadow)"/></g><g id="id240_Graphic"><rect x="13.999878" y="13" width="394.00012" height="155" fill="white"/><rect x="13.999878" y="13" width="394.00012" height="155" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/></g><g id="id239_Graphic"><rect x="28.177876" y="70.5" width="49.251003" height="24" fill="url(#Obj_Gradient)"/><rect x="28.177876" y="70.5" width="49.251003" height="24" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><text transform="translate(33.177876 75.5)" fill="black"><tspan font-family="Helvetica" font-size="12" font-weight="500" x="1.9536247" y="11" textLength="35.34375">Broker</tspan></text></g><g id="id238_Graphic"><path d="M 115.652176 41.796898 L 121.821274 28.999998 L 134.15947 28.999998 L 140.32857 41.796898 L 134.15947 54.593796 L 121.821274 54.593796 Z" fill="url(#Obj_Gradient_2)"/><path d="M 115.652176 41.796898 L 121.821274 28.999998 L 134.15947 28.999998 L 140.32857 41.796898 L 134.15947 54.593796 L 121.821274 54.593796 Z" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/></g><g id="id237_Graphic"><path d="M 148.526215 41.796898 L 154.69531 28.999998 L 167.03351 28.999998 L 173.20261 41.796898 L 167.03351 54.593796 L 154.69531 54.593796 Z" fill="url(#Obj_Gradient_3)"/><path d="M 148.526215 41.796898 L 154.69531 28.999998 L 167.03351 28.999998 L 173.20261 41.796898 L 167.03351 54.593796 L 154.69531 54.593796 Z" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/></g><g id="id236_Graphic"><path d="M 32.853378 107.5 L 72.753372 107.5 C 77.472977 107.5 81.303375 112.876 81.303375 119.5 C 81.303375 126.124 77.472977 131.5 72.753372 131.5 L 32.853378 131.5 C 28.133776 131.5 24.303375 126.124 24.303375 119.5 C 24.303375 112.876 28.133776 107.5 32.853378 107.5" fill="url(#Obj_Gradient_4)"/><path d="M 32.853378 107.5 L 72.753372 107.5 C 77.472977 107.5 81.303375 112.876 81.303375 119.5 C 81.303375 126.124 77.472977 131.5 72.753372 131.5 L 32.853378 131.5 C 28.133776 131.5 24.303375 126.124 24.303375 119.5 C 24.303375 112.876 28.133776 107.5 32.853378 107.5" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><text transform="translate(35.003376 112.5)" fill="black"><tspan font-family="Helvetica" font-size="12" font-weight="500" x="2.4601574" y="11" textLength="30.679688">Client</tspan></text></g><g id="id235_Graphic"><path d="M 30.434645 43.17154 C 18.959625 41.796898 23.535576 30.224663 41.840797 32.199223 C 43.539116 28.35017 64.825623 28.974915 64.686462 32.199223 C 78.033752 28.075294 95.09079 36.298325 83.649857 40.422256 C 97.37842 42.421642 83.476616 53.194073 72.209625 51.394573 C 71.307922 54.39391 51.165936 55.443512 49.398033 51.394573 C 37.992596 55.718647 14.210434 49.070145 30.434645 43.17154 Z" fill="url(#Obj_Gradient_5)"/><path d="M 30.434645 43.17154 C 18.959625 41.796898 23.535576 30.224663 41.840797 32.199223 C 43.539116 28.35017 64.825623 28.974915 64.686462 32.199223 C 78.033752 28.075294 95.09079 36.298325 83.649857 40.422256 C 97.37842 42.421642 83.476616 53.194073 72.209625 51.394573 C 71.307922 54.39391 51.165936 55.443512 49.398033 51.394573 C 37.992596 55.718647 14.210434 49.070145 30.434645 43.17154 Z" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><text transform="translate(36.828377 34.796898)" fill="black"><tspan font-family="Helvetica" font-size="12" font-weight="500" x=".84511757" y="11" textLength="38.009766">Cluster</tspan></text></g><text transform="translate(194.40121 29)" fill="black"><tspan font-family="Helvetica" font-size="12" font-weight="500" x="0" y="11" textLength="8.0039062">V</tspan><tspan font-family="Helvetica" font-size="12" font-weight="500" x="7.7929688" y="11" textLength="26.009766">irtual</tspan><tspan font-family="Helvetica" font-size="12" font-weight="500" x="0" y="25" textLength="22.68164">host</tspan></text><line x1="115.65217" y1="84" x2="162.7522" y2="84" marker-end="url(#Arrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><line x1="114.77717" y1="114.406006" x2="155.878815" y2="114.99225" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="3"/><text transform="translate(181.40121 70.5)" fill="black"><tspan font-family="Helvetica" font-size="12" font-weight="500" x="0" y="11" textLength="59.367188">Replication</tspan><tspan font-family="Helvetica" font-size="12" font-weight="500" x="0" y="25" textLength="36.673828">stream</tspan></text><text transform="translate(181.90121 93.906006)" fill="black"><tspan font-family="Helvetica" font-size="12" font-weight="500" x="0" y="25" textLength="30.679688">Client</tspan><tspan font-family="Helvetica" font-size="12" font-weight="500" x="0" y="39" textLength="58.04297">connection</tspan></text><g id="id229_Graphic"><path d="M 257.6145 123.341385 L 303.64609 123.13183 C 303.64609 123.13183 305.97821 110.84691 310.80124 114.69145 C 315.62408 118.53591 319 121.44636 319 121.44636 L 315.92612 122.44486 L 307.22827 122.069695 L 307.22821 132.69258 L 315.47678 133.06787 C 315.47678 133.06787 315.92618 136.46542 315.92618 136.78604 C 315.92618 137.10628 311.77792 139.65259 309.63474 139.972885 C 307.49097 140.29318 304.06018 131.63016 304.06018 131.63039 C 304.06018 131.63039 257.61444 130.06921 257.48056 130.06921 C 257.34662 130.06921 256.13666 132.15001 256.00693 126.86558 C 255.87709 121.581276 257.6145 123.341385 257.6145 123.341385 Z" fill="url(#Obj_Gradient_6)"/><path d="M 257.6145 123.341385 L 303.64609 123.13183 C 303.64609 123.13183 305.97821 110.84691 310.80124 114.69145 C 315.62408 118.53591 319 121.44636 319 121.44636 L 315.92612 122.44486 L 307.22827 122.069695 L 307.22821 132.69258 L 315.47678 133.06787 C 315.47678 133.06787 315.92618 136.46542 315.92618 136.78604 C 315.92618 137.10628 311.77792 139.65259 309.63474 139.972885 C 307.49097 140.29318 304.06018 131.63016 304.06018 131.63039 C 304.06018 131.63039 257.61444 130.06921 257.48056 130.06921 C 257.34662 130.06921 256.13666 132.15001 256.00693 126.86558 C 255.87709 121.581276 257.6145 123.341385 257.6145 123.341385 Z" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/></g><text transform="translate(334.09879 119.963974)" fill="black"><tspan font-family="Helvetica" font-size="12" font-weight="500" x="0" y="11" textLength="35.34961">Repair</tspan></text><g id="id227_Graphic"><path d="M 260 32.310394 L 275.19995 42.241386 L 263.13727 54.738464 L 267.99988 59 L 281.17648 45.481422 L 295.20001 54.655197 L 300 49.68975 L 284.79993 39.137974 L 297.59991 27.965553 L 290.39993 23 L 279.19989 35.413807 L 266.4 25.482777 Z" fill="url(#Obj_Gradient_7)"/><path d="M 260 32.310394 L 275.19995 42.241386 L 263.13727 54.738464 L 267.99988 59 L 281.17648 45.481422 L 295.20001 54.655197 L 300 49.68975 L 284.79993 39.137974 L 297.59991 27.965553 L 290.39993 23 L 279.19989 35.413807 L 266.4 25.482777 Z" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/></g><text transform="translate(329.02448 34)" fill="black"><tspan font-family="Helvetica" font-size="12" font-weight="500" x="0" y="11" textLength="26.677734">Fault</tspan></text><text transform="translate(264 59.5)" fill="#262626"><tspan font-family="Arial Unicode MS" font-size="36" font-weight="500" fill="#262626" x="0" y="38" textLength="36">â™›</tspan></text><text transform="translate(320.52448 72)" fill="black"><tspan font-family="Helvetica" font-size="12" font-weight="500" x="0" y="11" textLength="54.035156">Designate</tspan><tspan font-family="Helvetica" font-size="12" font-weight="500" x="0" y="25" textLength="41.332031">Primary</tspan></text></g></g></svg>
diff --git a/doc/book/src/java-broker/images/HA-2N-MasterFail.png b/doc/book/src/java-broker/images/HA-2N-MasterFail.png
new file mode 100644
index 0000000000..b839d291b9
--- /dev/null
+++ b/doc/book/src/java-broker/images/HA-2N-MasterFail.png
Binary files differ
diff --git a/doc/book/src/java-broker/images/HA-2N-MasterFail.svg b/doc/book/src/java-broker/images/HA-2N-MasterFail.svg
new file mode 100644
index 0000000000..35b2c643ff
--- /dev/null
+++ b/doc/book/src/java-broker/images/HA-2N-MasterFail.svg
@@ -0,0 +1,3 @@
+<?xml version="1.0"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xl="http://www.w3.org/1999/xlink" version="1.1" viewBox="-20 -16 600 871" width="50pc" height="871pt"><metadata xmlns:dc="http://purl.org/dc/elements/1.1/"><dc:date>2012-05-31 06:19Z</dc:date><!-- Produced by OmniGraffle Professional 5.3.6 --></metadata><defs><radialGradient cx="0" cy="0" r="1" id="Gradient" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="white"/><stop offset=".5" stop-color="#b5d0ea"/><stop offset="1" stop-color="#aaa"/></radialGradient><radialGradient id="Obj_Gradient" xl:href="#Gradient" gradientTransform="translate(200.35501 136.5) scale(145.18695)"/><linearGradient x1="0" x2="1" id="Gradient_2" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="white"/><stop offset="1" stop-color="#2824aa"/></linearGradient><linearGradient id="Obj_Gradient_2" xl:href="#Gradient_2" gradientTransform="translate(212.855 146) rotate(90) scale(69)"/><linearGradient x1="0" x2="1" id="Gradient_3" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="white"/><stop offset="1" stop-color="#0caa25"/></linearGradient><linearGradient id="Obj_Gradient_3" xl:href="#Gradient_3" gradientTransform="translate(212.85451 162.5) rotate(90) scale(36)"/><linearGradient x1="0" x2="1" id="Gradient_4" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="white"/><stop offset="1" stop-color="#6923aa"/></linearGradient><linearGradient id="Obj_Gradient_4" xl:href="#Gradient_4" gradientTransform="translate(73.18171 111) rotate(90) scale(24)"/><linearGradient id="Obj_Gradient_5" xl:href="#Gradient_2" gradientTransform="translate(195.355 59.999996) rotate(90) scale(69.000007)"/><linearGradient x1="0" x2="1" id="Gradient_5" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="white"/><stop offset="1" stop-color="#aa172d"/></linearGradient><linearGradient id="Obj_Gradient_6" xl:href="#Gradient_5" gradientTransform="translate(195.35451 78) rotate(90) scale(36)"/><marker orient="auto" overflow="visible" markerUnits="strokeWidth" id="FilledArrow_Marker" viewBox="-1 -3 6 6" markerWidth="6" markerHeight="6" color="black"><g><path d="M 3.7333333 0 L 0 -1.4 L 0 1.4 Z" fill="currentColor" stroke="currentColor" stroke-width="1"/></g></marker><marker orient="auto" overflow="visible" markerUnits="strokeWidth" id="Arrow_Marker" viewBox="-1 -4 10 8" markerWidth="10" markerHeight="8" color="black"><g><path d="M 8 0 L 0 -3 L 0 3 Z" fill="none" stroke="currentColor" stroke-width="1"/></g></marker><radialGradient id="Obj_Gradient_7" xl:href="#Gradient" gradientTransform="translate(470.5 133.5) scale(145.18695)"/><linearGradient id="Obj_Gradient_8" xl:href="#Gradient_2" gradientTransform="translate(488 141.5) rotate(90) scale(69)"/><linearGradient x1="0" x2="1" id="Gradient_6" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="white"/><stop offset="1" stop-color="#aaa3a7"/></linearGradient><linearGradient id="Obj_Gradient_9" xl:href="#Gradient_6" gradientTransform="translate(487.9995 158) rotate(90) scale(36)"/><linearGradient id="Obj_Gradient_10" xl:href="#Gradient_4" gradientTransform="translate(350.21 85) rotate(90) scale(24)"/><linearGradient id="Obj_Gradient_11" xl:href="#Gradient_2" gradientTransform="translate(470.5 55.5) rotate(90) scale(69)"/><linearGradient x1="0" x2="1" id="Gradient_7" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="white"/><stop offset="1" stop-color="#aaaaa3"/></linearGradient><linearGradient id="Obj_Gradient_12" xl:href="#Gradient_7" gradientTransform="translate(470.4995 73.5) rotate(90) scale(36)"/><radialGradient cx="0" cy="0" r="1" id="Gradient_8" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="white"/><stop offset=".5" stop-color="#ea061f"/><stop offset="1" stop-color="#aaa"/></radialGradient><radialGradient id="Obj_Gradient_13" xl:href="#Gradient_8" gradientTransform="translate(488 176) scale(38.183766)"/><font-face font-family="Helvetica" font-size="12" units-per-em="1000" underline-position="-75.683594" underline-thickness="49.316406" slope="0" x-height="532.22656" cap-height="719.72656" ascent="770.01953" descent="-229.98047" font-weight="bold"><font-face-src><font-face-name name="Helvetica-Bold"/></font-face-src></font-face><radialGradient id="Obj_Gradient_14" xl:href="#Gradient" gradientTransform="translate(474.08 415.255) scale(145.18695)"/><linearGradient id="Obj_Gradient_15" xl:href="#Gradient_2" gradientTransform="translate(491.58 423.255) rotate(90) scale(69)"/><linearGradient id="Obj_Gradient_16" xl:href="#Gradient_6" gradientTransform="translate(491.5795 439.755) rotate(90) scale(36)"/><linearGradient id="Obj_Gradient_17" xl:href="#Gradient_4" gradientTransform="translate(353.79 366.755) rotate(90) scale(24.00003)"/><linearGradient id="Obj_Gradient_18" xl:href="#Gradient_2" gradientTransform="translate(474.08 337.255) rotate(90) scale(69)"/><linearGradient x1="0" x2="1" id="Gradient_9" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="white"/><stop offset="1" stop-color="#21aa1a"/></linearGradient><linearGradient id="Obj_Gradient_19" xl:href="#Gradient_9" gradientTransform="translate(474.0795 355.255) rotate(90) scale(36)"/><radialGradient id="Obj_Gradient_20" xl:href="#Gradient" gradientTransform="translate(192.79001 696.5) scale(145.18695)"/><linearGradient id="Obj_Gradient_21" xl:href="#Gradient_2" gradientTransform="translate(210.28999 704.5) rotate(90) scale(69)"/><linearGradient x1="0" x2="1" id="Gradient_10" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="white"/><stop offset="1" stop-color="#aa1f43"/></linearGradient><linearGradient id="Obj_Gradient_22" xl:href="#Gradient_10" gradientTransform="translate(210.2895 721) rotate(90) scale(36)"/><linearGradient id="Obj_Gradient_23" xl:href="#Gradient_4" gradientTransform="translate(72.5 648) rotate(90) scale(24)"/><linearGradient id="Obj_Gradient_24" xl:href="#Gradient_2" gradientTransform="translate(192.78999 618.5) rotate(90) scale(69)"/><linearGradient id="Obj_Gradient_25" xl:href="#Gradient_9" gradientTransform="translate(192.7895 636.5) rotate(90) scale(36)"/><radialGradient id="Obj_Gradient_26" xl:href="#Gradient" gradientTransform="translate(166.45009 415.255) scale(145.18695)"/><linearGradient id="Obj_Gradient_27" xl:href="#Gradient_2" gradientTransform="translate(183.95009 423.255) rotate(90) scale(69)"/><linearGradient id="Obj_Gradient_28" xl:href="#Gradient_6" gradientTransform="translate(183.9496 439.755) rotate(90) scale(36)"/><linearGradient id="Obj_Gradient_29" xl:href="#Gradient_4" gradientTransform="translate(72.5 372.755) rotate(90) scale(24)"/><linearGradient id="Obj_Gradient_30" xl:href="#Gradient_2" gradientTransform="translate(180.08009 343.255) rotate(90) scale(69)"/><linearGradient x1="0" x2="1" id="Gradient_11" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="white"/><stop offset="1" stop-color="#a9a5a6"/></linearGradient><linearGradient id="Obj_Gradient_31" xl:href="#Gradient_11" gradientTransform="translate(180.0796 361.255) rotate(90) scale(36)"/><radialGradient id="Obj_Gradient_32" xl:href="#Gradient_8" gradientTransform="translate(183.95009 457.755) scale(38.183766)"/><font-face font-family="Arial Unicode MS" font-size="36" panose-1="2 11 6 4 2 2 2 2 2 4" units-per-em="1000" underline-position="-100.097656" underline-thickness="49.804688" slope="0" x-height="529.78516" cap-height="728.02734" ascent="1068.84766" descent="-270.9961" font-weight="500"><font-face-src><font-face-name name="ArialUnicodeMS"/></font-face-src></font-face></defs><g stroke="none" stroke-opacity="1" stroke-dasharray="none" fill="none" fill-opacity="1"><title>Canvas 2</title><g><title>Layer 1</title><rect x="0" y="0" width="278" height="273" fill="white"/><rect x="0" y="0" width="278" height="273" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><path d="M 146.38904 149.98122 C 122.79251 136.5 132.20221 23.010353 169.84393 42.375 C 173.33626 4.6271057 217.1085 10.754013 216.82236 42.375 C 244.26889 1.931366 279.34393 82.575165 255.81749 123.01879 C 284.04803 142.62691 255.46124 248.27281 232.29251 230.625 C 230.43831 260.03967 189.01958 270.33319 185.38417 230.625 C 161.930725 273.03143 113.02657 207.82918 146.38904 149.98122 Z" fill="url(#Obj_Gradient)"/><path d="M 146.38904 149.98122 C 122.79251 136.5 132.20221 23.010353 169.84393 42.375 C 173.33626 4.6271057 217.1085 10.754013 216.82236 42.375 C 244.26889 1.931366 279.34393 82.575165 255.81749 123.01879 C 284.04803 142.62691 255.46124 248.27281 232.29251 230.625 C 230.43831 260.03967 189.01958 270.33319 185.38417 230.625 C 161.930725 273.03143 113.02657 207.82918 146.38904 149.98122 Z" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><rect x="179.355" y="146" width="67" height="69" fill="url(#Obj_Gradient_2)"/><rect x="179.355" y="146" width="67" height="69" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><path d="M 192.524 180.5 L 202.68925 162.5 L 223.01976 162.5 L 233.18501 180.5 L 223.01976 198.5 L 202.68925 198.5 Z" fill="url(#Obj_Gradient_3)"/><path d="M 192.524 180.5 L 202.68925 162.5 L 223.01976 162.5 L 233.18501 180.5 L 223.01976 198.5 L 202.68925 198.5 Z" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><path d="M 62.68171 111 L 83.68171 111 C 86.16571 111 88.18171 116.376 88.18171 123 C 88.18171 129.62399 86.16571 135 83.68171 135 L 62.68171 135 C 60.197708 135 58.18171 129.62399 58.18171 123 C 58.18171 116.376 60.197708 111 62.68171 111" fill="url(#Obj_Gradient_4)"/><path d="M 62.68171 111 L 83.68171 111 C 86.16571 111 88.18171 116.376 88.18171 123 C 88.18171 129.62399 86.16571 135 83.68171 135 L 62.68171 135 C 60.197708 135 58.18171 129.62399 58.18171 123 C 58.18171 116.376 60.197708 111 62.68171 111" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><rect x="161.855" y="60" width="67" height="69" fill="url(#Obj_Gradient_5)"/><rect x="161.855" y="60" width="67" height="69" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><path d="M 175.024 96 L 185.18925 78 L 205.51976 78 L 215.68501 96 L 205.51976 114 L 185.18925 114 Z" fill="url(#Obj_Gradient_6)"/><path d="M 175.024 96 L 185.18925 78 L 205.51976 78 L 215.68501 96 L 205.51976 114 L 185.18925 114 Z" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><path d="M 74.355003 137 C 80.38701 150.765915 72.80871 171.11536 92.452835 178.3019 C 109.12348 184.40063 145.40762 181.02281 176.33522 180.23158" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="3"/><path d="M 222.38084 162.05576 C 227.03842 153.03807 238.59448 143.85422 236.355 135 C 234.66139 128.303986 225.07715 121.79347 216.5538 115.25858" marker-end="url(#Arrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><rect x="281.29001" y="0" width="278.00003" height="273" fill="white"/><rect x="281.29001" y="0" width="278.00003" height="273" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><path d="M 416.53403 146.98122 C 392.9375 133.5 402.3472 20.010353 439.98892 39.375 C 443.48123 1.6271057 487.2535 7.754013 486.96735 39.375 C 514.41388 -1.06863403 549.4889 79.575165 525.96246 120.01879 C 554.19305 139.62691 525.60626 245.27281 502.4375 227.625 C 500.5833 257.03967 459.16455 267.33319 455.52917 227.625 C 432.07571 270.03143 383.17157 204.82918 416.53403 146.98122 Z" fill="url(#Obj_Gradient_7)"/><path d="M 416.53403 146.98122 C 392.9375 133.5 402.3472 20.010353 439.98892 39.375 C 443.48123 1.6271057 487.2535 7.754013 486.96735 39.375 C 514.41388 -1.06863403 549.4889 79.575165 525.96246 120.01879 C 554.19305 139.62691 525.60626 245.27281 502.4375 227.625 C 500.5833 257.03967 459.16455 267.33319 455.52917 227.625 C 432.07571 270.03143 383.17157 204.82918 416.53403 146.98122 Z" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><rect x="454.5" y="141.5" width="67" height="69" fill="url(#Obj_Gradient_8)"/><rect x="454.5" y="141.5" width="67" height="69" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><path d="M 467.669 176 L 477.83426 158 L 498.16476 158 L 508.33002 176 L 498.16476 194 L 477.83426 194 Z" fill="url(#Obj_Gradient_9)"/><path d="M 467.669 176 L 477.83426 158 L 498.16476 158 L 508.33002 176 L 498.16476 194 L 477.83426 194 Z" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><path d="M 339.71 85 L 360.71 85 C 363.194 85 365.21 90.376 365.21 97 C 365.21 103.624 363.194 109 360.71 109 L 339.71 109 C 337.22598 109 335.21 103.624 335.21 97 C 335.21 90.376 337.22598 85 339.71 85" fill="url(#Obj_Gradient_10)"/><path d="M 339.71 85 L 360.71 85 C 363.194 85 365.21 90.376 365.21 97 C 365.21 103.624 363.194 109 360.71 109 L 339.71 109 C 337.22598 109 335.21 103.624 335.21 97 C 335.21 90.376 337.22598 85 339.71 85" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><rect x="437" y="55.5" width="67" height="69" fill="url(#Obj_Gradient_11)"/><rect x="437" y="55.5" width="67" height="69" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><path d="M 450.169 91.5 L 460.33426 73.5 L 480.66476 73.5 L 490.83002 91.5 L 480.66476 109.5 L 460.33426 109.5 Z" fill="url(#Obj_Gradient_12)"/><path d="M 450.169 91.5 L 460.33426 73.5 L 480.66476 73.5 L 490.83002 91.5 L 480.66476 109.5 L 460.33426 109.5 Z" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><path d="M 461 162.96559 L 481.51996 177.86208 L 465.23532 196.6077 L 471.79984 203 L 489.58826 182.72214 L 508.52 196.48279 L 515 189.03462 L 494.4799 173.20695 L 511.7599 156.44833 L 502.0399 149 L 486.91986 167.62071 L 469.64001 152.72417 Z" fill="url(#Obj_Gradient_13)"/><path d="M 461 162.96559 L 481.51996 177.86208 L 465.23532 196.6077 L 471.79984 203 L 489.58826 182.72214 L 508.52 196.48279 L 515 189.03462 L 494.4799 173.20695 L 511.7599 156.44833 L 502.0399 149 L 486.91986 167.62071 L 469.64001 152.72417 Z" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><text transform="translate(5.8400302 4)" fill="black"><tspan font-family="Helvetica" font-size="12" font-weight="bold" x=".16308594" y="11" textLength="6.673828">1</tspan></text><rect x="281.29001" y="278.755" width="278.00003" height="273" fill="white"/><rect x="281.29001" y="278.755" width="278.00003" height="273" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><path d="M 420.11401 428.7362 C 396.51749 415.255 405.92719 301.76535 443.5689 321.13 C 447.06122 283.38211 490.8335 289.50903 490.54733 321.13 C 517.9939 280.68637 553.0689 361.33017 529.54248 401.7738 C 557.773 421.38193 529.18622 527.02783 506.0175 509.38 C 504.1633 538.79468 462.74454 549.0882 459.10913 509.38 C 435.6557 551.78644 386.75156 486.58417 420.11401 428.7362 Z" fill="url(#Obj_Gradient_14)"/><path d="M 420.11401 428.7362 C 396.51749 415.255 405.92719 301.76535 443.5689 321.13 C 447.06122 283.38211 490.8335 289.50903 490.54733 321.13 C 517.9939 280.68637 553.0689 361.33017 529.54248 401.7738 C 557.773 421.38193 529.18622 527.02783 506.0175 509.38 C 504.1633 538.79468 462.74454 549.0882 459.10913 509.38 C 435.6557 551.78644 386.75156 486.58417 420.11401 428.7362 Z" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><rect x="458.08" y="423.255" width="66.99997" height="69" fill="url(#Obj_Gradient_15)"/><rect x="458.08" y="423.255" width="66.99997" height="69" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><path d="M 471.249 457.755 L 481.41425 439.755 L 501.74475 439.755 L 511.91 457.755 L 501.74475 475.755 L 481.41425 475.755 Z" fill="url(#Obj_Gradient_16)"/><path d="M 471.249 457.755 L 481.41425 439.755 L 501.74475 439.755 L 511.91 457.755 L 501.74475 475.755 L 481.41425 475.755 Z" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><path d="M 343.29 366.755 L 364.29 366.755 C 366.77402 366.755 368.79 372.13101 368.79 378.755 C 368.79 385.379 366.77402 390.755 364.29 390.755 L 343.29 390.755 C 340.806 390.755 338.79 385.379 338.79 378.755 C 338.79 372.13101 340.806 366.755 343.29 366.755" fill="url(#Obj_Gradient_17)"/><path d="M 343.29 366.755 L 364.29 366.755 C 366.77402 366.755 368.79 372.13101 368.79 378.755 C 368.79 385.379 366.77402 390.755 364.29 390.755 L 343.29 390.755 C 340.806 390.755 338.79 385.379 338.79 378.755 C 338.79 372.13101 340.806 366.755 343.29 366.755" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><rect x="440.57999" y="337.255" width="67" height="69" fill="url(#Obj_Gradient_18)"/><rect x="440.57999" y="337.255" width="67" height="69" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><path d="M 453.749 373.255 L 463.91425 355.255 L 484.24475 355.255 L 494.41 373.255 L 484.24475 391.255 L 463.91425 391.255 Z" fill="url(#Obj_Gradient_19)"/><path d="M 453.749 373.255 L 463.91425 355.255 L 484.24475 355.255 L 494.41 373.255 L 484.24475 391.255 L 463.91425 391.255 Z" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><path d="M 365.46664 366.5985 C 373.74026 357.98486 375.04666 340.75385 390.29 340.755 C 402.3567 340.75592 423.16241 351.55505 442.3288 360.32996" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="3"/><rect x="0" y="558" width="278" height="273" fill="white"/><rect x="0" y="558" width="278" height="273" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><path d="M 138.824036 709.9812 C 115.22751 696.5 124.63721 583.01038 162.27893 602.375 C 165.77126 564.62708 209.5435 570.75403 209.25735 602.375 C 236.70389 561.9314 271.77893 642.57513 248.25249 683.0188 C 276.48303 702.6269 247.89624 808.27283 224.72751 790.625 C 222.8733 820.03967 181.45457 830.3332 177.81917 790.625 C 154.36572 833.03143 105.46157 767.82916 138.824036 709.9812 Z" fill="url(#Obj_Gradient_20)"/><path d="M 138.824036 709.9812 C 115.22751 696.5 124.63721 583.01038 162.27893 602.375 C 165.77126 564.62708 209.5435 570.75403 209.25735 602.375 C 236.70389 561.9314 271.77893 642.57513 248.25249 683.0188 C 276.48303 702.6269 247.89624 808.27283 224.72751 790.625 C 222.8733 820.03967 181.45457 830.3332 177.81917 790.625 C 154.36572 833.03143 105.46157 767.82916 138.824036 709.9812 Z" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><rect x="176.78999" y="704.5" width="67" height="69" fill="url(#Obj_Gradient_21)"/><rect x="176.78999" y="704.5" width="67" height="69" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><path d="M 189.959 739 L 200.12425 721 L 220.45476 721 L 230.62001 739 L 220.45476 757 L 200.12425 757 Z" fill="url(#Obj_Gradient_22)"/><path d="M 189.959 739 L 200.12425 721 L 220.45476 721 L 230.62001 739 L 220.45476 757 L 200.12425 757 Z" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><path d="M 62 648 L 83 648 C 85.484 648 87.5 653.37598 87.5 660 C 87.5 666.62402 85.484 672 83 672 L 62 672 C 59.516 672 57.5 666.62402 57.5 660 C 57.5 653.37598 59.516 648 62 648" fill="url(#Obj_Gradient_23)"/><path d="M 62 648 L 83 648 C 85.484 648 87.5 653.37598 87.5 660 C 87.5 666.62402 85.484 672 83 672 L 62 672 C 59.516 672 57.5 666.62402 57.5 660 C 57.5 653.37598 59.516 648 62 648" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><rect x="159.28999" y="618.5" width="67" height="69" fill="url(#Obj_Gradient_24)"/><rect x="159.28999" y="618.5" width="67" height="69" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><path d="M 172.459 654.5 L 182.62425 636.5 L 202.95476 636.5 L 213.12001 654.5 L 202.95476 672.5 L 182.62425 672.5 Z" fill="url(#Obj_Gradient_25)"/><path d="M 172.459 654.5 L 182.62425 636.5 L 202.95476 636.5 L 213.12001 654.5 L 202.95476 672.5 L 182.62425 672.5 Z" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><path d="M 84.176636 647.8435 C 92.450264 639.22986 93.75663 621.99884 109 622 C 121.06667 622.0009 141.87247 632.80005 161.03886 641.575" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="3"/><path d="M 181.93205 672.16388 C 174.38545 684.44135 157.17926 699.40002 159.28999 709 C 160.93364 716.4756 174.29166 720.7052 185.68005 725.4799" marker-end="url(#Arrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><text transform="translate(286 8)" fill="black"><tspan font-family="Helvetica" font-size="12" font-weight="bold" x=".16308594" y="11" textLength="6.673828">2</tspan></text><text transform="translate(286 289.62299)" fill="black"><tspan font-family="Helvetica" font-size="12" font-weight="bold" x=".16308594" y="11" textLength="6.673828">4</tspan></text><text transform="translate(10.3773594 571.472)" fill="black"><tspan font-family="Helvetica" font-size="12" font-weight="bold" x=".16308594" y="11" textLength="6.673828">5</tspan></text><rect x="0" y="278.755" width="278" height="273" fill="white"/><rect x="0" y="278.755" width="278" height="273" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><path d="M 112.48411 428.7362 C 88.88759 415.255 98.297287 301.76535 135.93901 321.13 C 139.431335 283.38211 183.20358 289.50903 182.91743 321.13 C 210.36397 280.68637 245.439 361.33017 221.91257 401.7738 C 250.14313 421.38193 221.55634 527.02783 198.38759 509.38 C 196.53339 538.79468 155.11465 549.0882 151.47925 509.38 C 128.02582 551.78644 79.12165 486.58417 112.48411 428.7362 Z" fill="url(#Obj_Gradient_26)"/><path d="M 112.48411 428.7362 C 88.88759 415.255 98.297287 301.76535 135.93901 321.13 C 139.431335 283.38211 183.20358 289.50903 182.91743 321.13 C 210.36397 280.68637 245.439 361.33017 221.91257 401.7738 C 250.14313 421.38193 221.55634 527.02783 198.38759 509.38 C 196.53339 538.79468 155.11465 549.0882 151.47925 509.38 C 128.02582 551.78644 79.12165 486.58417 112.48411 428.7362 Z" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><rect x="150.45009" y="423.255" width="67" height="69" fill="url(#Obj_Gradient_27)"/><rect x="150.45009" y="423.255" width="67" height="69" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><path d="M 163.61909 457.755 L 173.78435 439.755 L 194.11485 439.755 L 204.2801 457.755 L 194.11485 475.755 L 173.78435 475.755 Z" fill="url(#Obj_Gradient_28)"/><path d="M 163.61909 457.755 L 173.78435 439.755 L 194.11485 439.755 L 204.2801 457.755 L 194.11485 475.755 L 173.78435 475.755 Z" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><path d="M 62 372.755 L 83 372.755 C 85.484 372.755 87.5 378.13101 87.5 384.755 C 87.5 391.379 85.484 396.755 83 396.755 L 62 396.755 C 59.516 396.755 57.5 391.379 57.5 384.755 C 57.5 378.13101 59.516 372.755 62 372.755" fill="url(#Obj_Gradient_29)"/><path d="M 62 372.755 L 83 372.755 C 85.484 372.755 87.5 378.13101 87.5 384.755 C 87.5 391.379 85.484 396.755 83 396.755 L 62 396.755 C 59.516 396.755 57.5 391.379 57.5 384.755 C 57.5 378.13101 59.516 372.755 62 372.755" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><rect x="146.58009" y="343.255" width="67" height="69" fill="url(#Obj_Gradient_30)"/><rect x="146.58009" y="343.255" width="67" height="69" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><path d="M 159.7491 379.255 L 169.91435 361.255 L 190.24486 361.255 L 200.41011 379.255 L 190.24486 397.255 L 169.91435 397.255 Z" fill="url(#Obj_Gradient_31)"/><path d="M 159.7491 379.255 L 169.91435 361.255 L 190.24486 361.255 L 200.41011 379.255 L 190.24486 397.255 L 169.91435 397.255 Z" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><path d="M 156.95009 444.72058 L 177.47003 459.6171 L 161.18541 478.3627 L 167.74992 484.755 L 185.53835 464.47714 L 204.47009 478.2378 L 210.95009 470.78964 L 190.42998 454.96198 L 207.70998 438.20334 L 197.98997 430.755 L 182.86996 449.3757 L 165.59009 434.47916 Z" fill="url(#Obj_Gradient_32)"/><path d="M 156.95009 444.72058 L 177.47003 459.6171 L 161.18541 478.3627 L 167.74992 484.755 L 185.53835 464.47714 L 204.47009 478.2378 L 210.95009 470.78964 L 190.42998 454.96198 L 207.70998 438.20334 L 197.98997 430.755 L 182.86996 449.3757 L 165.59009 434.47916 Z" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><text transform="translate(210.37738 346.23645)" fill="#262626"><tspan font-family="Arial Unicode MS" font-size="36" font-weight="500" fill="#262626" x="0" y="38" textLength="36">â™›</tspan></text><text transform="translate(5.8400302 287.736)" fill="black"><tspan font-family="Helvetica" font-size="12" font-weight="bold" x=".16308594" y="11" textLength="6.673828">3</tspan></text></g></g></svg>
diff --git a/doc/book/src/java-broker/images/HA-2N-NetworkPartition.png b/doc/book/src/java-broker/images/HA-2N-NetworkPartition.png
new file mode 100644
index 0000000000..cd4a196924
--- /dev/null
+++ b/doc/book/src/java-broker/images/HA-2N-NetworkPartition.png
Binary files differ
diff --git a/doc/book/src/java-broker/images/HA-2N-NetworkPartition.svg b/doc/book/src/java-broker/images/HA-2N-NetworkPartition.svg
new file mode 100644
index 0000000000..375d88a7db
--- /dev/null
+++ b/doc/book/src/java-broker/images/HA-2N-NetworkPartition.svg
@@ -0,0 +1,3 @@
+<?xml version="1.0"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xl="http://www.w3.org/1999/xlink" version="1.1" viewBox="-20 -12 600 596" width="50pc" height="596pt"><metadata xmlns:dc="http://purl.org/dc/elements/1.1/"><dc:date>2012-05-31 06:19Z</dc:date><!-- Produced by OmniGraffle Professional 5.3.6 --></metadata><defs><radialGradient cx="0" cy="0" r="1" id="Gradient" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="white"/><stop offset=".5" stop-color="#b5d0ea"/><stop offset="1" stop-color="#aaa"/></radialGradient><radialGradient id="Obj_Gradient" xl:href="#Gradient" gradientTransform="translate(474.08 425.5) scale(145.18695)"/><linearGradient x1="0" x2="1" id="Gradient_2" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="white"/><stop offset="1" stop-color="#2824aa"/></linearGradient><linearGradient id="Obj_Gradient_2" xl:href="#Gradient_2" gradientTransform="translate(466.66 343.723) rotate(90) scale(69)"/><linearGradient x1="0" x2="1" id="Gradient_3" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="white"/><stop offset="1" stop-color="#aa1f43"/></linearGradient><linearGradient id="Obj_Gradient_3" xl:href="#Gradient_3" gradientTransform="translate(466.65952 360.223) rotate(90) scale(36)"/><linearGradient x1="0" x2="1" id="Gradient_4" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="white"/><stop offset="1" stop-color="#6923aa"/></linearGradient><linearGradient id="Obj_Gradient_4" xl:href="#Gradient_4" gradientTransform="translate(353.79 377) rotate(90) scale(24.00003)"/><linearGradient id="Obj_Gradient_5" xl:href="#Gradient_2" gradientTransform="translate(474.08 438) rotate(90) scale(69)"/><linearGradient x1="0" x2="1" id="Gradient_5" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="white"/><stop offset="1" stop-color="#21aa1a"/></linearGradient><linearGradient id="Obj_Gradient_6" xl:href="#Gradient_5" gradientTransform="translate(474.0795 456) rotate(90) scale(36)"/><marker orient="auto" overflow="visible" markerUnits="strokeWidth" id="FilledArrow_Marker" viewBox="-1 -3 6 6" markerWidth="6" markerHeight="6" color="black"><g><path d="M 3.7333333 0 L 0 -1.4 L 0 1.4 Z" fill="currentColor" stroke="currentColor" stroke-width="1"/></g></marker><marker orient="auto" overflow="visible" markerUnits="strokeWidth" id="Arrow_Marker" viewBox="-1 -4 10 8" markerWidth="10" markerHeight="8" color="black"><g><path d="M 8 0 L 0 -3 L 0 3 Z" fill="none" stroke="currentColor" stroke-width="1"/></g></marker><radialGradient id="Obj_Gradient_7" xl:href="#Gradient" gradientTransform="translate(470.5 137.5) scale(145.18695)"/><linearGradient id="Obj_Gradient_8" xl:href="#Gradient_2" gradientTransform="translate(488 145.5) rotate(90) scale(69)"/><linearGradient x1="0" x2="1" id="Gradient_6" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="white"/><stop offset="1" stop-color="#6ead6a"/></linearGradient><linearGradient id="Obj_Gradient_9" xl:href="#Gradient_6" gradientTransform="translate(487.9995 162) rotate(90) scale(36)"/><linearGradient id="Obj_Gradient_10" xl:href="#Gradient_4" gradientTransform="translate(350.21 89) rotate(90) scale(24)"/><radialGradient cx="0" cy="0" r="1" id="Gradient_7" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="white"/><stop offset=".5" stop-color="#ea061f"/><stop offset="1" stop-color="#aaa"/></radialGradient><radialGradient id="Obj_Gradient_11" xl:href="#Gradient_7" gradientTransform="translate(487.17532 136.54291) scale(20.071926)"/><linearGradient id="Obj_Gradient_12" xl:href="#Gradient_2" gradientTransform="translate(466.66 55.445) rotate(90) scale(69)"/><linearGradient x1="0" x2="1" id="Gradient_8" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="white"/><stop offset="1" stop-color="#b6b4b5"/></linearGradient><linearGradient id="Obj_Gradient_13" xl:href="#Gradient_8" gradientTransform="translate(466.65952 71.945) rotate(90) scale(36)"/><font-face font-family="Helvetica" font-size="12" units-per-em="1000" underline-position="-75.683594" underline-thickness="49.316406" slope="0" x-height="532.22656" cap-height="719.72656" ascent="770.01953" descent="-229.98047" font-weight="bold"><font-face-src><font-face-name name="Helvetica-Bold"/></font-face-src></font-face><radialGradient id="Obj_Gradient_14" xl:href="#Gradient" gradientTransform="translate(200.35501 140.5) scale(145.18695)"/><linearGradient id="Obj_Gradient_15" xl:href="#Gradient_2" gradientTransform="translate(212.855 150) rotate(90) scale(69)"/><linearGradient x1="0" x2="1" id="Gradient_9" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="white"/><stop offset="1" stop-color="#0caa25"/></linearGradient><linearGradient id="Obj_Gradient_16" xl:href="#Gradient_9" gradientTransform="translate(212.85451 166.5) rotate(90) scale(36)"/><linearGradient id="Obj_Gradient_17" xl:href="#Gradient_4" gradientTransform="translate(80.355003 115) rotate(90) scale(24)"/><linearGradient id="Obj_Gradient_18" xl:href="#Gradient_2" gradientTransform="translate(195.355 63.999996) rotate(90) scale(69.000007)"/><linearGradient x1="0" x2="1" id="Gradient_10" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="white"/><stop offset="1" stop-color="#aa172d"/></linearGradient><linearGradient id="Obj_Gradient_19" xl:href="#Gradient_10" gradientTransform="translate(195.35451 82) rotate(90) scale(36)"/><radialGradient id="Obj_Gradient_20" xl:href="#Gradient" gradientTransform="translate(180.29001 423.5) scale(145.18695)"/><linearGradient id="Obj_Gradient_21" xl:href="#Gradient_2" gradientTransform="translate(172.37 346) rotate(90) scale(69)"/><linearGradient x1="0" x2="1" id="Gradient_11" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="white"/><stop offset="1" stop-color="#aaa3a7"/></linearGradient><linearGradient id="Obj_Gradient_22" xl:href="#Gradient_11" gradientTransform="translate(172.36951 360.5) rotate(90) scale(36)"/><linearGradient id="Obj_Gradient_23" xl:href="#Gradient_4" gradientTransform="translate(72.5 379) rotate(90) scale(24)"/><linearGradient id="Obj_Gradient_24" xl:href="#Gradient_2" gradientTransform="translate(180.953 435.5) rotate(90) scale(69)"/><linearGradient x1="0" x2="1" id="Gradient_12" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="white"/><stop offset="1" stop-color="#66ab61"/></linearGradient><linearGradient id="Obj_Gradient_25" xl:href="#Gradient_12" gradientTransform="translate(180.95251 452) rotate(90) scale(36)"/><linearGradient x1="0" x2="1" id="Gradient_13" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="white"/><stop offset="1" stop-color="#b5011d"/></linearGradient><linearGradient id="Obj_Gradient_26" xl:href="#Gradient_13" gradientTransform="translate(169.38802 421.22614) rotate(45) scale(21.988586)"/></defs><g stroke="none" stroke-opacity="1" stroke-dasharray="none" fill="none" fill-opacity="1"><title>Canvas 5</title><g><title>Layer 1</title><rect x="281.29001" y="287" width="278.00003" height="273" fill="white"/><rect x="281.29001" y="287" width="278.00003" height="273" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><path d="M 420.11401 438.9812 C 396.51749 425.5 405.92719 312.01035 443.5689 331.375 C 447.06122 293.6271 490.8335 299.75403 490.54733 331.375 C 517.9939 290.93137 553.0689 371.57516 529.54248 412.0188 C 557.773 431.62692 529.18622 537.27283 506.0175 519.625 C 504.1633 549.03967 462.74454 559.3332 459.10913 519.625 C 435.6557 562.03143 386.75156 496.82916 420.11401 438.9812 Z" fill="url(#Obj_Gradient)"/><path d="M 420.11401 438.9812 C 396.51749 425.5 405.92719 312.01035 443.5689 331.375 C 447.06122 293.6271 490.8335 299.75403 490.54733 331.375 C 517.9939 290.93137 553.0689 371.57516 529.54248 412.0188 C 557.773 431.62692 529.18622 537.27283 506.0175 519.625 C 504.1633 549.03967 462.74454 559.3332 459.10913 519.625 C 435.6557 562.03143 386.75156 496.82916 420.11401 438.9812 Z" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><rect x="433.16" y="343.723" width="67" height="69" fill="url(#Obj_Gradient_2)"/><rect x="433.16" y="343.723" width="67" height="69" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><path d="M 446.329 378.223 L 456.49426 360.223 L 476.82477 360.223 L 486.99002 378.223 L 476.82477 396.223 L 456.49426 396.223 Z" fill="url(#Obj_Gradient_3)"/><path d="M 446.329 378.223 L 456.49426 360.223 L 476.82477 360.223 L 486.99002 378.223 L 476.82477 396.223 L 456.49426 396.223 Z" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><path d="M 343.29 377 L 364.29 377 C 366.77402 377 368.79 382.376 368.79 389 C 368.79 395.624 366.77402 401 364.29 401 L 343.29 401 C 340.806 401 338.79 395.624 338.79 389 C 338.79 382.376 340.806 377 343.29 377" fill="url(#Obj_Gradient_4)"/><path d="M 343.29 377 L 364.29 377 C 366.77402 377 368.79 382.376 368.79 389 C 368.79 395.624 366.77402 401 364.29 401 L 343.29 401 C 340.806 401 338.79 395.624 338.79 389 C 338.79 382.376 340.806 377 343.29 377" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><rect x="440.57999" y="438" width="67" height="69" fill="url(#Obj_Gradient_5)"/><rect x="440.57999" y="438" width="67" height="69" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><path d="M 453.749 474 L 463.91425 456 L 484.24475 456 L 494.41 474 L 484.24475 492 L 463.91425 492 Z" fill="url(#Obj_Gradient_6)"/><path d="M 453.749 474 L 463.91425 456 L 484.24475 456 L 494.41 474 L 484.24475 492 L 463.91425 492 Z" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><path d="M 358.11069 401.47244 C 364.4065 419.64648 360.82266 444.49713 377 456 C 390.09668 465.31238 416.1513 465.88107 439.42624 468.3237" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="3"/><path d="M 480.27563 455.52597 C 482.5702 448.68466 488.31772 444.80447 487.16 435 C 486.26978 427.46088 481.2962 416.41544 476.94943 405.90878" marker-end="url(#Arrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><rect x="281.29001" y="4" width="278.00003" height="273" fill="white"/><rect x="281.29001" y="4" width="278.00003" height="273" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><path d="M 416.53403 150.98122 C 392.9375 137.5 402.3472 24.010353 439.98892 43.375 C 443.48123 5.6271057 487.2535 11.754013 486.96735 43.375 C 514.41388 2.931366 549.4889 83.575165 525.96246 124.01879 C 554.19305 143.62691 525.60626 249.27281 502.4375 231.625 C 500.5833 261.03967 459.16455 271.33319 455.52917 231.625 C 432.07571 274.03143 383.17157 208.82918 416.53403 150.98122 Z" fill="url(#Obj_Gradient_7)"/><path d="M 416.53403 150.98122 C 392.9375 137.5 402.3472 24.010353 439.98892 43.375 C 443.48123 5.6271057 487.2535 11.754013 486.96735 43.375 C 514.41388 2.931366 549.4889 83.575165 525.96246 124.01879 C 554.19305 143.62691 525.60626 249.27281 502.4375 231.625 C 500.5833 261.03967 459.16455 271.33319 455.52917 231.625 C 432.07571 274.03143 383.17157 208.82918 416.53403 150.98122 Z" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><rect x="454.5" y="145.5" width="67" height="69" fill="url(#Obj_Gradient_8)"/><rect x="454.5" y="145.5" width="67" height="69" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><path d="M 467.669 180 L 477.83426 162 L 498.16476 162 L 508.33002 180 L 498.16476 198 L 477.83426 198 Z" fill="url(#Obj_Gradient_9)"/><path d="M 467.669 180 L 477.83426 162 L 498.16476 162 L 508.33002 180 L 498.16476 198 L 477.83426 198 Z" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><path d="M 339.71 89 L 360.71 89 C 363.194 89 365.21 94.376 365.21 101 C 365.21 107.624 363.194 113 360.71 113 L 339.71 113 C 337.22598 113 335.21 107.624 335.21 101 C 335.21 94.376 337.22598 89 339.71 89" fill="url(#Obj_Gradient_10)"/><path d="M 339.71 89 L 360.71 89 C 363.194 89 365.21 94.376 365.21 101 C 365.21 107.624 363.194 113 360.71 113 L 339.71 113 C 337.22598 113 335.21 107.624 335.21 101 C 335.21 94.376 337.22598 89 339.71 89" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><path d="M 474.53464 129.01602 L 484.14154 137.61832 L 476.51752 148.44287 L 479.59082 152.134415 L 487.91891 140.42473 L 496.7823 148.37096 L 499.816 144.06992 L 490.20901 134.93007 L 498.2991 125.25254 L 493.74844 120.95141 L 486.66962 131.70415 L 478.57965 123.101974 Z" fill="url(#Obj_Gradient_11)"/><path d="M 474.53464 129.01602 L 484.14154 137.61832 L 476.51752 148.44287 L 479.59082 152.134415 L 487.91891 140.42473 L 496.7823 148.37096 L 499.816 144.06992 L 490.20901 134.93007 L 498.2991 125.25254 L 493.74844 120.95141 L 486.66962 131.70415 L 478.57965 123.101974 Z" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><rect x="433.16" y="55.445" width="67" height="69" fill="url(#Obj_Gradient_12)"/><rect x="433.16" y="55.445" width="67" height="69" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><path d="M 446.329 89.945 L 456.49426 71.945 L 476.82477 71.945 L 486.99002 89.945 L 476.82477 107.945 L 456.49426 107.945 Z" fill="url(#Obj_Gradient_13)"/><path d="M 446.329 89.945 L 456.49426 71.945 L 476.82477 71.945 L 486.99002 89.945 L 476.82477 107.945 L 456.49426 107.945 Z" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><path d="M 487.69427 161.50006 C 487.55954 153.3342 489.4468 145.84863 487.29 137 C 485.7971 130.87509 482.3659 124.09454 479.00916 117.33957" marker-end="url(#Arrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><text transform="translate(5.8400302 4)" fill="black"><tspan font-family="Helvetica" font-size="12" font-weight="bold" x=".16308594" y="11" textLength="6.673828">1</tspan></text><text transform="translate(286 6)" fill="black"><tspan font-family="Helvetica" font-size="12" font-weight="bold" x=".16308594" y="11" textLength="6.673828">2</tspan></text><rect x="0" y="4" width="278" height="273" fill="white"/><rect x="0" y="4" width="278" height="273" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><path d="M 146.38904 153.98122 C 122.79251 140.5 132.20221 27.010353 169.84393 46.375 C 173.33626 8.6271057 217.1085 14.754013 216.82236 46.375 C 244.26889 5.931366 279.34393 86.575165 255.81749 127.01879 C 284.04803 146.62691 255.46124 252.27281 232.29251 234.625 C 230.43831 264.03967 189.01958 274.33319 185.38417 234.625 C 161.930725 277.03143 113.02657 211.82918 146.38904 153.98122 Z" fill="url(#Obj_Gradient_14)"/><path d="M 146.38904 153.98122 C 122.79251 140.5 132.20221 27.010353 169.84393 46.375 C 173.33626 8.6271057 217.1085 14.754013 216.82236 46.375 C 244.26889 5.931366 279.34393 86.575165 255.81749 127.01879 C 284.04803 146.62691 255.46124 252.27281 232.29251 234.625 C 230.43831 264.03967 189.01958 274.33319 185.38417 234.625 C 161.930725 277.03143 113.02657 211.82918 146.38904 153.98122 Z" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><rect x="179.355" y="150" width="67" height="69" fill="url(#Obj_Gradient_15)"/><rect x="179.355" y="150" width="67" height="69" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><path d="M 192.524 184.5 L 202.68925 166.5 L 223.01976 166.5 L 233.18501 184.5 L 223.01976 202.5 L 202.68925 202.5 Z" fill="url(#Obj_Gradient_16)"/><path d="M 192.524 184.5 L 202.68925 166.5 L 223.01976 166.5 L 233.18501 184.5 L 223.01976 202.5 L 202.68925 202.5 Z" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><path d="M 69.855003 115 L 90.855003 115 C 93.339005 115 95.355003 120.376 95.355003 127 C 95.355003 133.62399 93.339005 139 90.855003 139 L 69.855003 139 C 67.371002 139 65.355003 133.62399 65.355003 127 C 65.355003 120.376 67.371002 115 69.855003 115" fill="url(#Obj_Gradient_17)"/><path d="M 69.855003 115 L 90.855003 115 C 93.339005 115 95.355003 120.376 95.355003 127 C 95.355003 133.62399 93.339005 139 90.855003 139 L 69.855003 139 C 67.371002 139 65.355003 133.62399 65.355003 127 C 65.355003 120.376 67.371002 115 69.855003 115" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><rect x="161.855" y="64" width="67" height="69" fill="url(#Obj_Gradient_18)"/><rect x="161.855" y="64" width="67" height="69" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><path d="M 175.024 100 L 185.18925 82 L 205.51976 82 L 215.68501 100 L 205.51976 118 L 185.18925 118 Z" fill="url(#Obj_Gradient_19)"/><path d="M 175.024 100 L 185.18925 82 L 205.51976 82 L 215.68501 100 L 205.51976 118 L 185.18925 118 Z" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><path d="M 88 139 C 101.11702 162.9976 109.51097 202.49907 127.355 211 C 141.45248 217.71606 161.45502 205.08597 180.36313 196.03654" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="3"/><path d="M 222.38084 166.05576 C 227.03842 157.03807 238.59448 147.85422 236.355 139 C 234.66139 132.304 225.07715 125.79347 216.5538 119.25858" marker-end="url(#Arrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><text transform="translate(286 293)" fill="black"><tspan font-family="Helvetica" font-size="12" font-weight="bold" x=".16308594" y="11" textLength="6.673828">4</tspan></text><text transform="translate(5.8400302 6)" fill="black"><tspan font-family="Helvetica" font-size="12" font-weight="bold" x=".16308594" y="11" textLength="6.673828">1</tspan></text><text transform="translate(5.840027 287)" fill="black"><tspan font-family="Helvetica" font-size="12" font-weight="bold" x=".16308594" y="11" textLength="6.673828">3</tspan></text><rect x="0" y="287" width="278" height="273" fill="white"/><rect x="0" y="287" width="278" height="273" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><path d="M 126.32403 436.9812 C 102.72751 423.5 112.13721 310.01035 149.77893 329.375 C 153.27126 291.6271 197.0435 297.75403 196.75735 329.375 C 224.20389 288.93137 259.27893 369.57516 235.75249 410.0188 C 263.98303 429.62692 235.39624 535.27283 212.22751 517.625 C 210.37331 547.03967 168.95457 557.3332 165.31917 517.625 C 141.86572 560.03143 92.96157 494.82916 126.32403 436.9812 Z" fill="url(#Obj_Gradient_20)"/><path d="M 126.32403 436.9812 C 102.72751 423.5 112.13721 310.01035 149.77893 329.375 C 153.27126 291.6271 197.0435 297.75403 196.75735 329.375 C 224.20389 288.93137 259.27893 369.57516 235.75249 410.0188 C 263.98303 429.62692 235.39624 535.27283 212.22751 517.625 C 210.37331 547.03967 168.95457 557.3332 165.31917 517.625 C 141.86572 560.03143 92.96157 494.82916 126.32403 436.9812 Z" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><rect x="138.869995" y="346" width="67" height="69" fill="url(#Obj_Gradient_21)"/><rect x="138.869995" y="346" width="67" height="69" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><path d="M 152.039 378.5 L 162.20425 360.5 L 182.53476 360.5 L 192.70001 378.5 L 182.53476 396.5 L 162.20425 396.5 Z" fill="url(#Obj_Gradient_22)"/><path d="M 152.039 378.5 L 162.20425 360.5 L 182.53476 360.5 L 192.70001 378.5 L 182.53476 396.5 L 162.20425 396.5 Z" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><path d="M 62 379 L 83 379 C 85.484 379 87.5 384.376 87.5 391 C 87.5 397.624 85.484 403 83 403 L 62 403 C 59.516 403 57.5 397.624 57.5 391 C 57.5 384.376 59.516 379 62 379" fill="url(#Obj_Gradient_23)"/><path d="M 62 379 L 83 379 C 85.484 379 87.5 384.376 87.5 391 C 87.5 397.624 85.484 403 83 403 L 62 403 C 59.516 403 57.5 397.624 57.5 391 C 57.5 384.376 59.516 379 62 379" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><rect x="147.453" y="435.5" width="67" height="69" fill="url(#Obj_Gradient_24)"/><rect x="147.453" y="435.5" width="67" height="69" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><path d="M 160.62201 470 L 170.78726 452 L 191.11777 452 L 201.28302 470 L 191.11777 488 L 170.78726 488 Z" fill="url(#Obj_Gradient_25)"/><path d="M 160.62201 470 L 170.78726 452 L 191.11777 452 L 201.28302 470 L 191.11777 488 L 170.78726 488 Z" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><path d="M 181.17079 451.50006 C 181.27284 442.8504 182.34718 434.63248 181.47696 425.54852 C 180.89874 419.51263 179.46176 413.09204 178.022 406.67056" marker-end="url(#Arrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><path d="M 162.48625 439.34933 L 182.67911 418.90622 C 182.67911 418.90622 176.37192 410.54022 180.79669 410.70734 C 185.22139 410.87448 187.68919 413.07565 187.68919 413.07565 L 183.62592 416.69077 L 189.96997 423.03482 L 193.83488 419.61807 C 193.83488 419.61807 196.0623 421.44876 196.25372 421.64017 C 196.44499 421.83145 196.1347 425.18307 195.37999 426.3204 C 194.62503 427.45789 187.93712 423.79865 187.93724 423.79877 C 187.93724 423.79877 166.50412 443.3672 166.44502 443.4263 C 166.38591 443.4854 165.92685 444.32736 163.88141 442.16357 C 161.83583 439.99976 162.48625 439.34933 162.48625 439.34933 Z" fill="url(#Obj_Gradient_26)"/><path d="M 162.48625 439.34933 L 182.67911 418.90622 C 182.67911 418.90622 176.37192 410.54022 180.79669 410.70734 C 185.22139 410.87448 187.68919 413.07565 187.68919 413.07565 L 183.62592 416.69077 L 189.96997 423.03482 L 193.83488 419.61807 C 193.83488 419.61807 196.0623 421.44876 196.25372 421.64017 C 196.44499 421.83145 196.1347 425.18307 195.37999 426.3204 C 194.62503 427.45789 187.93712 423.79865 187.93724 423.79877 C 187.93724 423.79877 166.50412 443.3672 166.44502 443.4263 C 166.38591 443.4854 165.92685 444.32736 163.88141 442.16357 C 161.83583 439.99976 162.48625 439.34933 162.48625 439.34933 Z" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><path d="M 75.526443 403.48596 C 80.05397 422.16476 74.80702 448.81583 89.11038 459.52802 C 100.46647 468.0329 124.151474 466.49478 145.480865 466.87387" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="3"/><text transform="translate(10 297)" fill="black"><tspan font-family="Helvetica" font-size="12" font-weight="bold" x=".16308594" y="11" textLength="6.673828">3</tspan></text></g></g></svg>
diff --git a/doc/book/src/java-broker/images/HA-2N-Normal.png b/doc/book/src/java-broker/images/HA-2N-Normal.png
new file mode 100644
index 0000000000..eeaad4f230
--- /dev/null
+++ b/doc/book/src/java-broker/images/HA-2N-Normal.png
Binary files differ
diff --git a/doc/book/src/java-broker/images/HA-2N-Normal.svg b/doc/book/src/java-broker/images/HA-2N-Normal.svg
new file mode 100644
index 0000000000..c4fac9d37a
--- /dev/null
+++ b/doc/book/src/java-broker/images/HA-2N-Normal.svg
@@ -0,0 +1,3 @@
+<?xml version="1.0"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xl="http://www.w3.org/1999/xlink" version="1.1" viewBox="-11 -10 318 313" width="318pt" height="313pt"><metadata xmlns:dc="http://purl.org/dc/elements/1.1/"><dc:date>2012-05-31 06:19Z</dc:date><!-- Produced by OmniGraffle Professional 5.3.6 --></metadata><defs><radialGradient cx="0" cy="0" r="1" id="Gradient" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="white"/><stop offset=".5" stop-color="#b5d0ea"/><stop offset="1" stop-color="#aaa"/></radialGradient><radialGradient id="Obj_Gradient" xl:href="#Gradient" gradientTransform="translate(209.35501 142.5) scale(145.18695)"/><linearGradient x1="0" x2="1" id="Gradient_2" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="white"/><stop offset="1" stop-color="#2824aa"/></linearGradient><linearGradient id="Obj_Gradient_2" xl:href="#Gradient_2" gradientTransform="translate(221.85501 152) rotate(90) scale(69)"/><linearGradient x1="0" x2="1" id="Gradient_3" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="white"/><stop offset="1" stop-color="#0caa25"/></linearGradient><linearGradient id="Obj_Gradient_3" xl:href="#Gradient_3" gradientTransform="translate(221.85452 168.5) rotate(90) scale(36)"/><linearGradient x1="0" x2="1" id="Gradient_4" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="white"/><stop offset="1" stop-color="#6923aa"/></linearGradient><linearGradient id="Obj_Gradient_4" xl:href="#Gradient_4" gradientTransform="translate(71.35501 115) rotate(90) scale(24)"/><linearGradient id="Obj_Gradient_5" xl:href="#Gradient_2" gradientTransform="translate(204.35501 66) rotate(90) scale(69.000007)"/><linearGradient x1="0" x2="1" id="Gradient_5" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="white"/><stop offset="1" stop-color="#aa172d"/></linearGradient><linearGradient id="Obj_Gradient_6" xl:href="#Gradient_5" gradientTransform="translate(204.35452 84) rotate(90) scale(36)"/><marker orient="auto" overflow="visible" markerUnits="strokeWidth" id="FilledArrow_Marker" viewBox="-1 -3 6 6" markerWidth="6" markerHeight="6" color="black"><g><path d="M 3.7333333 0 L 0 -1.4 L 0 1.4 Z" fill="currentColor" stroke="currentColor" stroke-width="1"/></g></marker><marker orient="auto" overflow="visible" markerUnits="strokeWidth" id="Arrow_Marker" viewBox="-1 -4 10 8" markerWidth="10" markerHeight="8" color="black"><g><path d="M 8 0 L 0 -3 L 0 3 Z" fill="none" stroke="currentColor" stroke-width="1"/></g></marker></defs><g stroke="none" stroke-opacity="1" stroke-dasharray="none" fill="none" fill-opacity="1"><title>Canvas 1</title><g><title>Layer 1</title><rect x="9" y="6" width="278" height="273" fill="white"/><rect x="9" y="6" width="278" height="273" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><path d="M 155.38904 155.98122 C 131.79251 142.5 141.20221 29.010353 178.84393 48.375 C 182.33626 10.627106 226.1085 16.754013 225.82236 48.375 C 253.26889 7.931366 288.34393 88.575165 264.8175 129.01878 C 293.04803 148.62691 264.46124 254.27281 241.29251 236.625 C 239.43831 266.03967 198.01958 276.33319 194.38417 236.625 C 170.93073 279.03143 122.02657 213.82918 155.38904 155.98122 Z" fill="url(#Obj_Gradient)"/><path d="M 155.38904 155.98122 C 131.79251 142.5 141.20221 29.010353 178.84393 48.375 C 182.33626 10.627106 226.1085 16.754013 225.82236 48.375 C 253.26889 7.931366 288.34393 88.575165 264.8175 129.01878 C 293.04803 148.62691 264.46124 254.27281 241.29251 236.625 C 239.43831 266.03967 198.01958 276.33319 194.38417 236.625 C 170.93073 279.03143 122.02657 213.82918 155.38904 155.98122 Z" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><rect x="188.35501" y="152" width="67" height="69" fill="url(#Obj_Gradient_2)"/><rect x="188.35501" y="152" width="67" height="69" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><path d="M 201.52402 186.5 L 211.68927 168.5 L 232.01978 168.5 L 242.18503 186.5 L 232.01978 204.5 L 211.68927 204.5 Z" fill="url(#Obj_Gradient_3)"/><path d="M 201.52402 186.5 L 211.68927 168.5 L 232.01978 168.5 L 242.18503 186.5 L 232.01978 204.5 L 211.68927 204.5 Z" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><path d="M 60.85501 115 L 81.85501 115 C 84.33901 115 86.35501 120.376 86.35501 127 C 86.35501 133.62399 84.33901 139 81.85501 139 L 60.85501 139 C 58.37101 139 56.35501 133.62399 56.35501 127 C 56.35501 120.376 58.37101 115 60.85501 115" fill="url(#Obj_Gradient_4)"/><path d="M 60.85501 115 L 81.85501 115 C 84.33901 115 86.35501 120.376 86.35501 127 C 86.35501 133.62399 84.33901 139 81.85501 139 L 60.85501 139 C 58.37101 139 56.35501 133.62399 56.35501 127 C 56.35501 120.376 58.37101 115 60.85501 115" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><rect x="170.85501" y="66" width="67" height="69" fill="url(#Obj_Gradient_5)"/><rect x="170.85501" y="66" width="67" height="69" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><path d="M 184.02402 102 L 194.18927 84 L 214.51978 84 L 224.68503 102 L 214.51978 120 L 194.18927 120 Z" fill="url(#Obj_Gradient_6)"/><path d="M 184.02402 102 L 194.18927 84 L 214.51978 84 L 224.68503 102 L 214.51978 120 L 194.18927 120 Z" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><path d="M 83.35501 143 C 101.01991 166.33099 116.23704 204.83237 136.35501 213 C 152.19005 219.42882 171.06885 207.06767 189.39609 198.1017" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="3"/><path d="M 231.38086 168.05576 C 236.03844 159.03807 247.59447 149.85422 245.35498 141 C 243.66136 134.304 234.07715 127.79349 225.55383 121.2586" marker-end="url(#Arrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/></g></g></svg>
diff --git a/doc/book/src/java-broker/images/HA-2N-ReplicaFail.png b/doc/book/src/java-broker/images/HA-2N-ReplicaFail.png
new file mode 100644
index 0000000000..769fc959fc
--- /dev/null
+++ b/doc/book/src/java-broker/images/HA-2N-ReplicaFail.png
Binary files differ
diff --git a/doc/book/src/java-broker/images/HA-2N-ReplicaFail.svg b/doc/book/src/java-broker/images/HA-2N-ReplicaFail.svg
new file mode 100644
index 0000000000..aa872a30e3
--- /dev/null
+++ b/doc/book/src/java-broker/images/HA-2N-ReplicaFail.svg
@@ -0,0 +1,3 @@
+<?xml version="1.0"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xl="http://www.w3.org/1999/xlink" version="1.1" viewBox="-20 -16 600 590" width="50pc" height="590pt"><metadata xmlns:dc="http://purl.org/dc/elements/1.1/"><dc:date>2012-05-31 06:19Z</dc:date><!-- Produced by OmniGraffle Professional 5.3.6 --></metadata><defs><radialGradient cx="0" cy="0" r="1" id="Gradient" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="white"/><stop offset=".5" stop-color="#b5d0ea"/><stop offset="1" stop-color="#aaa"/></radialGradient><radialGradient id="Obj_Gradient" xl:href="#Gradient" gradientTransform="translate(470.5 133.5) scale(145.18695)"/><linearGradient x1="0" x2="1" id="Gradient_2" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="white"/><stop offset="1" stop-color="#2824aa"/></linearGradient><linearGradient id="Obj_Gradient_2" xl:href="#Gradient_2" gradientTransform="translate(488 141.5) rotate(90) scale(69)"/><linearGradient x1="0" x2="1" id="Gradient_3" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="white"/><stop offset="1" stop-color="#6cad67"/></linearGradient><linearGradient id="Obj_Gradient_3" xl:href="#Gradient_3" gradientTransform="translate(487.9995 158) rotate(90) scale(36)"/><linearGradient x1="0" x2="1" id="Gradient_4" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="white"/><stop offset="1" stop-color="#6923aa"/></linearGradient><linearGradient id="Obj_Gradient_4" xl:href="#Gradient_4" gradientTransform="translate(350.21 85) rotate(90) scale(24)"/><linearGradient id="Obj_Gradient_5" xl:href="#Gradient_2" gradientTransform="translate(470.5 55.5) rotate(90) scale(69)"/><linearGradient x1="0" x2="1" id="Gradient_5" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="white"/><stop offset="1" stop-color="#aaaaa3"/></linearGradient><linearGradient id="Obj_Gradient_6" xl:href="#Gradient_5" gradientTransform="translate(470.4995 73.5) rotate(90) scale(36)"/><marker orient="auto" overflow="visible" markerUnits="strokeWidth" id="FilledArrow_Marker" viewBox="-1 -3 6 6" markerWidth="6" markerHeight="6" color="black"><g><path d="M 3.7333333 0 L 0 -1.4 L 0 1.4 Z" fill="currentColor" stroke="currentColor" stroke-width="1"/></g></marker><radialGradient cx="0" cy="0" r="1" id="Gradient_6" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="white"/><stop offset=".5" stop-color="#ea061f"/><stop offset="1" stop-color="#aaa"/></radialGradient><radialGradient id="Obj_Gradient_7" xl:href="#Gradient_6" gradientTransform="translate(472.145 91.5) scale(38.183766)"/><font-face font-family="Helvetica" font-size="12" units-per-em="1000" underline-position="-75.683594" underline-thickness="49.316406" slope="0" x-height="532.22656" cap-height="719.72656" ascent="770.01953" descent="-229.98047" font-weight="bold"><font-face-src><font-face-name name="Helvetica-Bold"/></font-face-src></font-face><radialGradient id="Obj_Gradient_8" xl:href="#Gradient" gradientTransform="translate(474.08 415.5) scale(145.18695)"/><linearGradient id="Obj_Gradient_9" xl:href="#Gradient_2" gradientTransform="translate(466.66 333.723) rotate(90) scale(69)"/><linearGradient x1="0" x2="1" id="Gradient_7" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="white"/><stop offset="1" stop-color="#aa1f43"/></linearGradient><linearGradient id="Obj_Gradient_10" xl:href="#Gradient_7" gradientTransform="translate(466.65952 350.223) rotate(90) scale(36)"/><linearGradient id="Obj_Gradient_11" xl:href="#Gradient_4" gradientTransform="translate(353.79 367) rotate(90) scale(24.00003)"/><linearGradient id="Obj_Gradient_12" xl:href="#Gradient_2" gradientTransform="translate(474.08 428) rotate(90) scale(69)"/><linearGradient x1="0" x2="1" id="Gradient_8" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="white"/><stop offset="1" stop-color="#21aa1a"/></linearGradient><linearGradient id="Obj_Gradient_13" xl:href="#Gradient_8" gradientTransform="translate(474.0795 446) rotate(90) scale(36)"/><marker orient="auto" overflow="visible" markerUnits="strokeWidth" id="Arrow_Marker" viewBox="-1 -4 10 8" markerWidth="10" markerHeight="8" color="black"><g><path d="M 8 0 L 0 -3 L 0 3 Z" fill="none" stroke="currentColor" stroke-width="1"/></g></marker><radialGradient id="Obj_Gradient_14" xl:href="#Gradient" gradientTransform="translate(180.29001 409.5) scale(145.18695)"/><linearGradient id="Obj_Gradient_15" xl:href="#Gradient_2" gradientTransform="translate(172.37 332) rotate(90) scale(69)"/><linearGradient x1="0" x2="1" id="Gradient_9" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="white"/><stop offset="1" stop-color="#aaa3a7"/></linearGradient><linearGradient id="Obj_Gradient_16" xl:href="#Gradient_9" gradientTransform="translate(172.36951 346.5) rotate(90) scale(36)"/><linearGradient id="Obj_Gradient_17" xl:href="#Gradient_4" gradientTransform="translate(72.5 365) rotate(90) scale(24)"/><linearGradient id="Obj_Gradient_18" xl:href="#Gradient_2" gradientTransform="translate(180.953 421.5) rotate(90) scale(69)"/><linearGradient id="Obj_Gradient_19" xl:href="#Gradient_8" gradientTransform="translate(180.9525 438) rotate(90) scale(36)"/><linearGradient x1="0" x2="1" id="Gradient_10" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="white"/><stop offset="1" stop-color="#b5011d"/></linearGradient><linearGradient id="Obj_Gradient_20" xl:href="#Gradient_10" gradientTransform="translate(134.69392 361.18848) rotate(45) scale(23.213103)"/><radialGradient id="Obj_Gradient_21" xl:href="#Gradient" gradientTransform="translate(200.35501 136.5) scale(145.18695)"/><linearGradient id="Obj_Gradient_22" xl:href="#Gradient_2" gradientTransform="translate(212.855 146) rotate(90) scale(69)"/><linearGradient x1="0" x2="1" id="Gradient_11" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="white"/><stop offset="1" stop-color="#0caa25"/></linearGradient><linearGradient id="Obj_Gradient_23" xl:href="#Gradient_11" gradientTransform="translate(212.85451 162.5) rotate(90) scale(36)"/><linearGradient id="Obj_Gradient_24" xl:href="#Gradient_4" gradientTransform="translate(80.355003 111) rotate(90) scale(24)"/><linearGradient id="Obj_Gradient_25" xl:href="#Gradient_2" gradientTransform="translate(195.355 59.999996) rotate(90) scale(69.000007)"/><linearGradient x1="0" x2="1" id="Gradient_12" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="white"/><stop offset="1" stop-color="#aa172d"/></linearGradient><linearGradient id="Obj_Gradient_26" xl:href="#Gradient_12" gradientTransform="translate(195.35451 78) rotate(90) scale(36)"/></defs><g stroke="none" stroke-opacity="1" stroke-dasharray="none" fill="none" fill-opacity="1"><title>Canvas 4</title><g><title>Layer 1</title><rect x="281.29001" y="0" width="278.00003" height="273" fill="white"/><rect x="281.29001" y="0" width="278.00003" height="273" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><path d="M 416.53403 146.98122 C 392.9375 133.5 402.3472 20.010353 439.98892 39.375 C 443.48123 1.6271057 487.2535 7.754013 486.96735 39.375 C 514.41388 -1.06863403 549.4889 79.575165 525.96246 120.01879 C 554.19305 139.62691 525.60626 245.27281 502.4375 227.625 C 500.5833 257.03967 459.16455 267.33319 455.52917 227.625 C 432.07571 270.03143 383.17157 204.82918 416.53403 146.98122 Z" fill="url(#Obj_Gradient)"/><path d="M 416.53403 146.98122 C 392.9375 133.5 402.3472 20.010353 439.98892 39.375 C 443.48123 1.6271057 487.2535 7.754013 486.96735 39.375 C 514.41388 -1.06863403 549.4889 79.575165 525.96246 120.01879 C 554.19305 139.62691 525.60626 245.27281 502.4375 227.625 C 500.5833 257.03967 459.16455 267.33319 455.52917 227.625 C 432.07571 270.03143 383.17157 204.82918 416.53403 146.98122 Z" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><rect x="454.5" y="141.5" width="67" height="69" fill="url(#Obj_Gradient_2)"/><rect x="454.5" y="141.5" width="67" height="69" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><path d="M 467.669 176 L 477.83426 158 L 498.16476 158 L 508.33002 176 L 498.16476 194 L 477.83426 194 Z" fill="url(#Obj_Gradient_3)"/><path d="M 467.669 176 L 477.83426 158 L 498.16476 158 L 508.33002 176 L 498.16476 194 L 477.83426 194 Z" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><path d="M 339.71 85 L 360.71 85 C 363.194 85 365.21 90.376 365.21 97 C 365.21 103.624 363.194 109 360.71 109 L 339.71 109 C 337.22598 109 335.21 103.624 335.21 97 C 335.21 90.376 337.22598 85 339.71 85" fill="url(#Obj_Gradient_4)"/><path d="M 339.71 85 L 360.71 85 C 363.194 85 365.21 90.376 365.21 97 C 365.21 103.624 363.194 109 360.71 109 L 339.71 109 C 337.22598 109 335.21 103.624 335.21 97 C 335.21 90.376 337.22598 85 339.71 85" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><rect x="437" y="55.5" width="67" height="69" fill="url(#Obj_Gradient_5)"/><rect x="437" y="55.5" width="67" height="69" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><path d="M 450.169 91.5 L 460.33426 73.5 L 480.66476 73.5 L 490.83002 91.5 L 480.66476 109.5 L 460.33426 109.5 Z" fill="url(#Obj_Gradient_6)"/><path d="M 450.169 91.5 L 460.33426 73.5 L 480.66476 73.5 L 490.83002 91.5 L 480.66476 109.5 L 460.33426 109.5 Z" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><path d="M 355.0216 109.46646 C 360.75049 124.30949 353.19086 143.50909 372.21 154 C 388.3057 162.87834 423.4454 165.52399 453.4511 169.84836" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="3"/><path d="M 445.145 78.46559 L 465.66495 93.362083 L 449.3803 112.107697 L 455.94482 118.5 L 473.73325 98.22214 L 492.66498 111.982796 L 499.145 104.53463 L 478.62488 88.706955 L 495.90488 71.948326 L 486.18488 64.5 L 471.06485 83.12071 L 453.78497 68.224167 Z" fill="url(#Obj_Gradient_7)"/><path d="M 445.145 78.46559 L 465.66495 93.362083 L 449.3803 112.107697 L 455.94482 118.5 L 473.73325 98.22214 L 492.66498 111.982796 L 499.145 104.53463 L 478.62488 88.706955 L 495.90488 71.948326 L 486.18488 64.5 L 471.06485 83.12071 L 453.78497 68.224167 Z" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><text transform="translate(286 6)" fill="black"><tspan font-family="Helvetica" font-size="12" font-weight="bold" x=".16308594" y="11" textLength="6.673828">2</tspan></text><rect x="281.29001" y="277" width="278.00003" height="273" fill="white"/><rect x="281.29001" y="277" width="278.00003" height="273" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><path d="M 420.11401 428.9812 C 396.51749 415.5 405.92719 302.01035 443.5689 321.375 C 447.06122 283.6271 490.8335 289.75403 490.54733 321.375 C 517.9939 280.93137 553.0689 361.57516 529.54248 402.0188 C 557.773 421.62692 529.18622 527.27283 506.0175 509.625 C 504.1633 539.03967 462.74454 549.3332 459.10913 509.625 C 435.6557 552.03143 386.75156 486.82916 420.11401 428.9812 Z" fill="url(#Obj_Gradient_8)"/><path d="M 420.11401 428.9812 C 396.51749 415.5 405.92719 302.01035 443.5689 321.375 C 447.06122 283.6271 490.8335 289.75403 490.54733 321.375 C 517.9939 280.93137 553.0689 361.57516 529.54248 402.0188 C 557.773 421.62692 529.18622 527.27283 506.0175 509.625 C 504.1633 539.03967 462.74454 549.3332 459.10913 509.625 C 435.6557 552.03143 386.75156 486.82916 420.11401 428.9812 Z" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><rect x="433.16" y="333.723" width="67" height="69" fill="url(#Obj_Gradient_9)"/><rect x="433.16" y="333.723" width="67" height="69" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><path d="M 446.329 368.223 L 456.49426 350.223 L 476.82477 350.223 L 486.99002 368.223 L 476.82477 386.223 L 456.49426 386.223 Z" fill="url(#Obj_Gradient_10)"/><path d="M 446.329 368.223 L 456.49426 350.223 L 476.82477 350.223 L 486.99002 368.223 L 476.82477 386.223 L 456.49426 386.223 Z" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><path d="M 343.29 367 L 364.29 367 C 366.77402 367 368.79 372.376 368.79 379 C 368.79 385.624 366.77402 391 364.29 391 L 343.29 391 C 340.806 391 338.79 385.624 338.79 379 C 338.79 372.376 340.806 367 343.29 367" fill="url(#Obj_Gradient_11)"/><path d="M 343.29 367 L 364.29 367 C 366.77402 367 368.79 372.376 368.79 379 C 368.79 385.624 366.77402 391 364.29 391 L 343.29 391 C 340.806 391 338.79 385.624 338.79 379 C 338.79 372.376 340.806 367 343.29 367" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><rect x="440.57999" y="428" width="67" height="69" fill="url(#Obj_Gradient_12)"/><rect x="440.57999" y="428" width="67" height="69" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><path d="M 453.749 464 L 463.91425 446 L 484.24475 446 L 494.41 464 L 484.24475 482 L 463.91425 482 Z" fill="url(#Obj_Gradient_13)"/><path d="M 453.749 464 L 463.91425 446 L 484.24475 446 L 494.41 464 L 484.24475 482 L 463.91425 482 Z" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><path d="M 358.11069 391.47244 C 364.4065 409.64648 360.82266 434.49713 377 446 C 390.09668 455.31238 416.1513 455.88107 439.42624 458.3237" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="3"/><path d="M 480.27567 445.52594 C 482.57022 438.68463 488.31775 434.80447 487.16 425 C 486.26974 417.46088 481.2962 406.41544 476.94943 395.90878" marker-end="url(#Arrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><rect x="0" y="277" width="278" height="273" fill="white"/><rect x="0" y="277" width="278" height="273" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><path d="M 126.32403 422.9812 C 102.72751 409.5 112.13721 296.01035 149.77893 315.375 C 153.27126 277.6271 197.0435 283.75403 196.75735 315.375 C 224.20389 274.93137 259.27893 355.57516 235.75249 396.0188 C 263.98303 415.62692 235.39624 521.27283 212.22751 503.625 C 210.37331 533.03967 168.95457 543.3332 165.31917 503.625 C 141.86572 546.03143 92.96157 480.82916 126.32403 422.9812 Z" fill="url(#Obj_Gradient_14)"/><path d="M 126.32403 422.9812 C 102.72751 409.5 112.13721 296.01035 149.77893 315.375 C 153.27126 277.6271 197.0435 283.75403 196.75735 315.375 C 224.20389 274.93137 259.27893 355.57516 235.75249 396.0188 C 263.98303 415.62692 235.39624 521.27283 212.22751 503.625 C 210.37331 533.03967 168.95457 543.3332 165.31917 503.625 C 141.86572 546.03143 92.96157 480.82916 126.32403 422.9812 Z" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><rect x="138.869995" y="332" width="67" height="69" fill="url(#Obj_Gradient_15)"/><rect x="138.869995" y="332" width="67" height="69" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><path d="M 152.039 364.5 L 162.20425 346.5 L 182.53476 346.5 L 192.70001 364.5 L 182.53476 382.5 L 162.20425 382.5 Z" fill="url(#Obj_Gradient_16)"/><path d="M 152.039 364.5 L 162.20425 346.5 L 182.53476 346.5 L 192.70001 364.5 L 182.53476 382.5 L 162.20425 382.5 Z" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><path d="M 62 365 L 83 365 C 85.484 365 87.5 370.376 87.5 377 C 87.5 383.624 85.484 389 83 389 L 62 389 C 59.516 389 57.5 383.624 57.5 377 C 57.5 370.376 59.516 365 62 365" fill="url(#Obj_Gradient_17)"/><path d="M 62 365 L 83 365 C 85.484 365 87.5 370.376 87.5 377 C 87.5 383.624 85.484 389 83 389 L 62 389 C 59.516 389 57.5 383.624 57.5 377 C 57.5 370.376 59.516 365 62 365" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><rect x="147.453" y="421.5" width="67" height="69" fill="url(#Obj_Gradient_18)"/><rect x="147.453" y="421.5" width="67" height="69" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><path d="M 160.62199 456 L 170.78725 438 L 191.11775 438 L 201.283 456 L 191.11775 474 L 170.78725 474 Z" fill="url(#Obj_Gradient_19)"/><path d="M 160.62199 456 L 170.78725 438 L 191.11775 438 L 201.283 456 L 191.11775 474 L 170.78725 474 Z" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><path d="M 75.38166 389.48718 C 79.4207 406.98972 73.112816 431.39597 87.5 442 C 99.01256 450.4853 123.781944 450.13696 145.894165 451.55768" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="3"/><path d="M 118.20667 389.5221 L 154.46504 352.99951 C 154.46504 352.99951 148.56358 343.41068 154.80022 342.02164 C 161.03673 340.63266 163.73999 342.85837 163.73999 342.85837 L 156.62726 349.49799 L 163.3246 356.19534 L 170.08206 349.91098 C 170.08206 349.91098 172.57938 351.69775 172.78146 351.89984 C 172.98338 352.10178 171.3094 356.98645 169.817 358.88278 C 168.32417 360.77942 160.15027 358.03 160.15039 358.03012 C 160.15039 358.03012 122.44828 393.7637 122.342445 393.86954 C 122.23656 393.9754 121.27359 395.3426 119.157745 393.0148 C 117.04174 390.68701 118.20667 389.5221 118.20667 389.5221 Z" fill="url(#Obj_Gradient_20)"/><path d="M 118.20667 389.5221 L 154.46504 352.99951 C 154.46504 352.99951 148.56358 343.41068 154.80022 342.02164 C 161.03673 340.63266 163.73999 342.85837 163.73999 342.85837 L 156.62726 349.49799 L 163.3246 356.19534 L 170.08206 349.91098 C 170.08206 349.91098 172.57938 351.69775 172.78146 351.89984 C 172.98338 352.10178 171.3094 356.98645 169.817 358.88278 C 168.32417 360.77942 160.15027 358.03 160.15039 358.03012 C 160.15039 358.03012 122.44828 393.7637 122.342445 393.86954 C 122.23656 393.9754 121.27359 395.3426 119.157745 393.0148 C 117.04174 390.68701 118.20667 389.5221 118.20667 389.5221 Z" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><rect x="0" y="0" width="278" height="273" fill="white"/><rect x="0" y="0" width="278" height="273" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><path d="M 146.38904 149.98122 C 122.79251 136.5 132.20221 23.010353 169.84393 42.375 C 173.33626 4.6271057 217.1085 10.754013 216.82236 42.375 C 244.26889 1.931366 279.34393 82.575165 255.81749 123.01879 C 284.04803 142.62691 255.46124 248.27281 232.29251 230.625 C 230.43831 260.03967 189.01958 270.33319 185.38417 230.625 C 161.930725 273.03143 113.02657 207.82918 146.38904 149.98122 Z" fill="url(#Obj_Gradient_21)"/><path d="M 146.38904 149.98122 C 122.79251 136.5 132.20221 23.010353 169.84393 42.375 C 173.33626 4.6271057 217.1085 10.754013 216.82236 42.375 C 244.26889 1.931366 279.34393 82.575165 255.81749 123.01879 C 284.04803 142.62691 255.46124 248.27281 232.29251 230.625 C 230.43831 260.03967 189.01958 270.33319 185.38417 230.625 C 161.930725 273.03143 113.02657 207.82918 146.38904 149.98122 Z" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><rect x="179.355" y="146" width="67" height="69" fill="url(#Obj_Gradient_22)"/><rect x="179.355" y="146" width="67" height="69" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><path d="M 192.524 180.5 L 202.68925 162.5 L 223.01976 162.5 L 233.18501 180.5 L 223.01976 198.5 L 202.68925 198.5 Z" fill="url(#Obj_Gradient_23)"/><path d="M 192.524 180.5 L 202.68925 162.5 L 223.01976 162.5 L 233.18501 180.5 L 223.01976 198.5 L 202.68925 198.5 Z" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><path d="M 69.855003 111 L 90.855003 111 C 93.339005 111 95.355003 116.376 95.355003 123 C 95.355003 129.62399 93.339005 135 90.855003 135 L 69.855003 135 C 67.371002 135 65.355003 129.62399 65.355003 123 C 65.355003 116.376 67.371002 111 69.855003 111" fill="url(#Obj_Gradient_24)"/><path d="M 69.855003 111 L 90.855003 111 C 93.339005 111 95.355003 116.376 95.355003 123 C 95.355003 129.62399 93.339005 135 90.855003 135 L 69.855003 135 C 67.371002 135 65.355003 129.62399 65.355003 123 C 65.355003 116.376 67.371002 111 69.855003 111" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><rect x="161.855" y="60" width="67" height="69" fill="url(#Obj_Gradient_25)"/><rect x="161.855" y="60" width="67" height="69" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><path d="M 175.024 96 L 185.18925 78 L 205.51976 78 L 215.68501 96 L 205.51976 114 L 185.18925 114 Z" fill="url(#Obj_Gradient_26)"/><path d="M 175.024 96 L 185.18925 78 L 205.51976 78 L 215.68501 96 L 205.51976 114 L 185.18925 114 Z" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><path d="M 74.355003 137 C 92.019905 160.33099 107.23704 198.83237 127.355 207 C 143.19005 213.42882 162.06882 201.06767 180.39609 192.10172" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="3"/><path d="M 222.38084 162.05576 C 227.03842 153.03807 238.59448 143.85422 236.355 135 C 234.66139 128.303986 225.07715 121.79347 216.5538 115.25858" marker-end="url(#Arrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><text transform="translate(5.8400302 4)" fill="black"><tspan font-family="Helvetica" font-size="12" font-weight="bold" x=".16308594" y="11" textLength="6.673828">1</tspan></text><text transform="translate(8 286)" fill="black"><tspan font-family="Helvetica" font-size="12" font-weight="bold" x=".16308594" y="11" textLength="6.673828">3</tspan></text><text transform="translate(286 286)" fill="black"><tspan font-family="Helvetica" font-size="12" font-weight="bold" x=".16308594" y="11" textLength="6.673828">4</tspan></text></g></g></svg>
diff --git a/doc/book/src/java-broker/images/HA-2N-SplitBrain.png b/doc/book/src/java-broker/images/HA-2N-SplitBrain.png
new file mode 100644
index 0000000000..74393648a5
--- /dev/null
+++ b/doc/book/src/java-broker/images/HA-2N-SplitBrain.png
Binary files differ
diff --git a/doc/book/src/java-broker/images/HA-2N-SplitBrain.svg b/doc/book/src/java-broker/images/HA-2N-SplitBrain.svg
new file mode 100644
index 0000000000..c82cc5065a
--- /dev/null
+++ b/doc/book/src/java-broker/images/HA-2N-SplitBrain.svg
@@ -0,0 +1,3 @@
+<?xml version="1.0"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xl="http://www.w3.org/1999/xlink" version="1.1" viewBox="-20 -16 598 591" width="598pt" height="591pt"><metadata xmlns:dc="http://purl.org/dc/elements/1.1/"><dc:date>2012-05-31 06:19Z</dc:date><!-- Produced by OmniGraffle Professional 5.3.6 --></metadata><defs><radialGradient cx="0" cy="0" r="1" id="Gradient" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="white"/><stop offset=".5" stop-color="#b5d0ea"/><stop offset="1" stop-color="#aaa"/></radialGradient><radialGradient id="Obj_Gradient" xl:href="#Gradient" gradientTransform="translate(200.35501 136.5) scale(145.18695)"/><linearGradient x1="0" x2="1" id="Gradient_2" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="white"/><stop offset="1" stop-color="#2824aa"/></linearGradient><linearGradient id="Obj_Gradient_2" xl:href="#Gradient_2" gradientTransform="translate(212.855 146) rotate(90) scale(69)"/><linearGradient x1="0" x2="1" id="Gradient_3" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="white"/><stop offset="1" stop-color="#0caa25"/></linearGradient><linearGradient id="Obj_Gradient_3" xl:href="#Gradient_3" gradientTransform="translate(212.85451 162.5) rotate(90) scale(36)"/><linearGradient x1="0" x2="1" id="Gradient_4" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="white"/><stop offset="1" stop-color="#6923aa"/></linearGradient><linearGradient id="Obj_Gradient_4" xl:href="#Gradient_4" gradientTransform="translate(80.355003 111) rotate(90) scale(24)"/><linearGradient id="Obj_Gradient_5" xl:href="#Gradient_2" gradientTransform="translate(195.355 59.999996) rotate(90) scale(69.000007)"/><linearGradient x1="0" x2="1" id="Gradient_5" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="white"/><stop offset="1" stop-color="#aa172d"/></linearGradient><linearGradient id="Obj_Gradient_6" xl:href="#Gradient_5" gradientTransform="translate(195.35451 78) rotate(90) scale(36)"/><marker orient="auto" overflow="visible" markerUnits="strokeWidth" id="FilledArrow_Marker" viewBox="-1 -3 6 6" markerWidth="6" markerHeight="6" color="black"><g><path d="M 3.7333333 0 L 0 -1.4 L 0 1.4 Z" fill="currentColor" stroke="currentColor" stroke-width="1"/></g></marker><marker orient="auto" overflow="visible" markerUnits="strokeWidth" id="Arrow_Marker" viewBox="-1 -4 10 8" markerWidth="10" markerHeight="8" color="black"><g><path d="M 8 0 L 0 -3 L 0 3 Z" fill="none" stroke="currentColor" stroke-width="1"/></g></marker><font-face font-family="Helvetica" font-size="12" units-per-em="1000" underline-position="-75.683594" underline-thickness="49.316406" slope="0" x-height="532.22656" cap-height="719.72656" ascent="770.01953" descent="-229.98047" font-weight="bold"><font-face-src><font-face-name name="Helvetica-Bold"/></font-face-src></font-face><radialGradient id="Obj_Gradient_7" xl:href="#Gradient" gradientTransform="translate(468.855 133.5) scale(145.18695)"/><linearGradient id="Obj_Gradient_8" xl:href="#Gradient_2" gradientTransform="translate(486.355 141.5) rotate(90) scale(69)"/><linearGradient x1="0" x2="1" id="Gradient_6" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="white"/><stop offset="1" stop-color="#6ead6a"/></linearGradient><linearGradient id="Obj_Gradient_9" xl:href="#Gradient_6" gradientTransform="translate(486.3545 158) rotate(90) scale(36)"/><linearGradient id="Obj_Gradient_10" xl:href="#Gradient_4" gradientTransform="translate(348.565 85) rotate(90) scale(24)"/><radialGradient cx="0" cy="0" r="1" id="Gradient_7" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="white"/><stop offset=".5" stop-color="#ea061f"/><stop offset="1" stop-color="#aaa"/></radialGradient><radialGradient id="Obj_Gradient_11" xl:href="#Gradient_7" gradientTransform="translate(483.56808 132.68761) scale(20.071926)"/><linearGradient id="Obj_Gradient_12" xl:href="#Gradient_2" gradientTransform="translate(465.01501 51.445) rotate(90) scale(69)"/><linearGradient x1="0" x2="1" id="Gradient_8" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="white"/><stop offset="1" stop-color="#b6b4b5"/></linearGradient><linearGradient id="Obj_Gradient_13" xl:href="#Gradient_8" gradientTransform="translate(465.0145 67.945) rotate(90) scale(36)"/><font-face font-family="Arial Unicode MS" font-size="36" panose-1="2 11 6 4 2 2 2 2 2 4" units-per-em="1000" underline-position="-100.097656" underline-thickness="49.804688" slope="0" x-height="529.78516" cap-height="728.02734" ascent="1068.84766" descent="-270.9961" font-weight="500"><font-face-src><font-face-name name="ArialUnicodeMS"/></font-face-src></font-face><radialGradient id="Obj_Gradient_14" xl:href="#Gradient" gradientTransform="translate(180.29001 414.5) scale(145.18695)"/><linearGradient id="Obj_Gradient_15" xl:href="#Gradient_2" gradientTransform="translate(172.37 337) rotate(90) scale(69)"/><linearGradient x1="0" x2="1" id="Gradient_9" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="white"/><stop offset="1" stop-color="#66ab61"/></linearGradient><linearGradient id="Obj_Gradient_16" xl:href="#Gradient_9" gradientTransform="translate(172.36951 351.5) rotate(90) scale(36)"/><linearGradient id="Obj_Gradient_17" xl:href="#Gradient_4" gradientTransform="translate(53.18649 396) rotate(90) scale(24)"/><linearGradient id="Obj_Gradient_18" xl:href="#Gradient_2" gradientTransform="translate(180.953 426.5) rotate(90) scale(69)"/><linearGradient x1="0" x2="1" id="Gradient_10" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="white"/><stop offset="1" stop-color="#21aa1a"/></linearGradient><linearGradient id="Obj_Gradient_19" xl:href="#Gradient_10" gradientTransform="translate(180.9525 443) rotate(90) scale(36)"/><radialGradient id="Obj_Gradient_20" xl:href="#Gradient_7" gradientTransform="translate(185.10121 416.23209) scale(20.071926)"/><font-face font-family="Arial Unicode MS" font-size="72" panose-1="2 11 6 4 2 2 2 2 2 4" units-per-em="1000" underline-position="-100.097656" underline-thickness="49.804688" slope="0" x-height="529.78516" cap-height="728.02734" ascent="1068.84766" descent="-270.9961" font-weight="500"><font-face-src><font-face-name name="ArialUnicodeMS"/></font-face-src></font-face></defs><g stroke="none" stroke-opacity="1" stroke-dasharray="none" fill="none" fill-opacity="1"><title>Canvas 6</title><g><title>Layer 1</title><rect x="0" y="0" width="278" height="273" fill="white"/><rect x="0" y="0" width="278" height="273" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><path d="M 146.38904 149.98122 C 122.79251 136.5 132.20221 23.010353 169.84393 42.375 C 173.33626 4.6271057 217.1085 10.754013 216.82236 42.375 C 244.26889 1.931366 279.34393 82.575165 255.81749 123.01879 C 284.04803 142.62691 255.46124 248.27281 232.29251 230.625 C 230.43831 260.03967 189.01958 270.33319 185.38417 230.625 C 161.930725 273.03143 113.02657 207.82918 146.38904 149.98122 Z" fill="url(#Obj_Gradient)"/><path d="M 146.38904 149.98122 C 122.79251 136.5 132.20221 23.010353 169.84393 42.375 C 173.33626 4.6271057 217.1085 10.754013 216.82236 42.375 C 244.26889 1.931366 279.34393 82.575165 255.81749 123.01879 C 284.04803 142.62691 255.46124 248.27281 232.29251 230.625 C 230.43831 260.03967 189.01958 270.33319 185.38417 230.625 C 161.930725 273.03143 113.02657 207.82918 146.38904 149.98122 Z" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><rect x="179.355" y="146" width="67" height="69" fill="url(#Obj_Gradient_2)"/><rect x="179.355" y="146" width="67" height="69" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><path d="M 192.524 180.5 L 202.68925 162.5 L 223.01976 162.5 L 233.18501 180.5 L 223.01976 198.5 L 202.68925 198.5 Z" fill="url(#Obj_Gradient_3)"/><path d="M 192.524 180.5 L 202.68925 162.5 L 223.01976 162.5 L 233.18501 180.5 L 223.01976 198.5 L 202.68925 198.5 Z" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><path d="M 69.855003 111 L 90.855003 111 C 93.339005 111 95.355003 116.376 95.355003 123 C 95.355003 129.62399 93.339005 135 90.855003 135 L 69.855003 135 C 67.371002 135 65.355003 129.62399 65.355003 123 C 65.355003 116.376 67.371002 111 69.855003 111" fill="url(#Obj_Gradient_4)"/><path d="M 69.855003 111 L 90.855003 111 C 93.339005 111 95.355003 116.376 95.355003 123 C 95.355003 129.62399 93.339005 135 90.855003 135 L 69.855003 135 C 67.371002 135 65.355003 129.62399 65.355003 123 C 65.355003 116.376 67.371002 111 69.855003 111" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><rect x="161.855" y="60" width="67" height="69" fill="url(#Obj_Gradient_5)"/><rect x="161.855" y="60" width="67" height="69" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><path d="M 175.024 96 L 185.18925 78 L 205.51976 78 L 215.68501 96 L 205.51976 114 L 185.18925 114 Z" fill="url(#Obj_Gradient_6)"/><path d="M 175.024 96 L 185.18925 78 L 205.51976 78 L 215.68501 96 L 205.51976 114 L 185.18925 114 Z" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><path d="M 83 135 C 87.728355 147.33211 78.882416 164.66258 97.186493 172 C 112.61268 178.18378 147.33044 177.27293 176.94928 178.23598" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="3"/><path d="M 222.38084 162.05576 C 227.03842 153.03807 238.59448 143.85422 236.355 135 C 234.66139 128.303986 225.07715 121.79347 216.5538 115.25858" marker-end="url(#Arrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><text transform="translate(285 6)" fill="black"><tspan font-family="Helvetica" font-size="12" font-weight="bold" x=".16308594" y="11" textLength="6.673828">2</tspan></text><rect x="279.64499" y="0" width="278.00003" height="273" fill="white"/><rect x="279.64499" y="0" width="278.00003" height="273" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><path d="M 414.88904 146.98122 C 391.2925 133.5 400.7022 20.010353 438.34393 39.375 C 441.83624 1.6271057 485.60852 7.754013 485.32236 39.375 C 512.76892 -1.06863403 547.84393 79.575165 524.3175 120.01879 C 552.54803 139.62691 523.96124 245.27281 500.7925 227.625 C 498.93832 257.03967 457.51956 267.33319 453.88416 227.625 C 430.43073 270.03143 381.52658 204.82918 414.88904 146.98122 Z" fill="url(#Obj_Gradient_7)"/><path d="M 414.88904 146.98122 C 391.2925 133.5 400.7022 20.010353 438.34393 39.375 C 441.83624 1.6271057 485.60852 7.754013 485.32236 39.375 C 512.76892 -1.06863403 547.84393 79.575165 524.3175 120.01879 C 552.54803 139.62691 523.96124 245.27281 500.7925 227.625 C 498.93832 257.03967 457.51956 267.33319 453.88416 227.625 C 430.43073 270.03143 381.52658 204.82918 414.88904 146.98122 Z" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><rect x="452.855" y="141.5" width="66.99997" height="69" fill="url(#Obj_Gradient_8)"/><rect x="452.855" y="141.5" width="66.99997" height="69" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><path d="M 466.024 176 L 476.18924 158 L 496.51974 158 L 506.685 176 L 496.51974 194 L 476.18924 194 Z" fill="url(#Obj_Gradient_9)"/><path d="M 466.024 176 L 476.18924 158 L 496.51974 158 L 506.685 176 L 496.51974 194 L 476.18924 194 Z" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><path d="M 338.065 85 L 359.065 85 C 361.54901 85 363.565 90.376 363.565 97 C 363.565 103.624 361.54901 109 359.065 109 L 338.065 109 C 335.581 109 333.565 103.624 333.565 97 C 333.565 90.376 335.581 85 338.065 85" fill="url(#Obj_Gradient_10)"/><path d="M 338.065 85 L 359.065 85 C 361.54901 85 363.565 90.376 363.565 97 C 363.565 103.624 361.54901 109 359.065 109 L 338.065 109 C 335.581 109 333.565 103.624 333.565 97 C 333.565 90.376 335.581 85 338.065 85" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><path d="M 353.37662 109.46646 C 359.1055 124.30949 351.54587 143.50909 370.565 154 C 386.66068 162.87834 421.80042 165.52399 451.8061 169.84834" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="3"/><path d="M 470.9274 125.16071 L 480.5343 133.763016 L 472.91028 144.58757 L 475.98358 148.27911 L 484.31168 136.56943 L 493.17505 144.515656 L 496.20877 140.214615 L 486.60178 131.07477 L 494.69186 121.39724 L 490.1412 117.09611 L 483.06238 127.84885 L 474.9724 119.246674 Z" fill="url(#Obj_Gradient_11)"/><path d="M 470.9274 125.16071 L 480.5343 133.763016 L 472.91028 144.58757 L 475.98358 148.27911 L 484.31168 136.56943 L 493.17505 144.515656 L 496.20877 140.214615 L 486.60178 131.07477 L 494.69186 121.39724 L 490.1412 117.09611 L 483.06238 127.84885 L 474.9724 119.246674 Z" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><rect x="431.51501" y="51.445" width="67" height="69" fill="url(#Obj_Gradient_12)"/><rect x="431.51501" y="51.445" width="67" height="69" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><path d="M 444.684 85.945 L 454.84924 67.945 L 475.17975 67.945 L 485.345 85.945 L 475.17975 103.945 L 454.84924 103.945 Z" fill="url(#Obj_Gradient_13)"/><path d="M 444.684 85.945 L 454.84924 67.945 L 475.17975 67.945 L 485.345 85.945 L 475.17975 103.945 L 454.84924 103.945 Z" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><path d="M 485.18884 157.50099 C 484.6743 149.33481 485.7887 141.847626 483.645 133 C 482.1737 126.92762 479.1671 120.211914 476.20593 113.515625" marker-end="url(#Arrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><text transform="translate(496 56.5)" fill="#262626"><tspan font-family="Arial Unicode MS" font-size="36" font-weight="500" fill="#262626" x="0" y="38" textLength="36">♛</tspan></text><text transform="translate(6 6)" fill="black"><tspan font-family="Helvetica" font-size="12" font-weight="bold" x=".16308594" y="11" textLength="6.673828">1</tspan></text><rect x="0" y="278" width="278" height="273" fill="white"/><rect x="0" y="278" width="278" height="273" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><path d="M 126.32403 427.9812 C 102.72751 414.5 112.13721 301.01035 149.77893 320.375 C 153.27126 282.6271 197.0435 288.75403 196.75735 320.375 C 224.20389 279.93137 259.27893 360.57516 235.75249 401.0188 C 263.98303 420.62692 235.39624 526.27283 212.22751 508.625 C 210.37331 538.03967 168.95457 548.3332 165.31917 508.625 C 141.86572 551.03143 92.96157 485.82916 126.32403 427.9812 Z" fill="url(#Obj_Gradient_14)"/><path d="M 126.32403 427.9812 C 102.72751 414.5 112.13721 301.01035 149.77893 320.375 C 153.27126 282.6271 197.0435 288.75403 196.75735 320.375 C 224.20389 279.93137 259.27893 360.57516 235.75249 401.0188 C 263.98303 420.62692 235.39624 526.27283 212.22751 508.625 C 210.37331 538.03967 168.95457 548.3332 165.31917 508.625 C 141.86572 551.03143 92.96157 485.82916 126.32403 427.9812 Z" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><rect x="138.869995" y="337" width="67" height="69" fill="url(#Obj_Gradient_15)"/><rect x="138.869995" y="337" width="67" height="69" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><path d="M 152.039 369.5 L 162.20425 351.5 L 182.53476 351.5 L 192.70001 369.5 L 182.53476 387.5 L 162.20425 387.5 Z" fill="url(#Obj_Gradient_16)"/><path d="M 152.039 369.5 L 162.20425 351.5 L 182.53476 351.5 L 192.70001 369.5 L 182.53476 387.5 L 162.20425 387.5 Z" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><path d="M 42.68649 396 L 63.68649 396 C 66.170486 396 68.186493 401.376 68.186493 408 C 68.186493 414.624 66.170486 420 63.68649 420 L 42.68649 420 C 40.202488 420 38.18649 414.624 38.18649 408 C 38.18649 401.376 40.202488 396 42.68649 396" fill="url(#Obj_Gradient_17)"/><path d="M 42.68649 396 L 63.68649 396 C 66.170486 396 68.186493 401.376 68.186493 408 C 68.186493 414.624 66.170486 420 63.68649 420 L 42.68649 420 C 40.202488 420 38.18649 414.624 38.18649 408 C 38.18649 401.376 40.202488 396 42.68649 396" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><rect x="147.453" y="426.5" width="67" height="69" fill="url(#Obj_Gradient_18)"/><rect x="147.453" y="426.5" width="67" height="69" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><path d="M 160.62199 461 L 170.78725 443 L 191.11775 443 L 201.283 461 L 191.11775 479 L 170.78725 479 Z" fill="url(#Obj_Gradient_19)"/><path d="M 160.62199 461 L 170.78725 443 L 191.11775 443 L 201.283 461 L 191.11775 479 L 170.78725 479 Z" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><path d="M 64.073936 420.37445 C 71.881844 429.24875 71.228394 440.71005 87.5 447 C 100.49186 452.02213 124.27972 453.7499 145.93179 456.12848" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="3"/><path d="M 61.40507 395.58307 C 67.269463 386.72293 63.968967 373.3653 79 369 C 90.933815 365.53418 114.428574 367.73508 135.71434 368.85406" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="3"/><text transform="translate(6 286)" fill="black"><tspan font-family="Helvetica" font-size="12" font-weight="bold" x=".16308594" y="11" textLength="6.673828">3</tspan></text><path d="M 172.46051 408.7052 L 182.06741 417.3075 L 174.4434 428.13205 L 177.51671 431.82358 L 185.8448 420.1139 L 194.70818 428.06015 L 197.74191 423.7591 L 188.1349 414.61926 L 196.22501 404.9417 L 191.67433 400.6406 L 184.59552 411.39334 L 176.50554 402.79114 Z" fill="url(#Obj_Gradient_20)"/><path d="M 172.46051 408.7052 L 182.06741 417.3075 L 174.4434 428.13205 L 177.51671 431.82358 L 185.8448 420.1139 L 194.70818 428.06015 L 197.74191 423.7591 L 188.1349 414.61926 L 196.22501 404.9417 L 191.67433 400.6406 L 184.59552 411.39334 L 176.50554 402.79114 Z" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><path d="M 186.722 441.046 C 186.20738 432.87949 187.32178 425.39178 185.17799 416.544 C 183.70665 410.47153 180.69995 403.75586 177.73871 397.05966" marker-end="url(#Arrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><text transform="translate(19.372978 273)" fill="black"><tspan font-family="Arial Unicode MS" font-size="72" font-weight="500" x="0" y="77" textLength="54">☠</tspan></text></g></g></svg>
diff --git a/doc/book/src/java-broker/images/HA-BDBHAMessageStore-MBean-jconsole.png b/doc/book/src/java-broker/images/HA-BDBHAMessageStore-MBean-jconsole.png
new file mode 100644
index 0000000000..6caaacb1e1
--- /dev/null
+++ b/doc/book/src/java-broker/images/HA-BDBHAMessageStore-MBean-jconsole.png
Binary files differ
diff --git a/doc/book/src/java-broker/images/HA-perftests-results.png b/doc/book/src/java-broker/images/HA-perftests-results.png
new file mode 100644
index 0000000000..e8dbb3c123
--- /dev/null
+++ b/doc/book/src/java-broker/images/HA-perftests-results.png
Binary files differ
diff --git a/doc/book/src/programming/Programming-In-Apache-Qpid-Book.xml b/doc/book/src/programming/Programming-In-Apache-Qpid-Book.xml
index 3052e2acc1..1c6bfafc27 100644
--- a/doc/book/src/programming/Programming-In-Apache-Qpid-Book.xml
+++ b/doc/book/src/programming/Programming-In-Apache-Qpid-Book.xml
@@ -1269,7 +1269,7 @@ spout - -content "$(cat rdu.xml | sed -e 's/70/45/')" xml/weather
unreliable will be used and for durable messages on
durable queues there is the possibility that messages
will be redelivered; if exactly-once is requested,
- at-most-once will be used and the application needs to
+ at-least-once will be used and the application needs to
be able to deal with duplicates.</para></footnote>
</entry>
</row>
@@ -3783,6 +3783,16 @@ spout - -content "$(cat rdu.xml | sed -e 's/70/45/')" xml/weather
<para>For compatibility with older clients, the synonym <varname>amqj.receiveBufferSize</varname> is supported.</para>
</entry>
</row>
+ <row>
+ <entry>qpid.failover_method_timeout</entry>
+ <entry>long</entry>
+ <entry>60000</entry>
+ <entry>
+ <para>During failover, this is the timeout for each attempt to try to re-establish the connection.
+ If a reconnection attempt exceeds the timeout, the entire failover process is aborted.</para>
+ <para>It is only applicable for AMQP 0-8/0-9/0-9-1 clients.</para>
+ </entry>
+ </row>
</tbody>
</tgroup>
</table>
diff --git a/extras/qmf/setup.py b/extras/qmf/setup.py
index ac0910f78f..fcfd2f8a30 100755
--- a/extras/qmf/setup.py
+++ b/extras/qmf/setup.py
@@ -20,7 +20,7 @@
from distutils.core import setup
setup(name="qpid-qmf",
- version="0.17",
+ version="0.19",
author="Apache Qpid",
author_email="dev@qpid.apache.org",
packages=["qmf"],
diff --git a/extras/qmf/src/py/qmf/console.py b/extras/qmf/src/py/qmf/console.py
index bd1ddb2833..90cc17d32b 100644
--- a/extras/qmf/src/py/qmf/console.py
+++ b/extras/qmf/src/py/qmf/console.py
@@ -2422,8 +2422,12 @@ class Broker(Thread):
sock.settimeout(5)
oldTimeout = sock.gettimeout()
sock.settimeout(self.connTimeout)
+ connSock = None
if self.ssl:
- connSock = ssl(sock)
+ if 'ssl_certfile' in self.connectArgs:
+ connSock = ssl(sock, certfile=self.connectArgs['ssl_certfile'])
+ else:
+ connSock = ssl(sock)
else:
connSock = sock
self.conn = Connection(connSock, username=self.authUser, password=self.authPass,
diff --git a/java/amqp-1-0-client-jms/build.xml b/java/amqp-1-0-client-jms/build.xml
index 4a685d7106..82d5aa5c7a 100644
--- a/java/amqp-1-0-client-jms/build.xml
+++ b/java/amqp-1-0-client-jms/build.xml
@@ -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
diff --git a/java/amqp-1-0-client/build.xml b/java/amqp-1-0-client/build.xml
index 173d7540d4..031809a380 100644
--- a/java/amqp-1-0-client/build.xml
+++ b/java/amqp-1-0-client/build.xml
@@ -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
diff --git a/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Dump.java b/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Dump.java
index f61fd64a61..65d27b21f8 100644
--- a/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Dump.java
+++ b/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Dump.java
@@ -1,3 +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.
+ *
+ */
package org.apache.qpid.amqp_1_0.client;
import org.apache.qpid.amqp_1_0.type.Binary;
diff --git a/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Filereceiver.java b/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Filereceiver.java
index 43ddd6ca25..4d98655ad2 100644
--- a/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Filereceiver.java
+++ b/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Filereceiver.java
@@ -1,3 +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.
+ *
+ */
package org.apache.qpid.amqp_1_0.client;
import org.apache.qpid.amqp_1_0.type.*;
diff --git a/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Filesender.java b/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Filesender.java
index 83b305ac03..46e6ba537f 100644
--- a/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Filesender.java
+++ b/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Filesender.java
@@ -1,3 +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.
+ *
+ */
package org.apache.qpid.amqp_1_0.client;
import org.apache.qpid.amqp_1_0.type.Binary;
diff --git a/java/amqp-1-0-common/build.xml b/java/amqp-1-0-common/build.xml
index 20b8b731b0..370769824f 100644
--- a/java/amqp-1-0-common/build.xml
+++ b/java/amqp-1-0-common/build.xml
@@ -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
diff --git a/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/codec/BinaryString.java b/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/codec/BinaryString.java
index 76bdac8ed7..4fc7f8e919 100644
--- a/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/codec/BinaryString.java
+++ b/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/codec/BinaryString.java
@@ -1,3 +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.
+ *
+ */
package org.apache.qpid.amqp_1_0.codec;
diff --git a/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/ConnectionEndpoint.java b/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/ConnectionEndpoint.java
index 4ad8b4196e..70e990d92e 100644
--- a/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/ConnectionEndpoint.java
+++ b/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/ConnectionEndpoint.java
@@ -106,15 +106,15 @@ public class ConnectionEndpoint implements DescribedTypeConstructorRegistry.Sour
private UnsignedInteger _desiredMaxFrameSize = UnsignedInteger.valueOf(DEFAULT_MAX_FRAME);
private Runnable _onSaslCompleteTask;
- private CallbackHandlerSource _callbackHandlersource;
+ private SaslServerProvider _saslServerProvider;
private SaslServer _saslServer;
private boolean _authenticated;
private String _remoteHostname;
- public ConnectionEndpoint(Container container, CallbackHandlerSource cbs)
+ public ConnectionEndpoint(Container container, SaslServerProvider cbs)
{
_container = container;
- _callbackHandlersource = cbs;
+ _saslServerProvider = cbs;
_requiresSASLClient = false;
_requiresSASLServer = cbs != null;
}
@@ -700,11 +700,7 @@ public class ConnectionEndpoint implements DescribedTypeConstructorRegistry.Sour
try
{
- _saslServer = Sasl.createSaslServer(mechanism.toString(),
- "AMQP",
- "localhost",
- null,
- _callbackHandlersource.getHandler(mechanism.toString()));
+ _saslServer = _saslServerProvider.getSaslServer(mechanism.toString(), "localhost");
// Process response from the client
byte[] challenge = _saslServer.evaluateResponse(response != null ? response : new byte[0]);
diff --git a/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/ErrorHandler.java b/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/ErrorHandler.java
index e3bd37b225..185b866900 100644
--- a/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/ErrorHandler.java
+++ b/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/ErrorHandler.java
@@ -1,3 +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.
+ *
+ */
package org.apache.qpid.amqp_1_0.transport;
import org.apache.qpid.amqp_1_0.type.transport.*;
diff --git a/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/ReceivingLinkEndpoint.java b/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/ReceivingLinkEndpoint.java
index bd9244c858..cf86fc2471 100644
--- a/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/ReceivingLinkEndpoint.java
+++ b/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/ReceivingLinkEndpoint.java
@@ -32,6 +32,8 @@ public class ReceivingLinkEndpoint extends LinkEndpoint<ReceivingLinkListener>
{
+ private UnsignedInteger _lastDeliveryId;
+
private static class TransientState
{
@@ -435,4 +437,16 @@ public class ReceivingLinkEndpoint extends LinkEndpoint<ReceivingLinkListener>
{
return _drainLimit;
}
+
+ UnsignedInteger getLastDeliveryId()
+ {
+ return _lastDeliveryId;
+ }
+
+ void setLastDeliveryId(UnsignedInteger lastDeliveryId)
+ {
+ _lastDeliveryId = lastDeliveryId;
+ }
+
+
}
diff --git a/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/CallbackHandlerSource.java b/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/SaslServerProvider.java
index 604279a21f..1b08488673 100644
--- a/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/CallbackHandlerSource.java
+++ b/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/SaslServerProvider.java
@@ -20,9 +20,10 @@
package org.apache.qpid.amqp_1_0.transport;
-import javax.security.auth.callback.CallbackHandler;
+import javax.security.sasl.SaslException;
+import javax.security.sasl.SaslServer;
-public interface CallbackHandlerSource
+public interface SaslServerProvider
{
- CallbackHandler getHandler(String mechanism);
+ SaslServer getSaslServer(String mechanism, String fqdn) throws SaslException;
}
diff --git a/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/SessionEndpoint.java b/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/SessionEndpoint.java
index 4b8bf82a4a..17f90fef59 100644
--- a/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/SessionEndpoint.java
+++ b/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/SessionEndpoint.java
@@ -321,21 +321,32 @@ public class SessionEndpoint
}
- Delivery delivery = _incomingUnsettled.get(transfer.getDeliveryId());
+ UnsignedInteger deliveryId = transfer.getDeliveryId();
+ if(deliveryId == null)
+ {
+ deliveryId = ((ReceivingLinkEndpoint)endpoint).getLastDeliveryId();
+ }
+
+ Delivery delivery = _incomingUnsettled.get(deliveryId);
if(delivery == null)
{
delivery = new Delivery(transfer, endpoint);
- _incomingUnsettled.put(transfer.getDeliveryId(),delivery);
+ _incomingUnsettled.put(deliveryId,delivery);
if(delivery.isSettled() || Boolean.TRUE.equals(transfer.getAborted()))
{
/*
_availableIncomingCredit++;
*/
}
+
+ if(Boolean.TRUE.equals(transfer.getMore()))
+ {
+ ((ReceivingLinkEndpoint)endpoint).setLastDeliveryId(transfer.getDeliveryId());
+ }
}
else
{
- if(delivery.getDeliveryId().equals(transfer.getDeliveryId()))
+ if(delivery.getDeliveryId().equals(deliveryId))
{
delivery.addTransfer(transfer);
if(delivery.isSettled())
@@ -350,6 +361,11 @@ public class SessionEndpoint
_availableIncomingCredit += delivery.getTransfers().size();
*/
}
+
+ if(!Boolean.TRUE.equals(transfer.getMore()))
+ {
+ ((ReceivingLinkEndpoint)endpoint).setLastDeliveryId(null);
+ }
}
else
{
@@ -365,7 +381,7 @@ public class SessionEndpoint
if((delivery.isComplete() && delivery.isSettled() || Boolean.TRUE.equals(transfer.getAborted())))
{
- _incomingUnsettled.remove(transfer.getDeliveryId());
+ _incomingUnsettled.remove(deliveryId);
}
}
}
diff --git a/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/codec/AMQPDescribedTypeRegistry.java b/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/codec/AMQPDescribedTypeRegistry.java
index 5ffa96e094..4ee0fd1f70 100644
--- a/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/codec/AMQPDescribedTypeRegistry.java
+++ b/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/codec/AMQPDescribedTypeRegistry.java
@@ -1,4 +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.
+ *
+ */
package org.apache.qpid.amqp_1_0.type.codec;
diff --git a/java/bdbstore/bin/backup.sh b/java/bdbstore/bin/backup.sh
index f3386e79dc..61311cd2ef 100755
--- a/java/bdbstore/bin/backup.sh
+++ b/java/bdbstore/bin/backup.sh
@@ -34,7 +34,7 @@ if [ -z "${QPID_HOME}" ]; then
export QPID_HOME=`cd ${WHEREAMI}/../ && pwd`
fi
-VERSION=0.17
+VERSION=0.19
# BDB's je JAR expected to be found in lib/opt
LIBS="${QPID_HOME}/lib/opt/*:${QPID_HOME}/lib/qpid-bdbstore-${VERSION}.jar:${QPID_HOME}/lib/qpid-all.jar"
diff --git a/java/bdbstore/build.xml b/java/bdbstore/build.xml
index 7e55b41b28..7c305c7c2f 100644
--- a/java/bdbstore/build.xml
+++ b/java/bdbstore/build.xml
@@ -16,21 +16,24 @@
- specific language governing permissions and limitations
- under the License.
-->
-<project name="bdbstore" default="build">
+<project name="bdbstore" xmlns:ivy="antlib:org.apache.ivy.ant" default="build">
<property name="module.depends" value="common broker" />
<property name="module.test.depends" value="test client common/test broker/test management/common systests" />
<property name="module.genpom" value="true"/>
<import file="../module.xml" />
- <property name="bdb.lib.dir" value="${project.root}/lib/bdbstore" />
- <property name="bdb.version" value="5.0.34" />
- <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" />
+ <condition property="download.bdb.jar">
+ <or>
+ <istrue value="${download-bdb}"/>
+ <istrue value="${optional.dependencies}"/>
+ <istrue value="${optional}"/>
+ </or>
+ </condition>
<!--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"/>
+ <available file="${project.root}/${bdb-je}" type="file" property="bdb.jar.available"/>
</target>
<!--echo that BDB is required if it isnt present, with associated licencing note-->
@@ -61,15 +64,16 @@ http://www.oracle.com/technetwork/database/berkeleydb/downloads/jeoslicense-0868
</target>
<!--check if an inline BDB download was requested with the build-->
- <target name="check-request-props" if="download-bdb">
+ <target name="check-request-props" if="download.bdb.jar">
<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 name="download-bdb" depends="bdb-licence-note, load-ivy, configure-ivy" unless="${ivy.dont.retrieve}">
+ <echo message="Resolving and retrieving dependencies..."/>
+ <ivy:resolve type="jar,bundle" file="${project.root}/ivy.retrieve.xml" conf="bdbje"/>
+ <ivy:retrieve type="jar,bundle" conf="bdbje" sync="true"
+ pattern="${project.root}/lib/bdbstore/[artifact]-[revision].[ext]" />
</target>
<target name="build" depends="check-request-props, bdb-jar-required, module.build" />
@@ -88,4 +92,5 @@ http://www.oracle.com/technetwork/database/berkeleydb/downloads/jeoslicense-0868
<fileset dir="src/test/resources"/>
</copy>
</target>
+
</project>
diff --git a/java/bdbstore/jmx/MANIFEST.MF b/java/bdbstore/jmx/MANIFEST.MF
new file mode 100644
index 0000000000..ee59bc3ad8
--- /dev/null
+++ b/java/bdbstore/jmx/MANIFEST.MF
@@ -0,0 +1,20 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Qpid Bdbstore-Plugins JMX
+Bundle-SymbolicName: bdbstore-plugins-jmx
+Bundle-Description: Bdbstore Management 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-RequiredExecutionEnvironment: JavaSE-1.6
+Bundle-ClassPath: .
+Fragment-Host: broker-plugins-management-jmx
+Import-Package: org.apache.qpid,
+ org.apache.qpid.management.common.mbeans.annotations,
+ org.apache.qpid.server.model,
+ org.apache.qpid.server.virtualhost,
+ org.apache.qpid.server.store.berkeleydb,
+ org.apache.log4j;version=1.2.16,
+ javax.management,
+ javax.management.openmbean
+Export-Package: org.apache.qpid.server.store.berkeleydb.jmx
diff --git a/java/bdbstore/jmx/build.xml b/java/bdbstore/jmx/build.xml
new file mode 100644
index 0000000000..229631555d
--- /dev/null
+++ b/java/bdbstore/jmx/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="bdbstore-jmx" default="build">
+ <property name="module.depends" value="common broker broker-plugins/management-jmx management/common bdbstore" />
+ <property name="module.test.depends" value="test broker/test common/test management/common client systests bdbstore/test" />
+
+ <property name="module.manifest" value="MANIFEST.MF" />
+ <property name="module.plugin" value="true" />
+ <property name="module.genpom" value="true"/>
+ <property name="module.genpom.args" value="-Sqpid-common=provided -Sqpid-broker=provided -Sqpid-broker-plugins-management-jmx=provided -Sqpid-management-common=provided -Sqpid-bdbstore=provided -Sje=provided"/>
+
+ <import file="../../module.xml" />
+
+ <target name="bundle" depends="bundle-tasks" />
+</project>
diff --git a/java/bdbstore/jmx/src/main/java/org/apache/qpid/server/store/berkeleydb/jmx/BDBHAMessageStoreManagerMBean.java b/java/bdbstore/jmx/src/main/java/org/apache/qpid/server/store/berkeleydb/jmx/BDBHAMessageStoreManagerMBean.java
new file mode 100644
index 0000000000..cfcea602b4
--- /dev/null
+++ b/java/bdbstore/jmx/src/main/java/org/apache/qpid/server/store/berkeleydb/jmx/BDBHAMessageStoreManagerMBean.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.server.store.berkeleydb.jmx;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+
+import javax.management.JMException;
+import javax.management.openmbean.CompositeData;
+import javax.management.openmbean.CompositeDataSupport;
+import javax.management.openmbean.CompositeType;
+import javax.management.openmbean.OpenDataException;
+import javax.management.openmbean.OpenType;
+import javax.management.openmbean.SimpleType;
+import javax.management.openmbean.TabularData;
+import javax.management.openmbean.TabularDataSupport;
+import javax.management.openmbean.TabularType;
+
+import org.apache.log4j.Logger;
+import org.apache.qpid.AMQStoreException;
+import org.apache.qpid.server.jmx.AMQManagedObject;
+import org.apache.qpid.server.jmx.ManagedObject;
+import org.apache.qpid.server.store.berkeleydb.BDBHAMessageStore;
+
+/**
+ * Management mbean for BDB HA.
+ * <p>
+ * At runtime, the classloader loading this clas must have visibility of the other Qpid JMX classes. This is
+ * currently arranged through OSGI using the <b>fragment</b> feature so that this bundle shares the
+ * same classloader as broker-plugins-management-jmx. See the <b>Fragment-Host:</b> header within the MANIFEST.MF
+ * of this bundle.
+ * </p>
+ */
+public class BDBHAMessageStoreManagerMBean extends AMQManagedObject implements ManagedBDBHAMessageStore
+{
+ private static final Logger LOGGER = Logger.getLogger(BDBHAMessageStoreManagerMBean.class);
+
+ private static final TabularType GROUP_MEMBERS_TABLE;
+ private static final CompositeType GROUP_MEMBER_ROW;
+ private static final OpenType<?>[] GROUP_MEMBER_ATTRIBUTE_TYPES;
+
+ static
+ {
+ try
+ {
+ GROUP_MEMBER_ATTRIBUTE_TYPES = new OpenType<?>[] {SimpleType.STRING, SimpleType.STRING};
+ final String[] itemNames = new String[] {BDBHAMessageStore.GRP_MEM_COL_NODE_NAME, BDBHAMessageStore.GRP_MEM_COL_NODE_HOST_PORT};
+ final String[] itemDescriptions = new String[] {"Unique node name", "Node host / port "};
+ GROUP_MEMBER_ROW = new CompositeType("GroupMember", "Replication group member",
+ itemNames,
+ itemDescriptions,
+ GROUP_MEMBER_ATTRIBUTE_TYPES );
+ GROUP_MEMBERS_TABLE = new TabularType("GroupMembers", "Replication group memebers",
+ GROUP_MEMBER_ROW,
+ new String[] {BDBHAMessageStore.GRP_MEM_COL_NODE_NAME});
+ }
+ catch (final OpenDataException ode)
+ {
+ throw new ExceptionInInitializerError(ode);
+ }
+ }
+
+ private final BDBHAMessageStore _store;
+
+ protected BDBHAMessageStoreManagerMBean(BDBHAMessageStore store, ManagedObject parent) throws JMException
+ {
+ super(ManagedBDBHAMessageStore.class, ManagedBDBHAMessageStore.TYPE, ((AMQManagedObject)parent).getRegistry());
+ LOGGER.debug("Creating BDBHAMessageStoreManagerMBean");
+ _store = store;
+ register();
+ }
+
+ @Override
+ public String getObjectInstanceName()
+ {
+ return _store.getName();
+ }
+
+ @Override
+ public String getGroupName()
+ {
+ return _store.getGroupName();
+ }
+
+ @Override
+ public String getNodeName()
+ {
+ return _store.getNodeName();
+ }
+
+ @Override
+ public String getNodeHostPort()
+ {
+ return _store.getNodeHostPort();
+ }
+
+ @Override
+ public String getHelperHostPort()
+ {
+ return _store.getHelperHostPort();
+ }
+
+ @Override
+ public String getDurability() throws IOException, JMException
+ {
+ try
+ {
+ return _store.getDurability();
+ }
+ catch (RuntimeException e)
+ {
+ LOGGER.debug("Failed query replication policy", e);
+ throw new JMException(e.getMessage());
+ }
+ }
+
+
+ @Override
+ public boolean getCoalescingSync() throws IOException, JMException
+ {
+ return _store.isCoalescingSync();
+ }
+
+ @Override
+ public String getNodeState() throws IOException, JMException
+ {
+ try
+ {
+ return _store.getNodeState();
+ }
+ catch (RuntimeException e)
+ {
+ LOGGER.debug("Failed query node state", e);
+ throw new JMException(e.getMessage());
+ }
+ }
+
+ @Override
+ public boolean getDesignatedPrimary() throws IOException, JMException
+ {
+ try
+ {
+ return _store.isDesignatedPrimary();
+ }
+ catch (RuntimeException e)
+ {
+ LOGGER.debug("Failed query designated primary", e);
+ throw new JMException(e.getMessage());
+ }
+ }
+
+ @Override
+ public TabularData getAllNodesInGroup() throws IOException, JMException
+ {
+ final TabularDataSupport data = new TabularDataSupport(GROUP_MEMBERS_TABLE);
+ final List<Map<String, String>> members = _store.getGroupMembers();
+
+ for (Map<String, String> map : members)
+ {
+ CompositeData memberData = new CompositeDataSupport(GROUP_MEMBER_ROW, map);
+ data.put(memberData);
+ }
+ return data;
+ }
+
+ @Override
+ public void removeNodeFromGroup(String nodeName) throws JMException
+ {
+ try
+ {
+ _store.removeNodeFromGroup(nodeName);
+ }
+ catch (AMQStoreException e)
+ {
+ LOGGER.error("Failed to remove node " + nodeName + " from group", e);
+ throw new JMException(e.getMessage());
+ }
+ }
+
+ @Override
+ public void setDesignatedPrimary(boolean primary) throws JMException
+ {
+ try
+ {
+ _store.setDesignatedPrimary(primary);
+ }
+ catch (AMQStoreException e)
+ {
+ LOGGER.error("Failed to set node " + _store.getNodeName() + " as designated primary", e);
+ throw new JMException(e.getMessage());
+ }
+ }
+
+ @Override
+ public void updateAddress(String nodeName, String newHostName, int newPort) throws JMException
+ {
+ try
+ {
+ _store.updateAddress(nodeName, newHostName, newPort);
+ }
+ catch(AMQStoreException e)
+ {
+ LOGGER.error("Failed to update address for node " + nodeName + " to " + newHostName + ":" + newPort, e);
+ throw new JMException(e.getMessage());
+ }
+ }
+
+ @Override
+ public ManagedObject getParentObject()
+ {
+ return null;
+ }
+
+}
diff --git a/java/bdbstore/jmx/src/main/java/org/apache/qpid/server/store/berkeleydb/jmx/BDBHAMessageStoreManagerMBeanProvider.java b/java/bdbstore/jmx/src/main/java/org/apache/qpid/server/store/berkeleydb/jmx/BDBHAMessageStoreManagerMBeanProvider.java
new file mode 100644
index 0000000000..837da1eef3
--- /dev/null
+++ b/java/bdbstore/jmx/src/main/java/org/apache/qpid/server/store/berkeleydb/jmx/BDBHAMessageStoreManagerMBeanProvider.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.server.store.berkeleydb.jmx;
+
+import javax.management.JMException;
+import javax.management.StandardMBean;
+
+import org.apache.log4j.Logger;
+import org.apache.qpid.server.jmx.MBeanProvider;
+import org.apache.qpid.server.jmx.ManagedObject;
+import org.apache.qpid.server.model.ConfiguredObject;
+import org.apache.qpid.server.model.VirtualHost;
+import org.apache.qpid.server.registry.ApplicationRegistry;
+import org.apache.qpid.server.store.berkeleydb.BDBHAMessageStore;
+import org.apache.qpid.server.virtualhost.VirtualHostRegistry;
+
+/**
+ * This provide will create a {@link BDBHAMessageStoreManagerMBean} if the child is a virtual
+ * host and of type {@link BDBHAMessageStore#BDB_HA_STORE_TYPE}.
+ *
+ */
+public class BDBHAMessageStoreManagerMBeanProvider implements MBeanProvider
+{
+ private static final Logger LOGGER = Logger.getLogger(BDBHAMessageStoreManagerMBeanProvider.class);
+
+ public BDBHAMessageStoreManagerMBeanProvider()
+ {
+ super();
+ }
+
+ @Override
+ public boolean isChildManageableByMBean(ConfiguredObject child)
+ {
+ return (child instanceof VirtualHost
+ && BDBHAMessageStore.BDB_HA_STORE_TYPE.equals(child.getAttribute(VirtualHost.STORE_TYPE)));
+ }
+
+ @Override
+ public StandardMBean createMBean(ConfiguredObject child, StandardMBean parent) throws JMException
+ {
+ VirtualHost virtualHostChild = (VirtualHost) child;
+
+ VirtualHostRegistry virtualHostRegistry = ApplicationRegistry.getInstance().getVirtualHostRegistry();
+ org.apache.qpid.server.virtualhost.VirtualHost vhost = virtualHostRegistry.getVirtualHost(virtualHostChild.getName());
+
+ BDBHAMessageStore messageStore = (BDBHAMessageStore) vhost.getMessageStore();
+
+ if (LOGGER.isDebugEnabled())
+ {
+ LOGGER.debug("Creating mBean for child " + child);
+ }
+
+ return new BDBHAMessageStoreManagerMBean(messageStore, (ManagedObject) parent);
+ }
+}
diff --git a/java/bdbstore/jmx/src/main/java/org/apache/qpid/server/store/berkeleydb/jmx/ManagedBDBHAMessageStore.java b/java/bdbstore/jmx/src/main/java/org/apache/qpid/server/store/berkeleydb/jmx/ManagedBDBHAMessageStore.java
new file mode 100644
index 0000000000..b85e44526b
--- /dev/null
+++ b/java/bdbstore/jmx/src/main/java/org/apache/qpid/server/store/berkeleydb/jmx/ManagedBDBHAMessageStore.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.server.store.berkeleydb.jmx;
+
+import java.io.IOException;
+
+import javax.management.JMException;
+import javax.management.openmbean.TabularData;
+
+import org.apache.qpid.management.common.mbeans.annotations.MBeanAttribute;
+import org.apache.qpid.management.common.mbeans.annotations.MBeanOperationParameter;
+import org.apache.qpid.management.common.mbeans.annotations.MBeanOperation;
+
+public interface ManagedBDBHAMessageStore
+{
+ public static final String TYPE = "BDBHAMessageStore";
+
+ public static final String ATTR_GROUP_NAME = "GroupName";
+ public static final String ATTR_NODE_NAME = "NodeName";
+ public static final String ATTR_NODE_HOST_PORT = "NodeHostPort";
+ public static final String ATTR_HELPER_HOST_PORT = "HelperHostPort";
+ public static final String ATTR_DURABILITY = "Durability";
+ public static final String ATTR_NODE_STATE = "NodeState";
+ public static final String ATTR_DESIGNATED_PRIMARY = "DesignatedPrimary";
+ public static final String ATTR_COALESCING_SYNC = "CoalescingSync";
+
+ @MBeanAttribute(name=ATTR_GROUP_NAME, description="Name identifying the group")
+ String getGroupName() throws IOException, JMException;
+
+ @MBeanAttribute(name=ATTR_NODE_NAME, description="Unique name identifying the node within the group")
+ String getNodeName() throws IOException, JMException;
+
+ @MBeanAttribute(name=ATTR_NODE_HOST_PORT, description="Host/port used to replicate data between this node and others in the group")
+ String getNodeHostPort() throws IOException, JMException;
+
+ @MBeanAttribute(name=ATTR_NODE_STATE, description="Current state of this node")
+ String getNodeState() throws IOException, JMException;
+
+ @MBeanAttribute(name=ATTR_HELPER_HOST_PORT, description="Host/port used to allow a new node to discover other group members")
+ String getHelperHostPort() throws IOException, JMException;
+
+ @MBeanAttribute(name=ATTR_DURABILITY, description="Durability")
+ String getDurability() throws IOException, JMException;
+
+ @MBeanAttribute(name=ATTR_DESIGNATED_PRIMARY, description="Designated primary flag. Applicable to the two node case.")
+ boolean getDesignatedPrimary() throws IOException, JMException;
+
+ @MBeanAttribute(name=ATTR_COALESCING_SYNC, description="Coalescing sync flag. Applicable to the master sync policies NO_SYNC and WRITE_NO_SYNC only.")
+ boolean getCoalescingSync() throws IOException, JMException;
+
+ @MBeanAttribute(name="getAllNodesInGroup", description="Get all nodes within the group, regardless of whether currently attached or not")
+ TabularData getAllNodesInGroup() throws IOException, JMException;
+
+ @MBeanOperation(name="removeNodeFromGroup", description="Remove an existing node from the group")
+ void removeNodeFromGroup(@MBeanOperationParameter(name="nodeName", description="name of node")String nodeName) throws JMException;
+
+ @MBeanOperation(name="setDesignatedPrimary", description="Set/unset this node as the designated primary for the group. Applicable to the two node case.")
+ void setDesignatedPrimary(@MBeanOperationParameter(name="primary", description="designated primary")boolean primary) throws JMException;
+
+ @MBeanOperation(name="updateAddress", description="Update the address of another node. The node must be in a STOPPED state.")
+ void updateAddress(@MBeanOperationParameter(name="nodeName", description="name of node")String nodeName,
+ @MBeanOperationParameter(name="newHostName", description="new hostname")String newHostName,
+ @MBeanOperationParameter(name="newPort", description="new port number")int newPort) throws JMException;
+}
+
diff --git a/java/bdbstore/jmx/src/main/resources/META-INF/services/org.apache.qpid.server.jmx.MBeanProvider b/java/bdbstore/jmx/src/main/resources/META-INF/services/org.apache.qpid.server.jmx.MBeanProvider
new file mode 100644
index 0000000000..b5bc947612
--- /dev/null
+++ b/java/bdbstore/jmx/src/main/resources/META-INF/services/org.apache.qpid.server.jmx.MBeanProvider
@@ -0,0 +1 @@
+org.apache.qpid.server.store.berkeleydb.jmx.BDBHAMessageStoreManagerMBeanProvider
diff --git a/java/bdbstore/jmx/src/test/java/org/apache/qpid/server/store/berkeleydb/HAClusterManagementTest.java b/java/bdbstore/jmx/src/test/java/org/apache/qpid/server/store/berkeleydb/HAClusterManagementTest.java
new file mode 100644
index 0000000000..606983cdae
--- /dev/null
+++ b/java/bdbstore/jmx/src/test/java/org/apache/qpid/server/store/berkeleydb/HAClusterManagementTest.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.server.store.berkeleydb;
+
+import static com.sleepycat.je.rep.ReplicatedEnvironment.State.DETACHED;
+import static com.sleepycat.je.rep.ReplicatedEnvironment.State.MASTER;
+import static com.sleepycat.je.rep.ReplicatedEnvironment.State.REPLICA;
+import static com.sleepycat.je.rep.ReplicatedEnvironment.State.UNKNOWN;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+import javax.jms.Connection;
+import javax.management.openmbean.CompositeData;
+import javax.management.openmbean.TabularData;
+
+import org.apache.log4j.Logger;
+import org.apache.qpid.jms.ConnectionURL;
+import org.apache.qpid.management.common.mbeans.ManagedBroker;
+import org.apache.qpid.server.store.berkeleydb.jmx.ManagedBDBHAMessageStore;
+import org.apache.qpid.server.virtualhost.ManagedVirtualHost;
+import org.apache.qpid.test.utils.JMXTestUtils;
+import org.apache.qpid.test.utils.QpidBrokerTestCase;
+
+import com.sleepycat.je.EnvironmentFailureException;
+
+/**
+ * System test verifying the ability to control a cluster via the Management API.
+ *
+ * @see HAClusterBlackboxTest
+ */
+public class HAClusterManagementTest extends QpidBrokerTestCase
+{
+ protected static final Logger LOGGER = Logger.getLogger(HAClusterManagementTest.class);
+
+ private static final Set<String> NON_MASTER_STATES = new HashSet<String>(Arrays.asList(REPLICA.toString(), DETACHED.toString(), UNKNOWN.toString()));;
+ private static final String VIRTUAL_HOST = "test";
+
+ private static final String MANAGED_OBJECT_QUERY = "org.apache.qpid:type=BDBHAMessageStore,name=" + VIRTUAL_HOST;
+ private static final int NUMBER_OF_NODES = 4;
+
+ private final HATestClusterCreator _clusterCreator = new HATestClusterCreator(this, VIRTUAL_HOST, NUMBER_OF_NODES);
+ private final JMXTestUtils _jmxUtils = new JMXTestUtils(this);
+
+ private ConnectionURL _brokerFailoverUrl;
+
+ @Override
+ protected void setUp() throws Exception
+ {
+ _brokerType = BrokerType.SPAWNED;
+ _jmxUtils.setUp();
+
+ _clusterCreator.configureClusterNodes();
+ _brokerFailoverUrl = _clusterCreator.getConnectionUrlForAllClusterNodes();
+ _clusterCreator.startCluster();
+
+ super.setUp();
+ }
+
+ @Override
+ protected void tearDown() throws Exception
+ {
+ try
+ {
+ _jmxUtils.close();
+ }
+ finally
+ {
+ super.tearDown();
+ }
+ }
+
+ @Override
+ public void startBroker() throws Exception
+ {
+ // Don't start default broker provided by QBTC.
+ }
+
+ public void testReadonlyMBeanAttributes() throws Exception
+ {
+ final int brokerPortNumber = getBrokerPortNumbers().iterator().next();
+ final int bdbPortNumber = _clusterCreator.getBdbPortForBrokerPort(brokerPortNumber);
+
+ ManagedBDBHAMessageStore storeBean = getStoreBeanForNodeAtBrokerPort(brokerPortNumber);
+ assertEquals("Unexpected store group name", _clusterCreator.getGroupName(), storeBean.getGroupName());
+ assertEquals("Unexpected store node name", _clusterCreator.getNodeNameForNodeAt(bdbPortNumber), storeBean.getNodeName());
+ assertEquals("Unexpected store node host port",_clusterCreator.getNodeHostPortForNodeAt(bdbPortNumber), storeBean.getNodeHostPort());
+ assertEquals("Unexpected store helper host port", _clusterCreator.getHelperHostPort(), storeBean.getHelperHostPort());
+ // As we have chosen an arbitrary broker from the cluster, we cannot predict its state
+ assertNotNull("Store state must not be null", storeBean.getNodeState());
+ }
+
+ public void testStateOfActiveBrokerIsMaster() throws Exception
+ {
+ final Connection activeConnection = getConnection(_brokerFailoverUrl);
+ final int activeBrokerPortNumber = _clusterCreator.getBrokerPortNumberFromConnection(activeConnection);
+
+ ManagedBDBHAMessageStore storeBean = getStoreBeanForNodeAtBrokerPort(activeBrokerPortNumber);
+ assertEquals("Unexpected store state", MASTER.toString(), storeBean.getNodeState());
+ }
+
+ public void testStateOfNonActiveBrokerIsNotMaster() throws Exception
+ {
+ final Connection activeConnection = getConnection(_brokerFailoverUrl);
+ final int inactiveBrokerPortNumber = _clusterCreator.getPortNumberOfAnInactiveBroker(activeConnection);
+ ManagedBDBHAMessageStore storeBean = getStoreBeanForNodeAtBrokerPort(inactiveBrokerPortNumber);
+ final String nodeState = storeBean.getNodeState();
+ assertTrue("Unexpected store state : " + nodeState, NON_MASTER_STATES.contains(nodeState));
+ }
+
+ public void testGroupMembers() throws Exception
+ {
+ final int brokerPortNumber = getBrokerPortNumbers().iterator().next();
+
+ ManagedBDBHAMessageStore storeBean = getStoreBeanForNodeAtBrokerPort(brokerPortNumber);
+ final TabularData groupMembers = storeBean.getAllNodesInGroup();
+ assertNotNull(groupMembers);
+
+ final int numberOfDataRows = groupMembers.size();
+ assertEquals("Unexpected number of data rows", NUMBER_OF_NODES ,numberOfDataRows);
+
+ for(int bdbPortNumber : _clusterCreator.getBdbPortNumbers())
+ {
+ final String nodeName = _clusterCreator.getNodeNameForNodeAt(bdbPortNumber);
+ final String nodeHostPort = _clusterCreator.getNodeHostPortForNodeAt(bdbPortNumber);
+
+ CompositeData row = groupMembers.get(new Object[] {nodeName});
+ assertNotNull("Table does not contain row for node name " + nodeName, row);
+ assertEquals(nodeHostPort, row.get(BDBHAMessageStore.GRP_MEM_COL_NODE_HOST_PORT));
+ }
+ }
+
+ public void testRemoveNodeFromGroup() throws Exception
+ {
+ final Iterator<Integer> brokerPortNumberIterator = getBrokerPortNumbers().iterator();
+ final int brokerPortNumberToMakeObservation = brokerPortNumberIterator.next();
+ final int brokerPortNumberToBeRemoved = brokerPortNumberIterator.next();
+ final ManagedBDBHAMessageStore storeBean = getStoreBeanForNodeAtBrokerPort(brokerPortNumberToMakeObservation);
+ final int numberOfDataRows = storeBean.getAllNodesInGroup().size();
+ assertEquals("Unexpected number of data rows before test", NUMBER_OF_NODES ,numberOfDataRows);
+
+ final String removedNodeName = _clusterCreator.getNodeNameForNodeAt(_clusterCreator.getBdbPortForBrokerPort(brokerPortNumberToBeRemoved));
+ _clusterCreator.stopNode(brokerPortNumberToBeRemoved);
+ storeBean.removeNodeFromGroup(removedNodeName);
+
+ final int numberOfDataRowsAfterRemoval = storeBean.getAllNodesInGroup().size();
+ assertEquals("Unexpected number of data rows before test", NUMBER_OF_NODES - 1,numberOfDataRowsAfterRemoval);
+ }
+
+ /**
+ * Updates the address of a node.
+ *
+ * If the broker (node) can subsequently start without error then the update was a success, hence no need for an explicit
+ * assert.
+ *
+ * @see #testRestartNodeWithNewPortNumberWithoutFirstCallingUpdateAddressThrowsAnException() for converse case
+ */
+ public void testUpdateAddress() throws Exception
+ {
+ final Iterator<Integer> brokerPortNumberIterator = getBrokerPortNumbers().iterator();
+ final int brokerPortNumberToPerformUpdate = brokerPortNumberIterator.next();
+ final int brokerPortNumberToBeMoved = brokerPortNumberIterator.next();
+ final ManagedBDBHAMessageStore storeBean = getStoreBeanForNodeAtBrokerPort(brokerPortNumberToPerformUpdate);
+
+ _clusterCreator.stopNode(brokerPortNumberToBeMoved);
+
+ final int oldBdbPort = _clusterCreator.getBdbPortForBrokerPort(brokerPortNumberToBeMoved);
+ final int newBdbPort = getNextAvailable(oldBdbPort + 1);
+
+ storeBean.updateAddress(_clusterCreator.getNodeNameForNodeAt(oldBdbPort), _clusterCreator.getIpAddressOfBrokerHost(), newBdbPort);
+
+ _clusterCreator.modifyClusterNodeBdbAddress(brokerPortNumberToBeMoved, newBdbPort);
+
+ _clusterCreator.startNode(brokerPortNumberToBeMoved);
+ }
+
+ /**
+ * @see #testUpdateAddress()
+ */
+ public void testRestartNodeWithNewPortNumberWithoutFirstCallingUpdateAddressThrowsAnException() throws Exception
+ {
+ final Iterator<Integer> brokerPortNumberIterator = getBrokerPortNumbers().iterator();
+ final int brokerPortNumberToBeMoved = brokerPortNumberIterator.next();
+
+ _clusterCreator.stopNode(brokerPortNumberToBeMoved);
+
+ final int oldBdbPort = _clusterCreator.getBdbPortForBrokerPort(brokerPortNumberToBeMoved);
+ final int newBdbPort = getNextAvailable(oldBdbPort + 1);
+
+ // now deliberately don't call updateAddress
+
+ _clusterCreator.modifyClusterNodeBdbAddress(brokerPortNumberToBeMoved, newBdbPort);
+
+ try
+ {
+ _clusterCreator.startNode(brokerPortNumberToBeMoved);
+ fail("Exception not thrown");
+ }
+ catch(RuntimeException rte)
+ {
+ //check cause was BDBs EnvironmentFailureException
+ assertTrue(rte.getMessage().contains(EnvironmentFailureException.class.getName()));
+ // PASS
+ }
+ }
+
+ public void testVirtualHostOperationsDeniedForNonMasterNode() throws Exception
+ {
+ final Connection activeConnection = getConnection(_brokerFailoverUrl);
+ final int inactiveBrokerPortNumber = _clusterCreator.getPortNumberOfAnInactiveBroker(activeConnection);
+
+ ManagedBroker inactiveBroker = getManagedBrokerBeanForNodeAtBrokerPort(inactiveBrokerPortNumber);
+
+ try
+ {
+ inactiveBroker.createNewQueue(getTestQueueName(), null, true);
+ fail("Exception not thrown");
+ }
+ catch (Exception e)
+ {
+ String message = e.getMessage();
+ assertEquals(message, "The virtual hosts state of INITIALISING does not permit this operation.");
+ }
+
+ try
+ {
+ inactiveBroker.createNewExchange(getName(), "direct", true);
+ fail("Exception not thrown");
+ }
+ catch (Exception e)
+ {
+ String message = e.getMessage();
+ assertEquals(message, "The virtual hosts state of INITIALISING does not permit this operation.");
+ }
+ }
+
+ private ManagedBDBHAMessageStore getStoreBeanForNodeAtBrokerPort(final int brokerPortNumber) throws Exception
+ {
+ _jmxUtils.open(brokerPortNumber);
+
+ return _jmxUtils.getManagedObject(ManagedBDBHAMessageStore.class, MANAGED_OBJECT_QUERY);
+ }
+
+ private ManagedBroker getManagedBrokerBeanForNodeAtBrokerPort(final int brokerPortNumber) throws Exception
+ {
+ _jmxUtils.open(brokerPortNumber);
+
+ return _jmxUtils.getManagedBroker(VIRTUAL_HOST);
+ }
+}
diff --git a/java/bdbstore/jmx/src/test/java/org/apache/qpid/server/store/berkeleydb/HAClusterTwoNodeTest.java b/java/bdbstore/jmx/src/test/java/org/apache/qpid/server/store/berkeleydb/HAClusterTwoNodeTest.java
new file mode 100644
index 0000000000..22877ec36c
--- /dev/null
+++ b/java/bdbstore/jmx/src/test/java/org/apache/qpid/server/store/berkeleydb/HAClusterTwoNodeTest.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.server.store.berkeleydb;
+
+import java.io.File;
+
+import javax.jms.Connection;
+import javax.jms.Destination;
+import javax.jms.JMSException;
+import javax.jms.Message;
+import javax.jms.MessageConsumer;
+import javax.jms.Session;
+
+import org.apache.qpid.jms.ConnectionURL;
+import org.apache.qpid.server.store.berkeleydb.jmx.ManagedBDBHAMessageStore;
+import org.apache.qpid.test.utils.JMXTestUtils;
+import org.apache.qpid.test.utils.QpidBrokerTestCase;
+
+import com.sleepycat.je.rep.ReplicationConfig;
+
+public class HAClusterTwoNodeTest extends QpidBrokerTestCase
+{
+ private static final long RECEIVE_TIMEOUT = 5000l;
+
+ private static final String VIRTUAL_HOST = "test";
+
+ private static final String MANAGED_OBJECT_QUERY = "org.apache.qpid:type=BDBHAMessageStore,name=" + VIRTUAL_HOST;
+ private static final int NUMBER_OF_NODES = 2;
+
+ private final HATestClusterCreator _clusterCreator = new HATestClusterCreator(this, VIRTUAL_HOST, NUMBER_OF_NODES);
+ private final JMXTestUtils _jmxUtils = new JMXTestUtils(this);
+
+ private ConnectionURL _brokerFailoverUrl;
+
+ @Override
+ protected void setUp() throws Exception
+ {
+ _brokerType = BrokerType.SPAWNED;
+
+ assertTrue(isJavaBroker());
+ assertTrue(isBrokerStorePersistent());
+ _jmxUtils.setUp();
+
+ super.setUp();
+ }
+
+ @Override
+ protected void tearDown() throws Exception
+ {
+ try
+ {
+ _jmxUtils.close();
+ }
+ finally
+ {
+ super.tearDown();
+ }
+ }
+
+ @Override
+ public void startBroker() throws Exception
+ {
+ // Don't start default broker provided by QBTC.
+ }
+
+ private void startCluster(boolean designedPrimary) throws Exception
+ {
+ setSystemProperty("java.util.logging.config.file", "etc" + File.separator + "log.properties");
+
+ String storeConfigKeyPrefix = _clusterCreator.getStoreConfigKeyPrefix();
+
+ setConfigurationProperty(storeConfigKeyPrefix + ".repConfig(0).name", ReplicationConfig.INSUFFICIENT_REPLICAS_TIMEOUT);
+ setConfigurationProperty(storeConfigKeyPrefix + ".repConfig(0).value", "2 s");
+
+ setConfigurationProperty(storeConfigKeyPrefix + ".repConfig(1).name", ReplicationConfig.ELECTIONS_PRIMARY_RETRIES);
+ setConfigurationProperty(storeConfigKeyPrefix + ".repConfig(1).value", "0");
+
+ _clusterCreator.configureClusterNodes();
+ _clusterCreator.setDesignatedPrimaryOnFirstBroker(designedPrimary);
+ _brokerFailoverUrl = _clusterCreator.getConnectionUrlForAllClusterNodes();
+ _clusterCreator.startCluster();
+ }
+
+ public void testMasterDesignatedPrimaryCanBeRestartedWithoutReplica() throws Exception
+ {
+ startCluster(true);
+ final Connection initialConnection = getConnection(_brokerFailoverUrl);
+ int masterPort = _clusterCreator.getBrokerPortNumberFromConnection(initialConnection);
+ assertProducingConsuming(initialConnection);
+ initialConnection.close();
+ _clusterCreator.stopCluster();
+ _clusterCreator.startNode(masterPort);
+ final Connection secondConnection = getConnection(_brokerFailoverUrl);
+ assertProducingConsuming(secondConnection);
+ secondConnection.close();
+ }
+
+ public void testClusterRestartWithoutDesignatedPrimary() throws Exception
+ {
+ startCluster(false);
+ final Connection initialConnection = getConnection(_brokerFailoverUrl);
+ assertProducingConsuming(initialConnection);
+ initialConnection.close();
+ _clusterCreator.stopCluster();
+ _clusterCreator.startClusterParallel();
+ final Connection secondConnection = getConnection(_brokerFailoverUrl);
+ assertProducingConsuming(secondConnection);
+ secondConnection.close();
+ }
+
+ public void testDesignatedPrimaryContinuesAfterSecondaryStopped() throws Exception
+ {
+ startCluster(true);
+ _clusterCreator.stopNode(_clusterCreator.getBrokerPortNumberOfSecondaryNode());
+ final Connection connection = getConnection(_brokerFailoverUrl);
+ assertNotNull("Expected to get a valid connection to primary", connection);
+ assertProducingConsuming(connection);
+ }
+
+ public void testPersistentOperationsFailOnNonDesignatedPrimarysAfterSecondaryStopped() throws Exception
+ {
+ startCluster(false);
+ _clusterCreator.stopNode(_clusterCreator.getBrokerPortNumberOfSecondaryNode());
+ final Connection connection = getConnection(_brokerFailoverUrl);
+ assertNotNull("Expected to get a valid connection to primary", connection);
+ try
+ {
+ assertProducingConsuming(connection);
+ fail("JMS peristent operations succeded on Master 'not designated primary' buy they should fail as replica is not available");
+ }
+ catch(JMSException e)
+ {
+ // JMSException should be thrown on transaction start/commit
+ }
+ }
+
+ public void testSecondaryDoesNotBecomePrimaryWhenDesignatedPrimaryStopped() throws Exception
+ {
+ startCluster(true);
+ _clusterCreator.stopNode(_clusterCreator.getBrokerPortNumberOfPrimary());
+
+ try
+ {
+ getConnection(_brokerFailoverUrl);
+ fail("Connection not expected");
+ }
+ catch (JMSException e)
+ {
+ // PASS
+ }
+ }
+
+ public void testInitialDesignatedPrimaryStateOfNodes() throws Exception
+ {
+ startCluster(true);
+ final ManagedBDBHAMessageStore primaryStoreBean = getStoreBeanForNodeAtBrokerPort(_clusterCreator.getBrokerPortNumberOfPrimary());
+ assertTrue("Expected primary node to be set as designated primary", primaryStoreBean.getDesignatedPrimary());
+
+ final ManagedBDBHAMessageStore secondaryStoreBean = getStoreBeanForNodeAtBrokerPort(_clusterCreator.getBrokerPortNumberOfSecondaryNode());
+ assertFalse("Expected secondary node to NOT be set as designated primary", secondaryStoreBean.getDesignatedPrimary());
+ }
+
+ public void testSecondaryDesignatedAsPrimaryAfterOrginalPrimaryStopped() throws Exception
+ {
+ startCluster(true);
+ _clusterCreator.stopNode(_clusterCreator.getBrokerPortNumberOfPrimary());
+ final ManagedBDBHAMessageStore storeBean = getStoreBeanForNodeAtBrokerPort(_clusterCreator.getBrokerPortNumberOfSecondaryNode());
+
+ assertFalse("Expected node to NOT be set as designated primary", storeBean.getDesignatedPrimary());
+ storeBean.setDesignatedPrimary(true);
+ assertTrue("Expected node to now be set as designated primary", storeBean.getDesignatedPrimary());
+
+ final Connection connection = getConnection(_brokerFailoverUrl);
+ assertNotNull("Expected to get a valid connection to new primary", connection);
+ assertProducingConsuming(connection);
+ }
+
+ private ManagedBDBHAMessageStore getStoreBeanForNodeAtBrokerPort(
+ final int activeBrokerPortNumber) throws Exception
+ {
+ _jmxUtils.open(activeBrokerPortNumber);
+
+ ManagedBDBHAMessageStore storeBean = _jmxUtils.getManagedObject(ManagedBDBHAMessageStore.class, MANAGED_OBJECT_QUERY);
+ return storeBean;
+ }
+
+ private void assertProducingConsuming(final Connection connection) throws JMSException, Exception
+ {
+ Session session = connection.createSession(true, Session.SESSION_TRANSACTED);
+ Destination destination = session.createQueue(getTestQueueName());
+ MessageConsumer consumer = session.createConsumer(destination);
+ sendMessage(session, destination, 1);
+ connection.start();
+ Message m1 = consumer.receive(RECEIVE_TIMEOUT);
+ assertNotNull("Message 1 is not received", m1);
+ assertEquals("Unexpected first message received", 0, m1.getIntProperty(INDEX));
+ session.commit();
+ }
+
+}
diff --git a/java/bdbstore/jmx/src/test/java/org/apache/qpid/server/store/berkeleydb/jmx/BDBHAMessageStoreManagerMBeanTest.java b/java/bdbstore/jmx/src/test/java/org/apache/qpid/server/store/berkeleydb/jmx/BDBHAMessageStoreManagerMBeanTest.java
new file mode 100644
index 0000000000..49b3ddd3dc
--- /dev/null
+++ b/java/bdbstore/jmx/src/test/java/org/apache/qpid/server/store/berkeleydb/jmx/BDBHAMessageStoreManagerMBeanTest.java
@@ -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.
+ *
+ */
+package org.apache.qpid.server.store.berkeleydb.jmx;
+
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.management.JMException;
+import javax.management.openmbean.CompositeData;
+import javax.management.openmbean.CompositeType;
+import javax.management.openmbean.TabularData;
+
+import junit.framework.TestCase;
+
+import org.apache.qpid.AMQStoreException;
+import org.apache.qpid.server.jmx.AMQManagedObject;
+import org.apache.qpid.server.jmx.ManagedObjectRegistry;
+import org.apache.qpid.server.logging.SystemOutMessageLogger;
+import org.apache.qpid.server.logging.actors.CurrentActor;
+import org.apache.qpid.server.logging.actors.TestLogActor;
+import org.apache.qpid.server.store.berkeleydb.BDBHAMessageStore;
+import org.apache.qpid.server.store.berkeleydb.jmx.BDBHAMessageStoreManagerMBean;
+import org.apache.qpid.server.store.berkeleydb.jmx.ManagedBDBHAMessageStore;
+
+public class BDBHAMessageStoreManagerMBeanTest extends TestCase
+{
+ private static final String TEST_GROUP_NAME = "testGroupName";
+ private static final String TEST_NODE_NAME = "testNodeName";
+ private static final String TEST_NODE_HOST_PORT = "host:1234";
+ private static final String TEST_HELPER_HOST_PORT = "host:5678";
+ private static final String TEST_DURABILITY = "sync,sync,all";
+ private static final String TEST_NODE_STATE = "MASTER";
+ private static final String TEST_STORE_NAME = "testStoreName";
+ private static final boolean TEST_DESIGNATED_PRIMARY_FLAG = false;
+
+ private BDBHAMessageStore _store;
+ private BDBHAMessageStoreManagerMBean _mBean;
+ private AMQManagedObject _mBeanParent;
+
+ @Override
+ protected void setUp() throws Exception
+ {
+ super.setUp();
+
+ CurrentActor.set(new TestLogActor(new SystemOutMessageLogger()));
+ _store = mock(BDBHAMessageStore.class);
+ _mBeanParent = mock(AMQManagedObject.class);
+ when(_mBeanParent.getRegistry()).thenReturn(mock(ManagedObjectRegistry.class));
+ _mBean = new BDBHAMessageStoreManagerMBean(_store, _mBeanParent);
+ }
+
+ @Override
+ protected void tearDown() throws Exception
+ {
+ super.tearDown();
+ CurrentActor.remove();
+ }
+
+ public void testObjectName() throws Exception
+ {
+ when(_store.getName()).thenReturn(TEST_STORE_NAME);
+
+ String expectedObjectName = "org.apache.qpid:type=BDBHAMessageStore,name=" + TEST_STORE_NAME;
+ assertEquals(expectedObjectName, _mBean.getObjectName().toString());
+ }
+
+ public void testGroupName() throws Exception
+ {
+ when(_store.getGroupName()).thenReturn(TEST_GROUP_NAME);
+
+ assertEquals(TEST_GROUP_NAME, _mBean.getAttribute(ManagedBDBHAMessageStore.ATTR_GROUP_NAME));
+ }
+
+ public void testNodeName() throws Exception
+ {
+ when(_store.getNodeName()).thenReturn(TEST_NODE_NAME);
+
+ assertEquals(TEST_NODE_NAME, _mBean.getAttribute(ManagedBDBHAMessageStore.ATTR_NODE_NAME));
+ }
+
+ public void testNodeHostPort() throws Exception
+ {
+ when(_store.getNodeHostPort()).thenReturn(TEST_NODE_HOST_PORT);
+
+ assertEquals(TEST_NODE_HOST_PORT, _mBean.getAttribute(ManagedBDBHAMessageStore.ATTR_NODE_HOST_PORT));
+ }
+
+ public void testHelperHostPort() throws Exception
+ {
+ when(_store.getHelperHostPort()).thenReturn(TEST_HELPER_HOST_PORT);
+
+ assertEquals(TEST_HELPER_HOST_PORT, _mBean.getAttribute(ManagedBDBHAMessageStore.ATTR_HELPER_HOST_PORT));
+ }
+
+ public void testDurability() throws Exception
+ {
+ when(_store.getDurability()).thenReturn(TEST_DURABILITY);
+
+ assertEquals(TEST_DURABILITY, _mBean.getAttribute(ManagedBDBHAMessageStore.ATTR_DURABILITY));
+ }
+
+ public void testCoalescingSync() throws Exception
+ {
+ when(_store.isCoalescingSync()).thenReturn(true);
+
+ assertEquals(true, _mBean.getAttribute(ManagedBDBHAMessageStore.ATTR_COALESCING_SYNC));
+ }
+
+ public void testNodeState() throws Exception
+ {
+ when(_store.getNodeState()).thenReturn(TEST_NODE_STATE);
+
+ assertEquals(TEST_NODE_STATE, _mBean.getAttribute(ManagedBDBHAMessageStore.ATTR_NODE_STATE));
+ }
+
+ public void testDesignatedPrimaryFlag() throws Exception
+ {
+ when(_store.isDesignatedPrimary()).thenReturn(TEST_DESIGNATED_PRIMARY_FLAG);
+
+ assertEquals(TEST_DESIGNATED_PRIMARY_FLAG, _mBean.getAttribute(ManagedBDBHAMessageStore.ATTR_DESIGNATED_PRIMARY));
+ }
+
+ public void testGroupMembersForGroupWithOneNode() throws Exception
+ {
+ List<Map<String, String>> members = Collections.singletonList(createTestNodeResult());
+ when(_store.getGroupMembers()).thenReturn(members);
+
+ final TabularData resultsTable = _mBean.getAllNodesInGroup();
+
+ assertTableHasHeadingsNamed(resultsTable, BDBHAMessageStore.GRP_MEM_COL_NODE_NAME, BDBHAMessageStore.GRP_MEM_COL_NODE_HOST_PORT);
+
+ final int numberOfDataRows = resultsTable.size();
+ assertEquals("Unexpected number of data rows", 1 ,numberOfDataRows);
+ final CompositeData row = (CompositeData) resultsTable.values().iterator().next();
+ assertEquals(TEST_NODE_NAME, row.get(BDBHAMessageStore.GRP_MEM_COL_NODE_NAME));
+ assertEquals(TEST_NODE_HOST_PORT, row.get(BDBHAMessageStore.GRP_MEM_COL_NODE_HOST_PORT));
+ }
+
+ public void testRemoveNodeFromReplicationGroup() throws Exception
+ {
+ _mBean.removeNodeFromGroup(TEST_NODE_NAME);
+
+ verify(_store).removeNodeFromGroup(TEST_NODE_NAME);
+ }
+
+ public void testRemoveNodeFromReplicationGroupWithError() throws Exception
+ {
+ doThrow(new AMQStoreException("mocked exception")).when(_store).removeNodeFromGroup(TEST_NODE_NAME);
+
+ try
+ {
+ _mBean.removeNodeFromGroup(TEST_NODE_NAME);
+ fail("Exception not thrown");
+ }
+ catch (JMException je)
+ {
+ // PASS
+ }
+ }
+
+ public void testSetAsDesignatedPrimary() throws Exception
+ {
+ _mBean.setDesignatedPrimary(true);
+
+ verify(_store).setDesignatedPrimary(true);
+ }
+
+ public void testSetAsDesignatedPrimaryWithError() throws Exception
+ {
+ doThrow(new AMQStoreException("mocked exception")).when(_store).setDesignatedPrimary(true);
+
+ try
+ {
+ _mBean.setDesignatedPrimary(true);
+ fail("Exception not thrown");
+ }
+ catch (JMException je)
+ {
+ // PASS
+ }
+ }
+
+ public void testUpdateAddress() throws Exception
+ {
+ String newHostName = "newHostName";
+ int newPort = 1967;
+
+ _mBean.updateAddress(TEST_NODE_NAME, newHostName, newPort);
+
+ verify(_store).updateAddress(TEST_NODE_NAME, newHostName, newPort);
+ }
+
+ private void assertTableHasHeadingsNamed(final TabularData resultsTable, String... headingNames)
+ {
+ CompositeType headingsRow = resultsTable.getTabularType().getRowType();
+ for (final String headingName : headingNames)
+ {
+ assertTrue("Table should have column with heading " + headingName, headingsRow.containsKey(headingName));
+ }
+ }
+
+ private Map<String, String> createTestNodeResult()
+ {
+ Map<String, String> items = new HashMap<String, String>();
+ items.put(BDBHAMessageStore.GRP_MEM_COL_NODE_NAME, TEST_NODE_NAME);
+ items.put(BDBHAMessageStore.GRP_MEM_COL_NODE_HOST_PORT, TEST_NODE_HOST_PORT);
+ return items;
+ }
+}
diff --git a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/AbstractBDBMessageStore.java b/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/AbstractBDBMessageStore.java
index fb1d7c5265..9323111fdd 100644
--- a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/AbstractBDBMessageStore.java
+++ b/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/AbstractBDBMessageStore.java
@@ -22,6 +22,7 @@ package org.apache.qpid.server.store.berkeleydb;
import com.sleepycat.bind.tuple.ByteBinding;
import com.sleepycat.bind.tuple.LongBinding;
+import com.sleepycat.je.CheckpointConfig;
import com.sleepycat.je.Cursor;
import com.sleepycat.je.Database;
import com.sleepycat.je.DatabaseConfig;
@@ -29,14 +30,17 @@ import com.sleepycat.je.DatabaseEntry;
import com.sleepycat.je.DatabaseException;
import com.sleepycat.je.Environment;
import com.sleepycat.je.EnvironmentConfig;
+import com.sleepycat.je.ExceptionEvent;
+import com.sleepycat.je.ExceptionListener;
import com.sleepycat.je.LockConflictException;
import com.sleepycat.je.LockMode;
import com.sleepycat.je.OperationStatus;
-import com.sleepycat.je.TransactionConfig;
import java.io.File;
import java.lang.ref.SoftReference;
import java.nio.ByteBuffer;
import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
@@ -44,6 +48,7 @@ import java.util.Random;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicLong;
import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration.ConfigurationException;
import org.apache.log4j.Logger;
import org.apache.qpid.AMQStoreException;
import org.apache.qpid.framing.FieldTable;
@@ -53,28 +58,13 @@ import org.apache.qpid.server.federation.Bridge;
import org.apache.qpid.server.federation.BrokerLink;
import org.apache.qpid.server.message.EnqueableMessage;
import org.apache.qpid.server.queue.AMQQueue;
-import org.apache.qpid.server.store.ConfigurationRecoveryHandler;
+import org.apache.qpid.server.store.*;
import org.apache.qpid.server.store.ConfigurationRecoveryHandler.BindingRecoveryHandler;
+import org.apache.qpid.server.store.ConfigurationRecoveryHandler.BrokerLinkRecoveryHandler;
import org.apache.qpid.server.store.ConfigurationRecoveryHandler.ExchangeRecoveryHandler;
import org.apache.qpid.server.store.ConfigurationRecoveryHandler.QueueRecoveryHandler;
-import org.apache.qpid.server.store.ConfiguredObjectHelper;
-import org.apache.qpid.server.store.DurableConfigurationStore;
-import org.apache.qpid.server.store.Event;
-import org.apache.qpid.server.store.EventListener;
-import org.apache.qpid.server.store.EventManager;
-import org.apache.qpid.server.store.MessageStore;
-import org.apache.qpid.server.store.MessageStoreRecoveryHandler;
import org.apache.qpid.server.store.MessageStoreRecoveryHandler.StoredMessageRecoveryHandler;
-import org.apache.qpid.server.store.State;
-import org.apache.qpid.server.store.StateManager;
-import org.apache.qpid.server.store.StorableMessageMetaData;
-import org.apache.qpid.server.store.StoreFuture;
-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.TransactionLogRecoveryHandler.QueueEntryRecoveryHandler;
-import org.apache.qpid.server.store.TransactionLogResource;
-import org.apache.qpid.server.store.ConfiguredObjectRecord;
import org.apache.qpid.server.store.berkeleydb.entry.PreparedTransaction;
import org.apache.qpid.server.store.berkeleydb.entry.QueueEntryKey;
import org.apache.qpid.server.store.berkeleydb.entry.Xid;
@@ -96,7 +86,10 @@ public abstract class AbstractBDBMessageStore implements MessageStore
public static final int VERSION = 6;
- public static final String ENVIRONMENT_PATH_PROPERTY = "environment-path";
+ private static final Map<String, String> ENVCONFIG_DEFAULTS = Collections.unmodifiableMap(new HashMap<String, String>()
+ {{
+ put(EnvironmentConfig.LOCK_N_LOCK_TABLES, "7");
+ }});
private Environment _environment;
@@ -145,36 +138,44 @@ public abstract class AbstractBDBMessageStore implements MessageStore
protected final StateManager _stateManager;
- protected TransactionConfig _transactionConfig = new TransactionConfig();
-
private MessageStoreRecoveryHandler _messageRecoveryHandler;
private TransactionLogRecoveryHandler _tlogRecoveryHandler;
private ConfigurationRecoveryHandler _configRecoveryHandler;
-
+
+ private long _totalStoreSize;
+ private boolean _limitBusted;
+ private long _persistentSizeLowThreshold;
+ private long _persistentSizeHighThreshold;
+
private final EventManager _eventManager = new EventManager();
private String _storeLocation;
private ConfiguredObjectHelper _configuredObjectHelper = new ConfiguredObjectHelper();
+ private Map<String, String> _envConfigMap;
+
public AbstractBDBMessageStore()
{
_stateManager = new StateManager(_eventManager);
}
+ @Override
+ public void addEventListener(EventListener eventListener, Event... events)
+ {
+ _eventManager.addEventListener(eventListener, events);
+ }
+
public void configureConfigStore(String name,
ConfigurationRecoveryHandler recoveryHandler,
Configuration storeConfiguration) throws Exception
{
- _stateManager.attainState(State.CONFIGURING);
+ _stateManager.attainState(State.INITIALISING);
_configRecoveryHandler = recoveryHandler;
- configure(name,storeConfiguration);
-
-
-
+ configure(name, storeConfiguration);
}
public void configureMessageStore(String name,
@@ -185,12 +186,12 @@ public abstract class AbstractBDBMessageStore implements MessageStore
_messageRecoveryHandler = messageRecoveryHandler;
_tlogRecoveryHandler = tlogRecoveryHandler;
- _stateManager.attainState(State.CONFIGURED);
+ _stateManager.attainState(State.INITIALISED);
}
- public void activate() throws Exception
+ public synchronized void activate() throws Exception
{
- _stateManager.attainState(State.RECOVERING);
+ _stateManager.attainState(State.ACTIVATING);
recoverConfig(_configRecoveryHandler);
recoverMessages(_messageRecoveryHandler);
@@ -204,7 +205,6 @@ public abstract class AbstractBDBMessageStore implements MessageStore
return new BDBTransaction();
}
-
/**
* Called after instantiation in order to configure the message store.
*
@@ -215,9 +215,16 @@ public abstract class AbstractBDBMessageStore implements MessageStore
*/
public void configure(String name, Configuration storeConfig) throws Exception
{
- final String storeLocation = storeConfig.getString(ENVIRONMENT_PATH_PROPERTY,
+ final String storeLocation = storeConfig.getString(MessageStoreConstants.ENVIRONMENT_PATH_PROPERTY,
System.getProperty("QPID_WORK") + File.separator + "bdbstore" + File.separator + name);
+ _persistentSizeHighThreshold = storeConfig.getLong(MessageStoreConstants.OVERFULL_SIZE_PROPERTY, Long.MAX_VALUE);
+ _persistentSizeLowThreshold = storeConfig.getLong(MessageStoreConstants.UNDERFULL_SIZE_PROPERTY, _persistentSizeHighThreshold);
+ if(_persistentSizeLowThreshold > _persistentSizeHighThreshold || _persistentSizeLowThreshold < 0l)
+ {
+ _persistentSizeLowThreshold = _persistentSizeHighThreshold;
+ }
+
File environmentPath = new File(storeLocation);
if (!environmentPath.exists())
{
@@ -230,11 +237,39 @@ public abstract class AbstractBDBMessageStore implements MessageStore
_storeLocation = storeLocation;
+ _envConfigMap = getConfigMap(ENVCONFIG_DEFAULTS, storeConfig, "envConfig");
+
LOGGER.info("Configuring BDB message store");
setupStore(environmentPath, name);
}
+ protected Map<String,String> getConfigMap(Map<String, String> defaultConfig, Configuration config, String prefix) throws ConfigurationException
+ {
+ final List<Object> argumentNames = config.getList(prefix + ".name");
+ final List<Object> argumentValues = config.getList(prefix + ".value");
+ final int initialSize = argumentNames.size() + defaultConfig.size();
+
+ final Map<String,String> attributes = new HashMap<String,String>(initialSize);
+ attributes.putAll(defaultConfig);
+
+ for (int i = 0; i < argumentNames.size(); i++)
+ {
+ final String argName = argumentNames.get(i).toString();
+ final String argValue = argumentValues.get(i).toString();
+
+ attributes.put(argName, argValue);
+ }
+
+ return Collections.unmodifiableMap(attributes);
+ }
+
+ @Override
+ public String getStoreLocation()
+ {
+ return _storeLocation;
+ }
+
/**
* Move the store state from INITIAL to ACTIVE without actually recovering.
*
@@ -244,9 +279,9 @@ public abstract class AbstractBDBMessageStore implements MessageStore
*/
void startWithNoRecover() throws AMQStoreException
{
- _stateManager.attainState(State.CONFIGURING);
- _stateManager.attainState(State.CONFIGURED);
- _stateManager.attainState(State.RECOVERING);
+ _stateManager.attainState(State.INITIALISING);
+ _stateManager.attainState(State.INITIALISED);
+ _stateManager.attainState(State.ACTIVATING);
_stateManager.attainState(State.ACTIVE);
}
@@ -257,54 +292,12 @@ public abstract class AbstractBDBMessageStore implements MessageStore
new Upgrader(_environment, name).upgradeIfNecessary();
openDatabases();
- }
-
- protected Environment createEnvironment(File environmentPath) throws DatabaseException
- {
- LOGGER.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");
-
- // 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(false);
- try
- {
- return new Environment(environmentPath, envConfig);
- }
- 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();
- }
- return new Environment(environmentPath, envConfig);
- }
- else
- {
- throw de;
- }
- }
+ _totalStoreSize = getSizeOnDisk();
}
+ protected abstract Environment createEnvironment(File environmentPath) throws DatabaseException;
+
public Environment getEnvironment()
{
return _environment;
@@ -343,14 +336,9 @@ public abstract class AbstractBDBMessageStore implements MessageStore
*/
public void close() throws Exception
{
- if (_stateManager.isInState(State.ACTIVE) || _stateManager.isInState(State.QUIESCED))
- {
- _stateManager.stateTransition(State.ACTIVE, State.CLOSING);
-
- closeInternal();
-
- _stateManager.stateTransition(State.CLOSING, State.CLOSED);
- }
+ _stateManager.attainState(State.CLOSING);
+ closeInternal();
+ _stateManager.attainState(State.CLOSED);
}
protected void closeInternal() throws Exception
@@ -409,8 +397,14 @@ public abstract class AbstractBDBMessageStore implements MessageStore
// 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();
+ try
+ {
+ _environment.cleanLog();
+ }
+ finally
+ {
+ _environment.close();
+ }
}
}
@@ -420,16 +414,16 @@ public abstract class AbstractBDBMessageStore implements MessageStore
try
{
List<ConfiguredObjectRecord> configuredObjects = loadConfiguredObjects();
- QueueRecoveryHandler qrh = recoveryHandler.begin(this);
- _configuredObjectHelper.recoverQueues(qrh, configuredObjects);
-
- ExchangeRecoveryHandler erh = qrh.completeQueueRecovery();
+ ExchangeRecoveryHandler erh = recoveryHandler.begin(this);
_configuredObjectHelper.recoverExchanges(erh, configuredObjects);
- BindingRecoveryHandler brh = erh.completeExchangeRecovery();
+ QueueRecoveryHandler qrh = erh.completeExchangeRecovery();
+ _configuredObjectHelper.recoverQueues(qrh, configuredObjects);
+
+ BindingRecoveryHandler brh = qrh.completeQueueRecovery();
_configuredObjectHelper.recoverBindings(brh, configuredObjects);
- ConfigurationRecoveryHandler.BrokerLinkRecoveryHandler lrh = brh.completeBindingRecovery();
+ BrokerLinkRecoveryHandler lrh = brh.completeBindingRecovery();
recoverBrokerLinks(lrh);
}
catch (DatabaseException e)
@@ -552,7 +546,8 @@ public abstract class AbstractBDBMessageStore implements MessageStore
long messageId = LongBinding.entryToLong(key);
StorableMessageMetaData metaData = valueBinding.entryToObject(value);
- StoredBDBMessage message = new StoredBDBMessage(messageId, metaData, false);
+ StoredBDBMessage message = new StoredBDBMessage(messageId, metaData, true);
+
mrh.message(message);
maxId = Math.max(maxId, messageId);
@@ -950,10 +945,10 @@ public abstract class AbstractBDBMessageStore implements MessageStore
if (_stateManager.isInState(State.ACTIVE))
{
DatabaseEntry key = new DatabaseEntry();
- UUIDTupleBinding.getInstance().objectToEntry(link.getId(), key);
+ UUIDTupleBinding.getInstance().objectToEntry(link.getQMFId(), key);
DatabaseEntry value = new DatabaseEntry();
- LongBinding.longToEntry(link.getCreateTime(),value);
+ LongBinding.longToEntry(link.getCreateTime(), value);
StringMapBinding.getInstance().objectToEntry(link.getArguments(), value);
try
@@ -971,7 +966,7 @@ public abstract class AbstractBDBMessageStore implements MessageStore
public void deleteBrokerLink(final BrokerLink link) throws AMQStoreException
{
DatabaseEntry key = new DatabaseEntry();
- UUIDTupleBinding.getInstance().objectToEntry(link.getId(), key);
+ UUIDTupleBinding.getInstance().objectToEntry(link.getQMFId(), key);
try
{
OperationStatus status = _linkDb.delete(null, key);
@@ -991,10 +986,10 @@ public abstract class AbstractBDBMessageStore implements MessageStore
if (_stateManager.isInState(State.ACTIVE))
{
DatabaseEntry key = new DatabaseEntry();
- UUIDTupleBinding.getInstance().objectToEntry(bridge.getId(), key);
+ UUIDTupleBinding.getInstance().objectToEntry(bridge.getQMFId(), key);
DatabaseEntry value = new DatabaseEntry();
- UUIDTupleBinding.getInstance().objectToEntry(bridge.getLink().getId(),value);
+ UUIDTupleBinding.getInstance().objectToEntry(bridge.getLink().getQMFId(),value);
LongBinding.longToEntry(bridge.getCreateTime(),value);
StringMapBinding.getInstance().objectToEntry(bridge.getArguments(), value);
@@ -1014,7 +1009,7 @@ public abstract class AbstractBDBMessageStore implements MessageStore
public void deleteBridge(final Bridge bridge) throws AMQStoreException
{
DatabaseEntry key = new DatabaseEntry();
- UUIDTupleBinding.getInstance().objectToEntry(bridge.getId(), key);
+ UUIDTupleBinding.getInstance().objectToEntry(bridge.getQMFId(), key);
try
{
OperationStatus status = _bridgeDb.delete(null, key);
@@ -1247,7 +1242,7 @@ public abstract class AbstractBDBMessageStore implements MessageStore
/**
* Primarily for testing purposes.
*
- * @param queueName
+ * @param queueId
*
* @return a list of message ids for messages enqueued for a particular queue
*/
@@ -1494,6 +1489,7 @@ public abstract class AbstractBDBMessageStore implements MessageStore
return true;
}
+ @SuppressWarnings("unchecked")
public <T extends StorableMessageMetaData> StoredMessage<T> addMessage(T metaData)
{
if(metaData.isPersistent())
@@ -1580,34 +1576,29 @@ public abstract class AbstractBDBMessageStore implements MessageStore
{
private final long _messageId;
- private volatile SoftReference<StorableMessageMetaData> _metaDataRef;
+ private final boolean _isRecovered;
private StorableMessageMetaData _metaData;
- private volatile SoftReference<byte[]> _dataRef;
+ private volatile SoftReference<StorableMessageMetaData> _metaDataRef;
+
private byte[] _data;
+ private volatile SoftReference<byte[]> _dataRef;
StoredBDBMessage(long messageId, StorableMessageMetaData metaData)
{
- this(messageId, metaData, true);
+ this(messageId, metaData, false);
}
-
- StoredBDBMessage(long messageId,
- StorableMessageMetaData metaData, boolean persist)
+ StoredBDBMessage(long messageId, StorableMessageMetaData metaData, boolean isRecovered)
{
- try
- {
- _messageId = messageId;
- _metaData = metaData;
+ _messageId = messageId;
+ _isRecovered = isRecovered;
- _metaDataRef = new SoftReference<StorableMessageMetaData>(metaData);
-
- }
- catch (DatabaseException e)
+ if(!_isRecovered)
{
- throw new RuntimeException(e);
+ _metaData = metaData;
}
-
+ _metaDataRef = new SoftReference<StorableMessageMetaData>(metaData);
}
public StorableMessageMetaData getMetaData()
@@ -1697,8 +1688,7 @@ public abstract class AbstractBDBMessageStore implements MessageStore
synchronized void store(com.sleepycat.je.Transaction txn)
{
-
- if(_metaData != null)
+ if (!stored())
{
try
{
@@ -1730,12 +1720,12 @@ public abstract class AbstractBDBMessageStore implements MessageStore
public synchronized StoreFuture flushToStore()
{
- if(_metaData != null)
+ if(!stored())
{
com.sleepycat.je.Transaction txn = _environment.beginTransaction(null, null);
store(txn);
AbstractBDBMessageStore.this.commit(txn,true);
-
+ storedSizeChange(getMetaData().getContentSize());
}
return StoreFuture.IMMEDIATE_FUTURE;
}
@@ -1744,18 +1734,27 @@ public abstract class AbstractBDBMessageStore implements MessageStore
{
try
{
+ int delta = getMetaData().getContentSize();
AbstractBDBMessageStore.this.removeMessage(_messageId, false);
+ storedSizeChange(-delta);
+
}
catch (AMQStoreException e)
{
throw new RuntimeException(e);
}
}
+
+ private boolean stored()
+ {
+ return _metaData == null || _isRecovered;
+ }
}
private class BDBTransaction implements org.apache.qpid.server.store.Transaction
{
private com.sleepycat.je.Transaction _txn;
+ private int _storeSizeIncrease;
private BDBTransaction()
{
@@ -1765,7 +1764,10 @@ public abstract class AbstractBDBMessageStore implements MessageStore
}
catch (DatabaseException e)
{
- throw new RuntimeException(e);
+ LOGGER.error("Exception during transaction begin, closing store environment.", e);
+ closeEnvironmentSafely();
+
+ throw new RuntimeException("Exception during transaction begin, store environment closed.", e);
}
}
@@ -1773,7 +1775,9 @@ public abstract class AbstractBDBMessageStore implements MessageStore
{
if(message.getStoredMessage() instanceof StoredBDBMessage)
{
- ((StoredBDBMessage)message.getStoredMessage()).store(_txn);
+ final StoredBDBMessage storedMessage = (StoredBDBMessage) message.getStoredMessage();
+ storedMessage.store(_txn);
+ _storeSizeIncrease += storedMessage.getMetaData().getContentSize();
}
AbstractBDBMessageStore.this.enqueueMessage(_txn, queue, message.getMessageNumber());
@@ -1787,10 +1791,12 @@ public abstract class AbstractBDBMessageStore implements MessageStore
public void commitTran() throws AMQStoreException
{
AbstractBDBMessageStore.this.commitTranImpl(_txn, true);
+ AbstractBDBMessageStore.this.storedSizeChange(_storeSizeIncrease);
}
public StoreFuture commitTranAsync() throws AMQStoreException
{
+ AbstractBDBMessageStore.this.storedSizeChange(_storeSizeIncrease);
return AbstractBDBMessageStore.this.commitTranImpl(_txn, false);
}
@@ -1811,15 +1817,133 @@ public abstract class AbstractBDBMessageStore implements MessageStore
}
}
- @Override
- public void addEventListener(EventListener eventListener, Event... events)
+ private void storedSizeChange(final int delta)
{
- _eventManager.addEventListener(eventListener, events);
+ if(getPersistentSizeHighThreshold() > 0)
+ {
+ synchronized (this)
+ {
+ // the delta supplied is an approximation of a store size change. we don;t want to check the statistic every
+ // time, so we do so only when there's been enough change that it is worth looking again. We do this by
+ // assuming the total size will change by less than twice the amount of the message data change.
+ long newSize = _totalStoreSize += 2*delta;
+
+ if(!_limitBusted && newSize > getPersistentSizeHighThreshold())
+ {
+ _totalStoreSize = getSizeOnDisk();
+
+ if(_totalStoreSize > getPersistentSizeHighThreshold())
+ {
+ _limitBusted = true;
+ _eventManager.notifyEvent(Event.PERSISTENT_MESSAGE_SIZE_OVERFULL);
+ }
+ }
+ else if(_limitBusted && newSize < getPersistentSizeLowThreshold())
+ {
+ long oldSize = _totalStoreSize;
+ _totalStoreSize = getSizeOnDisk();
+
+ if(oldSize <= _totalStoreSize)
+ {
+
+ reduceSizeOnDisk();
+
+ _totalStoreSize = getSizeOnDisk();
+
+ }
+
+ if(_totalStoreSize < getPersistentSizeLowThreshold())
+ {
+ _limitBusted = false;
+ _eventManager.notifyEvent(Event.PERSISTENT_MESSAGE_SIZE_UNDERFULL);
+ }
+
+
+ }
+ }
+ }
}
- @Override
- public String getStoreLocation()
+ private void reduceSizeOnDisk()
{
- return _storeLocation;
+ _environment.getConfig().setConfigParam(EnvironmentConfig.ENV_RUN_CLEANER, "false");
+ boolean cleaned = false;
+ while (_environment.cleanLog() > 0)
+ {
+ cleaned = true;
+ }
+ if (cleaned)
+ {
+ CheckpointConfig force = new CheckpointConfig();
+ force.setForce(true);
+ _environment.checkpoint(force);
+ }
+
+
+ _environment.getConfig().setConfigParam(EnvironmentConfig.ENV_RUN_CLEANER, "true");
+ }
+
+ private long getSizeOnDisk()
+ {
+ return _environment.getStats(null).getTotalLogSize();
+ }
+
+ private long getPersistentSizeLowThreshold()
+ {
+ return _persistentSizeLowThreshold;
+ }
+
+ private long getPersistentSizeHighThreshold()
+ {
+ return _persistentSizeHighThreshold;
+ }
+
+ private void setEnvironmentConfigProperties(EnvironmentConfig envConfig)
+ {
+ for (Map.Entry<String, String> configItem : _envConfigMap.entrySet())
+ {
+ LOGGER.debug("Setting EnvironmentConfig key " + configItem.getKey() + " to '" + configItem.getValue() + "'");
+ envConfig.setConfigParam(configItem.getKey(), configItem.getValue());
+ }
+ }
+
+ protected EnvironmentConfig createEnvironmentConfig()
+ {
+ EnvironmentConfig envConfig = new EnvironmentConfig();
+ envConfig.setAllowCreate(true);
+ envConfig.setTransactional(true);
+
+ setEnvironmentConfigProperties(envConfig);
+
+ envConfig.setExceptionListener(new LoggingAsyncExceptionListener());
+
+ return envConfig;
+ }
+
+ protected void closeEnvironmentSafely()
+ {
+ try
+ {
+ _environment.close();
+ }
+ catch (DatabaseException ex)
+ {
+ LOGGER.error("Exception closing store environment", ex);
+ }
+ catch (IllegalStateException ex)
+ {
+ LOGGER.error("Exception closing store environment", ex);
+ }
+ }
+
+
+ private class LoggingAsyncExceptionListener implements ExceptionListener
+ {
+ @Override
+ public void exceptionThrown(ExceptionEvent event)
+ {
+ LOGGER.error("Asynchronous exception thrown by BDB thread '"
+ + event.getThreadName() + "'", event.getException());
+ }
}
}
diff --git a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBHAMessageStore.java b/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBHAMessageStore.java
new file mode 100644
index 0000000000..c40f24dbc3
--- /dev/null
+++ b/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBHAMessageStore.java
@@ -0,0 +1,607 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.net.InetSocketAddress;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.Callable;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+
+import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration.ConfigurationException;
+import org.apache.log4j.Logger;
+import org.apache.qpid.AMQStoreException;
+import org.apache.qpid.server.logging.RootMessageLogger;
+import org.apache.qpid.server.logging.actors.AbstractActor;
+import org.apache.qpid.server.logging.actors.CurrentActor;
+import org.apache.qpid.server.store.HAMessageStore;
+import org.apache.qpid.server.store.MessageStore;
+import org.apache.qpid.server.store.MessageStoreRecoveryHandler;
+import org.apache.qpid.server.store.State;
+import org.apache.qpid.server.store.StoreFuture;
+import org.apache.qpid.server.store.TransactionLogRecoveryHandler;
+
+import com.sleepycat.je.DatabaseException;
+import com.sleepycat.je.Durability;
+import com.sleepycat.je.Durability.ReplicaAckPolicy;
+import com.sleepycat.je.Durability.SyncPolicy;
+import com.sleepycat.je.Environment;
+import com.sleepycat.je.EnvironmentConfig;
+import com.sleepycat.je.OperationFailureException;
+import com.sleepycat.je.Transaction;
+import com.sleepycat.je.rep.InsufficientLogException;
+import com.sleepycat.je.rep.NetworkRestore;
+import com.sleepycat.je.rep.NetworkRestoreConfig;
+import com.sleepycat.je.rep.ReplicatedEnvironment;
+import com.sleepycat.je.rep.ReplicationConfig;
+import com.sleepycat.je.rep.ReplicationMutableConfig;
+import com.sleepycat.je.rep.ReplicationNode;
+import com.sleepycat.je.rep.StateChangeEvent;
+import com.sleepycat.je.rep.StateChangeListener;
+import com.sleepycat.je.rep.util.ReplicationGroupAdmin;
+
+public class BDBHAMessageStore extends AbstractBDBMessageStore implements HAMessageStore
+{
+ private static final Logger LOGGER = Logger.getLogger(BDBHAMessageStore.class);
+
+ private static final Durability DEFAULT_DURABILITY = new Durability(SyncPolicy.NO_SYNC, SyncPolicy.NO_SYNC, ReplicaAckPolicy.SIMPLE_MAJORITY);
+
+ public static final String GRP_MEM_COL_NODE_HOST_PORT = "NodeHostPort";
+ public static final String GRP_MEM_COL_NODE_NAME = "NodeName";
+
+ @SuppressWarnings("serial")
+ private static final Map<String, String> REPCONFIG_DEFAULTS = Collections.unmodifiableMap(new HashMap<String, String>()
+ {{
+ /**
+ * Parameter decreased as the 24h default may lead very large log files for most users.
+ */
+ put(ReplicationConfig.REP_STREAM_TIMEOUT, "1 h");
+ /**
+ * Parameter increased as the 5 s default may lead to spurious timeouts.
+ */
+ put(ReplicationConfig.REPLICA_ACK_TIMEOUT, "15 s");
+ /**
+ * Parameter increased as the 10 s default may lead to spurious timeouts.
+ */
+ put(ReplicationConfig.INSUFFICIENT_REPLICAS_TIMEOUT, "20 s");
+ /**
+ * Parameter increased as the 10 h default may cause user confusion.
+ */
+ put(ReplicationConfig.ENV_SETUP_TIMEOUT, "15 min");
+ /**
+ * Parameter changed from default true so we adopt immediately adopt the new behaviour early. False
+ * is scheduled to become default after JE 5.0.48.
+ */
+ put(ReplicationConfig.PROTOCOL_OLD_STRING_ENCODING, Boolean.FALSE.toString());
+ /**
+ * Parameter decreased as a default 5min interval may lead to bigger data losses on Node
+ * with NO_SYN durability in case if such Node crushes.
+ */
+ put(ReplicationConfig.LOG_FLUSH_TASK_INTERVAL, "1 min");
+ }});
+
+ public static final String BDB_HA_STORE_TYPE = "BDB-HA";
+
+ private String _groupName;
+ private String _nodeName;
+ private String _nodeHostPort;
+ private String _helperHostPort;
+ private Durability _durability;
+
+ private String _name;
+
+ private CommitThreadWrapper _commitThreadWrapper;
+ private boolean _coalescingSync;
+ private boolean _designatedPrimary;
+ private Map<String, String> _repConfig;
+
+ @Override
+ public void configure(String name, Configuration storeConfig) throws Exception
+ {
+ //Mandatory configuration
+ _groupName = getValidatedPropertyFromConfig("highAvailability.groupName", storeConfig);
+ _nodeName = getValidatedPropertyFromConfig("highAvailability.nodeName", storeConfig);
+ _nodeHostPort = getValidatedPropertyFromConfig("highAvailability.nodeHostPort", storeConfig);
+ _helperHostPort = getValidatedPropertyFromConfig("highAvailability.helperHostPort", storeConfig);
+ _name = name;
+
+ //Optional configuration
+ String durabilitySetting = storeConfig.getString("highAvailability.durability");
+ if (durabilitySetting == null)
+ {
+ _durability = DEFAULT_DURABILITY;
+ }
+ else
+ {
+ _durability = Durability.parse(durabilitySetting);
+ }
+ _designatedPrimary = storeConfig.getBoolean("highAvailability.designatedPrimary", Boolean.FALSE);
+ _coalescingSync = storeConfig.getBoolean("highAvailability.coalescingSync", Boolean.TRUE);
+ _repConfig = getConfigMap(REPCONFIG_DEFAULTS, storeConfig, "repConfig");
+
+ if (_coalescingSync && _durability.getLocalSync() == SyncPolicy.SYNC)
+ {
+ throw new ConfigurationException("Coalescing sync cannot be used with master sync policy " + SyncPolicy.SYNC
+ + "! Please set highAvailability.coalescingSync to false in store configuration.");
+ }
+
+ super.configure(name, storeConfig);
+ }
+
+ @Override
+ protected void setupStore(File storePath, String name) throws DatabaseException, AMQStoreException
+ {
+ super.setupStore(storePath, name);
+
+ if(_coalescingSync)
+ {
+ _commitThreadWrapper = new CommitThreadWrapper("Commit-Thread-" + name, getEnvironment());
+ _commitThreadWrapper.startCommitThread();
+ }
+ }
+
+ @Override
+ protected Environment createEnvironment(File environmentPath) throws DatabaseException
+ {
+ if (LOGGER.isInfoEnabled())
+ {
+ LOGGER.info("Environment path " + environmentPath.getAbsolutePath());
+ LOGGER.info("Group name " + _groupName);
+ LOGGER.info("Node name " + _nodeName);
+ LOGGER.info("Node host port " + _nodeHostPort);
+ LOGGER.info("Helper host port " + _helperHostPort);
+ LOGGER.info("Durability " + _durability);
+ LOGGER.info("Coalescing sync " + _coalescingSync);
+ LOGGER.info("Designated primary (applicable to 2 node case only) " + _designatedPrimary);
+ }
+
+ final ReplicationConfig replicationConfig = new ReplicationConfig(_groupName, _nodeName, _nodeHostPort);
+
+ replicationConfig.setHelperHosts(_helperHostPort);
+ replicationConfig.setDesignatedPrimary(_designatedPrimary);
+ setReplicationConfigProperties(replicationConfig);
+
+ final EnvironmentConfig envConfig = createEnvironmentConfig();
+ envConfig.setDurability(_durability);
+
+ ReplicatedEnvironment replicatedEnvironment = null;
+ try
+ {
+ replicatedEnvironment = new ReplicatedEnvironment(environmentPath, replicationConfig, envConfig);
+ }
+ catch (final InsufficientLogException ile)
+ {
+ LOGGER.info("InsufficientLogException thrown and so full network restore required", ile);
+ NetworkRestore restore = new NetworkRestore();
+ NetworkRestoreConfig config = new NetworkRestoreConfig();
+ config.setRetainLogFiles(false);
+ restore.execute(ile, config);
+ replicatedEnvironment = new ReplicatedEnvironment(environmentPath, replicationConfig, envConfig);
+ }
+
+ return replicatedEnvironment;
+ }
+
+ @Override
+ public void configureMessageStore(String name, MessageStoreRecoveryHandler messageRecoveryHandler,
+ TransactionLogRecoveryHandler tlogRecoveryHandler,
+ Configuration config) throws Exception
+ {
+ super.configureMessageStore(name, messageRecoveryHandler, tlogRecoveryHandler, config);
+
+ final ReplicatedEnvironment replicatedEnvironment = getReplicatedEnvironment();
+
+ replicatedEnvironment.setStateChangeListener(new BDBHAMessageStoreStateChangeListener());
+ }
+
+ @Override
+ public synchronized void activate() throws Exception
+ {
+ // Before proceeding, perform a log flush with an fsync
+ getEnvironment().flushLog(true);
+
+ super.activate();
+ }
+
+ @Override
+ public synchronized void passivate()
+ {
+ if (_stateManager.isNotInState(State.INITIALISED))
+ {
+ LOGGER.debug("Store becoming passive");
+ _stateManager.attainState(State.INITIALISED);
+ }
+ }
+
+ public String getName()
+ {
+ return _name;
+ }
+
+ public String getGroupName()
+ {
+ return _groupName;
+ }
+
+ public String getNodeName()
+ {
+ return _nodeName;
+ }
+
+ public String getNodeHostPort()
+ {
+ return _nodeHostPort;
+ }
+
+ public String getHelperHostPort()
+ {
+ return _helperHostPort;
+ }
+
+ public String getDurability()
+ {
+ return _durability.toString();
+ }
+
+ public boolean isCoalescingSync()
+ {
+ return _coalescingSync;
+ }
+
+ public String getNodeState()
+ {
+ ReplicatedEnvironment.State state = getReplicatedEnvironment().getState();
+ return state.toString();
+ }
+
+ public Boolean isDesignatedPrimary()
+ {
+ return getReplicatedEnvironment().getRepMutableConfig().getDesignatedPrimary();
+ }
+
+ public List<Map<String, String>> getGroupMembers()
+ {
+ List<Map<String, String>> members = new ArrayList<Map<String,String>>();
+
+ for (ReplicationNode node : getReplicatedEnvironment().getGroup().getNodes())
+ {
+ Map<String, String> nodeMap = new HashMap<String, String>();
+ nodeMap.put(BDBHAMessageStore.GRP_MEM_COL_NODE_NAME, node.getName());
+ nodeMap.put(BDBHAMessageStore.GRP_MEM_COL_NODE_HOST_PORT, node.getHostName() + ":" + node.getPort());
+ members.add(nodeMap);
+ }
+
+ return members;
+ }
+
+ public void removeNodeFromGroup(String nodeName) throws AMQStoreException
+ {
+ try
+ {
+ createReplicationGroupAdmin().removeMember(nodeName);
+ }
+ catch (OperationFailureException ofe)
+ {
+ throw new AMQStoreException("Failed to remove '" + nodeName + "' from group. " + ofe.getMessage(), ofe);
+ }
+ catch (DatabaseException e)
+ {
+ throw new AMQStoreException("Failed to remove '" + nodeName + "' from group. " + e.getMessage(), e);
+ }
+ }
+
+ public void setDesignatedPrimary(boolean isPrimary) throws AMQStoreException
+ {
+ try
+ {
+ final ReplicatedEnvironment replicatedEnvironment = getReplicatedEnvironment();
+ synchronized(replicatedEnvironment)
+ {
+ final ReplicationMutableConfig oldConfig = replicatedEnvironment.getRepMutableConfig();
+ final ReplicationMutableConfig newConfig = oldConfig.setDesignatedPrimary(isPrimary);
+ replicatedEnvironment.setRepMutableConfig(newConfig);
+ }
+
+ if (LOGGER.isInfoEnabled())
+ {
+ LOGGER.info("Node " + _nodeName + " successfully set as designated primary for group");
+ }
+ }
+ catch (DatabaseException e)
+ {
+ throw new AMQStoreException("Failed to set '" + _nodeName + "' as designated primary for group. " + e.getMessage(), e);
+ }
+ }
+
+ ReplicatedEnvironment getReplicatedEnvironment()
+ {
+ return (ReplicatedEnvironment)getEnvironment();
+ }
+
+ public void updateAddress(String nodeName, String newHostName, int newPort) throws AMQStoreException
+ {
+ try
+ {
+ createReplicationGroupAdmin().updateAddress(nodeName, newHostName, newPort);
+ }
+ catch (OperationFailureException ofe)
+ {
+ throw new AMQStoreException("Failed to update address for '" + nodeName +
+ "' with new host " + newHostName + " and new port " + newPort + ". " + ofe.getMessage(), ofe);
+ }
+ catch (DatabaseException e)
+ {
+ throw new AMQStoreException("Failed to update address for '" + nodeName +
+ "' with new host " + newHostName + " and new port " + newPort + ". " + e.getMessage(), e);
+ }
+ }
+
+ @Override
+ protected StoreFuture commit(Transaction tx, boolean syncCommit) throws DatabaseException
+ {
+ // Using commit() instead of commitNoSync() for the HA store to allow
+ // the HA durability configuration to influence resulting behaviour.
+ try
+ {
+ tx.commit();
+ }
+ catch (DatabaseException de)
+ {
+ LOGGER.error("Got DatabaseException on commit, closing environment", de);
+
+ closeEnvironmentSafely();
+
+ throw de;
+ }
+
+ if(_coalescingSync)
+ {
+ return _commitThreadWrapper.commit(tx, syncCommit);
+ }
+ else
+ {
+ return StoreFuture.IMMEDIATE_FUTURE;
+ }
+ }
+
+ @Override
+ protected void closeInternal() throws Exception
+ {
+ substituteNoOpStateChangeListenerOn(getReplicatedEnvironment());
+
+ try
+ {
+ if(_coalescingSync)
+ {
+ _commitThreadWrapper.stopCommitThread();
+ }
+ }
+ finally
+ {
+ super.closeInternal();
+ }
+ }
+
+ /**
+ * Replicas emit a state change event {@link com.sleepycat.je.rep.ReplicatedEnvironment.State#DETACHED} during
+ * {@link Environment#close()}. We replace the StateChangeListener so we silently ignore this state change.
+ */
+ private void substituteNoOpStateChangeListenerOn(ReplicatedEnvironment replicatedEnvironment)
+ {
+ LOGGER.debug("Substituting no-op state change listener for environment close");
+ replicatedEnvironment.setStateChangeListener(new NoOpStateChangeListener());
+ }
+
+ private ReplicationGroupAdmin createReplicationGroupAdmin()
+ {
+ final Set<InetSocketAddress> helpers = new HashSet<InetSocketAddress>();
+ helpers.addAll(getReplicatedEnvironment().getRepConfig().getHelperSockets());
+
+ final ReplicationConfig repConfig = getReplicatedEnvironment().getRepConfig();
+ helpers.add(InetSocketAddress.createUnresolved(repConfig.getNodeHostname(), repConfig.getNodePort()));
+
+ return new ReplicationGroupAdmin(_groupName, helpers);
+ }
+
+
+ private void setReplicationConfigProperties(ReplicationConfig replicationConfig)
+ {
+ for (Map.Entry<String, String> configItem : _repConfig.entrySet())
+ {
+ if (LOGGER.isDebugEnabled())
+ {
+ LOGGER.debug("Setting ReplicationConfig key " + configItem.getKey() + " to '" + configItem.getValue() + "'");
+ }
+ replicationConfig.setConfigParam(configItem.getKey(), configItem.getValue());
+ }
+ }
+
+ private String getValidatedPropertyFromConfig(String key, Configuration config) throws ConfigurationException
+ {
+ if (!config.containsKey(key))
+ {
+ throw new ConfigurationException("BDB HA configuration key not found. Please specify configuration key with XPath: "
+ + key.replace('.', '/'));
+ }
+ return config.getString(key);
+ }
+
+ private class BDBHAMessageStoreStateChangeListener implements StateChangeListener
+ {
+ private final Executor _executor = Executors.newSingleThreadExecutor();
+
+ @Override
+ public void stateChange(StateChangeEvent stateChangeEvent) throws RuntimeException
+ {
+ com.sleepycat.je.rep.ReplicatedEnvironment.State state = stateChangeEvent.getState();
+
+ if (LOGGER.isInfoEnabled())
+ {
+ LOGGER.info("Received BDB event indicating transition to state " + state);
+ }
+
+ switch (state)
+ {
+ case MASTER:
+ activateStoreAsync();
+ break;
+ case REPLICA:
+ passivateStoreAsync();
+ break;
+ case DETACHED:
+ LOGGER.error("BDB replicated node in detached state, therefore passivating.");
+ passivateStoreAsync();
+ break;
+ case UNKNOWN:
+ LOGGER.warn("BDB replicated node in unknown state (hopefully temporarily)");
+ break;
+ default:
+ LOGGER.error("Unexpected state change: " + state);
+ throw new IllegalStateException("Unexpected state change: " + state);
+ }
+ }
+
+ /**
+ * Calls {@link MessageStore#activate()}.
+ *
+ * <p/>
+ *
+ * This is done a background thread, in line with
+ * {@link StateChangeListener#stateChange(StateChangeEvent)}'s JavaDoc, because
+ * activate may execute transactions, which can't complete until
+ * {@link StateChangeListener#stateChange(StateChangeEvent)} has returned.
+ */
+ private void activateStoreAsync()
+ {
+ String threadName = "BDBHANodeActivationThread-" + _name;
+ executeStateChangeAsync(new Callable<Void>()
+ {
+ @Override
+ public Void call() throws Exception
+ {
+ try
+ {
+ activate();
+ }
+ catch (Exception e)
+ {
+ LOGGER.error("Failed to activate on hearing MASTER change event",e);
+ throw e;
+ }
+ return null;
+ }
+ }, threadName);
+ }
+
+ /**
+ * Calls {@link #passivate()}.
+ *
+ * <p/>
+ * This is done a background thread, in line with
+ * {@link StateChangeListener#stateChange(StateChangeEvent)}'s JavaDoc, because
+ * passivation due to the effect of state change listeners.
+ */
+ private void passivateStoreAsync()
+ {
+ String threadName = "BDBHANodePassivationThread-" + _name;
+ executeStateChangeAsync(new Callable<Void>()
+ {
+
+ @Override
+ public Void call() throws Exception
+ {
+ try
+ {
+ passivate();
+ }
+ catch (Exception e)
+ {
+ LOGGER.error("Failed to passivate on hearing REPLICA or DETACHED change event",e);
+ throw e;
+ }
+ return null;
+ }
+ }, threadName);
+ }
+
+ private void executeStateChangeAsync(final Callable<Void> callable, final String threadName)
+ {
+ final RootMessageLogger _rootLogger = CurrentActor.get().getRootMessageLogger();
+
+ _executor.execute(new Runnable()
+ {
+
+ @Override
+ public void run()
+ {
+ final String originalThreadName = Thread.currentThread().getName();
+ Thread.currentThread().setName(threadName);
+ try
+ {
+ CurrentActor.set(new AbstractActor(_rootLogger)
+ {
+ @Override
+ public String getLogMessage()
+ {
+ return threadName;
+ }
+ });
+
+ try
+ {
+ callable.call();
+ }
+ catch (Exception e)
+ {
+ LOGGER.error("Exception during state change", e);
+ }
+ }
+ finally
+ {
+ Thread.currentThread().setName(originalThreadName);
+ }
+ }
+ });
+ }
+ }
+
+ private class NoOpStateChangeListener implements StateChangeListener
+ {
+ @Override
+ public void stateChange(StateChangeEvent stateChangeEvent)
+ throws RuntimeException
+ {
+ }
+ }
+
+ @Override
+ public String getStoreType()
+ {
+ return BDB_HA_STORE_TYPE;
+ }
+}
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
index 9f7eb4bfd9..82bc3d8564 100644
--- 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
@@ -21,16 +21,12 @@
package org.apache.qpid.server.store.berkeleydb;
import java.io.File;
-import java.util.Queue;
-import java.util.concurrent.ConcurrentLinkedQueue;
-import java.util.concurrent.atomic.AtomicBoolean;
import org.apache.log4j.Logger;
import org.apache.qpid.AMQStoreException;
import org.apache.qpid.server.store.MessageStore;
import org.apache.qpid.server.store.StoreFuture;
-import com.sleepycat.je.CheckpointConfig;
import com.sleepycat.je.DatabaseException;
import com.sleepycat.je.Environment;
import com.sleepycat.je.EnvironmentConfig;
@@ -46,39 +42,23 @@ import com.sleepycat.je.EnvironmentConfig;
public class BDBMessageStore extends AbstractBDBMessageStore
{
private static final Logger LOGGER = Logger.getLogger(BDBMessageStore.class);
-
- private final CommitThread _commitThread = new CommitThread("Commit-Thread");
+ private static final String BDB_STORE_TYPE = "BDB";
+ private CommitThreadWrapper _commitThreadWrapper;
@Override
protected void setupStore(File storePath, String name) throws DatabaseException, AMQStoreException
{
super.setupStore(storePath, name);
- startCommitThread();
+ _commitThreadWrapper = new CommitThreadWrapper("Commit-Thread-" + name, getEnvironment());
+ _commitThreadWrapper.startCommitThread();
}
protected Environment createEnvironment(File environmentPath) throws DatabaseException
{
LOGGER.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");
-
- // 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);
+ EnvironmentConfig envConfig = createEnvironmentConfig();
- //This prevents background threads running which will potentially update the store.
- envConfig.setReadOnly(false);
try
{
return new Environment(environmentPath, envConfig);
@@ -98,12 +78,10 @@ public class BDBMessageStore extends AbstractBDBMessageStore
}
}
-
-
@Override
protected void closeInternal() throws Exception
{
- stopCommitThread();
+ _commitThreadWrapper.stopCommitThread();
super.closeInternal();
}
@@ -111,206 +89,26 @@ public class BDBMessageStore extends AbstractBDBMessageStore
@Override
protected StoreFuture commit(com.sleepycat.je.Transaction tx, boolean syncCommit) throws DatabaseException
{
- tx.commitNoSync();
-
- BDBCommitFuture commitFuture = new BDBCommitFuture(_commitThread, tx, syncCommit);
- commitFuture.commit();
-
- return commitFuture;
- }
-
- private void startCommitThread()
- {
- _commitThread.start();
- }
-
- private void stopCommitThread() throws InterruptedException
- {
- _commitThread.close();
- _commitThread.join();
- }
-
- private static final class BDBCommitFuture implements StoreFuture
- {
- 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)
- {
- _commitThread = commitThread;
- _tx = tx;
- _syncCommit = syncCommit;
- }
-
- public synchronized void complete()
+ try
{
- if (LOGGER.isDebugEnabled())
- {
- LOGGER.debug("public synchronized void complete(): called (Transaction = " + _tx + ")");
- }
- _complete = true;
-
- notifyAll();
+ tx.commitNoSync();
}
-
- public synchronized void abort(DatabaseException databaseException)
+ catch(DatabaseException de)
{
- _complete = true;
- _databaseException = databaseException;
+ LOGGER.error("Got DatabaseException on commit, closing environment", de);
- notifyAll();
- }
-
- public void commit() throws DatabaseException
- {
- _commitThread.addJob(this, _syncCommit);
-
- if(!_syncCommit)
- {
- LOGGER.debug("CommitAsync was requested, returning immediately.");
- return;
- }
-
- waitForCompletion();
-
- if (_databaseException != null)
- {
- throw _databaseException;
- }
+ closeEnvironmentSafely();
+ throw de;
}
- public synchronized boolean isComplete()
- {
- return _complete;
- }
-
- public synchronized void waitForCompletion()
- {
- while (!isComplete())
- {
- _commitThread.explicitNotify();
- try
- {
- wait(250);
- }
- catch (InterruptedException e)
- {
- //TODO Should we ignore, or throw a 'StoreException'?
- throw new RuntimeException(e);
- }
- }
- }
+ return _commitThreadWrapper.commit(tx, syncCommit);
}
- /**
- * 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> Collaborations </table>
- */
- private class CommitThread extends Thread
+ @Override
+ public String getStoreType()
{
- private final AtomicBoolean _stopped = new AtomicBoolean(false);
- private final Queue<BDBCommitFuture> _jobQueue = 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 explicitNotify()
- {
- synchronized (_lock)
- {
- _lock.notify();
- }
- }
-
- 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(1000);
- }
- catch (InterruptedException e)
- {
- }
- }
- }
- processJobs();
- }
- }
-
- private void processJobs()
- {
- int size = _jobQueue.size();
-
- try
- {
- getEnvironment().flushLog(true);
-
- for(int i = 0; i < size; i++)
- {
- BDBCommitFuture commit = _jobQueue.poll();
- commit.complete();
- }
-
- }
- catch (DatabaseException e)
- {
- for(int i = 0; i < size; i++)
- {
- BDBCommitFuture commit = _jobQueue.poll();
- commit.abort(e);
- }
- }
-
- }
-
- private boolean hasJobs()
- {
- return !_jobQueue.isEmpty();
- }
-
- public void addJob(BDBCommitFuture commit, final boolean sync)
- {
-
- _jobQueue.add(commit);
- if(sync)
- {
- synchronized (_lock)
- {
- _lock.notifyAll();
- }
- }
- }
-
- public void close()
- {
- synchronized (_lock)
- {
- _stopped.set(true);
- _lock.notifyAll();
- }
- }
+ return BDB_STORE_TYPE;
}
}
diff --git a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/CommitThreadWrapper.java b/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/CommitThreadWrapper.java
new file mode 100644
index 0000000000..fe1556b5a6
--- /dev/null
+++ b/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/CommitThreadWrapper.java
@@ -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.
+ *
+ */
+package org.apache.qpid.server.store.berkeleydb;
+
+import java.util.Queue;
+import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import org.apache.log4j.Logger;
+import org.apache.qpid.server.store.StoreFuture;
+
+import com.sleepycat.je.CheckpointConfig;
+import com.sleepycat.je.DatabaseException;
+import com.sleepycat.je.Environment;
+import com.sleepycat.je.Transaction;
+
+public class CommitThreadWrapper
+{
+ private final CommitThread _commitThread;
+
+ public CommitThreadWrapper(String name, Environment env)
+ {
+ _commitThread = new CommitThread(name, env);
+ }
+
+ public void startCommitThread()
+ {
+ _commitThread.start();
+ }
+
+ public void stopCommitThread() throws InterruptedException
+ {
+ _commitThread.close();
+ _commitThread.join();
+ }
+
+ public StoreFuture commit(Transaction tx, boolean syncCommit)
+ {
+ BDBCommitFuture commitFuture = new BDBCommitFuture(_commitThread, tx, syncCommit);
+ commitFuture.commit();
+ return commitFuture;
+ }
+
+ private static final class BDBCommitFuture implements StoreFuture
+ {
+ private static final Logger LOGGER = Logger.getLogger(BDBCommitFuture.class);
+
+ private final CommitThread _commitThread;
+ private final Transaction _tx;
+ private DatabaseException _databaseException;
+ private boolean _complete;
+ private boolean _syncCommit;
+
+ public BDBCommitFuture(CommitThread commitThread, Transaction tx, boolean syncCommit)
+ {
+ _commitThread = commitThread;
+ _tx = tx;
+ _syncCommit = syncCommit;
+ }
+
+ public synchronized void complete()
+ {
+ if (LOGGER.isDebugEnabled())
+ {
+ LOGGER.debug("public synchronized void complete(): called (Transaction = " + _tx + ")");
+ }
+ _complete = true;
+
+ notifyAll();
+ }
+
+ public synchronized void abort(DatabaseException databaseException)
+ {
+ _complete = true;
+ _databaseException = databaseException;
+
+ notifyAll();
+ }
+
+ public void commit() throws DatabaseException
+ {
+ _commitThread.addJob(this, _syncCommit);
+
+ if(!_syncCommit)
+ {
+ LOGGER.debug("CommitAsync was requested, returning immediately.");
+ return;
+ }
+
+ waitForCompletion();
+
+ if (_databaseException != null)
+ {
+ throw _databaseException;
+ }
+
+ }
+
+ public synchronized boolean isComplete()
+ {
+ return _complete;
+ }
+
+ public synchronized void waitForCompletion()
+ {
+ while (!isComplete())
+ {
+ _commitThread.explicitNotify();
+ try
+ {
+ wait(250);
+ }
+ catch (InterruptedException e)
+ {
+ 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> Collaborations </table>
+ */
+ private static class CommitThread extends Thread
+ {
+ private static final Logger LOGGER = Logger.getLogger(CommitThread.class);
+
+ private final AtomicBoolean _stopped = new AtomicBoolean(false);
+ private final Queue<BDBCommitFuture> _jobQueue = new ConcurrentLinkedQueue<BDBCommitFuture>();
+ private final CheckpointConfig _config = new CheckpointConfig();
+ private final Object _lock = new Object();
+ private Environment _environment;
+
+ public CommitThread(String name, Environment env)
+ {
+ super(name);
+ _config.setForce(true);
+ _environment = env;
+ }
+
+ public void explicitNotify()
+ {
+ synchronized (_lock)
+ {
+ _lock.notify();
+ }
+ }
+
+ 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(1000);
+ }
+ catch (InterruptedException e)
+ {
+ }
+ }
+ }
+ processJobs();
+ }
+ }
+
+ private void processJobs()
+ {
+ int size = _jobQueue.size();
+
+ try
+ {
+ _environment.flushLog(true);
+
+ for(int i = 0; i < size; i++)
+ {
+ BDBCommitFuture commit = _jobQueue.poll();
+ commit.complete();
+ }
+
+ }
+ catch (DatabaseException e)
+ {
+ try
+ {
+ LOGGER.error("Exception during environment log flush", e);
+
+ for(int i = 0; i < size; i++)
+ {
+ BDBCommitFuture commit = _jobQueue.poll();
+ commit.abort(e);
+ }
+ }
+ finally
+ {
+ LOGGER.error("Closing store environment", e);
+
+ try
+ {
+ _environment.close();
+ }
+ catch (DatabaseException ex)
+ {
+ LOGGER.error("Exception closing store environment", ex);
+ }
+ }
+ }
+ }
+
+ private boolean hasJobs()
+ {
+ return !_jobQueue.isEmpty();
+ }
+
+ public void addJob(BDBCommitFuture commit, final boolean sync)
+ {
+
+ _jobQueue.add(commit);
+ if(sync)
+ {
+ synchronized (_lock)
+ {
+ _lock.notifyAll();
+ }
+ }
+ }
+
+ public void close()
+ {
+ synchronized (_lock)
+ {
+ _stopped.set(true);
+ _lock.notifyAll();
+ }
+ }
+ }
+}
diff --git a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuple/ConfiguredObjectBinding.java b/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuple/ConfiguredObjectBinding.java
index 8b84a4c9bb..945bcf1d28 100644
--- a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuple/ConfiguredObjectBinding.java
+++ b/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuple/ConfiguredObjectBinding.java
@@ -1,3 +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.
+ *
+ */
package org.apache.qpid.server.store.berkeleydb.tuple;
import org.apache.qpid.server.store.ConfiguredObjectRecord;
diff --git a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/CursorTemplate.java b/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/CursorTemplate.java
index 0b14080486..dc68837d47 100644
--- a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/CursorTemplate.java
+++ b/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/CursorTemplate.java
@@ -1,5 +1,3 @@
-package org.apache.qpid.server.store.berkeleydb.upgrade;
-
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
@@ -20,6 +18,8 @@ package org.apache.qpid.server.store.berkeleydb.upgrade;
* under the License.
*
*/
+package org.apache.qpid.server.store.berkeleydb.upgrade;
+
import com.sleepycat.je.Cursor;
import com.sleepycat.je.CursorConfig;
import com.sleepycat.je.Database;
diff --git a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom5To6.java b/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom5To6.java
index 3265fb6823..2b7c782ad1 100644
--- a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom5To6.java
+++ b/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom5To6.java
@@ -45,6 +45,7 @@ import org.apache.qpid.server.model.Exchange;
import org.apache.qpid.server.model.LifetimePolicy;
import org.apache.qpid.server.model.Queue;
import org.apache.qpid.server.model.UUIDGenerator;
+import org.apache.qpid.server.queue.AMQQueueFactory;
import org.apache.qpid.server.store.berkeleydb.AMQShortStringEncoding;
import org.apache.qpid.server.store.berkeleydb.FieldTableEncoding;
import org.apache.qpid.server.util.MapJsonSerializer;
@@ -93,6 +94,8 @@ public class UpgradeFrom5To6 extends AbstractStoreUpgrade
private MapJsonSerializer _serializer = new MapJsonSerializer();
+ private static final boolean _moveNonExclusiveQueueOwnerToDescription = Boolean.parseBoolean(System.getProperty("qpid.move_non_exclusive_queue_owner_to_description", Boolean.TRUE.toString()));
+
/**
* Upgrades from a v5 database to a v6 database
*
@@ -380,7 +383,7 @@ public class UpgradeFrom5To6 extends AbstractStoreUpgrade
for (int i = 0; i < newDequeues.length; i++)
{
OldRecordImpl dequeue = oldDequeues[i];
- UUID id = UUIDGenerator.generateUUID(dequeue.getQueueName(), virtualHostName);
+ UUID id = UUIDGenerator.generateQueueUUID(dequeue.getQueueName(), virtualHostName);
newDequeues[i] = new NewRecordImpl(id, dequeue.getMessageNumber());
}
}
@@ -390,7 +393,7 @@ public class UpgradeFrom5To6 extends AbstractStoreUpgrade
for (int i = 0; i < newEnqueues.length; i++)
{
OldRecordImpl enqueue = oldEnqueues[i];
- UUID id = UUIDGenerator.generateUUID(enqueue.getQueueName(), virtualHostName);
+ UUID id = UUIDGenerator.generateQueueUUID(enqueue.getQueueName(), virtualHostName);
newEnqueues[i] = new NewRecordImpl(id, enqueue.getMessageNumber());
}
}
@@ -420,7 +423,7 @@ public class UpgradeFrom5To6 extends AbstractStoreUpgrade
Transaction transaction, DatabaseEntry key, DatabaseEntry value)
{
OldQueueEntryKey oldEntryRecord = oldBinding.entryToObject(key);
- UUID queueId = UUIDGenerator.generateUUID(oldEntryRecord.getQueueName().asString(), virtualHostName);
+ UUID queueId = UUIDGenerator.generateQueueUUID(oldEntryRecord.getQueueName().asString(), virtualHostName);
NewQueueEntryKey newEntryRecord = new NewQueueEntryKey(queueId, oldEntryRecord.getMessageId());
DatabaseEntry newKey = new DatabaseEntry();
@@ -455,7 +458,7 @@ public class UpgradeFrom5To6 extends AbstractStoreUpgrade
String routingKey = bindingRecord.getRoutingKey().asString();
FieldTable arguments = bindingRecord.getArguments();
- UUID bindingId = UUIDGenerator.generateUUID();
+ UUID bindingId = UUIDGenerator.generateBindingUUID(exchangeName, queueName, routingKey, virtualHostName);
UpgradeConfiguredObjectRecord configuredObject = createBindingConfiguredObjectRecord(exchangeName, queueName,
routingKey, arguments, virtualHostName);
storeConfiguredObjectEntry(configuredObjectsDatabase, bindingId, configuredObject, transaction);
@@ -489,7 +492,7 @@ public class UpgradeFrom5To6 extends AbstractStoreUpgrade
String exchangeType = exchangeRecord.getType().asString();
boolean autoDelete = exchangeRecord.isAutoDelete();
- UUID exchangeId = UUIDGenerator.generateUUID(exchangeName, virtualHostName);
+ UUID exchangeId = UUIDGenerator.generateExchangeUUID(exchangeName, virtualHostName);
UpgradeConfiguredObjectRecord configuredObject = createExchangeConfiguredObjectRecord(exchangeName,
exchangeType, autoDelete);
@@ -526,7 +529,7 @@ public class UpgradeFrom5To6 extends AbstractStoreUpgrade
boolean exclusive = queueRecord.isExclusive();
FieldTable arguments = queueRecord.getArguments();
- UUID queueId = UUIDGenerator.generateUUID(queueName, virtualHostName);
+ UUID queueId = UUIDGenerator.generateQueueUUID(queueName, virtualHostName);
UpgradeConfiguredObjectRecord configuredObject = createQueueConfiguredObjectRecord(queueName, owner, exclusive,
arguments);
storeConfiguredObjectEntry(configuredObjectsDatabase, queueId, configuredObject, transaction);
@@ -554,17 +557,49 @@ public class UpgradeFrom5To6 extends AbstractStoreUpgrade
private UpgradeConfiguredObjectRecord createQueueConfiguredObjectRecord(String queueName, String owner, boolean exclusive,
FieldTable arguments)
{
+ Map<String, Object> attributesMap = buildQueueArgumentMap(queueName,
+ owner, exclusive, arguments);
+ String json = _serializer.serialize(attributesMap);
+ UpgradeConfiguredObjectRecord configuredObject = new UpgradeConfiguredObjectRecord(Queue.class.getName(), json);
+ return configuredObject;
+ }
+
+ private Map<String, Object> buildQueueArgumentMap(String queueName,
+ String owner, boolean exclusive, FieldTable arguments)
+ {
+
Map<String, Object> attributesMap = new HashMap<String, Object>();
attributesMap.put(Queue.NAME, queueName);
- attributesMap.put(Queue.OWNER, owner);
attributesMap.put(Queue.EXCLUSIVE, exclusive);
+
+ FieldTable argumentsCopy = new FieldTable();
if (arguments != null)
{
- attributesMap.put("ARGUMENTS", FieldTable.convertToMap(arguments));
+ argumentsCopy.addAll(arguments);
}
- String json = _serializer.serialize(attributesMap);
- UpgradeConfiguredObjectRecord configuredObject = new UpgradeConfiguredObjectRecord(Queue.class.getName(), json);
- return configuredObject;
+
+ if (moveNonExclusiveOwnerToDescription(owner, exclusive))
+ {
+ _logger.info("Non-exclusive owner " + owner + " for queue " + queueName + " moved to " + AMQQueueFactory.X_QPID_DESCRIPTION);
+
+ attributesMap.put(Queue.OWNER, null);
+ argumentsCopy.put(AMQShortString.valueOf(AMQQueueFactory.X_QPID_DESCRIPTION), owner);
+ }
+ else
+ {
+ attributesMap.put(Queue.OWNER, owner);
+ }
+ if (!argumentsCopy.isEmpty())
+ {
+ attributesMap.put(Queue.ARGUMENTS, FieldTable.convertToMap(argumentsCopy));
+ }
+ return attributesMap;
+ }
+
+ private boolean moveNonExclusiveOwnerToDescription(String owner,
+ boolean exclusive)
+ {
+ return exclusive == false && owner != null && _moveNonExclusiveQueueOwnerToDescription;
}
private UpgradeConfiguredObjectRecord createExchangeConfiguredObjectRecord(String exchangeName, String exchangeType,
@@ -585,8 +620,8 @@ public class UpgradeFrom5To6 extends AbstractStoreUpgrade
{
Map<String, Object> attributesMap = new HashMap<String, Object>();
attributesMap.put(Binding.NAME, routingKey);
- attributesMap.put(Binding.EXCHANGE, UUIDGenerator.generateUUID(exchangeName, virtualHostName));
- attributesMap.put(Binding.QUEUE, UUIDGenerator.generateUUID(queueName, virtualHostName));
+ attributesMap.put(Binding.EXCHANGE, UUIDGenerator.generateExchangeUUID(exchangeName, virtualHostName));
+ attributesMap.put(Binding.QUEUE, UUIDGenerator.generateQueueUUID(queueName, virtualHostName));
if (arguments != null)
{
attributesMap.put(Binding.ARGUMENTS, FieldTable.convertToMap(arguments));
diff --git a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/Upgrader.java b/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/Upgrader.java
index e71e39cbb8..f1ab012efc 100644
--- a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/Upgrader.java
+++ b/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/Upgrader.java
@@ -24,7 +24,7 @@ import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import org.apache.qpid.AMQStoreException;
-import org.apache.qpid.server.store.berkeleydb.BDBMessageStore;
+import org.apache.qpid.server.store.berkeleydb.AbstractBDBMessageStore;
import com.sleepycat.bind.tuple.IntegerBinding;
import com.sleepycat.bind.tuple.LongBinding;
@@ -63,7 +63,7 @@ public class Upgrader
if(versionDb.count() == 0L)
{
- int sourceVersion = isEmpty ? BDBMessageStore.VERSION: identifyOldStoreVersion();
+ int sourceVersion = isEmpty ? AbstractBDBMessageStore.VERSION: identifyOldStoreVersion();
DatabaseEntry key = new DatabaseEntry();
IntegerBinding.intToEntry(sourceVersion, key);
DatabaseEntry value = new DatabaseEntry();
@@ -87,7 +87,7 @@ public class Upgrader
int getSourceVersion(Database versionDb)
{
- int version = BDBMessageStore.VERSION + 1;
+ int version = AbstractBDBMessageStore.VERSION + 1;
OperationStatus result;
do
@@ -106,7 +106,7 @@ public class Upgrader
void performUpgradeFromVersion(int sourceVersion, Database versionDb)
throws AMQStoreException
{
- while(sourceVersion != BDBMessageStore.VERSION)
+ while(sourceVersion != AbstractBDBMessageStore.VERSION)
{
upgrade(sourceVersion, ++sourceVersion);
DatabaseEntry key = new DatabaseEntry();
diff --git a/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBHAMessageStoreTest.java b/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBHAMessageStoreTest.java
new file mode 100644
index 0000000000..a04fb20680
--- /dev/null
+++ b/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBHAMessageStoreTest.java
@@ -0,0 +1,165 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.net.InetAddress;
+
+import org.apache.commons.configuration.XMLConfiguration;
+import org.apache.qpid.server.configuration.ServerConfiguration;
+import org.apache.qpid.server.logging.SystemOutMessageLogger;
+import org.apache.qpid.server.logging.actors.CurrentActor;
+import org.apache.qpid.server.logging.actors.TestLogActor;
+import org.apache.qpid.server.registry.ApplicationRegistry;
+import org.apache.qpid.server.util.TestApplicationRegistry;
+import org.apache.qpid.server.virtualhost.VirtualHost;
+import org.apache.qpid.test.utils.QpidTestCase;
+import org.apache.qpid.util.FileUtils;
+
+import com.sleepycat.je.Environment;
+import com.sleepycat.je.EnvironmentConfig;
+import com.sleepycat.je.rep.ReplicatedEnvironment;
+import com.sleepycat.je.rep.ReplicationConfig;
+
+
+public class BDBHAMessageStoreTest extends QpidTestCase
+{
+ private static final String TEST_LOG_FILE_MAX = "1000000";
+ private static final String TEST_ELECTION_RETRIES = "1000";
+ private static final String TEST_NUMBER_OF_THREADS = "10";
+ private static final String TEST_ENV_CONSISTENCY_TIMEOUT = "9999999";
+ private String _groupName;
+ private String _workDir;
+ private int _masterPort;
+ private String _host;
+ private XMLConfiguration _configXml;
+
+ public void setUp() throws Exception
+ {
+ super.setUp();
+
+ _workDir = TMP_FOLDER + File.separator + getName();
+ _host = InetAddress.getByName("localhost").getHostAddress();
+ _groupName = "group" + getName();
+ _masterPort = -1;
+
+ FileUtils.delete(new File(_workDir), true);
+ _configXml = new XMLConfiguration();
+ }
+
+ public void tearDown() throws Exception
+ {
+ FileUtils.delete(new File(_workDir), true);
+ super.tearDown();
+ }
+
+ public void testSetSystemConfiguration() throws Exception
+ {
+ // create virtual host configuration, registry and host instance
+ addVirtualHostConfiguration();
+ TestApplicationRegistry registry = initialize();
+ try
+ {
+ VirtualHost virtualhost = registry.getVirtualHostRegistry().getVirtualHost("test" + _masterPort);
+ BDBHAMessageStore store = (BDBHAMessageStore) virtualhost.getMessageStore();
+
+ // test whether JVM system settings were applied
+ Environment env = store.getEnvironment();
+ assertEquals("Unexpected number of cleaner threads", TEST_NUMBER_OF_THREADS, env.getConfig().getConfigParam(EnvironmentConfig.CLEANER_THREADS));
+ assertEquals("Unexpected log file max", TEST_LOG_FILE_MAX, env.getConfig().getConfigParam(EnvironmentConfig.LOG_FILE_MAX));
+
+ ReplicatedEnvironment repEnv = store.getReplicatedEnvironment();
+ assertEquals("Unexpected number of elections primary retries", TEST_ELECTION_RETRIES,
+ repEnv.getConfig().getConfigParam(ReplicationConfig.ELECTIONS_PRIMARY_RETRIES));
+ assertEquals("Unexpected number of elections primary retries", TEST_ENV_CONSISTENCY_TIMEOUT,
+ repEnv.getConfig().getConfigParam(ReplicationConfig.ENV_CONSISTENCY_TIMEOUT));
+ }
+ finally
+ {
+ ApplicationRegistry.remove();
+ }
+ }
+
+ private void addVirtualHostConfiguration() throws Exception
+ {
+ int port = findFreePort();
+ if (_masterPort == -1)
+ {
+ _masterPort = port;
+ }
+ String nodeName = getNodeNameForNodeAt(port);
+
+ String vhostName = "test" + port;
+ String vhostPrefix = "virtualhosts.virtualhost." + vhostName;
+
+ _configXml.addProperty("virtualhosts.virtualhost.name", vhostName);
+ _configXml.addProperty(vhostPrefix + ".store.class", BDBHAMessageStore.class.getName());
+ _configXml.addProperty(vhostPrefix + ".store.environment-path", _workDir + File.separator
+ + port);
+ _configXml.addProperty(vhostPrefix + ".store.highAvailability.groupName", _groupName);
+ _configXml.addProperty(vhostPrefix + ".store.highAvailability.nodeName", nodeName);
+ _configXml.addProperty(vhostPrefix + ".store.highAvailability.nodeHostPort",
+ getNodeHostPortForNodeAt(port));
+ _configXml.addProperty(vhostPrefix + ".store.highAvailability.helperHostPort",
+ getHelperHostPort());
+
+ _configXml.addProperty(vhostPrefix + ".store.envConfig(-1).name", EnvironmentConfig.CLEANER_THREADS);
+ _configXml.addProperty(vhostPrefix + ".store.envConfig.value", TEST_NUMBER_OF_THREADS);
+
+ _configXml.addProperty(vhostPrefix + ".store.envConfig(-1).name", EnvironmentConfig.LOG_FILE_MAX);
+ _configXml.addProperty(vhostPrefix + ".store.envConfig.value", TEST_LOG_FILE_MAX);
+
+ _configXml.addProperty(vhostPrefix + ".store.repConfig(-1).name", ReplicationConfig.ELECTIONS_PRIMARY_RETRIES);
+ _configXml.addProperty(vhostPrefix + ".store.repConfig.value", TEST_ELECTION_RETRIES);
+
+ _configXml.addProperty(vhostPrefix + ".store.repConfig(-1).name", ReplicationConfig.ENV_CONSISTENCY_TIMEOUT);
+ _configXml.addProperty(vhostPrefix + ".store.repConfig.value", TEST_ENV_CONSISTENCY_TIMEOUT);
+ }
+
+ private String getNodeNameForNodeAt(final int bdbPort)
+ {
+ return "node" + getName() + bdbPort;
+ }
+
+ private String getNodeHostPortForNodeAt(final int bdbPort)
+ {
+ return _host + ":" + bdbPort;
+ }
+
+ private String getHelperHostPort()
+ {
+ if (_masterPort == -1)
+ {
+ throw new IllegalStateException("Helper port not yet assigned.");
+ }
+ return _host + ":" + _masterPort;
+ }
+
+ private TestApplicationRegistry initialize() throws Exception
+ {
+ CurrentActor.set(new TestLogActor(new SystemOutMessageLogger()));
+ ServerConfiguration configuration = new ServerConfiguration(_configXml);
+ TestApplicationRegistry registry = new TestApplicationRegistry(configuration);
+ ApplicationRegistry.initialise(registry);
+ registry.getVirtualHostRegistry().setDefaultVirtualHostName("test" + _masterPort);
+ return registry;
+ }
+}
diff --git a/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStoreConfigurationTest.java b/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStoreConfigurationTest.java
index 687c671566..5cc436a22a 100644
--- a/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStoreConfigurationTest.java
+++ b/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStoreConfigurationTest.java
@@ -1,3 +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.
+ *
+ */
package org.apache.qpid.server.store.berkeleydb;
import org.apache.qpid.server.store.DurableConfigurationStoreTest;
diff --git a/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStoreQuotaEventsTest.java b/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStoreQuotaEventsTest.java
new file mode 100644
index 0000000000..fe48e29d0b
--- /dev/null
+++ b/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStoreQuotaEventsTest.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.server.store.berkeleydb;
+
+import org.apache.commons.configuration.XMLConfiguration;
+import org.apache.log4j.Logger;
+import org.apache.qpid.server.store.MessageStore;
+import org.apache.qpid.server.store.MessageStoreQuotaEventsTestBase;
+
+public class BDBMessageStoreQuotaEventsTest extends MessageStoreQuotaEventsTestBase
+{
+ private static final Logger _logger = Logger.getLogger(BDBMessageStoreQuotaEventsTest.class);
+
+ /*
+ * Notes on calculation of quota limits.
+ *
+ * 150 32kb messages is approximately 4.8MB which is greater than
+ * OVERFULL_SIZE.
+ *
+ * We deliberately use settings that force BDB to use multiple log files, so
+ * that when one or more of them are subsequently cleaned (following message
+ * consumption) the actual size on disk is reduced.
+ */
+
+ private static final String MAX_BDB_LOG_SIZE = "1000000"; // ~1MB
+
+ private static final int NUMBER_OF_MESSAGES_TO_OVERFILL_STORE = 150;
+
+ private static final int OVERFULL_SIZE = 4000000; // ~4MB
+ private static final int UNDERFULL_SIZE = 3500000; // ~3.5MB
+
+ @Override
+ protected int getNumberOfMessagesToFillStore()
+ {
+ return NUMBER_OF_MESSAGES_TO_OVERFILL_STORE;
+ }
+
+ @Override
+ protected void applyStoreSpecificConfiguration(XMLConfiguration config)
+ {
+ _logger.debug("Applying store specific config. overfull-sze=" + OVERFULL_SIZE + ", underfull-size=" + UNDERFULL_SIZE);
+
+ config.addProperty("envConfig(-1).name", "je.log.fileMax");
+ config.addProperty("envConfig.value", MAX_BDB_LOG_SIZE);
+ config.addProperty("overfull-size", OVERFULL_SIZE);
+ config.addProperty("underfull-size", UNDERFULL_SIZE);
+ }
+
+ @Override
+ protected MessageStore createStore() throws Exception
+ {
+ MessageStore store = new BDBMessageStore();
+ return store;
+ }
+}
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
index a318187f13..eef9f7eab4 100644
--- 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
@@ -55,7 +55,7 @@ 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.
+ * the BDB Store as well as additional tests specific to the BDB store-implementation.
*/
public class BDBMessageStoreTest extends org.apache.qpid.server.store.MessageStoreTest
{
@@ -70,7 +70,7 @@ public class BDBMessageStoreTest extends org.apache.qpid.server.store.MessageSto
{
MessageStore store = getVirtualHost().getMessageStore();
- BDBMessageStore bdbStore = assertBDBStore(store);
+ AbstractBDBMessageStore bdbStore = assertBDBStore(store);
// Create content ByteBuffers.
// Split the content into 2 chunks for the 0-8 message, as per broker behaviour.
@@ -220,11 +220,11 @@ public class BDBMessageStoreTest extends org.apache.qpid.server.store.MessageSto
* 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 reloadStore(BDBMessageStore messageStore) throws Exception
+ private AbstractBDBMessageStore reloadStore(AbstractBDBMessageStore messageStore) throws Exception
{
messageStore.close();
- BDBMessageStore newStore = new BDBMessageStore();
+ AbstractBDBMessageStore newStore = new BDBMessageStore();
newStore.configure("", _config.subset("store"));
newStore.startWithNoRecover();
@@ -282,7 +282,7 @@ public class BDBMessageStoreTest extends org.apache.qpid.server.store.MessageSto
public void testGetContentWithOffset() throws Exception
{
MessageStore store = getVirtualHost().getMessageStore();
- BDBMessageStore bdbStore = assertBDBStore(store);
+ AbstractBDBMessageStore bdbStore = assertBDBStore(store);
StoredMessage<MessageMetaData> storedMessage_0_8 = createAndStoreSingleChunkMessage_0_8(store);
long messageid_0_8 = storedMessage_0_8.getMessageNumber();
@@ -342,7 +342,7 @@ public class BDBMessageStoreTest extends org.apache.qpid.server.store.MessageSto
public void testMessageCreationAndRemoval() throws Exception
{
MessageStore store = getVirtualHost().getMessageStore();
- BDBMessageStore bdbStore = assertBDBStore(store);
+ AbstractBDBMessageStore bdbStore = assertBDBStore(store);
StoredMessage<MessageMetaData> storedMessage_0_8 = createAndStoreSingleChunkMessage_0_8(store);
long messageid_0_8 = storedMessage_0_8.getMessageNumber();
@@ -367,12 +367,12 @@ public class BDBMessageStoreTest extends org.apache.qpid.server.store.MessageSto
assertEquals("Retrieved content when none was expected",
0, bdbStore.getContent(messageid_0_8, 0, dst));
}
- private BDBMessageStore assertBDBStore(MessageStore store)
+ private AbstractBDBMessageStore assertBDBStore(MessageStore store)
{
assertEquals("Test requires an instance of BDBMessageStore to proceed", BDBMessageStore.class, store.getClass());
- return (BDBMessageStore) store;
+ return (AbstractBDBMessageStore) store;
}
private StoredMessage<MessageMetaData> createAndStoreSingleChunkMessage_0_8(MessageStore store)
@@ -405,9 +405,9 @@ public class BDBMessageStoreTest extends org.apache.qpid.server.store.MessageSto
{
MessageStore log = getVirtualHost().getMessageStore();
- BDBMessageStore bdbStore = assertBDBStore(log);
+ AbstractBDBMessageStore bdbStore = assertBDBStore(log);
- final UUID mockQueueId = UUIDGenerator.generateUUID();
+ final UUID mockQueueId = UUIDGenerator.generateRandomUUID();
TransactionLogResource mockQueue = new TransactionLogResource()
{
@Override
@@ -443,9 +443,9 @@ public class BDBMessageStoreTest extends org.apache.qpid.server.store.MessageSto
{
MessageStore log = getVirtualHost().getMessageStore();
- BDBMessageStore bdbStore = assertBDBStore(log);
+ AbstractBDBMessageStore bdbStore = assertBDBStore(log);
- final UUID mockQueueId = UUIDGenerator.generateUUID();
+ final UUID mockQueueId = UUIDGenerator.generateRandomUUID();
TransactionLogResource mockQueue = new TransactionLogResource()
{
@Override
@@ -484,9 +484,9 @@ public class BDBMessageStoreTest extends org.apache.qpid.server.store.MessageSto
{
MessageStore log = getVirtualHost().getMessageStore();
- BDBMessageStore bdbStore = assertBDBStore(log);
+ AbstractBDBMessageStore bdbStore = assertBDBStore(log);
- final UUID mockQueueId = UUIDGenerator.generateUUID();
+ final UUID mockQueueId = UUIDGenerator.generateRandomUUID();
TransactionLogResource mockQueue = new TransactionLogResource()
{
@Override
diff --git a/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/HAClusterBlackboxTest.java b/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/HAClusterBlackboxTest.java
new file mode 100644
index 0000000000..c6a9ba8f8b
--- /dev/null
+++ b/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/HAClusterBlackboxTest.java
@@ -0,0 +1,165 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import javax.jms.Connection;
+import javax.jms.Session;
+
+import org.apache.log4j.Logger;
+import org.apache.qpid.client.AMQConnection;
+import org.apache.qpid.jms.ConnectionListener;
+import org.apache.qpid.jms.ConnectionURL;
+import org.apache.qpid.test.utils.QpidBrokerTestCase;
+
+import com.sleepycat.je.rep.ReplicationConfig;
+
+/**
+ * The HA black box tests test the BDB cluster as a opaque unit. Client connects to
+ * the cluster via a failover url
+ *
+ * @see HAClusterWhiteboxTest
+ */
+public class HAClusterBlackboxTest extends QpidBrokerTestCase
+{
+ protected static final Logger LOGGER = Logger.getLogger(HAClusterBlackboxTest.class);
+
+ private static final String VIRTUAL_HOST = "test";
+ private static final int NUMBER_OF_NODES = 3;
+
+ private final HATestClusterCreator _clusterCreator = new HATestClusterCreator(this, VIRTUAL_HOST, NUMBER_OF_NODES);
+
+ private FailoverAwaitingListener _failoverAwaitingListener;
+ private ConnectionURL _brokerFailoverUrl;
+
+ @Override
+ protected void setUp() throws Exception
+ {
+ _brokerType = BrokerType.SPAWNED;
+
+ assertTrue(isJavaBroker());
+ assertTrue(isBrokerStorePersistent());
+
+ setSystemProperty("java.util.logging.config.file", "etc" + File.separator + "log.properties");
+
+ _clusterCreator.configureClusterNodes();
+
+ _brokerFailoverUrl = _clusterCreator.getConnectionUrlForAllClusterNodes();
+
+ _clusterCreator.startCluster();
+ _failoverAwaitingListener = new FailoverAwaitingListener();
+
+ super.setUp();
+ }
+
+ @Override
+ public void startBroker() throws Exception
+ {
+ // Don't start default broker provided by QBTC.
+ }
+
+ public void testLossOfMasterNodeCausesClientToFailover() throws Exception
+ {
+ final Connection connection = getConnection(_brokerFailoverUrl);
+
+ ((AMQConnection)connection).setConnectionListener(_failoverAwaitingListener);
+
+ final int activeBrokerPort = _clusterCreator.getBrokerPortNumberFromConnection(connection);
+ LOGGER.info("Active connection port " + activeBrokerPort);
+
+ _clusterCreator.stopNode(activeBrokerPort);
+ LOGGER.info("Node is stopped");
+ _failoverAwaitingListener.assertFailoverOccurs(20000);
+ LOGGER.info("Listener has finished");
+ // any op to ensure connection remains
+ connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
+ }
+
+ public void testLossOfReplicaNodeDoesNotCauseClientToFailover() throws Exception
+ {
+ LOGGER.info("Connecting to " + _brokerFailoverUrl);
+ final Connection connection = getConnection(_brokerFailoverUrl);
+ LOGGER.info("Got connection to cluster");
+
+ ((AMQConnection)connection).setConnectionListener(_failoverAwaitingListener);
+ final int activeBrokerPort = _clusterCreator.getBrokerPortNumberFromConnection(connection);
+ LOGGER.info("Active connection port " + activeBrokerPort);
+ final int inactiveBrokerPort = _clusterCreator.getPortNumberOfAnInactiveBroker(connection);
+
+ LOGGER.info("Stopping inactive broker on port " + inactiveBrokerPort);
+
+ _clusterCreator.stopNode(inactiveBrokerPort);
+
+ _failoverAwaitingListener.assertFailoverDoesNotOccur(2000);
+
+ // any op to ensure connection remains
+ connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
+ }
+
+ private final class FailoverAwaitingListener implements ConnectionListener
+ {
+ private final CountDownLatch _failoverLatch = new CountDownLatch(1);
+
+ @Override
+ public boolean preResubscribe()
+ {
+ return true;
+ }
+
+ @Override
+ public boolean preFailover(boolean redirect)
+ {
+ return true;
+ }
+
+ public void assertFailoverOccurs(long delay) throws InterruptedException
+ {
+ _failoverLatch.await(delay, TimeUnit.MILLISECONDS);
+ assertEquals("Failover did not occur", 0, _failoverLatch.getCount());
+ }
+
+ public void assertFailoverDoesNotOccur(long delay) throws InterruptedException
+ {
+ _failoverLatch.await(delay, TimeUnit.MILLISECONDS);
+ assertEquals("Failover occurred unexpectedly", 1L, _failoverLatch.getCount());
+ }
+
+
+ @Override
+ public void failoverComplete()
+ {
+ _failoverLatch.countDown();
+ }
+
+ @Override
+ public void bytesSent(long count)
+ {
+ }
+
+ @Override
+ public void bytesReceived(long count)
+ {
+ }
+ }
+
+}
diff --git a/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/HAClusterWhiteboxTest.java b/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/HAClusterWhiteboxTest.java
new file mode 100644
index 0000000000..408643b98a
--- /dev/null
+++ b/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/HAClusterWhiteboxTest.java
@@ -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.
+ *
+ */
+package org.apache.qpid.server.store.berkeleydb;
+
+import java.io.File;
+import java.util.Set;
+
+import javax.jms.Connection;
+import javax.jms.Destination;
+import javax.jms.JMSException;
+import javax.jms.Message;
+import javax.jms.MessageConsumer;
+import javax.jms.Queue;
+import javax.jms.Session;
+
+import org.apache.log4j.Logger;
+import org.apache.qpid.test.utils.QpidBrokerTestCase;
+import org.apache.qpid.url.URLSyntaxException;
+
+/**
+ * The HA white box tests test the BDB cluster where the test retains the knowledge of the
+ * individual test nodes. It uses this knowledge to examine the nodes to ensure that they
+ * remain in the correct state throughout the test.
+ *
+ * @see HAClusterBlackboxTest
+ */
+public class HAClusterWhiteboxTest extends QpidBrokerTestCase
+{
+ protected static final Logger LOGGER = Logger.getLogger(HAClusterWhiteboxTest.class);
+
+ private static final String VIRTUAL_HOST = "test";
+
+ private final int NUMBER_OF_NODES = 3;
+ private final HATestClusterCreator _clusterCreator = new HATestClusterCreator(this, VIRTUAL_HOST, NUMBER_OF_NODES);
+
+ @Override
+ protected void setUp() throws Exception
+ {
+ _brokerType = BrokerType.SPAWNED;
+
+ assertTrue(isJavaBroker());
+ assertTrue(isBrokerStorePersistent());
+
+ setSystemProperty("java.util.logging.config.file", "etc" + File.separator + "log.properties");
+
+ _clusterCreator.configureClusterNodes();
+ _clusterCreator.startCluster();
+
+ super.setUp();
+ }
+
+ @Override
+ public void startBroker() throws Exception
+ {
+ // Don't start default broker provided by QBTC.
+ }
+
+ public void testClusterPermitsConnectionToOnlyOneNode() throws Exception
+ {
+ int connectionSuccesses = 0;
+ int connectionFails = 0;
+
+ for (int brokerPortNumber : getBrokerPortNumbers())
+ {
+ try
+ {
+ getConnection(_clusterCreator.getConnectionUrlForSingleNodeWithoutRetry(brokerPortNumber));
+ connectionSuccesses++;
+ }
+ catch(JMSException e)
+ {
+ assertTrue(e.getMessage().contains("Virtual host '" + VIRTUAL_HOST + "' is not active"));
+ connectionFails++;
+ }
+ }
+
+ assertEquals("Unexpected number of failed connections", NUMBER_OF_NODES - 1, connectionFails);
+ assertEquals("Unexpected number of successful connections", 1, connectionSuccesses);
+ }
+
+ public void testClusterThatLosesNodeStillAllowsConnection() throws Exception
+ {
+ final Connection initialConnection = getConnectionToNodeInCluster();
+ assertNotNull(initialConnection);
+
+ closeConnectionAndKillBroker(initialConnection);
+
+ final Connection subsequentConnection = getConnectionToNodeInCluster();
+ assertNotNull(subsequentConnection);
+
+ // verify that JMS persistence operations are working
+ assertProducingConsuming(subsequentConnection);
+
+ closeConnection(initialConnection);
+ }
+
+ public void testClusterThatLosesAllButOneNodeRefusesConnection() throws Exception
+ {
+ final Connection initialConnection = getConnectionToNodeInCluster();
+ assertNotNull(initialConnection);
+
+ closeConnectionAndKillBroker(initialConnection);
+
+ final Connection subsequentConnection = getConnectionToNodeInCluster();
+ assertNotNull(subsequentConnection);
+ final int subsequentPortNumber = _clusterCreator.getBrokerPortNumberFromConnection(subsequentConnection);
+
+ killBroker(subsequentPortNumber);
+
+ final Connection finalConnection = getConnectionToNodeInCluster();
+ assertNull(finalConnection);
+
+ closeConnection(initialConnection);
+ }
+
+ public void testClusterWithRestartedNodeStillAllowsConnection() throws Exception
+ {
+ final Connection connection = getConnectionToNodeInCluster();
+ assertNotNull(connection);
+
+ final int brokerPortNumber = _clusterCreator.getBrokerPortNumberFromConnection(connection);
+ connection.close();
+
+ _clusterCreator.stopNode(brokerPortNumber);
+ _clusterCreator.startNode(brokerPortNumber);
+
+ final Connection subsequentConnection = getConnectionToNodeInCluster();
+ assertNotNull(subsequentConnection);
+ }
+
+ public void testClusterLosingNodeRetainsData() throws Exception
+ {
+ final Connection initialConnection = getConnectionToNodeInCluster();
+
+ final String queueNamePrefix = getTestQueueName();
+ final String inbuiltExchangeQueueUrl = "direct://amq.direct/" + queueNamePrefix + "1/" + queueNamePrefix + "1?durable='true'";
+ final String customExchangeQueueUrl = "direct://my.exchange/" + queueNamePrefix + "2/" + queueNamePrefix + "2?durable='true'";
+
+ populateBrokerWithData(initialConnection, inbuiltExchangeQueueUrl, customExchangeQueueUrl);
+
+ closeConnectionAndKillBroker(initialConnection);
+
+ final Connection subsequentConnection = getConnectionToNodeInCluster();
+
+ assertNotNull("no valid connection obtained", subsequentConnection);
+
+ checkBrokerData(subsequentConnection, inbuiltExchangeQueueUrl, customExchangeQueueUrl);
+ }
+
+ public void xtestRecoveryOfOutOfDateNode() throws Exception
+ {
+ /*
+ * TODO: Implement
+ *
+ * Cant yet find a way to control cleaning in a deterministic way to allow provoking
+ * a node to become out of date. We do now know that even a new joiner to the group
+ * can throw the InsufficientLogException, so ensuring an existing cluster of nodes has
+ * done *any* cleaning and then adding a new node should be sufficient to cause this.
+ */
+ }
+
+ private void populateBrokerWithData(final Connection connection, final String... queueUrls) throws JMSException, Exception
+ {
+ populateBrokerWithData(connection, 1, queueUrls);
+ }
+
+ private void populateBrokerWithData(final Connection connection, int noOfMessages, final String... queueUrls) throws JMSException, Exception
+ {
+ final Session session = connection.createSession(true, Session.SESSION_TRANSACTED);
+ for (final String queueUrl : queueUrls)
+ {
+ final Queue queue = session.createQueue(queueUrl);
+ session.createConsumer(queue).close();
+ sendMessage(session, queue, noOfMessages);
+ }
+ }
+
+ private void checkBrokerData(final Connection connection, final String... queueUrls) throws JMSException
+ {
+ connection.start();
+ final Session session = connection.createSession(true, Session.SESSION_TRANSACTED);
+ for (final String queueUrl : queueUrls)
+ {
+ final Queue queue = session.createQueue(queueUrl);
+ final MessageConsumer consumer = session.createConsumer(queue);
+ final Message message = consumer.receive(1000);
+ session.commit();
+ assertNotNull("Queue " + queue + " should have message", message);
+ assertEquals("Queue " + queue + " message has unexpected content", 0, message.getIntProperty(INDEX));
+ }
+ }
+
+ private Connection getConnectionToNodeInCluster() throws URLSyntaxException
+ {
+ Connection connection = null;
+ Set<Integer> runningBrokerPorts = getBrokerPortNumbers();
+
+ for (int brokerPortNumber : runningBrokerPorts)
+ {
+ try
+ {
+ connection = getConnection(_clusterCreator.getConnectionUrlForSingleNodeWithRetry(brokerPortNumber));
+ break;
+ }
+ catch(JMSException je)
+ {
+ assertTrue(je.getMessage().contains("Virtual host '" + VIRTUAL_HOST + "' is not active"));
+ }
+ }
+ return connection;
+ }
+
+ private void closeConnectionAndKillBroker(final Connection initialConnection) throws Exception
+ {
+ final int initialPortNumber = _clusterCreator.getBrokerPortNumberFromConnection(initialConnection);
+ initialConnection.close();
+
+ killBroker(initialPortNumber); // kill awaits the death of the child
+ }
+
+ private void assertProducingConsuming(final Connection connection) throws JMSException, Exception
+ {
+ Session session = connection.createSession(true, Session.SESSION_TRANSACTED);
+ Destination destination = session.createQueue(getTestQueueName());
+ MessageConsumer consumer = session.createConsumer(destination);
+ sendMessage(session, destination, 2);
+ connection.start();
+ Message m1 = consumer.receive(RECEIVE_TIMEOUT);
+ assertNotNull("Message 1 is not received", m1);
+ assertEquals("Unexpected first message received", 0, m1.getIntProperty(INDEX));
+ Message m2 = consumer.receive(RECEIVE_TIMEOUT);
+ assertNotNull("Message 2 is not received", m2);
+ assertEquals("Unexpected second message received", 1, m2.getIntProperty(INDEX));
+ session.commit();
+ }
+
+ private void closeConnection(final Connection initialConnection)
+ {
+ try
+ {
+ initialConnection.close();
+ }
+ catch(Exception e)
+ {
+ // ignore.
+ // java.net.SocketException is seen sometimes on active connection
+ }
+ }
+}
diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/NumberVerifyListener.java b/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/HAMessageStoreSmokeTest.java
index 1774209dae..eaa3c3eba4 100644
--- a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/NumberVerifyListener.java
+++ b/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/HAMessageStoreSmokeTest.java
@@ -1,5 +1,4 @@
/*
- *
* Licensed 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,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
@@ -18,29 +17,27 @@
* under the License.
*
*/
-package org.apache.qpid.management.ui.views;
+package org.apache.qpid.server.store.berkeleydb;
-import org.eclipse.swt.events.VerifyEvent;
-import org.eclipse.swt.events.VerifyListener;
+import org.apache.commons.configuration.ConfigurationException;
+import org.apache.commons.configuration.XMLConfiguration;
+import org.apache.qpid.test.utils.QpidTestCase;
-/**
- * Implementation of VeryfyListener for numeric values
- * @author Bhupendra Bhardwaj
- */
-public class NumberVerifyListener implements VerifyListener
+public class HAMessageStoreSmokeTest extends QpidTestCase
{
- public void verifyText(VerifyEvent event)
+ private final BDBHAMessageStore _store = new BDBHAMessageStore();
+ private final XMLConfiguration _config = new XMLConfiguration();
+
+ public void testMissingHAConfigThrowsException() throws Exception
{
- String string = event.text;
- char [] chars = new char [string.length ()];
- string.getChars (0, chars.length, chars, 0);
- for (int i=0; i<chars.length; i++)
+ try
+ {
+ _store.configure("test", _config);
+ fail("Expected an exception to be thrown");
+ }
+ catch (ConfigurationException ce)
{
- if (!('0' <= chars [i] && chars [i] <= '9'))
- {
- event.doit = false;
- return;
- }
+ assertTrue(ce.getMessage().contains("BDB HA configuration key not found"));
}
}
-}
+} \ No newline at end of file
diff --git a/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/HATestClusterCreator.java b/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/HATestClusterCreator.java
new file mode 100644
index 0000000000..abe13edc32
--- /dev/null
+++ b/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/HATestClusterCreator.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.server.store.berkeleydb;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.concurrent.Callable;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+
+import javax.jms.Connection;
+
+import org.apache.commons.configuration.XMLConfiguration;
+import org.apache.commons.lang.StringUtils;
+import org.apache.log4j.Logger;
+import org.apache.qpid.client.AMQConnection;
+import org.apache.qpid.client.AMQConnectionURL;
+import org.apache.qpid.test.utils.QpidBrokerTestCase;
+import org.apache.qpid.url.URLSyntaxException;
+
+public class HATestClusterCreator
+{
+ protected static final Logger LOGGER = Logger.getLogger(HATestClusterCreator.class);
+
+ private static final String MANY_BROKER_URL_FORMAT = "amqp://guest:guest@/%s?brokerlist='%s'&failover='roundrobin?cyclecount='%d''";
+ private static final String BROKER_PORTION_FORMAT = "tcp://localhost:%d?connectdelay='%d',retries='%d'";
+
+ private static final int FAILOVER_CYCLECOUNT = 10;
+ private static final int FAILOVER_RETRIES = 1;
+ private static final int FAILOVER_CONNECTDELAY = 1000;
+
+ private static final String SINGLE_BROKER_URL_WITH_RETRY_FORMAT = "amqp://guest:guest@/%s?brokerlist='tcp://localhost:%d?connectdelay='%d',retries='%d''";
+ private static final String SINGLE_BROKER_URL_WITHOUT_RETRY_FORMAT = "amqp://guest:guest@/%s?brokerlist='tcp://localhost:%d'";
+
+ private static final int RETRIES = 60;
+ private static final int CONNECTDELAY = 75;
+
+ private final QpidBrokerTestCase _testcase;
+ private final Map<Integer, Integer> _brokerPortToBdbPortMap = new HashMap<Integer, Integer>();
+ private final Map<Integer, BrokerConfigHolder> _brokerConfigurations = new TreeMap<Integer, BrokerConfigHolder>();
+ private final String _virtualHostName;
+ private final String _storeConfigKeyPrefix;
+
+ private final String _ipAddressOfBroker;
+ private final String _groupName ;
+ private final int _numberOfNodes;
+ private int _bdbHelperPort;
+ private int _primaryBrokerPort;
+
+ public HATestClusterCreator(QpidBrokerTestCase testcase, String virtualHostName, int numberOfNodes)
+ {
+ _testcase = testcase;
+ _virtualHostName = virtualHostName;
+ _groupName = "group" + _testcase.getName();
+ _ipAddressOfBroker = getIpAddressOfBrokerHost();
+ _numberOfNodes = numberOfNodes;
+ _storeConfigKeyPrefix = "virtualhosts.virtualhost." + _virtualHostName + ".store.";
+ _bdbHelperPort = 0;
+ }
+
+ public void configureClusterNodes() throws Exception
+ {
+ int brokerPort = _testcase.findFreePort();
+
+ for (int i = 0; i < _numberOfNodes; i++)
+ {
+ int bdbPort = _testcase.getNextAvailable(brokerPort + 1);
+ _brokerPortToBdbPortMap.put(brokerPort, bdbPort);
+
+ LOGGER.debug("Cluster broker port " + brokerPort + ", bdb replication port " + bdbPort);
+ if (_bdbHelperPort == 0)
+ {
+ _bdbHelperPort = bdbPort;
+ }
+
+ configureClusterNode(brokerPort, bdbPort);
+ collectConfig(brokerPort, _testcase.getTestConfiguration(), _testcase.getTestVirtualhosts());
+
+ brokerPort = _testcase.getNextAvailable(bdbPort + 1);
+ }
+ }
+
+ public void setDesignatedPrimaryOnFirstBroker(boolean designatedPrimary) throws Exception
+ {
+ if (_numberOfNodes != 2)
+ {
+ throw new IllegalArgumentException("Only two nodes groups have the concept of primary");
+ }
+
+ final Entry<Integer, BrokerConfigHolder> brokerConfigEntry = _brokerConfigurations.entrySet().iterator().next();
+ final String configKey = getConfigKey("highAvailability.designatedPrimary");
+ brokerConfigEntry.getValue().getTestVirtualhosts().setProperty(configKey, Boolean.toString(designatedPrimary));
+ _primaryBrokerPort = brokerConfigEntry.getKey();
+ }
+
+ /**
+ * @param configKeySuffix "highAvailability.designatedPrimary", for example
+ * @return "virtualhost.test.store.highAvailability.designatedPrimary", for example
+ */
+ private String getConfigKey(String configKeySuffix)
+ {
+ final String configKey = StringUtils.substringAfter(_storeConfigKeyPrefix + configKeySuffix, "virtualhosts.");
+ return configKey;
+ }
+
+ public void startNode(final int brokerPortNumber) throws Exception
+ {
+ final BrokerConfigHolder brokerConfigHolder = _brokerConfigurations.get(brokerPortNumber);
+
+ _testcase.setTestConfiguration(brokerConfigHolder.getTestConfiguration());
+ _testcase.setTestVirtualhosts(brokerConfigHolder.getTestVirtualhosts());
+
+ _testcase.startBroker(brokerPortNumber);
+ }
+
+ public void startCluster() throws Exception
+ {
+ for (final Integer brokerPortNumber : _brokerConfigurations.keySet())
+ {
+ startNode(brokerPortNumber);
+ }
+ }
+
+ public void startClusterParallel() throws Exception
+ {
+ final ExecutorService executor = Executors.newFixedThreadPool(_brokerConfigurations.size());
+ try
+ {
+ List<Future<Object>> brokers = new CopyOnWriteArrayList<Future<Object>>();
+ for (final Integer brokerPortNumber : _brokerConfigurations.keySet())
+ {
+ final BrokerConfigHolder brokerConfigHolder = _brokerConfigurations.get(brokerPortNumber);
+ Future<Object> future = executor.submit(new Callable<Object>()
+ {
+ public Object call()
+ {
+ try
+ {
+ _testcase.startBroker(brokerPortNumber, brokerConfigHolder.getTestConfiguration(),
+ brokerConfigHolder.getTestVirtualhosts());
+ return "OK";
+ }
+ catch (Exception e)
+ {
+ return e;
+ }
+ }
+ });
+ brokers.add(future);
+ }
+ for (Future<Object> future : brokers)
+ {
+ Object result = future.get(30, TimeUnit.SECONDS);
+ LOGGER.debug("Node startup result:" + result);
+ if (result instanceof Exception)
+ {
+ throw (Exception) result;
+ }
+ else if (!"OK".equals(result))
+ {
+ throw new Exception("One of the cluster nodes is not started");
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ stopCluster();
+ throw e;
+ }
+ finally
+ {
+ executor.shutdown();
+ }
+
+ }
+
+ public void stopNode(final int brokerPortNumber)
+ {
+ _testcase.stopBroker(brokerPortNumber);
+ }
+
+ public void stopCluster() throws Exception
+ {
+ for (final Integer brokerPortNumber : _brokerConfigurations.keySet())
+ {
+ try
+ {
+ stopNode(brokerPortNumber);
+ }
+ catch(Exception e)
+ {
+ LOGGER.warn("Failed to stop node on port:" + brokerPortNumber);
+ }
+ }
+ }
+
+ public int getBrokerPortNumberFromConnection(Connection connection)
+ {
+ final AMQConnection amqConnection = (AMQConnection)connection;
+ return amqConnection.getActiveBrokerDetails().getPort();
+ }
+
+ public int getPortNumberOfAnInactiveBroker(final Connection activeConnection)
+ {
+ final Set<Integer> allBrokerPorts = _testcase.getBrokerPortNumbers();
+ LOGGER.debug("Broker ports:" + allBrokerPorts);
+ final int activeBrokerPort = getBrokerPortNumberFromConnection(activeConnection);
+ allBrokerPorts.remove(activeBrokerPort);
+ LOGGER.debug("Broker ports:" + allBrokerPorts);
+ final int inactiveBrokerPort = allBrokerPorts.iterator().next();
+ return inactiveBrokerPort;
+ }
+
+ public int getBdbPortForBrokerPort(final int brokerPortNumber)
+ {
+ return _brokerPortToBdbPortMap.get(brokerPortNumber);
+ }
+
+ public Set<Integer> getBdbPortNumbers()
+ {
+ return new HashSet<Integer>(_brokerPortToBdbPortMap.values());
+ }
+
+ public AMQConnectionURL getConnectionUrlForAllClusterNodes() throws Exception
+ {
+ final StringBuilder brokerList = new StringBuilder();
+
+ for(Iterator<Integer> itr = _brokerPortToBdbPortMap.keySet().iterator(); itr.hasNext(); )
+ {
+ int brokerPortNumber = itr.next();
+
+ brokerList.append(String.format(BROKER_PORTION_FORMAT, brokerPortNumber, FAILOVER_CONNECTDELAY, FAILOVER_RETRIES));
+ if (itr.hasNext())
+ {
+ brokerList.append(";");
+ }
+ }
+
+ return new AMQConnectionURL(String.format(MANY_BROKER_URL_FORMAT, _virtualHostName, brokerList, FAILOVER_CYCLECOUNT));
+ }
+
+ public AMQConnectionURL getConnectionUrlForSingleNodeWithoutRetry(final int brokerPortNumber) throws URLSyntaxException
+ {
+ return getConnectionUrlForSingleNode(brokerPortNumber, false);
+ }
+
+ public AMQConnectionURL getConnectionUrlForSingleNodeWithRetry(final int brokerPortNumber) throws URLSyntaxException
+ {
+ return getConnectionUrlForSingleNode(brokerPortNumber, true);
+ }
+
+ private AMQConnectionURL getConnectionUrlForSingleNode(final int brokerPortNumber, boolean retryAllowed) throws URLSyntaxException
+ {
+ final String url;
+ if (retryAllowed)
+ {
+ url = String.format(SINGLE_BROKER_URL_WITH_RETRY_FORMAT, _virtualHostName, brokerPortNumber, CONNECTDELAY, RETRIES);
+ }
+ else
+ {
+ url = String.format(SINGLE_BROKER_URL_WITHOUT_RETRY_FORMAT, _virtualHostName, brokerPortNumber);
+ }
+
+ return new AMQConnectionURL(url);
+ }
+
+ public String getGroupName()
+ {
+ return _groupName;
+ }
+
+ public String getNodeNameForNodeAt(final int bdbPort)
+ {
+ return "node" + _testcase.getName() + bdbPort;
+ }
+
+ public String getNodeHostPortForNodeAt(final int bdbPort)
+ {
+ return _ipAddressOfBroker + ":" + bdbPort;
+ }
+
+ public String getHelperHostPort()
+ {
+ if (_bdbHelperPort == 0)
+ {
+ throw new IllegalStateException("Helper port not yet assigned.");
+ }
+
+ return _ipAddressOfBroker + ":" + _bdbHelperPort;
+ }
+
+ public void setHelperHostPort(int bdbHelperPort)
+ {
+ _bdbHelperPort = bdbHelperPort;
+ }
+
+ public int getBrokerPortNumberOfPrimary()
+ {
+ if (_numberOfNodes != 2)
+ {
+ throw new IllegalArgumentException("Only two nodes groups have the concept of primary");
+ }
+
+ return _primaryBrokerPort;
+ }
+
+ public int getBrokerPortNumberOfSecondaryNode()
+ {
+ final Set<Integer> portNumbers = getBrokerPortNumbersForNodes();
+ portNumbers.remove(getBrokerPortNumberOfPrimary());
+ return portNumbers.iterator().next();
+ }
+
+ public Set<Integer> getBrokerPortNumbersForNodes()
+ {
+ return new HashSet<Integer>(_brokerConfigurations.keySet());
+ }
+
+ private void configureClusterNode(final int brokerPort, final int bdbPort) throws Exception
+ {
+ final String nodeName = getNodeNameForNodeAt(bdbPort);
+
+ _testcase.setConfigurationProperty(_storeConfigKeyPrefix + "class", "org.apache.qpid.server.store.berkeleydb.BDBHAMessageStore");
+
+ _testcase.setConfigurationProperty(_storeConfigKeyPrefix + "highAvailability.groupName", _groupName);
+ _testcase.setConfigurationProperty(_storeConfigKeyPrefix + "highAvailability.nodeName", nodeName);
+ _testcase.setConfigurationProperty(_storeConfigKeyPrefix + "highAvailability.nodeHostPort", getNodeHostPortForNodeAt(bdbPort));
+ _testcase.setConfigurationProperty(_storeConfigKeyPrefix + "highAvailability.helperHostPort", getHelperHostPort());
+ }
+
+ public String getIpAddressOfBrokerHost()
+ {
+ String brokerHost = _testcase.getBroker().getHost();
+ try
+ {
+ return InetAddress.getByName(brokerHost).getHostAddress();
+ }
+ catch (UnknownHostException e)
+ {
+ throw new RuntimeException("Could not determine IP address of host : " + brokerHost, e);
+ }
+ }
+
+ private void collectConfig(final int brokerPortNumber, XMLConfiguration testConfiguration, XMLConfiguration testVirtualhosts)
+ {
+ _brokerConfigurations.put(brokerPortNumber, new BrokerConfigHolder((XMLConfiguration) testConfiguration.clone(),
+ (XMLConfiguration) testVirtualhosts.clone()));
+ }
+
+ public class BrokerConfigHolder
+ {
+ private final XMLConfiguration _testConfiguration;
+ private final XMLConfiguration _testVirtualhosts;
+
+ public BrokerConfigHolder(XMLConfiguration testConfiguration, XMLConfiguration testVirtualhosts)
+ {
+ _testConfiguration = testConfiguration;
+ _testVirtualhosts = testVirtualhosts;
+ }
+
+ public XMLConfiguration getTestConfiguration()
+ {
+ return _testConfiguration;
+ }
+
+ public XMLConfiguration getTestVirtualhosts()
+ {
+ return _testVirtualhosts;
+ }
+ }
+
+ public void modifyClusterNodeBdbAddress(int brokerPortNumberToBeMoved, int newBdbPort)
+ {
+ final BrokerConfigHolder brokerConfigHolder = _brokerConfigurations.get(brokerPortNumberToBeMoved);
+ final XMLConfiguration virtualHostConfig = brokerConfigHolder.getTestVirtualhosts();
+
+ final String configKey = getConfigKey("highAvailability.nodeHostPort");
+ final String oldBdbHostPort = virtualHostConfig.getString(configKey);
+
+ final String[] oldHostAndPort = StringUtils.split(oldBdbHostPort, ":");
+ final String oldHost = oldHostAndPort[0];
+
+ final String newBdbHostPort = oldHost + ":" + newBdbPort;
+
+ virtualHostConfig.setProperty(configKey, newBdbHostPort);
+ collectConfig(brokerPortNumberToBeMoved, brokerConfigHolder.getTestConfiguration(), virtualHostConfig);
+ }
+
+ public String getStoreConfigKeyPrefix()
+ {
+ return _storeConfigKeyPrefix;
+ }
+
+
+}
diff --git a/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/tuple/ConfiguredObjectBindingTest.java b/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/tuple/ConfiguredObjectBindingTest.java
index f8aeb7f7b0..7f93f5691e 100644
--- a/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/tuple/ConfiguredObjectBindingTest.java
+++ b/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/tuple/ConfiguredObjectBindingTest.java
@@ -42,7 +42,7 @@ public class ConfiguredObjectBindingTest extends TestCase
{
super.setUp();
_configuredObjectBinding = ConfiguredObjectBinding.getInstance();
- _object = new ConfiguredObjectRecord(UUIDGenerator.generateUUID(), DUMMY_TYPE_STRING, DUMMY_ATTRIBUTES_STRING);
+ _object = new ConfiguredObjectRecord(UUIDGenerator.generateRandomUUID(), DUMMY_TYPE_STRING, DUMMY_ATTRIBUTES_STRING);
}
public void testObjectToEntryAndEntryToObject()
diff --git a/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/AbstractUpgradeTestCase.java b/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/AbstractUpgradeTestCase.java
index 36991b90d0..cd2654f79f 100644
--- a/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/AbstractUpgradeTestCase.java
+++ b/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/AbstractUpgradeTestCase.java
@@ -52,8 +52,8 @@ public abstract class AbstractUpgradeTestCase extends QpidTestCase
}
public static final String[] QUEUE_NAMES = { "clientid:myDurSubName", "clientid:mySelectorDurSubName", "myUpgradeQueue",
- "queue-non-durable" };
- public static int[] QUEUE_SIZES = { 1, 1, 10, 3 };
+ "queue-non-durable", "nonexclusive-with-erroneous-owner" };
+ public static int[] QUEUE_SIZES = { 1, 1, 10, 3, 0};
public static int TOTAL_MESSAGE_NUMBER = 15;
protected static final LogSubject LOG_SUBJECT = new TestBlankSubject();
diff --git a/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom4to5Test.java b/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom4to5Test.java
index 3f9e4e4aa1..65a8bb03fb 100644
--- a/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom4to5Test.java
+++ b/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom4to5Test.java
@@ -23,10 +23,13 @@ package org.apache.qpid.server.store.berkeleydb.upgrade;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
+import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicReference;
import org.apache.qpid.common.AMQPFilterTypes;
import org.apache.qpid.framing.AMQShortString;
@@ -49,6 +52,7 @@ public class UpgradeFrom4to5Test extends AbstractUpgradeTestCase
{
private static final String NON_DURABLE_QUEUE = BDBStoreUpgradeTestPreparer.NON_DURABLE_QUEUE_NAME;
private static final String DURABLE_QUEUE = BDBStoreUpgradeTestPreparer.QUEUE_NAME;
+ private static final String NON_EXCLUSIVE_WITH_ERRONEOUS_OWNER = "nonexclusive-with-erroneous-owner";
private static final String DURABLE_SUBSCRIPTION_QUEUE_WITH_SELECTOR = "clientid:mySelectorDurSubName";
private static final String DURABLE_SUBSCRIPTION_QUEUE = "clientid:myDurSubName";
private static final String EXCHANGE_DB_NAME = "exchangeDb_v5";
@@ -87,6 +91,10 @@ public class UpgradeFrom4to5Test extends AbstractUpgradeTestCase
BDBStoreUpgradeTestPreparer.SELECTOR_TOPIC_NAME, "testprop='true'");
assertBindingRecord(queueBindings, DURABLE_QUEUE, "amq.direct", DURABLE_QUEUE, null);
assertBindingRecord(queueBindings, NON_DURABLE_QUEUE, "amq.direct", NON_DURABLE_QUEUE, null);
+ assertBindingRecord(queueBindings, NON_EXCLUSIVE_WITH_ERRONEOUS_OWNER, "amq.direct", NON_EXCLUSIVE_WITH_ERRONEOUS_OWNER, null);
+
+ assertQueueHasOwner(NON_EXCLUSIVE_WITH_ERRONEOUS_OWNER, "misused-owner-as-description");
+
assertContent();
}
@@ -94,7 +102,7 @@ public class UpgradeFrom4to5Test extends AbstractUpgradeTestCase
{
UpgradeFrom4To5 upgrade = new UpgradeFrom4To5();
upgrade.performUpgrade(_environment, new StaticAnswerHandler(UpgradeInteractionResponse.NO), getVirtualHostName());
- assertQueues(new HashSet<String>(Arrays.asList(DURABLE_SUBSCRIPTION_QUEUE, DURABLE_SUBSCRIPTION_QUEUE_WITH_SELECTOR, DURABLE_QUEUE)));
+ assertQueues(new HashSet<String>(Arrays.asList(DURABLE_SUBSCRIPTION_QUEUE, DURABLE_SUBSCRIPTION_QUEUE_WITH_SELECTOR, DURABLE_QUEUE, NON_EXCLUSIVE_WITH_ERRONEOUS_OWNER)));
assertDatabaseRecordCount(DELIVERY_DB_NAME, 12);
assertDatabaseRecordCount(MESSAGE_META_DATA_DB_NAME, 12);
@@ -112,6 +120,9 @@ public class UpgradeFrom4to5Test extends AbstractUpgradeTestCase
assertBindingRecord(queueBindings, DURABLE_SUBSCRIPTION_QUEUE_WITH_SELECTOR, "amq.topic",
BDBStoreUpgradeTestPreparer.SELECTOR_TOPIC_NAME, "testprop='true'");
assertBindingRecord(queueBindings, DURABLE_QUEUE, "amq.direct", DURABLE_QUEUE, null);
+
+ assertQueueHasOwner(NON_EXCLUSIVE_WITH_ERRONEOUS_OWNER, "misused-owner-as-description");
+
assertContent();
}
@@ -257,7 +268,7 @@ public class UpgradeFrom4to5Test extends AbstractUpgradeTestCase
private void assertQueues(Set<String> expectedQueueNames)
{
- List<AMQShortString> durableSubNames = new ArrayList<AMQShortString>();
+ List<AMQShortString> durableSubNames = Collections.emptyList();
final UpgradeFrom4To5.QueueRecordBinding binding = new UpgradeFrom4To5.QueueRecordBinding(durableSubNames);
final Set<String> actualQueueNames = new HashSet<String>();
@@ -278,6 +289,35 @@ public class UpgradeFrom4to5Test extends AbstractUpgradeTestCase
assertEquals("Unexpected queue names", expectedQueueNames, actualQueueNames);
}
+ private void assertQueueHasOwner(String queueName, final String expectedOwner)
+ {
+ List<AMQShortString> durableSubNames = Collections.emptyList();
+ final UpgradeFrom4To5.QueueRecordBinding binding = new UpgradeFrom4To5.QueueRecordBinding(durableSubNames);
+ final AtomicReference<String> actualOwner = new AtomicReference<String>();
+ final AtomicBoolean foundQueue = new AtomicBoolean(false);
+
+ CursorOperation queueNameCollector = new CursorOperation()
+ {
+
+ @Override
+ public void processEntry(Database sourceDatabase, Database targetDatabase, Transaction transaction,
+ DatabaseEntry key, DatabaseEntry value)
+ {
+ QueueRecord record = binding.entryToObject(value);
+ String queueName = record.getNameShortString().asString();
+ if (queueName.equals(queueName))
+ {
+ foundQueue.set(true);
+ actualOwner.set(AMQShortString.toString(record.getOwner()));
+ }
+ }
+ };
+ new DatabaseTemplate(_environment, "queueDb_v5", null).run(queueNameCollector);
+
+ assertTrue("Could not find queue in database", foundQueue.get());
+ assertEquals("Queue has unexpected owner", expectedOwner, actualOwner.get());
+ }
+
private void assertContent()
{
final UpgradeFrom4To5.ContentBinding contentBinding = new UpgradeFrom4To5.ContentBinding();
diff --git a/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom5To6Test.java b/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom5To6Test.java
index 5297692820..2d2a6b20a2 100644
--- a/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom5To6Test.java
+++ b/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom5To6Test.java
@@ -29,8 +29,11 @@ import static org.apache.qpid.server.store.berkeleydb.upgrade.UpgradeFrom5To6.OL
import static org.apache.qpid.server.store.berkeleydb.upgrade.UpgradeFrom5To6.OLD_XID_DB_NAME;
import java.io.File;
+import java.util.ArrayList;
+import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
@@ -41,6 +44,7 @@ import org.apache.qpid.server.model.Binding;
import org.apache.qpid.server.model.Exchange;
import org.apache.qpid.server.model.Queue;
import org.apache.qpid.server.model.UUIDGenerator;
+import org.apache.qpid.server.queue.AMQQueueFactory;
import org.apache.qpid.server.store.berkeleydb.entry.Xid;
import org.apache.qpid.server.store.berkeleydb.tuple.XidBinding;
import org.apache.qpid.server.store.berkeleydb.upgrade.UpgradeFrom5To6.CompoundKey;
@@ -163,11 +167,11 @@ public class UpgradeFrom5To6Test extends AbstractUpgradeTestCase
NewRecordImpl[] newDequeues = newTransaction.getDequeues();
assertEquals("Unxpected new enqueus number", 1, newEnqueues.length);
NewRecordImpl enqueue = newEnqueues[0];
- assertEquals("Unxpected queue id", UUIDGenerator.generateUUID("TEST1", getVirtualHostName()), enqueue.getId());
+ assertEquals("Unxpected queue id", UUIDGenerator.generateQueueUUID("TEST1", getVirtualHostName()), enqueue.getId());
assertEquals("Unxpected message id", 1, enqueue.getMessageNumber());
assertEquals("Unxpected new dequeues number", 1, newDequeues.length);
NewRecordImpl dequeue = newDequeues[0];
- assertEquals("Unxpected queue id", UUIDGenerator.generateUUID("TEST2", getVirtualHostName()), dequeue.getId());
+ assertEquals("Unxpected queue id", UUIDGenerator.generateQueueUUID("TEST2", getVirtualHostName()), dequeue.getId());
assertEquals("Unxpected message id", 2, dequeue.getMessageNumber());
}
@@ -260,7 +264,7 @@ public class UpgradeFrom5To6Test extends AbstractUpgradeTestCase
private void assertDatabaseRecordCounts()
{
- assertDatabaseRecordCount(CONFIGURED_OBJECTS_DB_NAME, 9);
+ assertDatabaseRecordCount(CONFIGURED_OBJECTS_DB_NAME, 12);
assertDatabaseRecordCount(NEW_DELIVERY_DB_NAME, 12);
assertDatabaseRecordCount(NEW_METADATA_DB_NAME, 12);
@@ -270,64 +274,27 @@ public class UpgradeFrom5To6Test extends AbstractUpgradeTestCase
private void assertConfiguredObjects()
{
Map<UUID, UpgradeConfiguredObjectRecord> configuredObjects = loadConfiguredObjects();
- assertEquals("Unexpected number of configured objects", 9, configuredObjects.size());
-
- Set<Map<String, Object>> expected = new HashSet<Map<String, Object>>(9);
- Map<String, Object> queue1 = new HashMap<String, Object>();
- queue1.put("exclusive", Boolean.FALSE);
- queue1.put("name", "myUpgradeQueue");
- queue1.put("owner", null);
- expected.add(queue1);
- Map<String, Object> queue2 = new HashMap<String, Object>();
- queue2.put("exclusive", Boolean.TRUE);
- queue2.put("name", "clientid:mySelectorDurSubName");
- queue2.put("owner", "clientid");
- expected.add(queue2);
- Map<String, Object> queue3 = new HashMap<String, Object>();
- queue3.put("exclusive", Boolean.TRUE);
- queue3.put("name", "clientid:myDurSubName");
- queue3.put("owner", "clientid");
- expected.add(queue3);
-
- Map<String, Object> queueBinding1 = new HashMap<String, Object>();
- queueBinding1.put("queue", UUIDGenerator.generateUUID("myUpgradeQueue", getVirtualHostName()).toString());
- queueBinding1.put("name", "myUpgradeQueue");
- queueBinding1.put("exchange", UUIDGenerator.generateUUID("<<default>>", getVirtualHostName()).toString());
- expected.add(queueBinding1);
- Map<String, Object> queueBinding2 = new HashMap<String, Object>();
- queueBinding2.put("queue", UUIDGenerator.generateUUID("myUpgradeQueue", getVirtualHostName()).toString());
- queueBinding2.put("name", "myUpgradeQueue");
- queueBinding2.put("exchange", UUIDGenerator.generateUUID("amq.direct", getVirtualHostName()).toString());
- Map<String, Object> arguments2 = new HashMap<String, Object>();
- arguments2.put("x-filter-jms-selector", "");
- queueBinding2.put("arguments", arguments2);
- expected.add(queueBinding2);
- Map<String, Object> queueBinding3 = new HashMap<String, Object>();
- queueBinding3.put("queue", UUIDGenerator.generateUUID("clientid:myDurSubName", getVirtualHostName()).toString());
- queueBinding3.put("name", "myUpgradeTopic");
- queueBinding3.put("exchange", UUIDGenerator.generateUUID("amq.topic", getVirtualHostName()).toString());
- Map<String, Object> arguments3 = new HashMap<String, Object>();
- arguments3.put("x-filter-jms-selector", "");
- queueBinding3.put("arguments", arguments3);
- expected.add(queueBinding3);
- Map<String, Object> queueBinding4 = new HashMap<String, Object>();
- queueBinding4.put("queue", UUIDGenerator.generateUUID("clientid:mySelectorDurSubName", getVirtualHostName()).toString());
- queueBinding4.put("name", "mySelectorUpgradeTopic");
- queueBinding4.put("exchange", UUIDGenerator.generateUUID("amq.topic", getVirtualHostName()).toString());
- Map<String, Object> arguments4 = new HashMap<String, Object>();
- arguments4.put("x-filter-jms-selector", "testprop='true'");
- queueBinding4.put("arguments", arguments4);
- expected.add(queueBinding4);
- Map<String, Object> queueBinding5 = new HashMap<String, Object>();
- queueBinding5.put("queue", UUIDGenerator.generateUUID("clientid:myDurSubName", getVirtualHostName()).toString());
- queueBinding5.put("name", "clientid:myDurSubName");
- queueBinding5.put("exchange", UUIDGenerator.generateUUID("<<default>>", getVirtualHostName()).toString());
- expected.add(queueBinding5);
- Map<String, Object> queueBinding6 = new HashMap<String, Object>();
- queueBinding6.put("queue", UUIDGenerator.generateUUID("clientid:mySelectorDurSubName", getVirtualHostName()).toString());
- queueBinding6.put("name", "clientid:mySelectorDurSubName");
- queueBinding6.put("exchange", UUIDGenerator.generateUUID("<<default>>", getVirtualHostName()).toString());
- expected.add(queueBinding6);
+ assertEquals("Unexpected number of configured objects", 12, configuredObjects.size());
+
+ Set<Map<String, Object>> expected = new HashSet<Map<String, Object>>(12);
+ List<UUID> expectedBindingIDs = new ArrayList<UUID>();
+
+ expected.add(createExpectedQueueMap("myUpgradeQueue", Boolean.FALSE, null, null));
+ expected.add(createExpectedQueueMap("clientid:mySelectorDurSubName", Boolean.TRUE, "clientid", null));
+ expected.add(createExpectedQueueMap("clientid:myDurSubName", Boolean.TRUE, "clientid", null));
+ expected.add(createExpectedQueueMap("nonexclusive-with-erroneous-owner", Boolean.FALSE, null,
+ Collections.singletonMap(AMQQueueFactory.X_QPID_DESCRIPTION, "misused-owner-as-description")));
+
+ expected.add(createExpectedQueueBindingMapAndID("myUpgradeQueue","myUpgradeQueue", "<<default>>", null, expectedBindingIDs));
+ expected.add(createExpectedQueueBindingMapAndID("myUpgradeQueue", "myUpgradeQueue", "amq.direct", null, expectedBindingIDs));
+ expected.add(createExpectedQueueBindingMapAndID("clientid:myDurSubName", "myUpgradeTopic", "amq.topic",
+ Collections.singletonMap("x-filter-jms-selector", ""), expectedBindingIDs));
+ expected.add(createExpectedQueueBindingMapAndID("clientid:mySelectorDurSubName", "mySelectorUpgradeTopic", "amq.topic",
+ Collections.singletonMap("x-filter-jms-selector", "testprop='true'"), expectedBindingIDs));
+ expected.add(createExpectedQueueBindingMapAndID("clientid:myDurSubName", "clientid:myDurSubName", "<<default>>", null, expectedBindingIDs));
+ expected.add(createExpectedQueueBindingMapAndID("clientid:mySelectorDurSubName", "clientid:mySelectorDurSubName", "<<default>>", null, expectedBindingIDs));
+ expected.add(createExpectedQueueBindingMapAndID("nonexclusive-with-erroneous-owner", "nonexclusive-with-erroneous-owner", "amq.direct", null, expectedBindingIDs));
+ expected.add(createExpectedQueueBindingMapAndID("nonexclusive-with-erroneous-owner","nonexclusive-with-erroneous-owner", "<<default>>", null, expectedBindingIDs));
Set<String> expectedTypes = new HashSet<String>();
expectedTypes.add(Queue.class.getName());
@@ -337,21 +304,63 @@ public class UpgradeFrom5To6Test extends AbstractUpgradeTestCase
for (Entry<UUID, UpgradeConfiguredObjectRecord> entry : configuredObjects.entrySet())
{
UpgradeConfiguredObjectRecord object = entry.getValue();
- UUID key = entry.getKey();
Map<String, Object> deserialized = jsonSerializer.deserialize(object.getAttributes());
assertTrue("Unexpected entry:" + object.getAttributes(), expected.remove(deserialized));
String type = object.getType();
assertTrue("Unexpected type:" + type, expectedTypes.contains(type));
- if (type.equals(Exchange.class.getName()) || type.equals(Queue.class.getName()))
+ UUID key = entry.getKey();
+
+ assertNotNull("Key cannot be null", key);
+
+ if (type.equals(Exchange.class.getName()))
+ {
+ String exchangeName = (String) deserialized.get(Exchange.NAME);
+ assertNotNull(exchangeName);
+ assertEquals("Unexpected key", key, UUIDGenerator.generateExchangeUUID(exchangeName, getVirtualHostName()));
+ }
+ else if (type.equals(Queue.class.getName()))
{
- assertEquals("Unexpected key", key, UUIDGenerator.generateUUID(((String) deserialized.get("name")), getVirtualHostName()));
+ String queueName = (String) deserialized.get(Queue.NAME);
+ assertNotNull(queueName);
+ assertEquals("Unexpected key", key, UUIDGenerator.generateQueueUUID(queueName, getVirtualHostName()));
}
- else
+ else if (type.equals(Binding.class.getName()))
{
- assertNotNull("Key cannot be null", key);
+ assertTrue("unexpected binding id", expectedBindingIDs.remove(key));
}
}
+
assertTrue("Not all expected configured objects found:" + expected, expected.isEmpty());
+ assertTrue("Not all expected bindings found:" + expectedBindingIDs, expectedBindingIDs.isEmpty());
+ }
+
+ private Map<String, Object> createExpectedQueueBindingMapAndID(String queue, String bindingName, String exchangeName, Map<String, String> argumentMap, List<UUID> expectedBindingIDs)
+ {
+ Map<String, Object> expectedQueueBinding = new HashMap<String, Object>();
+ expectedQueueBinding.put(Binding.QUEUE, UUIDGenerator.generateQueueUUID(queue, getVirtualHostName()).toString());
+ expectedQueueBinding.put(Binding.NAME, bindingName);
+ expectedQueueBinding.put(Binding.EXCHANGE, UUIDGenerator.generateExchangeUUID(exchangeName, getVirtualHostName()).toString());
+ if (argumentMap != null)
+ {
+ expectedQueueBinding.put(Binding.ARGUMENTS, argumentMap);
+ }
+
+ expectedBindingIDs.add(UUIDGenerator.generateBindingUUID(exchangeName, queue, bindingName, getVirtualHostName()));
+
+ return expectedQueueBinding;
+ }
+
+ private Map<String, Object> createExpectedQueueMap(String name, boolean exclusiveFlag, String owner, Map<String, String> argumentMap)
+ {
+ Map<String, Object> expectedQueueEntry = new HashMap<String, Object>();
+ expectedQueueEntry.put(Queue.NAME, name);
+ expectedQueueEntry.put(Queue.EXCLUSIVE, exclusiveFlag);
+ expectedQueueEntry.put(Queue.OWNER, owner);
+ if (argumentMap != null)
+ {
+ expectedQueueEntry.put(Queue.ARGUMENTS, argumentMap);
+ }
+ return expectedQueueEntry;
}
private Map<UUID, UpgradeConfiguredObjectRecord> loadConfiguredObjects()
diff --git a/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgraderTest.java b/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgraderTest.java
index ba5ca842bf..23fd9bc24f 100644
--- a/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgraderTest.java
+++ b/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgraderTest.java
@@ -24,7 +24,7 @@ import java.io.File;
import java.util.ArrayList;
import java.util.List;
-import org.apache.qpid.server.store.berkeleydb.BDBMessageStore;
+import org.apache.qpid.server.store.berkeleydb.AbstractBDBMessageStore;
import org.apache.qpid.server.store.berkeleydb.tuple.ContentBinding;
import com.sleepycat.bind.tuple.IntegerBinding;
@@ -94,7 +94,7 @@ public class UpgraderTest extends AbstractUpgradeTestCase
{
assertEquals("Unexpected store version", -1, getStoreVersion());
_upgrader.upgradeIfNecessary();
- assertEquals("Unexpected store version", BDBMessageStore.VERSION, getStoreVersion());
+ assertEquals("Unexpected store version", AbstractBDBMessageStore.VERSION, getStoreVersion());
assertContent();
}
@@ -112,7 +112,7 @@ public class UpgraderTest extends AbstractUpgradeTestCase
List<String> expectedDatabases = new ArrayList<String>();
expectedDatabases.add(Upgrader.VERSION_DB_NAME);
assertEquals("Expectedonly VERSION table in initially empty store after upgrade: ", expectedDatabases, databaseNames);
- assertEquals("Unexpected store version", BDBMessageStore.VERSION, getStoreVersion());
+ assertEquals("Unexpected store version", AbstractBDBMessageStore.VERSION, getStoreVersion());
nonExistentStoreLocation.delete();
}
diff --git a/java/bdbstore/src/test/resources/upgrade/bdbstore-v4/test-store/00000000.jdb b/java/bdbstore/src/test/resources/upgrade/bdbstore-v4/test-store/00000000.jdb
index 167ab7f0ca..f5ed9aa5a2 100644
--- a/java/bdbstore/src/test/resources/upgrade/bdbstore-v4/test-store/00000000.jdb
+++ b/java/bdbstore/src/test/resources/upgrade/bdbstore-v4/test-store/00000000.jdb
Binary files differ
diff --git a/java/bdbstore/src/test/resources/upgrade/bdbstore-v5/test-store/00000000.jdb b/java/bdbstore/src/test/resources/upgrade/bdbstore-v5/test-store/00000000.jdb
index d44b21a83e..f5ed9aa5a2 100644
--- a/java/bdbstore/src/test/resources/upgrade/bdbstore-v5/test-store/00000000.jdb
+++ b/java/bdbstore/src/test/resources/upgrade/bdbstore-v5/test-store/00000000.jdb
Binary files differ
diff --git a/java/bdbstore/src/test/resources/upgrade/bdbstore-v5/test-store/00000001.jdb b/java/bdbstore/src/test/resources/upgrade/bdbstore-v5/test-store/00000001.jdb
index 9b85860c19..d5ae8c1096 100644
--- a/java/bdbstore/src/test/resources/upgrade/bdbstore-v5/test-store/00000001.jdb
+++ b/java/bdbstore/src/test/resources/upgrade/bdbstore-v5/test-store/00000001.jdb
Binary files differ
diff --git a/java/broker-plugins/access-control/MANIFEST.MF b/java/broker-plugins/access-control/MANIFEST.MF
index 78072850e4..a8fb99995e 100644
--- a/java/broker-plugins/access-control/MANIFEST.MF
+++ b/java/broker-plugins/access-control/MANIFEST.MF
@@ -13,12 +13,10 @@ Bundle-ActivationPolicy: lazy
Import-Package: org.apache.qpid,
org.apache.qpid.exchange,
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.logging,
org.apache.qpid.server.logging.actors,
org.apache.qpid.server.logging.subjects,
diff --git a/java/broker-plugins/access-control/build.xml b/java/broker-plugins/access-control/build.xml
index 89f8240fd5..df3346788c 100644
--- a/java/broker-plugins/access-control/build.xml
+++ b/java/broker-plugins/access-control/build.xml
@@ -17,15 +17,20 @@
- under the License.
-->
<project name="Qpid Broker-Plugins Access Control" default="build">
- <property name="module.depends" value="common broker broker-plugins" />
+ <property name="module.depends" value="common broker" />
<property name="module.test.depends" value="test common/test broker/test management/common systests" />
<property name="module.manifest" value="MANIFEST.MF" />
<property name="module.plugin" value="true" />
+ <property name="module.genpom" value="true"/>
+ <property name="module.genpom.args" value="-Sqpid-common=provided -Sqpid-broker=provided"/>
+
+ <property name="broker-plugins-access-control.libs" value=""/>
<import file="../../module.xml" />
<target name="bundle" depends="bundle-tasks"/>
<target name="precompile" depends="gen_logging"/>
+
</project>
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
index 25f903e860..c2282694fb 100644
--- 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
@@ -38,7 +38,7 @@ import org.apache.qpid.server.security.access.config.RuleSet;
/**
* 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.
*/
@@ -48,7 +48,7 @@ public class PlainConfigurationTest extends TestCase
{
File acl = File.createTempFile(getClass().getName() + getName(), "acl");
acl.deleteOnExit();
-
+
// Write ACL file
PrintWriter aclWriter = new PrintWriter(new FileWriter(acl));
for (String line : aclData)
@@ -70,14 +70,13 @@ public class PlainConfigurationTest extends TestCase
// 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());
}
}
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 4d46a32f45..f7cc60543d 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
@@ -40,12 +40,12 @@ import org.apache.qpid.test.utils.QpidTestCase;
/**
* This test checks that the {@link RuleSet} object which forms the core of the access control plugin performs correctly.
- *
+ *
* 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).
@@ -82,11 +82,11 @@ public class RuleSetTest extends QpidTestCase
{
assertDenyGrantAllow(subject, operation, objectType, ObjectProperties.EMPTY);
}
-
+
public void assertDenyGrantAllow(Subject subject, Operation operation, ObjectType objectType, ObjectProperties properties)
{
- final Principal identity = UsernamePrincipal.getUsernamePrincipalFromSubject(subject);
-
+ final Principal identity = subject.getPrincipals().iterator().next();
+
assertEquals(Result.DENIED, _ruleSet.check(subject, operation, objectType, properties));
_ruleSet.grant(0, identity.getName(), Permission.ALLOW, operation, objectType, properties);
assertEquals(1, _ruleSet.getRuleCount());
@@ -99,7 +99,7 @@ public class RuleSetTest extends QpidTestCase
assertEquals(_ruleSet.getRuleCount(), 0);
assertEquals(_ruleSet.getDefault(), _ruleSet.check(_testSubject, Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY));
}
-
+
public void testVirtualHostAccess() throws Exception
{
assertDenyGrantAllow(_testSubject, Operation.ACCESS, ObjectType.VIRTUALHOST);
@@ -114,7 +114,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);
}
@@ -122,7 +122,7 @@ public class RuleSetTest extends QpidTestCase
{
ObjectProperties properties = new ObjectProperties(_exchangeName);
properties.put(ObjectProperties.Property.TYPE, _exchangeType.asString());
-
+
assertDenyGrantAllow(_testSubject, Operation.CREATE, ObjectType.EXCHANGE, properties);
}
@@ -144,15 +144,15 @@ public class RuleSetTest extends QpidTestCase
{
ObjectProperties temporary = new ObjectProperties();
temporary.put(ObjectProperties.Property.AUTO_DELETE, Boolean.TRUE);
-
+
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(1, _ruleSet.getRuleCount());
assertEquals(Result.ALLOWED, _ruleSet.check(_testSubject, 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));
}
@@ -164,17 +164,17 @@ public class RuleSetTest extends QpidTestCase
{
ObjectProperties temporary = new ObjectProperties(_queueName);
temporary.put(ObjectProperties.Property.AUTO_DELETE, Boolean.TRUE);
-
+
ObjectProperties normal = new ObjectProperties(_queueName);
normal.put(ObjectProperties.Property.AUTO_DELETE, Boolean.FALSE);
-
+
assertEquals(Result.DENIED, _ruleSet.check(_testSubject, 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);
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));
}
@@ -186,17 +186,17 @@ public class RuleSetTest extends QpidTestCase
{
ObjectProperties temporary = new ObjectProperties(_queueName);
temporary.put(ObjectProperties.Property.AUTO_DELETE, Boolean.TRUE);
-
+
ObjectProperties normal = new ObjectProperties(_queueName);
normal.put(ObjectProperties.Property.AUTO_DELETE, Boolean.FALSE);
-
+
assertEquals(Result.DENIED, _ruleSet.check(_testSubject, 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);
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));
}
@@ -204,7 +204,7 @@ public class RuleSetTest extends QpidTestCase
/*
* Test different rules for temporary queues.
*/
-
+
/**
* The more generic rule first is used, so both requests are allowed.
*/
@@ -213,18 +213,18 @@ public class RuleSetTest extends QpidTestCase
ObjectProperties named = new ObjectProperties(_queueName);
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));
_ruleSet.grant(1, TEST_USER, Permission.ALLOW, Operation.CREATE, ObjectType.QUEUE, named);
_ruleSet.grant(2, TEST_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));
}
-
+
/**
* The more specific rule is first, so those requests are denied.
*/
@@ -233,18 +233,18 @@ public class RuleSetTest extends QpidTestCase
ObjectProperties named = new ObjectProperties(_queueName);
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));
_ruleSet.grant(1, TEST_USER, Permission.DENY, Operation.CREATE, ObjectType.QUEUE, namedTemporary);
_ruleSet.grant(2, TEST_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));
}
-
+
/**
* The more specific rules are first, so those requests are denied.
*/
@@ -255,7 +255,7 @@ public class RuleSetTest extends QpidTestCase
namedTemporary.put(ObjectProperties.Property.AUTO_DELETE, Boolean.TRUE);
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));
@@ -264,48 +264,48 @@ public class RuleSetTest extends QpidTestCase
_ruleSet.grant(2, TEST_USER, Permission.DENY, Operation.CREATE, ObjectType.QUEUE, namedDurable);
_ruleSet.grant(3, TEST_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));
}
-
+
public void testNamedTemporaryQueueAllowed()
{
ObjectProperties named = new ObjectProperties(_queueName);
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));
_ruleSet.grant(1, TEST_USER, Permission.ALLOW, Operation.CREATE, ObjectType.QUEUE, namedTemporary);
_ruleSet.grant(2, TEST_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));
}
-
+
public void testNamedTemporaryQueueDeniedAllowed()
{
ObjectProperties named = new ObjectProperties(_queueName);
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));
_ruleSet.grant(1, TEST_USER, Permission.ALLOW, Operation.CREATE, ObjectType.QUEUE, namedTemporary);
_ruleSet.grant(2, TEST_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.
+ /**
+ * Tests support for the {@link Rule#ALL} keyword.
*/
public void testAllowToAll()
{
@@ -316,13 +316,13 @@ public class RuleSetTest extends QpidTestCase
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"})));
-
+ 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());
@@ -331,14 +331,14 @@ public class RuleSetTest extends QpidTestCase
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"})));
-
+ 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());
@@ -346,7 +346,7 @@ public class RuleSetTest extends QpidTestCase
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()
@@ -358,7 +358,7 @@ public class RuleSetTest extends QpidTestCase
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
@@ -367,7 +367,7 @@ public class RuleSetTest extends QpidTestCase
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());
@@ -382,10 +382,10 @@ public class RuleSetTest extends QpidTestCase
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));
diff --git a/java/broker-plugins/experimental/shutdown/MANIFEST.MF b/java/broker-plugins/experimental/shutdown/MANIFEST.MF
deleted file mode 100644
index 0bd0a835e4..0000000000
--- a/java/broker-plugins/experimental/shutdown/MANIFEST.MF
+++ /dev/null
@@ -1,16 +0,0 @@
-Manifest-Version: 1.0
-Bundle-ManifestVersion: 2
-Bundle-Name: Experimental Shutdown
-Bundle-Description: Experimental Qpid Broker Shutdown Plugin
-Bundle-License: http://www.apache.org/licenses/LICENSE-2.0.txt
-Bundle-DocURL: http://qpid.apache.org/
-Bundle-SymbolicName: broker-plugins-experimental-shutdown;singleton:=true
-Bundle-Version: 1.0.0
-Bundle-Activator: org.apache.qpid.shutdown.Activator
-Import-Package: javax.management;resolution:=optional,
- org.apache.log4j,
- org.osgi.framework,
- org.apache.qpid.server.management
-Bundle-RequiredExecutionEnvironment: J2SE-1.5
-Bundle-ActivationPolicy: lazy
-
diff --git a/java/broker-plugins/experimental/shutdown/src/main/java/org/apache/qpid/shutdown/Activator.java b/java/broker-plugins/experimental/shutdown/src/main/java/org/apache/qpid/shutdown/Activator.java
deleted file mode 100644
index 2b7fa33784..0000000000
--- a/java/broker-plugins/experimental/shutdown/src/main/java/org/apache/qpid/shutdown/Activator.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.shutdown;
-
-
-import org.apache.log4j.Logger;
-import org.osgi.framework.BundleActivator;
-import org.osgi.framework.BundleContext;
-
-public class Activator implements BundleActivator
-{
- private static final Logger _logger = Logger.getLogger(Activator.class);
-
- private Shutdown _shutdown = null;
-
- /** @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext) */
- public void start(BundleContext ctx) throws Exception {
- _shutdown = new Shutdown();
- if (ctx != null)
- {
- ctx.registerService(ShutdownMBean.class.getName(), _shutdown, null);
- }
-
- _shutdown.register();
-
- _logger.info("Shutdown plugin MBean registered");
- }
-
- /** @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext) */
- public void stop(BundleContext ctx) throws Exception
- {
- if (_shutdown != null)
- {
- _shutdown.unregister();
- _shutdown = null;
- }
-
- _logger.info("Shutdown plugin MBean unregistered");
- }
-}
diff --git a/java/broker-plugins/extras/MANIFEST.MF b/java/broker-plugins/extras/MANIFEST.MF
deleted file mode 100644
index f4ef6e8178..0000000000
--- a/java/broker-plugins/extras/MANIFEST.MF
+++ /dev/null
@@ -1,21 +0,0 @@
-Bundle-ManifestVersion: 2
-Bundle-Name: Qpid Broker-Plugins Extras
-Bundle-SymbolicName: broker-plugins-extras
-Bundle-Description: Extra exchange types plugin for Qpid.
-Bundle-License: http://www.apache.org/licenses/LICENSE-2.0.txt
-Bundle-DocURL: http://www.apache.org/
-Bundle-Activator: org.apache.qpid.extras.Activator
-Private-Package: org.apache.qpid.extras,
- org.apache.qpid.extras.exchanges.diagnostic,
- org.apache.qpid.extras.exchanges.example
-Import-Package: org.apache.qpid,
- org.apache.qpid.framing,
- org.apache.qpid.junit.extensions.util,
- org.apache.qpid.protocol,
- org.apache.qpid.server.exchange,
- org.apache.qpid.server.management,
- org.apache.qpid.server.queue,
- org.apache.qpid.server.virtualhost,
- javax.management;version=1.0.0,
- javax.management.openmbean;version=1.0.0,
- org.osgi.framework;version=1.3
diff --git a/java/broker-plugins/extras/src/main/java/org/apache/qpid/extras/exchanges/diagnostic/DiagnosticExchange.java b/java/broker-plugins/extras/src/main/java/org/apache/qpid/extras/exchanges/diagnostic/DiagnosticExchange.java
deleted file mode 100644
index af56b50437..0000000000
--- a/java/broker-plugins/extras/src/main/java/org/apache/qpid/extras/exchanges/diagnostic/DiagnosticExchange.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.extras.exchanges.diagnostic;
-
-import org.apache.log4j.Logger;
-
-import org.apache.qpid.AMQException;
-import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpid.framing.FieldTable;
-import org.apache.qpid.management.common.mbeans.annotations.MBeanConstructor;
-import org.apache.qpid.management.common.mbeans.annotations.MBeanDescription;
-import org.apache.qpid.server.binding.Binding;
-import org.apache.qpid.server.exchange.AbstractExchange;
-import org.apache.qpid.server.exchange.AbstractExchangeMBean;
-import org.apache.qpid.server.exchange.ExchangeType;
-import org.apache.qpid.server.message.InboundMessage;
-import org.apache.qpid.server.queue.AMQQueue;
-import org.apache.qpid.server.virtualhost.VirtualHost;
-
-import javax.management.JMException;
-import javax.management.openmbean.OpenDataException;
-import javax.management.openmbean.TabularData;
-import java.util.ArrayList;
-import java.util.Map;
-import java.util.UUID;
-
-/**
- * This is a special diagnostic exchange type which doesn't actually do anything
- * with messages. When it receives a message, it writes information about the
- * current memory usage to the "memory" property of the message and places it on the
- * diagnosticqueue for retrieval
- */
-public class DiagnosticExchange extends AbstractExchange
-{
- private static final Logger _logger = Logger.getLogger(DiagnosticExchange.class);
-
- public static final AMQShortString DIAGNOSTIC_EXCHANGE_CLASS = new AMQShortString("x-diagnostic");
- public static final AMQShortString DIAGNOSTIC_EXCHANGE_NAME = new AMQShortString("diagnostic");
-
- /**
- * MBean class implementing the management interfaces.
- */
- @MBeanDescription("Management Bean for Diagnostic Exchange")
- private final class DiagnosticExchangeMBean extends AbstractExchangeMBean<DiagnosticExchange>
- {
- /**
- * Usual constructor.
- *
- * @throws JMException
- */
- @MBeanConstructor("Creates an MBean for AMQ Diagnostic exchange")
- public DiagnosticExchangeMBean() throws JMException
- {
- super(DiagnosticExchange.this);
-
- init();
- }
-
- /**
- * Returns nothing, there can be no tabular data for this...
- *
- * @throws OpenDataException
- * @returns null
- * TODO or can there? Could this actually return all the information in one easy to read table?
- */
- public TabularData bindings() throws OpenDataException
- {
- return null;
- }
-
- /**
- * This exchange type doesn't support queues, so this method does
- * nothing.
- *
- * @param queueName the queue you'll fail to create
- * @param binding the binding you'll fail to create
- * @throws JMException an exception that will never be thrown
- */
- @Override
- public void createNewBinding(String queueName, String binding) throws JMException
- {
- // No Op
- }
-
- /**
- * This exchange type doesn't support queues.
- *
- * @see #createNewBinding(String, String)
- */
- @Override
- public void removeBinding(String queueName, String binding) throws JMException
- {
- // No Op
- }
- }
-
-
- public static final ExchangeType<DiagnosticExchange> TYPE = new ExchangeType<DiagnosticExchange>()
- {
-
- public AMQShortString getName()
- {
- return DIAGNOSTIC_EXCHANGE_CLASS;
- }
-
- public Class<DiagnosticExchange> getExchangeClass()
- {
- return DiagnosticExchange.class;
- }
-
- public DiagnosticExchange newInstance(UUID id, VirtualHost host,
- AMQShortString name,
- boolean durable,
- int ticket,
- boolean autoDelete) throws AMQException
- {
- DiagnosticExchange exch = new DiagnosticExchange();
- exch.initialise(id, host,name,durable,ticket,autoDelete);
- return exch;
- }
-
- public AMQShortString getDefaultExchangeName()
- {
- return DIAGNOSTIC_EXCHANGE_NAME ;
- }
- };
-
- public DiagnosticExchange()
- {
- super(TYPE);
- }
-
- /**
- * Creates a new MBean instance
- *
- * @return the newly created MBean
- * @throws AMQException
- * if something goes wrong
- */
- protected AbstractExchangeMBean createMBean() throws JMException
- {
- return new DiagnosticExchange.DiagnosticExchangeMBean();
- }
-
- public void registerQueue(String routingKey, AMQQueue queue, Map<String, Object> args) throws AMQException
- {
- // No op
- }
-
-
- public boolean isBound(AMQShortString routingKey, AMQQueue queue)
- {
- return false;
- }
-
- public boolean isBound(AMQShortString routingKey)
- {
- return false;
- }
-
- public boolean isBound(AMQQueue queue)
- {
- return false;
- }
-
- public boolean hasBindings()
- {
- return false;
- }
-
- public ArrayList<AMQQueue> doRoute(InboundMessage payload)
- {
- //TODO shouldn't modify messages... perhaps put a new message on the queue?
- AMQQueue q = getQueueRegistry().getQueue(new AMQShortString("diagnosticqueue"));
- ArrayList<AMQQueue> queues = new ArrayList<AMQQueue>();
- queues.add(q);
- return queues;
- }
-
-
- public boolean isBound(AMQShortString routingKey, FieldTable arguments,
- AMQQueue queue) {
- // TODO Auto-generated method stub
- return false;
- }
-
- protected void onBind(final Binding binding)
- {
- // No op
- }
-
- protected void onUnbind(final Binding binding)
- {
- // No op
- }
-}
diff --git a/java/broker-plugins/extras/src/main/java/org/apache/qpid/extras/exchanges/diagnostic/DiagnosticExchangeType.java b/java/broker-plugins/extras/src/main/java/org/apache/qpid/extras/exchanges/diagnostic/DiagnosticExchangeType.java
deleted file mode 100644
index c0f325e42f..0000000000
--- a/java/broker-plugins/extras/src/main/java/org/apache/qpid/extras/exchanges/diagnostic/DiagnosticExchangeType.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.extras.exchanges.diagnostic;
-
-import java.util.UUID;
-
-import org.apache.qpid.AMQException;
-import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpid.server.exchange.ExchangeType;
-import org.apache.qpid.server.virtualhost.VirtualHost;
-
-/**
- * Exchange type class for getting hold of the exchange.
- */
-public final class DiagnosticExchangeType implements ExchangeType<DiagnosticExchange>
-{
-
- public AMQShortString getName()
- {
- return DiagnosticExchange.DIAGNOSTIC_EXCHANGE_CLASS;
- }
-
- public Class<DiagnosticExchange> getExchangeClass()
- {
- return DiagnosticExchange.class;
- }
-
- public DiagnosticExchange newInstance(UUID id, VirtualHost host, AMQShortString name, boolean durable, int ticket, boolean autoDelete)
- throws AMQException
- {
- DiagnosticExchange exch = new DiagnosticExchange();
- exch.initialise(id, host, name, durable, ticket, autoDelete);
- return exch;
- }
-
- public AMQShortString getDefaultExchangeName()
- {
- return DiagnosticExchange.DIAGNOSTIC_EXCHANGE_NAME;
- }
-}
diff --git a/java/broker-plugins/extras/src/main/java/org/apache/qpid/extras/exchanges/example/TestExchange.java b/java/broker-plugins/extras/src/main/java/org/apache/qpid/extras/exchanges/example/TestExchange.java
deleted file mode 100644
index 691f4c8d0b..0000000000
--- a/java/broker-plugins/extras/src/main/java/org/apache/qpid/extras/exchanges/example/TestExchange.java
+++ /dev/null
@@ -1,262 +0,0 @@
-package org.apache.qpid.extras.exchanges.example;
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT 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.AMQException;
-import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpid.framing.FieldTable;
-import org.apache.qpid.server.binding.Binding;
-import org.apache.qpid.server.configuration.ConfiguredObject;
-import org.apache.qpid.server.configuration.ExchangeConfigType;
-import org.apache.qpid.server.configuration.VirtualHostConfig;
-import org.apache.qpid.server.exchange.Exchange;
-import org.apache.qpid.server.exchange.ExchangeReferrer;
-import org.apache.qpid.server.exchange.ExchangeType;
-import org.apache.qpid.server.message.InboundMessage;
-import org.apache.qpid.server.queue.AMQQueue;
-import org.apache.qpid.server.queue.BaseQueue;
-import org.apache.qpid.server.virtualhost.VirtualHost;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Map;
-import java.util.UUID;
-
-public class TestExchange implements Exchange
-{
-
- public void close() throws AMQException
- {
- }
-
-
-
- public void addBindingListener(final BindingListener listener)
- {
- //To change body of implemented methods use File | Settings | File Templates.
- }
-
- public void removeBindingListener(final BindingListener listener)
- {
- //To change body of implemented methods use File | Settings | File Templates.
- }
-
- public AMQShortString getNameShortString()
- {
- return null;
- }
-
- public AMQShortString getTypeShortString()
- {
- return null;
- }
-
- public boolean hasBindings()
- {
- return false;
- }
-
- public boolean isBound(String bindingKey, AMQQueue queue)
- {
- return false;
- }
-
- public boolean isBound(String bindingKey, Map<String, Object> arguments, AMQQueue queue)
- {
- return false;
- }
-
- public boolean isBound(String bindingKey)
- {
- return false;
- }
-
- public void addCloseTask(final Task task)
- {
-
- }
-
- public void removeCloseTask(final Task task)
- {
-
- }
-
- public Exchange getAlternateExchange()
- {
- return null;
- }
-
- public Map<String, Object> getArguments()
- {
- return null; //To change body of implemented methods use File | Settings | File Templates.
- }
-
- public long getBindingCount()
- {
- return 0; //To change body of implemented methods use File | Settings | File Templates.
- }
-
- public long getBindingCountHigh()
- {
- return 0; //To change body of implemented methods use File | Settings | File Templates.
- }
-
- public long getMsgReceives()
- {
- return 0; //To change body of implemented methods use File | Settings | File Templates.
- }
-
- public long getMsgRoutes()
- {
- return 0; //To change body of implemented methods use File | Settings | File Templates.
- }
-
- public long getByteReceives()
- {
- return 0; //To change body of implemented methods use File | Settings | File Templates.
- }
-
- public long getByteRoutes()
- {
- return 0; //To change body of implemented methods use File | Settings | File Templates.
- }
-
- public long getCreateTime()
- {
- return 0; //To change body of implemented methods use File | Settings | File Templates.
- }
-
- public void setAlternateExchange(Exchange exchange)
- {
-
- }
-
- public void removeReference(ExchangeReferrer exchange)
- {
-
- }
-
- public void addReference(ExchangeReferrer exchange)
- {
-
- }
-
- public boolean hasReferrers()
- {
- return false;
- }
-
- public void addBinding(final Binding binding)
- {
-
- }
-
- public void removeBinding(final Binding binding)
- {
-
- }
-
- public Collection<Binding> getBindings()
- {
- return null; //To change body of implemented methods use File | Settings | File Templates.
- }
-
- public void initialise(VirtualHost host, AMQShortString name, boolean durable, boolean autoDelete)
- throws AMQException
- {
- }
-
- public VirtualHostConfig getVirtualHost()
- {
- return null; //To change body of implemented methods use File | Settings | File Templates.
- }
-
- public String getName()
- {
- return null; //To change body of implemented methods use File | Settings | File Templates.
- }
-
- public ExchangeType getType()
- {
- return null; //To change body of implemented methods use File | Settings | File Templates.
- }
-
- public boolean isAutoDelete()
- {
- return false;
- }
-
- public boolean isBound(AMQShortString routingKey, FieldTable arguments, AMQQueue queue)
- {
- return false;
- }
-
- public boolean isBound(AMQShortString routingKey, AMQQueue queue)
- {
- return false;
- }
-
- public boolean isBound(AMQShortString routingKey)
- {
- return false;
- }
-
- public boolean isBound(AMQQueue queue)
- {
- return false;
- }
-
- public UUID getId()
- {
- return null; //To change body of implemented methods use File | Settings | File Templates.
- }
-
- public ExchangeConfigType getConfigType()
- {
- return null; //To change body of implemented methods use File | Settings | File Templates.
- }
-
- public ConfiguredObject getParent()
- {
- return null; //To change body of implemented methods use File | Settings | File Templates.
- }
-
- public boolean isDurable()
- {
- return false;
- }
-
- public ArrayList<? extends BaseQueue> route(InboundMessage message)
- {
- return new ArrayList<AMQQueue>();
- }
-
- public int getTicket()
- {
- return 0;
- }
-
- public void initialise(UUID id, VirtualHost arg0, AMQShortString arg1, boolean arg2, int arg3, boolean arg4)
- throws AMQException
- {
- }
-}
diff --git a/java/broker-plugins/extras/src/main/java/org/apache/qpid/extras/exchanges/example/TestExchangeType.java b/java/broker-plugins/extras/src/main/java/org/apache/qpid/extras/exchanges/example/TestExchangeType.java
deleted file mode 100644
index 5c454b9d0e..0000000000
--- a/java/broker-plugins/extras/src/main/java/org/apache/qpid/extras/exchanges/example/TestExchangeType.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.extras.exchanges.example;
-
-import java.util.UUID;
-
-import org.apache.qpid.AMQException;
-import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpid.server.exchange.Exchange;
-import org.apache.qpid.server.exchange.ExchangeType;
-import org.apache.qpid.server.virtualhost.VirtualHost;
-
-public class TestExchangeType implements ExchangeType
-{
-
- public Class getExchangeClass()
- {
- return TestExchange.class;
- }
-
- public AMQShortString getName()
- {
- return null;
- }
-
- public Exchange newInstance(UUID id, VirtualHost host, AMQShortString name, boolean durable,
- int token, boolean autoDelete)
- throws AMQException
- {
- TestExchange ex = new TestExchange();
- ex.initialise(id, host, name, durable, token, autoDelete);
- return ex;
- }
-
- public AMQShortString getDefaultExchangeName()
- {
- return new AMQShortString("test.exchange");
- }
-
-}
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
deleted file mode 100644
index 458f9a1846..0000000000
--- a/java/broker-plugins/extras/src/test/java/org/apache/qpid/server/plugins/ExtrasTest.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.plugins;
-
-import junit.framework.TestCase;
-import org.apache.commons.configuration.PropertiesConfiguration;
-
-import org.apache.qpid.server.configuration.ServerConfiguration;
-import org.apache.qpid.server.exchange.ExchangeType;
-import org.apache.qpid.server.registry.ApplicationRegistry;
-import org.apache.qpid.server.registry.IApplicationRegistry;
-import org.apache.qpid.server.util.TestApplicationRegistry;
-
-import java.util.Map;
-
-public class ExtrasTest extends TestCase
-{
- private static final String TEST_EXCHANGE_CLASS = "org.apache.qpid.extras.exchanges.example.TestExchangeType";
-
- private static final String PLUGIN_DIRECTORY = System.getProperty("example.plugin.target");
- private static final String CACHE_DIRECTORY = System.getProperty("example.cache.target");
-
- private IApplicationRegistry _registry;
-
- @Override
- public void setUp() throws Exception
- {
- PropertiesConfiguration properties = new PropertiesConfiguration();
- properties.addProperty("plugin-directory", PLUGIN_DIRECTORY);
- properties.addProperty("cache-directory", CACHE_DIRECTORY);
- ServerConfiguration config = new ServerConfiguration(properties);
-
- // This Test requires an application Registry
- ApplicationRegistry.initialise(new TestApplicationRegistry(config));
- _registry = ApplicationRegistry.getInstance();
- }
-
- @Override
- public void tearDown() throws Exception
- {
- ApplicationRegistry.remove();
- }
-
- public void testLoadExchanges() throws Exception
- {
- PluginManager manager = _registry.getPluginManager();
- Map<String, ExchangeType<?>> exchanges = manager.getExchanges();
- assertNotNull("No exchanges found in " + PLUGIN_DIRECTORY, exchanges);
- assertEquals("Wrong number of exchanges found in " + PLUGIN_DIRECTORY, 2, exchanges.size());
- assertNotNull("Wrong exchange found in " + PLUGIN_DIRECTORY, exchanges.get(TEST_EXCHANGE_CLASS));
- }
-
- public void testNoExchanges() throws Exception
- {
- PluginManager manager = new PluginManager("/path/to/nowhere", "/tmp", null);
- Map<String, ExchangeType<?>> exchanges = manager.getExchanges();
- assertTrue("Exchanges found", exchanges.isEmpty());
- }
-}
diff --git a/java/broker-plugins/firewall/MANIFEST.MF b/java/broker-plugins/firewall/MANIFEST.MF
index 6ceea119da..a302921d03 100644
--- a/java/broker-plugins/firewall/MANIFEST.MF
+++ b/java/broker-plugins/firewall/MANIFEST.MF
@@ -12,12 +12,10 @@ 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,
diff --git a/java/broker-plugins/firewall/build.xml b/java/broker-plugins/firewall/build.xml
index 576435de7f..6ae6a35b89 100644
--- a/java/broker-plugins/firewall/build.xml
+++ b/java/broker-plugins/firewall/build.xml
@@ -17,13 +17,18 @@
- under the License.
-->
<project name="Qpid Broker-Plugins Firewall" default="build">
- <property name="module.depends" value="common broker broker-plugins" />
+ <property name="module.depends" value="common broker" />
<property name="module.test.depends" value="test broker/test common/test management/common" />
<property name="module.manifest" value="MANIFEST.MF" />
<property name="module.plugin" value="true" />
+ <property name="module.genpom" value="true"/>
+ <property name="module.genpom.args" value="-Sqpid-common=provided -Sqpid-broker=provided"/>
+
+ <property name="broker-plugins-firewall.libs" value=""/>
<import file="../../module.xml" />
<target name="bundle" depends="bundle-tasks" />
+
</project>
diff --git a/java/broker-plugins/management-http/MANIFEST.MF b/java/broker-plugins/management-http/MANIFEST.MF
new file mode 100644
index 0000000000..cca10d3f89
--- /dev/null
+++ b/java/broker-plugins/management-http/MANIFEST.MF
@@ -0,0 +1,70 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Qpid Broker-Plugins Management HTTP
+Bundle-SymbolicName: broker-plugins-management-http
+Bundle-Description: HTTP management 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.management.plugin.ManagementActivator
+Bundle-RequiredExecutionEnvironment: JavaSE-1.6
+Bundle-ClassPath: .
+Bundle-ActivationPolicy: lazy
+Import-Package: org.apache.qpid,
+ org.apache.qpid.framing,
+ org.apache.qpid.protocol,
+ org.apache.qpid.common,
+ org.apache.qpid.server.security.auth,
+ org.apache.qpid.server.security.auth.manager,
+ org.apache.qpid.server.security.auth.sasl,
+ org.apache.qpid.server.binding,
+ org.apache.qpid.server.exchange,
+ org.apache.qpid.server.logging,
+ org.apache.qpid.server.message,
+ org.apache.qpid.server.model,
+ org.apache.qpid.server.model.adapter,
+ org.apache.qpid.server.model.impl,
+ org.apache.qpid.server.configuration,
+ org.apache.qpid.server.configuration.plugins,
+ org.apache.qpid.server.connection,
+ org.apache.qpid.server.plugins,
+ org.apache.qpid.server.protocol,
+ org.apache.qpid.server.queue,
+ org.apache.qpid.server.subscription,
+ org.apache.qpid.server.registry,
+ org.apache.qpid.server.security,
+ org.apache.qpid.server.security.access,
+ org.apache.qpid.server.stats,
+ org.apache.qpid.server.virtualhost,
+ org.apache.qpid.util,
+ org.eclipse.jetty.server;version=7.6.3,
+ org.eclipse.jetty.server.session;version=7.6.3,
+ org.eclipse.jetty.server.ssl;version=7.6.3,
+ org.eclipse.jetty.server.nio;version=7.6.3,
+ org.eclipse.jetty.security;version=7.6.3,
+ org.eclipse.jetty.http;version=7.6.3,
+ org.eclipse.jetty.io;version=7.6.3,
+ org.eclipse.jetty.io.nio;version=7.6.3,
+ org.eclipse.jetty.servlet;version=7.6.3,
+ org.eclipse.jetty.util.ssl;version=7.6.3,
+ org.apache.commons.codec;version=1.3.0,
+ org.apache.commons.codec.binary;version=1.3.0,
+ 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,
+ org.codehaus.jackson;version=1.9.0,
+ org.codehaus.jackson.map;version=1.9.0,
+ javax.crypto,
+ javax.crypto.spec,
+ javax.security.auth,
+ javax.security.auth.callback,
+ javax.security.sasl,
+ javax.servlet,
+ javax.servlet.http,
+ 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.management.plugin.impl
+Export-Package: org.apache.qpid.server.management.plugin;uses:="org.osgi.framework"
diff --git a/java/broker-plugins/management-http/build.xml b/java/broker-plugins/management-http/build.xml
new file mode 100644
index 0000000000..b792cb292e
--- /dev/null
+++ b/java/broker-plugins/management-http/build.xml
@@ -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.
+ -->
+<project name="Qpid Broker-Plugins Management HTTP" default="build">
+
+ <condition property="systests.optional.depends" value="bdbstore" else="">
+ <or>
+ <and>
+ <contains string="${modules.opt}" substring="bdbstore"/>
+ <contains string="${profile}" substring="bdb"/>
+ </and>
+ <and>
+ <istrue value="${optional}"/>
+ <contains string="${profile}" substring="bdb"/>
+ </and>
+ </or>
+ </condition>
+
+ <property name="module.depends" value="common broker" />
+ <property name="module.test.depends" value="systests test broker/test common/test management/common client ${systests.optional.depends}" />
+
+ <property name="module.manifest" value="MANIFEST.MF" />
+ <property name="module.plugin" value="true" />
+ <property name="module.genpom" value="true"/>
+ <property name="module.genpom.args" value="-Sqpid-common=provided -Sqpid-broker=provided"/>
+
+ <property name="broker-plugins-management-http.libs" value=""/>
+
+ <import file="../../module.xml" />
+
+ <target name="precompile">
+ <unwar src="${project.root}/${dojo}" dest="${module.classes}/resources/dojo">
+ <patternset>
+ <exclude name="META-INF/**"/>
+ <exclude name="WEB-INF/**"/>
+ <exclude name="**/*.uncompressed.js"/>
+ </patternset>
+ </unwar>
+ </target>
+
+ <target name="bundle" depends="bundle-tasks" />
+</project>
diff --git a/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/Management.java b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/Management.java
new file mode 100644
index 0000000000..c2f9b73b54
--- /dev/null
+++ b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/Management.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.server.management.plugin;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+
+import org.apache.commons.configuration.ConfigurationException;
+import org.apache.log4j.Logger;
+import org.apache.qpid.server.management.plugin.servlet.DefinedFileServlet;
+import org.apache.qpid.server.management.plugin.servlet.FileServlet;
+import org.apache.qpid.server.management.plugin.servlet.api.ExchangesServlet;
+import org.apache.qpid.server.management.plugin.servlet.api.VhostsServlet;
+import org.apache.qpid.server.management.plugin.servlet.rest.LogRecordsServlet;
+import org.apache.qpid.server.management.plugin.servlet.rest.MessageContentServlet;
+import org.apache.qpid.server.management.plugin.servlet.rest.MessageServlet;
+import org.apache.qpid.server.management.plugin.servlet.rest.RestServlet;
+import org.apache.qpid.server.management.plugin.servlet.rest.SaslServlet;
+import org.apache.qpid.server.management.plugin.servlet.rest.StructureServlet;
+import org.apache.qpid.server.model.AuthenticationProvider;
+import org.apache.qpid.server.model.Binding;
+import org.apache.qpid.server.model.Broker;
+import org.apache.qpid.server.model.ConfiguredObject;
+import org.apache.qpid.server.model.Connection;
+import org.apache.qpid.server.model.Exchange;
+import org.apache.qpid.server.model.Port;
+import org.apache.qpid.server.model.Protocol;
+import org.apache.qpid.server.model.Queue;
+import org.apache.qpid.server.model.Session;
+import org.apache.qpid.server.model.Transport;
+import org.apache.qpid.server.model.User;
+import org.apache.qpid.server.model.VirtualHost;
+import org.apache.qpid.server.registry.ApplicationRegistry;
+import org.apache.qpid.server.registry.IApplicationRegistry;
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.server.SessionManager;
+import org.eclipse.jetty.server.nio.SelectChannelConnector;
+import org.eclipse.jetty.server.ssl.SslSocketConnector;
+import org.eclipse.jetty.servlet.ServletContextHandler;
+import org.eclipse.jetty.servlet.ServletHolder;
+import org.eclipse.jetty.util.ssl.SslContextFactory;
+
+public class Management
+{
+
+ private final Logger _logger = Logger.getLogger(Management.class);
+
+ private Broker _broker;
+
+ private Collection<Server> _servers = new ArrayList<Server>();
+
+ public Management() throws ConfigurationException, IOException
+ {
+ _broker = ApplicationRegistry.getInstance().getBroker();
+
+ Collection<Port> ports = _broker.getPorts();
+ int httpPort = -1, httpsPort = -1;
+ for (Port port : ports)
+ {
+ if (port.getProtocols().contains(Protocol.HTTP))
+ {
+ if (port.getTransports().contains(Transport.TCP))
+ {
+ httpPort = port.getPort();
+ }
+ }
+ if (port.getProtocols().contains(Protocol.HTTPS))
+ {
+ if (port.getTransports().contains(Transport.SSL))
+ {
+ httpsPort = port.getPort();
+ }
+ }
+ }
+
+ if (httpPort != -1 || httpsPort != -1)
+ {
+ _servers.add(createServer(httpPort, httpsPort));
+ if (_logger.isDebugEnabled())
+ {
+ _logger.debug(_servers.size() + " server(s) defined");
+ }
+ }
+ else
+ {
+ if (_logger.isInfoEnabled())
+ {
+ _logger.info("Cannot create web server as neither HTTP nor HTTPS port specified");
+ }
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ private Server createServer(int port, int sslPort) throws IOException, ConfigurationException
+ {
+ if (_logger.isInfoEnabled())
+ {
+ _logger.info("Starting up web server on" + (port == -1 ? "" : " HTTP port " + port)
+ + (sslPort == -1 ? "" : " HTTPS port " + sslPort));
+ }
+
+ Server server = new Server();
+
+ if (port != -1)
+ {
+ SelectChannelConnector connector = new SelectChannelConnector();
+ connector.setPort(port);
+ if (sslPort != -1)
+ {
+ connector.setConfidentialPort(sslPort);
+ }
+ server.addConnector(connector);
+ }
+
+ if (sslPort != -1)
+ {
+ IApplicationRegistry appRegistry = ApplicationRegistry.getInstance();
+ String keyStorePath = getKeyStorePath(appRegistry);
+
+ SslContextFactory factory = new SslContextFactory();
+ factory.setKeyStorePath(keyStorePath);
+ factory.setKeyStorePassword(appRegistry.getConfiguration().getManagementKeyStorePassword());
+
+ SslSocketConnector connector = new SslSocketConnector(factory);
+ connector.setPort(sslPort);
+ server.addConnector(connector);
+ }
+
+ ServletContextHandler root = new ServletContextHandler(ServletContextHandler.SESSIONS);
+ root.setContextPath("/");
+ server.setHandler(root);
+
+ root.addServlet(new ServletHolder(new VhostsServlet(_broker)), "/api/vhosts/*");
+ root.addServlet(new ServletHolder(new ExchangesServlet(_broker)), "/api/exchanges/*");
+
+ addRestServlet(root, "broker");
+ addRestServlet(root, "virtualhost", VirtualHost.class);
+ addRestServlet(root, "authenticationprovider", AuthenticationProvider.class);
+ addRestServlet(root, "user", AuthenticationProvider.class, User.class);
+ addRestServlet(root, "exchange", VirtualHost.class, Exchange.class);
+ addRestServlet(root, "queue", VirtualHost.class, Queue.class);
+ addRestServlet(root, "connection", VirtualHost.class, Connection.class);
+ addRestServlet(root, "binding", VirtualHost.class, Exchange.class, Queue.class, Binding.class);
+ addRestServlet(root, "port", Port.class);
+ addRestServlet(root, "session", VirtualHost.class, Connection.class, Session.class);
+
+ root.addServlet(new ServletHolder(new StructureServlet(_broker)), "/rest/structure");
+ root.addServlet(new ServletHolder(new MessageServlet(_broker)), "/rest/message/*");
+ root.addServlet(new ServletHolder(new MessageContentServlet(_broker)), "/rest/message-content/*");
+
+ root.addServlet(new ServletHolder(new LogRecordsServlet(_broker)), "/rest/logrecords");
+
+ root.addServlet(new ServletHolder(new SaslServlet(_broker)), "/rest/sasl");
+
+ root.addServlet(new ServletHolder(new DefinedFileServlet("management.html")), "/management");
+
+ root.addServlet(new ServletHolder(FileServlet.INSTANCE), "*.js");
+ root.addServlet(new ServletHolder(FileServlet.INSTANCE), "*.css");
+ root.addServlet(new ServletHolder(FileServlet.INSTANCE), "*.html");
+ root.addServlet(new ServletHolder(FileServlet.INSTANCE), "*.png");
+ root.addServlet(new ServletHolder(FileServlet.INSTANCE), "*.gif");
+ root.addServlet(new ServletHolder(FileServlet.INSTANCE), "*.jpg");
+ root.addServlet(new ServletHolder(FileServlet.INSTANCE), "*.jpeg");
+ root.addServlet(new ServletHolder(FileServlet.INSTANCE), "*.json");
+ root.addServlet(new ServletHolder(FileServlet.INSTANCE), "*.txt");
+ root.addServlet(new ServletHolder(FileServlet.INSTANCE), "*.xsl");
+
+ final SessionManager sessionManager = root.getSessionHandler().getSessionManager();
+
+ sessionManager.setMaxInactiveInterval(60 * 15);
+
+ return server;
+ }
+
+ private void addRestServlet(ServletContextHandler root, String name, Class<? extends ConfiguredObject>... hierarchy)
+ {
+ root.addServlet(new ServletHolder(new RestServlet(_broker, hierarchy)), "/rest/" + name + "/*");
+ }
+
+ public void start() throws Exception
+ {
+ for (Server server : _servers)
+ {
+ server.start();
+ }
+ }
+
+ public void stop() throws Exception
+ {
+ for (Server server : _servers)
+ {
+ server.stop();
+ }
+ }
+
+ private String getKeyStorePath(IApplicationRegistry appRegistry) throws ConfigurationException, FileNotFoundException
+ {
+ String keyStorePath = null;
+ if (System.getProperty("javax.net.ssl.keyStore") != null)
+ {
+ keyStorePath = System.getProperty("javax.net.ssl.keyStore");
+ }
+ else
+ {
+ keyStorePath = appRegistry.getConfiguration().getManagementKeyStorePath();
+ }
+
+ if (keyStorePath == null)
+ {
+ throw new ConfigurationException("Management SSL keystore path not defined, unable to start SSL protected HTTP connector");
+ }
+ else
+ {
+ File ksf = new File(keyStorePath);
+ if (!ksf.exists())
+ {
+ throw new FileNotFoundException("Cannot find management SSL keystore file: " + ksf);
+ }
+ if (!ksf.canRead())
+ {
+ throw new FileNotFoundException("Cannot read management SSL keystore file: " + ksf + ". Check permissions.");
+ }
+ }
+ return keyStorePath;
+ }
+
+}
diff --git a/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/ManagementActivator.java b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/ManagementActivator.java
new file mode 100644
index 0000000000..09b7e08bfb
--- /dev/null
+++ b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/ManagementActivator.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.server.management.plugin;
+
+import org.apache.log4j.Logger;
+import org.apache.qpid.server.configuration.plugins.ConfigurationPluginFactory;
+import org.apache.qpid.server.registry.ApplicationRegistry;
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+
+public class ManagementActivator implements BundleActivator
+{
+ private static final Logger _logger = Logger.getLogger(ManagementActivator.class);
+
+
+ private BundleContext _ctx;
+ private String _bundleName;
+ private Management _managementService;
+
+
+ public void start(final BundleContext ctx) throws Exception
+ {
+ _ctx = ctx;
+ if (!ApplicationRegistry.getInstance().getConfiguration().getHTTPManagementEnabled()
+ && !ApplicationRegistry.getInstance().getConfiguration().getHTTPSManagementEnabled())
+ {
+ _logger.info("Management plugin is disabled!");
+ ctx.getBundle().uninstall();
+ return;
+ }
+ _managementService = new Management();
+ _managementService.start();
+ _bundleName = ctx.getBundle().getSymbolicName();
+
+ // register the service
+ _logger.info("Registering management plugin: " + _bundleName);
+ _ctx.registerService(Management.class.getName(), _managementService, null);
+ _ctx.registerService(ConfigurationPluginFactory.class.getName(), ManagementConfiguration.FACTORY, null);
+ }
+
+ public void stop(final BundleContext bundleContext) throws Exception
+ {
+ if (_managementService != null)
+ {
+ _logger.info("Stopping management plugin: " + _bundleName);
+
+ _managementService.stop();
+
+ // null object references
+ _managementService = null;
+ }
+ _ctx = null;
+ }
+
+}
diff --git a/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/ManagementConfiguration.java b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/ManagementConfiguration.java
new file mode 100644
index 0000000000..3866da8f89
--- /dev/null
+++ b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/ManagementConfiguration.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.server.management.plugin;
+
+import org.apache.commons.configuration.CompositeConfiguration;
+import org.apache.commons.configuration.Configuration;
+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.configuration.plugins.ConfigurationPluginFactory;
+
+import java.util.Arrays;
+import java.util.List;
+
+public class ManagementConfiguration extends ConfigurationPlugin
+{
+ CompositeConfiguration _finalConfig;
+
+ public static final ConfigurationPluginFactory FACTORY = new ConfigurationPluginFactory()
+ {
+ public ConfigurationPlugin newInstance(String path, Configuration config) throws ConfigurationException
+ {
+ ConfigurationPlugin instance = new ManagementConfiguration();
+ instance.setConfiguration(path, config);
+ return instance;
+ }
+
+ public List<String> getParentPaths()
+ {
+ return Arrays.asList("management");
+ }
+ };
+
+ public String[] getElementsProcessed()
+ {
+ return new String[] { "" };
+ }
+
+ public Configuration getConfiguration()
+ {
+ return _finalConfig;
+ }
+
+
+ @Override
+ public void validateConfiguration() throws ConfigurationException
+ {
+ // Valid Configuration either has xml links to new files
+ _finalConfig = new CompositeConfiguration(getConfig());
+ List subFiles = getConfig().getList("xml[@fileName]");
+ for (Object subFile : subFiles)
+ {
+ _finalConfig.addConfiguration(new XMLConfiguration((String) subFile));
+ }
+
+ }
+
+}
diff --git a/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/DefinedFileServlet.java b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/DefinedFileServlet.java
new file mode 100644
index 0000000000..d8a8395550
--- /dev/null
+++ b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/DefinedFileServlet.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.server.management.plugin.servlet;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+public class DefinedFileServlet extends HttpServlet
+{
+
+ private static final String FILENAME_INIT_PARAMETER = "filename";
+
+ private String _filename;
+
+ public DefinedFileServlet()
+ {
+ super();
+ }
+
+ public DefinedFileServlet(String filename)
+ {
+ _filename = filename;
+ }
+
+ @Override
+ public void init() throws ServletException
+ {
+ ServletConfig config = getServletConfig();
+ String fileName = config.getInitParameter(FILENAME_INIT_PARAMETER);
+ if (fileName != null && !"".equals(fileName))
+ {
+ _filename = fileName;
+ }
+ }
+
+ @Override
+ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
+ {
+ final ServletOutputStream output = response.getOutputStream();
+ InputStream fileInput = getClass().getResourceAsStream("/resources/"+_filename);
+
+ if(fileInput != null)
+ {
+ byte[] buffer = new byte[1024];
+ response.setStatus(HttpServletResponse.SC_OK);
+ int read = 0;
+
+ while((read = fileInput.read(buffer)) > 0)
+ {
+ output.write(buffer, 0, read);
+ }
+ }
+ else
+ {
+ response.sendError(404, "unknown file: "+ _filename);
+ }
+ }
+}
diff --git a/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/FileServlet.java b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/FileServlet.java
new file mode 100644
index 0000000000..f8ca082d79
--- /dev/null
+++ b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/FileServlet.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.server.management.plugin.servlet;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import javax.servlet.ServletException;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+public class FileServlet extends HttpServlet
+{
+ public static final FileServlet INSTANCE = new FileServlet();
+
+ private static final Map<String, String> CONTENT_TYPES;
+
+ static
+ {
+
+ Map<String, String> contentTypes = new HashMap<String, String>();
+ contentTypes.put("js", "application/javascript");
+ contentTypes.put("html", "text/html");
+ contentTypes.put("css", "text/css");
+ contentTypes.put("json", "application/json");
+ contentTypes.put("jpg", "image/jpg");
+ contentTypes.put("png", "image/png");
+ contentTypes.put("gif", "image/gif");
+ CONTENT_TYPES = Collections.unmodifiableMap(contentTypes);
+ }
+
+
+ public FileServlet()
+ {
+ }
+
+ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
+ {
+ String filename = request.getServletPath();
+ if(filename.contains("."))
+ {
+ String suffix = filename.substring(filename.lastIndexOf('.')+1);
+ String contentType = CONTENT_TYPES.get(suffix);
+ if(contentType != null)
+ {
+ response.setContentType(contentType);
+ }
+ }
+ URL resourceURL = getClass().getResource("/resources" + filename);
+ if(resourceURL != null)
+ {
+ response.setStatus(HttpServletResponse.SC_OK);
+ InputStream fileInput = resourceURL.openStream();
+ try
+ {
+ byte[] buffer = new byte[1024];
+ int read = 0;
+ ServletOutputStream output = response.getOutputStream();
+ try
+ {
+ while((read = fileInput.read(buffer)) != -1)
+ {
+ output.write(buffer, 0, read);
+ }
+ }
+ finally
+ {
+ output.close();
+ }
+ }
+ finally
+ {
+ fileInput.close();
+ }
+ }
+ else
+ {
+ response.sendError(404, "unknown file: "+ filename);
+ }
+
+ }
+
+}
diff --git a/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/api/ExchangesServlet.java b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/api/ExchangesServlet.java
new file mode 100644
index 0000000000..a3c5ec68a2
--- /dev/null
+++ b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/api/ExchangesServlet.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.server.management.plugin.servlet.api;
+
+import org.codehaus.jackson.map.ObjectMapper;
+import org.codehaus.jackson.map.ObjectReader;
+
+import org.apache.qpid.server.model.Broker;
+import org.apache.qpid.server.model.Exchange;
+import org.apache.qpid.server.model.LifetimePolicy;
+import org.apache.qpid.server.model.State;
+import org.apache.qpid.server.model.VirtualHost;
+import org.apache.qpid.server.registry.ApplicationRegistry;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+public class ExchangesServlet extends HttpServlet
+{
+
+
+ private Broker _broker;
+
+ public ExchangesServlet()
+ {
+ super();
+ _broker = ApplicationRegistry.getInstance().getBroker();
+ }
+
+ public ExchangesServlet(Broker broker)
+ {
+ _broker = broker;
+ }
+
+ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
+ {
+ response.setContentType("application/json");
+ response.setStatus(HttpServletResponse.SC_OK);
+
+ Collection<VirtualHost> vhosts = _broker.getVirtualHosts();
+ Collection<Exchange> exchanges = new ArrayList<Exchange>();
+ Collection<Map<String,Object>> outputObject = new ArrayList<Map<String,Object>>();
+
+ final PrintWriter writer = response.getWriter();
+
+ ObjectMapper mapper = new ObjectMapper();
+ String vhostName = null;
+ String exchangeName = null;
+
+ if(request.getPathInfo() != null && request.getPathInfo().length()>0)
+ {
+ String path = request.getPathInfo().substring(1);
+ String[] parts = path.split("/");
+ vhostName = parts.length == 0 ? "" : parts[0];
+ if(parts.length > 1)
+ {
+ exchangeName = parts[1];
+ }
+ }
+
+ for(VirtualHost vhost : vhosts)
+ {
+ if(vhostName == null || vhostName.equals(vhost.getName()))
+ {
+ for(Exchange exchange : vhost.getExchanges())
+ {
+ if(exchangeName == null || exchangeName.equals(exchange.getName()))
+ {
+ outputObject.add(convertToObject(exchange));
+ if(exchangeName != null)
+ {
+ break;
+ }
+ }
+ }
+ if(vhostName != null)
+ {
+ break;
+ }
+ }
+ }
+
+ mapper.writeValue(writer, outputObject);
+
+ }
+
+ private Map<String,Object> convertToObject(final Exchange exchange)
+ {
+ Map<String, Object> object = new LinkedHashMap<String, Object>();
+ object.put("name",exchange.getName());
+ object.put("type", exchange.getExchangeType());
+ object.put("durable", exchange.isDurable());
+ object.put("auto-delete", exchange.getLifetimePolicy() == LifetimePolicy.AUTO_DELETE);
+
+ Map<String,Object> arguments = new HashMap<String, Object>();
+ for(String key : exchange.getAttributeNames())
+ {
+ if(!key.equals(Exchange.TYPE))
+ {
+ arguments.put(key, exchange.getAttribute(key));
+ }
+ }
+ object.put("arguments", arguments);
+ return object;
+ }
+
+ protected void doPut(final HttpServletRequest request, final HttpServletResponse response)
+ throws ServletException, IOException
+ {
+
+ response.setContentType("application/json");
+
+
+ String vhostName = null;
+ String exchangeName = null;
+ if(request.getPathInfo() != null && request.getPathInfo().length()>0)
+ {
+ String path = request.getPathInfo().substring(1);
+ String[] parts = path.split("/");
+ vhostName = parts.length == 0 ? "" : parts[0];
+ if(parts.length > 1)
+ {
+ exchangeName = parts[1];
+ }
+ }
+ if(vhostName == null)
+ {
+ response.setStatus(HttpServletResponse.SC_PRECONDITION_FAILED);
+ }
+ else if (exchangeName == null)
+ {
+ response.setStatus(HttpServletResponse.SC_PRECONDITION_FAILED);
+ }
+ else
+ {
+ VirtualHost vhost = null;
+ for(VirtualHost host : _broker.getVirtualHosts())
+ {
+ if(host.getName().equals(vhostName))
+ {
+ vhost = host;
+ }
+ }
+ if(vhost == null)
+ {
+ response.setStatus(HttpServletResponse.SC_PRECONDITION_FAILED);
+ }
+ else
+ {
+ response.setStatus(HttpServletResponse.SC_NO_CONTENT);
+ ObjectMapper mapper = new ObjectMapper();
+ Map<String,Object> exchangeObject = mapper.readValue(request.getInputStream(), LinkedHashMap.class);
+
+ final boolean isDurable = exchangeObject.get("durable") instanceof Boolean
+ && ((Boolean)exchangeObject.get("durable"));
+ final boolean isAutoDelete = exchangeObject.get("auto_delete") instanceof Boolean
+ && ((Boolean)exchangeObject.get("auto_delete"));
+
+ final String type = (String) exchangeObject.get("type");
+ final Map<String, Object> attributes = new HashMap<String, Object>(exchangeObject);
+ attributes.remove("durable");
+ attributes.remove("auto_delete");
+ attributes.remove("type");
+
+ vhost.createExchange(exchangeName, State.ACTIVE, isDurable,
+ isAutoDelete ? LifetimePolicy.AUTO_DELETE : LifetimePolicy.PERMANENT,
+ 0l,
+ type,
+ attributes);
+ }
+
+
+
+ }
+
+
+
+ }
+}
diff --git a/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/api/VhostsServlet.java b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/api/VhostsServlet.java
new file mode 100644
index 0000000000..b2c0fcfe52
--- /dev/null
+++ b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/api/VhostsServlet.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.server.management.plugin.servlet.api;
+
+import org.codehaus.jackson.map.ObjectMapper;
+
+import org.apache.qpid.common.QpidProperties;
+import org.apache.qpid.server.model.Broker;
+import org.apache.qpid.server.model.LifetimePolicy;
+import org.apache.qpid.server.model.State;
+import org.apache.qpid.server.model.VirtualHost;
+import org.apache.qpid.server.protocol.AMQConnectionModel;
+import org.apache.qpid.server.registry.ApplicationRegistry;
+
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.*;
+
+public class VhostsServlet extends HttpServlet
+{
+
+
+ private Broker _broker;
+
+ public VhostsServlet()
+ {
+ super();
+ _broker = ApplicationRegistry.getInstance().getBroker();
+ }
+
+ public VhostsServlet(Broker broker)
+ {
+ _broker = broker;
+ }
+
+ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
+ {
+System.out.println("Get /api/vhosts");
+ response.setContentType("application/json");
+ response.setStatus(HttpServletResponse.SC_OK);
+
+ Collection<VirtualHost> vhosts = _broker.getVirtualHosts();
+
+
+
+ final PrintWriter writer = response.getWriter();
+
+ ObjectMapper mapper = new ObjectMapper();
+
+ if(request.getPathInfo() == null || request.getPathInfo().length()==0)
+ {
+
+ LinkedHashMap<String, Object> vhostObject = new LinkedHashMap<String, Object>();
+ List<Map> vhostList = new ArrayList<Map>();
+
+ for(VirtualHost vhost : vhosts)
+ {
+ vhostList.add(Collections.singletonMap("name", vhost.getName()));
+ }
+ mapper.writeValue(writer, vhostList);
+ }
+ else
+ {
+ LinkedHashMap<String, Object> vhostObject = new LinkedHashMap<String, Object>();
+ String vhostName = request.getPathInfo().substring(1);
+
+ for(VirtualHost vhost : vhosts)
+ {
+ if(vhostName.equals(vhost.getName()))
+ {
+ vhostObject.put("name", vhost.getName());
+ break;
+ }
+ }
+ mapper.writeValue(writer, vhostObject);
+ }
+ }
+
+
+ protected void doPut(final HttpServletRequest request, final HttpServletResponse response)
+ throws ServletException, IOException
+ {
+
+ response.setContentType("application/json");
+ response.setStatus(HttpServletResponse.SC_NO_CONTENT);
+
+ if(request.getPathInfo() != null && request.getPathInfo().length()>0)
+ {
+ String vhostName = request.getPathInfo().substring(1);
+ _broker.createVirtualHost(vhostName, State.ACTIVE, true, LifetimePolicy.PERMANENT, 0L, Collections.EMPTY_MAP);
+ }
+
+
+ }
+}
diff --git a/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/AbstractServlet.java b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/AbstractServlet.java
new file mode 100644
index 0000000000..a76bd98179
--- /dev/null
+++ b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/AbstractServlet.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.server.management.plugin.servlet.rest;
+
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.net.SocketAddress;
+import java.security.Principal;
+import java.util.Collections;
+import javax.security.auth.Subject;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+import org.apache.commons.codec.binary.Base64;
+import org.apache.qpid.server.model.Broker;
+import org.apache.qpid.server.registry.ApplicationRegistry;
+import org.apache.qpid.server.security.auth.AuthenticationResult;
+import org.apache.qpid.server.security.auth.manager.AnonymousAuthenticationManager;
+import org.apache.qpid.server.security.auth.manager.AuthenticationManager;
+
+public abstract class AbstractServlet extends HttpServlet
+{
+ private final Broker _broker;
+
+ protected AbstractServlet()
+ {
+ super();
+ _broker = ApplicationRegistry.getInstance().getBroker();
+ }
+
+ protected AbstractServlet(Broker broker)
+ {
+ _broker = broker;
+ }
+
+ @Override
+ protected final void doGet(HttpServletRequest request, HttpServletResponse resp) throws ServletException, IOException
+ {
+ setAuthorizedSubject(request);
+ try
+ {
+ onGet(request, resp);
+ }
+ finally
+ {
+ clearAuthorizedSubject();
+ }
+ }
+
+ protected void onGet(HttpServletRequest request, HttpServletResponse resp) throws IOException, ServletException
+ {
+ super.doGet(request, resp);
+ }
+
+ private void clearAuthorizedSubject()
+ {
+ org.apache.qpid.server.security.SecurityManager.setThreadSubject(null);
+ }
+
+
+ private void setAuthorizedSubject(HttpServletRequest request)
+ {
+ HttpSession session = request.getSession(true);
+ Subject subject = (Subject) session.getAttribute("subject");
+
+ if(subject == null)
+ {
+ Principal principal = request.getUserPrincipal();
+ if(principal != null)
+ {
+ subject = new Subject(false, Collections.singleton(principal),Collections.emptySet(),
+ Collections.emptySet());
+ }
+ else
+ {
+ String header = request.getHeader("Authorization");
+
+ /*
+ * TODO - Should configure whether basic authentication is allowed... and in particular whether it
+ * should be allowed over non-ssl connections
+ * */
+
+ if (header != null)
+ {
+ String[] tokens = header.split("\\s");
+ if(tokens.length >= 2
+ && "BASIC".equalsIgnoreCase(tokens[0]))
+ {
+ String[] credentials = (new String(Base64.decodeBase64(tokens[1].getBytes()))).split(":",2);
+ if(credentials.length == 2)
+ {
+ SocketAddress address = getSocketAddress(request);
+ AuthenticationManager authenticationManager =
+ ApplicationRegistry.getInstance().getAuthenticationManager(address);
+ AuthenticationResult authResult =
+ authenticationManager.authenticate(credentials[0], credentials[1]);
+ subject = authResult.getSubject();
+
+ }
+ }
+ }
+ }
+ }
+ if (subject == null)
+ {
+ subject = AnonymousAuthenticationManager.ANONYMOUS_SUBJECT;
+ }
+ org.apache.qpid.server.security.SecurityManager.setThreadSubject(subject);
+
+ }
+
+ protected Subject getSubject(HttpSession session)
+ {
+ return (Subject)session.getAttribute("subject");
+ }
+
+ @Override
+ protected final void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
+ {
+ setAuthorizedSubject(req);
+ try
+ {
+ onPost(req, resp);
+ }
+ finally
+ {
+ clearAuthorizedSubject();
+ }
+
+ }
+
+ protected void onPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
+ {
+ super.doPost(req, resp);
+ }
+
+ @Override
+ protected final void doPut(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
+ {
+ setAuthorizedSubject(req);
+ try
+ {
+ onPut(req, resp);
+
+ }
+ finally
+ {
+ clearAuthorizedSubject();
+ }
+ }
+
+ protected void onPut(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException
+ {
+ super.doPut(req,resp);
+ }
+
+ @Override
+ protected final void doDelete(HttpServletRequest req, HttpServletResponse resp)
+ throws ServletException, IOException
+ {
+ setAuthorizedSubject(req);
+ try
+ {
+ onDelete(req, resp);
+ }
+ finally
+ {
+ clearAuthorizedSubject();
+ }
+ }
+
+ protected void onDelete(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
+ {
+ super.doDelete(req, resp);
+ }
+
+
+ protected Broker getBroker()
+ {
+ return _broker;
+ }
+
+ protected SocketAddress getSocketAddress(HttpServletRequest request)
+ {
+ return InetSocketAddress.createUnresolved(request.getServerName(), request.getServerPort());
+ }
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/store/derby/DerbyMessageStoreFactory.java b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/KeyComparator.java
index 12d7f64a8d..3d862ce321 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/store/derby/DerbyMessageStoreFactory.java
+++ b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/KeyComparator.java
@@ -1,4 +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
@@ -17,24 +18,36 @@
* under the License.
*
*/
-package org.apache.qpid.server.store.derby;
+package org.apache.qpid.server.management.plugin.servlet.rest;
-import org.apache.qpid.server.store.MessageStore;
-import org.apache.qpid.server.store.MessageStoreFactory;
+import java.util.Comparator;
+import java.util.Map;
-public class DerbyMessageStoreFactory implements MessageStoreFactory
+class KeyComparator implements Comparator<Map>
{
+ private String _key;
- @Override
- public MessageStore createMessageStore()
+ public KeyComparator(final String key)
{
- return new DerbyMessageStore();
+ _key = key;
}
- @Override
- public String getStoreClassName()
+ public int compare(final Map o1, final Map o2)
{
- return DerbyMessageStore.class.getSimpleName();
- }
+ Comparable left = (Comparable) o1.get(_key);
+ Comparable right = (Comparable) o2.get(_key);
+
+ int result;
+ if(left == null)
+ {
+ result = right == null ? 0 : -1;
+ }
+ else
+ {
+ result = left.compareTo(right);
+ }
+ return result;
+
+ }
}
diff --git a/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/LogRecordsServlet.java b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/LogRecordsServlet.java
new file mode 100644
index 0000000000..404793b592
--- /dev/null
+++ b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/LogRecordsServlet.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.server.management.plugin.servlet.rest;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import org.apache.qpid.server.logging.LogRecorder;
+import org.apache.qpid.server.model.Broker;
+import org.apache.qpid.server.registry.ApplicationRegistry;
+import org.codehaus.jackson.map.ObjectMapper;
+import org.codehaus.jackson.map.SerializationConfig;
+
+public class LogRecordsServlet extends AbstractServlet
+{
+ public LogRecordsServlet()
+ {
+ super(ApplicationRegistry.getInstance().getBroker());
+ }
+
+ public LogRecordsServlet(Broker broker)
+ {
+ super(broker);
+ }
+
+ @Override
+ protected void onGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
+ {
+ response.setContentType("application/json");
+ response.setStatus(HttpServletResponse.SC_OK);
+
+ response.setHeader("Cache-Control","no-cache");
+ response.setHeader("Pragma","no-cache");
+ response.setDateHeader ("Expires", 0);
+
+ ApplicationRegistry applicationRegistry = (ApplicationRegistry) ApplicationRegistry.getInstance();
+ List<Map<String,Object>> logRecords = new ArrayList<Map<String, Object>>();
+
+ for(LogRecorder.Record record : applicationRegistry.getLogRecorder())
+ {
+ logRecords.add(logRecordToObject(record));
+ }
+
+ final PrintWriter writer = response.getWriter();
+ ObjectMapper mapper = new ObjectMapper();
+ mapper.configure(SerializationConfig.Feature.INDENT_OUTPUT, true);
+ mapper.writeValue(writer, logRecords);
+
+ response.setStatus(HttpServletResponse.SC_OK);
+
+ }
+
+ private Map<String, Object> logRecordToObject(LogRecorder.Record record)
+ {
+ Map<String, Object> recordMap = new LinkedHashMap<String, Object>();
+ recordMap.put("id",record.getId());
+ recordMap.put("timestamp", record.getTimestamp());
+ recordMap.put("level", record.getLevel());
+ recordMap.put("thread", record.getThreadName());
+ recordMap.put("logger", record.getLogger());
+ recordMap.put("message", record.getMessage());
+ return recordMap;
+ }
+
+}
diff --git a/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MapComparator.java b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MapComparator.java
new file mode 100644
index 0000000000..84d987813b
--- /dev/null
+++ b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MapComparator.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.server.management.plugin.servlet.rest;
+
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Map;
+
+class MapComparator implements Comparator<Map>
+{
+ private Comparator<Map>[] _sortKeys;
+
+ public MapComparator(final String[] sortKeys)
+ {
+ _sortKeys = parseKeys(sortKeys);
+ }
+
+ private static Comparator<Map>[] parseKeys(final String[] sortKeys)
+ {
+ Comparator<Map>[] comparators = new Comparator[sortKeys.length];
+ for(int i = 0; i < sortKeys.length; i++)
+ {
+ String key = sortKeys[i];
+
+ if(key.startsWith("+") || key.startsWith(" "))
+ {
+ comparators[i] = new KeyComparator(key.substring(1));
+ }
+ else if(key.startsWith("-"))
+ {
+ comparators[i] = Collections.reverseOrder(new KeyComparator(key.substring(1)));
+ }
+ else
+ {
+ comparators[i] = new KeyComparator(key);
+ }
+ }
+ return comparators;
+ }
+
+
+ public int compare(final Map o1, final Map o2)
+ {
+ int result = 0;
+ for(int i = 0; i < _sortKeys.length; i++)
+ {
+ result = _sortKeys[i].compare(o1, o2);
+ if(result != 0)
+ {
+ return result;
+ }
+ }
+ return 0;
+ }
+
+}
diff --git a/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MessageContentServlet.java b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MessageContentServlet.java
new file mode 100644
index 0000000000..bc87f0bcc5
--- /dev/null
+++ b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MessageContentServlet.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.server.management.plugin.servlet.rest;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.qpid.server.message.MessageReference;
+import org.apache.qpid.server.message.ServerMessage;
+import org.apache.qpid.server.model.Broker;
+import org.apache.qpid.server.model.Queue;
+import org.apache.qpid.server.model.VirtualHost;
+import org.apache.qpid.server.queue.QueueEntry;
+import org.apache.qpid.server.queue.QueueEntryVisitor;
+
+public class MessageContentServlet extends AbstractServlet
+{
+ public MessageContentServlet()
+ {
+ super();
+ }
+
+ public MessageContentServlet(Broker broker)
+ {
+ super(broker);
+ }
+
+ @Override
+ protected void onGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
+ {
+
+ if(request.getPathInfo() != null && request.getPathInfo().length()>0 && request.getPathInfo().substring(1).split("/").length > 2)
+ {
+ getMessageContent(request, response);
+ }
+
+ }
+
+ private void getMessageContent(HttpServletRequest request, HttpServletResponse response) throws IOException
+ {
+ Queue queue = getQueueFromRequest(request);
+ String path[] = request.getPathInfo().substring(1).split("/");
+ MessageFinder finder = new MessageFinder(Long.parseLong(path[2]));
+ queue.visit(finder);
+ if(finder.isFound())
+ {
+ response.setContentType(finder.getMimeType());
+ response.setContentLength((int) finder.getSize());
+ response.getOutputStream().write(finder.getContent());
+
+ }
+
+ }
+
+ private Queue getQueueFromRequest(HttpServletRequest request)
+ {
+ List<String> names = new ArrayList<String>();
+ // TODO - validation that there is a vhost and queue and only those in the path
+ if(request.getPathInfo() != null && request.getPathInfo().length()>0)
+ {
+ String path = request.getPathInfo().substring(1);
+ names.addAll(Arrays.asList(path.split("/")));
+ }
+ String vhostName = names.get(0);
+ String queueName = names.get(1);
+
+ VirtualHost vhost = null;
+
+ for(VirtualHost vh : getBroker().getVirtualHosts())
+ {
+ if(vh.getName().equals(vhostName))
+ {
+ vhost = vh;
+ break;
+ }
+ }
+
+ return getQueueFromVirtualHost(queueName, vhost);
+ }
+
+ private Queue getQueueFromVirtualHost(String queueName, VirtualHost vhost)
+ {
+ Queue queue = null;
+
+ for(Queue q : vhost.getQueues())
+ {
+ if(q.getName().equals(queueName))
+ {
+ queue = q;
+ break;
+ }
+ }
+ return queue;
+ }
+
+ private class MessageFinder implements QueueEntryVisitor
+ {
+ private final long _messageNumber;
+ private String _mimeType;
+ private long _size;
+ private byte[] _content;
+ private boolean _found;
+
+ private MessageFinder(long messageNumber)
+ {
+ _messageNumber = messageNumber;
+ }
+
+
+ public boolean visit(QueueEntry entry)
+ {
+ ServerMessage message = entry.getMessage();
+ if(message != null)
+ {
+ if(_messageNumber == message.getMessageNumber())
+ {
+ MessageReference reference = message.newReference();
+
+ _mimeType = message.getMessageHeader().getMimeType();
+ _size = message.getSize();
+ _content = new byte[(int)_size];
+ _found = true;
+ message.getContent(ByteBuffer.wrap(_content),0);
+ reference.release();
+ return true;
+ }
+
+ }
+ return false;
+ }
+
+ public String getMimeType()
+ {
+ return _mimeType;
+ }
+
+ public long getSize()
+ {
+ return _size;
+ }
+
+ public byte[] getContent()
+ {
+ return _content;
+ }
+
+ public boolean isFound()
+ {
+ return _found;
+ }
+ }
+
+
+}
diff --git a/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MessageServlet.java b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MessageServlet.java
new file mode 100644
index 0000000000..6e7bc1d935
--- /dev/null
+++ b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MessageServlet.java
@@ -0,0 +1,502 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF 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.management.plugin.servlet.rest;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.log4j.Logger;
+import org.apache.qpid.server.message.AMQMessageHeader;
+import org.apache.qpid.server.message.MessageReference;
+import org.apache.qpid.server.message.ServerMessage;
+import org.apache.qpid.server.model.Broker;
+import org.apache.qpid.server.model.Queue;
+import org.apache.qpid.server.model.VirtualHost;
+import org.apache.qpid.server.queue.QueueEntry;
+import org.apache.qpid.server.queue.QueueEntryVisitor;
+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.access.Operation;
+import org.apache.qpid.server.subscription.Subscription;
+import org.codehaus.jackson.map.ObjectMapper;
+import org.codehaus.jackson.map.SerializationConfig;
+
+public class MessageServlet extends AbstractServlet
+{
+ private static final Logger LOGGER = Logger.getLogger(MessageServlet.class);
+
+ public MessageServlet()
+ {
+ super();
+ }
+
+ public MessageServlet(Broker broker)
+ {
+ super(broker);
+ }
+
+ @Override
+ protected void onGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
+ {
+
+ if(request.getPathInfo() != null && request.getPathInfo().length()>0 && request.getPathInfo().substring(1).split("/").length > 2)
+ {
+ getMessageContent(request, response);
+ }
+ else
+ {
+ getMessageList(request, response);
+ }
+
+ }
+
+ private void getMessageContent(HttpServletRequest request, HttpServletResponse response) throws IOException
+ {
+ Queue queue = getQueueFromRequest(request);
+ String path[] = request.getPathInfo().substring(1).split("/");
+ MessageFinder messageFinder = new MessageFinder(Long.parseLong(path[2]));
+ queue.visit(messageFinder);
+
+ response.setStatus(HttpServletResponse.SC_OK);
+
+ response.setHeader("Cache-Control","no-cache");
+ response.setHeader("Pragma","no-cache");
+ response.setDateHeader ("Expires", 0);
+
+ final PrintWriter writer = response.getWriter();
+ ObjectMapper mapper = new ObjectMapper();
+ mapper.configure(SerializationConfig.Feature.INDENT_OUTPUT, true);
+ mapper.writeValue(writer, messageFinder.getMessageObject());
+ }
+
+ private void getMessageList(HttpServletRequest request, HttpServletResponse response) throws IOException
+ {
+ Queue queue = getQueueFromRequest(request);
+
+ int first = -1;
+ int last = -1;
+ String range = request.getHeader("Range");
+ if(range != null)
+ {
+ String[] boundaries = range.split("=")[1].split("-");
+ first = Integer.parseInt(boundaries[0]);
+ last = Integer.parseInt(boundaries[1]);
+ }
+ final MessageCollector messageCollector = new MessageCollector(first, last);
+ queue.visit(messageCollector);
+
+ response.setContentType("application/json");
+ final List<Map<String, Object>> messages = messageCollector.getMessages();
+ int queueSize = ((Number) queue.getStatistics().getStatistic(Queue.QUEUE_DEPTH_MESSAGES)).intValue();
+ String min = messages.isEmpty() ? "0" : messages.get(0).get("position").toString();
+ String max = messages.isEmpty() ? "0" : messages.get(messages.size()-1).get("position").toString();
+ response.setHeader("Content-Range", (min + "-" + max + "/" + queueSize));
+ response.setStatus(HttpServletResponse.SC_OK);
+
+ response.setHeader("Cache-Control","no-cache");
+ response.setHeader("Pragma","no-cache");
+ response.setDateHeader ("Expires", 0);
+
+ final PrintWriter writer = response.getWriter();
+ ObjectMapper mapper = new ObjectMapper();
+ mapper.configure(SerializationConfig.Feature.INDENT_OUTPUT, true);
+ mapper.writeValue(writer, messages);
+ }
+
+ private Queue getQueueFromRequest(HttpServletRequest request)
+ {
+ List<String> names = new ArrayList<String>();
+ // TODO - validation that there is a vhost and queue and only those in the path
+ if(request.getPathInfo() != null && request.getPathInfo().length()>0)
+ {
+ String path = request.getPathInfo().substring(1);
+ names.addAll(Arrays.asList(path.split("/")));
+ }
+ String vhostName = names.get(0);
+ String queueName = names.get(1);
+
+ VirtualHost vhost = null;
+
+ for(VirtualHost vh : getBroker().getVirtualHosts())
+ {
+ if(vh.getName().equals(vhostName))
+ {
+ vhost = vh;
+ break;
+ }
+ }
+
+ return getQueueFromVirtualHost(queueName, vhost);
+ }
+
+ private Queue getQueueFromVirtualHost(String queueName, VirtualHost vhost)
+ {
+ Queue queue = null;
+
+ for(Queue q : vhost.getQueues())
+ {
+
+ if(q.getName().equals(queueName))
+ {
+ queue = q;
+ break;
+ }
+ }
+ return queue;
+ }
+
+ private abstract static class QueueEntryTransaction implements VirtualHost.TransactionalOperation
+ {
+ private final Queue _sourceQueue;
+ private final List _messageIds;
+
+ protected QueueEntryTransaction(Queue sourceQueue, List messageIds)
+ {
+ _sourceQueue = sourceQueue;
+ _messageIds = messageIds;
+ }
+
+
+ public void withinTransaction(final VirtualHost.Transaction txn)
+ {
+
+ _sourceQueue.visit(new QueueEntryVisitor()
+ {
+
+ public boolean visit(final QueueEntry entry)
+ {
+ final ServerMessage message = entry.getMessage();
+ if(message != null)
+ {
+ final long messageId = message.getMessageNumber();
+ if (_messageIds.remove(messageId) || (messageId <= (long) Integer.MAX_VALUE
+ && _messageIds.remove(Integer.valueOf((int)messageId))))
+ {
+ updateEntry(entry, txn);
+ }
+ }
+ return _messageIds.isEmpty();
+ }
+ });
+ }
+
+
+ protected abstract void updateEntry(QueueEntry entry, VirtualHost.Transaction txn);
+ }
+
+ private static class MoveTransaction extends QueueEntryTransaction
+ {
+ private final Queue _destinationQueue;
+
+ public MoveTransaction(Queue sourceQueue, List<Long> messageIds, Queue destinationQueue)
+ {
+ super(sourceQueue, messageIds);
+ _destinationQueue = destinationQueue;
+ }
+
+ protected void updateEntry(QueueEntry entry, VirtualHost.Transaction txn)
+ {
+ txn.move(entry, _destinationQueue);
+ }
+ }
+
+ private static class CopyTransaction extends QueueEntryTransaction
+ {
+ private final Queue _destinationQueue;
+
+ public CopyTransaction(Queue sourceQueue, List<Long> messageIds, Queue destinationQueue)
+ {
+ super(sourceQueue, messageIds);
+ _destinationQueue = destinationQueue;
+ }
+
+ protected void updateEntry(QueueEntry entry, VirtualHost.Transaction txn)
+ {
+ txn.copy(entry, _destinationQueue);
+ }
+ }
+
+ private static class DeleteTransaction extends QueueEntryTransaction
+ {
+ public DeleteTransaction(Queue sourceQueue, List<Long> messageIds)
+ {
+ super(sourceQueue, messageIds);
+ }
+
+ protected void updateEntry(QueueEntry entry, VirtualHost.Transaction txn)
+ {
+ txn.dequeue(entry);
+ }
+ }
+
+
+
+ private class MessageCollector implements QueueEntryVisitor
+ {
+ private final int _first;
+ private final int _last;
+ private int _position = -1;
+ private final List<Map<String, Object>> _messages = new ArrayList<Map<String, Object>>();
+
+ private MessageCollector(int first, int last)
+ {
+ _first = first;
+ _last = last;
+ }
+
+
+ public boolean visit(QueueEntry entry)
+ {
+
+ _position++;
+ if((_first == -1 || _position >= _first) && (_last == -1 || _position <= _last))
+ {
+ final Map<String, Object> messageObject = convertToObject(entry, false);
+ messageObject.put("position", _position);
+ _messages.add(messageObject);
+ }
+ return _last != -1 && _position > _last;
+ }
+
+ public List<Map<String, Object>> getMessages()
+ {
+ return _messages;
+ }
+ }
+
+
+ private class MessageFinder implements QueueEntryVisitor
+ {
+ private final long _messageNumber;
+ private Map<String, Object> _messageObject;
+
+ private MessageFinder(long messageNumber)
+ {
+ _messageNumber = messageNumber;
+ }
+
+
+ public boolean visit(QueueEntry entry)
+ {
+ ServerMessage message = entry.getMessage();
+ if(message != null)
+ {
+ if(_messageNumber == message.getMessageNumber())
+ {
+ MessageReference reference = message.newReference();
+ _messageObject = convertToObject(entry, true);
+ reference.release();
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public Map<String, Object> getMessageObject()
+ {
+ return _messageObject;
+ }
+ }
+
+ private Map<String, Object> convertToObject(QueueEntry entry, boolean includeContent)
+ {
+ Map<String, Object> object = new LinkedHashMap<String, Object>();
+ object.put("size", entry.getSize());
+ object.put("deliveryCount", entry.getDeliveryCount());
+ object.put("state",entry.isAvailable()
+ ? "Available"
+ : entry.isAcquired()
+ ? "Acquired"
+ : "");
+ final Subscription deliveredSubscription = entry.getDeliveredSubscription();
+ object.put("deliveredTo", deliveredSubscription == null ? null : deliveredSubscription.getSubscriptionID());
+ ServerMessage message = entry.getMessage();
+
+ if(message != null)
+ {
+ convertMessageProperties(object, message);
+ if(includeContent)
+ {
+ convertMessageHeaders(object, message);
+ }
+ }
+
+ return object;
+ }
+
+ private void convertMessageProperties(Map<String, Object> object, ServerMessage message)
+ {
+ object.put("id", message.getMessageNumber());
+ object.put("arrivalTime",message.getArrivalTime());
+ object.put("persistent", message.isPersistent());
+
+ final AMQMessageHeader messageHeader = message.getMessageHeader();
+ if(messageHeader != null)
+ {
+ addIfPresent(object, "messageId", messageHeader.getMessageId());
+ addIfPresent(object, "expirationTime", messageHeader.getExpiration());
+ addIfPresent(object, "applicationId", messageHeader.getAppId());
+ addIfPresent(object, "correlationId", messageHeader.getCorrelationId());
+ addIfPresent(object, "encoding", messageHeader.getEncoding());
+ addIfPresent(object, "mimeType", messageHeader.getMimeType());
+ addIfPresent(object, "priority", messageHeader.getPriority());
+ addIfPresent(object, "replyTo", messageHeader.getReplyTo());
+ addIfPresent(object, "timestamp", messageHeader.getTimestamp());
+ addIfPresent(object, "type", messageHeader.getType());
+ addIfPresent(object, "userId", messageHeader.getUserId());
+ }
+
+ }
+
+ private void addIfPresent(Map<String, Object> object, String name, Object property)
+ {
+ if(property != null)
+ {
+ object.put(name, property);
+ }
+ }
+
+ private void convertMessageHeaders(Map<String, Object> object, ServerMessage message)
+ {
+ final AMQMessageHeader messageHeader = message.getMessageHeader();
+ if(messageHeader != null)
+ {
+ Map<String, Object> headers = new HashMap<String,Object>();
+ for(String headerName : messageHeader.getHeaderNames())
+ {
+ headers.put(headerName, messageHeader.getHeader(headerName));
+ }
+ object.put("headers", headers);
+ }
+ }
+
+ /*
+ * POST moves or copies messages to the given queue from a queue specified in the posted JSON data
+ */
+ @Override
+ protected void onPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
+ {
+
+ try
+ {
+ final Queue sourceQueue = getQueueFromRequest(request);
+
+ ObjectMapper mapper = new ObjectMapper();
+
+ @SuppressWarnings("unchecked")
+ Map<String,Object> providedObject = mapper.readValue(request.getInputStream(), LinkedHashMap.class);
+
+ String destQueueName = (String) providedObject.get("destinationQueue");
+ Boolean move = (Boolean) providedObject.get("move");
+
+ final VirtualHost vhost = sourceQueue.getParent(VirtualHost.class);
+
+ boolean isMoveTransaction = move != null && Boolean.valueOf(move);
+
+ // FIXME: added temporary authorization check until we introduce management layer
+ // and review current ACL rules to have common rules for all management interfaces
+ String methodName = isMoveTransaction? "moveMessages":"copyMessages";
+ if (isQueueUpdateMethodAuthorized(methodName, vhost.getName()))
+ {
+ final Queue destinationQueue = getQueueFromVirtualHost(destQueueName, vhost);
+ final List messageIds = new ArrayList((List) providedObject.get("messages"));
+ QueueEntryTransaction txn =
+ isMoveTransaction
+ ? new MoveTransaction(sourceQueue, messageIds, destinationQueue)
+ : new CopyTransaction(sourceQueue, messageIds, destinationQueue);
+ vhost.executeTransaction(txn);
+ response.setStatus(HttpServletResponse.SC_OK);
+ }
+ else
+ {
+ response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
+ }
+ }
+ catch(RuntimeException e)
+ {
+ LOGGER.error("Failure to perform message opertion", e);
+ response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+ }
+ }
+
+
+ /*
+ * DELETE removes messages from the queue
+ */
+ @Override
+ protected void onDelete(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
+ {
+
+ final Queue sourceQueue = getQueueFromRequest(request);
+
+ final VirtualHost vhost = sourceQueue.getParent(VirtualHost.class);
+
+
+ final List<Long> messageIds = new ArrayList<Long>();
+ for(String idStr : request.getParameterValues("id"))
+ {
+ messageIds.add(Long.valueOf(idStr));
+ }
+
+ // FIXME: added temporary authorization check until we introduce management layer
+ // and review current ACL rules to have common rules for all management interfaces
+ if (isQueueUpdateMethodAuthorized("deleteMessages", vhost.getName()))
+ {
+ vhost.executeTransaction(new DeleteTransaction(sourceQueue, messageIds));
+ response.setStatus(HttpServletResponse.SC_OK);
+ }
+ else
+ {
+ response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
+ }
+
+ }
+
+ private boolean isQueueUpdateMethodAuthorized(String methodName, String virtualHost)
+ {
+ SecurityManager securityManager = getSecurityManager(virtualHost);
+ return securityManager.authoriseMethod(Operation.UPDATE, "VirtualHost.Queue", methodName);
+ }
+
+ private SecurityManager getSecurityManager(String virtualHost)
+ {
+ IApplicationRegistry appRegistry = ApplicationRegistry.getInstance();
+ SecurityManager security;
+ if (virtualHost == null)
+ {
+ security = appRegistry.getSecurityManager();
+ }
+ else
+ {
+ security = appRegistry.getVirtualHostRegistry().getVirtualHost(virtualHost).getSecurityManager();
+ }
+ return security;
+ }
+
+}
diff --git a/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RestServlet.java b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RestServlet.java
new file mode 100644
index 0000000000..593377beed
--- /dev/null
+++ b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RestServlet.java
@@ -0,0 +1,586 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * <p/>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p/>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF 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.management.plugin.servlet.rest;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.net.SocketAddress;
+import java.util.*;
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.log4j.Logger;
+import org.apache.qpid.AMQSecurityException;
+import org.apache.qpid.server.model.*;
+import org.codehaus.jackson.map.ObjectMapper;
+import org.codehaus.jackson.map.SerializationConfig;
+
+
+public class RestServlet extends AbstractServlet
+{
+ private static final Logger LOGGER = Logger.getLogger(RestServlet.class);
+ /**
+ * An initialization parameter to specify hierarchy
+ */
+ private static final String HIERARCHY_INIT_PARAMETER = "hierarchy";
+
+ public static final String DEPTH_PARAM = "depth";
+ public static final String SORT_PARAM = "sort";
+
+ public static final Set<String> RESERVED_PARAMS = new HashSet<String>(Arrays.asList(DEPTH_PARAM, SORT_PARAM));
+
+ private Class<? extends ConfiguredObject>[] _hierarchy;
+
+ private volatile boolean initializationRequired = false;
+
+ public RestServlet()
+ {
+ super();
+ initializationRequired = true;
+ }
+
+ public RestServlet(Broker broker, Class<? extends ConfiguredObject>... hierarchy)
+ {
+ super(broker);
+ _hierarchy = hierarchy;
+ }
+
+ @Override
+ public void init() throws ServletException
+ {
+ if (initializationRequired)
+ {
+ doInitialization();
+ initializationRequired = false;
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ private void doInitialization() throws ServletException
+ {
+ ServletConfig config = getServletConfig();
+ String hierarchy = config.getInitParameter(HIERARCHY_INIT_PARAMETER);
+ if (hierarchy != null && !"".equals(hierarchy))
+ {
+ List<Class<? extends ConfiguredObject>> classes = new ArrayList<Class<? extends ConfiguredObject>>();
+ String[] hierarchyItems = hierarchy.split(",");
+ for (String item : hierarchyItems)
+ {
+ Class<?> itemClass = null;
+ try
+ {
+ itemClass = Class.forName(item);
+ }
+ catch (ClassNotFoundException e)
+ {
+ try
+ {
+ itemClass = Class.forName("org.apache.qpid.server.model." + item);
+ }
+ catch (ClassNotFoundException e1)
+ {
+ throw new ServletException("Unknown configured object class '" + item
+ + "' is specified in hierarchy for " + config.getServletName());
+ }
+ }
+ Class<? extends ConfiguredObject> clazz = (Class<? extends ConfiguredObject>)itemClass;
+ classes.add(clazz);
+ }
+ Class<? extends ConfiguredObject>[] hierachyClasses = (Class<? extends ConfiguredObject>[])new Class[classes.size()];
+ _hierarchy = classes.toArray(hierachyClasses);
+ }
+ else
+ {
+ _hierarchy = (Class<? extends ConfiguredObject>[])new Class[0];
+ }
+ }
+
+ protected Collection<ConfiguredObject> getObjects(HttpServletRequest request)
+ {
+ List<String> names = new ArrayList<String>();
+ if(request.getPathInfo() != null && request.getPathInfo().length()>0)
+ {
+ String path = request.getPathInfo().substring(1);
+ names.addAll(Arrays.asList(path.split("/")));
+
+ if(names.size() > _hierarchy.length)
+ {
+ throw new IllegalArgumentException("Too many entries in path");
+ }
+ }
+
+ Collection<ConfiguredObject> parents = Collections.singleton((ConfiguredObject) getBroker());
+ Collection<ConfiguredObject> children = new ArrayList<ConfiguredObject>();
+
+ Map<Class<? extends ConfiguredObject>, String> filters =
+ new HashMap<Class<? extends ConfiguredObject>, String>();
+
+ for(int i = 0; i < _hierarchy.length; i++)
+ {
+ if(i == 0 || Model.getChildTypes(_hierarchy[i - 1]).contains(_hierarchy[i]))
+ {
+
+ for(ConfiguredObject parent : parents)
+ {
+ if(names.size() > i
+ && names.get(i) != null
+ && !names.get(i).equals("*")
+ && names.get(i).trim().length() != 0)
+ {
+ for(ConfiguredObject child : parent.getChildren(_hierarchy[i]))
+ {
+ if(child.getName().equals(names.get(i)))
+ {
+ children.add(child);
+ }
+ }
+ }
+ else
+ {
+ children.addAll(parent.getChildren(_hierarchy[i]));
+ }
+ }
+ }
+ else
+ {
+ children = parents;
+ if(names.size() > i
+ && names.get(i) != null
+ && !names.get(i).equals("*")
+ && names.get(i).trim().length() != 0)
+ {
+ filters.put(_hierarchy[i], names.get(i));
+ }
+ }
+
+ parents = children;
+ children = new ArrayList<ConfiguredObject>();
+ }
+
+ if(!filters.isEmpty())
+ {
+ Collection<ConfiguredObject> potentials = parents;
+ parents = new ArrayList<ConfiguredObject>();
+
+ for(ConfiguredObject o : potentials)
+ {
+
+ boolean match = true;
+
+ for(Map.Entry<Class<? extends ConfiguredObject>, String> entry : filters.entrySet())
+ {
+ Collection<? extends ConfiguredObject> ancestors =
+ getAncestors(getConfiguredClass(),entry.getKey(), o);
+ match = false;
+ for(ConfiguredObject ancestor : ancestors)
+ {
+ if(ancestor.getName().equals(entry.getValue()))
+ {
+ match = true;
+ break;
+ }
+ }
+ if(!match)
+ {
+ break;
+ }
+ }
+ if(match)
+ {
+ parents.add(o);
+ }
+
+ }
+ }
+
+ return filter(parents, request);
+ }
+
+ private Collection<ConfiguredObject> filter(Collection<ConfiguredObject> objects, HttpServletRequest request)
+ {
+
+
+ Map<String, Collection<String>> filters = new HashMap<String, Collection<String>>();
+
+ for(String param : (Collection<String>) Collections.list(request.getParameterNames()))
+ {
+ if(!RESERVED_PARAMS.contains(param))
+ {
+ filters.put(param, Arrays.asList(request.getParameterValues(param)));
+ }
+ }
+
+ if(filters.isEmpty())
+ {
+ return objects;
+ }
+
+ Collection<ConfiguredObject> filteredObj = new ArrayList<ConfiguredObject>(objects);
+
+ Iterator<ConfiguredObject> iter = filteredObj.iterator();
+
+ while(iter.hasNext())
+ {
+ ConfiguredObject obj = iter.next();
+ for(Map.Entry<String, Collection<String>> entry : filters.entrySet())
+ {
+ Object value = obj.getAttribute(entry.getKey());
+ if(!entry.getValue().contains(String.valueOf(value)))
+ {
+ iter.remove();
+ }
+ }
+
+ }
+
+ return filteredObj;
+ }
+
+ private Collection<? extends ConfiguredObject> getAncestors(Class<? extends ConfiguredObject> childType,
+ Class<? extends ConfiguredObject> ancestorType,
+ ConfiguredObject child)
+ {
+ Collection<ConfiguredObject> ancestors = new HashSet<ConfiguredObject>();
+ Collection<Class<? extends ConfiguredObject>> parentTypes = Model.getParentTypes(childType);
+
+ for(Class<? extends ConfiguredObject> parentClazz : parentTypes)
+ {
+ if(parentClazz == ancestorType)
+ {
+ ConfiguredObject parent = child.getParent(parentClazz);
+ if(parent != null)
+ {
+ ancestors.add(parent);
+ }
+ }
+ else
+ {
+ ConfiguredObject parent = child.getParent(parentClazz);
+ if(parent != null)
+ {
+ ancestors.addAll(getAncestors(parentClazz, ancestorType, parent));
+ }
+ }
+ }
+
+ return ancestors;
+ }
+
+
+ protected Map<String, Object> convertObjectToMap(final ConfiguredObject confObject,
+ Class<? extends ConfiguredObject> clazz,
+ int depth)
+ {
+ Map<String, Object> object = new LinkedHashMap<String, Object>();
+
+ for(String name : confObject.getAttributeNames())
+ {
+ Object value = confObject.getAttribute(name);
+ if(value instanceof ConfiguredObject)
+ {
+ object.put(name, ((ConfiguredObject) value).getName());
+ }
+ else if(value != null)
+ {
+ object.put(name, value);
+ }
+ }
+
+ Statistics statistics = confObject.getStatistics();
+ Map<String, Object> statMap = new HashMap<String, Object>();
+ for(String name : statistics.getStatisticNames())
+ {
+ Object value = statistics.getStatistic(name);
+ if(value != null)
+ {
+ statMap.put(name, value);
+ }
+ }
+
+ if(!statMap.isEmpty())
+ {
+ object.put("statistics", statMap);
+ }
+
+ if(depth > 0)
+ {
+ for(Class<? extends ConfiguredObject> childClass : Model.getChildTypes(clazz))
+ {
+ Collection<? extends ConfiguredObject> children = confObject.getChildren(childClass);
+ if(children != null)
+ {
+ List<Map<String, Object>> childObjects = new ArrayList<Map<String, Object>>();
+
+ for(ConfiguredObject child : children)
+ {
+ childObjects.add(convertObjectToMap(child, childClass, depth-1));
+ }
+
+ if(!childObjects.isEmpty())
+ {
+ object.put(childClass.getSimpleName().toLowerCase()+"s",childObjects);
+ }
+ }
+ }
+ }
+ return object;
+ }
+
+ @Override
+ protected void onGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
+ {
+ response.setContentType("application/json");
+ response.setStatus(HttpServletResponse.SC_OK);
+
+ response.setHeader("Cache-Control","no-cache");
+ response.setHeader("Pragma","no-cache");
+ response.setDateHeader ("Expires", 0);
+
+ Collection<ConfiguredObject> allObjects = getObjects(request);
+
+ @SuppressWarnings("unchecked")
+ Map params = new HashMap(request.getParameterMap());
+
+ int depth = 1;
+ try
+ {
+ depth = Integer.parseInt(String.valueOf(params.remove("depth")));
+ }
+ catch (NumberFormatException e)
+ {
+ // Ignore
+ }
+
+ List<Map<String, Object>> output = new ArrayList<Map<String, Object>>();
+
+ // TODO - depth and sort special params, everything else should act as a filter
+ if(request.getParameter(DEPTH_PARAM)!=null)
+ {
+ try
+ {
+ depth = Integer.parseInt(request.getParameter(DEPTH_PARAM));
+ }
+ catch (NumberFormatException e)
+ {
+
+ }
+ }
+
+ for(ConfiguredObject configuredObject : allObjects)
+ {
+ output.add(convertObjectToMap(configuredObject, getConfiguredClass(),depth));
+ }
+
+ final PrintWriter writer = response.getWriter();
+ ObjectMapper mapper = new ObjectMapper();
+ mapper.configure(SerializationConfig.Feature.INDENT_OUTPUT, true);
+ mapper.writeValue(writer, output);
+
+ response.setContentType("application/json");
+ response.setStatus(HttpServletResponse.SC_OK);
+
+ }
+
+ private Class<? extends ConfiguredObject> getConfiguredClass()
+ {
+ return _hierarchy.length == 0 ? Broker.class : _hierarchy[_hierarchy.length-1];
+ }
+
+ @Override
+ protected void onPut(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
+ {
+ response.setContentType("application/json");
+
+ ObjectMapper mapper = new ObjectMapper();
+ @SuppressWarnings("unchecked")
+ Map<String,Object> providedObject = mapper.readValue(request.getInputStream(), LinkedHashMap.class);
+
+
+ List<String> names = new ArrayList<String>();
+ if(request.getPathInfo() != null && request.getPathInfo().length()>0)
+ {
+ String path = request.getPathInfo().substring(1);
+ names.addAll(Arrays.asList(path.split("/")));
+
+ if(names.size() != _hierarchy.length)
+ {
+ throw new IllegalArgumentException("Path to object to create must be fully specified");
+ }
+ }
+
+
+ providedObject.put("name", names.get(names.size()-1));
+
+ @SuppressWarnings("unchecked")
+ Collection<ConfiguredObject>[] objects = new Collection[_hierarchy.length];
+ if(_hierarchy.length == 1)
+ {
+ try
+ {
+ getBroker().createChild(_hierarchy[0], providedObject);
+ }
+ catch (RuntimeException e)
+ {
+ setResponseStatus(response, e);
+ return;
+ }
+
+ }
+ else
+ {
+ for(int i = 0; i < _hierarchy.length-1; i++)
+ {
+ objects[i] = new HashSet<ConfiguredObject>();
+ if(i == 0)
+ {
+ for(ConfiguredObject object : getBroker().getChildren(_hierarchy[0]))
+ {
+ if(object.getName().equals(names.get(0)))
+ {
+ objects[0].add(object);
+ break;
+ }
+ }
+ }
+ else
+ {
+ for(int j = i-1; j >=0; j--)
+ {
+ if(Model.getChildTypes(_hierarchy[j]).contains(_hierarchy[i]))
+ {
+ for(ConfiguredObject parent : objects[j])
+ {
+ for(ConfiguredObject object : parent.getChildren(_hierarchy[i]))
+ {
+ if(object.getName().equals(names.get(i)))
+ {
+ objects[i].add(object);
+ }
+ }
+ }
+ break;
+ }
+ }
+ }
+
+ }
+ List<ConfiguredObject> parents = new ArrayList<ConfiguredObject>();
+ Class<? extends ConfiguredObject> objClass = getConfiguredClass();
+ Collection<Class<? extends ConfiguredObject>> parentClasses = Model.getParentTypes(objClass);
+ for(int i = _hierarchy.length-2; i >=0 ; i--)
+ {
+ if(parentClasses.contains(_hierarchy[i]))
+ {
+ if(objects[i].size() == 1)
+ {
+ parents.add(objects[i].iterator().next());
+ }
+ else
+ {
+ throw new IllegalArgumentException("Cannot deduce parent of class "
+ + _hierarchy[i].getSimpleName());
+ }
+ }
+
+ }
+ ConfiguredObject theParent = parents.remove(0);
+ ConfiguredObject[] otherParents = parents.toArray(new ConfiguredObject[parents.size()]);
+
+ try
+ {
+
+ Collection<? extends ConfiguredObject> existingChildren = theParent.getChildren(objClass);
+ for(ConfiguredObject obj: existingChildren)
+ {
+ if((providedObject.containsKey("id") && String.valueOf(providedObject.get("id")).equals(obj.getId().toString()))
+ || (obj.getName().equals(providedObject.get("name")) && equalParents(obj, otherParents)))
+ {
+ doUpdate(obj, providedObject);
+ }
+ }
+ theParent.createChild(objClass, providedObject, otherParents);
+ }
+ catch (RuntimeException e)
+ {
+ setResponseStatus(response, e);
+ return;
+ }
+
+ }
+ response.setStatus(HttpServletResponse.SC_CREATED);
+ }
+
+ private void doUpdate(ConfiguredObject obj, Map<String, Object> providedObject)
+ {
+ for(Map.Entry<String,Object> entry : providedObject.entrySet())
+ {
+ obj.setAttribute(entry.getKey(), obj.getAttribute(entry.getKey()), entry.getValue());
+ }
+ //TODO - Implement.
+ }
+
+ private boolean equalParents(ConfiguredObject obj, ConfiguredObject[] otherParents)
+ {
+ if(otherParents == null || otherParents.length == 0)
+ {
+ return true;
+ }
+ return false; //TODO - Implement.
+ }
+
+ private void setResponseStatus(HttpServletResponse response, RuntimeException e) throws IOException
+ {
+ if (e.getCause() instanceof AMQSecurityException)
+ {
+ response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
+ }
+ else
+ {
+ LOGGER.warn("Unexpected exception is caught", e);
+
+ // TODO
+ response.setStatus(HttpServletResponse.SC_CONFLICT);
+ }
+ }
+
+ @Override
+ protected void onDelete(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
+ {
+ response.setContentType("application/json");
+ response.setStatus(HttpServletResponse.SC_OK);
+
+ response.setHeader("Cache-Control","no-cache");
+ response.setHeader("Pragma","no-cache");
+ response.setDateHeader ("Expires", 0);
+ try
+ {
+ Collection<ConfiguredObject> allObjects = getObjects(request);
+ for(ConfiguredObject o : allObjects)
+ {
+ o.setDesiredState(o.getActualState(), State.DELETED);
+ }
+
+ response.setStatus(HttpServletResponse.SC_OK);
+ }
+ catch(RuntimeException e)
+ {
+ setResponseStatus(response, e);
+ }
+ }
+}
diff --git a/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/SaslServlet.java b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/SaslServlet.java
new file mode 100644
index 0000000000..1b78611a50
--- /dev/null
+++ b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/SaslServlet.java
@@ -0,0 +1,256 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.management.plugin.servlet.rest;
+
+import org.apache.commons.codec.binary.Base64;
+import org.codehaus.jackson.map.ObjectMapper;
+import org.codehaus.jackson.map.SerializationConfig;
+
+import org.apache.log4j.Logger;
+import org.apache.qpid.server.model.Broker;
+import org.apache.qpid.server.registry.ApplicationRegistry;
+import org.apache.qpid.server.security.auth.manager.AuthenticationManager;
+import org.apache.qpid.server.security.auth.sasl.UsernamePrincipal;
+
+import javax.security.auth.Subject;
+import javax.security.sasl.SaslException;
+import javax.security.sasl.SaslServer;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.security.Principal;
+import java.security.SecureRandom;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Random;
+
+public class SaslServlet extends AbstractServlet
+{
+ private static final Logger LOGGER = Logger.getLogger(SaslServlet.class);
+
+ private static final SecureRandom SECURE_RANDOM = new SecureRandom();
+ private static final String ATTR_RANDOM = "SaslServlet.Random";
+ private static final String ATTR_ID = "SaslServlet.ID";
+ private static final String ATTR_SASL_SERVER = "SaslServlet.SaslServer";
+ private static final String ATTR_EXPIRY = "SaslServlet.Expiry";
+ private static final long SASL_EXCHANGE_EXPIRY = 1000L;
+
+
+ public SaslServlet()
+ {
+ super();
+ }
+
+ public SaslServlet(Broker broker)
+ {
+ super(broker);
+ }
+
+ protected void onGet(HttpServletRequest request, HttpServletResponse response) throws
+ ServletException,
+ IOException
+ {
+ response.setContentType("application/json");
+ response.setStatus(HttpServletResponse.SC_OK);
+
+ response.setHeader("Cache-Control","no-cache");
+ response.setHeader("Pragma","no-cache");
+ response.setDateHeader ("Expires", 0);
+
+ HttpSession session = request.getSession();
+ Random rand = getRandom(session);
+
+ AuthenticationManager authManager = ApplicationRegistry.getInstance().getAuthenticationManager(getSocketAddress(request));
+ String[] mechanisms = authManager.getMechanisms().split(" ");
+ Map<String, Object> outputObject = new LinkedHashMap<String, Object>();
+ final Subject subject = (Subject) session.getAttribute("subject");
+ if(subject != null)
+ {
+ final Principal principal = subject.getPrincipals().iterator().next();
+ outputObject.put("user", principal.getName());
+ }
+ else if (request.getRemoteUser() != null)
+ {
+ outputObject.put("user", request.getRemoteUser());
+ }
+
+ outputObject.put("mechanisms", (Object) mechanisms);
+
+ final PrintWriter writer = response.getWriter();
+
+ ObjectMapper mapper = new ObjectMapper();
+ mapper.configure(SerializationConfig.Feature.INDENT_OUTPUT, true);
+ mapper.writeValue(writer, outputObject);
+
+ }
+
+ private Random getRandom(final HttpSession session)
+ {
+ Random rand = (Random) session.getAttribute(ATTR_RANDOM);
+ if(rand == null)
+ {
+ synchronized (SECURE_RANDOM)
+ {
+ rand = new Random(SECURE_RANDOM.nextLong());
+ }
+ session.setAttribute(ATTR_RANDOM, rand);
+ }
+ return rand;
+ }
+
+
+ @Override
+ protected void onPost(final HttpServletRequest request, final HttpServletResponse response)
+ throws ServletException, IOException
+ {
+ try
+ {
+ response.setContentType("application/json");
+ response.setHeader("Cache-Control","no-cache");
+ response.setHeader("Pragma","no-cache");
+ response.setDateHeader("Expires", 0);
+
+ HttpSession session = request.getSession();
+
+ String mechanism = request.getParameter("mechanism");
+ String id = request.getParameter("id");
+ String saslResponse = request.getParameter("response");
+
+ AuthenticationManager authManager = ApplicationRegistry.getInstance().getAuthenticationManager(getSocketAddress(request));
+
+ if(mechanism != null)
+ {
+ if(id == null)
+ {
+ SaslServer saslServer = authManager.createSaslServer(mechanism, request.getServerName(), null/*TODO*/);
+ evaluateSaslResponse(response, session, saslResponse, saslServer);
+ }
+ else
+ {
+ response.setStatus(HttpServletResponse.SC_EXPECTATION_FAILED);
+ session.removeAttribute(ATTR_ID);
+ session.removeAttribute(ATTR_SASL_SERVER);
+ session.removeAttribute(ATTR_EXPIRY);
+
+ }
+
+ }
+ else
+ {
+ if(id != null)
+ {
+ if(id.equals(session.getAttribute(ATTR_ID)) && System.currentTimeMillis() < (Long) session.getAttribute(ATTR_EXPIRY))
+ {
+ SaslServer saslServer = (SaslServer) session.getAttribute(ATTR_SASL_SERVER);
+ evaluateSaslResponse(response, session, saslResponse, saslServer);
+
+ }
+ else
+ {
+ response.setStatus(HttpServletResponse.SC_EXPECTATION_FAILED);
+ session.removeAttribute(ATTR_ID);
+ session.removeAttribute(ATTR_SASL_SERVER);
+ session.removeAttribute(ATTR_EXPIRY);
+ }
+ }
+ else
+ {
+ response.setStatus(HttpServletResponse.SC_EXPECTATION_FAILED);
+ session.removeAttribute(ATTR_ID);
+ session.removeAttribute(ATTR_SASL_SERVER);
+ session.removeAttribute(ATTR_EXPIRY);
+
+ }
+ }
+ }
+ catch(IOException e)
+ {
+ LOGGER.error("Error processing SASL request", e);
+ throw e;
+ }
+ catch(RuntimeException e)
+ {
+ LOGGER.error("Error processing SASL request", e);
+ throw e;
+ }
+
+ }
+
+ private void evaluateSaslResponse(final HttpServletResponse response,
+ final HttpSession session,
+ final String saslResponse, final SaslServer saslServer) throws IOException
+ {
+ final String id;
+ byte[] challenge;
+ try
+ {
+ challenge = saslServer.evaluateResponse(saslResponse == null ? new byte[0] : Base64.decodeBase64(saslResponse.getBytes()));
+ }
+ catch(SaslException e)
+ {
+
+ session.removeAttribute(ATTR_ID);
+ session.removeAttribute(ATTR_SASL_SERVER);
+ session.removeAttribute(ATTR_EXPIRY);
+ response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
+
+ return;
+ }
+
+ if(saslServer.isComplete())
+ {
+ final Subject subject = new Subject();
+ subject.getPrincipals().add(new UsernamePrincipal(saslServer.getAuthorizationID()));
+ session.setAttribute("subject", subject);
+ session.removeAttribute(ATTR_ID);
+ session.removeAttribute(ATTR_SASL_SERVER);
+ session.removeAttribute(ATTR_EXPIRY);
+
+ response.setStatus(HttpServletResponse.SC_OK);
+
+
+ }
+ else
+ {
+ Random rand = getRandom(session);
+ id = String.valueOf(rand.nextLong());
+ session.setAttribute(ATTR_ID, id);
+ session.setAttribute(ATTR_SASL_SERVER, saslServer);
+ session.setAttribute(ATTR_EXPIRY, System.currentTimeMillis() + SASL_EXCHANGE_EXPIRY);
+
+ response.setStatus(HttpServletResponse.SC_OK);
+
+ Map<String, Object> outputObject = new LinkedHashMap<String, Object>();
+ outputObject.put("id", id);
+ outputObject.put("challenge", new String(Base64.encodeBase64(challenge)));
+
+ final PrintWriter writer = response.getWriter();
+
+ ObjectMapper mapper = new ObjectMapper();
+ mapper.configure(SerializationConfig.Feature.INDENT_OUTPUT, true);
+ mapper.writeValue(writer, outputObject);
+
+ }
+ }
+}
diff --git a/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/StructureServlet.java b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/StructureServlet.java
new file mode 100644
index 0000000000..e4ba374f89
--- /dev/null
+++ b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/StructureServlet.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
+ * <p/>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p/>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF 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.management.plugin.servlet.rest;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.qpid.server.model.Broker;
+import org.apache.qpid.server.model.ConfiguredObject;
+import org.apache.qpid.server.model.Model;
+import org.codehaus.jackson.map.ObjectMapper;
+import org.codehaus.jackson.map.SerializationConfig;
+
+public class StructureServlet extends AbstractServlet
+{
+ public StructureServlet()
+ {
+ super();
+ }
+
+ public StructureServlet(Broker broker)
+ {
+ super(broker);
+ }
+
+ @Override
+ protected void onGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
+ {
+ response.setContentType("application/json");
+ response.setStatus(HttpServletResponse.SC_OK);
+
+ response.setHeader("Cache-Control","no-cache");
+ response.setHeader("Pragma","no-cache");
+ response.setDateHeader ("Expires", 0);
+
+ Map<String,Object> structure = generateStructure(getBroker(), Broker.class);
+
+ final PrintWriter writer = response.getWriter();
+ ObjectMapper mapper = new ObjectMapper();
+ mapper.configure(SerializationConfig.Feature.INDENT_OUTPUT, true);
+ mapper.writeValue(writer, structure);
+
+ response.setStatus(HttpServletResponse.SC_OK);
+
+ }
+
+ private Map<String, Object> generateStructure(ConfiguredObject object, Class<? extends ConfiguredObject> clazz)
+ {
+ Map<String, Object> structure = new LinkedHashMap<String, Object>();
+ structure.put("id", object.getId());
+ structure.put("name", object.getName());
+
+ for(Class<? extends ConfiguredObject> childClass : Model.getChildTypes(clazz))
+ {
+ Collection<? extends ConfiguredObject> children = object.getChildren(childClass);
+ if(children != null)
+ {
+ List<Map<String, Object>> childObjects = new ArrayList<Map<String, Object>>();
+
+ for(ConfiguredObject child : children)
+ {
+ childObjects.add(generateStructure(child, childClass));
+ }
+
+ if(!childObjects.isEmpty())
+ {
+ structure.put(pluralize(childClass),childObjects);
+ }
+ }
+ }
+
+ return structure;
+ }
+
+ private String pluralize(Class<? extends ConfiguredObject> childClass)
+ {
+ String name = childClass.getSimpleName().toLowerCase();
+ return name + (name.endsWith("s") ? "es" : "s");
+ }
+}
diff --git a/java/broker-plugins/management-http/src/main/java/resources/addBinding.html b/java/broker-plugins/management-http/src/main/java/resources/addBinding.html
new file mode 100644
index 0000000000..8dbd219c8d
--- /dev/null
+++ b/java/broker-plugins/management-http/src/main/java/resources/addBinding.html
@@ -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.
+ -->
+<div class="dijitHidden">
+ <div data-dojo-type="dijit.Dialog" style="width:600px;" data-dojo-props="title:'Add Binding'" id="addBinding">
+ <form id="formAddBinding" method="post" dojoType="dijit.form.Form">
+ <table cellpadding="0" cellspacing="2">
+ <tr>
+ <td valign="top"><strong>Exchange Name*: </strong></td>
+ <td><div id="addBinding.selectExchangeDiv"></div></td>
+ </tr>
+ <tr>
+ <td valign="top"><strong>Queue Name*: </strong></td>
+ <td><div id="addBinding.selectQueueDiv"></div></td>
+ </tr>
+ <tr>
+ <td valign="top"><strong>Binding Key*: </strong></td>
+ <td><input type="text" required="true" name="name" id="formAddbinding.bindingKey" placeholder="Binding Key"
+ dojoType="dijit.form.ValidationTextBox" missingMessage="A name must be supplied" /></td>
+ </tr>
+ </table>
+ <br/>
+
+ <!-- submit buttons -->
+ <input type="submit" value="Create Binding" label="Create Binding" dojoType="dijit.form.Button" />
+
+ </form>
+ </div>
+</div>
diff --git a/java/broker-plugins/management-http/src/main/java/resources/addExchange.html b/java/broker-plugins/management-http/src/main/java/resources/addExchange.html
new file mode 100644
index 0000000000..10ac5388ff
--- /dev/null
+++ b/java/broker-plugins/management-http/src/main/java/resources/addExchange.html
@@ -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.
+ -
+ -->
+<div class="dijitHidden">
+ <div data-dojo-type="dijit.Dialog" style="width:600px;" data-dojo-props="title:'Add Exchange'" id="addExchange">
+ <form id="formAddExchange" method="post" dojoType="dijit.form.Form">
+ <table cellpadding="0" cellspacing="2">
+ <tr>
+ <td valign="top"><strong>Exchange Name*: </strong></td>
+ <td><input type="text" required="true" name="name" id="formAddExchange.name" placeholder="Exchange Name"
+ dojoType="dijit.form.ValidationTextBox" missingMessage="A name must be supplied"
+ data-dojo-props="regExp:'^(?!qpid\.|amq\.|\<\<default\>\>).*$', invalidMessage:'Reserved exchange name!'"/></td>
+ </tr>
+ <tr>
+ <td valign="top"><strong>Durable? </strong></td>
+ <td><input type="checkbox" name="durable" id="formAddExchange.durable" value="durable" checked="checked" dojoType="dijit.form.CheckBox" /></td>
+ </tr>
+ <tr>
+ <td valign="top"><strong>Exchange Type: </strong></td>
+ <td>
+ <select name="type" id="formAddExchange.type" dojoType="dijit.form.FilteringSelect">
+ <option value="direct">direct</option>
+ <option value="topic">topic</option>
+ <option value="headers">headers</option>
+ <option value="fanout">fanout</option>
+ </select>
+ </td>
+ </tr>
+ </table>
+ <br/>
+
+ <!-- submit buttons -->
+ <input type="submit" value="Create Exchange" label="Create Exchange" dojoType="dijit.form.Button" />
+
+ </form>
+ </div>
+</div>
diff --git a/java/broker-plugins/management-http/src/main/java/resources/addQueue.html b/java/broker-plugins/management-http/src/main/java/resources/addQueue.html
new file mode 100644
index 0000000000..d396f28877
--- /dev/null
+++ b/java/broker-plugins/management-http/src/main/java/resources/addQueue.html
@@ -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.
+ -
+ -->
+<div class="dijitHidden">
+ <div data-dojo-type="dijit.Dialog" style="width:600px;" data-dojo-props="title:'Add Queue'" id="addQueue">
+ <form id="formAddQueue" method="post" dojoType="dijit.form.Form">
+ <table cellpadding="0" cellspacing="2">
+ <tr>
+ <td valign="top"><strong>Queue Name*: </strong></td>
+ <td><input type="text" required="true" name="name" id="formAddQueue.name" placeholder="Queue Name"
+ dojoType="dijit.form.ValidationTextBox" missingMessage="A name must be supplied" /></td>
+ </tr>
+ <tr>
+ <td valign="top"><strong>Durable? </strong></td>
+ <td><input type="checkbox" name="durable" id="formAddQueue.durable" value="durable" checked="checked" dojoType="dijit.form.CheckBox" /></td>
+ </tr>
+ <tr>
+ <td valign="top"><strong>Queue Type: </strong></td>
+ <td>
+ <input type="radio" id="formAddQueueTypeStandard" name="type" value="standard" checked="checked" dojoType="dijit.form.RadioButton" />
+ <label for="formAddQueueTypeStandard">Standard</label>
+ &nbsp;&nbsp;
+ <input type="radio" id="formAddQueueTypePriority" name="type" value="priority" dojoType="dijit.form.RadioButton" />
+ <label for="formAddQueueTypePriority">Priority</label>
+ &nbsp;&nbsp;
+ <input type="radio" id="formAddQueueTypeLVQ" name="type" value="lvq" dojoType="dijit.form.RadioButton" />
+ <label for="formAddQueueTypeLVQ">LVQ</label>
+ &nbsp;&nbsp;
+ <input type="radio" id="formAddQueueTypeSorted" name="type" value="sorted" dojoType="dijit.form.RadioButton" />
+ <label for="formAddQueueTypeSorted">Sorted</label>
+ </td>
+ </tr>
+ </table>
+ <br/>
+
+ <div id="formAddQueueTypePriority:fields" style="display:none"
+ data-dojo-type="dijit.TitlePane" data-dojo-props="title: 'Priority Queue Settings'">
+ <table cellpadding="0" cellspacing="2">
+ <tr>
+ <td valign="top"><strong>Priorities: </strong></td>
+ <td><input data-dojo-type="dijit.form.NumberSpinner" id="formAddQueue.priorities"
+ name="priorities" value="10" smallDelta="1" constraints="{min:1,max:10,places:0}"/>
+ </tr>
+ </table>
+ </div>
+
+
+ <div id="formAddQueueTypeLVQ:fields" style="display:none"
+ data-dojo-type="dijit.TitlePane" data-dojo-props="title: 'Last Value Queue Settings'">
+ <table cellpadding="0" cellspacing="2">
+ <tr>
+ <td valign="top"><strong>LVQ Message Property: </strong></td>
+ <td><input type="text" name="lvqKey" id="formAddQueue.lvqkey"
+ placeholder="qpid.LVQ_key" dojoType="dijit.form.ValidationTextBox" /></td>
+ </tr>
+ </table>
+ </div>
+
+ <div id="formAddQueueTypeSorted:fields" style="display:none"
+ data-dojo-type="dijit.TitlePane" data-dojo-props="title: 'Sorted Queue Settings'">
+ <table cellpadding="0" cellspacing="2">
+ <tr>
+ <td valign="top"><strong>Sort Message Property: </strong></td>
+ <td><input type="text" name="sortKey" id="formAddQueue.sortkey" required="false"
+ placeholder="" dojoType="dijit.form.ValidationTextBox" /></td>
+ </tr>
+ </table>
+ </div>
+
+ <br/>
+ <div data-dojo-type="dijit.TitlePane" data-dojo-props="title: 'Flow Control Settings', open: false">
+ <table cellpadding="0" cellspacing="2">
+
+ <!-- x-qpid-capacity -->
+ <tr>
+ <td valign="top"><strong>Capacity: </strong></td>
+ <td><input type="text" required="false" name="queueFlowControlSizeBytes" id="formAddQueue.capacity" placeholder="Size in bytes"
+ dojoType="dijit.form.ValidationTextBox"
+ trim="true"
+ regexp="[0-9]+"
+ invalidMessage= "Invalid value"/></td>
+ </tr>
+ <!-- x-qpid-flow-resume-capacity -->
+ <tr>
+ <td valign="top"><strong>Resume Capacity: </strong></td>
+ <td><input type="text" required="false" name="queueFlowResumeSizeBytes" id="formAddQueue.flowResumeCapacity" placeholder="Size in bytes"
+ dojoType="dijit.form.ValidationTextBox"
+ trim="true"
+ regexp="[0-9]+"
+ invalidMessage= "Invalid value"/></td>
+ </tr>
+ </table>
+ </div>
+ <br/>
+ <div data-dojo-type="dijit.TitlePane" data-dojo-props="title: 'Alerting Settings', open: false">
+ <table cellpadding="0" cellspacing="2">
+ <!-- x-qpid-maximum-message-count -->
+ <tr>
+ <td valign="top"><strong>Queue Depth: </strong></td>
+ <td><input type="text" required="false" name="alertThresholdQueueDepthMessages" id="formAddQueue.maximumMessageCount" placeholder="Count of messages"
+ dojoType="dijit.form.ValidationTextBox"
+ trim="true"
+ regexp="[0-9]+"
+ invalidMessage= "Invalid value" /></td>
+ </tr>
+ <!-- x-qpid-maximum-message-age -->
+ <tr>
+ <td valign="top"><strong>Message Age: </strong></td>
+ <td><input type="text" required="false" name="alertThresholdMessageAge" id="formAddQueue.maximumMessageAge" placeholder="Time in ms"
+ dojoType="dijit.form.ValidationTextBox"
+ trim="true"
+ regexp="[0-9]+"
+ invalidMessage= "Invalid value" /></td>
+ </tr>
+ <!-- x-qpid-maximum-message-size -->
+ <tr>
+ <td valign="top"><strong>Message Size: </strong></td>
+ <td><input type="text" required="false" name="alertThresholdMessageSize" id="formAddQueue.maximumMessageSize" placeholder="Size in bytes"
+ dojoType="dijit.form.ValidationTextBox"
+ trim="true"
+ regexp="[0-9]+"
+ invalidMessage= "Invalid value"/></td>
+ </tr>
+ <!-- x-qpid-minimum-alert-repeat-gap -->
+ <tr>
+ <td valign="top"><strong>Gap between alerts: </strong></td>
+ <td><input type="text" required="false" name="alertRepeatGap" id="formAddQueue.minimumAlertRepeatGap" placeholder="Time in ms"
+ dojoType="dijit.form.ValidationTextBox"
+ trim="true"
+ regexp="[0-9]+"
+ invalidMessage= "Invalid value" /></td>
+ </tr>
+ </table>
+ </div>
+ <br/>
+ <div data-dojo-type="dijit.TitlePane" data-dojo-props="title: 'Other Settings', open: false">
+ <table cellpadding="0" cellspacing="2">
+
+ <!-- x-qpid-maximum-delivery-count -->
+ <tr>
+ <td valign="top"><strong>Maximum Delivery Retries: </strong></td>
+ <td><input type="text" required="false" name="maximumDeliveryAttempts" id="formAddQueue.maximumDeliveryCount"
+ dojoType="dijit.form.ValidationTextBox"
+ trim="true"
+ regexp="[0-9]+"
+ invalidMessage= "Invalid value"/></td>
+ </tr>
+ <tr>
+ <td valign="top"><strong>Create DLQ? </strong></td>
+ <td><input type="checkbox" name="dlqEnabled" id="formAddQueue.dlqEnabled" value="dlqEnabled" dojoType="dijit.form.CheckBox" /></td>
+ </tr>
+ </table>
+ <table cellpadding="0" cellspacing="2">
+ <tr>
+ <td valign="top">NOTE: Configuring maximum delivery retries on a queue which has no DLQ / AlternateExchange will result in messages being discarded after the limit is reached.</td>
+ </tr>
+ </table>
+ </div>
+ <br/>
+ <!-- submit buttons -->
+ <input type="submit" value="Create Queue" label="Create Queue" dojoType="dijit.form.Button" />
+
+ </form>
+ </div>
+</div>
diff --git a/java/broker-plugins/management-http/src/main/java/resources/authenticationprovider/addUser.html b/java/broker-plugins/management-http/src/main/java/resources/authenticationprovider/addUser.html
new file mode 100644
index 0000000000..785605f694
--- /dev/null
+++ b/java/broker-plugins/management-http/src/main/java/resources/authenticationprovider/addUser.html
@@ -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.
+ -
+ -->
+<div class="dijitHidden">
+ <div data-dojo-type="dijit.Dialog" style="width:600px;" data-dojo-props="title:'Add User'" id="addUser">
+ <form id="formAddUser" method="post" dojoType="dijit.form.Form">
+ <table cellpadding="0" cellspacing="2">
+ <tr>
+ <td valign="top"><strong>User Name*: </strong></td>
+ <td><input type="text" required="true" name="name" id="formAddUser.name" placeholder="User Name"
+ dojoType="dijit.form.ValidationTextBox" missingMessage="A name must be supplied" /></td>
+ </tr>
+ <tr>
+ <td valign="top"><strong>Password*</strong></td>
+ <td><input type="password" required="true" name="password" id="formAddUser.password" dojoType="dijit.form.ValidationTextBox"/></td>
+ </tr>
+ </table>
+ <br/>
+
+ <!-- submit buttons -->
+ <input type="submit" value="Create User" label="Create User" dojoType="dijit.form.Button" />
+
+ </form>
+ </div>
+</div>
diff --git a/java/broker-plugins/management-http/src/main/java/resources/authenticationprovider/setPassword.html b/java/broker-plugins/management-http/src/main/java/resources/authenticationprovider/setPassword.html
new file mode 100644
index 0000000000..3d67463abd
--- /dev/null
+++ b/java/broker-plugins/management-http/src/main/java/resources/authenticationprovider/setPassword.html
@@ -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.
+ -
+ -->
+<div class="dijitHidden">
+ <div data-dojo-type="dijit.Dialog" style="width:600px;" data-dojo-props="title:'Set Password'" id="setPassword">
+ <form id="formSetPassword" method="post" dojoType="dijit.form.Form">
+ <table cellpadding="0" cellspacing="2">
+ <tr>
+ <td valign="top"><strong>User Name: </strong></td>
+ <td><input type="text" required="true" name="name" id="formSetPassword.name" placeholder="User Name"
+ dojoType="dijit.form.TextBox" enabled="false" /></td>
+ </tr>
+ <tr>
+ <td valign="top"><strong>Password*</strong></td>
+ <td><input type="password" required="true" name="password" id="formSetPassword.password" dojoType="dijit.form.ValidationTextBox"/></td>
+ </tr>
+ </table>
+ <br/>
+
+ <!-- submit buttons -->
+ <input type="submit" value="Set Password" label="Set Password" dojoType="dijit.form.Button" />
+
+ </form>
+ </div>
+</div>
diff --git a/java/broker-plugins/experimental/shutdown/build.xml b/java/broker-plugins/management-http/src/main/java/resources/authenticationprovider/showPrincipalDatabaseAuthenticationManager.html
index cb4254806b..baadc8c35f 100644
--- a/java/broker-plugins/experimental/shutdown/build.xml
+++ b/java/broker-plugins/management-http/src/main/java/resources/authenticationprovider/showPrincipalDatabaseAuthenticationManager.html
@@ -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
@@ -18,15 +18,12 @@
- under the License.
-
-->
-<project name="AMQ Broker Shutdown Plugin" default="build">
-
- <property name="module.depends" value="common broker management/common broker-plugins"/>
- <property name="module.test.depends" value="test broker/test management/common client systests"/>
- <property name="module.manifest" value="MANIFEST.MF"/>
- <property name="module.plugin" value="true"/>
-
- <import file="../../../module.xml"/>
+<div class="PrincipalDatabaseAuthenticationManager">
+ <div data-dojo-type="dijit.TitlePane" data-dojo-props="title: 'Users'">
+ <div class="users"></div>
+ <button data-dojo-type="dijit.form.Button" class="addUserButton">Add User</button>
+ <button data-dojo-type="dijit.form.Button" class="deleteUserButton">Delete Users</button>
- <target name="bundle" depends="bundle-tasks"/>
+ </div>
-</project>
+</div>
diff --git a/java/broker-plugins/management-http/src/main/java/resources/css/common.css b/java/broker-plugins/management-http/src/main/java/resources/css/common.css
new file mode 100644
index 0000000000..78780edcd9
--- /dev/null
+++ b/java/broker-plugins/management-http/src/main/java/resources/css/common.css
@@ -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.
+ *
+ */
+* {
+ outline: none !important;
+}
+
+html, body {
+ height: 100%;
+ margin: 0;
+ margin-right: 40px;
+ padding: 0;
+ overflow: hidden;
+ font-family: Lucida Sans,Lucida Grande,Arial !important;
+ font-size: 13px !important;
+ background: white;
+ color: #333;
+}
+
+#pageLayout {
+ height: 100%;
+}
+button {
+ -webkit-transition: background-color 0.2s linear;
+ border-radius:4px;
+ -moz-border-radius: 4px 4px 4px 4px;
+ -moz-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.15);
+ background-color: #E4F2FF;
+ background-image: url("../dojo/dijit/themes/claro/form/images/button.png");
+ background-position: center top;
+ background-repeat: repeat-x;
+ border: 1px solid #769DC0;
+ padding: 2px 8px 4px;
+ font-size:1em;
+}
+
+button:hover {
+ background-color: #AFD9FF;
+ color: #000000;
+}
+
+h1 {
+ font-size:1.5em;
+}
+
+.header {
+ height:100px;
+ background:url("../images/qpid-logo.png") left center no-repeat
+}
+
+.logo {
+ text-align:left;
+ vertical-align: top;
+ font-weight:600;
+ height: 90px;
+ padding-left: 200px;
+ padding-top: 1px;
+ padding-bottom: 10px;
+ font-size:14px;
+ font-family:"Verdana", cursive;
+}
+
+.footer {
+ color:#000000;
+ clear:both;
+ text-align:center;
+ font-size:11px;
+ line-height:17px;
+
+}
+
+div .messages {
+ width: 100%;
+ height: 350px;
+} \ No newline at end of file
diff --git a/java/broker-plugins/management-http/src/main/java/resources/footer.html b/java/broker-plugins/management-http/src/main/java/resources/footer.html
new file mode 100644
index 0000000000..fa84825e80
--- /dev/null
+++ b/java/broker-plugins/management-http/src/main/java/resources/footer.html
@@ -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.
+ -
+ -->
+
+<div class="footer"><p>&#xA9; 2004-<span class="currentYear">2012</span> 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.
+</div> \ No newline at end of file
diff --git a/java/broker-plugins/management-http/src/main/java/resources/images/qpid-logo.png b/java/broker-plugins/management-http/src/main/java/resources/images/qpid-logo.png
new file mode 100644
index 0000000000..95d49ea469
--- /dev/null
+++ b/java/broker-plugins/management-http/src/main/java/resources/images/qpid-logo.png
Binary files differ
diff --git a/java/broker-plugins/management-http/src/main/java/resources/js/qpid/authorization/sasl.js b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/authorization/sasl.js
new file mode 100644
index 0000000000..152504da86
--- /dev/null
+++ b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/authorization/sasl.js
@@ -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.
+ *
+ */
+require(["dijit/form/DropDownButton", "dijit/TooltipDialog", "dijit/form/TextBox",
+ "dojo/_base/xhr", "dojox/encoding/base64", "dojox/encoding/digests/_base", "dojox/encoding/digests/MD5"]);
+var button;
+var usernameSpan;
+
+var encodeUTF8 = function encodeUTF8(str) {
+ var byteArray = [];
+ for (var i = 0; i < str.length; i++) {
+ if (str.charCodeAt(i) <= 0x7F) {
+ byteArray.push(str.charCodeAt(i));
+ }
+ else {
+ var h = encodeURIComponent(str.charAt(i)).substr(1).split('%');
+ for (var j = 0; j < h.length; j++)
+ byteArray.push(parseInt(h[j], 16));
+ }
+ }
+ return byteArray;
+};
+
+var decodeUTF8 = function decodeUTF8(byteArray)
+{
+ var str = '';
+ for (var i = 0; i < byteArray.length; i++)
+ str += byteArray[i] <= 0x7F?
+ byteArray[i] === 0x25 ? "%25" :
+ String.fromCharCode(byteArray[i]) :
+ "%" + byteArray[i].toString(16).toUpperCase();
+ return decodeURIComponent(str);
+};
+
+
+var saslPlain = function saslPlain(user, password)
+{
+ var responseArray = [ 0 ].concat(encodeUTF8( user )).concat( [ 0 ] ).concat( encodeUTF8( password ) );
+ var plainResponse = dojox.encoding.base64.encode(responseArray);
+
+ // Using dojo.xhrGet, as very little information is being sent
+ dojo.xhrPost({
+ // The URL of the request
+ url: "rest/sasl",
+ content: {
+ mechanism: "PLAIN",
+ response: plainResponse
+ },
+ handleAs: "json",
+ failOk: true
+ }).then(function()
+ {
+ updateAuthentication();
+ },
+ function(error)
+ {
+ if(error.status == 401)
+ {
+ alert("Authentication Failed");
+ }
+ else
+ {
+ alert(error);
+ }
+ updateAuthentication();
+ });
+};
+
+var saslCramMD5 = function saslCramMD5(user, password)
+{
+
+ // Using dojo.xhrGet, as very little information is being sent
+ dojo.xhrPost({
+ // The URL of the request
+ url: "rest/sasl",
+ content: {
+ mechanism: "CRAM-MD5"
+ },
+ handleAs: "json",
+ failOk: true
+ }).then(function(data)
+ {
+
+ var challengeBytes = dojox.encoding.base64.decode(data.challenge);
+ var wa=[];
+ var bitLength = challengeBytes.length*8;
+ for(var i=0; i<bitLength; i+=8)
+ {
+ wa[i>>5] |= (challengeBytes[i/8] & 0xFF)<<(i%32);
+ }
+ var challengeStr = dojox.encoding.digests.wordToString(wa).substring(0,challengeBytes.length);
+
+ var digest = user + " " + dojox.encoding.digests.MD5._hmac(challengeStr, password, dojox.encoding.digests.outputTypes.Hex);
+ var id = data.id;
+
+ var response = dojox.encoding.base64.encode(encodeUTF8( digest ));
+
+ dojo.xhrPost({
+ // The URL of the request
+ url: "rest/sasl",
+ content: {
+ id: id,
+ response: response
+ },
+ handleAs: "json",
+ failOk: true
+ }).then(function()
+ {
+ updateAuthentication();
+ },
+ function(error)
+ {
+ if(error.status == 401)
+ {
+ alert("Authentication Failed");
+ }
+ else
+ {
+ alert(error);
+ }
+ updateAuthentication();
+ });
+
+ },
+ function(error)
+ {
+ if(error.status == 401)
+ {
+ alert("Authentication Failed");
+ }
+ else
+ {
+ alert(error);
+ }
+ });
+};
+
+var doAuthenticate = function doAuthenticate()
+{
+ saslCramMD5(dojo.byId("username").value, dojo.byId("pass").value);
+ updateAuthentication();
+};
+
+
+var updateAuthentication = function updateAuthentication()
+{
+ dojo.xhrGet({
+ // The URL of the request
+ url: "rest/sasl",
+ handleAs: "json"
+ }).then(function(data)
+ {
+ if(data.user)
+ {
+ dojo.byId("authenticatedUser").innerHTML = data.user;
+ dojo.style(button.domNode, {visibility: 'hidden'});
+ dojo.style(usernameSpan, {visibility: 'visible'});
+ }
+ else
+ {
+ dojo.style(button.domNode, {visibility: 'visible'});
+ dojo.style(usernameSpan, {visibility: 'hidden'});
+ }
+ }
+ );
+};
+
+require(["dijit/form/DropDownButton", "dijit/TooltipDialog", "dijit/form/TextBox", "dojo/_base/xhr", "dojo/dom", "dojo/dom-construct", "dojo/domReady!"],
+ function(DropDownButton, TooltipDialog, TextBox, xhr, dom, domConstruct){
+ var dialog = new TooltipDialog({
+ content:
+ '<strong><label for="username" style="display:inline-block;width:100px;">Username:</label></strong>' +
+ '<div data-dojo-type="dijit.form.TextBox" id="username"></div><br/>' +
+ '<strong><label for="pass" style="display:inline-block;width:100px;">Password:</label></strong>' +
+ '<div data-dojo-type="dijit.form.TextBox" type="password" id="pass"></div><br/>' +
+ '<button data-dojo-type="dijit.form.Button" data-dojo-props="onClick:doAuthenticate" type="submit">Login</button>'
+ });
+
+ button = new DropDownButton({
+ label: "Login",
+ dropDown: dialog
+ });
+
+ usernameSpan = domConstruct.create("span", { innerHTML: '<strong>User: </strong><span id="authenticatedUser"></span>',
+ style: { visibility: "hidden" }});
+
+
+ var loginDiv = dom.byId("login");
+ loginDiv.appendChild(button.domNode);
+ loginDiv.appendChild(usernameSpan);
+
+
+
+
+ updateAuthentication();
+}); \ No newline at end of file
diff --git a/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/UpdatableStore.js b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/UpdatableStore.js
new file mode 100644
index 0000000000..f7ede1a7f7
--- /dev/null
+++ b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/UpdatableStore.js
@@ -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.
+ *
+ */
+define(["dojo/store/Memory",
+ "dojox/grid/DataGrid",
+ "dojo/data/ObjectStore",
+ "dojo/store/Observable"], function (Memory, DataGrid, ObjectStore, Observable) {
+
+ function UpdatableStore( data, divName, structure, func, props, Grid ) {
+
+ var that = this;
+ var GridType = DataGrid;
+
+ that.store = Observable(Memory({data: data, idProperty: "id"}));
+ that.dataStore = ObjectStore({objectStore: that.store});
+
+ var gridProperties = { store: that.dataStore,
+ structure: structure,
+ autoHeight: true
+ };
+ if(props) {
+ for(var prop in props) {
+ if(props.hasOwnProperty(prop))
+ {
+ gridProperties[ prop ] = props[ prop ];
+ }
+ }
+ }
+
+ if(Grid)
+ {
+ GridType = Grid;
+ }
+
+ that.grid = new GridType(gridProperties, divName);
+
+ // since we created this grid programmatically, call startup to render it
+ that.grid.startup();
+
+ if( func )
+ {
+ func(that);
+ }
+
+ }
+
+ UpdatableStore.prototype.update = function(data)
+ {
+
+ var store = this.store;
+ var theItem;
+
+ // handle deletes
+ // iterate over existing store... if not in new data then remove
+ store.query({ }).forEach(function(object) {
+ if(data) {
+ for(var i=0; i < data.length; i++) {
+ if(data[i].id == object.id) {
+ return;
+ }
+ }
+ }
+ store.remove(object.id);
+
+ });
+
+ // iterate over data...
+ if(data) {
+ for(var i=0; i < data.length; i++) {
+ if(theItem = store.get(data[i].id)) {
+ var modified;
+ for(var propName in data[i]) {
+ if(data[i].hasOwnProperty(propName)) {
+ if(theItem[ propName ] != data[i][ propName ]) {
+ theItem[ propName ] = data[i][ propName ];
+ modified = true;
+ }
+ }
+ }
+ if(modified) {
+ // ... check attributes for updates
+ store.notify(theItem, data[i].id);
+ }
+ } else {
+ // ,,, if not in the store then add
+ store.put(data[i]);
+ }
+ }
+ }
+
+ };
+ return UpdatableStore;
+});
diff --git a/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/footer.js b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/footer.js
new file mode 100644
index 0000000000..ea13b1fc53
--- /dev/null
+++ b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/footer.js
@@ -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.
+ *
+ */
+define(["dojo/_base/xhr", "dojo/query", "dojo/domReady!"], function (xhr, query) {
+ query('div[qpid-type="footer"]').forEach(function(node, index, arr) {
+ xhr.get({url: "footer.html",
+ sync: true,
+ load: function(data) {
+ node.innerHTML = data;
+ } });
+ });
+});
+
diff --git a/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/formatter.js b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/formatter.js
new file mode 100644
index 0000000000..2f8683ee1c
--- /dev/null
+++ b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/formatter.js
@@ -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.
+ *
+ */
+
+define(function () {
+ return {
+
+ formatBytes: function formatBytes(amount)
+ {
+ var returnVal = { units: "B",
+ value: "0"};
+
+
+ if(amount < 1000)
+ {
+ returnVal.value = amount.toPrecision(3);;
+ }
+ else if(amount < 1000 * 1024)
+ {
+ returnVal.units = "KB";
+ returnVal.value = (amount / 1024).toPrecision(3);
+ }
+ else if(amount < 1000 * 1024 * 1024)
+ {
+ returnVal.units = "MB";
+ returnVal.value = (amount / (1024 * 1024)).toPrecision(3);
+ }
+ else if(amount < 1000 * 1024 * 1024 * 1024)
+ {
+ returnVal.units = "GB";
+ returnVal.value = (amount / (1024 * 1024 * 1024)).toPrecision(3);
+ }
+
+ return returnVal;
+
+ },
+
+ formatTime: function formatTime(amount)
+ {
+ var returnVal = { units: "ms",
+ value: "0"};
+
+ if(amount < 1000)
+ {
+ returnVal.units = "ms";
+ returnVal.value = amount.toString();
+ }
+ else if(amount < 1000 * 60)
+ {
+ returnVal.units = "s";
+ returnVal.value = (amount / 1000).toPrecision(3);
+ }
+ else if(amount < 1000 * 60 * 60)
+ {
+ returnVal.units = "min";
+ returnVal.value = (amount / (1000 * 60)).toPrecision(3);
+ }
+ else if(amount < 1000 * 60 * 60 * 24)
+ {
+ returnVal.units = "hr";
+ returnVal.value = (amount / (1000 * 60 * 60)).toPrecision(3);
+ }
+ else if(amount < 1000 * 60 * 60 * 24 * 7)
+ {
+ returnVal.units = "d";
+ returnVal.value = (amount / (1000 * 60 * 60 * 24)).toPrecision(3);
+ }
+ else if(amount < 1000 * 60 * 60 * 24 * 365)
+ {
+ returnVal.units = "wk";
+ returnVal.value = (amount / (1000 * 60 * 60 * 24 * 7)).toPrecision(3);
+ }
+ else
+ {
+ returnVal.units = "yr";
+ returnVal.value = (amount / (1000 * 60 * 60 * 24 * 365)).toPrecision(3);
+ }
+
+ return returnVal;
+ }
+ };
+}); \ No newline at end of file
diff --git a/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/properties.js b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/properties.js
new file mode 100644
index 0000000000..8d85345b74
--- /dev/null
+++ b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/properties.js
@@ -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.
+ *
+ */
+define(["dojo/has", "dojo/_base/sniff", "dojo/domReady!"],
+ function (has) {
+ var properties = {};
+ properties.useSyncGet = (has("ie") <= 8);
+ return properties;
+ }); \ No newline at end of file
diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/type/ExchangeTypeTabControl.java b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/updater.js
index 3995f94eb0..86bbaa46ba 100644
--- a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/type/ExchangeTypeTabControl.java
+++ b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/updater.js
@@ -18,29 +18,28 @@
* under the License.
*
*/
-package org.apache.qpid.management.ui.views.type;
+define(function () {
+ var updateList = new Array();
-import org.eclipse.swt.widgets.TabFolder;
+ setInterval(function() {
+ for(var i = 0; i < updateList.length; i++) {
+ var obj = updateList[i];
+ obj.update();
+ }
+ }, 5000); // TODO: Should make this configurable
-import org.apache.qpid.management.ui.ManagedBean;
-import org.apache.qpid.management.ui.ManagedServer;
+ return {
+ add: function(obj) {
+ updateList.push(obj);
+ },
-import static org.apache.qpid.management.ui.Constants.EXCHANGE;
-
-import java.util.List;
-
-public class ExchangeTypeTabControl extends MBeanTypeTabControl
-{
-
- public ExchangeTypeTabControl(TabFolder tabFolder, ManagedServer server, String virtualHost)
- {
- super(tabFolder, server, virtualHost, EXCHANGE);
- }
-
- @Override
- protected List<ManagedBean> getMbeans()
- {
- return getServerRegistry().getExchanges(getVirtualHost());
- }
-
-}
+ remove: function(obj) {
+ for(var i = 0; i < updateList.length; i++) {
+ if(updateList[i] === obj) {
+ updateList.splice(i,1);
+ return;
+ }
+ }
+ }
+ };
+}); \ No newline at end of file
diff --git a/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/util.js b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/util.js
new file mode 100644
index 0000000000..08fdf5c99b
--- /dev/null
+++ b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/util.js
@@ -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.
+ *
+ */
+define(["dojo/_base/xhr"],
+ function (xhr) {
+ var util = {};
+ if (Array.isArray) {
+ util.isArray = function (object) {
+ return Array.isArray(object);
+ };
+ } else {
+ util.isArray = function (object) {
+ return object instanceof Array;
+ };
+ }
+
+ util.flattenStatistics = function (data) {
+ var attrName, stats, propName, theList;
+ for(attrName in data) {
+ if(data.hasOwnProperty(attrName)) {
+ if(attrName == "statistics") {
+ stats = data.statistics;
+ for(propName in stats) {
+ if(stats.hasOwnProperty( propName )) {
+ data[ propName ] = stats[ propName ];
+ }
+ }
+ } else if(data[ attrName ] instanceof Array) {
+ theList = data[ attrName ];
+
+ for(var i=0; i < theList.length; i++) {
+ util.flattenStatistics( theList[i] );
+ }
+ }
+ }
+ }
+ };
+
+ util.isReservedExchangeName = function(exchangeName)
+ {
+ return exchangeName == null || exchangeName == "" || "<<default>>" == exchangeName || exchangeName.indexOf("amq.") == 0 || exchangeName.indexOf("qpid.") == 0;
+ };
+
+ util.deleteGridSelections = function(updater, gridName, url, confirmationMessageStart)
+ {
+ var grid = updater[gridName].grid;
+ var data = grid.selection.getSelected();
+ if(data.length)
+ {
+ var confirmationMessage = null;
+ if (data.length == 1)
+ {
+ confirmationMessage = confirmationMessageStart + " '" + data[0].name + "'?";
+ }
+ else
+ {
+ var names = '';
+ for(var i = 0; i<data.length; i++)
+ {
+ if (names)
+ {
+ names += ', ';
+ }
+ names += "\""+ data[i].name + "\"";
+ }
+ confirmationMessage = confirmationMessageStart + "s " + names + "?";
+ }
+ if(confirm(confirmationMessage))
+ {
+ var i, queryParam;
+ for(i = 0; i<data.length; i++)
+ {
+ if(queryParam)
+ {
+ queryParam += "&";
+ }
+ else
+ {
+ queryParam = "?";
+ }
+ queryParam += "id=" + data[i].id;
+ }
+ var query = url + queryParam;
+ var success = true
+ var failureReason = "";
+ xhr.del({url: query, sync: true, handleAs: "json"}).then(
+ function(data)
+ {
+ grid.setQuery({id: "*"});
+ grid.selection.deselectAll();
+ updater.update();
+ },
+ function(error) {success = false; failureReason = error;});
+ if(!success )
+ {
+ alert("Error:" + failureReason);
+ }
+ }
+ }
+ }
+
+ return util;
+ }); \ No newline at end of file
diff --git a/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/AuthenticationProvider.js b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/AuthenticationProvider.js
new file mode 100644
index 0000000000..7613fd5d71
--- /dev/null
+++ b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/AuthenticationProvider.js
@@ -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.
+ *
+ */
+define(["dojo/_base/xhr",
+ "dojo/parser",
+ "dojo/query",
+ "dojo/_base/connect",
+ "qpid/common/properties",
+ "qpid/common/updater",
+ "qpid/common/util",
+ "qpid/common/UpdatableStore",
+ "dojox/grid/EnhancedGrid",
+ "dojox/grid/enhanced/plugins/Pagination",
+ "dojox/grid/enhanced/plugins/IndirectSelection",
+ "dojo/domReady!"],
+ function (xhr, parser, query, connect, properties, updater, util, UpdatableStore, EnhancedGrid) {
+
+ function AuthenticationProvider(name, parent, controller) {
+ this.name = name;
+ this.controller = controller;
+ this.modelObj = { type: "authenticationprovider", name: name };
+ if(parent) {
+ this.modelObj.parent = {};
+ this.modelObj.parent[ parent.type] = parent;
+ }
+ }
+
+ AuthenticationProvider.prototype.getTitle = function() {
+ return "AuthenticationProvider";
+ };
+
+ AuthenticationProvider.prototype.open = function(contentPane) {
+ var that = this;
+ this.contentPane = contentPane;
+ xhr.get({url: "showAuthProvider.html",
+ sync: true,
+ load: function(data) {
+ contentPane.containerNode.innerHTML = data;
+ parser.parse(contentPane.containerNode);
+
+ that.authProviderAdapter = new AuthProviderUpdater(contentPane.containerNode, that.modelObj, that.controller);
+
+ updater.add( that.authProviderAdapter );
+
+ that.authProviderAdapter.update();
+
+ }});
+ };
+
+ AuthenticationProvider.prototype.close = function() {
+ updater.remove( this.authProviderAdapter );
+ };
+
+ function AuthProviderUpdater(node, authProviderObj, controller)
+ {
+ this.controller = controller;
+ this.name = query(".name", node)[0];
+ /*this.state = dom.byId("state");
+ this.durable = dom.byId("durable");
+ this.lifetimePolicy = dom.byId("lifetimePolicy");
+ */
+ this.query = "rest/authenticationprovider/"+encodeURIComponent(authProviderObj.name);
+
+ var that = this;
+
+ xhr.get({url: this.query, sync: properties.useSyncGet, handleAs: "json"})
+ .then(function(data)
+ {
+ that.authProviderData = data[0];
+
+ util.flattenStatistics( that.authProviderData );
+
+ that.updateHeader();
+
+ require(["qpid/management/authenticationprovider/"+that.authProviderData.type],
+ function(SpecificProvider) {
+ that.details = new SpecificProvider(node, authProviderObj, controller);
+ that.details.update();
+ });
+
+ });
+
+ }
+
+ AuthProviderUpdater.prototype.updateHeader = function()
+ {
+ this.name.innerHTML = this.authProviderData[ "name" ];
+ /* this.state.innerHTML = this.brokerData[ "state" ];
+ this.durable.innerHTML = this.brokerData[ "durable" ];
+ this.lifetimePolicy.innerHTML = this.brokerData[ "lifetimePolicy" ];
+*/
+ };
+
+ AuthProviderUpdater.prototype.update = function()
+ {
+
+ var that = this;
+
+
+ };
+
+
+
+ return AuthenticationProvider;
+ });
diff --git a/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Broker.js b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Broker.js
new file mode 100644
index 0000000000..dcf6711073
--- /dev/null
+++ b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Broker.js
@@ -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.
+ *
+ */
+define(["dojo/_base/xhr",
+ "dojo/parser",
+ "dojo/query",
+ "dojo/_base/connect",
+ "qpid/common/properties",
+ "qpid/common/updater",
+ "qpid/common/util",
+ "qpid/common/UpdatableStore",
+ "dojox/grid/EnhancedGrid",
+ "dojox/grid/enhanced/plugins/Pagination",
+ "dojox/grid/enhanced/plugins/IndirectSelection",
+ "dojo/domReady!"],
+ function (xhr, parser, query, connect, properties, updater, util, UpdatableStore, EnhancedGrid) {
+
+ function Broker(name, parent, controller) {
+ this.name = name;
+ this.controller = controller;
+ this.modelObj = { type: "broker", name: name };
+ if(parent) {
+ this.modelObj.parent = {};
+ this.modelObj.parent[ parent.type] = parent;
+ }
+ }
+
+ Broker.prototype.getTitle = function()
+ {
+ return "Broker";
+ };
+
+ Broker.prototype.open = function(contentPane) {
+ var that = this;
+ this.contentPane = contentPane;
+ xhr.get({url: "showBroker.html",
+ sync: true,
+ load: function(data) {
+ contentPane.containerNode.innerHTML = data;
+ parser.parse(contentPane.containerNode);
+
+ that.brokerUpdater = new BrokerUpdater(contentPane.containerNode, that.modelObj, that.controller);
+
+ updater.add( that.brokerUpdater );
+
+ that.brokerUpdater.update();
+
+ }});
+ };
+
+ Broker.prototype.close = function() {
+ updater.remove( this.brokerUpdater );
+ };
+
+ function BrokerUpdater(node, brokerObj, controller)
+ {
+ this.controller = controller;
+ this.name = query(".broker-name", node)[0];
+ /*this.state = dom.byId("state");
+ this.durable = dom.byId("durable");
+ this.lifetimePolicy = dom.byId("lifetimePolicy");
+ */
+ this.query = "rest/broker";
+
+ var that = this;
+
+ xhr.get({url: this.query, sync: properties.useSyncGet, handleAs: "json"})
+ .then(function(data)
+ {
+ that.brokerData= data[0];
+
+ util.flattenStatistics( that.brokerData);
+
+ that.updateHeader();
+ that.vhostsGrid =
+ new UpdatableStore(that.brokerData.vhosts, query(".broker-virtualhosts")[0],
+ [ { name: "Virtual Host", field: "name", width: "120px"},
+ { name: "Connections", field: "connectionCount", width: "80px"},
+ { name: "Queues", field: "queueCount", width: "80px"},
+ { name: "Exchanges", field: "exchangeCount", width: "100%"}
+ ], function(obj) {
+ connect.connect(obj.grid, "onRowDblClick", obj.grid,
+ function(evt){
+ var idx = evt.rowIndex,
+ theItem = this.getItem(idx);
+ var name = obj.dataStore.getValue(theItem,"name");
+ that.controller.show("virtualhost", name, brokerObj);
+ });
+ });
+
+ that.portsGrid =
+ new UpdatableStore(that.brokerData.ports, query(".broker-ports")[0],
+ [ { name: "Address", field: "bindingAddress", width: "70px"},
+ { name: "Port", field: "port", width: "70px"},
+ { name: "Transports", field: "transports", width: "150px"},
+ { name: "Protocols", field: "protocols", width: "100%"}
+ ], function(obj) {
+ connect.connect(obj.grid, "onRowDblClick", obj.grid,
+ function(evt){
+ var idx = evt.rowIndex,
+ theItem = this.getItem(idx);
+ var name = obj.dataStore.getValue(theItem,"name");
+ that.controller.show("port", name, brokerObj);
+ });
+ });
+
+ });
+
+ xhr.get({url: "rest/logrecords", sync: properties.useSyncGet, handleAs: "json"})
+ .then(function(data)
+ {
+ that.logData = data;
+
+ var gridProperties = {
+ height: 400,
+ plugins: {
+ pagination: {
+ pageSizes: ["10", "25", "50", "100"],
+ description: true,
+ sizeSwitch: true,
+ pageStepper: true,
+ gotoButton: true,
+ maxPageStep: 4,
+ position: "bottom"
+ }
+ }};
+
+
+ that.logfileGrid =
+ new UpdatableStore(that.logData, query(".broker-logfile")[0],
+ [ { name: "Timestamp", field: "timestamp", width: "200px",
+ formatter: function(val) {
+ var d = new Date(0);
+ d.setUTCSeconds(val/1000);
+
+ return d.toLocaleString();
+ }},
+ { name: "Level", field: "level", width: "60px"},
+ { name: "Logger", field: "logger", width: "280px"},
+ { name: "Thread", field: "thread", width: "120px"},
+ { name: "Log Message", field: "message", width: "100%"}
+
+ ], null, gridProperties, EnhancedGrid);
+ });
+ }
+
+ BrokerUpdater.prototype.updateHeader = function()
+ {
+ this.name.innerHTML = this.brokerData[ "name" ];
+ /* this.state.innerHTML = this.brokerData[ "state" ];
+ this.durable.innerHTML = this.brokerData[ "durable" ];
+ this.lifetimePolicy.innerHTML = this.brokerData[ "lifetimePolicy" ];
+*/
+ };
+
+ BrokerUpdater.prototype.update = function()
+ {
+
+ var that = this;
+
+ xhr.get({url: this.query, sync: properties.useSyncGet, handleAs: "json"}).then(function(data)
+ {
+ that.brokerData = data[0];
+ util.flattenStatistics( that.brokerData );
+
+ that.updateHeader();
+
+ that.vhostsGrid.update(that.brokerData.virtualhosts);
+
+ that.portsGrid.update(that.brokerData.ports);
+
+
+ });
+
+
+ xhr.get({url: "rest/logrecords", sync: properties.useSyncGet, handleAs: "json"})
+ .then(function(data)
+ {
+ that.logData = data;
+ that.logfileGrid.update(that.logData);
+ });
+
+ };
+
+
+
+ return Broker;
+ });
diff --git a/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Connection.js b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Connection.js
new file mode 100644
index 0000000000..01f9a325c5
--- /dev/null
+++ b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Connection.js
@@ -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.
+ *
+ */
+define(["dojo/_base/xhr",
+ "dojo/parser",
+ "dojo/query",
+ "dojo/_base/connect",
+ "qpid/common/properties",
+ "qpid/common/updater",
+ "qpid/common/util",
+ "qpid/common/formatter",
+ "qpid/common/UpdatableStore",
+ "dojo/domReady!"],
+ function (xhr, parser, query, connect, properties, updater, util, formatter, UpdatableStore) {
+
+ function Connection(name, parent, controller) {
+ this.name = name;
+ this.controller = controller;
+ this.modelObj = { type: "exchange", name: name };
+ if(parent) {
+ this.modelObj.parent = {};
+ this.modelObj.parent[ parent.type] = parent;
+ }
+ }
+
+ Connection.prototype.getTitle = function()
+ {
+ return "Connection: " + this.name;
+ };
+
+ Connection.prototype.open = function(contentPane) {
+ var that = this;
+ this.contentPane = contentPane;
+ xhr.get({url: "showConnection.html",
+ sync: true,
+ load: function(data) {
+ contentPane.containerNode.innerHTML = data;
+ parser.parse(contentPane.containerNode);
+
+ that.connectionUpdater = new ConnectionUpdater(contentPane.containerNode, that.modelObj, that.controller);
+
+ updater.add( that.connectionUpdater );
+
+ that.connectionUpdater.update();
+
+ }});
+ };
+
+ Connection.prototype.close = function() {
+ updater.remove( this.connectionUpdater );
+ };
+
+ function ConnectionUpdater(containerNode, connectionObj, controller)
+ {
+ var that = this;
+
+ function findNode(name) {
+ return query("." + name, containerNode)[0];
+ }
+
+ function storeNodes(names)
+ {
+ for(var i = 0; i < names.length; i++) {
+ that[names[i]] = findNode(names[i]);
+ }
+ }
+
+ storeNodes(["name",
+ "state",
+ "durable",
+ "lifetimePolicy",
+ "msgInRate",
+ "bytesInRate",
+ "bytesInRateUnits",
+ "msgOutRate",
+ "bytesOutRate",
+ "bytesOutRateUnits"]);
+
+
+
+ this.query = "rest/connection/"+ encodeURIComponent(connectionObj.parent.virtualhost.name) + "/" + encodeURIComponent(connectionObj.name);
+
+ xhr.get({url: this.query, sync: properties.useSyncGet, handleAs: "json"}).then(function(data)
+ {
+ that.connectionData = data[0];
+
+ util.flattenStatistics( that.connectionData );
+
+ that.updateHeader();
+ that.sessionsGrid = new UpdatableStore(that.connectionData.sessions, findNode("sessions"),
+ [ { name: "Name", field: "name", width: "70px"},
+ { name: "Mode", field: "distributionMode", width: "70px"},
+ { name: "Msgs Rate", field: "msgRate",
+ width: "150px"},
+ { name: "Bytes Rate", field: "bytesRate",
+ width: "100%"}
+ ]);
+
+
+ });
+
+ }
+
+ ConnectionUpdater.prototype.updateHeader = function()
+ {
+ this.name.innerHTML = this.connectionData[ "name" ];
+ this.state.innerHTML = this.connectionData[ "state" ];
+ this.durable.innerHTML = this.connectionData[ "durable" ];
+ this.lifetimePolicy.innerHTML = this.connectionData[ "lifetimePolicy" ];
+
+ };
+
+ ConnectionUpdater.prototype.update = function()
+ {
+
+ var that = this;
+
+ xhr.get({url: this.query, sync: properties.useSyncGet, handleAs: "json"}).then(function(data)
+ {
+ that.connectionData = data[0];
+
+ util.flattenStatistics( that.connectionData );
+
+ var sessions = that.connectionData[ "sessions" ];
+
+ that.updateHeader();
+
+ var sampleTime = new Date();
+ var messageIn = that.connectionData["messagesIn"];
+ var bytesIn = that.connectionData["bytesIn"];
+ var messageOut = that.connectionData["messagesOut"];
+ var bytesOut = that.connectionData["bytesOut"];
+
+ if(that.sampleTime)
+ {
+ var samplePeriod = sampleTime.getTime() - that.sampleTime.getTime();
+
+ var msgInRate = (1000 * (messageIn - that.messageIn)) / samplePeriod;
+ var msgOutRate = (1000 * (messageOut - that.messageOut)) / samplePeriod;
+ var bytesInRate = (1000 * (bytesIn - that.bytesIn)) / samplePeriod;
+ var bytesOutRate = (1000 * (bytesOut - that.bytesOut)) / samplePeriod;
+
+ that.msgInRate.innerHTML = msgInRate.toFixed(0);
+ var bytesInFormat = formatter.formatBytes( bytesInRate );
+ that.bytesInRate.innerHTML = "(" + bytesInFormat.value;
+ that.bytesInRateUnits.innerHTML = bytesInFormat.units + "/s)";
+
+ that.msgOutRate.innerHTML = msgOutRate.toFixed(0);
+ var bytesOutFormat = formatter.formatBytes( bytesOutRate );
+ that.bytesOutRate.innerHTML = "(" + bytesOutFormat.value;
+ that.bytesOutRateUnits.innerHTML = bytesOutFormat.units + "/s)";
+
+ if(sessions && that.sessions)
+ {
+ for(var i=0; i < sessions.length; i++)
+ {
+ var session = sessions[i];
+ for(var j = 0; j < that.sessions.length; j++)
+ {
+ var oldSession = that.sessions[j];
+ if(oldSession.id == session.id)
+ {
+ var msgRate = (1000 * (session.messagesOut - oldSession.messagesOut)) /
+ samplePeriod;
+ session.msgRate = msgRate.toFixed(0) + "msg/s";
+
+ var bytesRate = (1000 * (session.bytesOut - oldSession.bytesOut)) /
+ samplePeriod;
+ var bytesRateFormat = formatter.formatBytes( bytesRate );
+ session.bytesRate = bytesRateFormat.value + bytesRateFormat.units + "/s";
+ }
+
+
+ }
+
+ }
+ }
+
+ }
+
+ that.sampleTime = sampleTime;
+ that.messageIn = messageIn;
+ that.bytesIn = bytesIn;
+ that.messageOut = messageOut;
+ that.bytesOut = bytesOut;
+ that.sessions = sessions;
+
+
+ // update sessions
+ that.sessionsGrid.update(that.connectionData.sessions)
+ });
+ };
+
+
+ return Connection;
+ }); \ No newline at end of file
diff --git a/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Exchange.js b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Exchange.js
new file mode 100644
index 0000000000..37bae1ef8e
--- /dev/null
+++ b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Exchange.js
@@ -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.
+ *
+ */
+define(["dojo/_base/xhr",
+ "dojo/parser",
+ "dojo/query",
+ "dojo/_base/connect",
+ "dijit/registry",
+ "qpid/common/properties",
+ "qpid/common/updater",
+ "qpid/common/util",
+ "qpid/common/formatter",
+ "qpid/common/UpdatableStore",
+ "qpid/management/addBinding",
+ "dojox/grid/EnhancedGrid",
+ "dojo/domReady!"],
+ function (xhr, parser, query, connect, registry, properties, updater, util, formatter, UpdatableStore, addBinding, EnhancedGrid) {
+
+ function Exchange(name, parent, controller) {
+ this.name = name;
+ this.controller = controller;
+ this.modelObj = { type: "exchange", name: name };
+ if(parent) {
+ this.modelObj.parent = {};
+ this.modelObj.parent[ parent.type] = parent;
+ }
+ }
+
+
+ Exchange.prototype.getExchangeName = function()
+ {
+ return this.name;
+ };
+
+
+ Exchange.prototype.getVirtualHostName = function()
+ {
+ return this.modelObj.parent.virtualhost.name;
+ };
+
+ Exchange.prototype.getTitle = function()
+ {
+ return "Exchange: " + this.name;
+ };
+
+ Exchange.prototype.open = function(contentPane) {
+ var that = this;
+ this.contentPane = contentPane;
+ xhr.get({url: "showExchange.html",
+ sync: true,
+ load: function(data) {
+ contentPane.containerNode.innerHTML = data;
+ parser.parse(contentPane.containerNode);
+
+ that.exchangeUpdater = new ExchangeUpdater(contentPane.containerNode, that.modelObj, that.controller);
+
+ updater.add( that.exchangeUpdater );
+
+ that.exchangeUpdater.update();
+
+
+ var addBindingButton = query(".addBindingButton", contentPane.containerNode)[0];
+ connect.connect(registry.byNode(addBindingButton), "onClick",
+ function(evt){
+ addBinding.show({ virtualhost: that.getVirtualHostName(),
+ exchange: that.getExchangeName()});
+ });
+
+ var deleteBindingButton = query(".deleteBindingButton", contentPane.containerNode)[0];
+ connect.connect(registry.byNode(deleteBindingButton), "onClick",
+ function(evt){
+ that.deleteBindings();
+ });
+
+ var isStandard = util.isReservedExchangeName(that.name);
+ var deleteExchangeButton = query(".deleteExchangeButton", contentPane.containerNode)[0];
+ var node = registry.byNode(deleteExchangeButton);
+ if(isStandard)
+ {
+ node.set('disabled', true);
+ }
+ else
+ {
+ connect.connect(node, "onClick",
+ function(evt){
+ that.deleteExchange();
+ });
+ }
+
+ }});
+ };
+
+ Exchange.prototype.close = function() {
+ updater.remove( this.exchangeUpdater );
+ };
+
+ Exchange.prototype.deleteBindings = function()
+ {
+ util.deleteGridSelections(
+ this.exchangeUpdater,
+ "bindingsGrid",
+ "rest/binding/"+ encodeURIComponent(this.getVirtualHostName()) + "/" + encodeURIComponent(this.name),
+ "Are you sure you want to delete binding for queue");
+ }
+
+ function ExchangeUpdater(containerNode, exchangeObj, controller)
+ {
+ var that = this;
+
+ function findNode(name) {
+ return query("." + name, containerNode)[0];
+ }
+
+ function storeNodes(names)
+ {
+ for(var i = 0; i < names.length; i++) {
+ that[names[i]] = findNode(names[i]);
+ }
+ }
+
+ storeNodes(["name",
+ "state",
+ "durable",
+ "lifetimePolicy",
+ "alertRepeatGap",
+ "alertRepeatGapUnits",
+ "alertThresholdMessageAge",
+ "alertThresholdMessageAgeUnits",
+ "alertThresholdMessageSize",
+ "alertThresholdMessageSizeUnits",
+ "alertThresholdQueueDepthBytes",
+ "alertThresholdQueueDepthBytesUnits",
+ "alertThresholdQueueDepthMessages",
+ "msgInRate",
+ "bytesInRate",
+ "bytesInRateUnits",
+ "msgDropRate",
+ "bytesDropRate",
+ "bytesDropRateUnits"]);
+
+
+
+ this.query = "rest/exchange/"+ encodeURIComponent(exchangeObj.parent.virtualhost.name) + "/" + encodeURIComponent(exchangeObj.name);
+
+ xhr.get({url: this.query, sync: properties.useSyncGet, handleAs: "json"}).then(function(data)
+ {
+ that.exchangeData = data[0];
+ util.flattenStatistics( that.exchangeData );
+
+ that.updateHeader();
+ that.bindingsGrid = new UpdatableStore(that.exchangeData.bindings, findNode("bindings"),
+ [ { name: "Queue", field: "queue", width: "90px"},
+ { name: "Binding Key", field: "name", width: "120px"},
+ { name: "Arguments", field: "argumentString", width: "100%"}
+ ], null, {
+ keepSelection: true,
+ plugins: {
+ pagination: {
+ pageSizes: ["10", "25", "50", "100"],
+ description: true,
+ sizeSwitch: true,
+ pageStepper: true,
+ gotoButton: true,
+ maxPageStep: 4,
+ position: "bottom"
+ },
+ indirectSelection: true
+
+ }}, EnhancedGrid);
+
+ });
+
+ }
+
+ ExchangeUpdater.prototype.updateHeader = function()
+ {
+ this.name.innerHTML = this.exchangeData[ "name" ];
+ this.state.innerHTML = this.exchangeData[ "state" ];
+ this.durable.innerHTML = this.exchangeData[ "durable" ];
+ this.lifetimePolicy.innerHTML = this.exchangeData[ "lifetimePolicy" ];
+
+ };
+
+ ExchangeUpdater.prototype.update = function()
+ {
+
+ var thisObj = this;
+
+ xhr.get({url: this.query, sync: properties.useSyncGet, handleAs: "json"}).then(function(data)
+ {
+ thisObj.exchangeData = data[0];
+
+ util.flattenStatistics( thisObj.exchangeData );
+
+ var bindings = thisObj.exchangeData[ "bindings" ];
+
+ if(bindings)
+ {
+ for(var i=0; i < bindings.length; i++)
+ {
+ if(bindings[i].arguments)
+ {
+ bindings[i].argumentString = dojo.toJson(bindings[i].arguments);
+ }
+ else
+ {
+ bindings[i].argumentString = "";
+ }
+ }
+ }
+
+
+ var sampleTime = new Date();
+
+ thisObj.updateHeader();
+
+ var messageIn = thisObj.exchangeData["messagesIn"];
+ var bytesIn = thisObj.exchangeData["bytesIn"];
+ var messageDrop = thisObj.exchangeData["messagesDropped"];
+ var bytesDrop = thisObj.exchangeData["bytesDropped"];
+
+ if(thisObj.sampleTime)
+ {
+ var samplePeriod = sampleTime.getTime() - thisObj.sampleTime.getTime();
+
+ var msgInRate = (1000 * (messageIn - thisObj.messageIn)) / samplePeriod;
+ var msgDropRate = (1000 * (messageDrop - thisObj.messageDrop)) / samplePeriod;
+ var bytesInRate = (1000 * (bytesIn - thisObj.bytesIn)) / samplePeriod;
+ var bytesDropRate = (1000 * (bytesDrop - thisObj.bytesDrop)) / samplePeriod;
+
+ thisObj.msgInRate.innerHTML = msgInRate.toFixed(0);
+ var bytesInFormat = formatter.formatBytes( bytesInRate );
+ thisObj.bytesInRate.innerHTML = "(" + bytesInFormat.value;
+ thisObj.bytesInRateUnits.innerHTML = bytesInFormat.units + "/s)";
+
+ thisObj.msgDropRate.innerHTML = msgDropRate.toFixed(0);
+ var bytesDropFormat = formatter.formatBytes( bytesDropRate );
+ thisObj.bytesDropRate.innerHTML = "(" + bytesDropFormat.value;
+ thisObj.bytesDropRateUnits.innerHTML = bytesDropFormat.units + "/s)"
+
+ }
+
+ thisObj.sampleTime = sampleTime;
+ thisObj.messageIn = messageIn;
+ thisObj.bytesIn = bytesIn;
+ thisObj.messageDrop = messageDrop;
+ thisObj.bytesDrop = bytesDrop;
+
+ // update bindings
+ thisObj.bindingsGrid.update(thisObj.exchangeData.bindings)
+
+ });
+ };
+
+ Exchange.prototype.deleteExchange = function() {
+ if(confirm("Are you sure you want to delete exchange '" +this.name+"'?")) {
+ var query = "rest/exchange/"+ encodeURIComponent(this.getVirtualHostName()) + "/" + encodeURIComponent(this.name);
+ this.success = true
+ var that = this;
+ xhr.del({url: query, sync: true, handleAs: "json"}).then(
+ function(data) {
+ that.contentPane.onClose()
+ that.controller.tabContainer.removeChild(that.contentPane);
+ that.contentPane.destroyRecursive();
+ },
+ function(error) {that.success = false; that.failureReason = error;});
+ if(!this.success ) {
+ alert("Error:" + this.failureReason);
+ }
+ }
+ }
+
+ return Exchange;
+ });
diff --git a/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Queue.js b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Queue.js
new file mode 100644
index 0000000000..8b332dbf92
--- /dev/null
+++ b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Queue.js
@@ -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.
+ *
+ */
+define(["dojo/_base/xhr",
+ "dojo/parser",
+ "dojo/query",
+ "dijit/registry",
+ "dojo/_base/connect",
+ "dojo/_base/event",
+ "dojo/json",
+ "qpid/common/properties",
+ "qpid/common/updater",
+ "qpid/common/util",
+ "qpid/common/formatter",
+ "qpid/common/UpdatableStore",
+ "qpid/management/addBinding",
+ "qpid/management/moveCopyMessages",
+ "qpid/management/showMessage",
+ "dojo/store/JsonRest",
+ "dojox/grid/EnhancedGrid",
+ "dojo/data/ObjectStore",
+ "dojox/grid/enhanced/plugins/Pagination",
+ "dojox/grid/enhanced/plugins/IndirectSelection",
+ "dojo/domReady!"],
+ function (xhr, parser, query, registry, connect, event, json, properties, updater, util, formatter,
+ UpdatableStore, addBinding, moveMessages, showMessage, JsonRest, EnhancedGrid, ObjectStore) {
+
+ function Queue(name, parent, controller) {
+ this.name = name;
+ this.controller = controller;
+ this.modelObj = { type: "queue", name: name };
+ if(parent) {
+ this.modelObj.parent = {};
+ this.modelObj.parent[ parent.type] = parent;
+ }
+ }
+
+ Queue.prototype.getQueueName = function()
+ {
+ return this.name;
+ };
+
+
+ Queue.prototype.getVirtualHostName = function()
+ {
+ return this.modelObj.parent.virtualhost.name;
+ };
+
+ Queue.prototype.getTitle = function()
+ {
+ return "Queue: " + this.name;
+ };
+
+ Queue.prototype.open = function(contentPane) {
+ var that = this;
+ this.contentPane = contentPane;
+ xhr.get({url: "showQueue.html",
+ sync: true,
+ load: function(data) {
+ contentPane.containerNode.innerHTML = data;
+ parser.parse(contentPane.containerNode);
+
+ that.queueUpdater = new QueueUpdater(contentPane.containerNode, that, that.controller);
+
+ updater.add( that.queueUpdater );
+
+ that.queueUpdater.update();
+
+ var myStore = new JsonRest({target:"rest/message/"+ encodeURIComponent(that.getVirtualHostName()) +
+ "/" + encodeURIComponent(that.getQueueName())});
+ var messageGridDiv = query(".messages",contentPane.containerNode)[0];
+ that.dataStore = new ObjectStore({objectStore: myStore});
+ that.grid = new EnhancedGrid({
+ store: that.dataStore,
+ autoHeight: 10,
+ keepSelection: true,
+ structure: [
+ {name:"Size", field:"size", width: "60px"},
+ {name:"State", field:"state", width: "120px"},
+
+ {name:"Arrival", field:"arrivalTime", width: "100%",
+ formatter: function(val) {
+ var d = new Date(0);
+ d.setUTCSeconds(val/1000);
+
+ return d.toLocaleString();
+ } }
+ ],
+ plugins: {
+ pagination: {
+ pageSizes: ["10", "25", "50", "100"],
+ description: true,
+ sizeSwitch: true,
+ pageStepper: true,
+ gotoButton: true,
+ maxPageStep: 4,
+ position: "bottom"
+ },
+ indirectSelection: true
+ }
+ }, messageGridDiv);
+
+ connect.connect(that.grid, "onRowDblClick", that.grid,
+ function(evt){
+ var idx = evt.rowIndex,
+ theItem = this.getItem(idx);
+ var id = that.dataStore.getValue(theItem,"id");
+ showMessage.show({ messageNumber: id,
+ queue: that.getQueueName(),
+ virtualhost: that.getVirtualHostName() });
+ });
+
+ var deleteMessagesButton = query(".deleteMessagesButton", contentPane.containerNode)[0];
+ var deleteWidget = registry.byNode(deleteMessagesButton);
+ connect.connect(deleteWidget, "onClick",
+ function(evt){
+ event.stop(evt);
+ that.deleteMessages();
+ });
+ var moveMessagesButton = query(".moveMessagesButton", contentPane.containerNode)[0];
+ connect.connect(registry.byNode(moveMessagesButton), "onClick",
+ function(evt){
+ event.stop(evt);
+ that.moveOrCopyMessages({move: true});
+ });
+
+
+ var copyMessagesButton = query(".copyMessagesButton", contentPane.containerNode)[0];
+ connect.connect(registry.byNode(copyMessagesButton), "onClick",
+ function(evt){
+ event.stop(evt);
+ that.moveOrCopyMessages({move: false});
+ });
+
+ var addBindingButton = query(".addBindingButton", contentPane.containerNode)[0];
+ connect.connect(registry.byNode(addBindingButton), "onClick",
+ function(evt){
+ event.stop(evt);
+ addBinding.show({ virtualhost: that.getVirtualHostName(),
+ queue: that.getQueueName()});
+ });
+
+ var deleteQueueButton = query(".deleteQueueButton", contentPane.containerNode)[0];
+ connect.connect(registry.byNode(deleteQueueButton), "onClick",
+ function(evt){
+ event.stop(evt);
+ that.deleteQueue();
+ });
+ }});
+
+
+
+ };
+
+ Queue.prototype.deleteMessages = function() {
+ var data = this.grid.selection.getSelected();
+ if(data.length) {
+ var that = this;
+ if(confirm("Delete " + data.length + " messages?")) {
+ var i, queryParam;
+ for(i = 0; i<data.length; i++) {
+ if(queryParam) {
+ queryParam += "&";
+ } else {
+ queryParam = "?";
+ }
+
+ queryParam += "id=" + data[i].id;
+ }
+ var query = "rest/message/"+ encodeURIComponent(that.getVirtualHostName())
+ + "/" + encodeURIComponent(that.getQueueName()) + queryParam;
+ that.success = true
+ xhr.del({url: query, sync: true, handleAs: "json"}).then(
+ function(data) {
+ that.grid.setQuery({id: "*"});
+ that.grid.selection.deselectAll();
+ that.queueUpdater.update();
+ },
+ function(error) {that.success = false; that.failureReason = error;});
+ if(!that.success ) {
+ alert("Error:" + this.failureReason);
+ }
+ }
+ }
+ };
+
+ Queue.prototype.moveOrCopyMessages = function(obj) {
+ var that = this;
+ var move = obj.move;
+ var data = this.grid.selection.getSelected();
+ if(data.length) {
+ var that = this;
+ var i, putData = { messages:[] };
+ if(move) {
+ putData.move = true;
+ }
+ for(i = 0; i<data.length; i++) {
+ putData.messages.push(data[i].id);
+ }
+ moveMessages.show({ virtualhost: this.getVirtualHostName(),
+ queue: this.getQueueName(),
+ data: putData}, function() {
+ if(move)
+ {
+ that.grid.setQuery({id: "*"});
+ that.grid.selection.deselectAll();
+ }
+ });
+
+ }
+
+
+
+ };
+
+ Queue.prototype.startup = function() {
+ this.grid.startup();
+ };
+
+ Queue.prototype.close = function() {
+ updater.remove( this.queueUpdater );
+ };
+
+ var queueTypeKeys = {
+ priority: "priorities",
+ lvq: "lvqKey",
+ sorted: "sortKey"
+ };
+
+ var queueTypeKeyNames = {
+ priority: "Number of priorities",
+ lvq: "LVQ key",
+ sorted: "Sort key"
+ };
+
+ function QueueUpdater(containerNode, queueObj, controller)
+ {
+ var that = this;
+
+ function findNode(name) {
+ return query("." + name, containerNode)[0];
+ }
+
+ function storeNodes(names)
+ {
+ for(var i = 0; i < names.length; i++) {
+ that[names[i]] = findNode(names[i]);
+ }
+ }
+
+ storeNodes(["name",
+ "state",
+ "durable",
+ "lifetimePolicy",
+ "type",
+ "typeQualifier",
+ "alertRepeatGap",
+ "alertRepeatGapUnits",
+ "alertThresholdMessageAge",
+ "alertThresholdMessageAgeUnits",
+ "alertThresholdMessageSize",
+ "alertThresholdMessageSizeUnits",
+ "alertThresholdQueueDepthBytes",
+ "alertThresholdQueueDepthBytesUnits",
+ "alertThresholdQueueDepthMessages",
+ "alternateExchange",
+ "queueDepthMessages",
+ "queueDepthBytes",
+ "queueDepthBytesUnits",
+ "unacknowledgedMessages",
+ "unacknowledgedBytes",
+ "unacknowledgedBytesUnits",
+ "msgInRate",
+ "bytesInRate",
+ "bytesInRateUnits",
+ "msgOutRate",
+ "bytesOutRate",
+ "bytesOutRateUnits"]);
+
+
+
+ this.query = "rest/queue/"+ encodeURIComponent(queueObj.getVirtualHostName()) + "/" + encodeURIComponent(queueObj.getQueueName());
+
+ xhr.get({url: this.query, sync: properties.useSyncGet, handleAs: "json"}).then(function(data)
+ {
+ that.queueData = data[0];
+
+ util.flattenStatistics( that.queueData );
+
+ that.updateHeader();
+ that.bindingsGrid = new UpdatableStore(that.queueData.bindings, findNode("bindings"),
+ [ { name: "Exchange", field: "exchange", width: "90px"},
+ { name: "Binding Key", field: "name", width: "120px"},
+ { name: "Arguments", field: "argumentString", width: "100%"}
+ ]);
+
+ that.consumersGrid = new UpdatableStore(that.queueData.consumers, findNode("consumers"),
+ [ { name: "Name", field: "name", width: "70px"},
+ { name: "Mode", field: "distributionMode", width: "70px"},
+ { name: "Msgs Rate", field: "msgRate",
+ width: "150px"},
+ { name: "Bytes Rate", field: "bytesRate",
+ width: "100%"}
+ ]);
+
+
+
+
+ });
+
+ }
+
+ QueueUpdater.prototype.updateHeader = function()
+ {
+
+ var bytesDepth;
+ this.name.innerHTML = this.queueData[ "name" ];
+ this.state.innerHTML = this.queueData[ "state" ];
+ this.durable.innerHTML = this.queueData[ "durable" ];
+ this.lifetimePolicy.innerHTML = this.queueData[ "lifetimePolicy" ];
+ this.alternateExchange.innerHTML = this.queueData[ "alternateExchange" ] ? this.queueData[ "alternateExchange" ]: "" ;
+
+ this.queueDepthMessages.innerHTML = this.queueData["queueDepthMessages"];
+ bytesDepth = formatter.formatBytes( this.queueData["queueDepthBytes"] );
+ this.queueDepthBytes.innerHTML = "(" + bytesDepth.value;
+ this.queueDepthBytesUnits.innerHTML = bytesDepth.units + ")";
+
+ this.unacknowledgedMessages.innerHTML = this.queueData["unacknowledgedMessages"];
+ bytesDepth = formatter.formatBytes( this.queueData["unacknowledgedBytes"] );
+ this.unacknowledgedBytes.innerHTML = "(" + bytesDepth.value;
+ this.unacknowledgedBytesUnits.innerHTML = bytesDepth.units + ")";
+ this.type.innerHTML = this.queueData[ "type" ];
+ if (this.queueData.type == "standard")
+ {
+ this.typeQualifier.style.display = "none";
+ }
+ else
+ {
+ this.typeQualifier.innerHTML = "(" + queueTypeKeyNames[this.queueData.type] + ": " + this.queueData[queueTypeKeys[this.queueData.type]] + ")";
+ }
+
+ };
+
+ QueueUpdater.prototype.update = function()
+ {
+
+ var thisObj = this;
+
+ xhr.get({url: this.query, sync: properties.useSyncGet, handleAs: "json"}).then(function(data) {
+ var i,j;
+ thisObj.queueData = data[0];
+ util.flattenStatistics( thisObj.queueData );
+
+ var bindings = thisObj.queueData[ "bindings" ];
+ var consumers = thisObj.queueData[ "consumers" ];
+
+ for(i=0; i < bindings.length; i++) {
+ bindings[i].argumentString = json.stringify(bindings[i].arguments);
+ }
+
+ thisObj.updateHeader();
+
+
+ // update alerting info
+ var alertRepeatGap = formatter.formatTime( thisObj.queueData["alertRepeatGap"] );
+
+ thisObj.alertRepeatGap.innerHTML = alertRepeatGap.value;
+ thisObj.alertRepeatGapUnits.innerHTML = alertRepeatGap.units;
+
+
+ var alertMsgAge = formatter.formatTime( thisObj.queueData["alertThresholdMessageAge"] );
+
+ thisObj.alertThresholdMessageAge.innerHTML = alertMsgAge.value;
+ thisObj.alertThresholdMessageAgeUnits.innerHTML = alertMsgAge.units;
+
+ var alertMsgSize = formatter.formatBytes( thisObj.queueData["alertThresholdMessageSize"] );
+
+ thisObj.alertThresholdMessageSize.innerHTML = alertMsgSize.value;
+ thisObj.alertThresholdMessageSizeUnits.innerHTML = alertMsgSize.units;
+
+ var alertQueueDepth = formatter.formatBytes( thisObj.queueData["alertThresholdQueueDepthBytes"] );
+
+ thisObj.alertThresholdQueueDepthBytes.innerHTML = alertQueueDepth.value;
+ thisObj.alertThresholdQueueDepthBytesUnits.innerHTML = alertQueueDepth.units;
+
+ thisObj.alertThresholdQueueDepthMessages.innerHTML = thisObj.queueData["alertThresholdQueueDepthMessages"];
+
+ var sampleTime = new Date();
+ var messageIn = thisObj.queueData["totalEnqueuedMessages"];
+ var bytesIn = thisObj.queueData["totalEnqueuedBytes"];
+ var messageOut = thisObj.queueData["totalDequeuedMessages"];
+ var bytesOut = thisObj.queueData["totalDequeuedBytes"];
+
+ if(thisObj.sampleTime) {
+ var samplePeriod = sampleTime.getTime() - thisObj.sampleTime.getTime();
+
+ var msgInRate = (1000 * (messageIn - thisObj.messageIn)) / samplePeriod;
+ var msgOutRate = (1000 * (messageOut - thisObj.messageOut)) / samplePeriod;
+ var bytesInRate = (1000 * (bytesIn - thisObj.bytesIn)) / samplePeriod;
+ var bytesOutRate = (1000 * (bytesOut - thisObj.bytesOut)) / samplePeriod;
+
+ thisObj.msgInRate.innerHTML = msgInRate.toFixed(0);
+ var bytesInFormat = formatter.formatBytes( bytesInRate );
+ thisObj.bytesInRate.innerHTML = "(" + bytesInFormat.value;
+ thisObj.bytesInRateUnits.innerHTML = bytesInFormat.units + "/s)";
+
+ thisObj.msgOutRate.innerHTML = msgOutRate.toFixed(0);
+ var bytesOutFormat = formatter.formatBytes( bytesOutRate );
+ thisObj.bytesOutRate.innerHTML = "(" + bytesOutFormat.value;
+ thisObj.bytesOutRateUnits.innerHTML = bytesOutFormat.units + "/s)";
+
+ if(consumers && thisObj.consumers) {
+ for(i=0; i < consumers.length; i++) {
+ var consumer = consumers[i];
+ for(j = 0; j < thisObj.consumers.length; j++) {
+ var oldConsumer = thisObj.consumers[j];
+ if(oldConsumer.id == consumer.id) {
+ var msgRate = (1000 * (consumer.messagesOut - oldConsumer.messagesOut)) /
+ samplePeriod;
+ consumer.msgRate = msgRate.toFixed(0) + "msg/s";
+
+ var bytesRate = (1000 * (consumer.bytesOut - oldConsumer.bytesOut)) /
+ samplePeriod;
+ var bytesRateFormat = formatter.formatBytes( bytesRate );
+ consumer.bytesRate = bytesRateFormat.value + bytesRateFormat.units + "/s";
+ }
+ }
+ }
+ }
+
+ }
+
+ thisObj.sampleTime = sampleTime;
+ thisObj.messageIn = messageIn;
+ thisObj.bytesIn = bytesIn;
+ thisObj.messageOut = messageOut;
+ thisObj.bytesOut = bytesOut;
+ thisObj.consumers = consumers;
+
+ // update bindings
+ thisObj.bindingsGrid.update(thisObj.queueData.bindings);
+
+ // update consumers
+ thisObj.consumersGrid.update(thisObj.queueData.consumers)
+
+ });
+ };
+
+ Queue.prototype.deleteQueue = function() {
+ if(confirm("Are you sure you want to delete queue '" +this.name+"'?")) {
+ var query = "rest/queue/"+ encodeURIComponent(this.getVirtualHostName()) + "/" + encodeURIComponent(this.name);
+ this.success = true
+ var that = this;
+ xhr.del({url: query, sync: true, handleAs: "json"}).then(
+ function(data) {
+ that.contentPane.onClose()
+ that.controller.tabContainer.removeChild(that.contentPane);
+ that.contentPane.destroyRecursive();
+ },
+ function(error) {that.success = false; that.failureReason = error;});
+ if(!this.success ) {
+ alert("Error:" + this.failureReason);
+ }
+ }
+ }
+
+ return Queue;
+ });
diff --git a/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/VirtualHost.js b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/VirtualHost.js
new file mode 100644
index 0000000000..957f2381cf
--- /dev/null
+++ b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/VirtualHost.js
@@ -0,0 +1,378 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+define(["dojo/_base/xhr",
+ "dojo/parser",
+ "dojo/query",
+ "dojo/_base/connect",
+ "dijit/registry",
+ "qpid/common/properties",
+ "qpid/common/updater",
+ "qpid/common/util",
+ "qpid/common/formatter",
+ "qpid/common/UpdatableStore",
+ "qpid/management/addQueue",
+ "qpid/management/addExchange",
+ "dojox/grid/EnhancedGrid",
+ "dojo/domReady!"],
+ function (xhr, parser, query, connect, registry, properties, updater, util, formatter, UpdatableStore, addQueue, addExchange, EnhancedGrid) {
+
+ function VirtualHost(name, parent, controller) {
+ this.name = name;
+ this.controller = controller;
+ this.modelObj = { type: "virtualhost", name: name};
+ if(parent) {
+ this.modelObj.parent = {};
+ this.modelObj.parent[ parent.type] = parent;
+ }
+ }
+
+ VirtualHost.prototype.getTitle = function()
+ {
+ return "VirtualHost: " + this.name;
+ };
+
+ VirtualHost.prototype.open = function(contentPane) {
+ var that = this;
+ this.contentPane = contentPane;
+ xhr.get({url: "showVirtualHost.html",
+ sync: true,
+ load: function(data) {
+ contentPane.containerNode.innerHTML = data;
+ parser.parse(contentPane.containerNode);
+
+ that.vhostUpdater = new Updater(contentPane.containerNode, that.modelObj, that.controller);
+
+ updater.add( that.vhostUpdater );
+
+ that.vhostUpdater.update();
+
+ var addQueueButton = query(".addQueueButton", contentPane.containerNode)[0];
+ connect.connect(registry.byNode(addQueueButton), "onClick", function(evt){ addQueue.show(that.name) });
+
+ var deleteQueueButton = query(".deleteQueueButton", contentPane.containerNode)[0];
+ connect.connect(registry.byNode(deleteQueueButton), "onClick",
+ function(evt){
+ util.deleteGridSelections(
+ that.vhostUpdater,
+ "queuesGrid",
+ "rest/queue/"+ encodeURIComponent(that.name),
+ "Are you sure you want to delete queue");
+ }
+ );
+
+ var addExchangeButton = query(".addExchangeButton", contentPane.containerNode)[0];
+ connect.connect(registry.byNode(addExchangeButton), "onClick", function(evt){ addExchange.show(that.name) });
+
+ var deleteExchangeButton = query(".deleteExchangeButton", contentPane.containerNode)[0];
+ connect.connect(registry.byNode(deleteExchangeButton), "onClick",
+ function(evt)
+ {
+ util.deleteGridSelections(
+ that.vhostUpdater,
+ "exchangesGrid",
+ "rest/exchange/"+ encodeURIComponent(that.name),
+ "Are you sure you want to delete exchange");
+ }
+ );
+ }});
+
+ };
+
+ VirtualHost.prototype.close = function() {
+ updater.remove( this.vhostUpdater );
+ };
+
+ function Updater(node, vhost, controller)
+ {
+
+ var that = this;
+
+ function findNode(name) {
+ return query("." + name, node)[0];
+ }
+
+ function storeNodes(names)
+ {
+ for(var i = 0; i < names.length; i++) {
+ that[names[i]] = findNode(names[i]);
+ }
+ }
+
+ storeNodes(["name",
+ "state",
+ "durable",
+ "lifetimePolicy",
+ "alertRepeatGap",
+ "alertRepeatGapUnits",
+ "alertThresholdMessageAge",
+ "alertThresholdMessageAgeUnits",
+ "alertThresholdMessageSize",
+ "alertThresholdMessageSizeUnits",
+ "alertThresholdQueueDepthBytes",
+ "alertThresholdQueueDepthBytesUnits",
+ "alertThresholdQueueDepthMessages",
+ "msgInRate",
+ "bytesInRate",
+ "bytesInRateUnits",
+ "msgOutRate",
+ "bytesOutRate",
+ "bytesOutRateUnits"]);
+
+ this.query = "rest/virtualhost/"+ encodeURIComponent(vhost.name);
+
+ var that = this;
+
+ xhr.get({url: this.query, sync: properties.useSyncGet, handleAs: "json"}).then(function(data) {
+ that.vhostData = data[0];
+
+ // flatten statistics into attributes
+ util.flattenStatistics( that.vhostData );
+
+ var gridProperties = {
+ keepSelection: true,
+ plugins: {
+ pagination: {
+ pageSizes: ["10", "25", "50", "100"],
+ description: true,
+ sizeSwitch: true,
+ pageStepper: true,
+ gotoButton: true,
+ maxPageStep: 4,
+ position: "bottom"
+ },
+ indirectSelection: true
+
+ }};
+
+ that.updateHeader();
+ that.queuesGrid = new UpdatableStore(that.vhostData.queues, findNode("queues"),
+ [ { name: "Name", field: "name", width: "90px"},
+ { name: "Messages", field: "queueDepthMessages", width: "90px"},
+ { name: "Arguments", field: "arguments", width: "100%"}
+ ],
+ function(obj)
+ {
+ connect.connect(obj.grid, "onRowDblClick", obj.grid,
+ function(evt){
+ var idx = evt.rowIndex,
+ theItem = this.getItem(idx);
+ var queueName = obj.dataStore.getValue(theItem,"name");
+ controller.show("queue", queueName, vhost);
+ });
+ } , gridProperties, EnhancedGrid);
+
+ that.exchangesGrid = new UpdatableStore(that.vhostData.exchanges, findNode("exchanges"),
+ [
+ { name: "Name", field: "name", width: "120px"},
+ { name: "Type", field: "type", width: "120px"},
+ { name: "Binding Count", field: "bindingCount", width: "100%"}
+ ],
+ function(obj)
+ {
+ connect.connect(obj.grid, "onRowDblClick", obj.grid,
+ function(evt){
+ var idx = evt.rowIndex,
+ theItem = this.getItem(idx);
+ var exchangeName = obj.dataStore.getValue(theItem,"name");
+ controller.show("exchange", exchangeName, vhost);
+ });
+ } , gridProperties, EnhancedGrid);
+
+
+ that.connectionsGrid = new UpdatableStore(that.vhostData.connections,
+ findNode("connections"),
+ [ { name: "Name", field: "name", width: "150px"},
+ { name: "Sessions", field: "sessionCount", width: "70px"},
+ { name: "Msgs In", field: "msgInRate",
+ width: "80px"},
+ { name: "Bytes In", field: "bytesInRate",
+ width: "80px"},
+ { name: "Msgs Out", field: "msgOutRate",
+ width: "80px"},
+ { name: "Bytes Out", field: "bytesOutRate",
+ width: "100%"}
+ ],
+ function(obj)
+ {
+ connect.connect(obj.grid, "onRowDblClick", obj.grid,
+ function(evt){
+ var idx = evt.rowIndex,
+ theItem = this.getItem(idx);
+ var connectionName = obj.dataStore.getValue(theItem,"name");
+ controller.show("connection", connectionName, vhost);
+ });
+ } );
+
+
+
+ });
+
+ }
+
+ Updater.prototype.updateHeader = function()
+ {
+ this.name.innerHTML = this.vhostData[ "name" ];
+ this.state.innerHTML = this.vhostData[ "state" ];
+ this.durable.innerHTML = this.vhostData[ "durable" ];
+ this.lifetimePolicy.innerHTML = this.vhostData[ "lifetimePolicy" ];
+
+
+ };
+
+ Updater.prototype.update = function()
+ {
+
+ var thisObj = this;
+
+ xhr.get({url: this.query, sync: properties.useSyncGet, handleAs: "json"})
+ .then(function(data) {
+ thisObj.vhostData = data[0];
+ util.flattenStatistics( thisObj.vhostData );
+ var connections = thisObj.vhostData[ "connections" ];
+ var queues = thisObj.vhostData[ "queues" ];
+ var exchanges = thisObj.vhostData[ "exchanges" ];
+
+ thisObj.updateHeader();
+
+
+ // update alerting info
+ var alertRepeatGap = formatter.formatTime( thisObj.vhostData["alertRepeatGap"] );
+
+ thisObj.alertRepeatGap.innerHTML = alertRepeatGap.value;
+ thisObj.alertRepeatGapUnits.innerHTML = alertRepeatGap.units;
+
+
+ var alertMsgAge = formatter.formatTime( thisObj.vhostData["alertThresholdMessageAge"] );
+
+ thisObj.alertThresholdMessageAge.innerHTML = alertMsgAge.value;
+ thisObj.alertThresholdMessageAgeUnits.innerHTML = alertMsgAge.units;
+
+ var alertMsgSize = formatter.formatBytes( thisObj.vhostData["alertThresholdMessageSize"] );
+
+ thisObj.alertThresholdMessageSize.innerHTML = alertMsgSize.value;
+ thisObj.alertThresholdMessageSizeUnits.innerHTML = alertMsgSize.units;
+
+ var alertQueueDepth = formatter.formatBytes( thisObj.vhostData["alertThresholdQueueDepthBytes"] );
+
+ thisObj.alertThresholdQueueDepthBytes.innerHTML = alertQueueDepth.value;
+ thisObj.alertThresholdQueueDepthBytesUnits.innerHTML = alertQueueDepth.units;
+
+ thisObj.alertThresholdQueueDepthMessages.innerHTML = thisObj.vhostData["alertThresholdQueueDepthMessages"];
+
+ var stats = thisObj.vhostData[ "statistics" ];
+
+ var sampleTime = new Date();
+ var messageIn = stats["messagesIn"];
+ var bytesIn = stats["bytesIn"];
+ var messageOut = stats["messagesOut"];
+ var bytesOut = stats["bytesOut"];
+
+ if(thisObj.sampleTime)
+ {
+ var samplePeriod = sampleTime.getTime() - thisObj.sampleTime.getTime();
+
+ var msgInRate = (1000 * (messageIn - thisObj.messageIn)) / samplePeriod;
+ var msgOutRate = (1000 * (messageOut - thisObj.messageOut)) / samplePeriod;
+ var bytesInRate = (1000 * (bytesIn - thisObj.bytesIn)) / samplePeriod;
+ var bytesOutRate = (1000 * (bytesOut - thisObj.bytesOut)) / samplePeriod;
+
+ thisObj.msgInRate.innerHTML = msgInRate.toFixed(0);
+ var bytesInFormat = formatter.formatBytes( bytesInRate );
+ thisObj.bytesInRate.innerHTML = "(" + bytesInFormat.value;
+ thisObj.bytesInRateUnits.innerHTML = bytesInFormat.units + "/s)";
+
+ thisObj.msgOutRate.innerHTML = msgOutRate.toFixed(0);
+ var bytesOutFormat = formatter.formatBytes( bytesOutRate );
+ thisObj.bytesOutRate.innerHTML = "(" + bytesOutFormat.value;
+ thisObj.bytesOutRateUnits.innerHTML = bytesOutFormat.units + "/s)";
+
+ if(connections && thisObj.connections)
+ {
+ for(var i=0; i < connections.length; i++)
+ {
+ var connection = connections[i];
+ for(var j = 0; j < thisObj.connections.length; j++)
+ {
+ var oldConnection = thisObj.connections[j];
+ if(oldConnection.id == connection.id)
+ {
+ msgOutRate = (1000 * (connection.messagesOut - oldConnection.messagesOut)) /
+ samplePeriod;
+ connection.msgOutRate = msgOutRate.toFixed(0) + "msg/s";
+
+ bytesOutRate = (1000 * (connection.bytesOut - oldConnection.bytesOut)) /
+ samplePeriod;
+ var bytesOutRateFormat = formatter.formatBytes( bytesOutRate );
+ connection.bytesOutRate = bytesOutRateFormat.value + bytesOutRateFormat.units + "/s";
+
+
+ msgInRate = (1000 * (connection.messagesIn - oldConnection.messagesIn)) /
+ samplePeriod;
+ connection.msgInRate = msgInRate.toFixed(0) + "msg/s";
+
+ bytesInRate = (1000 * (connection.bytesIn - oldConnection.bytesIn)) /
+ samplePeriod;
+ var bytesInRateFormat = formatter.formatBytes( bytesInRate );
+ connection.bytesInRate = bytesInRateFormat.value + bytesInRateFormat.units + "/s";
+ }
+
+
+ }
+
+ }
+ }
+ }
+
+ thisObj.sampleTime = sampleTime;
+ thisObj.messageIn = messageIn;
+ thisObj.bytesIn = bytesIn;
+ thisObj.messageOut = messageOut;
+ thisObj.bytesOut = bytesOut;
+ thisObj.connections = connections;
+
+ // update queues
+ thisObj.queuesGrid.update(thisObj.vhostData.queues);
+
+ // update exchanges
+ thisObj.exchangesGrid.update(thisObj.vhostData.exchanges);
+
+ var exchangesGrid = thisObj.exchangesGrid.grid;
+ for(var i=0; i< thisObj.vhostData.exchanges.length; i++)
+ {
+ var data = exchangesGrid.getItem(i);
+ var isStandard = false;
+ if (data && data.name)
+ {
+ isStandard = util.isReservedExchangeName(data.name);
+ }
+ exchangesGrid.rowSelectCell.setDisabled(i, isStandard);
+ }
+
+ // update connections
+ thisObj.connectionsGrid.update(thisObj.vhostData.connections)
+
+
+ });
+ };
+
+
+ return VirtualHost;
+ }); \ No newline at end of file
diff --git a/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addBinding.js b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addBinding.js
new file mode 100644
index 0000000000..83e724d0e9
--- /dev/null
+++ b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addBinding.js
@@ -0,0 +1,223 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+define(["dojo/_base/xhr",
+ "dojo/dom",
+ "dojo/dom-construct",
+ "dojo/_base/window",
+ "dijit/registry",
+ "dojo/parser",
+ "dojo/_base/array",
+ "dojo/_base/event",
+ 'dojo/_base/json',
+ "dojo/store/Memory",
+ "dijit/form/FilteringSelect",
+ "dijit/form/NumberSpinner", // required by the form
+ /* dojox/ validate resources */
+ "dojox/validate/us", "dojox/validate/web",
+ /* basic dijit classes */
+ "dijit/Dialog",
+ "dijit/form/CheckBox", "dijit/form/Textarea",
+ "dijit/form/FilteringSelect", "dijit/form/TextBox",
+ "dijit/form/ValidationTextBox", "dijit/form/DateTextBox",
+ "dijit/form/TimeTextBox", "dijit/form/Button",
+ "dijit/form/RadioButton", "dijit/form/Form",
+ "dijit/form/DateTextBox",
+ /* basic dojox classes */
+ "dojox/form/BusyButton", "dojox/form/CheckedMultiSelect",
+ "dojo/domReady!"],
+ function (xhr, dom, construct, win, registry, parser, array, event, json, Memory, FilteringSelect) {
+
+ var addBinding = {};
+
+ var node = construct.create("div", null, win.body(), "last");
+
+ var convertToBinding = function convertToBinding(formValues)
+ {
+ var newBinding = {};
+
+ newBinding.name = formValues.name;
+ for(var propName in formValues)
+ {
+ if(formValues.hasOwnProperty(propName))
+ {
+ if(propName === "durable")
+ {
+ if (formValues.durable[0] && formValues.durable[0] == "durable") {
+ newBinding.durable = true;
+ }
+ } else {
+ if(formValues[ propName ] !== "") {
+ newBinding[ propName ] = formValues[propName];
+ }
+ }
+
+ }
+ }
+ if(addBinding.queue) {
+ newBinding.queue = addBinding.queue;
+ }
+ if(addBinding.exchange) {
+ newBinding.exchange = addBinding.exchange;
+ }
+ return newBinding;
+ };
+
+
+ xhr.get({url: "addBinding.html",
+ sync: true,
+ load: function(data) {
+ var theForm;
+ node.innerHTML = data;
+ addBinding.dialogNode = dom.byId("addBinding");
+ parser.instantiate([addBinding.dialogNode]);
+
+ theForm = registry.byId("formAddBinding");
+ array.forEach(theForm.getDescendants(), function(widget)
+ {
+ if(widget.name === "type") {
+ widget.on("change", function(isChecked) {
+
+ var obj = registry.byId(widget.id + ":fields");
+ if(obj) {
+ if(isChecked) {
+ obj.domNode.style.display = "block";
+ obj.resize();
+ } else {
+ obj.domNode.style.display = "none";
+ obj.resize();
+ }
+ }
+ })
+ }
+
+ });
+
+ theForm.on("submit", function(e) {
+
+ event.stop(e);
+ if(theForm.validate()){
+
+ var newBinding = convertToBinding(theForm.getValues());
+ var that = this;
+
+ xhr.put({url: "rest/binding/"+encodeURIComponent(addBinding.vhost)
+ +"/"+encodeURIComponent(newBinding.exchange)
+ +"/"+encodeURIComponent(newBinding.queue)
+ +"/"+encodeURIComponent(newBinding.name),
+ sync: true, handleAs: "json",
+ headers: { "Content-Type": "application/json"},
+ putData: json.toJson(newBinding),
+ load: function(x) {that.success = true; },
+ error: function(error) {that.success = false; that.failureReason = error;}});
+
+ if(this.success === true)
+ {
+ registry.byId("addBinding").hide();
+ }
+ else
+ {
+ alert("Error:" + this.failureReason);
+ }
+
+ return false;
+
+
+ }else{
+ alert('Form contains invalid data. Please correct first');
+ return false;
+ }
+
+ });
+ }});
+
+ addBinding.show = function(obj) {
+ var that = this;
+
+ addBinding.vhost = obj.virtualhost;
+ addBinding.queue = obj.queue;
+ addBinding.exchange = obj.exchange;
+ registry.byId("formAddBinding").reset();
+
+
+
+ xhr.get({url: "rest/queue/" + encodeURIComponent(obj.virtualhost) + "?depth=0",
+ handleAs: "json"}).then(
+ function(data) {
+ var queues = [];
+ for(var i=0; i < data.length; i++) {
+ queues[i] = {id: data[i].name, name: data[i].name};
+ }
+ var queueStore = new Memory({ data: queues });
+
+
+ if(that.queueChooser) {
+ that.queueChooser.destroy( false );
+ }
+ var queueDiv = dom.byId("addBinding.selectQueueDiv");
+ var input = construct.create("input", {id: "addBindingSelectQueue"}, queueDiv);
+
+ that.queueChooser = new FilteringSelect({ id: "addBindingSelectQueue",
+ name: "queue",
+ store: queueStore,
+ searchAttr: "name"}, input);
+
+ if(obj.queue)
+ {
+ that.queueChooser.set("value", obj.queue);
+ that.queueChooser.set("disabled", true);
+ }
+
+ xhr.get({url: "rest/exchange/" + encodeURIComponent(obj.virtualhost) + "?depth=0",
+ handleAs: "json"}).then(
+ function(data) {
+
+ var exchanges = [];
+ for(var i=0; i < data.length; i++) {
+ exchanges[i] = {id: data[i].name, name: data[i].name};
+ }
+ var exchangeStore = new Memory({ data: exchanges });
+
+
+ if(that.exchangeChooser) {
+ that.exchangeChooser.destroy( false );
+ }
+ var exchangeDiv = dom.byId("addBinding.selectExchangeDiv");
+ var input = construct.create("input", {id: "addBindingSelectExchange"}, exchangeDiv);
+
+ that.exchangeChooser = new FilteringSelect({ id: "addBindingSelectExchange",
+ name: "exchange",
+ store: exchangeStore,
+ searchAttr: "name"}, input);
+
+ if(obj.exchange)
+ {
+ that.exchangeChooser.set("value", obj.exchange);
+ that.exchangeChooser.set("disabled", true);
+ }
+
+
+ registry.byId("addBinding").show();
+ });
+
+
+ });
+
+
+ };
+
+ return addBinding;
+ });
diff --git a/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addExchange.js b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addExchange.js
new file mode 100644
index 0000000000..915092a9d1
--- /dev/null
+++ b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addExchange.js
@@ -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.
+ *
+ */
+define(["dojo/_base/xhr",
+ "dojo/dom",
+ "dojo/dom-construct",
+ "dojo/_base/window",
+ "dijit/registry",
+ "dojo/parser",
+ "dojo/_base/array",
+ "dojo/_base/event",
+ 'dojo/_base/json',
+ "dijit/form/NumberSpinner", // required by the form
+ /* dojox/ validate resources */
+ "dojox/validate/us", "dojox/validate/web",
+ /* basic dijit classes */
+ "dijit/Dialog",
+ "dijit/form/CheckBox", "dijit/form/Textarea",
+ "dijit/form/FilteringSelect", "dijit/form/TextBox",
+ "dijit/form/ValidationTextBox", "dijit/form/DateTextBox",
+ "dijit/form/TimeTextBox", "dijit/form/Button",
+ "dijit/form/RadioButton", "dijit/form/Form",
+ "dijit/form/DateTextBox",
+ /* basic dojox classes */
+ "dojox/form/BusyButton", "dojox/form/CheckedMultiSelect",
+ "dojo/domReady!"],
+ function (xhr, dom, construct, win, registry, parser, array, event, json) {
+
+ var addExchange = {};
+
+ var node = construct.create("div", null, win.body(), "last");
+
+ var convertToExchange = function convertToExchange(formValues)
+ {
+ var newExchange = {};
+ newExchange.name = formValues.name;
+ for(var propName in formValues)
+ {
+ if(formValues.hasOwnProperty(propName))
+ {
+ if(propName === "durable")
+ {
+ if (formValues.durable[0] && formValues.durable[0] == "durable") {
+ newExchange.durable = true;
+ }
+ } else {
+ if(formValues[ propName ] !== "") {
+ newExchange[ propName ] = formValues[propName];
+ }
+ }
+
+ }
+ }
+
+ return newExchange;
+ };
+
+
+ xhr.get({url: "addExchange.html",
+ sync: true,
+ load: function(data) {
+ var theForm;
+ node.innerHTML = data;
+ addExchange.dialogNode = dom.byId("addExchange");
+ parser.instantiate([addExchange.dialogNode]);
+
+ theForm = registry.byId("formAddExchange");
+ array.forEach(theForm.getDescendants(), function(widget)
+ {
+ if(widget.name === "type") {
+ widget.on("change", function(isChecked) {
+
+ var obj = registry.byId(widget.id + ":fields");
+ if(obj) {
+ if(isChecked) {
+ obj.domNode.style.display = "block";
+ obj.resize();
+ } else {
+ obj.domNode.style.display = "none";
+ obj.resize();
+ }
+ }
+ })
+ }
+
+ });
+
+ theForm.on("submit", function(e) {
+
+ event.stop(e);
+ if(theForm.validate()){
+
+ var newExchange = convertToExchange(theForm.getValues());
+ var that = this;
+ xhr.put({url: "rest/exchange/"+encodeURIComponent(addExchange.vhost) +
+ "/"+encodeURIComponent(newExchange.name), sync: true, handleAs: "json",
+ headers: { "Content-Type": "application/json"},
+ putData: json.toJson(newExchange),
+ load: function(x) {that.success = true; },
+ error: function(error) {that.success = false; that.failureReason = error;}});
+
+ if(this.success === true)
+ {
+ registry.byId("addExchange").hide();
+ }
+ else
+ {
+ alert("Error:" + this.failureReason);
+ }
+
+ return false;
+
+
+ }else{
+ alert('Form contains invalid data. Please correct first');
+ return false;
+ }
+
+ });
+ }});
+
+ addExchange.show = function(vhost) {
+ addExchange.vhost = vhost;
+ registry.byId("formAddExchange").reset();
+ registry.byId("addExchange").show();
+ };
+
+ return addExchange;
+ }); \ No newline at end of file
diff --git a/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addQueue.js b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addQueue.js
new file mode 100644
index 0000000000..53f82aff48
--- /dev/null
+++ b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addQueue.js
@@ -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.
+ *
+ */
+define(["dojo/_base/xhr",
+ "dojo/dom",
+ "dojo/dom-construct",
+ "dojo/_base/window",
+ "dijit/registry",
+ "dojo/parser",
+ "dojo/_base/array",
+ "dojo/_base/event",
+ 'dojo/_base/json',
+ "dijit/form/NumberSpinner", // required by the form
+ /* dojox/ validate resources */
+ "dojox/validate/us", "dojox/validate/web",
+ /* basic dijit classes */
+ "dijit/Dialog",
+ "dijit/form/CheckBox", "dijit/form/Textarea",
+ "dijit/form/FilteringSelect", "dijit/form/TextBox",
+ "dijit/form/ValidationTextBox", "dijit/form/DateTextBox",
+ "dijit/form/TimeTextBox", "dijit/form/Button",
+ "dijit/form/RadioButton", "dijit/form/Form",
+ "dijit/form/DateTextBox",
+ /* basic dojox classes */
+ "dojox/form/BusyButton", "dojox/form/CheckedMultiSelect",
+ "dojo/domReady!"],
+ function (xhr, dom, construct, win, registry, parser, array, event, json) {
+
+ var addQueue = {};
+
+ var node = construct.create("div", null, win.body(), "last");
+
+ var typeSpecificFields = {
+ priorities: "priority",
+ lvqKey: "lvq",
+ sortKey: "sorted"
+ };
+
+ var requiredFields = {
+ priority: "priorities",
+ sorted: "sortkey"
+ };
+
+ var fieldConverters = {
+ queueFlowControlSizeBytes: parseInt,
+ queueFlowResumeSizeBytes: parseInt,
+ alertThresholdMessageSize: parseInt,
+ alertThresholdQueueDepthMessages: parseInt,
+ maximumDeliveryAttempts: parseInt,
+ alertThresholdMessageAge: parseInt,
+ alertRepeatGap: parseInt
+ }
+
+ var convertToQueue = function convertToQueue(formValues)
+ {
+ var newQueue = {};
+ newQueue.name = formValues.name;
+ for(var propName in formValues)
+ {
+ if(formValues.hasOwnProperty(propName))
+ {
+ if(propName === "durable")
+ {
+ if (formValues.durable[0] && formValues.durable[0] == "durable") {
+ newQueue.durable = true;
+ }
+ }
+ else if(propName === "dlqEnabled")
+ {
+ if (formValues.dlqEnabled[0] && formValues.dlqEnabled[0] == "dlqEnabled") {
+ newQueue["x-qpid-dlq-enabled"] = true;
+ }
+ }
+ else if (!typeSpecificFields.hasOwnProperty(propName) ||
+ formValues.type === typeSpecificFields[ propName ]) {
+ if(formValues[ propName ] !== "") {
+ if (fieldConverters.hasOwnProperty(propName))
+ {
+ newQueue[ propName ] = fieldConverters[propName](formValues[propName]);
+ }
+ else
+ {
+ newQueue[ propName ] = formValues[propName];
+ }
+ }
+ }
+
+ }
+ }
+
+ return newQueue;
+ };
+
+
+ xhr.get({url: "addQueue.html",
+ sync: true,
+ load: function(data) {
+ var theForm;
+ node.innerHTML = data;
+ addQueue.dialogNode = dom.byId("addQueue");
+ parser.instantiate([addQueue.dialogNode]);
+
+ // for children which have name type, add a function to make all the associated rows
+ // visible / invisible as the radio button is checked / unchecked
+
+ theForm = registry.byId("formAddQueue");
+ array.forEach(theForm.getDescendants(), function(widget)
+ {
+ if(widget.name === "type") {
+ widget.on("change", function(isChecked) {
+
+ var objId = widget.id + ":fields";
+ var obj = registry.byId(objId);
+ if(obj) {
+ if(isChecked) {
+ obj.domNode.style.display = "block";
+ } else {
+ obj.domNode.style.display = "none";
+ }
+ obj.resize();
+ var widgetValue = widget.value;
+ if (requiredFields.hasOwnProperty(widgetValue))
+ {
+ dijit.byId('formAddQueue.' + requiredFields[widgetValue]).required = isChecked;
+ }
+ }
+ })
+ }
+
+ });
+
+ theForm.on("submit", function(e) {
+
+ event.stop(e);
+ if(theForm.validate()){
+
+ var newQueue = convertToQueue(theForm.getValues());
+ var that = this;
+
+ xhr.put({url: "rest/queue/"+encodeURIComponent(addQueue.vhost)
+ +"/"+encodeURIComponent(newQueue.name), sync: true, handleAs: "json",
+ headers: { "Content-Type": "application/json"},
+ putData: json.toJson(newQueue),
+ load: function(x) {that.success = true; },
+ error: function(error) {that.success = false; that.failureReason = error;}});
+
+ if(this.success === true)
+ {
+ registry.byId("addQueue").hide();
+ }
+ else
+ {
+ alert("Error:" + this.failureReason);
+ }
+
+ return false;
+
+
+ }else{
+ alert('Form contains invalid data. Please correct first');
+ return false;
+ }
+
+ });
+ }});
+
+ addQueue.show = function(vhost) {
+ addQueue.vhost = vhost;
+ registry.byId("formAddQueue").reset();
+ registry.byId("addQueue").show();
+ };
+
+ return addQueue;
+ }); \ No newline at end of file
diff --git a/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/authenticationprovider/PrincipalDatabaseAuthenticationManager.js b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/authenticationprovider/PrincipalDatabaseAuthenticationManager.js
new file mode 100644
index 0000000000..8e5ac862bd
--- /dev/null
+++ b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/authenticationprovider/PrincipalDatabaseAuthenticationManager.js
@@ -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.
+ *
+ */
+define(["dojo/_base/xhr",
+ "dojo/dom",
+ "dojo/parser",
+ "dojo/query",
+ "dojo/dom-construct",
+ "dojo/_base/connect",
+ "dojo/_base/window",
+ "dojo/_base/event",
+ "dojo/_base/json",
+ "dijit/registry",
+ "qpid/common/util",
+ "qpid/common/properties",
+ "qpid/common/updater",
+ "qpid/common/UpdatableStore",
+ "dojox/grid/EnhancedGrid",
+ "dojox/grid/enhanced/plugins/Pagination",
+ "dojox/grid/enhanced/plugins/IndirectSelection",
+ "dojox/validate/us", "dojox/validate/web",
+ "dijit/Dialog",
+ "dijit/form/TextBox",
+ "dijit/form/ValidationTextBox",
+ "dijit/form/TimeTextBox", "dijit/form/Button",
+ "dijit/form/Form",
+ "dijit/form/DateTextBox",
+ "dojo/domReady!"],
+ function (xhr, dom, parser, query, construct, connect, win, event, json, registry, util, properties, updater, UpdatableStore, EnhancedGrid) {
+ function DatabaseAuthManager(containerNode, authProviderObj, controller) {
+ var node = construct.create("div", null, containerNode, "last");
+ var that = this;
+ this.name = authProviderObj.name;
+ xhr.get({url: "authenticationprovider/showPrincipalDatabaseAuthenticationManager.html",
+ sync: true,
+ load: function(data) {
+ node.innerHTML = data;
+ parser.parse(node);
+
+
+ that.authDatabaseUpdater= new AuthProviderUpdater(node, authProviderObj, controller);
+
+ updater.add( that.authDatabaseUpdater);
+
+ that.authDatabaseUpdater.update();
+
+
+ }});
+ }
+
+ DatabaseAuthManager.prototype.update = function() {
+ this.authDatabaseUpdater.update();
+ };
+
+ DatabaseAuthManager.prototype.close = function() {
+ updater.remove( this.authDatabaseUpdater );
+ };
+
+ function AuthProviderUpdater(node, authProviderObj, controller)
+ {
+ this.controller = controller;
+ this.query = "rest/authenticationprovider/"+encodeURIComponent(authProviderObj.name);
+ this.name = authProviderObj.name;
+ var that = this;
+
+ xhr.get({url: this.query, sync: properties.useSyncGet, handleAs: "json"})
+ .then(function(data) {
+ that.authProviderData = data[0];
+
+ util.flattenStatistics( that.authProviderData );
+
+ var userDiv = query(".users")[0];
+
+ var gridProperties = {
+ height: 400,
+ keepSelection: true,
+ plugins: {
+ pagination: {
+ pageSizes: ["10", "25", "50", "100"],
+ description: true,
+ sizeSwitch: true,
+ pageStepper: true,
+ gotoButton: true,
+ maxPageStep: 4,
+ position: "bottom"
+ },
+ indirectSelection: true
+
+ }};
+
+
+ that.usersGrid =
+ new UpdatableStore(that.authProviderData.users, userDiv,
+ [ { name: "User Name", field: "name", width: "100%" }
+ ], function(obj) {
+ connect.connect(obj.grid, "onRowDblClick", obj.grid,
+ function(evt){
+ var idx = evt.rowIndex,
+ theItem = this.getItem(idx);
+ var name = obj.dataStore.getValue(theItem,"name");
+ var id = obj.dataStore.getValue(theItem,"id");
+ setPassword.show(authProviderObj.name, {name: name, id: id});
+ });
+ }, gridProperties, EnhancedGrid);
+
+
+ var addUserButton = query(".addUserButton", node)[0];
+ connect.connect(registry.byNode(addUserButton), "onClick", function(evt){ addUser.show(authProviderObj.name) });
+
+ var deleteMessagesButton = query(".deleteUserButton", node)[0];
+ var deleteWidget = registry.byNode(deleteMessagesButton);
+ connect.connect(deleteWidget, "onClick",
+ function(evt){
+ event.stop(evt);
+ that.deleteUsers();
+ });
+ });
+ }
+
+ AuthProviderUpdater.prototype.deleteUsers = function()
+ {
+ var grid = this.usersGrid.grid;
+ var data = grid.selection.getSelected();
+ if(data.length) {
+ var that = this;
+ if(confirm("Delete " + data.length + " users?")) {
+ var i, queryParam;
+ for(i = 0; i<data.length; i++) {
+ if(queryParam) {
+ queryParam += "&";
+ } else {
+ queryParam = "?";
+ }
+
+ queryParam += "id=" + data[i].id;
+ }
+ var query = "rest/user/"+ encodeURIComponent(that.name)
+ + queryParam;
+ that.success = true
+ xhr.del({url: query, sync: true, handleAs: "json"}).then(
+ function(data) {
+ grid.setQuery({id: "*"});
+ grid.selection.deselectAll();
+ that.update();
+ },
+ function(error) {that.success = false; that.failureReason = error;});
+ if(!that.success ) {
+ alert("Error:" + this.failureReason);
+ }
+ }
+}
+ };
+
+ AuthProviderUpdater.prototype.update = function()
+ {
+
+ var that = this;
+
+ xhr.get({url: this.query, sync: properties.useSyncGet, handleAs: "json"})
+ .then(function(data) {
+ that.authProviderData = data[0];
+ util.flattenStatistics( that.authProviderData );
+
+ that.usersGrid.update(that.authProviderData.users);
+
+ });
+
+
+ };
+
+ var addUser = {};
+
+ var node = construct.create("div", null, win.body(), "last");
+
+ var convertToUser = function convertToUser(formValues) {
+ var newUser = {};
+ newUser.name = formValues.name;
+ for(var propName in formValues)
+ {
+ if(formValues.hasOwnProperty(propName)) {
+ if(formValues[ propName ] !== "") {
+ newUser[ propName ] = formValues[propName];
+ }
+ }
+ }
+
+ return newUser;
+ };
+
+
+ xhr.get({url: "authenticationprovider/addUser.html",
+ sync: true,
+ load: function(data) {
+ var theForm;
+ node.innerHTML = data;
+ addUser.dialogNode = dom.byId("addUser");
+ parser.instantiate([addUser.dialogNode]);
+
+ var that = this;
+
+ theForm = registry.byId("formAddUser");
+ theForm.on("submit", function(e) {
+
+ event.stop(e);
+ if(theForm.validate()){
+
+ var newUser = convertToUser(theForm.getValues());
+
+
+ var url = "rest/user/"+encodeURIComponent(addUser.authProvider) +
+ "/"+encodeURIComponent(newUser.name);
+
+ xhr.put({url: url, sync: true, handleAs: "json",
+ headers: { "Content-Type": "application/json"},
+ putData: json.toJson(newUser),
+ load: function(x) {that.success = true; },
+ error: function(error) {that.success = false; that.failureReason = error;}});
+
+ if(that.success === true) {
+ registry.byId("addUser").hide();
+ } else {
+ alert("Error:" + that.failureReason);
+ }
+
+ return false;
+
+
+ }else{
+ alert('Form contains invalid data. Please correct first');
+ return false;
+ }
+
+ });
+ }});
+
+ addUser.show = function(authProvider) {
+ addUser.authProvider = authProvider;
+ registry.byId("formAddUser").reset();
+ registry.byId("addUser").show();
+ };
+
+
+ var setPassword = {};
+
+ var setPasswordNode = construct.create("div", null, win.body(), "last");
+
+ xhr.get({url: "authenticationprovider/setPassword.html",
+ sync: true,
+ load: function(data) {
+ var theForm;
+ setPasswordNode.innerHTML = data;
+ setPassword.dialogNode = dom.byId("setPassword");
+ parser.instantiate([setPassword.dialogNode]);
+
+ var that = this;
+
+ theForm = registry.byId("formSetPassword");
+ theForm.on("submit", function(e) {
+
+ event.stop(e);
+ if(theForm.validate()){
+
+ var newUser = convertToUser(theForm.getValues());
+ newUser.name = setPassword.name;
+ newUser.id = setPassword.id;
+
+ var url = "rest/user/"+encodeURIComponent(setPassword.authProvider) +
+ "/"+encodeURIComponent(newUser.name);
+
+ xhr.put({url: url, sync: true, handleAs: "json",
+ headers: { "Content-Type": "application/json"},
+ putData: json.toJson(newUser),
+ load: function(x) {that.success = true; },
+ error: function(error) {that.success = false; that.failureReason = error;}});
+
+ if(that.success === true) {
+ registry.byId("setPassword").hide();
+ } else {
+ alert("Error:" + that.failureReason);
+ }
+
+ return false;
+
+
+ }else{
+ alert('Form contains invalid data. Please correct first');
+ return false;
+ }
+
+ });
+ }});
+
+ setPassword.show = function(authProvider, user) {
+ setPassword.authProvider = authProvider;
+ setPassword.name = user.name;
+ setPassword.id = user.id;
+ registry.byId("formSetPassword").reset();
+
+ var namebox = registry.byId("formSetPassword.name");
+ namebox.set("value", user.name);
+ namebox.set("disabled", true);
+
+ registry.byId("setPassword").show();
+
+ };
+
+
+
+ return DatabaseAuthManager;
+ });
diff --git a/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/controller.js b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/controller.js
new file mode 100644
index 0000000000..1aa05a5a3c
--- /dev/null
+++ b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/controller.js
@@ -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.
+ *
+ */
+define(["dojo/dom",
+ "dijit/registry",
+ "dijit/layout/ContentPane",
+ "qpid/management/Broker",
+ "qpid/management/VirtualHost",
+ "qpid/management/Exchange",
+ "qpid/management/Queue",
+ "qpid/management/Connection",
+ "qpid/management/AuthenticationProvider",
+ "dojo/ready",
+ "dojo/domReady!"],
+ function (dom, registry, ContentPane, Broker, VirtualHost, Exchange, Queue, Connection, AuthProvider, ready) {
+ var controller = {};
+
+ var constructors = { broker: Broker, virtualhost: VirtualHost, exchange: Exchange,
+ queue: Queue, connection: Connection, authenticationprovider: AuthProvider };
+
+ var tabDiv = dom.byId("managedViews");
+
+ ready(function() {
+ controller.tabContainer = registry.byId("managedViews");
+ });
+
+
+ controller.viewedObjects = {};
+
+ controller.show = function(objType, name, parent) {
+
+ function generateName(obj)
+ {
+ if(obj) {
+ var name = "";
+ if(obj.parent)
+ {
+ for(var prop in obj.parent) {
+ if(obj.parent.hasOwnProperty(prop)) {
+ name = name + generateName( obj.parent[ prop ]);
+ }
+ }
+
+ }
+ return name + parent.type +":" + parent.name + "/"
+ }
+ }
+
+ var that = this;
+ var objId = generateName(parent) + objType+":"+name;
+ if( this.viewedObjects[ objId ] ) {
+ this.tabContainer.selectChild(this.viewedObjects[ objId ].contentPane);
+ } else {
+ var Constructor = constructors[ objType ];
+ if(Constructor) {
+ var obj = new Constructor(name, parent, this);
+ this.viewedObjects[ objId ] = obj;
+
+ var contentPane = new ContentPane({ region: "center" ,
+ title: obj.getTitle(),
+ closable: true,
+ onClose: function() {
+ obj.close();
+ delete that.viewedObjects[ objId ];
+ return true;
+ }
+ });
+ this.tabContainer.addChild( contentPane );
+ obj.open(contentPane);
+ contentPane.startup();
+ if(obj.startup) {
+ obj.startup();
+ }
+ this.tabContainer.selectChild( contentPane );
+ }
+
+ }
+
+ };
+
+ ready(function() {
+ controller.show("broker","");
+ });
+
+
+ return controller;
+ }); \ No newline at end of file
diff --git a/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/moveCopyMessages.js b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/moveCopyMessages.js
new file mode 100644
index 0000000000..8cc488324f
--- /dev/null
+++ b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/moveCopyMessages.js
@@ -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.
+ */
+
+define(["dojo/_base/xhr",
+ "dojo/dom",
+ "dojo/dom-construct",
+ "dojo/_base/window",
+ "dijit/registry",
+ "dojo/parser",
+ "dojo/_base/array",
+ "dojo/_base/event",
+ 'dojo/_base/json',
+ "dojo/store/Memory",
+ "dijit/form/FilteringSelect",
+ "dojo/query",
+ "dojo/_base/connect",
+ "dojo/domReady!"],
+ function (xhr, dom, construct, win, registry, parser, array, event, json, Memory, FilteringSelect, query, connect) {
+
+ var moveMessages = {};
+
+ var node = construct.create("div", null, win.body(), "last");
+
+ xhr.get({url: "moveCopyMessages.html",
+ sync: true,
+ load: function(data) {
+ var theForm;
+ node.innerHTML = data;
+ moveMessages.dialogNode = dom.byId("moveMessages");
+ parser.instantiate([moveMessages.dialogNode]);
+
+ theForm = registry.byId("formMoveMessages");
+
+
+ var cancelButton = query(".moveMessageCancel")[0];
+ connect.connect(registry.byNode(cancelButton), "onClick",
+ function(evt){
+ event.stop(evt);
+ registry.byId("moveMessages").hide();
+ });
+
+
+ theForm.on("submit", function(e) {
+
+ event.stop(e);
+ if(theForm.validate()){
+
+ moveMessages.data.destinationQueue = theForm.getValues()["queue"];
+ var that = this;
+
+ xhr.post({url: "rest/message/"+encodeURIComponent(moveMessages.vhost)
+ +"/"+encodeURIComponent(moveMessages.queue),
+ sync: true, handleAs: "json",
+ headers: { "Content-Type": "application/json"},
+ postData: json.toJson(moveMessages.data),
+ load: function(x) {that.success = true; },
+ error: function(error) {that.success = false; that.failureReason = error;}});
+
+ if(this.success === true) {
+ registry.byId("moveMessages").hide();
+ if(moveMessages.next) {
+ moveMessages.next();
+ }
+ } else {
+ alert("Error:" + this.failureReason);
+ }
+
+ return false;
+
+
+ }else{
+ alert('Form contains invalid data. Please correct first');
+ return false;
+ }
+
+ });
+
+ }});
+
+ moveMessages.show = function(obj, next) {
+ var that = this;
+
+ moveMessages.vhost = obj.virtualhost;
+ moveMessages.queue = obj.queue;
+ moveMessages.data = obj.data;
+ moveMessages.next = next;
+ registry.byId("formMoveMessages").reset();
+
+
+
+ xhr.get({url: "rest/queue/" + encodeURIComponent(obj.virtualhost) + "?depth=0",
+ handleAs: "json"}).then(
+ function(data) {
+ var queues = [];
+ for(var i=0; i < data.length; i++) {
+ queues[i] = {id: data[i].name, name: data[i].name};
+ }
+ var queueStore = new Memory({ data: queues });
+
+
+ if(that.queueChooser) {
+ that.queueChooser.destroy( false );
+ }
+ var queueDiv = dom.byId("moveMessages.selectQueueDiv");
+ var input = construct.create("input", {id: "moveMessagesSelectQueue"}, queueDiv);
+
+ that.queueChooser = new FilteringSelect({ id: "moveMessagesSelectQueue",
+ name: "queue",
+ store: queueStore,
+ searchAttr: "name"}, input);
+
+
+
+ registry.byId("moveMessages").show();
+
+
+ });
+
+
+ };
+
+ return moveMessages;
+ });
diff --git a/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/showMessage.js b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/showMessage.js
new file mode 100644
index 0000000000..b1ccc0ca07
--- /dev/null
+++ b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/showMessage.js
@@ -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.
+ */
+
+define(["dojo/_base/xhr",
+ "dojo/dom",
+ "dojo/dom-construct",
+ "dojo/dom-class",
+ "dojo/_base/window",
+ "dijit/registry",
+ "dojo/parser",
+ "dojo/_base/array",
+ "dojo/_base/event",
+ 'dojo/_base/json',
+ "dojo/query",
+ "dojo/_base/connect",
+ "qpid/common/properties",
+ "dojox/html/entities",
+ "dojo/domReady!"],
+ function (xhr, dom, construct, domClass, win, registry, parser, array, event, json, query, connect, properties, entities) {
+
+
+ function encode(val){
+ return typeof val === 'string' ? entities.encode(val) : val;
+ }
+
+ var showMessage = {};
+
+ showMessage.hide = function () {
+ if(this.populatedFields) {
+ for(var i = 0 ; i < this.populatedFields.length; i++) {
+ this.populatedFields[i].innerHTML = "";
+ }
+ this.populatedFields = [];
+ }
+ registry.byId("showMessage").hide();
+ };
+
+ showMessage.loadViewMessage = function(data) {
+ var that = this;
+ node.innerHTML = data;
+ showMessage.dialogNode = dom.byId("showMessage");
+ parser.instantiate([showMessage.dialogNode]);
+
+ var closeButton = query(".closeViewMessage")[0];
+ connect.connect(closeButton, "onclick",
+ function (evt) {
+ event.stop(evt);
+ showMessage.hide();
+ });
+ };
+
+ showMessage.populateShowMessage = function(data) {
+
+ this.populatedFields = [];
+
+ for(var attrName in data) {
+ if(data.hasOwnProperty(attrName)) {
+ var fields = query(".message-"+attrName, this.dialogNode);
+ if(fields && fields.length != 0) {
+ var field = fields[0];
+ this.populatedFields.push(field);
+ var val = data[attrName];
+ if(val) {
+ if(domClass.contains(field,"map")) {
+ var tableStr = "<table style='border: 1pt'><tr><th style='width: 6em; font-weight: bold'>Header</th><th style='font-weight: bold'>Value</th></tr>";
+ for(var name in val) {
+ if(val.hasOwnProperty(name)) {
+
+ tableStr += "<tr><td>"+encode(name)+"</td>";
+ tableStr += "<td>"+encode(val[ name ])+"</td></tr>";
+ }
+ field.innerHTML = tableStr;
+ }
+ tableStr += "</table>";
+ } else if(domClass.contains(field,"datetime")) {
+ var d = new Date(0);
+ d.setUTCSeconds(val/1000);
+ field.innerHTML = d.toLocaleString();
+ } else {
+ field.innerHTML = encode(val);
+ }
+ }
+ }
+ }
+ }
+ var contentField = query(".message-content", this.dialogNode)[0];
+
+ if(data.mimeType && data.mimeType.match(/text\/.*/)) {
+ xhr.get({url: "rest/message-content/" + encodeURIComponent(showMessage.virtualhost)
+ + "/" + encodeURIComponent(showMessage.queue)
+ + "/" + encodeURIComponent(showMessage.messageNumber),
+ sync: true
+
+ }).then(function(obj) { contentField.innerHTML = encode(obj) });
+ } else {
+ contentField.innerHTML = "<a href=\"" + "rest/message-content/" + encodeURIComponent(showMessage.virtualhost)
+ + "/" + encodeURIComponent(showMessage.queue)
+ + "/" + encodeURIComponent(showMessage.messageNumber)
+ + "\" target=\"_blank\">Download</a>";
+ }
+ this.populatedFields.push(contentField);
+
+ registry.byId("showMessage").show();
+ };
+
+ showMessage.show = function(obj) {
+ showMessage.virtualhost = obj.virtualhost;
+ showMessage.queue = obj.queue;
+ showMessage.messageNumber = obj.messageNumber;
+
+ xhr.get({url: "rest/message/" + encodeURIComponent(obj.virtualhost)
+ + "/" + encodeURIComponent(obj.queue)
+ + "/" + encodeURIComponent(obj.messageNumber),
+ sync: properties.useSyncGet,
+ handleAs: "json",
+ load: this.populateShowMessage
+ });
+ };
+
+ var node = construct.create("div", null, win.body(), "last");
+
+ xhr.get({url: "showMessage.html",
+ sync: true,
+ load: showMessage.loadViewMessage
+ });
+
+ return showMessage;
+ });
diff --git a/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/treeView.js b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/treeView.js
new file mode 100644
index 0000000000..b1d4abf8c1
--- /dev/null
+++ b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/treeView.js
@@ -0,0 +1,313 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+define(["dojo/_base/xhr",
+ "dojo/query",
+ "dojo/io-query",
+ "dijit/Tree",
+ "qpid/common/util",
+ "qpid/common/updater",
+ "qpid/management/controller",
+ "dojo/domReady!"],
+ function (xhr, query, ioQuery, Tree, util, updater, controller) {
+
+ function TreeViewModel(queryString) {
+ this.query = queryString;
+
+ this.onChildrenChange = function (parent, children) {
+ // fired when the set of children for an object change
+ };
+
+ this.onChange = function (object) {
+ // fired when the properties of an object change
+ };
+
+ this.onDelete = function (object) {
+ // fired when an object is deleted
+ };
+
+ }
+
+
+ TreeViewModel.prototype.buildModel = function (data) {
+ this.model = data;
+
+ };
+
+ TreeViewModel.prototype.updateModel = function (data) {
+ var that = this;
+
+ function checkForChanges(oldData, data) {
+ var propName;
+ if (oldData.name != data.name) {
+ that.onChange(data);
+ }
+
+ var childChanges = false;
+ // Iterate over old childTypes, check all are in new
+ for (propName in oldData) {
+ if (oldData.hasOwnProperty(propName)) {
+ var oldChildren = oldData[ propName ];
+ if (util.isArray(oldChildren)) {
+
+ var newChildren = data[ propName ];
+
+ if (!(newChildren && util.isArray(newChildren))) {
+ childChanges = true;
+ } else {
+ var subChanges = false;
+ // iterate over elements in array, make sure in both, in which case recurse
+ for (var i = 0; i < oldChildren.length; i++) {
+ var matched = false;
+ for (var j = 0; j < newChildren.length; j++) {
+ if (oldChildren[i].id == newChildren[j].id) {
+ checkForChanges(oldChildren[i], newChildren[j]);
+ matched = true;
+ break;
+ }
+ }
+ if (!matched) {
+ subChanges = true;
+ }
+ }
+ if (subChanges == true || oldChildren.length != newChildren.length) {
+ that.onChildrenChange({ id:data.id + propName, _dummyChild:propName, data:data },
+ newChildren);
+ }
+ }
+ }
+ }
+ }
+
+ for (propName in data) {
+ if (data.hasOwnProperty(propName)) {
+ var prop = data[ propName ];
+ if (util.isArray(prop)) {
+ if (!(oldData[ propName ] && util.isArray(oldData[propName]))) {
+ childChanges = true;
+ }
+ }
+ }
+ }
+
+ if (childChanges) {
+ var children = [];
+ that.getChildren(data, function (theChildren) {
+ children = theChildren
+ });
+ that.onChildrenChange(data, children);
+ }
+ }
+
+ var oldData = this.model;
+ this.model = data;
+
+ checkForChanges(oldData, data);
+ };
+
+
+ TreeViewModel.prototype.fetchItemByIdentity = function (id) {
+
+ function fetchItem(id, data) {
+ var propName;
+
+ if (data.id == id) {
+ return data;
+ } else if (id.indexOf(data.id) == 0) {
+ return { id:id, _dummyChild:id.substring(id.length), data:data };
+ } else {
+ for (propName in data) {
+ if (data.hasOwnProperty(propName)) {
+ var prop = data[ propName ];
+ if (util.isArray(prop)) {
+ for (var i = 0; i < prop.length; i++) {
+ var theItem = fetchItem(id, prop[i]);
+ if (theItem) {
+ return theItem;
+ }
+ }
+ }
+ }
+ }
+ return null;
+ }
+ }
+
+ return fetchItem(id, this.model);
+ };
+
+ TreeViewModel.prototype.getChildren = function (parentItem, onComplete) {
+
+ if (parentItem) {
+ if (parentItem._dummyChild) {
+ onComplete(parentItem.data[ parentItem._dummyChild ]);
+ } else {
+ var children = [];
+ for (var propName in parentItem) {
+ if (parentItem.hasOwnProperty(propName)) {
+ var prop = parentItem[ propName ];
+
+ if (util.isArray(prop)) {
+ children.push({ id:parentItem.id
+ + propName, _dummyChild:propName, data:parentItem });
+ }
+ }
+ }
+ onComplete(children);
+ }
+ } else {
+ onComplete([]);
+ }
+ };
+
+ TreeViewModel.prototype.getIdentity = function (theItem) {
+ if (theItem) {
+ return theItem.id;
+ }
+
+ };
+
+ TreeViewModel.prototype.getLabel = function (theItem) {
+ if (theItem) {
+ if (theItem._dummyChild) {
+ return theItem._dummyChild;
+ } else {
+ return theItem.name;
+ }
+ } else {
+ return "";
+ }
+ };
+
+ TreeViewModel.prototype.getRoot = function (onItem) {
+ onItem(this.model);
+ };
+
+ TreeViewModel.prototype.mayHaveChildren = function (theItem) {
+ if (theItem) {
+ if (theItem._dummyChild) {
+ return true;
+ } else {
+ for (var propName in theItem) {
+ if (theItem.hasOwnProperty(propName)) {
+ var prop = theItem[ propName ];
+ if (util.isArray(prop)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+ } else {
+ return false;
+ }
+ };
+
+ TreeViewModel.prototype.relocate = function (theItem) {
+
+ function findItemDetails(theItem, details, type, object) {
+ if (theItem.id == object.id) {
+ details.type = type;
+ details[ type ] = object.name;
+ } else {
+ details[ type ] = object.name;
+
+ // iterate over children
+ for (var propName in object) {
+ if (object.hasOwnProperty(propName)) {
+ var prop = object[ propName ];
+ if (util.isArray(prop)) {
+ for (var i = 0; i < prop.length; i++) {
+ findItemDetails(theItem, details, propName.substring(0, propName.length - 1),
+ prop[i]);
+
+ if (details.type) {
+ break;
+ }
+ }
+ }
+ if (details.type) {
+ break;
+ }
+ }
+ }
+
+ if (!details.type) {
+ details[ type ] = null;
+ }
+ }
+ }
+
+ var details = new Object();
+
+ findItemDetails(theItem, details, "broker", this.model);
+
+ if (details.type == "broker") {
+ controller.show("broker", "");
+ } else if (details.type == "virtualhost") {
+ controller.show("virtualhost", details.virtualhost, {type:"broker", name:""});
+ } else if (details.type == "exchange") {
+ controller.show("exchange", details.exchange, { type: "virtualhost", name: details.virtualhost, parent: {broker: {type:"broker", name:""}}});
+ } else if (details.type == "queue") {
+ controller.show("queue", details.queue, { type: "virtualhost", name: details.virtualhost, parent: {broker: {type:"broker", name:""}}});
+ } else if (details.type == "connection") {
+ controller.show("connection", details.connection, { type: "virtualhost", name: details.virtualhost, parent: {broker: {type:"broker", name:""}}});
+ } else if (details.type == 'port') {
+ controller.show("port", details.port, { type: "virtualhost", name: details.virtualhost, parent: {broker: {type:"broker", name:""}}});
+ } else if (details.type == 'authenticationprovider') {
+ controller.show("authenticationprovider", details.authenticationprovider, {broker: {type:"broker", name:""}});
+ }
+
+
+
+ };
+
+ TreeViewModel.prototype.update = function () {
+ var thisObj = this;
+
+ xhr.get({url:this.query, sync: true, handleAs:"json"})
+ .then(function (data) {
+ if (thisObj.model) {
+ thisObj.updateModel(data);
+ }
+ else {
+ thisObj.buildModel(data);
+ }
+ });
+
+ };
+
+ query('div[qpid-type="treeView"]').forEach(function(node, index, arr) {
+ var treeModel = new TreeViewModel("rest/structure");
+ treeModel.update();
+ var tree = new Tree({ model: treeModel }, node);
+ tree.on("dblclick",
+ function (object) {
+ if (object && !object._dummyChild) {
+ treeModel.relocate(object);
+ }
+
+ }, true);
+ tree.startup();
+ updater.add( treeModel );
+ });
+
+ return TreeViewModel;
+ }); \ No newline at end of file
diff --git a/java/broker-plugins/management-http/src/main/java/resources/management.html b/java/broker-plugins/management-http/src/main/java/resources/management.html
new file mode 100644
index 0000000000..a8345a8503
--- /dev/null
+++ b/java/broker-plugins/management-http/src/main/java/resources/management.html
@@ -0,0 +1,92 @@
+<!DOCTYPE HTML>
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one or more
+ ~ contributor license agreements. See the NOTICE file distributed with
+ ~ this work for additional information regarding copyright ownership.
+ ~ The ASF licenses this file to You under the Apache License, Version 2.0
+ ~ (the "License"); you may not use this file except in compliance with
+ ~ the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT 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 lang="en">
+<head>
+ <meta charset="utf-8">
+ <title>Qpid Management</title>
+ <link rel="stylesheet" href="dojo/dojo/resources/dojo.css">
+ <link rel="stylesheet" href="dojo/dijit/themes/claro/claro.css">
+ <link rel="stylesheet" href="dojo/dojox/grid/resources/claroGrid.css">
+ <link rel="stylesheet" href="dojo/dojox/grid/enhanced/resources/claro/EnhancedGrid.css">
+ <link rel="stylesheet" href="dojo/dojox/grid/enhanced/resources/EnhancedGrid_rtl.css">
+ <link rel="stylesheet" href="css/common.css" media="screen">
+ <script>
+ function getContextPath()
+ {
+ var contextPath = "/";
+ var documentURL = document.URL;
+ var managementPageStart = documentURL.lastIndexOf("/");
+ var firstSlashPos = documentURL.indexOf("/", documentURL.indexOf("//") + 2);
+ if (managementPageStart > firstSlashPos)
+ {
+ contextPath = documentURL.substring(firstSlashPos, managementPageStart);
+ }
+ return contextPath;
+ }
+
+ var dojoConfig = {
+ tlmSiblingOfDojo:false,
+ parseOnLoad:true,
+ async:true,
+ baseUrl: getContextPath(),
+ packages:[
+ { name:"dojo", location:"dojo/dojo" },
+ { name:"dijit", location:"dojo/dijit" },
+ { name:"dojox", location:"dojo/dojox" },
+ { name:"qpid", location:"js/qpid" }
+ ]
+ };
+
+ </script>
+ <script src="dojo/dojo/dojo.js">
+ </script>
+
+ <script>
+ require(["dijit/layout/BorderContainer",
+ "dijit/layout/TabContainer",
+ "dijit/layout/ContentPane",
+ "dijit/TitlePane",
+ "dojo/parser",
+ "qpid/management/treeView",
+ "qpid/management/controller",
+ "qpid/common/footer",
+ "qpid/authorization/sasl"]);
+ </script>
+
+</head>
+<body class="claro">
+
+<div id="pageLayout" data-dojo-type="dijit.layout.BorderContainer" data-dojo-props="design: 'headline', gutters: false">
+ <div data-dojo-type="dijit.layout.ContentPane" data-dojo-props="region:'top'">
+ <div id="header" class="header"></div>
+ </div>
+ <div data-dojo-type="dijit.layout.ContentPane" data-dojo-props="region:'top'">
+ <div id="login"></div>
+ </div>
+ <div data-dojo-type="dijit.layout.ContentPane" data-dojo-props="region:'leading', splitter: true">
+ <div qpid-type="treeView" qpid-props="query: 'rest/structure'" ></div>
+ </div>
+ <div id="managedViews" data-dojo-type="dijit.layout.TabContainer" data-dojo-props="region:'center', tabPosition: 'top'">
+ </div>
+ <div data-dojo-type="dijit.layout.ContentPane" data-dojo-props="region:'bottom'">
+ <div qpid-type="footer"></div>
+ </div>
+</div>
+
+</body>
+</html> \ No newline at end of file
diff --git a/java/broker-plugins/management-http/src/main/java/resources/moveCopyMessages.html b/java/broker-plugins/management-http/src/main/java/resources/moveCopyMessages.html
new file mode 100644
index 0000000000..f188c3001c
--- /dev/null
+++ b/java/broker-plugins/management-http/src/main/java/resources/moveCopyMessages.html
@@ -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 class="dijitHidden">
+ <div data-dojo-type="dijit.Dialog" style="width:600px;" data-dojo-props="title:'Move/Copy Messages'" id="moveMessages">
+ <form id="formMoveMessages" method="post" dojoType="dijit.form.Form">
+ <table cellpadding="0" cellspacing="2">
+ <tr>
+ <td valign="top"><strong>Queue: </strong></td>
+ <td><div id="moveMessages.selectQueueDiv"></div></td>
+ </tr>
+ </table>
+ <br/>
+
+ <!-- submit buttons -->
+
+ <input type="button" value="Cancel" label="Cancel" dojoType="dijit.form.Button" class="moveMessageCancel"/>
+ <input type="submit" value="Move Messages" label="Move Messages" dojoType="dijit.form.Button" />
+
+ </form>
+ </div>
+</div>
diff --git a/java/broker-plugins/management-http/src/main/java/resources/showAuthProvider.html b/java/broker-plugins/management-http/src/main/java/resources/showAuthProvider.html
new file mode 100644
index 0000000000..c5d4e48a75
--- /dev/null
+++ b/java/broker-plugins/management-http/src/main/java/resources/showAuthProvider.html
@@ -0,0 +1,25 @@
+<!--
+ -
+ - Licensed to the Apache Software Foundation (ASF) under one
+ - or more contributor license agreements. See the NOTICE file
+ - distributed with this work for additional information
+ - regarding copyright ownership. The ASF licenses this file
+ - to you under the Apache License, Version 2.0 (the
+ - "License"); you may not use this file except in compliance
+ - with the License. You may obtain a copy of the License at
+ -
+ - http://www.apache.org/licenses/LICENSE-2.0
+ -
+ - Unless required by applicable law or agreed to in writing,
+ - software distributed under the License is distributed on an
+ - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ - KIND, either express or implied. See the License for the
+ - specific language governing permissions and limitations
+ - under the License.
+ -
+ -->
+<div class="authorizationProvider">
+ <span style="">Name:</span><span class="name" style="position:absolute; left:6em"></span>
+ <br/>
+ <span style="">Type:</span><span class="type" style="position:absolute; left:6em"></span>
+</div> \ No newline at end of file
diff --git a/java/broker-plugins/management-http/src/main/java/resources/showBroker.html b/java/broker-plugins/management-http/src/main/java/resources/showBroker.html
new file mode 100644
index 0000000000..a39e334c40
--- /dev/null
+++ b/java/broker-plugins/management-http/src/main/java/resources/showBroker.html
@@ -0,0 +1,25 @@
+<div class="broker">
+ <span>Name:</span><span class="broker-name" style="position:absolute; left:6em"></span>
+ <br/>
+<!-- <span>State:</span><span class="broker-state" style="position:absolute; left:6em"></span>
+ <br/>
+ <span>Durable:</span><span class="broker-durable" style="position:absolute; left:6em"></span>
+ <br/>
+ <span>Lifespan:</span><span class="broker-lifetimePolicy" style="position:absolute; left:6em" ></span>
+ <br/> -->
+ <br/>
+ <div data-dojo-type="dijit.TitlePane" data-dojo-props="title: 'Virtual Hosts'">
+ <div class="broker-virtualhosts"></div>
+ </div>
+ <br/>
+ <div data-dojo-type="dijit.TitlePane" data-dojo-props="title: 'Ports'">
+ <div class="broker-ports"></div>
+ </div>
+ <br/>
+
+ <div data-dojo-type="dijit.TitlePane" data-dojo-props="title: 'Log File', open: false">
+ <div class="broker-logfile"></div>
+ </div>
+ <br/>
+</div>
+
diff --git a/java/broker-plugins/management-http/src/main/java/resources/showConnection.html b/java/broker-plugins/management-http/src/main/java/resources/showConnection.html
new file mode 100644
index 0000000000..84854daf47
--- /dev/null
+++ b/java/broker-plugins/management-http/src/main/java/resources/showConnection.html
@@ -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.
+ -
+ -->
+<div class="connection">
+ <span style="">Name:</span><span class="name" style="position:absolute; left:6em"></span>
+ <br/>
+ <span style="">State:</span><span class="state" style="position:absolute; left:6em"></span>
+ <span style="position:absolute; left:26em">Pre-fetched:</span>
+ <br/>
+ <span style="">Durable:</span><span class="durable" style="position:absolute; left:6em"></span>
+ <span style="position:absolute; left:26em">Inbound:</span>
+ <span class="msgInRate" style="position:absolute; right:9.5em"></span>
+ <span style="position:absolute; right: 5em; width: 4em"> msg/s</span>
+ <span class="bytesInRate" style="position:absolute; right: 3.3em"></span>
+ <span class="bytesInRateUnits" style="position:absolute; right: 0em; width: 3em"></span>
+ <br/>
+ <span style="">Lifespan:</span><span style="position:absolute; left:6em" class="lifetimePolicy"></span>
+ <span style="position:absolute; left:26em">Outbound:</span>
+ <span class="msgOutRate" style="position:absolute; right:9.5em"></span>
+ <span style="position:absolute; right: 5em; width: 4em"> msg/s</span>
+ <span class="bytesOutRate" style="position:absolute; right: 3.3em"></span>
+ <span class="bytesOutRateUnits" style="position:absolute; right: 0em; width: 3em"></span>
+ <br/>
+ <br/>
+ <div data-dojo-type="dijit.TitlePane" data-dojo-props="title: 'Sessions'">
+ <div class="sessions"></div>
+ </div>
+ <br/>
+
+</div>
diff --git a/java/broker-plugins/management-http/src/main/java/resources/showExchange.html b/java/broker-plugins/management-http/src/main/java/resources/showExchange.html
new file mode 100644
index 0000000000..f33b029026
--- /dev/null
+++ b/java/broker-plugins/management-http/src/main/java/resources/showExchange.html
@@ -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.
+ -
+ -->
+<div class="exchange">
+ <span style="">Name:</span><span class="name" style="position:absolute; left:6em"></span>
+ <br/>
+ <span style="">State:</span><span class="state" style="position:absolute; left:6em"></span>
+ <br/>
+ <span style="">Durable:</span><span class="durable" style="position:absolute; left:6em"></span>
+ <span style="position:absolute; left:26em">Inbound:</span>
+ <span class="msgInRate" style="position:absolute; right:9.5em"></span>
+ <span style="position:absolute; right: 5em; width: 4em"> msg/s</span>
+ <span class="bytesInRate" style="position:absolute; right: 3.3em"></span>
+ <span class="bytesInRateUnits" style="position:absolute; right: 0em; width: 3em"></span>
+ <br/>
+ <span style="">Lifespan:</span><span style="position:absolute; left:6em" class="lifetimePolicy"></span>
+ <span style="position:absolute; left:26em">Dropped:</span>
+ <span class="msgDropRate" style="position:absolute; right:9.5em"></span>
+ <span style="position:absolute; right: 5em; width: 4em"> msg/s</span>
+ <span class="bytesDropRate" style="position:absolute; right: 3.3em"></span>
+ <span class="bytesDropRateUnits" style="position:absolute; right: 0em; width: 3em"></span>
+ <br/>
+ <br/>
+ <div data-dojo-type="dijit.TitlePane" data-dojo-props="title: 'Bindings'">
+ <div class="bindings"></div>
+ <button data-dojo-type="dijit.form.Button" class="addBindingButton">Add Binding</button>
+ <button data-dojo-type="dijit.form.Button" class="deleteBindingButton">Delete Binding</button>
+ </div>
+ <br/>
+ <div class="dijitDialogPaneActionBar">
+ <button data-dojo-type="dijit.form.Button" class="deleteExchangeButton" type="button">Delete Exchange</button>
+ </div>
+</div>
diff --git a/java/broker-plugins/management-http/src/main/java/resources/showMessage.html b/java/broker-plugins/management-http/src/main/java/resources/showMessage.html
new file mode 100644
index 0000000000..0dea508c60
--- /dev/null
+++ b/java/broker-plugins/management-http/src/main/java/resources/showMessage.html
@@ -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.
+ -->
+
+<div class="dijitHidden">
+ <div data-dojo-type="dijit.Dialog" style="width:600px;" data-dojo-props="title:'View Message'" id="showMessage">
+
+ <table style="border: 0;">
+ <tr style="margin-bottom: 4pt">
+ <td style="width: 10em; vertical-align: top"><span style="font-weight: bold;">Message Number:</span></td>
+ <td><span class="message-id"></span></td>
+ </tr>
+ <tr style="margin-bottom: 4pt">
+ <td style="width: 10em; vertical-align: top"><span style="font-weight: bold;">Message Id:</span></td>
+ <td><span class="message-messageId"></span></td>
+ </tr>
+ <tr style="margin-bottom: 4pt">
+ <td style="width: 10em; vertical-align: top"><span style="font-weight: bold;">State:</span></td>
+ <td><span class="message-state"></span></td>
+ </tr>
+ <tr style="margin-bottom: 4pt">
+ <td style="width: 10em; vertical-align: top"><span style="font-weight: bold;">Persistent:</span></td>
+ <td><span class="message-persistent boolean"></span></td>
+ </tr>
+ <tr style="margin-bottom: 4pt">
+ <td style="width: 10em; vertical-align: top"><span style="font-weight: bold;">Priority:</span></td>
+ <td><span class="message-priority"></span></td>
+ </tr>
+ <tr style="margin-bottom: 4pt">
+ <td style="width: 10em; vertical-align: top"><span style="font-weight: bold;">Arrival Time:</span>
+ </td><td><span class="message-arrivalTime datetime"></span></td>
+ </tr>
+ <tr style="margin-bottom: 4pt">
+ <td style="width: 10em; vertical-align: top"><span style="font-weight: bold;">Expiration:</span></td>
+ <td><span class="message-expiration datetime"></span></td>
+ </tr>
+ <tr style="margin-bottom: 4pt">
+ <td style="width: 10em; vertical-align: top"><span style="font-weight: bold;">MIME Type:</span></td>
+ <td><span class="message-mimeType"></span></td>
+ </tr>
+ <tr style="margin-bottom: 4pt">
+ <td style="width: 10em; vertical-align: top"><span style="font-weight: bold;">User:</span></td>
+ <td><span class="message-userId"></span></td>
+ </tr>
+ <tr style="margin-bottom: 4pt">
+ <td style="width: 10em; vertical-align: top"><span style="font-weight: bold;">Headers:</span></td>
+ <td><div class="message-headers map"></div></td>
+ </tr>
+
+ <tr style="margin-bottom: 4pt">
+ <td style="width: 10em; vertical-align: top"><span style="font-weight: bold;">Content:</span></td>
+ <td><div class="message-content"></div></td>
+ </tr>
+ </table>
+ <br/>
+ <input type="button" value="Close" label="Close" dojoType="dijit.form.Button" class="closeViewMessage"/>
+
+ </div>
+</div>
+
diff --git a/java/broker-plugins/management-http/src/main/java/resources/showQueue.html b/java/broker-plugins/management-http/src/main/java/resources/showQueue.html
new file mode 100644
index 0000000000..929e1d1f23
--- /dev/null
+++ b/java/broker-plugins/management-http/src/main/java/resources/showQueue.html
@@ -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.
+ -
+ -->
+<div class="queue">
+ <span style="">Name:</span><span class="name" style="position:absolute; left:6em"></span>
+ <span style="position:absolute; left:26em">Size:</span>
+ <span class="queueDepthMessages" style="position:absolute; right:9.5em"></span>
+ <span style="position:absolute; right: 5em; width: 4em"> msgs</span>
+ <span class="queueDepthBytes" style="position:absolute; right: 3.3em">(</span>
+ <span class="queueDepthBytesUnits" style="position:absolute; right: 0em; width: 3em">)</span>
+ <br/>
+ <span style="">State:</span><span class="state" style="position:absolute; left:6em"></span>
+ <span style="position:absolute; left:26em">Pre-fetched:</span>
+ <span class="unacknowledgedMessages" style="position:absolute; right:9.5em"></span>
+ <span style="position:absolute; right: 5em; width: 4em"> msgs</span>
+ <span class="unacknowledgedBytes" style="position:absolute; right: 3.3em"></span>
+ <span class="unacknowledgedBytesUnits" style="position:absolute; right: 0em; width: 3em"></span>
+ <br/>
+ <span style="">Durable:</span><span class="durable" style="position:absolute; left:6em"></span>
+ <span style="position:absolute; left:26em">Inbound:</span>
+ <span class="msgInRate" style="position:absolute; right:9.5em"></span>
+ <span style="position:absolute; right: 5em; width: 4em"> msg/s</span>
+ <span class="bytesInRate" style="position:absolute; right: 3.3em"></span>
+ <span class="bytesInRateUnits" style="position:absolute; right: 0em; width: 3em"></span>
+ <br/>
+ <span style="">Lifespan:</span><span style="position:absolute; left:6em" class="lifetimePolicy"></span>
+ <span style="position:absolute; left:26em">Outbound:</span>
+ <span class="msgOutRate" style="position:absolute; right:9.5em"></span>
+ <span style="position:absolute; right: 5em; width: 4em"> msg/s</span>
+ <span class="bytesOutRate" style="position:absolute; right: 3.3em"></span>
+ <span class="bytesOutRateUnits" style="position:absolute; right: 0em; width: 3em"></span>
+ <br/>
+ <span style="">AlternateExchange:</span><span class="alternateExchange" style="position:absolute; left:10em"></span>
+ <span style="position:absolute; left:26em">Type:</span><span style="position:absolute; left:29em" class="type"></span>
+ <span style="position:absolute; right:1em" class="typeQualifier"></span>
+ <br/>
+ <br/>
+ <div data-dojo-type="dijit.TitlePane" data-dojo-props="title: 'Bindings'">
+ <div class="bindings"></div>
+ <button data-dojo-type="dijit.form.Button" class="addBindingButton" type="button">Add Binding</button>
+ </div>
+ <br/>
+ <div data-dojo-type="dijit.TitlePane" data-dojo-props="title: 'Consumers'">
+ <div class="consumers"></div>
+ </div>
+ <br/>
+ <div data-dojo-type="dijit.TitlePane" data-dojo-props="title: 'Messages'">
+ <div class="messages"></div>
+ <button data-dojo-type="dijit.form.Button" class="deleteMessagesButton" type="button">Delete Messages</button>
+ <button data-dojo-type="dijit.form.Button" class="moveMessagesButton" type="button">Move Messages</button>
+ <button data-dojo-type="dijit.form.Button" class="copyMessagesButton" type="button">Copy Messages</button>
+ </div>
+ <br/>
+ <div data-dojo-type="dijit.TitlePane" data-dojo-props="title: 'Alerting Thresholds', open: false">
+ <span style="">Queue Depth:</span>
+ <span class="alertThresholdQueueDepthMessages"
+ style="position:absolute; left:4em; width:8em; text-align:right"></span>
+ <span style="position:absolute; left:12.2em">msgs</span>
+
+ <span style="position:absolute; left:21em">Queue Depth:</span>
+ <span class="alertThresholdQueueDepthBytes"
+ style="position:absolute; left:22em; width:8em; text-align:right"></span>
+ <span class="alertThresholdQueueDepthBytesUnits" style="position:absolute; left:30.2em"></span>
+ <br>
+ <span style="">Message Age:</span>
+ <span class="alertThresholdMessageAge"
+ style="position:absolute; left:4em; width:8em; text-align:right"></span>
+ <span class="alertThresholdMessageAgeUnits" style="position:absolute; left:12.2em"></span>
+
+ <span style="position:absolute; left:21em">Message Size: </span>
+ <span class="alertThresholdMessageSize"
+ style="position:absolute; left:25em; width:5em; text-align:right"></span>
+ <span class="alertThresholdMessageSizeUnits" style="position:absolute; left:30.2em"></span>
+ <br/>
+ <br/>
+ <span style="">Alert frequency:</span>
+ <span class="alertRepeatGap"
+ style="position:absolute; left:4em; width:8em; text-align:right"></span>
+ <span class="alertRepeatGapUnits" style="position:absolute; left:12.2em"></span>
+ </div>
+
+ <div class="dijitDialogPaneActionBar">
+ <button data-dojo-type="dijit.form.Button" class="deleteQueueButton" type="button">Delete Queue</button>
+ </div>
+</div>
+
diff --git a/java/broker-plugins/management-http/src/main/java/resources/showVirtualHost.html b/java/broker-plugins/management-http/src/main/java/resources/showVirtualHost.html
new file mode 100644
index 0000000000..73c912e0d4
--- /dev/null
+++ b/java/broker-plugins/management-http/src/main/java/resources/showVirtualHost.html
@@ -0,0 +1,87 @@
+<!DOCTYPE HTML>
+<!--
+ -
+ - Licensed to the Apache Software Foundation (ASF) under one
+ - or more contributor license agreements. See the NOTICE file
+ - distributed with this work for additional information
+ - regarding copyright ownership. The ASF licenses this file
+ - to you under the Apache License, Version 2.0 (the
+ - "License"); you may not use this file except in compliance
+ - with the License. You may obtain a copy of the License at
+ -
+ - http://www.apache.org/licenses/LICENSE-2.0
+ -
+ - Unless required by applicable law or agreed to in writing,
+ - software distributed under the License is distributed on an
+ - "AS IS" BASIS, WITHOUT 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="virtualhost">
+ <span style="">Name:</span><span class="name" style="position:absolute; left:6em"></span>
+ <br/>
+ <span style="">State:</span><span class="state" style="position:absolute; left:6em"></span>
+ <br/>
+ <span style="">Durable:</span><span class="durable" style="position:absolute; left:6em"></span>
+ <span style="position:absolute; left:26em">Inbound:</span>
+ <span class="msgInRate" style="position:absolute; right:9.5em"></span>
+ <span style="position:absolute; right: 5em; width: 4em"> msg/s</span>
+ <span class="bytesInRate" style="position:absolute; right: 3.3em"></span>
+ <span class="bytesInRateUnits" style="position:absolute; right: 0em; width: 3em"></span>
+ <br/>
+ <span style="">Lifespan:</span><span style="position:absolute; left:6em" class="lifetimePolicy"></span>
+ <span style="position:absolute; left:26em">Outbound:</span>
+ <span class="msgOutRate" style="position:absolute; right:9.5em"></span>
+ <span style="position:absolute; right: 5em; width: 4em"> msg/s</span>
+ <span class="bytesOutRate" style="position:absolute; right: 3.3em"></span>
+ <span class="bytesOutRateUnits" style="position:absolute; right: 0em; width: 3em"></span>
+ <br/>
+ <br/>
+ <div data-dojo-type="dijit.TitlePane" data-dojo-props="title: 'Exchanges'">
+ <div class="exchanges"></div>
+ <button data-dojo-type="dijit.form.Button" class="addExchangeButton">Add Exchange</button>
+ <button data-dojo-type="dijit.form.Button" class="deleteExchangeButton">Delete Exchange</button>
+ </div>
+ <br/>
+ <div data-dojo-type="dijit.TitlePane" data-dojo-props="title: 'Queues'">
+ <div class="queues"></div>
+ <button data-dojo-type="dijit.form.Button" class="addQueueButton">Add Queue</button>
+ <button data-dojo-type="dijit.form.Button" class="deleteQueueButton">Delete Queue</button>
+ </div>
+ <br/>
+ <div data-dojo-type="dijit.TitlePane" data-dojo-props="title: 'Connections'">
+ <div class="connections"></div>
+ </div>
+ <br/>
+ <div data-dojo-type="dijit.TitlePane" data-dojo-props="title: 'Alerting Thresholds', open: false">
+ <span style="">Queue Depth:</span>
+ <span class="alertThresholdQueueDepthMessages"
+ style="position:absolute; left:4em; width:8em; text-align:right"></span>
+ <span style="position:absolute; left:12.2em">msgs</span>
+
+ <span style="position:absolute; left:21em">Queue Depth:</span>
+ <span class="alertThresholdQueueDepthBytes"
+ style="position:absolute; left:22em; width:8em; text-align:right"></span>
+ <span class="alertThresholdQueueDepthBytesUnits" style="position:absolute; left:30.2em"></span>
+ <br>
+ <span style="">Message Age:</span>
+ <span class="alertThresholdMessageAge"
+ style="position:absolute; left:4em; width:8em; text-align:right"></span>
+ <span class="alertThresholdMessageAgeUnits" style="position:absolute; left:12.2em"></span>
+
+ <span style="position:absolute; left:21em">Message Size: </span>
+ <span class="alertThresholdMessageSize"
+ style="position:absolute; left:25em; width:5em; text-align:right"></span>
+ <span class="alertThresholdMessageSizeUnits" style="position:absolute; left:30.2em"></span>
+ <br/>
+ <br/>
+ <span style="">Alert frequency:</span>
+ <span class="alertRepeatGap"
+ style="position:absolute; left:4em; width:8em; text-align:right"></span>
+ <span class="alertRepeatGapUnits" style="position:absolute; left:12.2em"></span>
+ </div>
+</div>
+
diff --git a/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/Asserts.java b/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/Asserts.java
new file mode 100644
index 0000000000..2595007574
--- /dev/null
+++ b/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/Asserts.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.server.management.plugin.servlet.rest;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertNotNull;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Map;
+
+import javax.jms.JMSException;
+
+import org.apache.qpid.client.AMQConnection;
+import org.apache.qpid.server.model.Binding;
+import org.apache.qpid.server.model.Broker;
+import org.apache.qpid.server.model.Connection;
+import org.apache.qpid.server.model.Exchange;
+import org.apache.qpid.server.model.LifetimePolicy;
+import org.apache.qpid.server.model.Port;
+import org.apache.qpid.server.model.Queue;
+import org.apache.qpid.server.model.State;
+import org.apache.qpid.server.model.VirtualHost;
+
+public class Asserts
+{
+ public static final String STATISTICS_ATTRIBUTE = "statistics";
+
+ public static void assertVirtualHost(String virtualHostName, Map<String, Object> virtualHost)
+ {
+ assertNotNull("Virtualhost " + virtualHostName + " data are not found", virtualHost);
+ assertAttributesPresent(virtualHost, VirtualHost.AVAILABLE_ATTRIBUTES, VirtualHost.TIME_TO_LIVE,
+ VirtualHost.CREATED, VirtualHost.UPDATED, VirtualHost.SUPPORTED_QUEUE_TYPES, VirtualHost.STORE_CONFIGURATION);
+
+ assertEquals("Unexpected value of attribute " + VirtualHost.NAME, virtualHostName, virtualHost.get(VirtualHost.NAME));
+ assertNotNull("Unexpected value of attribute " + VirtualHost.ID, virtualHost.get(VirtualHost.ID));
+ assertEquals("Unexpected value of attribute " + VirtualHost.STATE, State.ACTIVE.name(),
+ virtualHost.get(VirtualHost.STATE));
+ assertEquals("Unexpected value of attribute " + VirtualHost.DURABLE, Boolean.TRUE,
+ virtualHost.get(VirtualHost.DURABLE));
+ assertEquals("Unexpected value of attribute " + VirtualHost.LIFETIME_POLICY, LifetimePolicy.PERMANENT.name(),
+ virtualHost.get(VirtualHost.LIFETIME_POLICY));
+ assertEquals("Unexpected value of attribute " + VirtualHost.DEAD_LETTER_QUEUE_ENABLED, Boolean.FALSE,
+ virtualHost.get(VirtualHost.DEAD_LETTER_QUEUE_ENABLED));
+
+ @SuppressWarnings("unchecked")
+ Collection<String> exchangeTypes = (Collection<String>) virtualHost.get(VirtualHost.SUPPORTED_EXCHANGE_TYPES);
+ assertEquals("Unexpected value of attribute " + VirtualHost.SUPPORTED_EXCHANGE_TYPES,
+ new HashSet<String>(Arrays.asList("headers", "topic", "direct", "fanout", "management")),
+ new HashSet<String>(exchangeTypes));
+
+ @SuppressWarnings("unchecked")
+ Map<String, Object> statistics = (Map<String, Object>) virtualHost.get(STATISTICS_ATTRIBUTE);
+ Asserts.assertAttributesPresent(statistics, VirtualHost.AVAILABLE_STATISTICS, VirtualHost.BYTES_RETAINED,
+ VirtualHost.LOCAL_TRANSACTION_BEGINS, VirtualHost.LOCAL_TRANSACTION_ROLLBACKS,
+ VirtualHost.MESSAGES_RETAINED, VirtualHost.STATE_CHANGED, VirtualHost.XA_TRANSACTION_BRANCH_ENDS,
+ VirtualHost.XA_TRANSACTION_BRANCH_STARTS, VirtualHost.XA_TRANSACTION_BRANCH_SUSPENDS);
+
+ }
+
+ public static void assertQueue(String queueName, String queueType, Map<String, Object> queueData)
+ {
+ assertQueue(queueName, queueType, queueData, null);
+ }
+
+ public static void assertQueue(String queueName, String queueType, Map<String, Object> queueData, Map<String, Object> expectedAttributes)
+ {
+ assertNotNull("Queue " + queueName + " is not found!", queueData);
+ Asserts.assertAttributesPresent(queueData, Queue.AVAILABLE_ATTRIBUTES, Queue.CREATED, Queue.UPDATED,
+ Queue.DESCRIPTION, Queue.TIME_TO_LIVE, Queue.ALTERNATE_EXCHANGE, Queue.OWNER, Queue.NO_LOCAL, Queue.LVQ_KEY,
+ Queue.SORT_KEY, Queue.MESSAGE_GROUP_KEY, Queue.MESSAGE_GROUP_DEFAULT_GROUP,
+ Queue.MESSAGE_GROUP_SHARED_GROUPS, Queue.PRIORITIES);
+
+ assertEquals("Unexpected value of queue attribute " + Queue.NAME, queueName, queueData.get(Queue.NAME));
+ assertNotNull("Unexpected value of queue attribute " + Queue.ID, queueData.get(Queue.ID));
+ assertEquals("Unexpected value of queue attribute " + Queue.STATE, State.ACTIVE.name(), queueData.get(Queue.STATE));
+ assertEquals("Unexpected value of queue attribute " + Queue.LIFETIME_POLICY, LifetimePolicy.PERMANENT.name(),
+ queueData.get(Queue.LIFETIME_POLICY));
+ assertEquals("Unexpected value of queue attribute " + Queue.TYPE, queueType, queueData.get(Queue.TYPE));
+ if (expectedAttributes == null)
+ {
+ assertEquals("Unexpected value of queue attribute " + Queue.EXCLUSIVE, Boolean.FALSE, queueData.get(Queue.EXCLUSIVE));
+ assertEquals("Unexpected value of queue attribute " + Queue.MAXIMUM_DELIVERY_ATTEMPTS, 0,
+ queueData.get(Queue.MAXIMUM_DELIVERY_ATTEMPTS));
+ assertEquals("Unexpected value of queue attribute " + Queue.QUEUE_FLOW_CONTROL_SIZE_BYTES, 0,
+ queueData.get(Queue.QUEUE_FLOW_CONTROL_SIZE_BYTES));
+ assertEquals("Unexpected value of queue attribute " + Queue.QUEUE_FLOW_RESUME_SIZE_BYTES, 0,
+ queueData.get(Queue.QUEUE_FLOW_RESUME_SIZE_BYTES));
+ assertEquals("Unexpected value of queue attribute " + Queue.QUEUE_FLOW_STOPPED, Boolean.FALSE,
+ queueData.get(Queue.QUEUE_FLOW_STOPPED));
+ }
+ else
+ {
+ for (Map.Entry<String, Object> attribute : expectedAttributes.entrySet())
+ {
+ assertEquals("Unexpected value of " + queueName + " queue attribute " + attribute.getKey(),
+ attribute.getValue(), queueData.get(attribute.getKey()));
+ }
+ }
+
+ assertNotNull("Unexpected value of queue attribute statistics", queueData.get(Asserts.STATISTICS_ATTRIBUTE));
+ @SuppressWarnings("unchecked")
+ Map<String, Object> statistics = (Map<String, Object>) queueData.get(Asserts.STATISTICS_ATTRIBUTE);
+ Asserts.assertAttributesPresent(statistics, Queue.AVAILABLE_STATISTICS, Queue.DISCARDS_TTL_BYTES,
+ Queue.DISCARDS_TTL_MESSAGES, Queue.STATE_CHANGED);
+ }
+
+ public static void assertAttributesPresent(Map<String, Object> data, String[] attributes)
+ {
+ for (String name : attributes)
+ {
+ assertNotNull("Attribute " + name + " is not present", data.get(name));
+ }
+ }
+
+ public static void assertAttributesPresent(Map<String, Object> data, Collection<String> attributes,
+ String... unsupportedAttributes)
+ {
+ for (String name : attributes)
+ {
+ boolean unsupported = false;
+ for (String unsupportedAttribute : unsupportedAttributes)
+ {
+ if (unsupportedAttribute.equals(name))
+ {
+ unsupported = true;
+ break;
+ }
+ }
+ if (unsupported)
+ {
+ continue;
+ }
+ assertNotNull("Attribute " + name + " is not present", data.get(name));
+ }
+ }
+
+ public static void assertConnection(Map<String, Object> connectionData, AMQConnection connection) throws JMSException
+ {
+ assertNotNull("Unexpected connection data", connectionData);
+ assertAttributesPresent(connectionData, Connection.AVAILABLE_ATTRIBUTES, Connection.STATE, Connection.DURABLE,
+ Connection.LIFETIME_POLICY, Connection.TIME_TO_LIVE, Connection.CREATED, Connection.UPDATED,
+ Connection.INCOMING, Connection.REMOTE_PROCESS_NAME, Connection.REMOTE_PROCESS_PID,
+ Connection.LOCAL_ADDRESS, Connection.PROPERTIES);
+
+ assertEquals("Unexpected value of connection attribute " + Connection.SESSION_COUNT_LIMIT,
+ (int) connection.getMaximumChannelCount(), connectionData.get(Connection.SESSION_COUNT_LIMIT));
+ assertEquals("Unexpected value of connection attribute " + Connection.CLIENT_ID, "clientid",
+ connectionData.get(Connection.CLIENT_ID));
+ assertEquals("Unexpected value of connection attribute " + Connection.PRINCIPAL, "guest",
+ connectionData.get(Connection.PRINCIPAL));
+
+ @SuppressWarnings("unchecked")
+ Map<String, Object> statistics = (Map<String, Object>) connectionData.get(STATISTICS_ATTRIBUTE);
+ assertAttributesPresent(statistics, Connection.AVAILABLE_STATISTICS, Connection.LOCAL_TRANSACTION_BEGINS,
+ Connection.LOCAL_TRANSACTION_ROLLBACKS, Connection.STATE_CHANGED, Connection.XA_TRANSACTION_BRANCH_ENDS,
+ Connection.XA_TRANSACTION_BRANCH_STARTS, Connection.XA_TRANSACTION_BRANCH_SUSPENDS);
+ assertEquals("Unexpected value of connection statistics attribute " + Connection.SESSION_COUNT, 1,
+ statistics.get(Connection.SESSION_COUNT));
+ }
+
+ public static void assertPortAttributes(Map<String, Object> port)
+ {
+ assertAttributesPresent(port, Port.AVAILABLE_ATTRIBUTES, Port.CREATED, Port.UPDATED);
+
+ assertNotNull("Unexpected value of attribute " + Port.ID, port.get(Port.ID));
+ assertEquals("Unexpected value of attribute " + Port.DURABLE, Boolean.FALSE, port.get(Port.DURABLE));
+ assertEquals("Unexpected value of attribute " + Port.LIFETIME_POLICY, LifetimePolicy.PERMANENT.name(),
+ port.get(Broker.LIFETIME_POLICY));
+ assertEquals("Unexpected value of attribute " + Port.STATE, State.ACTIVE.name(), port.get(Port.STATE));
+ assertEquals("Unexpected value of attribute " + Port.TIME_TO_LIVE, 0, port.get(Port.TIME_TO_LIVE));
+ assertNotNull("Unexpected value of attribute " + Port.BINDING_ADDRESS, port.get(Port.BINDING_ADDRESS));
+ assertNotNull("Unexpected value of attribute " + Port.PROTOCOLS, port.get(Port.PROTOCOLS));
+ assertNotNull("Unexpected value of attribute " + Port.NAME, port.get(Port.NAME));
+
+ @SuppressWarnings("unchecked")
+ Collection<String> transports = (Collection<String>) port.get(Port.TRANSPORTS);
+ assertEquals("Unexpected value of attribute " + Port.TRANSPORTS, new HashSet<String>(Arrays.asList("TCP")),
+ new HashSet<String>(transports));
+ }
+
+ public static void assertDurableExchange(String exchangeName, String type, Map<String, Object> exchangeData)
+ {
+ assertExchange(exchangeName, type, exchangeData);
+
+ assertEquals("Unexpected value of exchange attribute " + Exchange.DURABLE, Boolean.TRUE,
+ exchangeData.get(Exchange.DURABLE));
+ }
+
+ public static void assertExchange(String exchangeName, String type, Map<String, Object> exchangeData)
+ {
+ assertNotNull("Exchange " + exchangeName + " is not found!", exchangeData);
+ assertAttributesPresent(exchangeData, Exchange.AVAILABLE_ATTRIBUTES, Exchange.CREATED, Exchange.UPDATED,
+ Exchange.ALTERNATE_EXCHANGE, Exchange.TIME_TO_LIVE);
+
+ assertEquals("Unexpected value of exchange attribute " + Exchange.NAME, exchangeName,
+ exchangeData.get(Exchange.NAME));
+ assertNotNull("Unexpected value of exchange attribute " + Exchange.ID, exchangeData.get(VirtualHost.ID));
+ assertEquals("Unexpected value of exchange attribute " + Exchange.STATE, State.ACTIVE.name(),
+ exchangeData.get(Exchange.STATE));
+
+ assertEquals("Unexpected value of exchange attribute " + Exchange.LIFETIME_POLICY, LifetimePolicy.PERMANENT.name(),
+ exchangeData.get(Exchange.LIFETIME_POLICY));
+ assertEquals("Unexpected value of exchange attribute " + Exchange.TYPE, type, exchangeData.get(Exchange.TYPE));
+ assertNotNull("Unexpected value of exchange attribute statistics", exchangeData.get(STATISTICS_ATTRIBUTE));
+
+ @SuppressWarnings("unchecked")
+ Map<String, Object> statistics = (Map<String, Object>) exchangeData.get(STATISTICS_ATTRIBUTE);
+ assertAttributesPresent(statistics, Exchange.AVAILABLE_STATISTICS, Exchange.STATE_CHANGED, Exchange.PRODUCER_COUNT);
+ }
+
+ public static void assertBinding(String bindingName, String queueName, String exchange, Map<String, Object> binding)
+ {
+ assertNotNull("Binding map should not be null", binding);
+ assertAttributesPresent(binding, Binding.AVAILABLE_ATTRIBUTES, Binding.STATE, Binding.TIME_TO_LIVE,
+ Binding.CREATED, Binding.UPDATED);
+
+ assertEquals("Unexpected binding attribute " + Binding.NAME, bindingName, binding.get(Binding.NAME));
+ assertEquals("Unexpected binding attribute " + Binding.QUEUE, queueName, binding.get(Binding.QUEUE));
+ assertEquals("Unexpected binding attribute " + Binding.EXCHANGE, exchange, binding.get(Binding.EXCHANGE));
+ assertEquals("Unexpected binding attribute " + Binding.LIFETIME_POLICY, LifetimePolicy.PERMANENT.name(),
+ binding.get(Binding.LIFETIME_POLICY));
+ }
+
+ public static void assertBinding(String queueName, String exchange, Map<String, Object> binding)
+ {
+ assertBinding(queueName, queueName, exchange, binding);
+ }
+
+}
diff --git a/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/AuthenticationProviderRestTest.java b/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/AuthenticationProviderRestTest.java
new file mode 100644
index 0000000000..37bc2733b0
--- /dev/null
+++ b/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/AuthenticationProviderRestTest.java
@@ -0,0 +1,53 @@
+package org.apache.qpid.server.management.plugin.servlet.rest;
+
+import java.util.List;
+import java.util.Map;
+
+import org.apache.qpid.server.model.AuthenticationProvider;
+import org.apache.qpid.server.model.LifetimePolicy;
+import org.apache.qpid.server.model.State;
+import org.apache.qpid.server.model.User;
+
+public class AuthenticationProviderRestTest extends QpidRestTestCase
+{
+
+ public void testGet() throws Exception
+ {
+ List<Map<String, Object>> providerDetails = getJsonAsList("/rest/authenticationprovider");
+ assertNotNull("Providers details cannot be null", providerDetails);
+ assertEquals("Unexpected number of providers", 1, providerDetails.size());
+ for (Map<String, Object> provider : providerDetails)
+ {
+ assertProvider("PrincipalDatabaseAuthenticationManager", provider);
+ Map<String, Object> data = getJsonAsSingletonList("/rest/authenticationprovider/"
+ + provider.get(AuthenticationProvider.NAME));
+ assertNotNull("Cannot load data for " + provider.get(AuthenticationProvider.NAME), data);
+ assertProvider("PrincipalDatabaseAuthenticationManager", data);
+ }
+ }
+
+ private void assertProvider(String type, Map<String, Object> provider)
+ {
+ Asserts.assertAttributesPresent(provider, AuthenticationProvider.AVAILABLE_ATTRIBUTES,
+ AuthenticationProvider.CREATED, AuthenticationProvider.UPDATED, AuthenticationProvider.DESCRIPTION,
+ AuthenticationProvider.TIME_TO_LIVE);
+ assertEquals("Unexpected value of provider attribute " + AuthenticationProvider.STATE, State.ACTIVE.name(),
+ provider.get(AuthenticationProvider.STATE));
+ assertEquals("Unexpected value of provider attribute " + AuthenticationProvider.LIFETIME_POLICY,
+ LifetimePolicy.PERMANENT.name(), provider.get(AuthenticationProvider.LIFETIME_POLICY));
+ assertEquals("Unexpected value of provider attribute " + AuthenticationProvider.DURABLE, Boolean.TRUE,
+ provider.get(AuthenticationProvider.DURABLE));
+ assertEquals("Unexpected value of provider attribute " + AuthenticationProvider.TYPE, type,
+ provider.get(AuthenticationProvider.TYPE));
+
+ @SuppressWarnings("unchecked")
+ List<Map<String, Object>> users = (List<Map<String, Object>>) provider.get("users");
+ assertNotNull("Users are not found", users);
+ assertTrue("Unexpected number of users", users.size() > 1);
+ for (Map<String, Object> user : users)
+ {
+ assertNotNull("Attribute " + User.ID, user.get(User.ID));
+ assertNotNull("Attribute " + User.NAME, user.get(User.NAME));
+ }
+ }
+}
diff --git a/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/BindingRestTest.java b/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/BindingRestTest.java
new file mode 100644
index 0000000000..527eb16927
--- /dev/null
+++ b/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/BindingRestTest.java
@@ -0,0 +1,109 @@
+package org.apache.qpid.server.management.plugin.servlet.rest;
+
+import java.net.HttpURLConnection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.qpid.server.model.Binding;
+
+public class BindingRestTest extends QpidRestTestCase
+{
+
+ public void testGetAllBindings() throws Exception
+ {
+ List<Map<String, Object>> bindings = getJsonAsList("/rest/binding");
+ assertNotNull("Bindings cannot be null", bindings);
+ assertTrue("Unexpected number of bindings", bindings.size() >= EXPECTED_HOSTS.length * EXPECTED_QUEUES.length);
+ for (Map<String, Object> binding : bindings)
+ {
+ Asserts.assertBinding((String) binding.get(Binding.NAME), (String) binding.get(Binding.EXCHANGE), binding);
+ }
+ }
+
+ public void testGetVirtualHostBindings() throws Exception
+ {
+ List<Map<String, Object>> bindings = getJsonAsList("/rest/binding/test");
+ assertNotNull("Bindings cannot be null", bindings);
+ assertEquals("Unexpected number of bindings", EXPECTED_QUEUES.length * 2, bindings.size());
+ for (String queueName : EXPECTED_QUEUES)
+ {
+ Map<String, Object> searchAttributes = new HashMap<String, Object>();
+ searchAttributes.put(Binding.NAME, queueName);
+ searchAttributes.put(Binding.EXCHANGE, "amq.direct");
+
+ Map<String, Object> binding = find(searchAttributes, bindings);
+ Asserts.assertBinding(queueName, "amq.direct", binding);
+
+ searchAttributes.put(Binding.EXCHANGE, "<<default>>");
+
+ binding = find(searchAttributes, bindings);
+ Asserts.assertBinding(queueName, "<<default>>", binding);
+ }
+ }
+
+ public void testGetVirtualHostExchangeBindings() throws Exception
+ {
+ List<Map<String, Object>> bindings = getJsonAsList("/rest/binding/test/amq.direct");
+ assertNotNull("Bindings cannot be null", bindings);
+ assertEquals("Unexpected number of bindings", EXPECTED_QUEUES.length, bindings.size());
+ for (String queueName : EXPECTED_QUEUES)
+ {
+ Map<String, Object> binding = find(Binding.NAME, queueName, bindings);
+ Asserts.assertBinding(queueName, "amq.direct", binding);
+ }
+ }
+
+ public void testGetVirtualHostExchangeQueueBindings() throws Exception
+ {
+ List<Map<String, Object>> bindings = getJsonAsList("/rest/binding/test/amq.direct/queue");
+ assertNotNull("Bindings cannot be null", bindings);
+ assertEquals("Unexpected number of bindings", 1, bindings.size());
+ Asserts.assertBinding("queue", "amq.direct", bindings.get(0));
+ }
+
+
+ public void testDeleteBinding() throws Exception
+ {
+ List<Map<String, Object>> bindings = getJsonAsList("/rest/binding/test/amq.direct/queue/queue");
+ assertEquals("Unexpected number of bindings", 1, bindings.size());
+ Asserts.assertBinding("queue", "amq.direct", bindings.get(0));
+
+ HttpURLConnection connection = openManagementConection("/rest/binding/test/amq.direct/queue/queue", "DELETE");
+ connection.connect();
+ assertEquals("Unexpected response code", 200, connection.getResponseCode());
+
+ bindings = getJsonAsList("/rest/binding/test/amq.direct/queue/queue");
+ assertEquals("Binding should be deleted", 0, bindings.size());
+ }
+
+ public void testDeleteBindingById() throws Exception
+ {
+ Map<String, Object> binding = getJsonAsSingletonList("/rest/binding/test/amq.direct/queue");
+ HttpURLConnection connection = openManagementConection("/rest/binding/test/amq.direct?id=" + binding.get(Binding.ID), "DELETE");
+ connection.connect();
+ assertEquals("Unexpected response code", 200, connection.getResponseCode());
+ List<Map<String, Object>> bindings = getJsonAsList("/rest/binding/test/amq.direct/queue");
+ assertEquals("Binding should be deleted", 0, bindings.size());
+ }
+
+ public void testCreateBinding() throws Exception
+ {
+ String bindingName = getTestName();
+ Map<String, Object> bindingData = new HashMap<String, Object>();
+ bindingData.put(Binding.NAME, bindingName);
+ bindingData.put(Binding.QUEUE, "queue");
+ bindingData.put(Binding.EXCHANGE, "amq.direct");
+
+ HttpURLConnection connection = openManagementConection("/rest/binding/test/amq.direct/queue/" + bindingName, "PUT");
+ connection.connect();
+ writeJsonRequest(connection, bindingData);
+ int responseCode = connection.getResponseCode();
+ connection.disconnect();
+ assertEquals("Unexpected response code", 201, responseCode);
+ Map<String, Object> binding = getJsonAsSingletonList("/rest/binding/test/amq.direct/queue/" + bindingName);
+
+ Asserts.assertBinding(bindingName, "queue", "amq.direct", binding);
+ }
+
+}
diff --git a/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/BrokerRestHttpsTest.java b/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/BrokerRestHttpsTest.java
new file mode 100644
index 0000000000..4bbe9155cd
--- /dev/null
+++ b/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/BrokerRestHttpsTest.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.server.management.plugin.servlet.rest;
+
+import java.io.IOException;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.util.Map;
+
+import javax.net.ssl.HttpsURLConnection;
+import javax.net.ssl.SSLSocketFactory;
+
+import org.apache.commons.configuration.ConfigurationException;
+import org.apache.qpid.server.model.Broker;
+
+public class BrokerRestHttpsTest extends QpidRestTestCase
+{
+ private static final String TRUSTSTORE = "test-profiles/test_resources/ssl/java_client_truststore.jks";
+ private static final String TRUSTSTORE_PASSWORD = "password";
+
+ @Override
+ public void setUp() throws Exception
+ {
+ setSystemProperty("javax.net.debug", "ssl");
+ super.setUp();
+ setSystemProperty("javax.net.ssl.trustStore", TRUSTSTORE);
+ setSystemProperty("javax.net.ssl.trustStorePassword", TRUSTSTORE_PASSWORD);
+ }
+
+ @Override
+ protected void customizeConfiguration() throws ConfigurationException, IOException
+ {
+ setConfigurationProperty("management.enabled", "true");
+ setConfigurationProperty("management.http.enabled", "false");
+ setConfigurationProperty("management.https.enabled", "true");
+ setConfigurationProperty("management.https.port", Integer.toString(getHttpPort()));
+ }
+
+ @Override
+ protected String getHostName()
+ {
+ return "localhost";
+ }
+
+ @Override
+ protected String getProtocol()
+ {
+ return "https";
+ }
+
+ @Override
+ protected HttpURLConnection openManagementConection(String path) throws IOException
+ {
+ URL url = getManagementURL(path);
+ HttpURLConnection httpCon = (HttpURLConnection) url.openConnection();
+ ((HttpsURLConnection) httpCon).setSSLSocketFactory((SSLSocketFactory) SSLSocketFactory.getDefault());
+ httpCon.setDoOutput(true);
+ return httpCon;
+ }
+
+ public void testGetWithHttps() throws Exception
+ {
+ Map<String, Object> brokerDetails = getJsonAsSingletonList("/rest/broker");
+
+ Asserts.assertAttributesPresent(brokerDetails, Broker.AVAILABLE_ATTRIBUTES, Broker.BYTES_RETAINED,
+ Broker.PROCESS_PID, Broker.SUPPORTED_STORE_TYPES, Broker.CREATED, Broker.TIME_TO_LIVE, Broker.UPDATED);
+ }
+}
diff --git a/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/BrokerRestTest.java b/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/BrokerRestTest.java
new file mode 100644
index 0000000000..f2970e2ba9
--- /dev/null
+++ b/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/BrokerRestTest.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.server.management.plugin.servlet.rest;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.qpid.common.QpidProperties;
+import org.apache.qpid.server.model.Broker;
+import org.apache.qpid.server.model.LifetimePolicy;
+import org.apache.qpid.server.model.Port;
+import org.apache.qpid.server.model.State;
+import org.apache.qpid.server.model.VirtualHost;
+
+public class BrokerRestTest extends QpidRestTestCase
+{
+
+ private static final String BROKER_AUTHENTICATIONPROVIDERS_ATTRIBUTE = "authenticationproviders";
+ private static final String BROKER_PORTS_ATTRIBUTE = "ports";
+ private static final String BROKER_VIRTUALHOSTS_ATTRIBUTE = "virtualhosts";
+ private static final String BROKER_STATISTICS_ATTRIBUTE = "statistics";
+
+ public void testGet() throws Exception
+ {
+ Map<String, Object> brokerDetails = getJsonAsSingletonList("/rest/broker");
+
+ assertBrokerAttributes(brokerDetails);
+
+ @SuppressWarnings("unchecked")
+ Map<String, Object> statistics = (Map<String, Object>) brokerDetails.get(BROKER_STATISTICS_ATTRIBUTE);
+ Asserts.assertAttributesPresent(statistics, new String[]{ "bytesIn", "messagesOut", "bytesOut", "messagesIn" });
+
+ @SuppressWarnings("unchecked")
+ List<Map<String, Object>> virtualhosts = (List<Map<String, Object>>) brokerDetails.get(BROKER_VIRTUALHOSTS_ATTRIBUTE);
+ assertEquals("Unexpected number of virtual hosts", 3, virtualhosts.size());
+
+ Asserts.assertVirtualHost("development", find(VirtualHost.NAME, "development", virtualhosts));
+ Asserts.assertVirtualHost("localhost", find(VirtualHost.NAME, "localhost", virtualhosts));
+ Asserts.assertVirtualHost("test", find(VirtualHost.NAME, "test", virtualhosts));
+
+ @SuppressWarnings("unchecked")
+ List<Map<String, Object>> ports = (List<Map<String, Object>>) brokerDetails.get(BROKER_PORTS_ATTRIBUTE);
+ assertEquals("Unexpected number of ports", 2, ports.size());
+
+ for (Map<String, Object> port : ports)
+ {
+ Asserts.assertPortAttributes(port);
+ }
+
+ String bindingAddress = (String)ports.get(0).get(Port.BINDING_ADDRESS);
+
+ Map<String, Object> amqpPort = find(Port.NAME, bindingAddress + ":" + getPort(), ports);
+ Map<String, Object> httpPort = find(Port.NAME, bindingAddress + ":" + getHttpPort(), ports);
+
+ assertNotNull("Cannot find AMQP port", amqpPort);
+ assertNotNull("Cannot find HTTP port", httpPort);
+
+ @SuppressWarnings("unchecked")
+ Collection<String> port1Protocols = (Collection<String>) amqpPort.get(Port.PROTOCOLS);
+ assertFalse("AMQP protocol list cannot contain HTTP", port1Protocols.contains("HTTP"));
+
+ @SuppressWarnings("unchecked")
+ Collection<String> port2Protocols = (Collection<String>) httpPort.get(Port.PROTOCOLS);
+ assertEquals("Unexpected value of attribute " + Port.PROTOCOLS, new HashSet<String>(Arrays.asList("HTTP")),
+ new HashSet<String>(port2Protocols));
+ }
+
+ protected void assertBrokerAttributes(Map<String, Object> brokerDetails)
+ {
+ Asserts.assertAttributesPresent(brokerDetails, Broker.AVAILABLE_ATTRIBUTES,
+ Broker.BYTES_RETAINED, Broker.PROCESS_PID, Broker.SUPPORTED_STORE_TYPES,
+ Broker.CREATED, Broker.TIME_TO_LIVE, Broker.UPDATED);
+
+ assertEquals("Unexpected value of attribute " + Broker.BUILD_VERSION, QpidProperties.getBuildVersion(),
+ brokerDetails.get(Broker.BUILD_VERSION));
+ assertEquals("Unexpected value of attribute " + Broker.OPERATING_SYSTEM, System.getProperty("os.name") + " "
+ + System.getProperty("os.version") + " " + System.getProperty("os.arch"),
+ brokerDetails.get(Broker.OPERATING_SYSTEM));
+ assertEquals(
+ "Unexpected value of attribute " + Broker.PLATFORM,
+ System.getProperty("java.vendor") + " "
+ + System.getProperty("java.runtime.version", System.getProperty("java.version")),
+ brokerDetails.get(Broker.PLATFORM));
+ assertEquals("Unexpected value of attribute " + Broker.DURABLE, Boolean.TRUE, brokerDetails.get(Broker.DURABLE));
+ assertEquals("Unexpected value of attribute " + Broker.LIFETIME_POLICY, LifetimePolicy.PERMANENT.name(),
+ brokerDetails.get(Broker.LIFETIME_POLICY));
+ assertEquals("Unexpected value of attribute " + Broker.NAME, "Broker", brokerDetails.get(Broker.NAME));
+ assertEquals("Unexpected value of attribute " + Broker.STATE, State.ACTIVE.name(), brokerDetails.get(Broker.STATE));
+
+ assertNotNull("Unexpected value of attribute " + Broker.ID, brokerDetails.get(Broker.ID));
+ assertNotNull("Unexpected value of attribute statistics", brokerDetails.get(BROKER_STATISTICS_ATTRIBUTE));
+ assertNotNull("Unexpected value of attribute virtualhosts", brokerDetails.get(BROKER_VIRTUALHOSTS_ATTRIBUTE));
+ assertNotNull("Unexpected value of attribute ports", brokerDetails.get(BROKER_PORTS_ATTRIBUTE));
+ assertNotNull("Unexpected value of attribute authenticationproviders", brokerDetails.get(BROKER_AUTHENTICATIONPROVIDERS_ATTRIBUTE));
+ }
+
+}
diff --git a/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/ConnectionRestTest.java b/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/ConnectionRestTest.java
new file mode 100644
index 0000000000..3661b94a7c
--- /dev/null
+++ b/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/ConnectionRestTest.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.server.management.plugin.servlet.rest;
+
+import java.io.IOException;
+import java.net.URLDecoder;
+import java.util.List;
+import java.util.Map;
+
+import javax.jms.Destination;
+import javax.jms.JMSException;
+import javax.jms.Message;
+import javax.jms.MessageConsumer;
+import javax.jms.MessageProducer;
+
+import org.apache.qpid.client.AMQConnection;
+import org.apache.qpid.client.AMQSession;
+import org.apache.qpid.server.model.Connection;
+import org.apache.qpid.server.model.Session;
+
+public class ConnectionRestTest extends QpidRestTestCase
+{
+ /**
+ * Message number to publish into queue
+ */
+ private static final int MESSAGE_NUMBER = 5;
+ private static final int MESSAGE_SIZE = 6;
+
+ private static final String SESSIONS_ATTRIBUTE = "sessions";
+
+ private javax.jms.Connection _connection;
+ private javax.jms.Session _session;
+
+ public void setUp() throws Exception
+ {
+ super.setUp();
+
+ _connection = getConnection();
+ _session = _connection.createSession(true, javax.jms.Session.SESSION_TRANSACTED);
+ String queueName = getTestQueueName();
+ Destination queue = _session.createQueue(queueName);
+ MessageConsumer consumer = _session.createConsumer(queue);
+ MessageProducer producer = _session.createProducer(queue);
+ _connection.start();
+
+ // send messages
+ for (int i = 0; i < MESSAGE_NUMBER; i++)
+ {
+ producer.send(_session.createTextMessage("Test-" + i));
+ }
+ _session.commit();
+
+ Message m = consumer.receive(1000l);
+ assertNotNull("Message was not received", m);
+ _session.commit();
+
+ // receive the rest of messages for rollback
+ for (int i = 0; i < MESSAGE_NUMBER - 1; i++)
+ {
+ m = consumer.receive(1000l);
+ assertNotNull("Message was not received", m);
+ }
+ _session.rollback();
+
+ // receive them again
+ for (int i = 0; i < MESSAGE_NUMBER - 1; i++)
+ {
+ m = consumer.receive(1000l);
+ assertNotNull("Message was not received", m);
+ }
+ }
+
+ public void testGetAllConnections() throws Exception
+ {
+ List<Map<String, Object>> connections = getJsonAsList("/rest/connection");
+ assertEquals("Unexpected number of connections", 1, connections.size());
+ Asserts.assertConnection(connections.get(0), (AMQConnection) _connection);
+ }
+
+ public void testGetVirtualHostConnections() throws Exception
+ {
+ List<Map<String, Object>> connections = getJsonAsList("/rest/connection/test");
+ assertEquals("Unexpected number of connections", 1, connections.size());
+ Asserts.assertConnection(connections.get(0), (AMQConnection) _connection);
+ }
+
+ public void testGetConnectionByName() throws Exception
+ {
+ // get connection name
+ String connectionName = getConnectionName();
+
+ Map<String, Object> connectionDetails = getJsonAsSingletonList("/rest/connection/test/"
+ + URLDecoder.decode(connectionName, "UTF-8"));
+ assertConnection(connectionDetails);
+ }
+
+ public void testGetAllSessions() throws Exception
+ {
+ List<Map<String, Object>> sessions = getJsonAsList("/rest/session");
+ assertEquals("Unexpected number of sessions", 1, sessions.size());
+ assertSession(sessions.get(0), (AMQSession<?, ?>) _session);
+ }
+
+ public void testGetVirtualHostSessions() throws Exception
+ {
+ List<Map<String, Object>> sessions = getJsonAsList("/rest/session/test");
+ assertEquals("Unexpected number of sessions", 1, sessions.size());
+ assertSession(sessions.get(0), (AMQSession<?, ?>) _session);
+ }
+
+ public void testGetConnectionSessions() throws Exception
+ {
+ // get connection name
+ String connectionName = getConnectionName();
+
+ List<Map<String, Object>> sessions = getJsonAsList("/rest/session/test/"
+ + URLDecoder.decode(connectionName, "UTF-8"));
+ assertEquals("Unexpected number of sessions", 1, sessions.size());
+ assertSession(sessions.get(0), (AMQSession<?, ?>) _session);
+ }
+
+ public void testGetSessionByName() throws Exception
+ {
+ // get connection name
+ String connectionName = getConnectionName();
+
+ List<Map<String, Object>> sessions = getJsonAsList("/rest/session/test/"
+ + URLDecoder.decode(connectionName, "UTF-8") + "/" + ((AMQSession<?, ?>) _session).getChannelId());
+ assertEquals("Unexpected number of sessions", 1, sessions.size());
+ assertSession(sessions.get(0), (AMQSession<?, ?>) _session);
+ }
+
+ private void assertConnection(Map<String, Object> connectionDetails) throws JMSException
+ {
+ Asserts.assertConnection(connectionDetails, (AMQConnection) _connection);
+
+ @SuppressWarnings("unchecked")
+ Map<String, Object> statistics = (Map<String, Object>) connectionDetails.get(Asserts.STATISTICS_ATTRIBUTE);
+ assertEquals("Unexpected value of connection statistics attribute " + Connection.BYTES_IN, MESSAGE_NUMBER
+ * MESSAGE_SIZE, statistics.get(Connection.BYTES_IN));
+ assertEquals("Unexpected value of connection statistics attribute " + Connection.BYTES_OUT, MESSAGE_SIZE
+ + ((MESSAGE_NUMBER - 1) * MESSAGE_SIZE) * 2, statistics.get(Connection.BYTES_OUT));
+ assertEquals("Unexpected value of connection statistics attribute " + Connection.MESSAGES_IN, MESSAGE_NUMBER,
+ statistics.get(Connection.MESSAGES_IN));
+ assertEquals("Unexpected value of connection statistics attribute " + Connection.MESSAGES_OUT,
+ MESSAGE_NUMBER * 2 - 1, statistics.get(Connection.MESSAGES_OUT));
+
+ @SuppressWarnings("unchecked")
+ List<Map<String, Object>> sessions = (List<Map<String, Object>>) connectionDetails.get(SESSIONS_ATTRIBUTE);
+ assertNotNull("Sessions cannot be found", sessions);
+ assertEquals("Unexpected number of sessions", 1, sessions.size());
+ assertSession(sessions.get(0), (AMQSession<?, ?>) _session);
+ }
+
+ private void assertSession(Map<String, Object> sessionData, AMQSession<?, ?> session)
+ {
+ assertNotNull("Session map cannot be null", sessionData);
+ Asserts.assertAttributesPresent(sessionData, Session.AVAILABLE_ATTRIBUTES, Session.STATE, Session.DURABLE,
+ Session.LIFETIME_POLICY, Session.TIME_TO_LIVE, Session.CREATED, Session.UPDATED);
+ assertEquals("Unexpecte value of attribute " + Session.NAME, session.getChannelId() + "",
+ sessionData.get(Session.NAME));
+ assertEquals("Unexpecte value of attribute " + Session.PRODUCER_FLOW_BLOCKED, Boolean.FALSE,
+ sessionData.get(Session.PRODUCER_FLOW_BLOCKED));
+ assertEquals("Unexpecte value of attribute " + Session.CHANNEL_ID, session.getChannelId(),
+ sessionData.get(Session.CHANNEL_ID));
+
+ @SuppressWarnings("unchecked")
+ Map<String, Object> statistics = (Map<String, Object>) sessionData.get(Asserts.STATISTICS_ATTRIBUTE);
+ Asserts.assertAttributesPresent(statistics, Session.AVAILABLE_STATISTICS, Session.BYTES_IN, Session.BYTES_OUT,
+ Session.STATE_CHANGED, Session.UNACKNOWLEDGED_BYTES, Session.LOCAL_TRANSACTION_OPEN,
+ Session.XA_TRANSACTION_BRANCH_ENDS, Session.XA_TRANSACTION_BRANCH_STARTS,
+ Session.XA_TRANSACTION_BRANCH_SUSPENDS);
+
+ assertEquals("Unexpecte value of statistic attribute " + Session.UNACKNOWLEDGED_MESSAGES, MESSAGE_NUMBER - 1,
+ statistics.get(Session.UNACKNOWLEDGED_MESSAGES));
+ assertEquals("Unexpecte value of statistic attribute " + Session.LOCAL_TRANSACTION_BEGINS, 4,
+ statistics.get(Session.LOCAL_TRANSACTION_BEGINS));
+ assertEquals("Unexpecte value of statistic attribute " + Session.LOCAL_TRANSACTION_ROLLBACKS, 1,
+ statistics.get(Session.LOCAL_TRANSACTION_ROLLBACKS));
+ assertEquals("Unexpecte value of statistic attribute " + Session.CONSUMER_COUNT, 1,
+ statistics.get(Session.CONSUMER_COUNT));
+ }
+
+ private String getConnectionName() throws IOException
+ {
+ Map<String, Object> hostDetails = getJsonAsSingletonList("/rest/virtualhost/test");
+ @SuppressWarnings("unchecked")
+ List<Map<String, Object>> connections = (List<Map<String, Object>>) hostDetails
+ .get(VirtualHostRestTest.VIRTUALHOST_CONNECTIONS_ATTRIBUTE);
+ assertEquals("Unexpected number of connections", 1, connections.size());
+ Map<String, Object> connection = connections.get(0);
+ String connectionName = (String) connection.get(Connection.NAME);
+ return connectionName;
+ }
+}
diff --git a/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/ExchangeRestTest.java b/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/ExchangeRestTest.java
new file mode 100644
index 0000000000..59936427f9
--- /dev/null
+++ b/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/ExchangeRestTest.java
@@ -0,0 +1,67 @@
+package org.apache.qpid.server.management.plugin.servlet.rest;
+
+import java.net.URLDecoder;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.qpid.server.model.Binding;
+import org.apache.qpid.server.model.Exchange;
+
+public class ExchangeRestTest extends QpidRestTestCase
+{
+ public void testGet() throws Exception
+ {
+ List<Map<String, Object>> exchanges = getJsonAsList("/rest/exchange");
+ assertNotNull("Exchanges cannot be null", exchanges);
+ assertTrue("Unexpected number of exchanges", exchanges.size() >= EXPECTED_HOSTS.length * EXPECTED_EXCHANGES.length);
+ for (Map<String, Object> exchange : exchanges)
+ {
+ Asserts.assertExchange((String) exchange.get(Exchange.NAME), (String) exchange.get(Exchange.TYPE), exchange);
+ }
+ }
+
+ public void testGetHostExchanges() throws Exception
+ {
+ List<Map<String, Object>> exchanges = getJsonAsList("/rest/exchange/test");
+ assertNotNull("Users cannot be null", exchanges);
+ assertEquals("Unexpected number of exchanges", 6, EXPECTED_EXCHANGES.length);
+ for (String exchangeName : EXPECTED_EXCHANGES)
+ {
+ Map<String, Object> exchange = find(Exchange.NAME, exchangeName, exchanges);
+ assertExchange(exchangeName, exchange);
+ }
+ }
+
+ public void testGetHostExchangeByName() throws Exception
+ {
+ for (String exchangeName : EXPECTED_EXCHANGES)
+ {
+ Map<String, Object> exchange = getJsonAsSingletonList("/rest/exchange/test/"
+ + URLDecoder.decode(exchangeName, "UTF-8"));
+ assertExchange(exchangeName, exchange);
+ }
+ }
+
+ private void assertExchange(String exchangeName, Map<String, Object> exchange)
+ {
+ assertNotNull("Exchange with name " + exchangeName + " is not found", exchange);
+ String type = (String) exchange.get(Exchange.TYPE);
+ Asserts.assertExchange(exchangeName, type, exchange);
+ if ("direct".equals(type))
+ {
+ assertBindings(exchange);
+ }
+ }
+
+ private void assertBindings(Map<String, Object> exchange)
+ {
+ @SuppressWarnings("unchecked")
+ List<Map<String, Object>> bindings = (List<Map<String, Object>>) exchange.get("bindings");
+ for (String queueName : EXPECTED_QUEUES)
+ {
+ Map<String, Object> binding = find(Binding.NAME, queueName, bindings);
+ Asserts.assertBinding(queueName, (String) exchange.get(Exchange.NAME), binding);
+ }
+ }
+
+}
diff --git a/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/LogRecordsRestTest.java b/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/LogRecordsRestTest.java
new file mode 100644
index 0000000000..c64fd6e1da
--- /dev/null
+++ b/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/LogRecordsRestTest.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.management.plugin.servlet.rest;
+
+import java.util.List;
+import java.util.Map;
+
+public class LogRecordsRestTest extends QpidRestTestCase
+{
+ public void testGet() throws Exception
+ {
+ List<Map<String, Object>> logs = getJsonAsList("/rest/logrecords");
+ assertNotNull("Logs data cannot be null", logs);
+ assertTrue("Logs are not found", logs.size() > 0);
+ Map<String, Object> record = find("message", "[Broker] BRK-1004 : Qpid Broker Ready", logs);
+
+ assertNotNull("BRK-1004 message is not found", record);
+ assertNotNull("Message id cannot be null", record.get("id"));
+ assertNotNull("Message timestamp cannot be null", record.get("timestamp"));
+ assertEquals("Unexpected log level", "INFO", record.get("level"));
+ assertEquals("Unexpected thread", "main", record.get("thread"));
+ assertEquals("Unexpected logger", "qpid.message.broker.ready", record.get("logger"));
+ }
+}
diff --git a/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/MessagesRestTest.java b/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/MessagesRestTest.java
new file mode 100644
index 0000000000..492df43957
--- /dev/null
+++ b/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/MessagesRestTest.java
@@ -0,0 +1,354 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.management.plugin.servlet.rest;
+
+import java.io.IOException;
+import java.net.HttpURLConnection;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+
+import javax.jms.BytesMessage;
+import javax.jms.Connection;
+import javax.jms.DeliveryMode;
+import javax.jms.Destination;
+import javax.jms.Message;
+import javax.jms.MessageProducer;
+import javax.jms.Session;
+
+import org.codehaus.jackson.JsonParseException;
+import org.codehaus.jackson.map.JsonMappingException;
+
+public class MessagesRestTest extends QpidRestTestCase
+{
+
+ /**
+ * Message number to publish into queue
+ */
+ private static final int MESSAGE_NUMBER = 12;
+
+ private Connection _connection;
+ private Session _session;
+ private MessageProducer _producer;
+ private long _startTime;
+ private long _ttl;
+
+ public void setUp() throws Exception
+ {
+ super.setUp();
+ _startTime = System.currentTimeMillis();
+ _connection = getConnection();
+ _session = _connection.createSession(true, Session.SESSION_TRANSACTED);
+ String queueName = getTestQueueName();
+ Destination queue = _session.createQueue(queueName);
+ _session.createConsumer(queue);
+ _producer = _session.createProducer(queue);
+
+ _ttl = TimeUnit.DAYS.toMillis(1);
+ for (int i = 0; i < MESSAGE_NUMBER; i++)
+ {
+ Message m = _session.createTextMessage("Test-" + i);
+ m.setIntProperty("index", i);
+ if (i % 2 == 0)
+ {
+ _producer.send(m);
+ }
+ else
+ {
+ _producer.send(m, DeliveryMode.NON_PERSISTENT, 5, _ttl);
+ }
+ }
+ _session.commit();
+ }
+
+ public void testGet() throws Exception
+ {
+ String queueName = getTestQueueName();
+ List<Map<String, Object>> messages = getJsonAsList("/rest/message/test/" + queueName);
+ assertNotNull("Messages are not found", messages);
+ assertEquals("Unexpected number of messages", MESSAGE_NUMBER, messages.size());
+ int position = 0;
+ for (Map<String, Object> message : messages)
+ {
+ assertMessage(position, message);
+ position++;
+ }
+ }
+
+ public void testGetMessageContent() throws Exception
+ {
+ String queueName = getTestQueueName();
+
+ // add bytes message
+ BytesMessage byteMessage = _session.createBytesMessage();
+ byte[] messageBytes = "Test".getBytes();
+ byteMessage.writeBytes(messageBytes);
+ byteMessage.setStringProperty("test", "value");
+ _producer.send(byteMessage);
+ _session.commit();
+
+ // get message IDs
+ List<Long> ids = getMesssageIds(queueName);
+
+ Map<String, Object> message = getJsonAsMap("/rest/message/test/" + queueName + "/" + ids.get(0));
+ assertMessageAttributes(message);
+ assertMessageAttributeValues(message, true);
+
+ @SuppressWarnings("unchecked")
+ Map<String, Object> headers = (Map<String, Object>) message.get("headers");
+ assertNotNull("Message headers are not found", headers);
+ assertEquals("Unexpected message header", 0, headers.get("index"));
+
+ Long lastMessageId = ids.get(ids.size() - 1);
+ message = getJsonAsMap("/rest/message/test/" + queueName + "/" + lastMessageId);
+ assertMessageAttributes(message);
+ assertEquals("Unexpected message attribute mimeType", "application/octet-stream", message.get("mimeType"));
+ assertEquals("Unexpected message attribute size", 4, message.get("size"));
+
+ @SuppressWarnings("unchecked")
+ Map<String, Object> bytesMessageHeader = (Map<String, Object>) message.get("headers");
+ assertNotNull("Message headers are not found", bytesMessageHeader);
+ assertEquals("Unexpected message header", "value", bytesMessageHeader.get("test"));
+
+ // get content
+ HttpURLConnection connection = openManagementConection("/rest/message-content/test/" + queueName + "/"
+ + lastMessageId, "GET");
+ connection.connect();
+ byte[] data = readConnectionInputStream(connection);
+ assertTrue("Unexpected message", Arrays.equals(messageBytes, data));
+
+ }
+
+ public void testPostMoveMessages() throws Exception
+ {
+ String queueName = getTestQueueName();
+ String queueName2 = queueName + "_2";
+ Destination queue2 = _session.createQueue(queueName2);
+ _session.createConsumer(queue2);
+
+ // get message IDs
+ List<Long> ids = getMesssageIds(queueName);
+
+ // move half of the messages
+ int movedNumber = ids.size() / 2;
+ List<Long> movedMessageIds = new ArrayList<Long>();
+ for (int i = 0; i < movedNumber; i++)
+ {
+ movedMessageIds.add(ids.remove(i));
+ }
+
+ // move messages
+ HttpURLConnection connection = openManagementConection("/rest/message/test/" + queueName, "POST");
+
+ Map<String, Object> messagesData = new HashMap<String, Object>();
+ messagesData.put("messages", movedMessageIds);
+ messagesData.put("destinationQueue", queueName2);
+ messagesData.put("move", Boolean.TRUE);
+
+ writeJsonRequest(connection, messagesData);
+ assertEquals("Unexpected response code", 200, connection.getResponseCode());
+
+ // check messages on target queue
+ List<Map<String, Object>> messages = getJsonAsList("/rest/message/test/" + queueName2);
+ assertNotNull("Messages are not found", messages);
+ assertEquals("Unexpected number of messages", movedMessageIds.size(), messages.size());
+ for (Long id : movedMessageIds)
+ {
+ Map<String, Object> message = find("id", id.intValue(), messages);
+ assertMessageAttributes(message);
+ }
+
+ // check messages on original queue
+ messages = getJsonAsList("/rest/message/test/" + queueName);
+ assertNotNull("Messages are not found", messages);
+ assertEquals("Unexpected number of messages", ids.size(), messages.size());
+ for (Long id : ids)
+ {
+ Map<String, Object> message = find("id", id.intValue(), messages);
+ assertMessageAttributes(message);
+ }
+ for (Long id : movedMessageIds)
+ {
+ Map<String, Object> message = find("id", id.intValue(), messages);
+ assertNull("Moved message " + id + " is found on original queue", message);
+ }
+ }
+
+ public void testPostCopyMessages() throws Exception
+ {
+ String queueName = getTestQueueName();
+ String queueName2 = queueName + "_2";
+ Destination queue2 = _session.createQueue(queueName2);
+ _session.createConsumer(queue2);
+
+ // get message IDs
+ List<Long> ids = getMesssageIds(queueName);
+
+ // copy half of the messages
+ int copyNumber = ids.size() / 2;
+ List<Long> copyMessageIds = new ArrayList<Long>();
+ for (int i = 0; i < copyNumber; i++)
+ {
+ copyMessageIds.add(ids.remove(i));
+ }
+
+ // copy messages
+ HttpURLConnection connection = openManagementConection("/rest/message/test/" + queueName, "POST");
+
+ Map<String, Object> messagesData = new HashMap<String, Object>();
+ messagesData.put("messages", copyMessageIds);
+ messagesData.put("destinationQueue", queueName2);
+
+ writeJsonRequest(connection, messagesData);
+ assertEquals("Unexpected response code", 200, connection.getResponseCode());
+
+ // check messages on target queue
+ List<Map<String, Object>> messages = getJsonAsList("/rest/message/test/" + queueName2);
+ assertNotNull("Messages are not found", messages);
+ assertEquals("Unexpected number of messages", copyMessageIds.size(), messages.size());
+ for (Long id : copyMessageIds)
+ {
+ Map<String, Object> message = find("id", id.intValue(), messages);
+ assertMessageAttributes(message);
+ }
+
+ // check messages on original queue
+ messages = getJsonAsList("/rest/message/test/" + queueName);
+ assertNotNull("Messages are not found", messages);
+ assertEquals("Unexpected number of messages", MESSAGE_NUMBER, messages.size());
+ for (Long id : ids)
+ {
+ Map<String, Object> message = find("id", id.intValue(), messages);
+ assertMessageAttributes(message);
+ }
+ for (Long id : copyMessageIds)
+ {
+ Map<String, Object> message = find("id", id.intValue(), messages);
+ assertMessageAttributes(message);
+ }
+ }
+
+ public void testDeleteMessages() throws Exception
+ {
+ String queueName = getTestQueueName();
+
+ // get message IDs
+ List<Long> ids = getMesssageIds(queueName);
+
+ // delete half of the messages
+ int deleteNumber = ids.size() / 2;
+ StringBuilder queryString = new StringBuilder();
+ List<Long> deleteMessageIds = new ArrayList<Long>();
+ for (int i = 0; i < deleteNumber; i++)
+ {
+ Long id = ids.remove(i);
+ deleteMessageIds.add(id);
+ if (queryString.length() > 0)
+ {
+ queryString.append("&");
+ }
+ queryString.append("id=").append(id);
+ }
+
+ // delete messages
+ HttpURLConnection connection = openManagementConection(
+ "/rest/message/test/" + queueName + "?" + queryString.toString(), "DELETE");
+ connection.connect();
+ assertEquals("Unexpected response code", 200, connection.getResponseCode());
+
+ // check messages on queue
+ List<Map<String, Object>> messages = getJsonAsList("/rest/message/test/" + queueName);
+ assertNotNull("Messages are not found", messages);
+ assertEquals("Unexpected number of messages", ids.size(), messages.size());
+ for (Long id : ids)
+ {
+ Map<String, Object> message = find("id", id.intValue(), messages);
+ assertMessageAttributes(message);
+ }
+ for (Long id : deleteMessageIds)
+ {
+ Map<String, Object> message = find("id", id.intValue(), messages);
+ assertNull("Message with id " + id + " was not deleted", message);
+ }
+ }
+
+ private List<Long> getMesssageIds(String queueName) throws IOException, JsonParseException, JsonMappingException
+ {
+ List<Map<String, Object>> messages = getJsonAsList("/rest/message/test/" + queueName);
+ List<Long> ids = new ArrayList<Long>();
+ for (Map<String, Object> message : messages)
+ {
+ ids.add(((Number) message.get("id")).longValue());
+ }
+ return ids;
+ }
+
+ private void assertMessage(int position, Map<String, Object> message)
+ {
+ assertMessageAttributes(message);
+
+ assertEquals("Unexpected message attribute position", position, message.get("position"));
+ assertEquals("Unexpected message attribute size", position < 10 ? 6 : 7, message.get("size"));
+ boolean even = position % 2 == 0;
+ assertMessageAttributeValues(message, even);
+ }
+
+ private void assertMessageAttributeValues(Map<String, Object> message, boolean even)
+ {
+ if (even)
+ {
+ assertEquals("Unexpected message attribute expirationTime", 0, message.get("expirationTime"));
+ assertEquals("Unexpected message attribute priority", 4, message.get("priority"));
+ assertEquals("Unexpected message attribute persistent", Boolean.TRUE, message.get("persistent"));
+ }
+ else
+ {
+ assertEquals("Unexpected message attribute expirationTime", ((Number) message.get("timestamp")).longValue()
+ + _ttl, message.get("expirationTime"));
+ assertEquals("Unexpected message attribute priority", 5, message.get("priority"));
+ assertEquals("Unexpected message attribute persistent", Boolean.FALSE, message.get("persistent"));
+ }
+ assertEquals("Unexpected message attribute mimeType", "text/plain", message.get("mimeType"));
+ assertEquals("Unexpected message attribute userId", "guest", message.get("userId"));
+ assertEquals("Unexpected message attribute deliveryCount", 0, message.get("deliveryCount"));
+ assertEquals("Unexpected message attribute state", "Available", message.get("state"));
+ }
+
+ private void assertMessageAttributes(Map<String, Object> message)
+ {
+ assertNotNull("Message map cannot be null", message);
+ assertNotNull("Unexpected message attribute deliveryCount", message.get("deliveryCount"));
+ assertNotNull("Unexpected message attribute state", message.get("state"));
+ assertNotNull("Unexpected message attribute id", message.get("id"));
+ assertNotNull("Message arrivalTime cannot be null", message.get("arrivalTime"));
+ assertNotNull("Message timestamp cannot be null", message.get("timestamp"));
+ assertTrue("Message arrivalTime cannot be null", ((Number) message.get("arrivalTime")).longValue() > _startTime);
+ assertNotNull("Message messageId cannot be null", message.get("messageId"));
+ assertNotNull("Unexpected message attribute mimeType", message.get("mimeType"));
+ assertNotNull("Unexpected message attribute userId", message.get("userId"));
+ assertNotNull("Message priority cannot be null", message.get("priority"));
+ assertNotNull("Message expirationTime cannot be null", message.get("expirationTime"));
+ assertNotNull("Message persistent cannot be null", message.get("persistent"));
+ }
+}
diff --git a/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/PortRestTest.java b/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/PortRestTest.java
new file mode 100644
index 0000000000..49f163baae
--- /dev/null
+++ b/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/PortRestTest.java
@@ -0,0 +1,41 @@
+package org.apache.qpid.server.management.plugin.servlet.rest;
+
+import java.net.URLDecoder;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.qpid.server.model.Port;
+
+public class PortRestTest extends QpidRestTestCase
+{
+ public void testGet() throws Exception
+ {
+ List<Map<String, Object>> ports = getJsonAsList("/rest/port/");
+ assertNotNull("Port data cannot be null", ports);
+ assertEquals("Unexpected number of ports", 2, ports.size());
+ int[] expectedPorts = { getPort(), getHttpPort() };
+ for (int port : expectedPorts)
+ {
+ String portName = "0.0.0.0:" + port;
+ Map<String, Object> portData = find(Port.NAME, portName, ports);
+ assertNotNull("Port " + portName + " is not found", portData);
+ Asserts.assertPortAttributes(portData);
+ }
+ }
+
+ public void testGetPort() throws Exception
+ {
+ List<Map<String, Object>> ports = getJsonAsList("/rest/port/");
+ assertNotNull("Ports data cannot be null", ports);
+ assertEquals("Unexpected number of ports", 2, ports.size());
+ for (Map<String, Object> portMap : ports)
+ {
+ String portName = (String) portMap.get(Port.NAME);
+ assertNotNull("Port name attribute is not found", portName);
+ Map<String, Object> portData = getJsonAsSingletonList("/rest/port/" + URLDecoder.decode(portName, "UTF-8"));
+ assertNotNull("Port " + portName + " is not found", portData);
+ Asserts.assertPortAttributes(portData);
+ }
+ }
+
+}
diff --git a/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/QpidRestTestCase.java b/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/QpidRestTestCase.java
new file mode 100644
index 0000000000..e83341de80
--- /dev/null
+++ b/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/QpidRestTestCase.java
@@ -0,0 +1,245 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.management.plugin.servlet.rest;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.HttpURLConnection;
+import java.net.InetAddress;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.configuration.ConfigurationException;
+import org.apache.log4j.Logger;
+import org.apache.qpid.test.utils.QpidBrokerTestCase;
+import org.codehaus.jackson.JsonGenerationException;
+import org.codehaus.jackson.JsonParseException;
+import org.codehaus.jackson.map.JsonMappingException;
+import org.codehaus.jackson.map.ObjectMapper;
+import org.codehaus.jackson.type.TypeReference;
+
+public class QpidRestTestCase extends QpidBrokerTestCase
+{
+ private static final Logger LOGGER = Logger.getLogger(QpidRestTestCase.class);
+
+ public static final String[] EXPECTED_HOSTS = { "development", "test", "localhost" };
+ public static final String[] EXPECTED_QUEUES = { "queue", "ping" };
+ public static final String[] EXPECTED_EXCHANGES = { "amq.fanout", "amq.match", "amq.direct", "amq.topic",
+ "qpid.management", "<<default>>" };
+
+ private int _httpPort;
+ private String _hostName;
+ private List<HttpURLConnection> _httpConnections;
+
+ @Override
+ public void setUp() throws Exception
+ {
+ _httpConnections = new ArrayList<HttpURLConnection>();
+ _hostName = InetAddress.getLocalHost().getHostName();
+ _httpPort = findFreePort();
+ customizeConfiguration();
+ super.setUp();
+
+ }
+
+ protected void customizeConfiguration() throws ConfigurationException, IOException
+ {
+ setConfigurationProperty("management.enabled", "false");
+ setConfigurationProperty("management.http.enabled", "true");
+ setConfigurationProperty("management.https.enabled", "false");
+ setConfigurationProperty("management.http.port", Integer.toString(_httpPort));
+ }
+
+ public void teearDown() throws Exception
+ {
+ for (HttpURLConnection connection : _httpConnections)
+ {
+ try
+ {
+ connection.disconnect();
+ }
+ catch (Exception e)
+ {
+ // ignore
+ }
+ }
+ super.tearDown();
+ }
+
+ protected int getHttpPort()
+ {
+ return _httpPort;
+ }
+
+ protected String getHostName()
+ {
+ return _hostName;
+ }
+
+ protected String getProtocol()
+ {
+ return "http";
+ }
+
+ protected String getManagementURL()
+ {
+ return getProtocol() + "://" + getHostName() + ":" + getHttpPort();
+ }
+
+ protected URL getManagementURL(String path) throws MalformedURLException
+ {
+ return new URL(getManagementURL() + path);
+ }
+
+ protected HttpURLConnection openManagementConection(String path) throws IOException
+ {
+ URL url = getManagementURL(path);
+ HttpURLConnection httpCon = (HttpURLConnection) url.openConnection();
+ httpCon.setDoOutput(true);
+ return httpCon;
+ }
+
+ protected HttpURLConnection openManagementConection(String path, String method) throws IOException
+ {
+ HttpURLConnection httpCon = openManagementConection(path);
+ httpCon.setRequestMethod(method);
+ return httpCon;
+ }
+
+ protected List<Map<String, Object>> readJsonResponseAsList(HttpURLConnection connection) throws IOException,
+ JsonParseException, JsonMappingException
+ {
+ byte[] data = readConnectionInputStream(connection);
+
+ ObjectMapper mapper = new ObjectMapper();
+
+ TypeReference<List<LinkedHashMap<String, Object>>> typeReference = new TypeReference<List<LinkedHashMap<String, Object>>>()
+ {
+ };
+ List<Map<String, Object>> providedObject = mapper.readValue(new ByteArrayInputStream(data), typeReference);
+ return providedObject;
+ }
+
+ protected Map<String, Object> readJsonResponseAsMap(HttpURLConnection connection) throws IOException,
+ JsonParseException, JsonMappingException
+ {
+ byte[] data = readConnectionInputStream(connection);
+
+ ObjectMapper mapper = new ObjectMapper();
+
+ TypeReference<LinkedHashMap<String, Object>> typeReference = new TypeReference<LinkedHashMap<String, Object>>()
+ {
+ };
+ Map<String, Object> providedObject = mapper.readValue(new ByteArrayInputStream(data), typeReference);
+ return providedObject;
+ }
+
+ protected byte[] readConnectionInputStream(HttpURLConnection connection) throws IOException
+ {
+ InputStream is = connection.getInputStream();
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ byte[] buffer = new byte[1024];
+ int len = -1;
+ while ((len = is.read(buffer)) != -1)
+ {
+ baos.write(buffer, 0, len);
+ }
+ if (LOGGER.isTraceEnabled())
+ {
+ LOGGER.trace("RESPONSE:" + new String(baos.toByteArray()));
+ }
+ return baos.toByteArray();
+ }
+
+ protected void writeJsonRequest(HttpURLConnection connection, Map<String, Object> data) throws JsonGenerationException,
+ JsonMappingException, IOException
+ {
+ ObjectMapper mapper = new ObjectMapper();
+ mapper.writeValue(connection.getOutputStream(), data);
+ }
+
+ protected Map<String, Object> find(String name, Object value, List<Map<String, Object>> data)
+ {
+ for (Map<String, Object> map : data)
+ {
+ Object mapValue = map.get(name);
+ if (value.equals(mapValue))
+ {
+ return map;
+ }
+ }
+ return null;
+ }
+
+ protected Map<String, Object> find(Map<String, Object> searchAttributes, List<Map<String, Object>> data)
+ {
+ for (Map<String, Object> map : data)
+ {
+ boolean equals = true;
+ for (Map.Entry<String, Object> entry : searchAttributes.entrySet())
+ {
+ Object mapValue = map.get(entry.getKey());
+ if (!entry.getValue().equals(mapValue))
+ {
+ equals = false;
+ break;
+ }
+ }
+ if (equals)
+ {
+ return map;
+ }
+ }
+ return null;
+ }
+
+ protected Map<String, Object> getJsonAsSingletonList(String path) throws IOException
+ {
+ List<Map<String, Object>> response = getJsonAsList(path);
+
+ assertNotNull("Response cannot be null", response);
+ assertEquals("Unexpected response", 1, response.size());
+ return response.get(0);
+ }
+
+ protected List<Map<String, Object>> getJsonAsList(String path) throws IOException, JsonParseException,
+ JsonMappingException
+ {
+ HttpURLConnection connection = openManagementConection(path, "GET");
+ connection.connect();
+ List<Map<String, Object>> response = readJsonResponseAsList(connection);
+ return response;
+ }
+
+ protected Map<String, Object> getJsonAsMap(String path) throws IOException
+ {
+ HttpURLConnection connection = openManagementConection(path, "GET");
+ connection.connect();
+ Map<String, Object> response = readJsonResponseAsMap(connection);
+ return response;
+ }
+}
diff --git a/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/QueueRestTest.java b/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/QueueRestTest.java
new file mode 100644
index 0000000000..5f11b3fb1d
--- /dev/null
+++ b/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/QueueRestTest.java
@@ -0,0 +1,225 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.management.plugin.servlet.rest;
+
+import java.io.IOException;
+import java.net.HttpURLConnection;
+import java.net.URLDecoder;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.jms.Connection;
+import javax.jms.Destination;
+import javax.jms.Message;
+import javax.jms.MessageConsumer;
+import javax.jms.MessageProducer;
+import javax.jms.Session;
+
+import org.apache.qpid.server.model.Binding;
+import org.apache.qpid.server.model.Consumer;
+import org.apache.qpid.server.model.LifetimePolicy;
+import org.apache.qpid.server.model.Queue;
+
+public class QueueRestTest extends QpidRestTestCase
+{
+ private static final String QUEUE_ATTRIBUTE_CONSUMERS = "consumers";
+ private static final String QUEUE_ATTRIBUTE_BINDINGS = "bindings";
+
+ /**
+ * Message number to publish into queue
+ */
+ private static final int MESSAGE_NUMBER = 2;
+ private static final int MESSAGE_PAYLOAD_SIZE = 6;
+ private static final int ENQUEUED_MESSAGES = 1;
+ private static final int DEQUEUED_MESSAGES = 1;
+ private static final int ENQUEUED_BYTES = MESSAGE_PAYLOAD_SIZE;
+ private static final int DEQUEUED_BYTES = MESSAGE_PAYLOAD_SIZE;
+
+ private Connection _connection;
+
+ public void setUp() throws Exception
+ {
+ super.setUp();
+ _connection = getConnection();
+ Session session = _connection.createSession(true, Session.SESSION_TRANSACTED);
+ String queueName = getTestQueueName();
+ Destination queue = session.createQueue(queueName);
+ MessageConsumer consumer = session.createConsumer(queue);
+ MessageProducer producer = session.createProducer(queue);
+
+ for (int i = 0; i < MESSAGE_NUMBER; i++)
+ {
+ producer.send(session.createTextMessage("Test-" + i));
+ }
+ session.commit();
+ _connection.start();
+ Message m = consumer.receive(1000l);
+ assertNotNull("Message is not received", m);
+ session.commit();
+ }
+
+ public void testGetVirtualHostQueues() throws Exception
+ {
+ String queueName = getTestQueueName();
+ List<Map<String, Object>> queues = getJsonAsList("/rest/queue/test");
+ assertEquals("Unexpected number of queues", EXPECTED_QUEUES.length + 1, queues.size());
+ String[] expectedQueues = new String[EXPECTED_QUEUES.length + 1];
+ System.arraycopy(EXPECTED_QUEUES, 0, expectedQueues, 0, EXPECTED_QUEUES.length);
+ expectedQueues[EXPECTED_QUEUES.length] = queueName;
+
+ for (String name : expectedQueues)
+ {
+ Map<String, Object> queueDetails = find(Queue.NAME, name, queues);
+ Asserts.assertQueue(name, "standard", queueDetails);
+
+ @SuppressWarnings("unchecked")
+ List<Map<String, Object>> bindings = (List<Map<String, Object>>) queueDetails.get(QUEUE_ATTRIBUTE_BINDINGS);
+ assertNotNull("Queue bindings are not found", bindings);
+ assertEquals("Unexpected number of bindings", 2, bindings.size());
+
+ Map<String, Object> defaultExchangeBinding = find(Binding.EXCHANGE, "<<default>>", bindings);
+ Map<String, Object> directExchangeBinding = find(Binding.EXCHANGE, "amq.direct", bindings);
+ Asserts.assertBinding(name, "<<default>>", defaultExchangeBinding);
+ Asserts.assertBinding(name, "amq.direct", directExchangeBinding);
+ }
+ }
+
+ public void testGetByName() throws Exception
+ {
+ String queueName = getTestQueueName();
+ Map<String, Object> queueDetails = getJsonAsSingletonList("/rest/queue/test/" + queueName);
+ Asserts.assertQueue(queueName, "standard", queueDetails);
+ assertStatistics(queueDetails);
+
+ @SuppressWarnings("unchecked")
+ List<Map<String, Object>> bindings = (List<Map<String, Object>>) queueDetails.get(QUEUE_ATTRIBUTE_BINDINGS);
+ assertNotNull("Queue bindings are not found", bindings);
+ assertEquals("Unexpected number of bindings", 2, bindings.size());
+
+ Map<String, Object> defaultExchangeBinding = find(Binding.EXCHANGE, "<<default>>", bindings);
+ Map<String, Object> directExchangeBinding = find(Binding.EXCHANGE, "amq.direct", bindings);
+ Asserts.assertBinding(queueName, "<<default>>", defaultExchangeBinding);
+ Asserts.assertBinding(queueName, "amq.direct", directExchangeBinding);
+
+ @SuppressWarnings("unchecked")
+ List<Map<String, Object>> consumers = (List<Map<String, Object>>) queueDetails.get(QUEUE_ATTRIBUTE_CONSUMERS);
+ assertNotNull("Queue consumers are not found", consumers);
+ assertEquals("Unexpected number of consumers", 1, consumers.size());
+ assertConsumer(consumers.get(0));
+ }
+
+ public void testPutCreateBinding() throws Exception
+ {
+ String queueName = getTestQueueName();
+ String bindingName = queueName + 2;
+ String[] exchanges = { "amq.direct", "amq.fanout", "amq.topic", "amq.match", "qpid.management", "<<default>>" };
+
+ for (int i = 0; i < exchanges.length; i++)
+ {
+ createBinding(bindingName, exchanges[i], queueName);
+ }
+
+ Map<String, Object> queueDetails = getJsonAsSingletonList("/rest/queue/test/" + queueName);
+ Asserts.assertQueue(queueName, "standard", queueDetails);
+
+ @SuppressWarnings("unchecked")
+ List<Map<String, Object>> bindings = (List<Map<String, Object>>) queueDetails.get(QUEUE_ATTRIBUTE_BINDINGS);
+ assertNotNull("Queue bindings are not found", bindings);
+ assertEquals("Unexpected number of bindings", exchanges.length + 2, bindings.size());
+
+ Map<String, Object> searchAttributes = new HashMap<String, Object>();
+ searchAttributes.put(Binding.NAME, bindingName);
+
+ for (int i = 0; i < exchanges.length; i++)
+ {
+ searchAttributes.put(Binding.EXCHANGE, exchanges[i]);
+ Map<String, Object> binding = find(searchAttributes, bindings);
+ Asserts.assertBinding(bindingName, queueName, exchanges[i], binding);
+ }
+ }
+
+ private void createBinding(String bindingName, String exchangeName, String queueName) throws IOException
+ {
+ HttpURLConnection connection = openManagementConection(
+ "/rest/binding/test/" + URLDecoder.decode(exchangeName, "UTF-8") + "/" + queueName + "/" + bindingName,
+ "PUT");
+
+ Map<String, Object> bindingData = new HashMap<String, Object>();
+ bindingData.put(Binding.NAME, bindingName);
+ bindingData.put(Binding.EXCHANGE, exchangeName);
+ bindingData.put(Binding.QUEUE, queueName);
+
+ writeJsonRequest(connection, bindingData);
+ assertEquals("Unexpected response code", 201, connection.getResponseCode());
+
+ connection.disconnect();
+ }
+
+ private void assertConsumer(Map<String, Object> consumer)
+ {
+ assertNotNull("Consumer map should not be null", consumer);
+ Asserts.assertAttributesPresent(consumer, Consumer.AVAILABLE_ATTRIBUTES, Consumer.STATE, Consumer.TIME_TO_LIVE,
+ Consumer.CREATED, Consumer.UPDATED, Consumer.SETTLEMENT_MODE, Consumer.EXCLUSIVE, Consumer.SELECTOR,
+ Consumer.NO_LOCAL);
+
+ assertEquals("Unexpected binding attribute " + Consumer.NAME, "1", consumer.get(Consumer.NAME));
+ assertEquals("Unexpected binding attribute " + Consumer.DURABLE, Boolean.FALSE, consumer.get(Consumer.DURABLE));
+ assertEquals("Unexpected binding attribute " + Consumer.LIFETIME_POLICY, LifetimePolicy.AUTO_DELETE.name(),
+ consumer.get(Consumer.LIFETIME_POLICY));
+ assertEquals("Unexpected binding attribute " + Consumer.DISTRIBUTION_MODE, "MOVE",
+ consumer.get(Consumer.DISTRIBUTION_MODE));
+
+ @SuppressWarnings("unchecked")
+ Map<String, Object> statistics = (Map<String, Object>) consumer.get(Asserts.STATISTICS_ATTRIBUTE);
+ assertNotNull("Consumer statistics is not present", statistics);
+ Asserts.assertAttributesPresent(statistics, Consumer.AVAILABLE_STATISTICS, Consumer.STATE_CHANGED);
+ }
+
+ private void assertStatistics(Map<String, Object> queueDetails)
+ {
+ @SuppressWarnings("unchecked")
+ Map<String, Object> statistics = (Map<String, Object>) queueDetails.get(Asserts.STATISTICS_ATTRIBUTE);
+ assertEquals("Unexpected queue statistics attribute " + Queue.PERSISTENT_DEQUEUED_MESSAGES, DEQUEUED_MESSAGES,
+ statistics.get(Queue.PERSISTENT_DEQUEUED_MESSAGES));
+ assertEquals("Unexpected queue statistics attribute " + Queue.QUEUE_DEPTH_MESSAGES, ENQUEUED_MESSAGES,
+ statistics.get(Queue.QUEUE_DEPTH_MESSAGES));
+ assertEquals("Unexpected queue statistics attribute " + Queue.CONSUMER_COUNT, 1,
+ statistics.get(Queue.CONSUMER_COUNT));
+ assertEquals("Unexpected queue statistics attribute " + Queue.CONSUMER_COUNT_WITH_CREDIT, 1,
+ statistics.get(Queue.CONSUMER_COUNT_WITH_CREDIT));
+ assertEquals("Unexpected queue statistics attribute " + Queue.BINDING_COUNT, 2, statistics.get(Queue.BINDING_COUNT));
+ assertEquals("Unexpected queue statistics attribute " + Queue.PERSISTENT_DEQUEUED_MESSAGES, DEQUEUED_MESSAGES,
+ statistics.get(Queue.PERSISTENT_DEQUEUED_MESSAGES));
+ assertEquals("Unexpected queue statistics attribute " + Queue.TOTAL_DEQUEUED_MESSAGES, DEQUEUED_MESSAGES,
+ statistics.get(Queue.TOTAL_DEQUEUED_MESSAGES));
+ assertEquals("Unexpected queue statistics attribute " + Queue.TOTAL_DEQUEUED_BYTES, DEQUEUED_BYTES,
+ statistics.get(Queue.TOTAL_DEQUEUED_BYTES));
+ assertEquals("Unexpected queue statistics attribute " + Queue.PERSISTENT_DEQUEUED_BYTES, DEQUEUED_BYTES,
+ statistics.get(Queue.TOTAL_DEQUEUED_BYTES));
+ assertEquals("Unexpected queue statistics attribute " + Queue.PERSISTENT_ENQUEUED_BYTES, ENQUEUED_BYTES
+ + DEQUEUED_BYTES, statistics.get(Queue.PERSISTENT_ENQUEUED_BYTES));
+ assertEquals("Unexpected queue statistics attribute " + Queue.TOTAL_ENQUEUED_BYTES, ENQUEUED_BYTES + DEQUEUED_BYTES,
+ statistics.get(Queue.TOTAL_ENQUEUED_BYTES));
+ assertEquals("Unexpected queue statistics attribute " + Queue.QUEUE_DEPTH_BYTES, ENQUEUED_BYTES,
+ statistics.get(Queue.QUEUE_DEPTH_BYTES));
+ }
+}
diff --git a/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/SaslRestTest.java b/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/SaslRestTest.java
new file mode 100644
index 0000000000..943466eda7
--- /dev/null
+++ b/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/SaslRestTest.java
@@ -0,0 +1,22 @@
+package org.apache.qpid.server.management.plugin.servlet.rest;
+
+import java.util.List;
+import java.util.Map;
+
+public class SaslRestTest extends QpidRestTestCase
+{
+ public void testGet() throws Exception
+ {
+ Map<String, Object> saslData = getJsonAsMap("/rest/sasl");
+ assertNotNull("mechanisms attribute is not found", saslData.get("mechanisms"));
+
+ @SuppressWarnings("unchecked")
+ List<String> mechanisms = (List<String>) saslData.get("mechanisms");
+ String[] expectedMechanisms = { "AMQPLAIN", "PLAIN", "CRAM-MD5" };
+ for (String mechanism : expectedMechanisms)
+ {
+ assertTrue("Mechanism " + mechanism + " is not found", mechanisms.contains(mechanism));
+ }
+ }
+
+}
diff --git a/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/StructureRestTest.java b/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/StructureRestTest.java
new file mode 100644
index 0000000000..b01e1d44b8
--- /dev/null
+++ b/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/StructureRestTest.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.server.management.plugin.servlet.rest;
+
+import java.util.List;
+import java.util.Map;
+
+public class StructureRestTest extends QpidRestTestCase
+{
+
+ public void testGet() throws Exception
+ {
+ Map<String, Object> structure = getJsonAsMap("/rest/structure");
+ assertNotNull("Structure data cannot be null", structure);
+ assertNode(structure, "Broker");
+
+ @SuppressWarnings("unchecked")
+ List<Map<String, Object>> virtualhosts = (List<Map<String, Object>>) structure.get("virtualhosts");
+ assertEquals("Unexpected number of virtual hosts", 3, virtualhosts.size());
+
+ @SuppressWarnings("unchecked")
+ List<Map<String, Object>> ports = (List<Map<String, Object>>) structure.get("ports");
+ assertEquals("Unexpected number of ports", 2, ports.size());
+
+ @SuppressWarnings("unchecked")
+ List<Map<String, Object>> providers = (List<Map<String, Object>>) structure.get("authenticationproviders");
+ assertEquals("Unexpected number of authentication providers", 1, providers.size());
+
+ for (String hostName : EXPECTED_HOSTS)
+ {
+ Map<String, Object> host = find("name", hostName, virtualhosts);
+ assertNotNull("Host " + hostName + " is not found ", host);
+ assertNode(host, hostName);
+
+ @SuppressWarnings("unchecked")
+ List<Map<String, Object>> queues = (List<Map<String, Object>>) host.get("queues");
+ assertNotNull("Host " + hostName + " queues are not found ", queues);
+ for (String queueName : EXPECTED_QUEUES)
+ {
+ Map<String, Object> queue = find("name", queueName, queues);
+ assertNotNull(hostName + " queue " + queueName + " is not found ", queue);
+ assertNode(queue, queueName);
+
+ @SuppressWarnings("unchecked")
+ List<Map<String, Object>> bindings = (List<Map<String, Object>>) queue.get("bindings");
+ assertNotNull(hostName + " queue " + queueName + " bindings are not found ", queues);
+ for (Map<String, Object> binding : bindings)
+ {
+ assertNode(binding, queueName);
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ List<Map<String, Object>> exchanges = (List<Map<String, Object>>) host.get("exchanges");
+ assertNotNull("Host " + hostName + " exchanges are not found ", exchanges);
+ for (String exchangeName : EXPECTED_EXCHANGES)
+ {
+ Map<String, Object> exchange = find("name", exchangeName, exchanges);
+ assertNotNull("Exchange " + exchangeName + " is not found ", exchange);
+ assertNode(exchange, exchangeName);
+ if ("amq.direct".equalsIgnoreCase(exchangeName) || "<<default>>".equalsIgnoreCase(exchangeName))
+ {
+ @SuppressWarnings("unchecked")
+ List<Map<String, Object>> bindings = (List<Map<String, Object>>) exchange.get("bindings");
+ assertNotNull(hostName + " exchange " + exchangeName + " bindings are not found ", bindings);
+ for (String queueName : EXPECTED_QUEUES)
+ {
+ Map<String, Object> binding = find("name", queueName, bindings);
+ assertNotNull(hostName + " exchange " + exchangeName + " binding " + queueName + " is not found", binding);
+ assertNode(binding, queueName);
+ }
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ List<Map<String, Object>> aliases = (List<Map<String, Object>>) host.get("virtualhostaliases");
+ assertNotNull("Host " + hostName + " aliaces are not found ", aliases);
+ assertEquals("Unexpected aliaces size", 1, aliases.size());
+ assertNode(aliases.get(0), hostName);
+ }
+
+ int[] expectedPorts = { getPort(), getHttpPort() };
+ for (int port : expectedPorts)
+ {
+ String portName = "0.0.0.0:" + port;
+ Map<String, Object> portData = find("name", portName, ports);
+ assertNotNull("Port " + portName + " is not found ", portData);
+ assertNode(portData, portName);
+ }
+ }
+
+ private void assertNode(Map<String, Object> node, String name)
+ {
+ assertEquals("Unexpected name", name, node.get("name"));
+ assertNotNull("Unexpected id", node.get("id"));
+ }
+}
diff --git a/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/UserRestTest.java b/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/UserRestTest.java
new file mode 100644
index 0000000000..378b349a99
--- /dev/null
+++ b/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/UserRestTest.java
@@ -0,0 +1,92 @@
+package org.apache.qpid.server.management.plugin.servlet.rest;
+
+import java.net.HttpURLConnection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.qpid.server.model.User;
+
+public class UserRestTest extends QpidRestTestCase
+{
+ public void testGet() throws Exception
+ {
+ List<Map<String, Object>> users = getJsonAsList("/rest/user");
+ assertNotNull("Users cannot be null", users);
+ assertTrue("Unexpected number of users", users.size() > 1);
+ for (Map<String, Object> user : users)
+ {
+ assertUser(user);
+ }
+ }
+
+ public void testGetUserByName() throws Exception
+ {
+ List<Map<String, Object>> users = getJsonAsList("/rest/user");
+ assertNotNull("Users cannot be null", users);
+ assertTrue("Unexpected number of users", users.size() > 1);
+ for (Map<String, Object> user : users)
+ {
+ assertNotNull("Attribute " + User.ID, user.get(User.ID));
+ String userName = (String) user.get(User.NAME);
+ assertNotNull("Attribute " + User.NAME, userName);
+ Map<String, Object> userDetails = getJsonAsSingletonList("/rest/user/PrincipalDatabaseAuthenticationManager/"
+ + userName);
+ assertUser(userDetails);
+ assertEquals("Unexpected user name", userName, userDetails.get(User.NAME));
+ }
+ }
+
+ public void testPut() throws Exception
+ {
+ String userName = getTestName();
+ HttpURLConnection connection = openManagementConection("/rest/user/PrincipalDatabaseAuthenticationManager/"
+ + userName, "PUT");
+
+ Map<String, Object> userData = new HashMap<String, Object>();
+ userData.put(User.NAME, userName);
+ userData.put(User.PASSWORD, userName);
+
+ writeJsonRequest(connection, userData);
+ assertEquals("Unexpected response code", 201, connection.getResponseCode());
+
+ connection.disconnect();
+
+ Map<String, Object> userDetails = getJsonAsSingletonList("/rest/user/PrincipalDatabaseAuthenticationManager/"
+ + userName);
+ assertUser(userDetails);
+ assertEquals("Unexpected user name", userName, userDetails.get(User.NAME));
+ }
+
+ public void testDelete() throws Exception
+ {
+ // add user
+ String userName = getTestName();
+ HttpURLConnection connection = openManagementConection("/rest/user/PrincipalDatabaseAuthenticationManager/"
+ + userName, "PUT");
+
+ Map<String, Object> userData = new HashMap<String, Object>();
+ userData.put(User.NAME, userName);
+ userData.put(User.PASSWORD, userName);
+
+ writeJsonRequest(connection, userData);
+ assertEquals("Unexpected response code", 201, connection.getResponseCode());
+ connection.disconnect();
+
+ Map<String, Object> userDetails = getJsonAsSingletonList("/rest/user/PrincipalDatabaseAuthenticationManager/"
+ + userName);
+ String id = (String) userDetails.get(User.ID);
+
+ connection = openManagementConection("/rest/user/PrincipalDatabaseAuthenticationManager?id=" + id, "DELETE");
+ connection.connect();
+ assertEquals("Unexpected response code", 200, connection.getResponseCode());
+ List<Map<String, Object>> users = getJsonAsList("/rest/user/PrincipalDatabaseAuthenticationManager/" + userName);
+ assertEquals("User should be deleted", 0, users.size());
+ }
+
+ private void assertUser(Map<String, Object> user)
+ {
+ assertNotNull("Attribute " + User.ID, user.get(User.ID));
+ assertNotNull("Attribute " + User.NAME, user.get(User.NAME));
+ }
+}
diff --git a/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/VirtualHostRestTest.java b/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/VirtualHostRestTest.java
new file mode 100644
index 0000000000..17f1aaaf7b
--- /dev/null
+++ b/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/VirtualHostRestTest.java
@@ -0,0 +1,434 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.management.plugin.servlet.rest;
+
+import java.io.IOException;
+import java.net.HttpURLConnection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.jms.Session;
+
+import org.apache.qpid.client.AMQConnection;
+import org.apache.qpid.server.model.Exchange;
+import org.apache.qpid.server.model.Queue;
+import org.apache.qpid.server.model.VirtualHost;
+import org.apache.qpid.server.queue.AMQQueueFactory;
+import org.codehaus.jackson.JsonGenerationException;
+import org.codehaus.jackson.map.JsonMappingException;
+
+public class VirtualHostRestTest extends QpidRestTestCase
+{
+ private static final String VIRTUALHOST_EXCHANGES_ATTRIBUTE = "exchanges";
+ public static final String VIRTUALHOST_QUEUES_ATTRIBUTE = "queues";
+ public static final String VIRTUALHOST_CONNECTIONS_ATTRIBUTE = "connections";
+
+ private AMQConnection _connection;
+
+ public void testGet() throws Exception
+ {
+ List<Map<String, Object>> hosts = getJsonAsList("/rest/virtualhost/");
+ assertNotNull("Hosts data cannot be null", hosts);
+ assertEquals("Unexpected number of hosts", 3, hosts.size());
+ for (String hostName : EXPECTED_HOSTS)
+ {
+ Map<String, Object> host = find("name", hostName, hosts);
+ Asserts.assertVirtualHost(hostName, host);
+ }
+ }
+
+ public void testGetHost() throws Exception
+ {
+ // create AMQP connection to get connection JSON details
+ _connection = (AMQConnection) getConnection();
+ _connection.createSession(true, Session.SESSION_TRANSACTED);
+
+ Map<String, Object> hostDetails = getJsonAsSingletonList("/rest/virtualhost/test");
+ Asserts.assertVirtualHost("test", hostDetails);
+
+ @SuppressWarnings("unchecked")
+ Map<String, Object> statistics = (Map<String, Object>) hostDetails.get(Asserts.STATISTICS_ATTRIBUTE);
+ assertEquals("Unexpected number of exchanges in statistics", 6, statistics.get(VirtualHost.EXCHANGE_COUNT));
+ assertEquals("Unexpected number of queues in statistics", 2, statistics.get(VirtualHost.QUEUE_COUNT));
+ assertEquals("Unexpected number of connections in statistics", 1, statistics.get(VirtualHost.CONNECTION_COUNT));
+
+ @SuppressWarnings("unchecked")
+ List<Map<String, Object>> exchanges = (List<Map<String, Object>>) hostDetails.get(VIRTUALHOST_EXCHANGES_ATTRIBUTE);
+ assertEquals("Unexpected number of exchanges", 6, exchanges.size());
+ Asserts.assertDurableExchange("amq.fanout", "fanout", find(Exchange.NAME, "amq.fanout", exchanges));
+ Asserts.assertDurableExchange("qpid.management", "management", find(Exchange.NAME, "qpid.management", exchanges));
+ Asserts.assertDurableExchange("amq.topic", "topic", find(Exchange.NAME, "amq.topic", exchanges));
+ Asserts.assertDurableExchange("amq.direct", "direct", find(Exchange.NAME, "amq.direct", exchanges));
+ Asserts.assertDurableExchange("amq.match", "headers", find(Exchange.NAME, "amq.match", exchanges));
+ Asserts.assertDurableExchange("<<default>>", "direct", find(Exchange.NAME, "<<default>>", exchanges));
+
+ @SuppressWarnings("unchecked")
+ List<Map<String, Object>> queues = (List<Map<String, Object>>) hostDetails.get(VIRTUALHOST_QUEUES_ATTRIBUTE);
+ assertEquals("Unexpected number of queues", 2, queues.size());
+ Map<String, Object> queue = find(Queue.NAME, "queue", queues);
+ Map<String, Object> ping = find(Queue.NAME, "ping", queues);
+ Asserts.assertQueue("queue", "standard", queue);
+ Asserts.assertQueue("ping", "standard", ping);
+ assertEquals("Unexpected value of queue attribute " + Queue.DURABLE, Boolean.FALSE, queue.get(Queue.DURABLE));
+ assertEquals("Unexpected value of queue attribute " + Queue.DURABLE, Boolean.FALSE, ping.get(Queue.DURABLE));
+
+ @SuppressWarnings("unchecked")
+ List<Map<String, Object>> connections = (List<Map<String, Object>>) hostDetails
+ .get(VIRTUALHOST_CONNECTIONS_ATTRIBUTE);
+ assertEquals("Unexpected number of connections", 1, connections.size());
+ Asserts.assertConnection(connections.get(0), _connection);
+ }
+
+ public void testPutCreateQueue() throws Exception
+ {
+ String queueName = getTestQueueName();
+
+ createQueue(queueName + "-standard", "standard", null);
+
+ Map<String, Object> sortedQueueAttributes = new HashMap<String, Object>();
+ sortedQueueAttributes.put(Queue.SORT_KEY, "sortme");
+ createQueue(queueName + "-sorted", "sorted", sortedQueueAttributes);
+
+ Map<String, Object> priorityQueueAttributes = new HashMap<String, Object>();
+ priorityQueueAttributes.put(Queue.PRIORITIES, 10);
+ createQueue(queueName + "-priority", "priority", priorityQueueAttributes);
+
+ Map<String, Object> lvqQueueAttributes = new HashMap<String, Object>();
+ lvqQueueAttributes.put(Queue.LVQ_KEY, "LVQ");
+ createQueue(queueName + "-lvq", "lvq", lvqQueueAttributes);
+
+ Map<String, Object> hostDetails = getJsonAsSingletonList("/rest/virtualhost/test");
+
+ @SuppressWarnings("unchecked")
+ List<Map<String, Object>> queues = (List<Map<String, Object>>) hostDetails.get(VirtualHostRestTest.VIRTUALHOST_QUEUES_ATTRIBUTE);
+ Map<String, Object> standardQueue = find(Queue.NAME, queueName + "-standard" , queues);
+ Map<String, Object> sortedQueue = find(Queue.NAME, queueName + "-sorted" , queues);
+ Map<String, Object> priorityQueue = find(Queue.NAME, queueName + "-priority" , queues);
+ Map<String, Object> lvqQueue = find(Queue.NAME, queueName + "-lvq" , queues);
+
+ Asserts.assertQueue(queueName + "-standard", "standard", standardQueue);
+ Asserts.assertQueue(queueName + "-sorted", "sorted", sortedQueue);
+ Asserts.assertQueue(queueName + "-priority", "priority", priorityQueue);
+ Asserts.assertQueue(queueName + "-lvq", "lvq", lvqQueue);
+
+ assertEquals("Unexpected value of queue attribute " + Queue.DURABLE, Boolean.TRUE, standardQueue.get(Queue.DURABLE));
+ assertEquals("Unexpected value of queue attribute " + Queue.DURABLE, Boolean.TRUE, sortedQueue.get(Queue.DURABLE));
+ assertEquals("Unexpected value of queue attribute " + Queue.DURABLE, Boolean.TRUE, priorityQueue.get(Queue.DURABLE));
+ assertEquals("Unexpected value of queue attribute " + Queue.DURABLE, Boolean.TRUE, lvqQueue.get(Queue.DURABLE));
+
+ assertEquals("Unexpected sorted key attribute", "sortme", sortedQueue.get(Queue.SORT_KEY));
+ assertEquals("Unexpected lvq key attribute", "LVQ", lvqQueue.get(Queue.LVQ_KEY));
+ assertEquals("Unexpected priorities key attribute", 10, priorityQueue.get(Queue.PRIORITIES));
+ }
+
+ public void testPutCreateExchange() throws Exception
+ {
+ String exchangeName = getTestName();
+
+ createExchange(exchangeName + "-direct", "direct");
+ createExchange(exchangeName + "-topic", "topic");
+ createExchange(exchangeName + "-headers", "headers");
+ createExchange(exchangeName + "-fanout", "fanout");
+
+ Map<String, Object> hostDetails = getJsonAsSingletonList("/rest/virtualhost/test");
+
+ @SuppressWarnings("unchecked")
+ List<Map<String, Object>> exchanges = (List<Map<String, Object>>) hostDetails.get(VirtualHostRestTest.VIRTUALHOST_EXCHANGES_ATTRIBUTE);
+ Map<String, Object> directExchange = find(Queue.NAME, exchangeName + "-direct" , exchanges);
+ Map<String, Object> topicExchange = find(Queue.NAME, exchangeName + "-topic" , exchanges);
+ Map<String, Object> headersExchange = find(Queue.NAME, exchangeName + "-headers" , exchanges);
+ Map<String, Object> fanoutExchange = find(Queue.NAME, exchangeName + "-fanout" , exchanges);
+
+ Asserts.assertDurableExchange(exchangeName + "-direct", "direct", directExchange);
+ Asserts.assertDurableExchange(exchangeName + "-topic", "topic", topicExchange);
+ Asserts.assertDurableExchange(exchangeName + "-headers", "headers", headersExchange);
+ Asserts.assertDurableExchange(exchangeName + "-fanout", "fanout", fanoutExchange);
+
+ assertEquals("Unexpected value of queue attribute " + Queue.DURABLE, Boolean.TRUE, directExchange.get(Queue.DURABLE));
+ assertEquals("Unexpected value of queue attribute " + Queue.DURABLE, Boolean.TRUE, topicExchange.get(Queue.DURABLE));
+ assertEquals("Unexpected value of queue attribute " + Queue.DURABLE, Boolean.TRUE, headersExchange.get(Queue.DURABLE));
+ assertEquals("Unexpected value of queue attribute " + Queue.DURABLE, Boolean.TRUE, fanoutExchange.get(Queue.DURABLE));
+
+ }
+
+ public void testPutCreateLVQWithoutKey() throws Exception
+ {
+ String queueName = getTestQueueName()+ "-lvq";
+ createQueue(queueName, "lvq", null);
+
+ Map<String, Object> hostDetails = getJsonAsSingletonList("/rest/virtualhost/test");
+
+ @SuppressWarnings("unchecked")
+ List<Map<String, Object>> queues = (List<Map<String, Object>>) hostDetails.get(VirtualHostRestTest.VIRTUALHOST_QUEUES_ATTRIBUTE);
+ Map<String, Object> lvqQueue = find(Queue.NAME, queueName , queues);
+
+ Asserts.assertQueue(queueName , "lvq", lvqQueue);
+ assertEquals("Unexpected value of queue attribute " + Queue.DURABLE, Boolean.TRUE, lvqQueue.get(Queue.DURABLE));
+ assertEquals("Unexpected lvq key attribute", AMQQueueFactory.QPID_LVQ_KEY, lvqQueue.get(Queue.LVQ_KEY));
+ }
+
+ public void testPutCreateSortedQueueWithoutKey() throws Exception
+ {
+ String queueName = getTestQueueName() + "-sorted";
+ int responseCode = tryCreateQueue(queueName, "sorted", null);
+ assertEquals("Unexpected response code", 409, responseCode);
+
+ Map<String, Object> hostDetails = getJsonAsSingletonList("/rest/virtualhost/test");
+
+ @SuppressWarnings("unchecked")
+ List<Map<String, Object>> queues = (List<Map<String, Object>>) hostDetails.get(VirtualHostRestTest.VIRTUALHOST_QUEUES_ATTRIBUTE);
+ Map<String, Object> testQueue = find(Queue.NAME, queueName , queues);
+
+ assertNull("Sorted queue without a key was created ", testQueue);
+ }
+
+ public void testPutCreatePriorityQueueWithoutKey() throws Exception
+ {
+ String queueName = getTestQueueName()+ "-priority";
+ createQueue(queueName, "priority", null);
+
+ Map<String, Object> hostDetails = getJsonAsSingletonList("/rest/virtualhost/test");
+
+ @SuppressWarnings("unchecked")
+ List<Map<String, Object>> queues = (List<Map<String, Object>>) hostDetails.get(VirtualHostRestTest.VIRTUALHOST_QUEUES_ATTRIBUTE);
+ Map<String, Object> priorityQueue = find(Queue.NAME, queueName , queues);
+
+ Asserts.assertQueue(queueName , "priority", priorityQueue);
+ assertEquals("Unexpected value of queue attribute " + Queue.DURABLE, Boolean.TRUE, priorityQueue.get(Queue.DURABLE));
+ assertEquals("Unexpected number of priorities", 10, priorityQueue.get(Queue.PRIORITIES));
+ }
+
+ public void testPutCreateStandardQueueWithoutType() throws Exception
+ {
+ String queueName = getTestQueueName();
+ createQueue(queueName, null, null);
+
+ Map<String, Object> hostDetails = getJsonAsSingletonList("/rest/virtualhost/test");
+
+ @SuppressWarnings("unchecked")
+ List<Map<String, Object>> queues = (List<Map<String, Object>>) hostDetails.get(VirtualHostRestTest.VIRTUALHOST_QUEUES_ATTRIBUTE);
+ Map<String, Object> queue = find(Queue.NAME, queueName , queues);
+
+ Asserts.assertQueue(queueName , "standard", queue);
+ }
+
+ public void testPutCreateQueueOfUnsupportedType() throws Exception
+ {
+ String queueName = getTestQueueName();
+ int responseCode = tryCreateQueue(queueName, "unsupported", null);
+ assertEquals("Unexpected response code", 409, responseCode);
+
+ Map<String, Object> hostDetails = getJsonAsSingletonList("/rest/virtualhost/test");
+
+ @SuppressWarnings("unchecked")
+ List<Map<String, Object>> queues = (List<Map<String, Object>>) hostDetails.get(VirtualHostRestTest.VIRTUALHOST_QUEUES_ATTRIBUTE);
+ Map<String, Object> queue = find(Queue.NAME, queueName , queues);
+
+ assertNull("Queue of unsupported type was created", queue);
+ }
+
+ public void testDeleteQueue() throws Exception
+ {
+ String queueName = getTestQueueName();
+ createQueue(queueName, null, null);
+
+ HttpURLConnection connection = openManagementConection("/rest/queue/test/" + queueName, "DELETE");
+ connection.connect();
+ assertEquals("Unexpected response code", 200, connection.getResponseCode());
+ List<Map<String, Object>> queues = getJsonAsList("/rest/queue/test/" + queueName);
+ assertEquals("Queue should be deleted", 0, queues.size());
+ }
+
+ public void testDeleteQueueById() throws Exception
+ {
+ String queueName = getTestQueueName();
+ createQueue(queueName, null, null);
+ Map<String, Object> queueDetails = getJsonAsSingletonList("/rest/queue/test/" + queueName);
+
+ HttpURLConnection connection = openManagementConection("/rest/queue/test?id=" + queueDetails.get(Queue.ID), "DELETE");
+ connection.connect();
+ assertEquals("Unexpected response code", 200, connection.getResponseCode());
+ List<Map<String, Object>> queues = getJsonAsList("/rest/queue/test/" + queueName);
+ assertEquals("Queue should be deleted", 0, queues.size());
+ }
+
+ public void testDeleteExchange() throws Exception
+ {
+ String exchangeName = getTestName();
+ createExchange(exchangeName, "direct");
+
+ HttpURLConnection connection = openManagementConection("/rest/exchange/test/" + exchangeName, "DELETE");
+ connection.connect();
+ assertEquals("Unexpected response code", 200, connection.getResponseCode());
+ List<Map<String, Object>> queues = getJsonAsList("/rest/exchange/test/" + exchangeName);
+ assertEquals("Exchange should be deleted", 0, queues.size());
+ }
+
+ public void testDeleteExchangeById() throws Exception
+ {
+ String exchangeName = getTestName();
+ createExchange(exchangeName, "direct");
+ Map<String, Object> echangeDetails = getJsonAsSingletonList("/rest/exchange/test/" + exchangeName);
+
+ HttpURLConnection connection = openManagementConection("/rest/exchange/test?id=" + echangeDetails.get(Exchange.ID), "DELETE");
+ connection.connect();
+ assertEquals("Unexpected response code", 200, connection.getResponseCode());
+ List<Map<String, Object>> queues = getJsonAsList("/rest/exchange/test/" + exchangeName);
+ assertEquals("Exchange should be deleted", 0, queues.size());
+ }
+
+ public void testPutCreateQueueWithAttributes() throws Exception
+ {
+ String queueName = getTestQueueName();
+
+ Map<String, Object> attributes = new HashMap<String, Object>();
+ attributes.put(Queue.ALERT_REPEAT_GAP, 1000);
+ attributes.put(Queue.ALERT_THRESHOLD_MESSAGE_AGE, 3600000);
+ attributes.put(Queue.ALERT_THRESHOLD_MESSAGE_SIZE, 1000000000);
+ attributes.put(Queue.ALERT_THRESHOLD_QUEUE_DEPTH_MESSAGES, 800);
+ attributes.put(Queue.MAXIMUM_DELIVERY_ATTEMPTS, 15);
+ attributes.put(Queue.QUEUE_FLOW_CONTROL_SIZE_BYTES, 2000000000);
+ attributes.put(Queue.QUEUE_FLOW_RESUME_SIZE_BYTES, 1500000000);
+
+ createQueue(queueName + "-standard", "standard", attributes);
+
+ Map<String, Object> sortedQueueAttributes = new HashMap<String, Object>();
+ sortedQueueAttributes.putAll(attributes);
+ sortedQueueAttributes.put(Queue.SORT_KEY, "sortme");
+ createQueue(queueName + "-sorted", "sorted", sortedQueueAttributes);
+
+ Map<String, Object> priorityQueueAttributes = new HashMap<String, Object>();
+ priorityQueueAttributes.putAll(attributes);
+ priorityQueueAttributes.put(Queue.PRIORITIES, 10);
+ createQueue(queueName + "-priority", "priority", priorityQueueAttributes);
+
+ Map<String, Object> lvqQueueAttributes = new HashMap<String, Object>();
+ lvqQueueAttributes.putAll(attributes);
+ lvqQueueAttributes.put(Queue.LVQ_KEY, "LVQ");
+ createQueue(queueName + "-lvq", "lvq", lvqQueueAttributes);
+
+ Map<String, Object> hostDetails = getJsonAsSingletonList("/rest/virtualhost/test");
+
+ @SuppressWarnings("unchecked")
+ List<Map<String, Object>> queues = (List<Map<String, Object>>) hostDetails.get(VirtualHostRestTest.VIRTUALHOST_QUEUES_ATTRIBUTE);
+ Map<String, Object> standardQueue = find(Queue.NAME, queueName + "-standard" , queues);
+ Map<String, Object> sortedQueue = find(Queue.NAME, queueName + "-sorted" , queues);
+ Map<String, Object> priorityQueue = find(Queue.NAME, queueName + "-priority" , queues);
+ Map<String, Object> lvqQueue = find(Queue.NAME, queueName + "-lvq" , queues);
+
+ attributes.put(Queue.DURABLE, Boolean.TRUE);
+ Asserts.assertQueue(queueName + "-standard", "standard", standardQueue, attributes);
+ Asserts.assertQueue(queueName + "-sorted", "sorted", sortedQueue, attributes);
+ Asserts.assertQueue(queueName + "-priority", "priority", priorityQueue, attributes);
+ Asserts.assertQueue(queueName + "-lvq", "lvq", lvqQueue, attributes);
+
+ assertEquals("Unexpected sorted key attribute", "sortme", sortedQueue.get(Queue.SORT_KEY));
+ assertEquals("Unexpected lvq key attribute", "LVQ", lvqQueue.get(Queue.LVQ_KEY));
+ assertEquals("Unexpected priorities key attribute", 10, priorityQueue.get(Queue.PRIORITIES));
+ }
+
+ @SuppressWarnings("unchecked")
+ public void testCreateQueueWithDLQEnabled() throws Exception
+ {
+ String queueName = getTestQueueName();
+
+ Map<String, Object> attributes = new HashMap<String, Object>();
+ attributes.put(AMQQueueFactory.X_QPID_DLQ_ENABLED, true);
+
+ //verify the starting state
+ Map<String, Object> hostDetails = getJsonAsSingletonList("/rest/virtualhost/test");
+ List<Map<String, Object>> queues = (List<Map<String, Object>>) hostDetails.get(VirtualHostRestTest.VIRTUALHOST_QUEUES_ATTRIBUTE);
+ List<Map<String, Object>> exchanges = (List<Map<String, Object>>) hostDetails.get(VirtualHostRestTest.VIRTUALHOST_EXCHANGES_ATTRIBUTE);
+
+ assertNull("queue should not have already been present", find(Queue.NAME, queueName , queues));
+ assertNull("queue should not have already been present", find(Queue.NAME, queueName + "_DLQ" , queues));
+ assertNull("exchange should not have already been present", find(Exchange.NAME, queueName + "_DLE" , exchanges));
+
+ //create the queue
+ createQueue(queueName, "standard", attributes);
+
+ //verify the new queue, as well as the DLQueue and DLExchange have been created
+ hostDetails = getJsonAsSingletonList("/rest/virtualhost/test");
+ queues = (List<Map<String, Object>>) hostDetails.get(VirtualHostRestTest.VIRTUALHOST_QUEUES_ATTRIBUTE);
+ exchanges = (List<Map<String, Object>>) hostDetails.get(VirtualHostRestTest.VIRTUALHOST_EXCHANGES_ATTRIBUTE);
+
+ Map<String, Object> queue = find(Queue.NAME, queueName , queues);
+ Map<String, Object> dlqQueue = find(Queue.NAME, queueName + "_DLQ" , queues);
+ Map<String, Object> dlExchange = find(Exchange.NAME, queueName + "_DLE" , exchanges);
+ assertNotNull("queue should not have been present", queue);
+ assertNotNull("queue should not have been present", dlqQueue);
+ assertNotNull("exchange should not have been present", dlExchange);
+
+ //verify that the alternate exchange is set as expected on the new queue
+ Map<String, Object> queueAttributes = new HashMap<String, Object>();
+ queueAttributes.put(Queue.ALTERNATE_EXCHANGE, queueName + "_DLE");
+
+ Asserts.assertQueue(queueName, "standard", queue, queueAttributes);
+ Asserts.assertQueue(queueName, "standard", queue, null);
+ }
+
+ private void createExchange(String exchangeName, String exchangeType) throws IOException
+ {
+ HttpURLConnection connection = openManagementConection("/rest/exchange/test/" + exchangeName, "PUT");
+
+ Map<String, Object> queueData = new HashMap<String, Object>();
+ queueData.put(Exchange.NAME, exchangeName);
+ queueData.put(Exchange.DURABLE, Boolean.TRUE);
+ queueData.put(Exchange.TYPE, exchangeType);
+
+ writeJsonRequest(connection, queueData);
+ assertEquals("Unexpected response code", 201, connection.getResponseCode());
+
+ connection.disconnect();
+ }
+
+ private void createQueue(String queueName, String queueType, Map<String, Object> attributes) throws IOException,
+ JsonGenerationException, JsonMappingException
+ {
+ int responseCode = tryCreateQueue(queueName, queueType, attributes);
+ assertEquals("Unexpected response code", 201, responseCode);
+ }
+
+ private int tryCreateQueue(String queueName, String queueType, Map<String, Object> attributes) throws IOException,
+ JsonGenerationException, JsonMappingException
+ {
+ HttpURLConnection connection = openManagementConection("/rest/queue/test/" + queueName, "PUT");
+
+ Map<String, Object> queueData = new HashMap<String, Object>();
+ queueData.put(Queue.NAME, queueName);
+ queueData.put(Queue.DURABLE, Boolean.TRUE);
+ if (queueType != null)
+ {
+ queueData.put(Queue.TYPE, queueType);
+ }
+ if (attributes != null)
+ {
+ queueData.putAll(attributes);
+ }
+
+ writeJsonRequest(connection, queueData);
+ int responseCode = connection.getResponseCode();
+ connection.disconnect();
+ return responseCode;
+ }
+
+}
diff --git a/java/broker-plugins/management-jmx/MANIFEST.MF b/java/broker-plugins/management-jmx/MANIFEST.MF
new file mode 100644
index 0000000000..b18ec1ace7
--- /dev/null
+++ b/java/broker-plugins/management-jmx/MANIFEST.MF
@@ -0,0 +1,66 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Qpid Broker-Plugins Management JMX
+Bundle-SymbolicName: broker-plugins-management-jmx
+Bundle-Description: JMX management 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.jmx.JMXActivator
+Bundle-RequiredExecutionEnvironment: JavaSE-1.6
+Bundle-ClassPath: .
+Bundle-ActivationPolicy: lazy
+Import-Package: org.apache.qpid,
+ org.apache.qpid.framing,
+ org.apache.qpid.protocol,
+ org.apache.qpid.common,
+ org.apache.qpid.management.common.mbeans,
+ org.apache.qpid.management.common.mbeans.annotations,
+ org.apache.qpid.server.security.auth,
+ org.apache.qpid.server.security.auth.manager,
+ org.apache.qpid.server.security.auth.rmi,
+ org.apache.qpid.server.security.auth.sasl,
+ org.apache.qpid.server.binding,
+ org.apache.qpid.server.exchange,
+ org.apache.qpid.server.logging,
+ org.apache.qpid.server.logging.log4j,
+ org.apache.qpid.server.logging.actors,
+ org.apache.qpid.server.logging.messages,
+ org.apache.qpid.server.message,
+ org.apache.qpid.server.model,
+ org.apache.qpid.server.model.adapter,
+ org.apache.qpid.server.model.impl,
+ org.apache.qpid.server.configuration,
+ org.apache.qpid.server.configuration.plugins,
+ org.apache.qpid.server.connection,
+ org.apache.qpid.server.plugins,
+ org.apache.qpid.server.protocol,
+ org.apache.qpid.server.queue,
+ org.apache.qpid.server.registry,
+ org.apache.qpid.server.security,
+ org.apache.qpid.server.security.access,
+ org.apache.qpid.server.stats,
+ org.apache.qpid.server.virtualhost,
+ org.apache.qpid.util,
+ org.apache.commons.codec;version=1.3.0,
+ org.apache.commons.codec.binary;version=1.3.0,
+ 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.lang.time;version=1.0.0,
+ org.apache.log4j;version=1.2.16,
+ org.codehaus.jackson;version=1.9.0,
+ org.codehaus.jackson.map;version=1.9.0,
+ javax.management.remote.rmi,
+ javax.management.remote,
+ javax.servlet,
+ javax.servlet.http,
+ javax.management;version=1.0.0,
+ javax.management.monitor;version=1.0.0,
+ javax.management.openmbean;version=1.0.0,
+ javax.security.auth.login;version=1.0.0,
+ javax.security.auth;version=1.0.0,
+ javax.rmi.ssl;version=1.0.0,
+ org.osgi.util.tracker;version=1.0.0,
+ org.osgi.framework;version=1.3
+Export-Package: org.apache.qpid.server.jmx;uses:="org.osgi.framework"
diff --git a/java/broker-plugins/management-jmx/build.xml b/java/broker-plugins/management-jmx/build.xml
new file mode 100644
index 0000000000..fa50b8467d
--- /dev/null
+++ b/java/broker-plugins/management-jmx/build.xml
@@ -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.
+ -->
+<project name="Qpid Broker-Plugins Management JMX" default="build">
+
+ <condition property="systests.optional.depends" value="bdbstore" else="">
+ <or>
+ <and>
+ <contains string="${modules.opt}" substring="bdbstore"/>
+ <contains string="${profile}" substring="bdb"/>
+ </and>
+ <and>
+ <istrue value="${optional}"/>
+ <contains string="${profile}" substring="bdb"/>
+ </and>
+ </or>
+ </condition>
+
+ <property name="module.depends" value="common broker management/common" />
+ <property name="module.test.depends" value="systests test broker/test common/test management/common client ${systests.optional.depends}" />
+
+ <property name="module.manifest" value="MANIFEST.MF" />
+ <property name="module.plugin" value="true" />
+ <property name="module.genpom" value="true"/>
+ <property name="module.genpom.args" value="-Sqpid-common=provided -Sqpid-broker=provided -Sqpid-management-common=provided"/>
+
+ <property name="broker-plugins-management-jmx.libs" value=""/>
+
+ <import file="../../module.xml" />
+
+ <target name="bundle" depends="bundle-tasks" />
+</project>
diff --git a/java/broker/src/main/java/org/apache/qpid/server/management/AMQManagedObject.java b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/AMQManagedObject.java
index 5c57c01f6e..5c39a0c26a 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/management/AMQManagedObject.java
+++ b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/AMQManagedObject.java
@@ -18,11 +18,9 @@
* under the License.
*
*/
-package org.apache.qpid.server.management;
+package org.apache.qpid.server.jmx;
-import org.apache.qpid.server.logging.LogActor;
-import org.apache.qpid.server.logging.actors.CurrentActor;
-import org.apache.qpid.server.logging.actors.ManagementActor;
+import java.util.concurrent.atomic.AtomicLong;
import javax.management.ListenerNotFoundException;
import javax.management.NotCompliantMBeanException;
@@ -32,7 +30,7 @@ import javax.management.NotificationFilter;
import javax.management.NotificationListener;
/**
- * This class provides additinal feature of Notification Broadcaster to the
+ * This class provides additional feature of Notification Broadcaster to the
* DefaultManagedObject.
* @author Bhupendra Bhardwaj
* @version 0.1
@@ -40,19 +38,17 @@ import javax.management.NotificationListener;
public abstract class AMQManagedObject extends DefaultManagedObject
implements NotificationBroadcaster
{
- private NotificationBroadcasterSupport _broadcaster = new NotificationBroadcasterSupport();
+ private final NotificationBroadcasterSupport _broadcaster = new NotificationBroadcasterSupport();
- private long _notificationSequenceNumber = 0;
+ private AtomicLong _notificationSequenceNumber = new AtomicLong();
- private LogActor _logActor;
-
- protected AMQManagedObject(Class<?> managementInterface, String typeName)
+ protected AMQManagedObject(Class<?> managementInterface, String typeName, ManagedObjectRegistry registry)
throws NotCompliantMBeanException
{
- super(managementInterface, typeName);
+ super(managementInterface, typeName, registry);
// CurrentActor will be defined as these objects are created during
// broker startup.
- _logActor = new ManagementActor(CurrentActor.get().getRootMessageLogger());
+
}
// notification broadcaster implementation
@@ -79,27 +75,10 @@ public abstract class AMQManagedObject extends DefaultManagedObject
return _broadcaster;
}
- /**
- * sequence number for notifications
- */
- protected long getNotificationSequenceNumber()
- {
- return _notificationSequenceNumber;
- }
-
- protected void setNotificationSequenceNumber(long notificationSequenceNumber)
- {
- _notificationSequenceNumber = notificationSequenceNumber;
- }
-
protected long incrementAndGetSequenceNumber()
{
- return ++_notificationSequenceNumber;
+ return _notificationSequenceNumber.incrementAndGet();
}
- protected LogActor getLogActor()
- {
- return _logActor;
- }
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/management/DefaultManagedObject.java b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/DefaultManagedObject.java
index 10d7503800..4446f96802 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/management/DefaultManagedObject.java
+++ b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/DefaultManagedObject.java
@@ -18,12 +18,10 @@
* under the License.
*
*/
-package org.apache.qpid.server.management;
+package org.apache.qpid.server.jmx;
import org.apache.log4j.Logger;
-import org.apache.qpid.server.registry.ApplicationRegistry;
-
import javax.management.JMException;
import javax.management.MBeanInfo;
import javax.management.MBeanNotificationInfo;
@@ -49,15 +47,21 @@ public abstract class DefaultManagedObject extends StandardMBean implements Mana
private ManagedObjectRegistry _registry;
- protected DefaultManagedObject(Class<?> managementInterface, String typeName)
+ protected DefaultManagedObject(Class<?> managementInterface, String typeName, ManagedObjectRegistry registry)
throws NotCompliantMBeanException
{
super(managementInterface);
+ _registry = registry;
_managementInterface = managementInterface;
_typeName = typeName;
_mbeanInfo = buildMBeanInfo();
}
+ public ManagedObjectRegistry getRegistry()
+ {
+ return _registry;
+ }
+
@Override
public MBeanInfo getMBeanInfo()
{
@@ -74,18 +78,15 @@ public abstract class DefaultManagedObject extends StandardMBean implements Mana
return _managementInterface;
}
- public ManagedObject getParentObject()
- {
- return null;
- }
+ public abstract ManagedObject getParentObject();
+
public void register() throws JMException
{
- _registry = ApplicationRegistry.getInstance().getManagedObjectRegistry();
_registry.registerObject(this);
}
- public void unregister()
+ public void unregister() throws JMException
{
try
{
@@ -94,10 +95,6 @@ public abstract class DefaultManagedObject extends StandardMBean implements Mana
_registry.unregisterObject(this);
}
}
- catch (JMException e)
- {
- LOGGER.error("Error unregistering managed object: " + this + ": " + e, e);
- }
finally
{
_registry = null;
@@ -112,7 +109,7 @@ public abstract class DefaultManagedObject extends StandardMBean implements Mana
/**
* Created the ObjectName as per the JMX Specs
* @return ObjectName
- * @throws MalformedObjectNameException
+ * @throws javax.management.MalformedObjectNameException
*/
public ObjectName getObjectName() throws MalformedObjectNameException
{
diff --git a/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXActivator.java b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXActivator.java
new file mode 100644
index 0000000000..c588b40de7
--- /dev/null
+++ b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXActivator.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.server.jmx;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.log4j.Logger;
+import org.apache.qpid.server.configuration.plugins.ConfigurationPluginFactory;
+import org.apache.qpid.server.registry.ApplicationRegistry;
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceRegistration;
+
+public class JMXActivator implements BundleActivator
+{
+ private static final Logger LOGGER = Logger.getLogger(JMXActivator.class);
+
+ private String _bundleName;
+ private JMXService _jmxService;
+
+ private List<ServiceRegistration> _registeredServices;
+
+
+ public void start(final BundleContext ctx) throws Exception
+ {
+ boolean jmxManagementEnabled = ApplicationRegistry.getInstance().getConfiguration().getJMXManagementEnabled();
+
+ if (jmxManagementEnabled)
+ {
+ _jmxService = new JMXService();
+ startJmsService(_jmxService);
+
+ _bundleName = ctx.getBundle().getSymbolicName();
+
+ _registeredServices = registerServices(ctx);
+ }
+ else
+ {
+ LOGGER.debug("Skipping registration of JMX plugin as JMX Management disabled in config. ");
+ }
+ }
+
+ public void stop(final BundleContext bundleContext) throws Exception
+ {
+ try
+ {
+ if (_jmxService != null)
+ {
+ if (LOGGER.isInfoEnabled())
+ {
+ LOGGER.info("Stopping jmx plugin: " + _bundleName);
+ }
+ _jmxService.close();
+ }
+
+ if (_registeredServices != null)
+ {
+ unregisterServices();
+ }
+ }
+ finally
+ {
+ _jmxService = null;
+ _registeredServices = null;
+ }
+ }
+
+
+ private List<ServiceRegistration> registerServices(BundleContext ctx)
+ {
+ if (LOGGER.isInfoEnabled())
+ {
+ LOGGER.info("Registering jmx plugin: " + _bundleName);
+ }
+
+ List<ServiceRegistration> serviceRegistrations = new ArrayList<ServiceRegistration>();
+
+ ServiceRegistration jmxServiceRegistration = ctx.registerService(JMXService.class.getName(), _jmxService, null);
+ ServiceRegistration jmxConfigFactoryRegistration = ctx.registerService(ConfigurationPluginFactory.class.getName(), JMXConfiguration.FACTORY, null);
+
+ serviceRegistrations.add(jmxServiceRegistration);
+ serviceRegistrations.add(jmxConfigFactoryRegistration);
+ return serviceRegistrations;
+ }
+
+ private void startJmsService(JMXService jmxService) throws Exception
+ {
+ if (LOGGER.isInfoEnabled())
+ {
+ LOGGER.info("Starting JMX service");
+ }
+ boolean startedSuccessfully = false;
+ try
+ {
+ jmxService.start();
+ startedSuccessfully = true;
+ }
+ finally
+ {
+ if (!startedSuccessfully)
+ {
+ LOGGER.error("JMX failed to start normally, closing service");
+ jmxService.close();
+ }
+ }
+ }
+
+ private void unregisterServices()
+ {
+ for (Iterator<ServiceRegistration> iterator = _registeredServices.iterator(); iterator.hasNext();)
+ {
+ ServiceRegistration service = iterator.next();
+ service.unregister();
+ }
+ }
+}
diff --git a/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXConfiguration.java b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXConfiguration.java
new file mode 100644
index 0000000000..dc9a712f90
--- /dev/null
+++ b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXConfiguration.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.server.jmx;
+
+import org.apache.commons.configuration.CompositeConfiguration;
+import org.apache.commons.configuration.Configuration;
+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.configuration.plugins.ConfigurationPluginFactory;
+
+import java.util.Arrays;
+import java.util.List;
+
+public class JMXConfiguration extends ConfigurationPlugin
+{
+ CompositeConfiguration _finalConfig;
+
+ public static final ConfigurationPluginFactory FACTORY = new ConfigurationPluginFactory()
+ {
+ public ConfigurationPlugin newInstance(String path, Configuration config) throws ConfigurationException
+ {
+ ConfigurationPlugin instance = new JMXConfiguration();
+ instance.setConfiguration(path, config);
+ return instance;
+ }
+
+ public List<String> getParentPaths()
+ {
+ return Arrays.asList("jmx");
+ }
+ };
+
+ public String[] getElementsProcessed()
+ {
+ return new String[] { "" };
+ }
+
+ public Configuration getConfiguration()
+ {
+ return _finalConfig;
+ }
+
+
+ @Override
+ public void validateConfiguration() throws ConfigurationException
+ {
+ // Valid Configuration either has xml links to new files
+ _finalConfig = new CompositeConfiguration(getConfig());
+ List subFiles = getConfig().getList("xml[@fileName]");
+ for (Object subFile : subFiles)
+ {
+ _finalConfig.addConfiguration(new XMLConfiguration((String) subFile));
+ }
+
+ }
+
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/management/JMXManagedObjectRegistry.java b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXManagedObjectRegistry.java
index 04a5b27991..0648235077 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/management/JMXManagedObjectRegistry.java
+++ b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXManagedObjectRegistry.java
@@ -18,16 +18,17 @@
* under the License.
*
*/
-package org.apache.qpid.server.management;
+package org.apache.qpid.server.jmx;
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 org.apache.qpid.server.security.auth.sasl.UsernamePrincipal;
@@ -55,6 +56,7 @@ import java.io.IOException;
import java.lang.management.ManagementFactory;
import java.lang.reflect.Proxy;
import java.net.InetAddress;
+import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
@@ -77,7 +79,7 @@ import java.util.concurrent.ConcurrentHashMap;
public class JMXManagedObjectRegistry implements ManagedObjectRegistry
{
private static final Logger _log = Logger.getLogger(JMXManagedObjectRegistry.class);
-
+
private final MBeanServer _mbeanServer;
private JMXConnectorServer _cs;
private Registry _rmiRegistry;
@@ -108,7 +110,7 @@ public class JMXManagedObjectRegistry implements ManagedObjectRegistry
{
CurrentActor.get().message(ManagementConsoleMessages.STARTUP());
-
+
//check if system properties are set to use the JVM's out-of-the-box JMXAgent
if (areOutOfTheBoxJMXOptionsSet())
{
@@ -161,10 +163,10 @@ public class JMXManagedObjectRegistry implements ManagedObjectRegistry
}
if (!ksf.canRead())
{
- throw new FileNotFoundException("Cannot read JMX management SSL keystore file: "
+ throw new FileNotFoundException("Cannot read JMX management SSL keystore file: "
+ ksf + ". Check permissions.");
}
-
+
CurrentActor.get().message(ManagementConsoleMessages.SSL_KEYSTORE(ksf.getAbsolutePath()));
}
@@ -196,15 +198,14 @@ 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());
+ RMIPasswordAuthenticator rmipa = new RMIPasswordAuthenticator(new InetSocketAddress(_jmxPortRegistryServer));
HashMap<String,Object> env = new HashMap<String,Object>();
env.put(JMXConnectorServer.AUTHENTICATOR, rmipa);
/*
- * Start a RMI registry on the management port, to hold the JMX RMI ConnectorServer stub.
+ * Start a RMI registry on the management port, to hold the JMX RMI ConnectorServer stub.
* Using custom socket factory to prevent anyone (including us unfortunately) binding to the registry using RMI.
- * As a result, only binds made using the object reference will succeed, thus securing it from external change.
+ * As a result, only binds made using the object reference will succeed, thus securing it from external change.
*/
System.setProperty("java.rmi.server.randomIDs", "true");
if(_useCustomSocketFactory)
@@ -215,17 +216,17 @@ public class JMXManagedObjectRegistry implements ManagedObjectRegistry
{
_rmiRegistry = LocateRegistry.createRegistry(_jmxPortRegistryServer, null, null);
}
-
+
CurrentActor.get().message(ManagementConsoleMessages.LISTENING("RMI Registry", _jmxPortRegistryServer));
/*
- * We must now create the RMI ConnectorServer manually, as the JMX Factory methods use RMI calls
+ * We must now create the RMI ConnectorServer manually, as the JMX Factory methods use RMI calls
* to bind the ConnectorServer to the registry, which will now fail as for security we have
- * locked it from any RMI based modifications, including our own. Instead, we will manually bind
+ * locked it from any RMI based modifications, including our own. Instead, we will manually bind
* the RMIConnectorServer stub to the registry using its object reference, which will still succeed.
- *
+ *
* 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.
+ * on 'port +1'. Use of these two well-defined ports will ease any navigation through firewall's.
*/
final Map<String, String> connectionIdUsernameMap = new ConcurrentHashMap<String, String>();
final RMIServerImpl rmiConnectorServerStub = new RMIJRMPServerImpl(_jmxPortConnectorServer, csf, ssf, env)
@@ -237,7 +238,7 @@ public class JMXManagedObjectRegistry implements ManagedObjectRegistry
* An instance of NotificationListener (mapCleanupListener) will be responsible for removing these Map
* entries.
*
- * @see javax.management.remote.rmi.RMIJRMPServerImpl#makeClient(java.lang.String, javax.security.auth.Subject)
+ * @see javax.management.remote.rmi.RMIJRMPServerImpl#makeClient(String, javax.security.auth.Subject)
*/
@Override
protected RMIConnection makeClient(String connectionId, Subject subject) throws IOException
@@ -253,7 +254,6 @@ public class JMXManagedObjectRegistry implements ManagedObjectRegistry
final NotificationListener mapCleanupListener = new NotificationListener()
{
- @Override
public void handleNotification(Notification notification, Object handback)
{
final String connectionId = ((JMXConnectionNotification) notification).getConnectionId();
@@ -276,32 +276,32 @@ public class JMXManagedObjectRegistry implements ManagedObjectRegistry
final JMXServiceURL internalUrl = new JMXServiceURL("rmi", hostname, _jmxPortConnectorServer);
_cs = new RMIConnectorServer(internalUrl, env, rmiConnectorServerStub, _mbeanServer)
- {
- @Override
+ {
+ @Override
public synchronized void start() throws IOException
- {
+ {
try
- {
- //manually bind the connector server to the registry at key 'jmxrmi', like the out-of-the-box agent
+ {
+ //manually bind the connector server to the registry at key 'jmxrmi', like the out-of-the-box agent
_rmiRegistry.bind("jmxrmi", rmiConnectorServerStub);
}
catch (AlreadyBoundException abe)
- {
+ {
//key was already in use. shouldnt happen here as its a new registry, unbindable by normal means.
//IOExceptions are the only checked type throwable by the method, wrap and rethrow
- IOException ioe = new IOException(abe.getMessage());
- ioe.initCause(abe);
- throw ioe;
+ IOException ioe = new IOException(abe.getMessage());
+ ioe.initCause(abe);
+ throw ioe;
}
//now do the normal tasks
- super.start();
+ super.start();
}
- @Override
+ @Override
public synchronized void stop() throws IOException
- {
+ {
try
{
if (_rmiRegistry != null)
@@ -311,22 +311,24 @@ public class JMXManagedObjectRegistry implements ManagedObjectRegistry
}
catch (NotBoundException nbe)
{
+ // TODO consider if we want to keep new logging
+ _log.error("Failed to unbind jmxrmi", nbe);
//ignore
}
-
+
//now do the normal tasks
super.stop();
}
-
- @Override
+
+ @Override
public JMXServiceURL getAddress()
{
//must return our pre-crafted url that includes the full details, inc JNDI details
return externalUrl;
- }
+ }
+
+ };
- };
-
//Add the custom invoker as an MBeanServerForwarder, and start the RMIConnectorServer.
MBeanServerForwarder mbsf = MBeanInvocationHandlerImpl.newProxyInstance();
@@ -362,14 +364,14 @@ public class JMXManagedObjectRegistry implements ManagedObjectRegistry
}
/*
- * Custom RMIServerSocketFactory class, used to prevent updates to the RMI registry.
+ * Custom RMIServerSocketFactory class, used to prevent updates to the RMI registry.
* Supplied to the registry at creation, this will prevent RMI-based operations on the
* registry such as attempting to bind a new object, thereby securing it from tampering.
* This is accomplished by always returning null when attempting to determine the address
* of the caller, thus ensuring the registry will refuse the attempt. Calls to bind etc
* made using the object reference will not be affected and continue to operate normally.
*/
-
+
private static class CustomRMIServerSocketFactory implements RMIServerSocketFactory
{
@@ -434,6 +436,8 @@ public class JMXManagedObjectRegistry implements ManagedObjectRegistry
//Stops the JMXConnectorServer and RMIRegistry, then unregisters any remaining MBeans from the MBeanServer
public void close()
{
+ _log.debug("close() called");
+
if (_cs != null)
{
// Stopping the JMX ConnectorServer
@@ -444,7 +448,7 @@ public class JMXManagedObjectRegistry implements ManagedObjectRegistry
}
catch (IOException e)
{
- _log.error("Exception while closing the JMX ConnectorServer: " + e.getMessage());
+ _log.error("Exception while closing the JMX ConnectorServer: ", e);
}
}
@@ -454,11 +458,15 @@ public class JMXManagedObjectRegistry implements ManagedObjectRegistry
CurrentActor.get().message(ManagementConsoleMessages.SHUTTING_DOWN("RMI Registry", _jmxPortRegistryServer));
try
{
- UnicastRemoteObject.unexportObject(_rmiRegistry, false);
+ boolean success = UnicastRemoteObject.unexportObject(_rmiRegistry, false);
+ if (!success)
+ {
+ _log.warn("Failed to unexport object " + _rmiRegistry);
+ }
}
catch (NoSuchObjectException e)
{
- _log.error("Exception while closing the RMI Registry: " + e.getMessage());
+ _log.error("Exception while closing the RMI Registry: ", e);
}
}
diff --git a/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXService.java b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXService.java
new file mode 100644
index 0000000000..7a232d2584
--- /dev/null
+++ b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXService.java
@@ -0,0 +1,193 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.jmx;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.ServiceLoader;
+
+import javax.management.JMException;
+import javax.management.StandardMBean;
+
+import org.apache.commons.configuration.ConfigurationException;
+import org.apache.log4j.Logger;
+import org.apache.qpid.AMQException;
+import org.apache.qpid.server.jmx.mbeans.LoggingManagementMBean;
+import org.apache.qpid.server.jmx.mbeans.UserManagementMBean;
+import org.apache.qpid.server.jmx.mbeans.ConfigurationManagementMBean;
+import org.apache.qpid.server.jmx.mbeans.ServerInformationMBean;
+import org.apache.qpid.server.jmx.mbeans.Shutdown;
+import org.apache.qpid.server.jmx.mbeans.VirtualHostMBean;
+import org.apache.qpid.server.logging.log4j.LoggingFacade;
+import org.apache.qpid.server.model.Broker;
+import org.apache.qpid.server.model.ConfigurationChangeListener;
+import org.apache.qpid.server.model.ConfiguredObject;
+import org.apache.qpid.server.model.PasswordCredentialManagingAuthenticationProvider;
+import org.apache.qpid.server.model.State;
+import org.apache.qpid.server.model.VirtualHost;
+import org.apache.qpid.server.registry.ApplicationRegistry;
+
+
+public class JMXService implements ConfigurationChangeListener
+{
+ private static final ClassLoader BUNDLE_CLASSLOADER = JMXService.class.getClassLoader();
+
+ private static final Logger LOGGER = Logger.getLogger(JMXService.class);
+
+ private final Broker _broker;
+ private final JMXManagedObjectRegistry _objectRegistry;
+ private final Shutdown _shutdown;
+ private final ServerInformationMBean _serverInfo;
+ private final ConfigurationManagementMBean _configManagement;
+ private final LoggingManagementMBean _loggingManagement;
+
+ private final Map<ConfiguredObject, AMQManagedObject> _children = new HashMap<ConfiguredObject, AMQManagedObject>();
+
+ public JMXService() throws AMQException, JMException
+ {
+ _broker = ApplicationRegistry.getInstance().getBroker();
+ _objectRegistry = new JMXManagedObjectRegistry();
+
+ _broker.addChangeListener(this);
+ synchronized (_children)
+ {
+ for(VirtualHost virtualHost : _broker.getVirtualHosts())
+ {
+ if(!_children.containsKey(virtualHost))
+ {
+ _children.put(virtualHost, new VirtualHostMBean(virtualHost, _objectRegistry));
+ }
+ }
+ }
+ _shutdown = new Shutdown(_objectRegistry);
+ _serverInfo = new ServerInformationMBean(_objectRegistry, _broker);
+ _configManagement = new ConfigurationManagementMBean(_objectRegistry);
+ _loggingManagement = new LoggingManagementMBean(LoggingFacade.getCurrentInstance(), _objectRegistry);
+ }
+
+ public void start() throws IOException, ConfigurationException
+ {
+ _objectRegistry.start();
+ }
+
+ public void close()
+ {
+ _broker.removeChangeListener(this);
+
+ _objectRegistry.close();
+ }
+
+ public void stateChanged(ConfiguredObject object, State oldState, State newState)
+ {
+
+ }
+
+ public void childAdded(ConfiguredObject object, ConfiguredObject child)
+ {
+ synchronized (_children)
+ {
+ try
+ {
+ AMQManagedObject mbean;
+ if(child instanceof VirtualHost)
+ {
+ VirtualHost vhostChild = (VirtualHost)child;
+ mbean = new VirtualHostMBean(vhostChild, _objectRegistry);
+ }
+ else if(child instanceof PasswordCredentialManagingAuthenticationProvider)
+ {
+ mbean = new UserManagementMBean((PasswordCredentialManagingAuthenticationProvider) child, _objectRegistry);
+ }
+ else
+ {
+ mbean = null;
+ }
+
+ if (mbean != null)
+ {
+ createAdditionalMBeansFromProviders(child, mbean);
+ }
+ }
+ catch(JMException e)
+ {
+ LOGGER.error("Error creating mbean", e);
+ // TODO - Implement error reporting on mbean creation
+ }
+ }
+ }
+
+
+ public void childRemoved(ConfiguredObject object, ConfiguredObject child)
+ {
+ // TODO - implement vhost removal (possibly just removing the instanceof check below)
+
+ synchronized (_children)
+ {
+ if(child instanceof PasswordCredentialManagingAuthenticationProvider)
+ {
+ AMQManagedObject mbean = _children.remove(child);
+ if(mbean != null)
+ {
+ try
+ {
+ mbean.unregister();
+ }
+ catch(JMException e)
+ {
+ LOGGER.error("Error creating mbean", e);
+ //TODO - report error on removing child MBean
+ }
+ }
+ }
+
+ }
+ }
+
+ private void createAdditionalMBeansFromProviders(ConfiguredObject child, AMQManagedObject mbean) throws JMException
+ {
+ _children.put(child, mbean);
+
+ for (Iterator<MBeanProvider> iterator = getMBeanProviderIterator(); iterator.hasNext();)
+ {
+ MBeanProvider provider = iterator.next();
+ LOGGER.debug("Consulting mbean provider : " + provider + " for child : " + child);
+ if (provider.isChildManageableByMBean(child))
+ {
+ LOGGER.debug("Provider will create mbean ");
+ StandardMBean bean = provider.createMBean(child, mbean);
+ // TODO track the mbeans that have been created on behalf of a child in a map, then
+ // if the child is ever removed, destroy these beans too.
+ }
+ }
+ }
+
+ /**
+ * Finds all classes implementing the {@link MBeanProvider} interface. This will find
+ * <b>only</b> those classes which are visible to the classloader of this OSGI bundle.
+ */
+ private Iterator<MBeanProvider> getMBeanProviderIterator()
+ {
+ return ServiceLoader.load(MBeanProvider.class, BUNDLE_CLASSLOADER).iterator();
+ }
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/management/MBeanIntrospector.java b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/MBeanIntrospector.java
index 89b74f939d..79ddc8cfc0 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/management/MBeanIntrospector.java
+++ b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/MBeanIntrospector.java
@@ -18,7 +18,7 @@
* under the License.
*
*/
-package org.apache.qpid.server.management;
+package org.apache.qpid.server.jmx;
import org.apache.qpid.management.common.mbeans.annotations.MBeanAttribute;
import org.apache.qpid.management.common.mbeans.annotations.MBeanConstructor;
@@ -43,7 +43,8 @@ import java.util.List;
* @author Bhupendra Bhardwaj
* @version 0.1
*/
-class MBeanIntrospector {
+class MBeanIntrospector
+{
private static final String _defaultAttributeDescription = "Management attribute";
private static final String _defaultOerationDescription = "Management operation";
@@ -58,7 +59,7 @@ class MBeanIntrospector {
* Introspects the management interface class for MBean attributes.
* @param interfaceClass
* @return MBeanAttributeInfo[]
- * @throws NotCompliantMBeanException
+ * @throws javax.management.NotCompliantMBeanException
*/
static MBeanAttributeInfo[] getMBeanAttributesInfo(Class interfaceClass)
throws NotCompliantMBeanException
@@ -221,7 +222,7 @@ class MBeanIntrospector {
* @param attribute
* @param list
* @return attribute index no. -1 if attribtue doesn't exist
- * @throws NotCompliantMBeanException
+ * @throws javax.management.NotCompliantMBeanException
*/
private static int getIndexIfAlreadyExists(MBeanAttributeInfo attribute,
List<MBeanAttributeInfo> list)
diff --git a/java/broker/src/main/java/org/apache/qpid/server/management/MBeanInvocationHandlerImpl.java b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/MBeanInvocationHandlerImpl.java
index 651372db16..49f06d5121 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/management/MBeanInvocationHandlerImpl.java
+++ b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/MBeanInvocationHandlerImpl.java
@@ -18,10 +18,11 @@
* under the License.
*
*/
-package org.apache.qpid.server.management;
+package org.apache.qpid.server.jmx;
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;
@@ -174,41 +175,40 @@ public class MBeanInvocationHandlerImpl implements InvocationHandler, Notificati
}
methodName = getMethodName(method, args);
- if (isAccessMethod(methodName) || impact == MBeanOperationInfo.INFO)
- {
- // Check for read-only method invocation permission
+ if (isAccessMethod(methodName) || impact == MBeanOperationInfo.INFO)
+ {
+ // Check for read-only method invocation permission
if (!security.authoriseMethod(Operation.ACCESS, type, methodName))
{
throw new SecurityException("Permission denied: Access " + methodName);
}
- }
- else
- {
- // Check for setting properties permission
- if (!security.authoriseMethod(Operation.UPDATE, type, methodName))
- {
- throw new SecurityException("Permission denied: Update " + methodName);
- }
- }
-
- boolean oldAccessChecksDisabled = false;
- if(_managementRightsInferAllAccess)
- {
- oldAccessChecksDisabled = SecurityManager.setAccessChecksDisabled(true);
- }
-
- try
- {
- // Actually invoke the method
- return method.invoke(_mbs, args);
- }
- finally
- {
- if(_managementRightsInferAllAccess)
- {
- SecurityManager.setAccessChecksDisabled(oldAccessChecksDisabled);
- }
- }
+ }
+ else
+ {
+ // Check for setting properties permission
+ if (!security.authoriseMethod(Operation.UPDATE, type, methodName))
+ {
+ throw new SecurityException("Permission denied: Update " + methodName);
+ }
+ }
+
+ boolean oldAccessChecksDisabled = false;
+ if(_managementRightsInferAllAccess)
+ {
+ oldAccessChecksDisabled = SecurityManager.setAccessChecksDisabled(true);
+ }
+
+ try
+ {
+ return doInvokeWrappingWithManagementActor(method, args);
+ }
+ finally
+ {
+ if(_managementRightsInferAllAccess)
+ {
+ SecurityManager.setAccessChecksDisabled(oldAccessChecksDisabled);
+ }
+ }
}
catch (InvocationTargetException e)
{
@@ -216,25 +216,40 @@ public class MBeanInvocationHandlerImpl implements InvocationHandler, Notificati
}
}
+ private Object doInvokeWrappingWithManagementActor(Method method,
+ Object[] args) throws IllegalAccessException,
+ InvocationTargetException
+ {
+ try
+ {
+ CurrentActor.set(_logActor);
+ return method.invoke(_mbs, args);
+ }
+ finally
+ {
+ CurrentActor.remove();
+ }
+ }
+
private String getType(Method method, Object[] args)
- {
- if (args[0] instanceof ObjectName)
- {
- ObjectName object = (ObjectName) args[0];
- String type = object.getKeyProperty("type");
-
- return type;
- }
- return null;
+ {
+ if (args[0] instanceof ObjectName)
+ {
+ ObjectName object = (ObjectName) args[0];
+ String type = object.getKeyProperty("type");
+
+ return type;
+ }
+ return null;
}
private String getVirtualHost(Method method, Object[] args)
- {
+ {
if (args[0] instanceof ObjectName)
{
ObjectName object = (ObjectName) args[0];
String vhost = object.getKeyProperty("VirtualHost");
-
+
if(vhost != null)
{
try
@@ -253,7 +268,7 @@ public class MBeanInvocationHandlerImpl implements InvocationHandler, Notificati
}
return null;
}
-
+
private String getMethodName(Method method, Object[] args)
{
String methodName = method.getName();
@@ -274,7 +289,7 @@ public class MBeanInvocationHandlerImpl implements InvocationHandler, Notificati
methodName = (String) args[1];
}
}
-
+
return methodName;
}
@@ -289,7 +304,7 @@ public class MBeanInvocationHandlerImpl implements InvocationHandler, Notificati
{
return -1;
}
-
+
try
{
//Get the impact attribute
diff --git a/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/MBeanProvider.java b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/MBeanProvider.java
new file mode 100644
index 0000000000..83909dbe72
--- /dev/null
+++ b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/MBeanProvider.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.server.jmx;
+
+import java.util.ServiceLoader;
+
+import javax.management.JMException;
+import javax.management.StandardMBean;
+
+import org.apache.qpid.server.model.ConfiguredObject;
+
+/**
+ * A provider of an mbean implementation.
+ *
+ * Provider implementations are advertised as services and loaded via {@link ServiceLoader}.
+ */
+public interface MBeanProvider
+{
+ /**
+ * Tests whether a <code>child</code> can be managed by the mbean
+ * provided by this provider.
+ */
+ boolean isChildManageableByMBean(ConfiguredObject child);
+
+ /**
+ * Creates a mbean for this child. This method should only be called if
+ * {@link #isChildManageableByMBean(ConfiguredObject)} has previously returned true.
+ *
+ * @return newly created mbean
+ */
+ StandardMBean createMBean(ConfiguredObject child, StandardMBean parent) throws JMException;
+
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/management/ManagedObject.java b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/ManagedObject.java
index 483b325455..40b778fd93 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/management/ManagedObject.java
+++ b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/ManagedObject.java
@@ -18,9 +18,7 @@
* under the License.
*
*/
-package org.apache.qpid.server.management;
-
-import org.apache.qpid.AMQException;
+package org.apache.qpid.server.jmx;
import javax.management.JMException;
import javax.management.MalformedObjectNameException;
@@ -46,14 +44,14 @@ public interface ManagedObject
ManagedObject getParentObject();
- void register() throws AMQException, JMException;
+ void register() throws JMException;
- void unregister() throws AMQException;
+ void unregister() throws JMException;
/**
* Returns the ObjectName required for the mbeanserver registration.
* @return ObjectName
- * @throws MalformedObjectNameException
+ * @throws javax.management.MalformedObjectNameException
*/
ObjectName getObjectName() throws MalformedObjectNameException;
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/management/ManagedObjectRegistry.java b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/ManagedObjectRegistry.java
index b3323c569c..2ae0ac7052 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/management/ManagedObjectRegistry.java
+++ b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/ManagedObjectRegistry.java
@@ -18,10 +18,9 @@
* under the License.
*
*/
-package org.apache.qpid.server.management;
+package org.apache.qpid.server.jmx;
import org.apache.commons.configuration.ConfigurationException;
-
import org.apache.qpid.common.Closeable;
import javax.management.JMException;
diff --git a/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/AbstractStatisticsGatheringMBean.java b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/AbstractStatisticsGatheringMBean.java
new file mode 100644
index 0000000000..6ab7db3629
--- /dev/null
+++ b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/AbstractStatisticsGatheringMBean.java
@@ -0,0 +1,200 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.jmx.mbeans;
+
+import javax.management.NotCompliantMBeanException;
+import org.apache.qpid.server.model.ConfiguredObject;
+import org.apache.qpid.server.model.Connection;
+import org.apache.qpid.server.jmx.AMQManagedObject;
+import org.apache.qpid.server.jmx.ManagedObjectRegistry;
+import org.apache.qpid.server.model.VirtualHost;
+
+abstract class AbstractStatisticsGatheringMBean<T extends ConfiguredObject> extends AMQManagedObject
+{
+ private long _lastStatUpdateTime;
+ private long _statUpdatePeriod = 5000L;
+ private long _lastMessagesReceived;
+ private long _lastMessagesSent;
+ private long _lastBytesReceived;
+ private long _lastBytesSent;
+ private double _messageReceivedRate;
+ private double _messageSentRate;
+ private double _bytesReceivedRate;
+ private double _bytesSentRate;
+ private double _peakMessageReceivedRate;
+ private double _peakMessageSentRate;
+ private double _peakBytesReceivedRate;
+ private double _peakBytesSentRate;
+ private final T _configuredObject;
+
+ protected AbstractStatisticsGatheringMBean(Class<?> managementInterface,
+ String typeName,
+ ManagedObjectRegistry registry,
+ T object) throws NotCompliantMBeanException
+ {
+ super(managementInterface, typeName, registry);
+ _configuredObject = object;
+ initStats();
+ }
+
+ protected void initStats()
+ {
+ _lastStatUpdateTime = System.currentTimeMillis();
+ }
+
+ protected synchronized void updateStats()
+ {
+ long time = System.currentTimeMillis();
+ final long period = time - _lastStatUpdateTime;
+ if(period > _statUpdatePeriod)
+ {
+ long messagesReceived = getStatistic(VirtualHost.MESSAGES_IN);
+ long messagesSent = getStatistic(VirtualHost.MESSAGES_OUT);
+ long bytesReceived = getStatistic(VirtualHost.BYTES_IN);
+ long bytesSent = getStatistic(VirtualHost.BYTES_OUT);
+
+ double messageReceivedRate = (double)(messagesReceived - _lastMessagesReceived) / (double)period;
+ double messageSentRate = (double)(messagesSent - _lastMessagesSent) / (double)period;
+ double bytesReceivedRate = (double)(bytesReceived - _lastBytesReceived) / (double)period;
+ double bytesSentRate = (double)(bytesSent - _lastBytesSent) / (double)period;
+
+ _lastMessagesReceived = messagesReceived;
+ _lastMessagesSent = messagesSent;
+ _lastBytesReceived = bytesReceived;
+ _lastBytesSent = bytesSent;
+
+ _messageReceivedRate = messageReceivedRate;
+ _messageSentRate = messageSentRate;
+ _bytesReceivedRate = bytesReceivedRate;
+ _bytesSentRate = bytesSentRate;
+
+ if(messageReceivedRate > _peakMessageReceivedRate)
+ {
+ _peakMessageReceivedRate = messageReceivedRate;
+ }
+
+ if(messageSentRate > _peakMessageSentRate)
+ {
+ _peakMessageSentRate = messageSentRate;
+ }
+
+ if(bytesReceivedRate > _peakBytesReceivedRate)
+ {
+ _peakBytesReceivedRate = bytesReceivedRate;
+ }
+
+ if(bytesSentRate > _peakBytesSentRate)
+ {
+ _peakBytesSentRate = bytesSentRate;
+ }
+
+ }
+ }
+
+ private long getStatistic(String name)
+ {
+ return (Long) getConfiguredObject().getStatistics().getStatistic(name);
+ }
+
+ public synchronized void resetStatistics() throws Exception
+ {
+ updateStats();
+ //TODO - implement resetStatistics()
+ }
+
+ public synchronized double getPeakMessageDeliveryRate()
+ {
+ updateStats();
+ return _peakMessageSentRate;
+ }
+
+ public synchronized double getPeakDataDeliveryRate()
+ {
+ updateStats();
+ return _peakBytesSentRate;
+ }
+
+ public synchronized double getMessageDeliveryRate()
+ {
+ updateStats();
+ return _messageSentRate;
+ }
+
+ public synchronized double getDataDeliveryRate()
+ {
+ updateStats();
+ return _bytesSentRate;
+ }
+
+ public synchronized long getTotalMessagesDelivered()
+ {
+ updateStats();
+ return getStatistic(Connection.MESSAGES_OUT);
+ }
+
+ public synchronized long getTotalDataDelivered()
+ {
+ updateStats();
+ return getStatistic(Connection.BYTES_OUT);
+ }
+
+ protected final T getConfiguredObject()
+ {
+ return _configuredObject;
+ }
+
+ public synchronized double getPeakMessageReceiptRate()
+ {
+ updateStats();
+ return _peakMessageReceivedRate;
+ }
+
+ public synchronized double getPeakDataReceiptRate()
+ {
+ updateStats();
+ return _peakBytesReceivedRate;
+ }
+
+ public synchronized double getMessageReceiptRate()
+ {
+ updateStats();
+ return _messageReceivedRate;
+ }
+
+ public synchronized double getDataReceiptRate()
+ {
+ updateStats();
+ return _bytesReceivedRate;
+ }
+
+ public synchronized long getTotalMessagesReceived()
+ {
+ updateStats();
+ return getStatistic(Connection.MESSAGES_IN);
+ }
+
+ public synchronized long getTotalDataReceived()
+ {
+ updateStats();
+ return getStatistic(Connection.BYTES_IN);
+ }
+
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/management/ConfigurationManagementMBean.java b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/ConfigurationManagementMBean.java
index f0ca5dc139..beffb4eaa9 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/configuration/management/ConfigurationManagementMBean.java
+++ b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/ConfigurationManagementMBean.java
@@ -18,20 +18,24 @@
* under the License.
*
*/
-package org.apache.qpid.server.configuration.management;
+package org.apache.qpid.server.jmx.mbeans;
import org.apache.qpid.management.common.mbeans.ConfigurationManagement;
-import org.apache.qpid.server.management.AMQManagedObject;
+import org.apache.qpid.server.jmx.AMQManagedObject;
+import org.apache.qpid.server.jmx.ManagedObject;
+import org.apache.qpid.server.jmx.ManagedObjectRegistry;
import org.apache.qpid.server.registry.ApplicationRegistry;
+import javax.management.JMException;
import javax.management.NotCompliantMBeanException;
public class ConfigurationManagementMBean extends AMQManagedObject implements ConfigurationManagement
{
- public ConfigurationManagementMBean() throws NotCompliantMBeanException
+ public ConfigurationManagementMBean(ManagedObjectRegistry registry) throws JMException
{
- super(ConfigurationManagement.class, ConfigurationManagement.TYPE);
+ super(ConfigurationManagement.class, ConfigurationManagement.TYPE, registry);
+ register();
}
public String getObjectInstanceName()
@@ -44,4 +48,9 @@ public class ConfigurationManagementMBean extends AMQManagedObject implements Co
ApplicationRegistry.getInstance().getConfiguration().reparseConfigFileSecuritySections();
}
+ @Override
+ public ManagedObject getParentObject()
+ {
+ return null;
+ }
}
diff --git a/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/ConnectionMBean.java b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/ConnectionMBean.java
new file mode 100644
index 0000000000..d0c0d5e73f
--- /dev/null
+++ b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/ConnectionMBean.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.server.jmx.mbeans;
+
+import java.io.IOException;
+import java.util.Collection;
+import java.util.Date;
+import javax.management.JMException;
+import javax.management.ObjectName;
+import javax.management.openmbean.CompositeData;
+import javax.management.openmbean.CompositeDataSupport;
+import javax.management.openmbean.CompositeType;
+import javax.management.openmbean.OpenType;
+import javax.management.openmbean.SimpleType;
+import javax.management.openmbean.TabularData;
+import javax.management.openmbean.TabularDataSupport;
+import javax.management.openmbean.TabularType;
+
+import org.apache.qpid.management.common.mbeans.ManagedConnection;
+import org.apache.qpid.server.jmx.ManagedObject;
+import org.apache.qpid.server.model.Connection;
+import org.apache.qpid.server.model.Session;
+import org.apache.qpid.server.model.Statistics;
+
+public class ConnectionMBean extends AbstractStatisticsGatheringMBean<Connection> implements ManagedConnection
+{
+ private static final OpenType[] CHANNEL_ATTRIBUTE_TYPES =
+ { SimpleType.INTEGER, SimpleType.BOOLEAN, SimpleType.STRING, SimpleType.INTEGER, SimpleType.BOOLEAN };
+ private static final CompositeType CHANNEL_TYPE;
+ private static final TabularType CHANNELS_TYPE;
+
+ static
+ {
+ try
+ {
+ CHANNEL_TYPE = new CompositeType("Channel", "Channel Details", COMPOSITE_ITEM_NAMES_DESC.toArray(new String[COMPOSITE_ITEM_NAMES_DESC.size()]),
+ COMPOSITE_ITEM_NAMES_DESC.toArray(new String[COMPOSITE_ITEM_NAMES_DESC.size()]),
+ CHANNEL_ATTRIBUTE_TYPES);
+ CHANNELS_TYPE = new TabularType("Channels", "Channels", CHANNEL_TYPE, (String[]) TABULAR_UNIQUE_INDEX.toArray(new String[TABULAR_UNIQUE_INDEX.size()]));
+ }
+ catch (JMException ex)
+ {
+ // This is not expected to ever occur.
+ throw new RuntimeException("Got JMException in static initializer.", ex);
+ }
+ }
+
+
+ private final VirtualHostMBean _virtualHostMBean;
+
+ public ConnectionMBean(Connection conn, VirtualHostMBean virtualHostMBean) throws JMException
+ {
+ super(ManagedConnection.class, ManagedConnection.TYPE, virtualHostMBean.getRegistry(), conn);
+ _virtualHostMBean = virtualHostMBean;
+ register();
+ }
+
+ public String getObjectInstanceName()
+ {
+ return ObjectName.quote(getRemoteAddress());
+ }
+
+ @Override
+ public ManagedObject getParentObject()
+ {
+ return _virtualHostMBean;
+ }
+
+ public String getClientId()
+ {
+ return (String) getConfiguredObject().getAttribute(Connection.CLIENT_ID);
+ }
+
+ public String getAuthorizedId()
+ {
+ return (String) getConfiguredObject().getAttribute(Connection.PRINCIPAL);
+ }
+
+ public String getVersion()
+ {
+ return (String) getConfiguredObject().getAttribute(Connection.CLIENT_VERSION);
+ }
+
+ public String getRemoteAddress()
+ {
+ return (String) getConfiguredObject().getAttribute(Connection.REMOTE_ADDRESS);
+ }
+
+ public Date getLastIoTime()
+ {
+ Long lastIo = (Long) getConfiguredObject().getStatistics().getStatistic(Connection.LAST_IO_TIME);
+ return new Date(lastIo);
+ }
+
+ public Long getMaximumNumberOfChannels()
+ {
+ return (Long) getConfiguredObject().getAttribute(Connection.SESSION_COUNT_LIMIT);
+ }
+
+ public TabularData channels() throws IOException, JMException
+ {
+ TabularDataSupport sessionTable = new TabularDataSupport(CHANNELS_TYPE);
+ Collection<Session> list = getConfiguredObject().getSessions();
+
+ for (Session session : list)
+ {
+ Statistics statistics = session.getStatistics();
+ Long txnBegins = (Long) statistics.getStatistic(Session.LOCAL_TRANSACTION_BEGINS);
+ Integer channelId = (Integer) session.getAttribute(Session.CHANNEL_ID);
+ int unacknowledgedSize = ((Number) statistics.getStatistic(Session.UNACKNOWLEDGED_MESSAGES)).intValue();
+ boolean blocked = (Boolean) session.getAttribute(Session.PRODUCER_FLOW_BLOCKED);
+ boolean isTransactional = (txnBegins>0l);
+
+ Object[] itemValues =
+ {
+ channelId,
+ isTransactional,
+ null, // TODO - default queue (which is meaningless)
+ unacknowledgedSize,
+ blocked
+ };
+
+ CompositeData sessionData = new CompositeDataSupport(CHANNEL_TYPE,
+ COMPOSITE_ITEM_NAMES_DESC.toArray(new String[COMPOSITE_ITEM_NAMES_DESC.size()]), itemValues);
+ sessionTable.put(sessionData);
+ }
+
+ return sessionTable;
+ }
+
+ public void commitTransactions(int channelId) throws JMException
+ {
+ throw buildUnsupportedException();
+ }
+
+ public void rollbackTransactions(int channelId) throws JMException
+ {
+ throw buildUnsupportedException();
+ }
+
+ public void closeConnection() throws Exception
+ {
+ getConfiguredObject().delete();
+ }
+
+ public boolean isStatisticsEnabled()
+ {
+ return true;
+ }
+
+ public void setStatisticsEnabled(boolean enabled)
+ {
+ updateStats();
+ }
+
+ private JMException buildUnsupportedException() throws JMException
+ {
+ String msg = "Operation not supported";
+ JMException jmException = new JMException(msg);
+ jmException.initCause(new UnsupportedOperationException(msg));
+ return jmException;
+ }
+}
diff --git a/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/ExchangeMBean.java b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/ExchangeMBean.java
new file mode 100644
index 0000000000..56802d0403
--- /dev/null
+++ b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/ExchangeMBean.java
@@ -0,0 +1,313 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.jmx.mbeans;
+
+import org.apache.qpid.management.common.mbeans.ManagedExchange;
+import org.apache.qpid.server.jmx.AMQManagedObject;
+import org.apache.qpid.server.jmx.ManagedObject;
+import org.apache.qpid.server.model.Binding;
+import org.apache.qpid.server.model.Exchange;
+import org.apache.qpid.server.model.LifetimePolicy;
+import org.apache.qpid.server.model.Queue;
+import org.apache.qpid.server.model.VirtualHost;
+
+import javax.management.JMException;
+import javax.management.MalformedObjectNameException;
+import javax.management.ObjectName;
+import javax.management.OperationsException;
+import javax.management.openmbean.ArrayType;
+import javax.management.openmbean.CompositeData;
+import javax.management.openmbean.CompositeDataSupport;
+import javax.management.openmbean.CompositeType;
+import javax.management.openmbean.OpenDataException;
+import javax.management.openmbean.OpenType;
+import javax.management.openmbean.SimpleType;
+import javax.management.openmbean.TabularData;
+import javax.management.openmbean.TabularDataSupport;
+import javax.management.openmbean.TabularType;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class ExchangeMBean extends AMQManagedObject implements ManagedExchange
+{
+
+ public static final String FANOUT_EXCHANGE_TYPE = "fanout";
+ public static final String HEADERS_EXCHANGE_TYPE = "headers";
+
+ private static final String[] TABULAR_UNIQUE_INDEX_ARRAY =
+ TABULAR_UNIQUE_INDEX.toArray(new String[TABULAR_UNIQUE_INDEX.size()]);
+
+ private static final String[] COMPOSITE_ITEM_NAMES_ARRAY =
+ COMPOSITE_ITEM_NAMES.toArray(new String[COMPOSITE_ITEM_NAMES.size()]);
+
+ private static final String[] COMPOSITE_ITEM_DESCRIPTIONS_ARRAY =
+ COMPOSITE_ITEM_DESCRIPTIONS.toArray(new String[COMPOSITE_ITEM_DESCRIPTIONS.size()]);
+
+ private static final OpenType[] BINDING_ITEM_TYPES;
+ private static final CompositeType BINDING_DATA_TYPE;
+ private static final OpenType[] HEADERS_BINDING_ITEM_TYPES;
+
+
+ private static final CompositeType HEADERS_BINDING_DATA_TYPE;
+
+ private static final String[] HEADERS_COMPOSITE_ITEM_NAMES_ARRAY =
+ HEADERS_COMPOSITE_ITEM_NAMES.toArray(new String[HEADERS_COMPOSITE_ITEM_NAMES.size()]);
+
+ private static final String[] HEADERS_COMPOSITE_ITEM_DESCS_ARRAY =
+ HEADERS_COMPOSITE_ITEM_DESC.toArray(new String[HEADERS_COMPOSITE_ITEM_DESC.size()]);
+ private static final String[] HEADERS_TABULAR_UNIQUE_INDEX_ARRAY =
+ HEADERS_TABULAR_UNIQUE_INDEX.toArray(new String[HEADERS_TABULAR_UNIQUE_INDEX.size()]);
+
+ static
+ {
+ try
+ {
+ BINDING_ITEM_TYPES = new OpenType[] {SimpleType.STRING, new ArrayType(1, SimpleType.STRING)};
+
+ BINDING_DATA_TYPE= new CompositeType("Exchange Binding", "Binding key and Queue names",
+ COMPOSITE_ITEM_NAMES_ARRAY,
+ COMPOSITE_ITEM_DESCRIPTIONS_ARRAY,
+ BINDING_ITEM_TYPES);
+
+ HEADERS_BINDING_ITEM_TYPES = new OpenType[] {SimpleType.INTEGER,
+ SimpleType.STRING,
+ new ArrayType(1, SimpleType.STRING)};
+
+ HEADERS_BINDING_DATA_TYPE = new CompositeType("Exchange Binding", "Queue name and header bindings",
+ HEADERS_COMPOSITE_ITEM_NAMES_ARRAY,
+ HEADERS_COMPOSITE_ITEM_DESCS_ARRAY,
+ HEADERS_BINDING_ITEM_TYPES);
+
+
+ }
+ catch(OpenDataException e)
+ {
+ throw new RuntimeException("Unexpected Error creating ArrayType", e);
+ }
+ }
+
+
+ private final Exchange _exchange;
+ private final VirtualHostMBean _vhostMBean;
+
+ protected ExchangeMBean(Exchange exchange, VirtualHostMBean virtualHostMBean)
+ throws JMException
+ {
+ super(ManagedExchange.class, ManagedExchange.TYPE, virtualHostMBean.getRegistry());
+ _exchange = exchange;
+ _vhostMBean = virtualHostMBean;
+
+ register();
+ }
+
+ public String getObjectInstanceName()
+ {
+ return ObjectName.quote(getName());
+ }
+
+ @Override
+ public ManagedObject getParentObject()
+ {
+ return _vhostMBean;
+ }
+
+ public ObjectName getObjectName() throws MalformedObjectNameException
+ {
+ String objNameString = super.getObjectName().toString();
+ objNameString = objNameString + ",ExchangeType=" + getExchangeType();
+ return new ObjectName(objNameString);
+ }
+
+
+ public String getName()
+ {
+ return _exchange.getName();
+ }
+
+ public String getExchangeType()
+ {
+ return _exchange.getExchangeType();
+ }
+
+ public Integer getTicketNo()
+ {
+ return 0;
+ }
+
+ public boolean isDurable()
+ {
+ return _exchange.isDurable();
+ }
+
+ public boolean isAutoDelete()
+ {
+ return _exchange.getLifetimePolicy() == LifetimePolicy.AUTO_DELETE;
+ }
+
+ public TabularData bindings() throws IOException, JMException
+ {
+ if(HEADERS_EXCHANGE_TYPE.equals(_exchange.getExchangeType()))
+ {
+ return getHeadersBindings(_exchange.getBindings());
+ }
+ else
+ {
+ return getNonHeadersBindings(_exchange.getBindings());
+ }
+ }
+
+ private TabularData getHeadersBindings(Collection<Binding> bindings) throws OpenDataException
+ {
+ TabularType bindinglistDataType =
+ new TabularType("Exchange Bindings", "List of exchange bindings for " + getName(),
+ HEADERS_BINDING_DATA_TYPE,
+ HEADERS_TABULAR_UNIQUE_INDEX_ARRAY);
+
+ TabularDataSupport bindingList = new TabularDataSupport(bindinglistDataType);
+ int count = 1;
+ for (Binding binding : bindings)
+ {
+
+ String queueName = binding.getParent(Queue.class).getName();
+
+
+ Map<String,Object> headerMappings = binding.getArguments();
+
+ final List<String> mappingList = new ArrayList<String>();
+
+ if(headerMappings != null)
+ {
+ for(Map.Entry<String,Object> entry : headerMappings.entrySet())
+ {
+
+ mappingList.add(entry.getKey() + "=" + entry.getValue());
+ }
+ }
+
+
+ Object[] bindingItemValues = {count++, queueName, mappingList.toArray(new String[0])};
+ CompositeData bindingData = new CompositeDataSupport(HEADERS_BINDING_DATA_TYPE,
+ HEADERS_COMPOSITE_ITEM_NAMES_ARRAY,
+ bindingItemValues);
+ bindingList.put(bindingData);
+ }
+
+ return bindingList;
+
+ }
+
+ private TabularData getNonHeadersBindings(Collection<Binding> bindings) throws OpenDataException
+ {
+
+ TabularType bindinglistDataType =
+ new TabularType("Exchange Bindings", "Exchange Bindings for " + getName(),
+ BINDING_DATA_TYPE,
+ TABULAR_UNIQUE_INDEX_ARRAY);
+
+ TabularDataSupport bindingList = new TabularDataSupport(bindinglistDataType);
+
+ Map<String, List<String>> bindingMap = new HashMap<String, List<String>>();
+
+ for (Binding binding : bindings)
+ {
+ String key = FANOUT_EXCHANGE_TYPE.equals(_exchange.getExchangeType()) ? "*" : binding.getName();
+ List<String> queueList = bindingMap.get(key);
+ if(queueList == null)
+ {
+ queueList = new ArrayList<String>();
+ bindingMap.put(key, queueList);
+ }
+ queueList.add(binding.getParent(Queue.class).getName());
+
+ }
+
+ for(Map.Entry<String, List<String>> entry : bindingMap.entrySet())
+ {
+ Object[] bindingItemValues = {entry.getKey(), entry.getValue().toArray(new String[0])};
+ CompositeData bindingData = new CompositeDataSupport(BINDING_DATA_TYPE,
+ COMPOSITE_ITEM_NAMES_ARRAY,
+ bindingItemValues);
+ bindingList.put(bindingData);
+ }
+
+ return bindingList;
+ }
+
+ public void createNewBinding(String queueName, String binding) throws JMException
+ {
+ final Map<String,Object> arguments = new HashMap<String, Object>();
+
+ if(HEADERS_EXCHANGE_TYPE.equals(_exchange.getExchangeType()))
+ {
+ final String[] bindings = binding.split(",");
+ for (int i = 0; i < bindings.length; i++)
+ {
+ final String[] keyAndValue = bindings[i].split("=");
+ if (keyAndValue == null || keyAndValue.length == 0 || keyAndValue.length > 2 || keyAndValue[0].length() == 0)
+ {
+ throw new JMException("Format for headers binding should be \"<attribute1>=<value1>,<attribute2>=<value2>\"");
+ }
+
+ if(keyAndValue.length == 1)
+ {
+ //no value was given, only a key. Use an empty value to signal match on key presence alone
+ arguments.put(keyAndValue[0], "");
+ }
+ else
+ {
+ arguments.put(keyAndValue[0], keyAndValue[1]);
+ }
+ }
+ }
+
+ VirtualHost virtualHost = _exchange.getParent(VirtualHost.class);
+ Queue queue = MBeanUtils.findQueueFromQueueName(virtualHost, queueName);
+ _exchange.createBinding(binding, queue, arguments, Collections.EMPTY_MAP);
+ }
+
+ public void removeBinding(String queueName, String bindingKey)
+ throws IOException, JMException
+ {
+ VirtualHost virtualHost = _exchange.getParent(VirtualHost.class);
+ Queue queue = MBeanUtils.findQueueFromQueueName(virtualHost, queueName);;
+
+ boolean deleted = false;
+ for(Binding binding : _exchange.getBindings())
+ {
+ if(queue.equals(binding.getParent(Queue.class)) && bindingKey.equals(binding.getName()))
+ {
+ binding.delete();
+ deleted = true;
+ }
+ }
+
+ if (!deleted)
+ {
+ throw new OperationsException("No such binding \"" + bindingKey + "\" on queue \"" + queueName + "\"");
+ }
+ }
+}
diff --git a/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/LoggingManagementMBean.java b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/LoggingManagementMBean.java
new file mode 100644
index 0000000000..0dac8ebe37
--- /dev/null
+++ b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/LoggingManagementMBean.java
@@ -0,0 +1,324 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.jmx.mbeans;
+
+import org.apache.log4j.Logger;
+import org.apache.qpid.management.common.mbeans.LoggingManagement;
+import org.apache.qpid.management.common.mbeans.annotations.MBeanDescription;
+import org.apache.qpid.server.jmx.AMQManagedObject;
+import org.apache.qpid.server.jmx.ManagedObject;
+import org.apache.qpid.server.jmx.ManagedObjectRegistry;
+import org.apache.qpid.server.logging.log4j.LoggingFacade;
+import org.apache.qpid.server.logging.log4j.LoggingFacadeException;
+
+import javax.management.JMException;
+import javax.management.openmbean.CompositeData;
+import javax.management.openmbean.CompositeDataSupport;
+import javax.management.openmbean.CompositeType;
+import javax.management.openmbean.OpenDataException;
+import javax.management.openmbean.OpenType;
+import javax.management.openmbean.SimpleType;
+import javax.management.openmbean.TabularData;
+import javax.management.openmbean.TabularDataSupport;
+import javax.management.openmbean.TabularType;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+
+/** MBean class for LoggingManagement. It implements all the management features exposed for managing logging. */
+@MBeanDescription("Logging Management Interface")
+public class LoggingManagementMBean extends AMQManagedObject implements LoggingManagement
+{
+ public static final String INHERITED_PSUEDO_LOG_LEVEL = "INHERITED";
+ private static final Logger LOGGER = Logger.getLogger(LoggingManagementMBean.class);
+ private static final TabularType LOGGER_LEVEL_TABULAR_TYE;
+ private static final CompositeType LOGGER_LEVEL_COMPOSITE_TYPE;
+
+ private final LoggingFacade _configurator;
+
+ static
+ {
+ try
+ {
+ OpenType[] loggerLevelItemTypes = new OpenType[]{SimpleType.STRING, SimpleType.STRING};
+
+ LOGGER_LEVEL_COMPOSITE_TYPE = new CompositeType("LoggerLevelList", "Logger Level Data",
+ COMPOSITE_ITEM_NAMES.toArray(new String[COMPOSITE_ITEM_NAMES.size()]),
+ COMPOSITE_ITEM_DESCRIPTIONS.toArray(new String[COMPOSITE_ITEM_DESCRIPTIONS.size()]),
+ loggerLevelItemTypes);
+
+ LOGGER_LEVEL_TABULAR_TYE = new TabularType("LoggerLevel", "List of loggers with levels",
+ LOGGER_LEVEL_COMPOSITE_TYPE,
+ TABULAR_UNIQUE_INDEX.toArray(new String[TABULAR_UNIQUE_INDEX.size()]));
+ }
+ catch (OpenDataException e)
+ {
+ throw new ExceptionInInitializerError(e);
+ }
+ }
+
+ public LoggingManagementMBean(LoggingFacade configurator, ManagedObjectRegistry registry) throws JMException
+ {
+ super(LoggingManagement.class, LoggingManagement.TYPE, registry);
+ register();
+ _configurator = configurator;
+ }
+
+ @Override
+ public String getObjectInstanceName()
+ {
+ return LoggingManagement.TYPE;
+ }
+
+ @Override
+ public ManagedObject getParentObject()
+ {
+ return null;
+ }
+
+ @Override
+ public Integer getLog4jLogWatchInterval()
+ {
+ return _configurator.getLog4jLogWatchInterval();
+ }
+
+ @Override
+ public String[] getAvailableLoggerLevels()
+ {
+ List<String> levels = _configurator.getAvailableLoggerLevels();
+ List<String> mbeanLevels = new ArrayList<String>(levels);
+ mbeanLevels.add(INHERITED_PSUEDO_LOG_LEVEL);
+
+ return mbeanLevels.toArray(new String[mbeanLevels.size()]);
+ }
+
+ @Override
+ public TabularData viewEffectiveRuntimeLoggerLevels()
+ {
+ Map<String, String> levels = _configurator.retrieveRuntimeLoggersLevels();
+ return createTabularDataFromLevelsMap(levels);
+ }
+
+ @Override
+ public String getRuntimeRootLoggerLevel()
+ {
+ return _configurator.retrieveRuntimeRootLoggerLevel();
+ }
+
+ @Override
+ public boolean setRuntimeRootLoggerLevel(String level)
+ {
+ try
+ {
+ validateLevelNotAllowingInherited(level);
+ }
+ catch (IllegalArgumentException iae)
+ {
+ LOGGER.warn(level + " is not a known level");
+ return false;
+ }
+
+ _configurator.setRuntimeRootLoggerLevel(level);
+ return true;
+ }
+
+ @Override
+ public boolean setRuntimeLoggerLevel(String logger, String level)
+ {
+ String validatedLevel;
+ try
+ {
+ validatedLevel = getValidateLevelAllowingInherited(level);
+ }
+ catch (IllegalArgumentException iae)
+ {
+ LOGGER.warn(level + " is not a known level");
+ return false;
+ }
+
+ try
+ {
+ _configurator.setRuntimeLoggerLevel(logger, validatedLevel);
+ }
+ catch (LoggingFacadeException e)
+ {
+ LOGGER.error("Cannot set runtime logging level", e);
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public TabularData viewConfigFileLoggerLevels()
+ {
+ Map<String,String> levels;
+ try
+ {
+ levels = _configurator.retrieveConfigFileLoggersLevels();
+ }
+ catch (LoggingFacadeException e)
+ {
+ LOGGER.error("Cannot determine logging levels", e);
+ return null;
+ }
+
+ return createTabularDataFromLevelsMap(levels);
+ }
+
+ @Override
+ public String getConfigFileRootLoggerLevel()throws IOException
+ {
+ try
+ {
+ return _configurator.retrieveConfigFileRootLoggerLevel().toUpperCase();
+ }
+ catch (LoggingFacadeException e)
+ {
+ LOGGER.warn("The log4j configuration get config request was aborted: ", e);
+ throw new IOException("The log4j configuration get config request was aborted: " + e.getMessage());
+ }
+ }
+
+ @Override
+ public boolean setConfigFileLoggerLevel(String logger, String level)
+ {
+ String validatedLevel;
+ try
+ {
+ validatedLevel = getValidateLevelAllowingInherited(level);
+ }
+ catch (IllegalArgumentException iae)
+ {
+ LOGGER.warn(level + " is not a known level");
+ return false;
+ }
+
+ try
+ {
+ _configurator.setConfigFileLoggerLevel(logger, validatedLevel);
+ }
+ catch (LoggingFacadeException e)
+ {
+ LOGGER.warn("The log4j configuration set config request was aborted: ", e);
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public boolean setConfigFileRootLoggerLevel(String level)
+ {
+ try
+ {
+ validateLevelNotAllowingInherited(level);
+ }
+ catch (IllegalArgumentException iae)
+ {
+ LOGGER.warn(level + " is not a known level");
+ return false;
+ }
+
+ try
+ {
+ _configurator.setConfigFileRootLoggerLevel(level);
+ return true;
+ }
+ catch (LoggingFacadeException e)
+ {
+ LOGGER.warn("The log4j configuration set config request was aborted: ", e);
+ return false;
+ }
+ }
+
+ @Override
+ public void reloadConfigFile() throws IOException
+ {
+ try
+ {
+
+ _configurator.reload();
+ }
+ catch (LoggingFacadeException e)
+ {
+ LOGGER.warn("The log4j configuration reload request was aborted: ", e);
+ throw new IOException("The log4j configuration reload request was aborted: " + e.getMessage());
+ }
+ }
+
+ private String getValidateLevelAllowingInherited(String level)
+ {
+ if(level == null
+ || "null".equalsIgnoreCase(level)
+ || INHERITED_PSUEDO_LOG_LEVEL.equalsIgnoreCase(level))
+ {
+ //the string "null" or "inherited" signals to inherit from a parent logger,
+ //using a null Level reference for the logger.
+ return null;
+ }
+
+ validateLevelNotAllowingInherited(level);
+ return level;
+ }
+
+ private void validateLevelNotAllowingInherited(String level)
+ {
+ final List<String> availableLoggerLevels = _configurator.getAvailableLoggerLevels();
+ if (!availableLoggerLevels.contains(level)
+ && !availableLoggerLevels.contains(String.valueOf(level).toUpperCase()))
+ {
+ throw new IllegalArgumentException(level + " not known");
+ }
+ }
+
+ private TabularData createTabularDataFromLevelsMap(Map<String, String> levels)
+ {
+ TabularData loggerLevelList = new TabularDataSupport(LOGGER_LEVEL_TABULAR_TYE);
+ for (Map.Entry<String,String> entry : levels.entrySet())
+ {
+ String loggerName = entry.getKey();
+ String level = entry.getValue();
+
+ CompositeData loggerData = createRow(loggerName, level);
+ loggerLevelList.put(loggerData);
+ }
+ return loggerLevelList;
+ }
+
+
+ private CompositeData createRow(String loggerName, String level)
+ {
+ Object[] itemData = {loggerName, level.toUpperCase()};
+ try
+ {
+ CompositeData loggerData = new CompositeDataSupport(LOGGER_LEVEL_COMPOSITE_TYPE,
+ COMPOSITE_ITEM_NAMES.toArray(new String[COMPOSITE_ITEM_NAMES.size()]), itemData);
+ return loggerData;
+ }
+ catch (OpenDataException ode)
+ {
+ // Should not happen
+ throw new RuntimeException(ode);
+ }
+ }
+}
diff --git a/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/MBeanUtils.java b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/MBeanUtils.java
new file mode 100644
index 0000000000..97e84d4796
--- /dev/null
+++ b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/MBeanUtils.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.jmx.mbeans;
+
+import javax.management.OperationsException;
+
+import org.apache.qpid.server.model.ConfiguredObjectFinder;
+import org.apache.qpid.server.model.Exchange;
+import org.apache.qpid.server.model.Queue;
+import org.apache.qpid.server.model.VirtualHost;
+
+public class MBeanUtils
+{
+ public static Queue findQueueFromQueueName(VirtualHost virtualHost, String queueName) throws OperationsException
+ {
+ Queue queue = ConfiguredObjectFinder.findConfiguredObjectByName(virtualHost.getQueues(), queueName);
+ if (queue == null)
+ {
+ throw new OperationsException("No such queue \""+queueName+"\"");
+ }
+ else
+ {
+ return queue;
+ }
+ }
+
+ public static Exchange findExchangeFromExchangeName(VirtualHost virtualHost, String exchangeName) throws OperationsException
+ {
+ Exchange exchange = ConfiguredObjectFinder.findConfiguredObjectByName(virtualHost.getExchanges(), exchangeName);
+ if (exchange == null)
+ {
+ throw new OperationsException("No such exchange \""+exchangeName+"\"");
+ }
+ else
+ {
+ return exchange;
+ }
+ }
+}
diff --git a/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/QueueMBean.java b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/QueueMBean.java
new file mode 100644
index 0000000000..5c8b0f7194
--- /dev/null
+++ b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/QueueMBean.java
@@ -0,0 +1,668 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.jmx.mbeans;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicLong;
+import javax.management.JMException;
+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;
+import javax.management.openmbean.CompositeData;
+import javax.management.openmbean.CompositeDataSupport;
+import javax.management.openmbean.CompositeType;
+import javax.management.openmbean.OpenDataException;
+import javax.management.openmbean.OpenType;
+import javax.management.openmbean.SimpleType;
+import javax.management.openmbean.TabularData;
+import javax.management.openmbean.TabularDataSupport;
+import javax.management.openmbean.TabularType;
+import org.apache.commons.lang.time.FastDateFormat;
+import org.apache.log4j.Logger;
+import org.apache.qpid.management.common.mbeans.ManagedQueue;
+import org.apache.qpid.server.jmx.AMQManagedObject;
+import org.apache.qpid.server.jmx.ManagedObject;
+import org.apache.qpid.server.message.AMQMessageHeader;
+import org.apache.qpid.server.message.ServerMessage;
+import org.apache.qpid.server.model.Exchange;
+import org.apache.qpid.server.model.LifetimePolicy;
+import org.apache.qpid.server.model.Queue;
+import org.apache.qpid.server.model.QueueNotificationListener;
+import org.apache.qpid.server.model.VirtualHost;
+import org.apache.qpid.server.queue.NotificationCheck;
+import org.apache.qpid.server.queue.QueueEntry;
+import org.apache.qpid.server.queue.QueueEntryVisitor;
+
+public class QueueMBean extends AMQManagedObject implements ManagedQueue, QueueNotificationListener
+{
+ private static final Logger LOGGER = Logger.getLogger(QueueMBean.class);
+
+ private static final String[] VIEW_MSGS_COMPOSITE_ITEM_NAMES_DESC_ARRAY =
+ VIEW_MSGS_COMPOSITE_ITEM_NAMES_DESC.toArray(new String[VIEW_MSGS_COMPOSITE_ITEM_NAMES_DESC.size()]);
+
+ private static final OpenType[] MSG_ATTRIBUTE_TYPES;
+ private static final CompositeType MSG_DATA_TYPE;
+ private static final TabularType MSG_LIST_DATA_TYPE;
+ private static final CompositeType MSG_CONTENT_TYPE;
+ private static final String[] VIEW_MSG_COMPOSIT_ITEM_NAMES_ARRAY = VIEW_MSG_CONTENT_COMPOSITE_ITEM_NAMES_DESC.toArray(
+ new String[VIEW_MSG_CONTENT_COMPOSITE_ITEM_NAMES_DESC.size()]);
+
+ static
+ {
+
+ try
+ {
+ MSG_ATTRIBUTE_TYPES = new OpenType[] {
+ SimpleType.LONG, // For message id
+ new ArrayType(1, SimpleType.STRING), // For header attributes
+ SimpleType.LONG, // For size
+ SimpleType.BOOLEAN, // For redelivered
+ SimpleType.LONG, // For queue position
+ SimpleType.INTEGER // For delivery count}
+ };
+
+ MSG_DATA_TYPE = new CompositeType("Message", "AMQ Message",
+ VIEW_MSGS_COMPOSITE_ITEM_NAMES_DESC_ARRAY,
+ VIEW_MSGS_COMPOSITE_ITEM_NAMES_DESC_ARRAY, MSG_ATTRIBUTE_TYPES);
+
+ MSG_LIST_DATA_TYPE = new TabularType("Messages", "List of messages", MSG_DATA_TYPE,
+ VIEW_MSGS_TABULAR_UNIQUE_INDEX.toArray(new String[VIEW_MSGS_TABULAR_UNIQUE_INDEX.size()]));
+
+ OpenType[] msgContentAttrs = new OpenType[] {
+ SimpleType.LONG, // For message id
+ SimpleType.STRING, // For MimeType
+ SimpleType.STRING, // For MimeType
+ new ArrayType(SimpleType.BYTE, true) // For message content
+ };
+
+
+ MSG_CONTENT_TYPE = new CompositeType("Message Content", "AMQ Message Content",
+ VIEW_MSG_CONTENT_COMPOSITE_ITEM_NAMES_DESC.toArray(new String[VIEW_MSG_CONTENT_COMPOSITE_ITEM_NAMES_DESC.size()]),
+ VIEW_MSG_CONTENT_COMPOSITE_ITEM_NAMES_DESC.toArray(new String[VIEW_MSG_CONTENT_COMPOSITE_ITEM_NAMES_DESC.size()]),
+ msgContentAttrs);
+
+ }
+ catch (OpenDataException e)
+ {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private final Queue _queue;
+ private final VirtualHostMBean _vhostMBean;
+
+ /** Date/time format used for message expiration and message timestamp formatting */
+ public static final String JMSTIMESTAMP_DATETIME_FORMAT = "MM-dd-yy HH:mm:ss.SSS z";
+
+ private static final FastDateFormat FAST_DATE_FORMAT = FastDateFormat.getInstance(JMSTIMESTAMP_DATETIME_FORMAT);
+
+ public QueueMBean(Queue queue, VirtualHostMBean virtualHostMBean) throws JMException
+ {
+ super(ManagedQueue.class, ManagedQueue.TYPE, virtualHostMBean.getRegistry());
+ _queue = queue;
+ _vhostMBean = virtualHostMBean;
+ register();
+ _queue.setNotificationListener(this);
+ }
+
+ public ManagedObject getParentObject()
+ {
+ return _vhostMBean;
+ }
+
+ public String getObjectInstanceName()
+ {
+ return ObjectName.quote(getName());
+ }
+
+ public String getName()
+ {
+ return _queue.getName();
+ }
+
+ public Integer getMessageCount()
+ {
+ return getStatisticValue(Queue.QUEUE_DEPTH_MESSAGES).intValue();
+ }
+
+ public Integer getMaximumDeliveryCount()
+ {
+ return (Integer) _queue.getAttribute(Queue.MAXIMUM_DELIVERY_ATTEMPTS);
+ }
+
+ public Long getReceivedMessageCount()
+ {
+ return getStatisticValue(Queue.TOTAL_ENQUEUED_MESSAGES).longValue();
+ }
+
+ public Long getQueueDepth()
+ {
+ return getStatisticValue(Queue.QUEUE_DEPTH_BYTES).longValue();
+ }
+
+ public Integer getActiveConsumerCount()
+ {
+ return getStatisticValue(Queue.CONSUMER_COUNT_WITH_CREDIT).intValue();
+ }
+
+ public Integer getConsumerCount()
+ {
+ return getStatisticValue(Queue.CONSUMER_COUNT).intValue();
+ }
+
+ public String getOwner()
+ {
+ return (String) _queue.getAttribute(Queue.OWNER);
+ }
+
+ @Override
+ public String getQueueType()
+ {
+ return (String) _queue.getAttribute(Queue.TYPE);
+ }
+
+ public boolean isDurable()
+ {
+ return _queue.isDurable();
+ }
+
+ public boolean isAutoDelete()
+ {
+ return _queue.getLifetimePolicy() == LifetimePolicy.AUTO_DELETE;
+ }
+
+ public Long getMaximumMessageAge()
+ {
+ return (Long) _queue.getAttribute(Queue.ALERT_THRESHOLD_MESSAGE_AGE);
+ }
+
+ public void setMaximumMessageAge(Long age)
+ {
+ _queue.setAttribute(Queue.ALERT_THRESHOLD_MESSAGE_AGE, getMaximumMessageAge(), age);
+ }
+
+ public Long getMaximumMessageSize()
+ {
+ return (Long) _queue.getAttribute(Queue.ALERT_THRESHOLD_MESSAGE_SIZE);
+ }
+
+ public void setMaximumMessageSize(Long size)
+ {
+ _queue.setAttribute(Queue.ALERT_THRESHOLD_MESSAGE_SIZE, getMaximumMessageSize(), size);
+ }
+
+ public Long getMaximumMessageCount()
+ {
+ return (Long) _queue.getAttribute(Queue.ALERT_THRESHOLD_QUEUE_DEPTH_MESSAGES);
+ }
+
+ public void setMaximumMessageCount(Long value)
+ {
+ _queue.setAttribute(Queue.ALERT_THRESHOLD_QUEUE_DEPTH_MESSAGES, getMaximumMessageCount(), value);
+ }
+
+ public Long getMaximumQueueDepth()
+ {
+ return (Long) _queue.getAttribute(Queue.ALERT_THRESHOLD_QUEUE_DEPTH_BYTES);
+ }
+
+ public void setMaximumQueueDepth(Long value)
+ {
+ _queue.setAttribute(Queue.ALERT_THRESHOLD_QUEUE_DEPTH_BYTES, getMaximumQueueDepth(), value);
+ }
+
+ public Long getCapacity()
+ {
+ return (Long) _queue.getAttribute(Queue.QUEUE_FLOW_CONTROL_SIZE_BYTES);
+ }
+
+ public void setCapacity(Long value)
+ {
+ _queue.setAttribute(Queue.QUEUE_FLOW_CONTROL_SIZE_BYTES, getCapacity(), value);
+ }
+
+ public Long getFlowResumeCapacity()
+ {
+ return (Long) _queue.getAttribute(Queue.QUEUE_FLOW_RESUME_SIZE_BYTES);
+ }
+
+ public void setFlowResumeCapacity(Long value)
+ {
+ _queue.setAttribute(Queue.QUEUE_FLOW_RESUME_SIZE_BYTES, getFlowResumeCapacity(), value);
+ }
+
+ public boolean isFlowOverfull()
+ {
+ return (Boolean)_queue.getAttribute(Queue.QUEUE_FLOW_STOPPED);
+ }
+
+ public boolean isExclusive()
+ {
+ return (Boolean) _queue.getAttribute(Queue.EXCLUSIVE);
+ }
+
+ public void setExclusive(boolean exclusive)
+ {
+ _queue.setAttribute(Queue.EXCLUSIVE, isExclusive(), exclusive);
+ }
+
+ public void setAlternateExchange(String exchangeName) throws OperationsException
+ {
+ if (exchangeName == null || "".equals(exchangeName))
+ {
+ _queue.setAttribute(Queue.ALTERNATE_EXCHANGE, getAlternateExchange(), null);
+ }
+ else
+ {
+ VirtualHost virtualHost = _queue.getParent(VirtualHost.class);
+ Exchange exchange = MBeanUtils.findExchangeFromExchangeName(virtualHost, exchangeName);
+
+ _queue.setAttribute(Queue.ALTERNATE_EXCHANGE, getAlternateExchange(), exchange);
+ }
+ }
+
+ public String getAlternateExchange()
+ {
+ Exchange alternateExchange = (Exchange) _queue.getAttribute(Queue.ALTERNATE_EXCHANGE);
+ return alternateExchange == null ? null : alternateExchange.getName();
+ }
+
+ public TabularData viewMessages(int fromIndex, int toIndex)
+ throws IOException, JMException
+ {
+ return viewMessages((long)fromIndex, (long)toIndex);
+ }
+
+ public TabularData viewMessages(long startPosition, long endPosition)
+ throws IOException, JMException
+ {
+ if ((startPosition > endPosition) || (startPosition < 1))
+ {
+ throw new OperationsException("From Index = " + startPosition + ", To Index = " + endPosition
+ + "\n\"From Index\" should be greater than 0 and less than \"To Index\"");
+ }
+
+ if ((endPosition - startPosition) > Integer.MAX_VALUE)
+ {
+ throw new OperationsException("Specified MessageID interval is too large. Intervals must be less than 2^31 in size");
+ }
+
+
+ List<QueueEntry> messages = getMessages(startPosition, endPosition);
+
+ TabularDataSupport messageTable = new TabularDataSupport(MSG_LIST_DATA_TYPE);
+
+
+ // Create the tabular list of message header contents
+ long position = startPosition;
+
+ for (QueueEntry queueEntry : messages)
+ {
+ ServerMessage serverMsg = queueEntry.getMessage();
+ AMQMessageHeader header = serverMsg.getMessageHeader();
+ String[] headerAttributes =
+ {"reply-to = " + header.getReplyTo(),
+ "propertyFlags = ",
+ "ApplicationID = " + header.getAppId(),
+ "ClusterID = ",
+ "UserId = " + header.getUserId(),
+ "JMSMessageID = " + header.getMessageId(),
+ "JMSCorrelationID = " + header.getCorrelationId(),
+ "JMSDeliveryMode = " + (serverMsg.isPersistent() ? "Persistent" : "Non_Persistent"),
+ "JMSPriority = " + header.getPriority(),
+ "JMSType = " + header.getType(),
+ "JMSExpiration = " + (header.getExpiration() == 0 ? null : FAST_DATE_FORMAT.format(header.getExpiration())),
+ "JMSTimestamp = " + (header.getTimestamp() == 0 ? null : FAST_DATE_FORMAT.format(header.getTimestamp()))
+ };
+
+ Object[] itemValues = new Object[]{ serverMsg.getMessageNumber(),
+ headerAttributes,
+ serverMsg.getSize(),
+ queueEntry.isRedelivered(),
+ position,
+ queueEntry.getDeliveryCount()};
+
+ position++;
+
+ CompositeData messageData =
+ new CompositeDataSupport(MSG_DATA_TYPE, VIEW_MSGS_COMPOSITE_ITEM_NAMES_DESC_ARRAY, itemValues);
+ messageTable.put(messageData);
+ }
+
+ return messageTable;
+
+ }
+
+ public CompositeData viewMessageContent(long messageId)
+ throws IOException, JMException
+ {
+ QueueEntry entry = getMessage(messageId);
+ if(entry == null)
+ {
+ throw new OperationsException("AMQMessage with message id = " + messageId + " is not in the " + _queue.getName());
+ }
+
+ ServerMessage serverMsg = entry.getMessage();
+ final int bodySize = (int) serverMsg.getSize();
+
+ byte[] msgContent = new byte[bodySize];
+
+ ByteBuffer buf = ByteBuffer.wrap(msgContent);
+ int stored = serverMsg.getContent(buf, 0);
+
+ if(bodySize != stored)
+ {
+ LOGGER.error(String.format("An unexpected amount of content was retrieved " +
+ "(expected %d, got %d bytes) when viewing content for message with ID %d " +
+ "on queue '%s' in virtual host '%s'",
+ bodySize, stored, messageId, _queue.getName(), _vhostMBean.getName()));
+ }
+
+ AMQMessageHeader header = serverMsg.getMessageHeader();
+
+ String mimeType = null, encoding = null;
+ if (header != null)
+ {
+ mimeType = header.getMimeType();
+
+ encoding = header.getEncoding();
+ }
+
+
+ Object[] itemValues = { messageId, mimeType, encoding, msgContent };
+
+ return new CompositeDataSupport(MSG_CONTENT_TYPE, VIEW_MSG_COMPOSIT_ITEM_NAMES_ARRAY, itemValues);
+
+
+ }
+
+ private QueueEntry getMessage(long messageId)
+ {
+ GetMessageVisitor visitor = new GetMessageVisitor(messageId);
+ _queue.visit(visitor);
+ return visitor.getEntry();
+ }
+
+ public void deleteMessageFromTop() throws IOException, JMException
+ {
+ VirtualHost vhost = _queue.getParent(VirtualHost.class);
+ vhost.executeTransaction(new VirtualHost.TransactionalOperation()
+ {
+ public void withinTransaction(final VirtualHost.Transaction txn)
+ {
+ _queue.visit(new QueueEntryVisitor()
+ {
+
+ public boolean visit(final QueueEntry entry)
+ {
+ if(entry.acquire())
+ {
+ txn.dequeue(entry);
+ return true;
+ }
+ return false;
+ }
+ });
+
+ }
+ });
+
+ }
+
+ public Long clearQueue() throws IOException, JMException
+ {
+ VirtualHost vhost = _queue.getParent(VirtualHost.class);
+ final AtomicLong count = new AtomicLong();
+
+ vhost.executeTransaction(new VirtualHost.TransactionalOperation()
+ {
+ public void withinTransaction(final VirtualHost.Transaction txn)
+ {
+ _queue.visit(new QueueEntryVisitor()
+ {
+
+ public boolean visit(final QueueEntry entry)
+ {
+ final ServerMessage message = entry.getMessage();
+ if(message != null)
+ {
+ txn.dequeue(entry);
+ count.incrementAndGet();
+
+ }
+ return false;
+ }
+ });
+
+ }
+ });
+ return count.get();
+ }
+
+ public void moveMessages(final long fromMessageId, final long toMessageId, String toQueue)
+ throws IOException, JMException
+ {
+ if ((fromMessageId > toMessageId) || (fromMessageId < 1))
+ {
+ throw new OperationsException("\"From MessageId\" should be greater than 0 and less than \"To MessageId\"");
+ }
+
+ VirtualHost vhost = _queue.getParent(VirtualHost.class);
+ final Queue destinationQueue = MBeanUtils.findQueueFromQueueName(vhost, toQueue);
+
+ vhost.executeTransaction(new VirtualHost.TransactionalOperation()
+ {
+ public void withinTransaction(final VirtualHost.Transaction txn)
+ {
+ _queue.visit(new QueueEntryVisitor()
+ {
+
+ public boolean visit(final QueueEntry entry)
+ {
+ final ServerMessage message = entry.getMessage();
+ if(message != null)
+ {
+ final long messageId = message.getMessageNumber();
+
+ if ((messageId >= fromMessageId)
+ && (messageId <= toMessageId))
+ {
+ txn.move(entry, destinationQueue);
+ }
+
+ }
+ return false;
+ }
+ });
+ }
+ });
+ }
+
+ public void deleteMessages(final long fromMessageId, final long toMessageId)
+ throws IOException, JMException
+ {
+ VirtualHost vhost = _queue.getParent(VirtualHost.class);
+ vhost.executeTransaction(new VirtualHost.TransactionalOperation()
+ {
+ public void withinTransaction(final VirtualHost.Transaction txn)
+ {
+ _queue.visit(new QueueEntryVisitor()
+ {
+
+ public boolean visit(final QueueEntry entry)
+ {
+ final ServerMessage message = entry.getMessage();
+ if(message != null)
+ {
+ final long messageId = message.getMessageNumber();
+
+ if ((messageId >= fromMessageId)
+ && (messageId <= toMessageId))
+ {
+ txn.dequeue(entry);
+ return true;
+ }
+ return false;
+ }
+ return true;
+ }
+ });
+ }
+ });
+ }
+
+ public void copyMessages(final long fromMessageId, final long toMessageId, String toQueue)
+ throws IOException, JMException
+ {
+ if ((fromMessageId > toMessageId) || (fromMessageId < 1))
+ {
+ throw new OperationsException("\"From MessageId\" should be greater than 0 and less than \"To MessageId\"");
+ }
+
+ VirtualHost vhost = _queue.getParent(VirtualHost.class);
+ final Queue destinationQueue = MBeanUtils.findQueueFromQueueName(vhost, toQueue);
+
+ vhost.executeTransaction(new VirtualHost.TransactionalOperation()
+ {
+ public void withinTransaction(final VirtualHost.Transaction txn)
+ {
+ _queue.visit(new QueueEntryVisitor()
+ {
+
+ public boolean visit(final QueueEntry entry)
+ {
+ final ServerMessage message = entry.getMessage();
+ if(message != null)
+ {
+ final long messageId = message.getMessageNumber();
+
+ if ((messageId >= fromMessageId)
+ && (messageId <= toMessageId))
+ {
+ txn.copy(entry, destinationQueue);
+ }
+
+ }
+ return false;
+ }
+ });
+ }
+ });
+ }
+
+ private List<QueueEntry> getMessages(final long first, final long last)
+ {
+ final List<QueueEntry> messages = new ArrayList<QueueEntry>((int)(last-first)+1);
+ _queue.visit(new QueueEntryVisitor()
+ {
+ private long position = 1;
+
+ public boolean visit(QueueEntry entry)
+ {
+ if(position >= first && position <= last)
+ {
+ messages.add(entry);
+ }
+ position++;
+ return position > last;
+ }
+ });
+ return messages;
+ }
+
+
+ protected static class GetMessageVisitor implements QueueEntryVisitor
+ {
+
+ private final long _messageNumber;
+ private QueueEntry _entry;
+
+ public GetMessageVisitor(long messageId)
+ {
+ _messageNumber = messageId;
+ }
+
+ public boolean visit(QueueEntry entry)
+ {
+ if(entry.getMessage().getMessageNumber() == _messageNumber)
+ {
+ _entry = entry;
+ return true;
+ }
+ return false;
+ }
+
+ public QueueEntry getEntry()
+ {
+ return _entry;
+ }
+ }
+
+ @Override
+ public void notifyClients(NotificationCheck notification, Queue queue, String notificationMsg)
+ {
+ notificationMsg = notification.name() + " " + notificationMsg;
+
+ Notification note = new Notification(MonitorNotification.THRESHOLD_VALUE_EXCEEDED, this,
+ incrementAndGetSequenceNumber(), System.currentTimeMillis(), notificationMsg);
+
+ getBroadcaster().sendNotification(note);
+ }
+
+ /**
+ * returns Notifications sent by this MBean.
+ */
+ @Override
+ public MBeanNotificationInfo[] getNotificationInfo()
+ {
+ String[] notificationTypes = new String[] { MonitorNotification.THRESHOLD_VALUE_EXCEEDED };
+ String name = MonitorNotification.class.getName();
+ String description = "Either Message count or Queue depth or Message size has reached threshold high value";
+ MBeanNotificationInfo info1 = new MBeanNotificationInfo(notificationTypes, name, description);
+
+ return new MBeanNotificationInfo[] { info1 };
+ }
+
+ @Override
+ public String getDescription()
+ {
+ return (String) _queue.getAttribute(Queue.DESCRIPTION);
+ }
+
+ @Override
+ public void setDescription(String description)
+ {
+ _queue.setAttribute(Queue.DESCRIPTION, getDescription(), description);
+ }
+
+ private Number getStatisticValue(String name)
+ {
+ final Number statistic = (Number) _queue.getStatistics().getStatistic(name);
+ return statistic == null ? Integer.valueOf(0) : statistic;
+ }
+}
diff --git a/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/ServerInformationMBean.java b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/ServerInformationMBean.java
new file mode 100644
index 0000000000..67d5861dec
--- /dev/null
+++ b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/ServerInformationMBean.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.server.jmx.mbeans;
+
+import java.io.IOException;
+
+import javax.management.JMException;
+import javax.management.NotCompliantMBeanException;
+
+import org.apache.qpid.management.common.mbeans.ServerInformation;
+import org.apache.qpid.management.common.mbeans.annotations.MBeanDescription;
+import org.apache.qpid.server.jmx.ManagedObject;
+import org.apache.qpid.server.jmx.ManagedObjectRegistry;
+import org.apache.qpid.server.model.Broker;
+
+@MBeanDescription("Server Information Interface")
+public class ServerInformationMBean extends AbstractStatisticsGatheringMBean<Broker> implements ServerInformation
+{
+ private final Broker _broker;
+
+ public ServerInformationMBean(ManagedObjectRegistry registry, Broker broker)
+ throws NotCompliantMBeanException, JMException
+ {
+ super(ServerInformation.class, ServerInformation.TYPE, registry, broker);
+ _broker = broker;
+
+ register();
+ }
+
+ @Override
+ public String getObjectInstanceName()
+ {
+ return ServerInformation.TYPE;
+ }
+
+ @Override
+ public Integer getManagementApiMajorVersion() throws IOException
+ {
+ return QPID_JMX_API_MAJOR_VERSION;
+ }
+
+ @Override
+ public Integer getManagementApiMinorVersion() throws IOException
+ {
+ return QPID_JMX_API_MINOR_VERSION;
+ }
+
+ @Override
+ public String getBuildVersion() throws IOException
+ {
+ return (String) _broker.getAttribute(Broker.BUILD_VERSION);
+ }
+
+ @Override
+ public String getProductVersion() throws IOException
+ {
+ return (String) _broker.getAttribute(Broker.PRODUCT_VERSION);
+ }
+
+ @Override
+ public boolean isStatisticsEnabled()
+ {
+ return true;
+ }
+
+ @Override
+ public ManagedObject getParentObject()
+ {
+ // does not have a parent
+ return null;
+ }
+}
diff --git a/java/broker-plugins/experimental/shutdown/src/main/java/org/apache/qpid/shutdown/Shutdown.java b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/Shutdown.java
index cef4a42b64..62733168ef 100644
--- a/java/broker-plugins/experimental/shutdown/src/main/java/org/apache/qpid/shutdown/Shutdown.java
+++ b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/Shutdown.java
@@ -17,8 +17,14 @@
* under the License.
*
*/
-package org.apache.qpid.shutdown;
+package org.apache.qpid.server.jmx.mbeans;
+import org.apache.log4j.Logger;
+import org.apache.qpid.server.jmx.DefaultManagedObject;
+import org.apache.qpid.server.jmx.ManagedObject;
+import org.apache.qpid.server.jmx.ManagedObjectRegistry;
+
+import javax.management.JMException;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
@@ -27,11 +33,6 @@ import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
-import javax.management.NotCompliantMBeanException;
-
-import org.apache.log4j.Logger;
-import org.apache.qpid.server.management.DefaultManagedObject;
-
/**
* Implementation of the JMX broker shutdown plugin.
*/
@@ -46,9 +47,10 @@ public class Shutdown extends DefaultManagedObject implements ShutdownMBean
private final Runnable _shutdown = new SystemExiter();
- public Shutdown() throws NotCompliantMBeanException
+ public Shutdown(ManagedObjectRegistry registry) throws JMException
{
- super(ShutdownMBean.class, ShutdownMBean.TYPE);
+ super(ShutdownMBean.class, ShutdownMBean.TYPE, registry);
+ register();
}
/** @see ShutdownMBean#shutdown() */
@@ -108,6 +110,12 @@ public class Shutdown extends DefaultManagedObject implements ShutdownMBean
EXECUTOR.schedule(_shutdown, delay, TimeUnit.MILLISECONDS);
}
+ @Override
+ public ManagedObject getParentObject()
+ {
+ return null;
+ }
+
/**
* Shutting down the system in another thread to avoid JMX exceptions being thrown.
*/
@@ -120,9 +128,8 @@ public class Shutdown extends DefaultManagedObject implements ShutdownMBean
}
/**
- * @see org.apache.qpid.server.management.ManagedObject#getObjectInstanceName()
+ * @see ManagedObject#getObjectInstanceName()
*/
- @Override
public String getObjectInstanceName()
{
return "Shutdown";
diff --git a/java/broker-plugins/experimental/shutdown/src/main/java/org/apache/qpid/shutdown/ShutdownMBean.java b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/ShutdownMBean.java
index 5c54fb3e21..ed69c351f7 100644
--- a/java/broker-plugins/experimental/shutdown/src/main/java/org/apache/qpid/shutdown/ShutdownMBean.java
+++ b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/ShutdownMBean.java
@@ -17,13 +17,13 @@
* under the License.
*
*/
-package org.apache.qpid.shutdown;
-
-import javax.management.MBeanOperationInfo;
+package org.apache.qpid.server.jmx.mbeans;
import org.apache.qpid.management.common.mbeans.annotations.MBeanOperation;
import org.apache.qpid.management.common.mbeans.annotations.MBeanOperationParameter;
+import javax.management.MBeanOperationInfo;
+
/**
* Shutdown plugin JMX MBean interface.
*
@@ -45,7 +45,7 @@ public interface ShutdownMBean
* @param delay the number of ms to wait
*/
@MBeanOperation(name="shutdown", description="Shutdown after the specified delay (ms)", impact = MBeanOperationInfo.ACTION)
- public void shutdown(@MBeanOperationParameter(name="when", description="delay (ms)")long delay);
+ public void shutdown(@MBeanOperationParameter(name = "when", description = "delay (ms)") long delay);
/**
* Broker will be shutdown at the specified date and time.
@@ -53,5 +53,6 @@ public interface ShutdownMBean
* @param when the date and time to shutdown
*/
@MBeanOperation(name="shutdownAt", description="Shutdown at the specified date and time (yyyy/MM/dd HH:mm:ss)", impact = MBeanOperationInfo.ACTION)
- public void shutdownAt(@MBeanOperationParameter(name="when", description="shutdown date/time (yyyy/MM/dd HH:mm:ss)")String when);
+ public void shutdownAt(@MBeanOperationParameter(name = "when",
+ description = "shutdown date/time (yyyy/MM/dd HH:mm:ss)") String when);
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/auth/management/AMQUserManagementMBean.java b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/UserManagementMBean.java
index 1314a5d6a6..c7aade34b4 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/security/auth/management/AMQUserManagementMBean.java
+++ b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/UserManagementMBean.java
@@ -18,16 +18,16 @@
*
*
*/
-package org.apache.qpid.server.security.auth.management;
+package org.apache.qpid.server.jmx.mbeans;
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.security.auth.database.PrincipalDatabase;
-import org.apache.qpid.server.security.auth.sasl.UsernamePrincipal;
+import org.apache.qpid.server.jmx.AMQManagedObject;
+import org.apache.qpid.server.jmx.ManagedObject;
+import org.apache.qpid.server.jmx.ManagedObjectRegistry;
+import org.apache.qpid.server.model.PasswordCredentialManagingAuthenticationProvider;
import javax.management.JMException;
import javax.management.openmbean.CompositeData;
@@ -40,17 +40,16 @@ import javax.management.openmbean.TabularData;
import javax.management.openmbean.TabularDataSupport;
import javax.management.openmbean.TabularType;
import javax.security.auth.login.AccountNotFoundException;
+
import java.io.IOException;
-import java.security.Principal;
-import java.util.List;
+import java.util.Map;
-/** MBean class for AMQUserManagementMBean. It implements all the management features exposed for managing users. */
@MBeanDescription("User Management Interface")
-public class AMQUserManagementMBean extends AMQManagedObject implements UserManagement
+public class UserManagementMBean extends AMQManagedObject implements UserManagement
{
- private static final Logger _logger = Logger.getLogger(AMQUserManagementMBean.class);
+ private static final Logger _logger = Logger.getLogger(UserManagementMBean.class);
- private PrincipalDatabase _principalDatabase;
+ private PasswordCredentialManagingAuthenticationProvider _authProvider;
// Setup for the TabularType
private static final TabularType _userlistDataType; // Datatype for representing User Lists
@@ -79,45 +78,46 @@ public class AMQUserManagementMBean extends AMQManagedObject implements UserMana
}
}
- public AMQUserManagementMBean() throws JMException
+ public UserManagementMBean(PasswordCredentialManagingAuthenticationProvider provider, ManagedObjectRegistry registry) throws JMException
{
- super(UserManagement.class, UserManagement.TYPE);
+ super(UserManagement.class, UserManagement.TYPE, registry);
+ register();
+ _authProvider = provider;
}
+ @Override
public String getObjectInstanceName()
{
return UserManagement.TYPE;
}
+ @Override
public boolean setPassword(String username, String password)
{
try
{
- //delegate password changes to the Principal Database
- return _principalDatabase.updatePassword(new UsernamePrincipal(username), password.toCharArray());
+ _authProvider.setPassword(username, password);
}
catch (AccountNotFoundException e)
{
- _logger.warn("Attempt to set password of non-existent user'" + username + "'");
+ _logger.warn("Attempt to set password of non-existent user '" + username + "'");
return false;
}
+ return true;
}
+ @Override
public boolean createUser(String username, String password)
{
- if (_principalDatabase.createPrincipal(new UsernamePrincipal(username), password.toCharArray()))
- {
- return true;
- }
-
- return false;
+ return _authProvider.createUser(username, password, null);
}
+ @Override
public boolean deleteUser(String username)
{
try
{
- _principalDatabase.deletePrincipal(new UsernamePrincipal(username));
+ _authProvider.deleteUser(username);
}
catch (AccountNotFoundException e)
{
@@ -128,37 +128,36 @@ public class AMQUserManagementMBean extends AMQManagedObject implements UserMana
return true;
}
+ @Override
public boolean reloadData()
{
try
{
- _principalDatabase.reload();
+ _authProvider.reload();
+ return true;
}
catch (IOException e)
{
- _logger.warn("Reload failed due to:", e);
+ _logger.error("Unable to reload user data", e);
return false;
}
- // Reload successful
- return true;
}
-
- @MBeanOperation(name = "viewUsers", description = "All users that are currently available to the system.")
+ @Override
public TabularData viewUsers()
{
- List<Principal> users = _principalDatabase.getUsers();
+ Map<String, Map<String, String>> users = _authProvider.getUsers();
TabularDataSupport userList = new TabularDataSupport(_userlistDataType);
try
{
// Create the tabular list of message header contents
- for (Principal user : users)
+ for (String user : users.keySet())
{
// Create header attributes list
- // Read,Write,Admin items are depcreated and we return always false.
- Object[] itemData = {user.getName(), false, false, false};
+ // Read,Write,Admin items are deprecated and we return always false.
+ Object[] itemData = {user, false, false, false};
CompositeData messageData = new CompositeDataSupport(_userDataType, COMPOSITE_ITEM_NAMES.toArray(new String[COMPOSITE_ITEM_NAMES.size()]), itemData);
userList.put(messageData);
}
@@ -172,15 +171,9 @@ public class AMQUserManagementMBean extends AMQManagedObject implements UserMana
return userList;
}
- /*** Broker Methods **/
-
- /**
- * setPrincipalDatabase
- *
- * @param database set The Database to use for user lookup
- */
- public void setPrincipalDatabase(PrincipalDatabase database)
+ @Override
+ public ManagedObject getParentObject()
{
- _principalDatabase = database;
+ return null;
}
}
diff --git a/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/VirtualHostMBean.java b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/VirtualHostMBean.java
new file mode 100644
index 0000000000..6990a40dee
--- /dev/null
+++ b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/VirtualHostMBean.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.server.jmx.mbeans;
+
+import org.apache.log4j.Logger;
+import org.apache.qpid.server.jmx.AMQManagedObject;
+import org.apache.qpid.server.jmx.ManagedObject;
+import org.apache.qpid.server.jmx.ManagedObjectRegistry;
+import org.apache.qpid.server.model.ConfigurationChangeListener;
+import org.apache.qpid.server.model.ConfiguredObject;
+import org.apache.qpid.server.model.Connection;
+import org.apache.qpid.server.model.Exchange;
+import org.apache.qpid.server.model.Queue;
+import org.apache.qpid.server.model.State;
+import org.apache.qpid.server.model.VirtualHost;
+import org.apache.qpid.server.virtualhost.ManagedVirtualHost;
+
+import javax.management.JMException;
+import javax.management.ObjectName;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
+public class VirtualHostMBean extends AMQManagedObject implements ManagedVirtualHost, ConfigurationChangeListener
+{
+ private static final Logger LOGGER = Logger.getLogger(VirtualHostMBean.class);
+
+ private final VirtualHost _virtualHost;
+
+ private final Map<ConfiguredObject, AMQManagedObject> _children =
+ new HashMap<ConfiguredObject, AMQManagedObject>();
+ private VirtualHostManagerMBean _managerMBean;
+
+ public VirtualHostMBean(VirtualHost virtualHost, ManagedObjectRegistry registry) throws JMException
+ {
+ super(ManagedVirtualHost.class, ManagedVirtualHost.TYPE, registry);
+ _virtualHost = virtualHost;
+ virtualHost.addChangeListener(this);
+
+ initQueues();
+ initExchanges();
+ initConnections();
+
+ //This is the actual JMX bean for this 'VirtualHostMBean', leave it alone.
+ _managerMBean = new VirtualHostManagerMBean(this);
+ }
+
+ private void initQueues() throws JMException
+ {
+ synchronized (_children)
+ {
+ for(Queue queue : _virtualHost.getQueues())
+ {
+ if(!_children.containsKey(queue))
+ {
+ _children.put(queue, new QueueMBean(queue, this));
+ }
+ }
+ }
+ }
+
+ private void initExchanges() throws JMException
+ {
+ synchronized (_children)
+ {
+ for(Exchange exchange : _virtualHost.getExchanges())
+ {
+ if(!_children.containsKey(exchange))
+ {
+ _children.put(exchange, new ExchangeMBean(exchange, this));
+ }
+ }
+ }
+ }
+
+ private void initConnections() throws JMException
+ {
+ synchronized (_children)
+ {
+ for(Connection conn : _virtualHost.getConnections())
+ {
+ if(!_children.containsKey(conn))
+ {
+ _children.put(conn, new ConnectionMBean(conn, this));
+ }
+ }
+ }
+ }
+
+ public String getObjectInstanceName()
+ {
+ return ObjectName.quote(_virtualHost.getName());
+ }
+
+ public String getName()
+ {
+ return _virtualHost.getName();
+ }
+
+ public void stateChanged(ConfiguredObject object, State oldState, State newState)
+ {
+ // ignore
+ }
+
+ public void childAdded(ConfiguredObject object, ConfiguredObject child)
+ {
+ synchronized (_children)
+ {
+ try
+ {
+ if(child instanceof Queue)
+ {
+ QueueMBean queueMB = new QueueMBean((Queue)child, this);
+ _children.put(child, queueMB);
+
+ }
+ else if(child instanceof Exchange)
+ {
+ ExchangeMBean exchangeMBean = new ExchangeMBean((Exchange)child, this);
+ _children.put(child, exchangeMBean);
+
+ }
+ else if(child instanceof Connection)
+ {
+ ConnectionMBean connectionMBean = new ConnectionMBean((Connection)child, this);
+ _children.put(child, connectionMBean);
+
+ }
+ else
+ {
+ LOGGER.debug("Unsupported child : " + child.getName() + " type : " + child.getClass());
+ }
+
+ }
+ catch(JMException e)
+ {
+ LOGGER.error("Failed to add mbean for child : " + child.getName(), e);
+ }
+ }
+ }
+
+ public void childRemoved(ConfiguredObject object, ConfiguredObject child)
+ {
+ synchronized (_children)
+ {
+ AMQManagedObject mbean = _children.remove(child);
+ if(mbean != null)
+ {
+ try
+ {
+ mbean.unregister();
+ }
+ catch(JMException e)
+ {
+ LOGGER.error("Failed to remove mbean for child : " + child.getName(), e);
+ }
+ }
+ }
+ }
+
+ @Override
+ public ManagedObject getParentObject()
+ {
+ return null;
+ }
+
+ protected VirtualHost getVirtualHost()
+ {
+ return _virtualHost;
+ }
+
+ public Collection<QueueMBean> getQueues()
+ {
+ Collection<AMQManagedObject> children;
+ synchronized (_children)
+ {
+ children = new ArrayList<AMQManagedObject>(_children.values());
+ }
+ Collection<QueueMBean> queues = new ArrayList<QueueMBean>();
+
+ for(AMQManagedObject child : children)
+ {
+ if(child instanceof QueueMBean)
+ {
+ queues.add((QueueMBean) child);
+ }
+ }
+
+ return queues;
+ }
+}
diff --git a/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/VirtualHostManagerMBean.java b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/VirtualHostManagerMBean.java
new file mode 100644
index 0000000000..b3dbbc424a
--- /dev/null
+++ b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/VirtualHostManagerMBean.java
@@ -0,0 +1,238 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+package org.apache.qpid.server.jmx.mbeans;
+
+import java.io.IOException;
+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 javax.management.JMException;
+import javax.management.MBeanException;
+import javax.management.MalformedObjectNameException;
+import javax.management.ObjectName;
+import javax.management.OperationsException;
+
+import org.apache.log4j.Logger;
+import org.apache.qpid.management.common.mbeans.ManagedBroker;
+import org.apache.qpid.management.common.mbeans.ManagedQueue;
+import org.apache.qpid.management.common.mbeans.annotations.MBeanConstructor;
+import org.apache.qpid.management.common.mbeans.annotations.MBeanDescription;
+import org.apache.qpid.management.common.mbeans.annotations.MBeanOperationParameter;
+import org.apache.qpid.server.jmx.ManagedObject;
+import org.apache.qpid.server.model.Exchange;
+import org.apache.qpid.server.model.LifetimePolicy;
+import org.apache.qpid.server.model.Queue;
+import org.apache.qpid.server.model.State;
+import org.apache.qpid.server.model.VirtualHost;
+import org.apache.qpid.server.queue.AMQQueueFactory;
+
+@MBeanDescription("This MBean exposes the broker level management features")
+public class VirtualHostManagerMBean extends AbstractStatisticsGatheringMBean<VirtualHost> implements ManagedBroker
+{
+ private static final Logger LOGGER = Logger.getLogger(VirtualHostManagerMBean.class);
+
+ private static final boolean _moveNonExclusiveQueueOwnerToDescription = Boolean.parseBoolean(System.getProperty("qpid.move_non_exclusive_queue_owner_to_description", Boolean.TRUE.toString()));
+
+ private final VirtualHostMBean _virtualHostMBean;
+
+ @MBeanConstructor("Creates the Broker Manager MBean")
+ public VirtualHostManagerMBean(VirtualHostMBean virtualHostMBean) throws JMException
+ {
+ super(ManagedBroker.class, ManagedBroker.TYPE, virtualHostMBean.getRegistry(), virtualHostMBean.getVirtualHost());
+ _virtualHostMBean = virtualHostMBean;
+ register();
+ }
+
+
+ @Override
+ public String getObjectInstanceName()
+ {
+ return ObjectName.quote(_virtualHostMBean.getName());
+ }
+
+ @Override
+ public ManagedObject getParentObject()
+ {
+ return _virtualHostMBean;
+ }
+
+ @Override
+ public String[] getExchangeTypes() throws IOException
+ {
+ Collection<String> exchangeTypes = _virtualHostMBean.getVirtualHost().getExchangeTypes();
+ return exchangeTypes.toArray(new String[exchangeTypes.size()]);
+ }
+
+ @Override
+ public List<String> retrieveQueueAttributeNames() throws IOException
+ {
+ return ManagedQueue.QUEUE_ATTRIBUTES;
+ }
+
+ @Override
+ public List<List<Object>> retrieveQueueAttributeValues(
+ @MBeanOperationParameter(name = "attributes", description = "Attributes to retrieve") String[] attributes)
+ throws IOException
+ {
+ int attributesLength = attributes.length;
+
+ List<List<Object>> queueAttributesList = new ArrayList<List<Object>>();
+
+ for(QueueMBean queue : _virtualHostMBean.getQueues())
+ {
+
+ if(queue == null)
+ {
+ continue;
+ }
+
+ List<Object> attributeValues = new ArrayList<Object>(attributesLength);
+
+ for(int i=0; i < attributesLength; i++)
+ {
+ try
+ {
+ attributeValues.add(queue.getAttribute(attributes[i]));
+ }
+ catch (Exception e)
+ {
+ attributeValues.add("-");
+ }
+ }
+
+ queueAttributesList.add(attributeValues);
+ }
+
+ return queueAttributesList;
+
+ }
+
+ @Override
+ public void createNewExchange(String name, String type, boolean durable)
+ throws IOException, JMException, MBeanException
+ {
+ if (!getConfiguredObject().getExchangeTypes().contains(type))
+ {
+ throw new OperationsException("No such exchange type \""+type+"\"");
+ }
+
+ try
+ {
+ getConfiguredObject().createExchange(name, State.ACTIVE, durable,
+ LifetimePolicy.PERMANENT, 0l, type, Collections.EMPTY_MAP);
+ }
+ catch (IllegalArgumentException iae)
+ {
+ JMException jme = new JMException(iae.toString());
+ throw new MBeanException(jme, "Error in creating exchange " + name);
+ }
+
+ }
+
+ @Override
+ public void unregisterExchange(String exchangeName)
+ throws IOException, JMException, MBeanException
+ {
+ Exchange theExchange = MBeanUtils.findExchangeFromExchangeName(_virtualHostMBean.getVirtualHost(), exchangeName);
+ try
+ {
+ theExchange.delete();
+ }
+ catch (IllegalStateException ex)
+ {
+ final JMException jme = new JMException(ex.toString());
+ throw new MBeanException(jme, "Error in unregistering exchange " + exchangeName);
+ }
+ }
+
+ @Override
+ public void createNewQueue(String queueName, String owner, boolean durable)
+ throws IOException, JMException, MBeanException
+ {
+ createNewQueue(queueName, owner, durable, Collections.EMPTY_MAP);
+ }
+
+ @Override
+ public void createNewQueue(String queueName, String owner, boolean durable, Map<String, Object> originalArguments)
+ throws IOException, JMException
+ {
+ final Map<String, Object> createArgs = processNewQueueArguments(queueName, owner, originalArguments);
+ getConfiguredObject().createQueue(queueName, State.ACTIVE, durable, false, LifetimePolicy.PERMANENT, 0l, createArgs);
+ }
+
+
+ /**
+ * Some users have been abusing the owner field to store a queue description. As the owner field
+ * only makes sense if exclusive=true, and it is currently impossible to create an exclusive queue via
+ * the JMX interface, if the user specifies a owner, then we assume that they actually mean to pass a description.
+ */
+ private Map<String, Object> processNewQueueArguments(String queueName,
+ String owner, Map<String, Object> arguments)
+ {
+ final Map<String, Object> argumentsCopy;
+ if (_moveNonExclusiveQueueOwnerToDescription && owner != null)
+ {
+ argumentsCopy = new HashMap<String, Object>(arguments == null ? new HashMap<String, Object>() : arguments);
+ if (!argumentsCopy.containsKey(AMQQueueFactory.X_QPID_DESCRIPTION))
+ {
+ LOGGER.warn("Non-exclusive owner " + owner + " for new queue " + queueName + " moved to " + AMQQueueFactory.X_QPID_DESCRIPTION);
+
+ argumentsCopy.put(AMQQueueFactory.X_QPID_DESCRIPTION, owner);
+ }
+ else
+ {
+ LOGGER.warn("Non-exclusive owner " + owner + " for new queue " + queueName + " ignored.");
+ }
+ }
+ else
+ {
+ argumentsCopy = arguments;
+ }
+ return argumentsCopy;
+ }
+
+ @Override
+ public void deleteQueue(
+ @MBeanOperationParameter(name = ManagedQueue.TYPE, description = "Queue Name") String queueName)
+ throws IOException, JMException, MBeanException
+ {
+ Queue theQueue = MBeanUtils.findQueueFromQueueName(_virtualHostMBean.getVirtualHost(), queueName);
+ theQueue.delete();
+ }
+
+ @Override
+ public ObjectName getObjectName() throws MalformedObjectNameException
+ {
+ return getObjectNameForSingleInstanceMBean();
+ }
+
+ public synchronized boolean isStatisticsEnabled()
+ {
+ updateStats();
+ return false; //TODO - implement isStatisticsEnabled
+ }
+
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/management/NoopManagedObjectRegistry.java b/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/NoopManagedObjectRegistry.java
index e77350c3e4..a2631bab7f 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/management/NoopManagedObjectRegistry.java
+++ b/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/NoopManagedObjectRegistry.java
@@ -18,29 +18,18 @@
* under the License.
*
*/
-package org.apache.qpid.server.management;
-
-import org.apache.log4j.Logger;
+package org.apache.qpid.server.jmx;
import javax.management.JMException;
-/**
- * This managed object registry does not actually register MBeans. This can be used in tests when management is
- * not required or when management has been disabled.
- *
- */
public class NoopManagedObjectRegistry implements ManagedObjectRegistry
{
- private static final Logger _log = Logger.getLogger(NoopManagedObjectRegistry.class);
-
public NoopManagedObjectRegistry()
{
- _log.info("Management is disabled");
}
public void start()
{
- //no-op
}
public void registerObject(ManagedObject managedObject) throws JMException
@@ -53,6 +42,5 @@ public class NoopManagedObjectRegistry implements ManagedObjectRegistry
public void close()
{
-
}
}
diff --git a/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/ConnectionMBeanTest.java b/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/ConnectionMBeanTest.java
new file mode 100644
index 0000000000..0c5fb0bf1f
--- /dev/null
+++ b/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/ConnectionMBeanTest.java
@@ -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.
+ */
+package org.apache.qpid.server.jmx.mbeans;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.util.Collections;
+import java.util.Date;
+
+import javax.management.JMException;
+import javax.management.openmbean.CompositeData;
+import javax.management.openmbean.TabularData;
+
+import junit.framework.TestCase;
+
+import org.apache.qpid.management.common.mbeans.ManagedConnection;
+import org.apache.qpid.server.jmx.ManagedObject;
+import org.apache.qpid.server.jmx.ManagedObjectRegistry;
+import org.apache.qpid.server.model.Connection;
+import org.apache.qpid.server.model.Session;
+import org.apache.qpid.server.model.Statistics;
+
+public class ConnectionMBeanTest extends TestCase
+{
+ private ConnectionMBean _connectionMBean;
+ private Connection _mockConnection;
+ private VirtualHostMBean _mockVirtualHostMBean;
+ private ManagedObjectRegistry _mockManagedObjectRegistry;
+
+ @Override
+ protected void setUp() throws Exception
+ {
+ _mockConnection = mock(Connection.class);
+ _mockVirtualHostMBean = mock(VirtualHostMBean.class);
+
+ _mockManagedObjectRegistry = mock(ManagedObjectRegistry.class);
+ when(_mockVirtualHostMBean.getRegistry()).thenReturn(_mockManagedObjectRegistry);
+
+ _connectionMBean = new ConnectionMBean(_mockConnection, _mockVirtualHostMBean);
+ }
+
+ public void testMBeanRegistersItself() throws Exception
+ {
+ ConnectionMBean connectionMBean = new ConnectionMBean(_mockConnection, _mockVirtualHostMBean);
+ verify(_mockManagedObjectRegistry).registerObject(connectionMBean);
+ }
+
+ public void testCloseConnection() throws Exception
+ {
+ _connectionMBean.closeConnection();
+ verify(_mockConnection).delete();
+ }
+
+ public void testCommitTransactions()
+ {
+ try
+ {
+ _connectionMBean.commitTransactions(0);
+ fail("Exception not thrown");
+ }
+ catch(JMException e)
+ {
+ assertTrue("Cause should be an UnsupportedOperationException", e.getCause() instanceof UnsupportedOperationException);
+ }
+ }
+
+ public void testRollbackTransactions()
+ {
+ try
+ {
+ _connectionMBean.rollbackTransactions(0);
+ fail("Exception not thrown");
+ }
+ catch(JMException e)
+ {
+ assertTrue("Cause should be an UnsupportedOperationException", e.getCause() instanceof UnsupportedOperationException);
+ }
+ }
+
+ public void testChannelsWithSingleTransactionalSession() throws Exception
+ {
+ int channelId = 10;
+ int unacknowledgedMessages = 2;
+ long localTransactionBegins = 1;
+ boolean transactional = true;
+ boolean blocked = false;
+
+ Session mockSession = createMockedSession(channelId, unacknowledgedMessages, localTransactionBegins, blocked);
+
+ when(_mockConnection.getSessions()).thenReturn(Collections.singletonList(mockSession));
+
+ TabularData table = _connectionMBean.channels();
+ assertEquals("Unexpected number of rows in table", 1, table.size());
+
+ final CompositeData row = table.get(new Integer[] {channelId} );
+ assertChannelRow(row, channelId, unacknowledgedMessages, transactional, blocked);
+ }
+
+ public void testChannelsWithSingleNonTransactionalSession() throws Exception
+ {
+ int channelId = 10;
+ int unacknowledgedMessages = 2;
+ long localTransactionBegins = 0;
+ boolean transactional = false;
+ boolean blocked = false;
+
+ Session mockSession = createMockedSession(channelId, unacknowledgedMessages, localTransactionBegins, blocked);
+
+ when(_mockConnection.getSessions()).thenReturn(Collections.singletonList(mockSession));
+
+ TabularData table = _connectionMBean.channels();
+ assertEquals("Unexpected number of rows in table", 1, table.size());
+
+ final CompositeData row = table.get(new Integer[] {channelId} );
+ assertChannelRow(row, channelId, unacknowledgedMessages, transactional, blocked);
+ }
+
+ public void testChannelsWithSessionBlocked() throws Exception
+ {
+ int channelId = 10;
+ int unacknowledgedMessages = 2;
+ long localTransactionBegins = 0;
+ boolean transactional = false;
+ boolean blocked = true;
+
+ Session mockSession = createMockedSession(channelId, unacknowledgedMessages, localTransactionBegins, blocked);
+
+ when(_mockConnection.getSessions()).thenReturn(Collections.singletonList(mockSession));
+
+ TabularData table = _connectionMBean.channels();
+ assertEquals("Unexpected number of rows in table", 1, table.size());
+
+ final CompositeData row = table.get(new Integer[] {channelId} );
+ assertChannelRow(row, channelId, unacknowledgedMessages, transactional, blocked);
+ }
+
+ public void testParentObjectIsVirtualHost()
+ {
+ ManagedObject parent = _connectionMBean.getParentObject();
+ assertEquals(_mockVirtualHostMBean, parent);
+ }
+
+ public void testGetObjectInstanceName()
+ {
+ String remoteAddress = "testRemoteAddress";
+ String quotedRemoteAddress = "\"testRemoteAddress\"";
+ when(_mockConnection.getAttribute(Connection.REMOTE_ADDRESS)).thenReturn(remoteAddress);
+ String objectInstanceName = _connectionMBean.getObjectInstanceName();
+ assertEquals(quotedRemoteAddress, objectInstanceName);
+ }
+
+ public void testGetAuthorizedId() throws Exception
+ {
+ assertAttribute("authorizedId", "testAuthorizedId", Connection.PRINCIPAL);
+ }
+
+ public void testGetClientId() throws Exception
+ {
+ assertAttribute("clientId", "testClientId", Connection.CLIENT_ID);
+ }
+
+ public void testGetVersion() throws Exception
+ {
+ assertAttribute("version", "testVersion", Connection.CLIENT_VERSION);
+ }
+
+ public void testGetRemoteAddress() throws Exception
+ {
+ assertAttribute("remoteAddress", "testRemoteAddress", Connection.REMOTE_ADDRESS);
+ }
+
+ public void testGetLastIoTime()
+ {
+ Statistics mockStatistics = mock(Statistics.class);
+ when(_mockConnection.getStatistics()).thenReturn(mockStatistics);
+ when(mockStatistics.getStatistic(Connection.LAST_IO_TIME)).thenReturn(1L);
+
+ Object actualValue = _connectionMBean.getLastIoTime();
+ assertEquals("Unexpected lastIoTime", new Date(1L), actualValue);
+ }
+
+ public void testGetMaximumNumberOfChannels() throws Exception
+ {
+ assertAttribute("maximumNumberOfChannels", 10l, Connection.SESSION_COUNT_LIMIT);
+ }
+
+ public void testIsStatisticsEnabledAlwaysTrue() throws Exception
+ {
+ assertTrue(_connectionMBean.isStatisticsEnabled());
+ }
+
+ private void assertAttribute(String jmxAttributeName, Object expectedValue, String underlyingAttributeName) throws Exception
+ {
+ when(_mockConnection.getAttribute(underlyingAttributeName)).thenReturn(expectedValue);
+ MBeanTestUtils.assertMBeanAttribute(_connectionMBean, jmxAttributeName, expectedValue);
+ }
+
+ private void assertChannelRow(final CompositeData row, int channelId, int unacknowledgedMessages, boolean isTransactional, boolean flowBlocked)
+ {
+ assertNotNull("No row for channel id " + channelId, row);
+ assertEquals("Unexpected channel id", channelId, row.get(ManagedConnection.CHAN_ID));
+ assertEquals("Unexpected transactional flag", isTransactional, row.get(ManagedConnection.TRANSACTIONAL));
+ assertEquals("Unexpected unacknowledged message count", unacknowledgedMessages, row.get(ManagedConnection.UNACKED_COUNT));
+ assertEquals("Unexpected flow blocked", flowBlocked, row.get(ManagedConnection.FLOW_BLOCKED));
+ }
+
+ private Session createMockedSession(int channelId, int unacknowledgedMessages, long localTransactionBegins, boolean blocked)
+ {
+ Session mockSession = mock(Session.class);
+ Statistics mockSessionStatistics = mock(Statistics.class);
+ when(mockSessionStatistics.getStatistic(Session.LOCAL_TRANSACTION_BEGINS)).thenReturn(localTransactionBegins);
+ when(mockSessionStatistics.getStatistic(Session.UNACKNOWLEDGED_MESSAGES)).thenReturn(unacknowledgedMessages);
+
+ when(mockSession.getStatistics()).thenReturn(mockSessionStatistics);
+ when(mockSession.getAttribute(Session.CHANNEL_ID)).thenReturn(channelId);
+ when(mockSession.getAttribute(Session.PRODUCER_FLOW_BLOCKED)).thenReturn(blocked);
+ return mockSession;
+ }
+}
diff --git a/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/ExchangeMBeanTest.java b/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/ExchangeMBeanTest.java
new file mode 100644
index 0000000000..e350f80a25
--- /dev/null
+++ b/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/ExchangeMBeanTest.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.server.jmx.mbeans;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.never;
+import static org.mockito.Matchers.isNull;
+import static org.mockito.Matchers.argThat;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Matchers.anyMap;
+
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.TreeMap;
+
+import javax.management.JMException;
+import javax.management.ListenerNotFoundException;
+import javax.management.Notification;
+import javax.management.NotificationListener;
+import javax.management.OperationsException;
+
+import org.apache.qpid.server.jmx.ManagedObjectRegistry;
+import org.apache.qpid.server.model.Binding;
+import org.apache.qpid.server.model.Exchange;
+import org.apache.qpid.server.model.LifetimePolicy;
+import org.apache.qpid.server.model.Queue;
+import org.apache.qpid.server.model.Statistics;
+import org.apache.qpid.server.model.VirtualHost;
+import org.apache.qpid.server.queue.NotificationCheck;
+import org.mockito.ArgumentMatcher;
+
+import junit.framework.TestCase;
+
+public class ExchangeMBeanTest extends TestCase
+{
+ private static final String EXCHANGE_NAME = "EXCHANGE_NAME";
+ private static final String EXCHANGE_TYPE = "EXCHANGE_TYPE";
+ private static final String QUEUE1_NAME = "QUEUE1_NAME";
+ private static final String QUEUE2_NAME = "QUEUE2_NAME";
+ private static final String BINDING1 = "BINDING1";
+ private static final String BINDING2 = "BINDING2";
+
+ private Exchange _mockExchange;
+ private VirtualHostMBean _mockVirtualHostMBean;
+ private ManagedObjectRegistry _mockManagedObjectRegistry;
+ private ExchangeMBean _exchangeMBean;
+ private Queue _mockQueue1;
+ private Queue _mockQueue2;
+ private Exchange _mockHeadersExchange;
+
+ @Override
+ protected void setUp() throws Exception
+ {
+ _mockExchange = mock(Exchange.class);
+ when(_mockExchange.getName()).thenReturn(EXCHANGE_NAME);
+ when(_mockExchange.getExchangeType()).thenReturn(EXCHANGE_TYPE);
+ _mockVirtualHostMBean = mock(VirtualHostMBean.class);
+
+ _mockManagedObjectRegistry = mock(ManagedObjectRegistry.class);
+ when(_mockVirtualHostMBean.getRegistry()).thenReturn(_mockManagedObjectRegistry);
+
+ _mockQueue1 = createMockQueue(QUEUE1_NAME);
+ _mockQueue2 = createMockQueue(QUEUE2_NAME);
+
+ VirtualHost mockVirtualHost = mock(VirtualHost.class);
+ when(mockVirtualHost.getQueues()).thenReturn(Arrays.asList(new Queue[] {_mockQueue1, _mockQueue2}));
+ when(_mockExchange.getParent(VirtualHost.class)).thenReturn(mockVirtualHost);
+
+ _exchangeMBean = new ExchangeMBean(_mockExchange, _mockVirtualHostMBean);
+
+ _mockHeadersExchange = mock(Exchange.class);
+ when(_mockHeadersExchange.getExchangeType()).thenReturn(ExchangeMBean.HEADERS_EXCHANGE_TYPE);
+ when(_mockHeadersExchange.getParent(VirtualHost.class)).thenReturn(mockVirtualHost);
+
+ }
+
+ public void testExchangeName()
+ {
+ assertEquals(EXCHANGE_NAME, _exchangeMBean.getName());
+ }
+
+ public void testExchangeType()
+ {
+ assertEquals(EXCHANGE_TYPE, _exchangeMBean.getExchangeType());
+ }
+
+ public void testNonHeadersExchangeCreateNewBinding() throws Exception
+ {
+ _exchangeMBean.createNewBinding(QUEUE1_NAME, BINDING1);
+ verify(_mockExchange).createBinding(BINDING1, _mockQueue1, Collections.EMPTY_MAP, Collections.EMPTY_MAP);
+ }
+
+ public void testCreateNewBindingWhereQueueIsUnknown() throws Exception
+ {
+ try
+ {
+ _exchangeMBean.createNewBinding("unknown", BINDING1);
+ }
+ catch (OperationsException oe)
+ {
+ // PASS
+ assertEquals("No such queue \"unknown\"", oe.getMessage());
+ }
+ verify(_mockExchange, never()).createBinding(anyString(), any(Queue.class), anyMap(), anyMap());
+ }
+
+ public void testRemoveBinding() throws Exception
+ {
+ Binding mockBinding1 = createBindingOnQueue(BINDING1, _mockQueue1);
+ Binding mockBinding2 = createBindingOnQueue(BINDING2, _mockQueue1);
+ when(_mockExchange.getBindings()).thenReturn(Arrays.asList(new Binding[] {mockBinding1, mockBinding2}));
+
+ _exchangeMBean.removeBinding(QUEUE1_NAME, BINDING1);
+ verify(mockBinding1).delete();
+ }
+
+ public void testRemoveBindingWhereQueueIsUnknown() throws Exception
+ {
+ Binding mockBinding1 = createBindingOnQueue(BINDING1, _mockQueue1);
+ when(_mockExchange.getBindings()).thenReturn(Arrays.asList(new Binding[] {mockBinding1}));
+
+ try
+ {
+ _exchangeMBean.removeBinding("unknown", BINDING1);
+ fail("Exception not thrown");
+ }
+ catch (OperationsException oe)
+ {
+ // PASS
+ assertEquals("No such queue \"unknown\"", oe.getMessage());
+ }
+ verify(mockBinding1, never()).delete();
+ }
+
+ public void testRemoveBindingWhereBindingNameIsUnknown() throws Exception
+ {
+ Binding mockBinding1 = createBindingOnQueue(BINDING1, _mockQueue1);
+ when(_mockExchange.getBindings()).thenReturn(Arrays.asList(new Binding[] {mockBinding1}));
+
+ try
+ {
+ _exchangeMBean.removeBinding(QUEUE1_NAME, "unknown");
+ fail("Exception not thrown");
+ }
+ catch (OperationsException oe)
+ {
+ // PASS
+ assertEquals("No such binding \"unknown\" on queue \"" + QUEUE1_NAME + "\"", oe.getMessage());
+ }
+ verify(mockBinding1, never()).delete();
+ }
+
+ public void testHeadersExchangeCreateNewBinding() throws Exception
+ {
+ String binding = "key1=binding1,key2=binding2";
+ Map<String, Object> expectedBindingMap = new HashMap<String, Object>()
+ {{
+ put("key1", "binding1");
+ put("key2", "binding2");
+ }};
+ _exchangeMBean = new ExchangeMBean(_mockHeadersExchange, _mockVirtualHostMBean);
+
+ _exchangeMBean.createNewBinding(QUEUE1_NAME, binding);
+ verify(_mockHeadersExchange).createBinding(binding, _mockQueue1, expectedBindingMap, Collections.EMPTY_MAP);
+ }
+
+ public void testHeadersExchangeCreateNewBindingWithFieldWithoutValue() throws Exception
+ {
+ String binding = "key1=binding1,key2=";
+ Map<String, Object> expectedBindingMap = new HashMap<String, Object>()
+ {{
+ put("key1", "binding1");
+ put("key2", "");
+ }};
+ _exchangeMBean = new ExchangeMBean(_mockHeadersExchange, _mockVirtualHostMBean);
+
+ _exchangeMBean.createNewBinding(QUEUE1_NAME, binding);
+ verify(_mockHeadersExchange).createBinding(binding, _mockQueue1, expectedBindingMap, Collections.EMPTY_MAP);
+ }
+
+ public void testHeadersExchangeCreateNewBindingMalformed() throws Exception
+ {
+ String binding = "=binding1,=";
+ _exchangeMBean = new ExchangeMBean(_mockHeadersExchange, _mockVirtualHostMBean);
+
+ try
+ {
+ _exchangeMBean.createNewBinding(QUEUE1_NAME, binding);
+ fail("Exception not thrown");
+ }
+ catch (JMException e)
+ {
+ assertEquals("Format for headers binding should be \"<attribute1>=<value1>,<attribute2>=<value2>\"", e.getMessage());
+ }
+ }
+
+ private Binding createBindingOnQueue(String bindingName, Queue queue)
+ {
+ Binding mockBinding = mock(Binding.class);
+ when(mockBinding.getParent(Queue.class)).thenReturn(queue);
+ when(mockBinding.getName()).thenReturn(bindingName);
+ return mockBinding;
+ }
+
+ private Queue createMockQueue(String queueName)
+ {
+ Queue mockQueue = mock(Queue.class);
+ when(mockQueue.getName()).thenReturn(queueName);
+ return mockQueue;
+ }
+
+}
diff --git a/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/LoggingManagementMBeanTest.java b/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/LoggingManagementMBeanTest.java
new file mode 100644
index 0000000000..ae1be5db00
--- /dev/null
+++ b/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/LoggingManagementMBeanTest.java
@@ -0,0 +1,245 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.jmx.mbeans;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static org.mockito.Matchers.anyString;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+
+import javax.management.openmbean.CompositeData;
+import javax.management.openmbean.TabularData;
+
+import junit.framework.TestCase;
+
+import org.apache.qpid.management.common.mbeans.LoggingManagement;
+import org.apache.qpid.server.jmx.ManagedObjectRegistry;
+import org.apache.qpid.server.logging.log4j.LoggingFacade;
+
+public class LoggingManagementMBeanTest extends TestCase
+{
+ private static final String TEST_LEVEL1 = "LEVEL1";
+ private static final String TEST_LEVEL2 = "LEVEL2";
+
+ private LoggingManagementMBean _loggingMBean;
+ private LoggingFacade _mockLoggingFacade;
+ private ManagedObjectRegistry _mockManagedObjectRegistry;
+
+ @Override
+ protected void setUp() throws Exception
+ {
+ _mockLoggingFacade = mock(LoggingFacade.class);
+ final List<String> listOfLevels = new ArrayList<String>()
+ {{
+ add(TEST_LEVEL1);
+ add(TEST_LEVEL2);
+ }};
+ when(_mockLoggingFacade.getAvailableLoggerLevels()).thenReturn(listOfLevels);
+
+ _mockManagedObjectRegistry = mock(ManagedObjectRegistry.class);
+
+ _loggingMBean = new LoggingManagementMBean(_mockLoggingFacade, _mockManagedObjectRegistry);
+ }
+
+ public void testMBeanRegistersItself() throws Exception
+ {
+ LoggingManagementMBean connectionMBean = new LoggingManagementMBean(_mockLoggingFacade, _mockManagedObjectRegistry);
+ verify(_mockManagedObjectRegistry).registerObject(connectionMBean);
+ }
+
+ public void testLog4jLogWatchInterval() throws Exception
+ {
+ final Integer value = 5000;
+ when(_mockLoggingFacade.getLog4jLogWatchInterval()).thenReturn(value);
+
+ assertEquals("Unexpected watch interval",value, _loggingMBean.getLog4jLogWatchInterval());
+ }
+
+ public void testGetAvailableLoggerLevels() throws Exception
+ {
+ String[] actualLevels = _loggingMBean.getAvailableLoggerLevels();
+ assertEquals(3, actualLevels.length);
+ assertEquals(TEST_LEVEL1, actualLevels[0]);
+ assertEquals(TEST_LEVEL2, actualLevels[1]);
+ assertEquals(LoggingManagementMBean.INHERITED_PSUEDO_LOG_LEVEL, actualLevels[2]);
+ }
+
+ public void testViewEffectiveRuntimeLoggerLevels() throws Exception
+ {
+ Map<String, String> loggerLevels = new TreeMap<String, String>();
+ loggerLevels.put("a.b.D", TEST_LEVEL2);
+ loggerLevels.put("a.b.C", TEST_LEVEL1);
+ loggerLevels.put("a.b.c.E", TEST_LEVEL2);
+
+ when(_mockLoggingFacade.retrieveRuntimeLoggersLevels()).thenReturn(loggerLevels );
+
+ TabularData table = _loggingMBean.viewEffectiveRuntimeLoggerLevels();
+ assertEquals(3, table.size());
+
+ final CompositeData row1 = table.get(new String[] {"a.b.C"} );
+ final CompositeData row2 = table.get(new String[] {"a.b.D"} );
+ final CompositeData row3 = table.get(new String[] {"a.b.c.E"} );
+ assertChannelRow(row1, "a.b.C", TEST_LEVEL1);
+ assertChannelRow(row2, "a.b.D", TEST_LEVEL2);
+ assertChannelRow(row3, "a.b.c.E", TEST_LEVEL2);
+ }
+
+ public void testGetRuntimeRootLoggerLevel() throws Exception
+ {
+ when(_mockLoggingFacade.retrieveRuntimeRootLoggerLevel()).thenReturn(TEST_LEVEL1);
+
+ assertEquals(TEST_LEVEL1, _loggingMBean.getRuntimeRootLoggerLevel());
+ }
+
+ public void testSetRuntimeRootLoggerLevel() throws Exception
+ {
+ _loggingMBean.setRuntimeRootLoggerLevel(TEST_LEVEL1);
+ verify(_mockLoggingFacade).setRuntimeRootLoggerLevel(TEST_LEVEL1);
+ }
+
+ public void testSetRuntimeRootLoggerLevelWhenLoggingLevelUnknown() throws Exception
+ {
+ boolean result = _loggingMBean.setRuntimeRootLoggerLevel("unknown");
+ assertFalse(result);
+ verify(_mockLoggingFacade, never()).setRuntimeRootLoggerLevel("unknown");
+ }
+
+ public void testSetRuntimeRootLoggerLevelWhenLoggingLevelInherited() throws Exception
+ {
+ boolean result = _loggingMBean.setRuntimeRootLoggerLevel(LoggingManagementMBean.INHERITED_PSUEDO_LOG_LEVEL);
+ assertFalse(result);
+ verify(_mockLoggingFacade, never()).setRuntimeRootLoggerLevel(anyString());
+ }
+
+ public void testSetRuntimeLoggerLevel() throws Exception
+ {
+ _loggingMBean.setRuntimeLoggerLevel("a.b.c.D", TEST_LEVEL1);
+ verify(_mockLoggingFacade).setRuntimeLoggerLevel("a.b.c.D", TEST_LEVEL1);
+ }
+
+ public void testSetRuntimeLoggerLevelWhenLoggingLevelUnknown() throws Exception
+ {
+ boolean result = _loggingMBean.setRuntimeLoggerLevel("a.b.c.D", "unknown");
+ assertFalse(result);
+ verify(_mockLoggingFacade, never()).setRuntimeLoggerLevel(anyString(), anyString());
+ }
+
+ public void testSetRuntimeLoggerLevelWhenLoggingLevelInherited() throws Exception
+ {
+ boolean result = _loggingMBean.setRuntimeLoggerLevel("a.b.c.D", LoggingManagementMBean.INHERITED_PSUEDO_LOG_LEVEL);
+ assertTrue(result);
+ verify(_mockLoggingFacade).setRuntimeLoggerLevel("a.b.c.D", null);
+ }
+
+ public void testViewEffectiveConfigFileLoggerLevels() throws Exception
+ {
+ Map<String, String> loggerLevels = new TreeMap<String, String>();
+ loggerLevels.put("a.b.D", "level2");
+ loggerLevels.put("a.b.C", TEST_LEVEL1);
+ loggerLevels.put("a.b.c.E", "level2");
+
+ when(_mockLoggingFacade.retrieveConfigFileLoggersLevels()).thenReturn(loggerLevels );
+
+ TabularData table = _loggingMBean.viewConfigFileLoggerLevels();
+ assertEquals(3, table.size());
+
+ final CompositeData row1 = table.get(new String[] {"a.b.C"} );
+ final CompositeData row2 = table.get(new String[] {"a.b.D"} );
+ final CompositeData row3 = table.get(new String[] {"a.b.c.E"} );
+ assertChannelRow(row1, "a.b.C", TEST_LEVEL1);
+ assertChannelRow(row2, "a.b.D", TEST_LEVEL2);
+ assertChannelRow(row3, "a.b.c.E", TEST_LEVEL2);
+ }
+
+ public void testGetConfigFileRootLoggerLevel() throws Exception
+ {
+ when(_mockLoggingFacade.retrieveConfigFileRootLoggerLevel()).thenReturn(TEST_LEVEL1);
+
+ assertEquals(TEST_LEVEL1, _loggingMBean.getConfigFileRootLoggerLevel());
+ }
+
+ public void testSetConfigFileRootLoggerLevel() throws Exception
+ {
+ when(_mockLoggingFacade.getAvailableLoggerLevels()).thenReturn(Collections.singletonList(TEST_LEVEL1));
+ _loggingMBean.setConfigFileRootLoggerLevel(TEST_LEVEL1);
+ verify(_mockLoggingFacade).setConfigFileRootLoggerLevel(TEST_LEVEL1);
+ }
+
+ public void testSetConfigFileRootLoggerLevelWhenLoggingLevelUnknown() throws Exception
+ {
+ when(_mockLoggingFacade.getAvailableLoggerLevels()).thenReturn(Collections.singletonList(TEST_LEVEL1));
+ boolean result = _loggingMBean.setConfigFileRootLoggerLevel("unknown");
+ assertFalse(result);
+ verify(_mockLoggingFacade, never()).setConfigFileRootLoggerLevel("unknown");
+ }
+
+ public void testSetConfigFileRootLoggerLevelWhenLoggingLevelInherited() throws Exception
+ {
+ when(_mockLoggingFacade.getAvailableLoggerLevels()).thenReturn(Collections.singletonList(TEST_LEVEL1));
+ boolean result = _loggingMBean.setConfigFileRootLoggerLevel(LoggingManagementMBean.INHERITED_PSUEDO_LOG_LEVEL);
+ assertFalse(result);
+ verify(_mockLoggingFacade, never()).setConfigFileRootLoggerLevel(anyString());
+ }
+
+ public void testSetConfigFileLoggerLevel() throws Exception
+ {
+ when(_mockLoggingFacade.getAvailableLoggerLevels()).thenReturn(Collections.singletonList(TEST_LEVEL1));
+ _loggingMBean.setConfigFileLoggerLevel("a.b.c.D", TEST_LEVEL1);
+ verify(_mockLoggingFacade).setConfigFileLoggerLevel("a.b.c.D", TEST_LEVEL1);
+ }
+
+ public void testSetConfigFileLoggerLevelWhenLoggingLevelUnknown() throws Exception
+ {
+ when(_mockLoggingFacade.getAvailableLoggerLevels()).thenReturn(Collections.singletonList(TEST_LEVEL1));
+ boolean result = _loggingMBean.setConfigFileLoggerLevel("a.b.c.D", "unknown");
+ assertFalse(result);
+ verify(_mockLoggingFacade, never()).setConfigFileLoggerLevel("a.b.c.D", "unknown");
+ }
+
+ public void testSetConfigFileLoggerLevelWhenLoggingLevelInherited() throws Exception
+ {
+ when(_mockLoggingFacade.getAvailableLoggerLevels()).thenReturn(Collections.singletonList(TEST_LEVEL1));
+ boolean result = _loggingMBean.setConfigFileLoggerLevel("a.b.c.D", LoggingManagementMBean.INHERITED_PSUEDO_LOG_LEVEL);
+ assertTrue(result);
+ verify(_mockLoggingFacade).setConfigFileLoggerLevel("a.b.c.D", null);
+ }
+
+ public void testReloadConfigFile() throws Exception
+ {
+ _loggingMBean.reloadConfigFile();
+
+ verify(_mockLoggingFacade).reload();
+ }
+
+ private void assertChannelRow(final CompositeData row, String logger, String level)
+ {
+ assertNotNull("No row for " + logger, row);
+ assertEquals("Unexpected logger name", logger, row.get(LoggingManagement.LOGGER_NAME));
+ assertEquals("Unexpected level", level, row.get(LoggingManagement.LOGGER_LEVEL));
+ }
+}
diff --git a/java/broker-plugins/extras/src/main/java/org/apache/qpid/extras/Activator.java b/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/MBeanTestUtils.java
index fa0ffb5045..5f913e5f33 100644
--- a/java/broker-plugins/extras/src/main/java/org/apache/qpid/extras/Activator.java
+++ b/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/MBeanTestUtils.java
@@ -1,5 +1,4 @@
/*
- *
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
@@ -18,32 +17,24 @@
* under the License.
*
*/
-package org.apache.qpid.extras;
-
-import org.osgi.framework.BundleActivator;
-import org.osgi.framework.BundleContext;
+package org.apache.qpid.server.jmx.mbeans;
-import org.apache.qpid.extras.exchanges.diagnostic.DiagnosticExchangeType;
-import org.apache.qpid.extras.exchanges.example.TestExchangeType;
-import org.apache.qpid.server.exchange.ExchangeType;
+import junit.framework.TestCase;
-/**
- *
- * @author aidan
- *
- * Dummy class, used by PluginTest
- */
+import org.apache.commons.beanutils.PropertyUtils;
+import org.apache.qpid.server.jmx.DefaultManagedObject;
-public class Activator implements BundleActivator
+public class MBeanTestUtils
{
- public void start(BundleContext ctx) throws Exception
+ public static void assertMBeanAttribute(DefaultManagedObject managedObject, String jmxAttributeName, Object expectedValue) throws Exception
{
- ctx.registerService(ExchangeType.class.getName(), new TestExchangeType(), null);
- ctx.registerService(ExchangeType.class.getName(), new DiagnosticExchangeType(), null);
+ Object actualValue = PropertyUtils.getSimpleProperty(managedObject, jmxAttributeName);
+ TestCase.assertEquals("Attribute " + jmxAttributeName + " has unexpected value", expectedValue, actualValue);
}
- public void stop(BundleContext ctx) throws Exception
+ public static void setMBeanAttribute(DefaultManagedObject managedObject, String jmxAttributeName, Object newValue) throws Exception
{
+ PropertyUtils.setSimpleProperty(managedObject, jmxAttributeName, newValue);
}
}
diff --git a/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/QueueMBeanTest.java b/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/QueueMBeanTest.java
new file mode 100644
index 0000000000..f2663bca4e
--- /dev/null
+++ b/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/QueueMBeanTest.java
@@ -0,0 +1,439 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.jmx.mbeans;
+
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Matchers.isNull;
+import static org.mockito.Matchers.argThat;
+
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+import java.util.Collections;
+
+import javax.management.ListenerNotFoundException;
+import javax.management.Notification;
+import javax.management.NotificationListener;
+import javax.management.OperationsException;
+import javax.management.openmbean.CompositeDataSupport;
+
+import org.apache.qpid.management.common.mbeans.ManagedQueue;
+import org.apache.qpid.server.jmx.ManagedObjectRegistry;
+import org.apache.qpid.server.jmx.mbeans.QueueMBean.GetMessageVisitor;
+import org.apache.qpid.server.message.ServerMessage;
+import org.apache.qpid.server.model.Exchange;
+import org.apache.qpid.server.model.LifetimePolicy;
+import org.apache.qpid.server.model.Queue;
+import org.apache.qpid.server.model.Statistics;
+import org.apache.qpid.server.model.VirtualHost;
+import org.apache.qpid.server.queue.NotificationCheck;
+import org.apache.qpid.server.queue.QueueEntry;
+import org.apache.qpid.test.utils.QpidTestCase;
+import org.mockito.ArgumentMatcher;
+import org.mockito.Matchers;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+
+public class QueueMBeanTest extends QpidTestCase
+{
+ private static final String QUEUE_NAME = "QUEUE_NAME";
+ private static final String QUEUE_DESCRIPTION = "QUEUE_DESCRIPTION";
+ private static final String QUEUE_TYPE = "QUEUE_TYPE";
+ private static final String QUEUE_ALTERNATE_EXCHANGE = "QUEUE_ALTERNATE_EXCHANGE";
+
+ private Queue _mockQueue;
+ private Statistics _mockQueueStatistics;
+ private VirtualHostMBean _mockVirtualHostMBean;
+ private ManagedObjectRegistry _mockManagedObjectRegistry;
+ private QueueMBean _queueMBean;
+
+ @Override
+ protected void setUp() throws Exception
+ {
+ super.setUp();
+ _mockQueue = mock(Queue.class);
+ _mockQueueStatistics = mock(Statistics.class);
+ when(_mockQueue.getName()).thenReturn(QUEUE_NAME);
+ when(_mockQueue.getStatistics()).thenReturn(_mockQueueStatistics);
+ _mockVirtualHostMBean = mock(VirtualHostMBean.class);
+
+ _mockManagedObjectRegistry = mock(ManagedObjectRegistry.class);
+ when(_mockVirtualHostMBean.getRegistry()).thenReturn(_mockManagedObjectRegistry);
+
+ _queueMBean = new QueueMBean(_mockQueue, _mockVirtualHostMBean);
+ }
+
+ public void testQueueName()
+ {
+ assertEquals(QUEUE_NAME, _queueMBean.getName());
+ }
+
+ /********** Statistics **********/
+
+ public void testGetMessageCount() throws Exception
+ {
+ assertStatistic("messageCount", 1000, Queue.QUEUE_DEPTH_MESSAGES);
+ }
+
+ public void testGetReceivedMessageCount() throws Exception
+ {
+ assertStatistic("receivedMessageCount", 1000l, Queue.TOTAL_ENQUEUED_MESSAGES);
+ }
+
+ public void testQueueDepth() throws Exception
+ {
+ assertStatistic("queueDepth", 4096l, Queue.QUEUE_DEPTH_BYTES);
+ }
+
+ public void testActiveConsumerCount() throws Exception
+ {
+ assertStatistic("activeConsumerCount", 3, Queue.CONSUMER_COUNT_WITH_CREDIT);
+ }
+
+ public void testConsumerCount() throws Exception
+ {
+ assertStatistic("consumerCount", 3, Queue.CONSUMER_COUNT);
+ }
+
+ /********** Simple Attributes **********/
+
+ public void testGetQueueDescription() throws Exception
+ {
+ assertAttribute("description", QUEUE_DESCRIPTION, Queue.DESCRIPTION);
+ }
+
+ public void testSetQueueDescription() throws Exception
+ {
+ testSetAttribute("description", Queue.DESCRIPTION, "descriptionold", "descriptionnew");
+ }
+
+ public void testQueueType() throws Exception
+ {
+ assertAttribute("queueType", QUEUE_TYPE, Queue.TYPE);
+ }
+
+ public void testMaximumDeliveryCount() throws Exception
+ {
+ assertAttribute("maximumDeliveryCount", 5, Queue.MAXIMUM_DELIVERY_ATTEMPTS);
+ }
+
+ public void testOwner() throws Exception
+ {
+ assertAttribute("owner", "testOwner", Queue.OWNER);
+ }
+
+ public void testIsDurable() throws Exception
+ {
+ when(_mockQueue.isDurable()).thenReturn(true);
+ assertTrue(_queueMBean.isDurable());
+ }
+
+ public void testIsNotDurable() throws Exception
+ {
+ when(_mockQueue.isDurable()).thenReturn(false);
+ assertFalse(_queueMBean.isDurable());
+ }
+
+ public void testIsAutoDelete() throws Exception
+ {
+ when(_mockQueue.getLifetimePolicy()).thenReturn(LifetimePolicy.AUTO_DELETE);
+ assertTrue(_queueMBean.isAutoDelete());
+ }
+
+ public void testIsNotAutoDelete() throws Exception
+ {
+ when(_mockQueue.getLifetimePolicy()).thenReturn(LifetimePolicy.PERMANENT);
+ assertFalse(_queueMBean.isAutoDelete());
+ }
+
+ public void testGetMaximumMessageAge() throws Exception
+ {
+ assertAttribute("maximumMessageAge", 10000l, Queue.ALERT_THRESHOLD_MESSAGE_AGE);
+ }
+
+ public void testSetMaximumMessageAge() throws Exception
+ {
+ testSetAttribute("maximumMessageAge", Queue.ALERT_THRESHOLD_MESSAGE_AGE, 1000l, 10000l);
+ }
+
+ public void testGetMaximumMessageSize() throws Exception
+ {
+ assertAttribute("maximumMessageSize", 1024l, Queue.ALERT_THRESHOLD_MESSAGE_SIZE);
+ }
+
+ public void testSetMaximumMessageSize() throws Exception
+ {
+ testSetAttribute("maximumMessageSize", Queue.ALERT_THRESHOLD_MESSAGE_SIZE, 1024l, 2048l);
+ }
+
+ public void testGetMaximumMessageCount() throws Exception
+ {
+ assertAttribute("maximumMessageCount", 5000l, Queue.ALERT_THRESHOLD_QUEUE_DEPTH_MESSAGES);
+ }
+
+ public void testSetMaximumMessageCount() throws Exception
+ {
+ testSetAttribute("maximumMessageCount", Queue.ALERT_THRESHOLD_QUEUE_DEPTH_MESSAGES, 4000l, 5000l);
+ }
+
+ public void testGetMaximumQueueDepth() throws Exception
+ {
+ assertAttribute("maximumQueueDepth", 1048576l, Queue.ALERT_THRESHOLD_QUEUE_DEPTH_BYTES);
+ }
+
+ public void testSetMaximumQueueDepth() throws Exception
+ {
+ testSetAttribute("maximumQueueDepth", Queue.ALERT_THRESHOLD_QUEUE_DEPTH_BYTES,1048576l , 2097152l);
+ }
+
+ public void testGetCapacity() throws Exception
+ {
+ assertAttribute("capacity", 1048576l, Queue.QUEUE_FLOW_CONTROL_SIZE_BYTES);
+ }
+
+ public void testSetCapacity() throws Exception
+ {
+ testSetAttribute("capacity", Queue.QUEUE_FLOW_CONTROL_SIZE_BYTES,1048576l , 2097152l);
+ }
+
+ public void testGetFlowResumeCapacity() throws Exception
+ {
+ assertAttribute("flowResumeCapacity", 1048576l, Queue.QUEUE_FLOW_RESUME_SIZE_BYTES);
+ }
+
+ public void testSetFlowResumeCapacity() throws Exception
+ {
+ testSetAttribute("flowResumeCapacity", Queue.QUEUE_FLOW_RESUME_SIZE_BYTES,1048576l , 2097152l);
+ }
+
+ public void testIsExclusive() throws Exception
+ {
+ assertAttribute("exclusive", Boolean.TRUE, Queue.EXCLUSIVE);
+ }
+
+ public void testIsNotExclusive() throws Exception
+ {
+ assertAttribute("exclusive", Boolean.FALSE, Queue.EXCLUSIVE);
+ }
+
+ public void testSetExclusive() throws Exception
+ {
+ testSetAttribute("exclusive", Queue.EXCLUSIVE, Boolean.FALSE , Boolean.TRUE);
+ }
+
+ /********** Other attributes **********/
+
+ public void testGetAlternateExchange()
+ {
+ Exchange mockAlternateExchange = mock(Exchange.class);
+ when(mockAlternateExchange.getName()).thenReturn(QUEUE_ALTERNATE_EXCHANGE);
+
+ when(_mockQueue.getAttribute(Queue.ALTERNATE_EXCHANGE)).thenReturn(mockAlternateExchange);
+
+ assertEquals(QUEUE_ALTERNATE_EXCHANGE, _queueMBean.getAlternateExchange());
+ }
+
+ public void testGetAlternateExchangeWhenQueueHasNone()
+ {
+ when(_mockQueue.getAttribute(Queue.ALTERNATE_EXCHANGE)).thenReturn(null);
+
+ assertNull(_queueMBean.getAlternateExchange());
+ }
+
+ public void testSetAlternateExchange() throws Exception
+ {
+ Exchange mockExchange1 = mock(Exchange.class);
+ when(mockExchange1.getName()).thenReturn("exchange1");
+
+ Exchange mockExchange2 = mock(Exchange.class);
+ when(mockExchange2.getName()).thenReturn("exchange2");
+
+ Exchange mockExchange3 = mock(Exchange.class);
+ when(mockExchange3.getName()).thenReturn("exchange3");
+
+ VirtualHost mockVirtualHost = mock(VirtualHost.class);
+ when(mockVirtualHost.getExchanges()).thenReturn(Arrays.asList(new Exchange[] {mockExchange1, mockExchange2, mockExchange3}));
+ when(_mockQueue.getParent(VirtualHost.class)).thenReturn(mockVirtualHost);
+
+ _queueMBean.setAlternateExchange("exchange2");
+ verify(_mockQueue).setAttribute(Queue.ALTERNATE_EXCHANGE, null, mockExchange2);
+ }
+
+ public void testSetAlternateExchangeWithUnknownExchangeName() throws Exception
+ {
+ Exchange mockExchange = mock(Exchange.class);
+ when(mockExchange.getName()).thenReturn("exchange1");
+
+ VirtualHost mockVirtualHost = mock(VirtualHost.class);
+ when(mockVirtualHost.getExchanges()).thenReturn(Collections.singletonList(mockExchange));
+ when(_mockQueue.getParent(VirtualHost.class)).thenReturn(mockVirtualHost);
+
+ try
+ {
+ _queueMBean.setAlternateExchange("notknown");
+ fail("Exception not thrown");
+ }
+ catch(OperationsException oe)
+ {
+ // PASS
+ }
+ }
+
+ public void testRemoveAlternateExchange() throws Exception
+ {
+ _queueMBean.setAlternateExchange("");
+ verify(_mockQueue).setAttribute(Queue.ALTERNATE_EXCHANGE, null, null);
+ }
+
+ /********** Operations **********/
+
+ /********** Notifications **********/
+
+ public void testNotificationListenerCalled() throws Exception
+ {
+ NotificationListener listener = mock(NotificationListener.class);
+ _queueMBean.addNotificationListener(listener, null, null);
+
+ NotificationCheck notification = mock(NotificationCheck.class);
+ String notificationMsg = "Test notification message";
+
+ _queueMBean.notifyClients(notification, _mockQueue, notificationMsg);
+ verify(listener).handleNotification(isNotificationWithMessage(notificationMsg),
+ isNull());
+ }
+
+ public void testAddRemoveNotificationListener() throws Exception
+ {
+ NotificationListener listener1 = mock(NotificationListener.class);
+ _queueMBean.addNotificationListener(listener1, null, null);
+ _queueMBean.removeNotificationListener(listener1);
+ }
+
+ public void testRemoveUnknownNotificationListener() throws Exception
+ {
+ NotificationListener listener1 = mock(NotificationListener.class);
+ try
+ {
+ _queueMBean.removeNotificationListener(listener1);
+ fail("Exception not thrown");
+ }
+ catch (ListenerNotFoundException e)
+ {
+ // PASS
+ }
+ }
+
+ private Notification isNotificationWithMessage(final String expectedMessage)
+ {
+ return argThat( new ArgumentMatcher<Notification>()
+ {
+ @Override
+ public boolean matches(Object argument)
+ {
+ Notification actual = (Notification) argument;
+ return actual.getMessage().endsWith(expectedMessage);
+ }
+ });
+ }
+
+ private void assertStatistic(String jmxAttributeName, Object expectedValue, String underlyingAttributeName) throws Exception
+ {
+ when(_mockQueueStatistics.getStatistic(underlyingAttributeName)).thenReturn(expectedValue);
+ MBeanTestUtils.assertMBeanAttribute(_queueMBean, jmxAttributeName, expectedValue);
+ }
+
+ private void assertAttribute(String jmxAttributeName, Object expectedValue, String underlyingAttributeName) throws Exception
+ {
+ when(_mockQueue.getAttribute(underlyingAttributeName)).thenReturn(expectedValue);
+ MBeanTestUtils.assertMBeanAttribute(_queueMBean, jmxAttributeName, expectedValue);
+ }
+
+ private void testSetAttribute(String jmxAttributeName, String underlyingAttributeName, Object originalAttributeValue, Object newAttributeValue) throws Exception
+ {
+ when(_mockQueue.getAttribute(underlyingAttributeName)).thenReturn(originalAttributeValue);
+
+ MBeanTestUtils.setMBeanAttribute(_queueMBean, jmxAttributeName, newAttributeValue);
+
+ verify(_mockQueue).setAttribute(underlyingAttributeName, originalAttributeValue, newAttributeValue);
+ }
+
+ public void testViewMessageContent() throws Exception
+ {
+ viewMessageContentTestImpl(16L, 1000, 1000);
+ }
+
+ public void testViewMessageContentWithMissingPayload() throws Exception
+ {
+ viewMessageContentTestImpl(16L, 1000, 0);
+ }
+
+ private void viewMessageContentTestImpl(final long messageNumber,
+ final int messageSize,
+ final int messageContentSize) throws Exception
+ {
+ final byte[] content = new byte[messageContentSize];
+
+ //mock message and queue entry to return a given message size, and have a given content
+ final ServerMessage<?> serverMessage = mock(ServerMessage.class);
+ when(serverMessage.getMessageNumber()).thenReturn(messageNumber);
+ when(serverMessage.getSize()).thenReturn((long)messageSize);
+ doAnswer(new Answer<Object>()
+ {
+ public Object answer(InvocationOnMock invocation)
+ {
+ Object[] args = invocation.getArguments();
+
+ //verify the arg types / expected values
+ assertEquals(2, args.length);
+ assertTrue(args[0] instanceof ByteBuffer);
+ assertTrue(args[1] instanceof Integer);
+
+ ByteBuffer dest = (ByteBuffer) args[0];
+ int offset = (Integer) args[1];
+ assertEquals(0, offset);
+
+ dest.put(content);
+ return messageContentSize;
+ }
+ }).when(serverMessage).getContent(Matchers.any(ByteBuffer.class), Matchers.anyInt());
+
+ final QueueEntry entry = mock(QueueEntry.class);
+ when(entry.getMessage()).thenReturn(serverMessage);
+
+ //mock the queue.visit() method to ensure we match the mock message
+ doAnswer(new Answer<Object>()
+ {
+ public Object answer(InvocationOnMock invocation)
+ {
+ Object[] args = invocation.getArguments();
+ GetMessageVisitor visitor = (GetMessageVisitor) args[0];
+ visitor.visit(entry);
+ return null;
+ }
+ }).when(_mockQueue).visit(Matchers.any(GetMessageVisitor.class));
+
+ //now retrieve the content and verify its size
+ CompositeDataSupport comp = (CompositeDataSupport) _queueMBean.viewMessageContent(messageNumber);
+ assertNotNull(comp);
+ byte[] data = (byte[]) comp.get(ManagedQueue.CONTENT);
+ assertEquals(messageSize, data.length);
+ }
+}
diff --git a/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/ServerInformationMBeanTest.java b/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/ServerInformationMBeanTest.java
new file mode 100644
index 0000000000..86eab0245e
--- /dev/null
+++ b/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/ServerInformationMBeanTest.java
@@ -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.
+ *
+ */
+package org.apache.qpid.server.jmx.mbeans;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import org.apache.qpid.server.jmx.ManagedObjectRegistry;
+import org.apache.qpid.server.model.Broker;
+import org.apache.qpid.server.model.Connection;
+import org.apache.qpid.server.model.Statistics;
+
+import junit.framework.TestCase;
+
+public class ServerInformationMBeanTest extends TestCase
+{
+ private ManagedObjectRegistry _mockManagedObjectRegistry;
+ private Broker _mockBroker;
+ private Statistics _mockBrokerStatistics;
+ private ServerInformationMBean _mbean;
+
+ @Override
+ protected void setUp() throws Exception
+ {
+ _mockManagedObjectRegistry = mock(ManagedObjectRegistry.class);
+ _mockBroker = mock(Broker.class);
+ _mockBrokerStatistics = mock(Statistics.class);
+ when(_mockBroker.getStatistics()).thenReturn(_mockBrokerStatistics);
+
+ _mbean = new ServerInformationMBean(_mockManagedObjectRegistry, _mockBroker);
+ }
+
+ public void testMBeanRegistersItself() throws Exception
+ {
+ ServerInformationMBean mbean = new ServerInformationMBean(_mockManagedObjectRegistry, _mockBroker);
+ verify(_mockManagedObjectRegistry).registerObject(mbean);
+ }
+
+ /********** Statistics **********/
+
+ public void testGetMessageCount() throws Exception
+ {
+ assertStatistic("totalDataDelivered", 16384l, Connection.BYTES_OUT);
+ }
+
+ /********** Attributes **********/
+
+ public void testBuildVersion() throws Exception
+ {
+ assertAttribute("buildVersion", "0.0.1", Broker.BUILD_VERSION);
+ }
+
+ public void testProductVersion() throws Exception
+ {
+ assertAttribute("productVersion", "0.0.1", Broker.PRODUCT_VERSION);
+ }
+
+ /********** Other Attributes **********/
+
+ public void testIsStatisticsEnabled() throws Exception
+ {
+ assertTrue("isStatisticsEnabled", _mbean.isStatisticsEnabled());
+ }
+
+ private void assertStatistic(String jmxAttributeName, Object expectedValue, String underlyingAttributeName) throws Exception
+ {
+ when(_mockBrokerStatistics.getStatistic(underlyingAttributeName)).thenReturn(expectedValue);
+ MBeanTestUtils.assertMBeanAttribute(_mbean, jmxAttributeName, expectedValue);
+ }
+
+ private void assertAttribute(String jmxAttributeName, Object expectedValue, String underlyingAttributeName) throws Exception
+ {
+ when(_mockBroker.getAttribute(underlyingAttributeName)).thenReturn(expectedValue);
+ MBeanTestUtils.assertMBeanAttribute(_mbean, jmxAttributeName, expectedValue);
+ }
+}
diff --git a/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/UserManagementMBeanTest.java b/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/UserManagementMBeanTest.java
new file mode 100644
index 0000000000..8ca6c521eb
--- /dev/null
+++ b/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/UserManagementMBeanTest.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.server.jmx.mbeans;
+
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.io.IOException;
+import java.util.Collections;
+import java.util.Map;
+
+import javax.management.openmbean.CompositeData;
+import javax.management.openmbean.TabularData;
+import javax.security.auth.login.AccountNotFoundException;
+
+import junit.framework.TestCase;
+
+import org.apache.qpid.management.common.mbeans.UserManagement;
+import org.apache.qpid.server.jmx.ManagedObjectRegistry;
+import org.apache.qpid.server.model.PasswordCredentialManagingAuthenticationProvider;
+
+public class UserManagementMBeanTest extends TestCase
+{
+ private UserManagementMBean _userManagement;
+ private ManagedObjectRegistry _mockRegistry;
+ private PasswordCredentialManagingAuthenticationProvider _mockProvider;
+
+ private static final String TEST_USERNAME = "testuser";
+ private static final String TEST_PASSWORD = "password";
+
+ @Override
+ public void setUp() throws Exception
+ {
+ super.setUp();
+
+ _mockProvider = mock(PasswordCredentialManagingAuthenticationProvider.class);
+ _mockRegistry = mock(ManagedObjectRegistry.class);
+ _userManagement = new UserManagementMBean(_mockProvider, _mockRegistry);
+ }
+
+ public void testMBeanRegistersItself() throws Exception
+ {
+ UserManagementMBean userManagementMBean = new UserManagementMBean(_mockProvider, _mockRegistry);
+ verify(_mockRegistry).registerObject(userManagementMBean);
+ }
+
+ public void testDeleteUser() throws Exception
+ {
+ boolean deleteSuccess = _userManagement.deleteUser(TEST_USERNAME);
+ assertTrue("Expected successful delete", deleteSuccess);
+
+ verify(_mockProvider).deleteUser(TEST_USERNAME);
+ }
+
+ public void testDeleteUserWhereUserDoesNotExist() throws Exception
+ {
+ doThrow(AccountNotFoundException.class).when(_mockProvider).deleteUser(TEST_USERNAME);
+
+ boolean deleteSuccess = _userManagement.deleteUser(TEST_USERNAME);
+ assertFalse("Expected unsuccessful delete", deleteSuccess);
+ }
+
+ public void testCreateUser() throws Exception
+ {
+ when(_mockProvider.createUser(TEST_USERNAME, TEST_PASSWORD, null)).thenReturn(true);
+
+ boolean createSuccess = _userManagement.createUser(TEST_USERNAME, TEST_PASSWORD);
+ assertTrue(createSuccess);
+ }
+
+ public void testCreateUserWhereUserAlreadyExists()
+ {
+ when(_mockProvider.createUser(TEST_USERNAME, TEST_PASSWORD, null)).thenReturn(false);
+
+ boolean createSuccess = _userManagement.createUser(TEST_USERNAME, TEST_PASSWORD);
+ assertFalse(createSuccess);
+ }
+
+ public void testSetPassword() throws Exception
+ {
+ boolean setPasswordSuccess = _userManagement.setPassword(TEST_USERNAME, TEST_PASSWORD);
+ assertTrue(setPasswordSuccess);
+
+ assertTrue("Set password should return true to flag successful change", setPasswordSuccess);
+
+ verify(_mockProvider).setPassword(TEST_USERNAME, TEST_PASSWORD);
+ }
+
+ public void testSetPasswordWhereUserDoesNotExist() throws Exception
+ {
+ doThrow(AccountNotFoundException.class).when(_mockProvider).setPassword(TEST_USERNAME, TEST_PASSWORD);
+
+ boolean setPasswordSuccess = _userManagement.setPassword(TEST_USERNAME, TEST_PASSWORD);
+
+ assertFalse("Set password should return false to flag unsuccessful change", setPasswordSuccess);
+ }
+
+ public void testReload() throws Exception
+ {
+ boolean reloadSuccess = _userManagement.reloadData();
+
+ assertTrue("Reload should return true to flag succesful update", reloadSuccess);
+
+ verify(_mockProvider).reload();
+ }
+
+ public void testReloadFails() throws Exception
+ {
+ doThrow(IOException.class).when(_mockProvider).reload();
+
+ boolean reloadSuccess = _userManagement.reloadData();
+
+ assertFalse("Expected reload to fail", reloadSuccess);
+ }
+
+ public void testViewUsers() throws Exception
+ {
+ Map<String,String> args = Collections.emptyMap();
+ when(_mockProvider.getUsers()).thenReturn(Collections.singletonMap(TEST_USERNAME, args));
+
+ TabularData userList = _userManagement.viewUsers();
+
+ 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));
+ }
+}
diff --git a/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/VirtualHostManagerMBeanTest.java b/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/VirtualHostManagerMBeanTest.java
new file mode 100644
index 0000000000..e3fac9f711
--- /dev/null
+++ b/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/VirtualHostManagerMBeanTest.java
@@ -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.
+ *
+ */
+package org.apache.qpid.server.jmx.mbeans;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.when;
+
+import java.util.Collections;
+import java.util.Map;
+
+import javax.management.OperationsException;
+
+import junit.framework.TestCase;
+
+import org.apache.qpid.server.jmx.ManagedObjectRegistry;
+import org.apache.qpid.server.model.Exchange;
+import org.apache.qpid.server.model.LifetimePolicy;
+import org.apache.qpid.server.model.Queue;
+import org.apache.qpid.server.model.State;
+import org.apache.qpid.server.model.VirtualHost;
+import org.apache.qpid.server.queue.AMQQueueFactory;
+
+public class VirtualHostManagerMBeanTest extends TestCase
+{
+ private static final String TEST_QUEUE_NAME = "QUEUE_NAME";
+ private static final String TEST_EXCHANGE_NAME = "EXCHANGE_NAME";
+ private static final String TEST_OWNER = "OWNER";
+ private static final String TEST_DESCRIPTION = "DESCRIPTION";
+ private static final String TEST_EXCHANGE_TYPE = "EXCHANGE_TYPE";
+
+ private static final Map<String, Object> EMPTY_ARGUMENT_MAP = Collections.emptyMap();
+
+ private VirtualHost _mockVirtualHost;
+ private ManagedObjectRegistry _mockManagedObjectRegistry;
+ private VirtualHostManagerMBean _virtualHostManagerMBean;
+
+ @Override
+ protected void setUp() throws Exception
+ {
+ _mockVirtualHost = mock(VirtualHost.class);
+ when(_mockVirtualHost.getExchangeTypes()).thenReturn(Collections.singletonList(TEST_EXCHANGE_TYPE));
+
+ _mockManagedObjectRegistry = mock(ManagedObjectRegistry.class);
+
+ _virtualHostManagerMBean = new VirtualHostManagerMBean(new VirtualHostMBean(_mockVirtualHost, _mockManagedObjectRegistry));
+ }
+
+ public void testCreateQueueWithNoOwner() throws Exception
+ {
+ _virtualHostManagerMBean.createNewQueue(TEST_QUEUE_NAME, null, true);
+
+ verify(_mockVirtualHost).createQueue(TEST_QUEUE_NAME, State.ACTIVE, true, false, LifetimePolicy.PERMANENT, 0, EMPTY_ARGUMENT_MAP);
+ }
+
+ /**
+ * Some users have been abusing the owner parameter as a description. Decision has been taken to map this parameter
+ * through to the description field (if the description field is passed, the owner is discarded).
+ */
+ public void testCreateQueueWithOwnerMappedThroughToDescription() throws Exception
+ {
+ _virtualHostManagerMBean.createNewQueue(TEST_QUEUE_NAME, TEST_OWNER, true);
+
+ Map<String, Object> expectedArguments = Collections.singletonMap(AMQQueueFactory.X_QPID_DESCRIPTION, (Object)TEST_OWNER);
+ verify(_mockVirtualHost).createQueue(TEST_QUEUE_NAME, State.ACTIVE, true, false, LifetimePolicy.PERMANENT, 0, expectedArguments);
+ }
+
+ public void testCreateQueueWithOwnerAndDescriptionDiscardsOwner() throws Exception
+ {
+ Map<String, Object> arguments = Collections.singletonMap(AMQQueueFactory.X_QPID_DESCRIPTION, (Object)TEST_DESCRIPTION);
+ _virtualHostManagerMBean.createNewQueue(TEST_QUEUE_NAME, TEST_OWNER, true, arguments);
+
+ Map<String, Object> expectedArguments = Collections.singletonMap(AMQQueueFactory.X_QPID_DESCRIPTION, (Object)TEST_DESCRIPTION);
+ verify(_mockVirtualHost).createQueue(TEST_QUEUE_NAME, State.ACTIVE, true, false, LifetimePolicy.PERMANENT, 0, expectedArguments);
+ }
+
+ public void testDeleteQueue() throws Exception
+ {
+ Queue mockQueue = mock(Queue.class);
+ when(mockQueue.getName()).thenReturn("queue1");
+ when(_mockVirtualHost.getQueues()).thenReturn(Collections.singletonList(mockQueue));
+
+ _virtualHostManagerMBean.deleteQueue("queue1");
+ verify(mockQueue).delete();
+ }
+
+ public void testDeleteQueueWhenQueueDoesNotExist() throws Exception
+ {
+ Queue mockQueue = mock(Queue.class);
+ when(mockQueue.getName()).thenReturn("queue1");
+ when(_mockVirtualHost.getQueues()).thenReturn(Collections.singletonList(mockQueue));
+
+ try
+ {
+ _virtualHostManagerMBean.deleteQueue("unknownqueue");
+ fail("Exception not thrown");
+ }
+ catch(OperationsException oe)
+ {
+ // PASS
+ assertEquals("No such queue \"unknownqueue\"", oe.getMessage());
+ }
+ verify(mockQueue, never()).delete();
+ }
+
+ public void testCreateNewDurableExchange() throws Exception
+ {
+ _virtualHostManagerMBean.createNewExchange(TEST_EXCHANGE_NAME, TEST_EXCHANGE_TYPE, true);
+ verify(_mockVirtualHost).createExchange(TEST_EXCHANGE_NAME, State.ACTIVE, true, LifetimePolicy.PERMANENT, 0, TEST_EXCHANGE_TYPE, EMPTY_ARGUMENT_MAP);
+ }
+
+ public void testCreateNewExchangeWithUnknownExchangeType() throws Exception
+ {
+ String exchangeType = "notknown";
+ try
+ {
+ _virtualHostManagerMBean.createNewExchange(TEST_EXCHANGE_NAME, exchangeType, true);
+ fail("Exception not thrown");
+ }
+ catch (OperationsException oe)
+ {
+ // PASS
+ }
+ verify(_mockVirtualHost, never()).createExchange(TEST_EXCHANGE_NAME, State.ACTIVE, true, LifetimePolicy.PERMANENT, 0, exchangeType, EMPTY_ARGUMENT_MAP);
+ }
+
+ public void testUnregisterExchange() throws Exception
+ {
+ Exchange mockExchange = mock(Exchange.class);
+ when(mockExchange.getName()).thenReturn("exchange1");
+ when(_mockVirtualHost.getExchanges()).thenReturn(Collections.singletonList(mockExchange));
+
+ _virtualHostManagerMBean.unregisterExchange("exchange1");
+ verify(mockExchange).delete();
+ }
+
+ public void testUnregisterExchangeWhenExchangeDoesNotExist() throws Exception
+ {
+ Exchange mockExchange = mock(Exchange.class);
+ when(mockExchange.getName()).thenReturn("exchange1");
+ when(_mockVirtualHost.getExchanges()).thenReturn(Collections.singletonList(mockExchange));
+
+ try
+ {
+ _virtualHostManagerMBean.unregisterExchange("unknownexchange");
+ fail("Exception not thrown");
+ }
+ catch(OperationsException oe)
+ {
+ // PASS
+ assertEquals("No such exchange \"unknownexchange\"", oe.getMessage());
+ }
+
+ verify(mockExchange, never()).delete();
+ }
+}
diff --git a/java/systests/src/main/java/org/apache/qpid/management/jmx/ManagedBrokerMBeanTest.java b/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/BrokerManagementTest.java
index ba0f955d76..7473a4d3e7 100644
--- a/java/systests/src/main/java/org/apache/qpid/management/jmx/ManagedBrokerMBeanTest.java
+++ b/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/BrokerManagementTest.java
@@ -16,38 +16,23 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.qpid.management.jmx;
+package org.apache.qpid.systest.management.jmx;
import org.apache.qpid.exchange.ExchangeDefaults;
import org.apache.qpid.management.common.mbeans.ManagedBroker;
import org.apache.qpid.management.common.mbeans.ManagedExchange;
-import org.apache.qpid.management.common.mbeans.ManagedQueue;
-import org.apache.qpid.server.queue.AMQQueueFactory;
import org.apache.qpid.test.utils.JMXTestUtils;
import org.apache.qpid.test.utils.QpidBrokerTestCase;
-import javax.management.MBeanException;
-import javax.management.ObjectName;
-import java.util.Collections;
-import java.util.Map;
-
/**
* Tests the JMX API for the Managed Broker.
*
*/
-public class ManagedBrokerMBeanTest extends QpidBrokerTestCase
+public class BrokerManagementTest extends QpidBrokerTestCase
{
- /**
- * Test virtual host
- */
private static final String VIRTUAL_HOST = "test";
/**
- * Test exchange type
- */
- private static final String EXCHANGE_TYPE = "topic";
-
- /**
* JMX helper.
*/
private JMXTestUtils _jmxUtils;
@@ -86,7 +71,7 @@ public class ManagedBrokerMBeanTest extends QpidBrokerTestCase
_managedBroker.createNewQueue(queueName, "testowner", true);
// Ensure the queue exists
- assertNotNull("Queue object name expected to exist", _jmxUtils.getQueueObjectName("test", queueName));
+ assertNotNull("Queue object name expected to exist", _jmxUtils.getQueueObjectName(VIRTUAL_HOST, queueName));
assertNotNull("Manager queue expected to be available", _jmxUtils.getManagedQueue(queueName));
// Now verify that the default exchange has been bound.
@@ -108,14 +93,11 @@ public class ManagedBrokerMBeanTest extends QpidBrokerTestCase
{
String exchangeName = getTestName();
_managedBroker.createNewExchange(exchangeName, "topic", true);
- String queryString = "org.apache.qpid:type=VirtualHost.Exchange,VirtualHost="
- + ObjectName.quote(VIRTUAL_HOST) + ",name=" + ObjectName.quote(exchangeName) + ",ExchangeType="
- + EXCHANGE_TYPE;
- ManagedExchange exchange = _jmxUtils.getManagedObject(ManagedExchange.class, queryString);
+
+ ManagedExchange exchange = _jmxUtils.getManagedExchange(exchangeName);
assertNotNull("Exchange should exist", exchange);
_managedBroker.unregisterExchange(exchangeName);
- assertFalse("Exchange should have been removed", _jmxUtils.isManagedObjectExist(queryString));
}
/**
@@ -130,35 +112,13 @@ public class ManagedBrokerMBeanTest extends QpidBrokerTestCase
_managedBroker.unregisterExchange(defaultExchangeName);
fail("Exception not thrown");
}
- catch (MBeanException mbe)
+ catch (UnsupportedOperationException e)
{
// PASS
- assertEquals("Error in unregistering exchange " + defaultExchangeName, mbe.getMessage());
- assertTrue(mbe.getCause().getMessage().contains("Cannot unregister the default exchange"));
+ assertEquals("'<<default>>' is a reserved exchange and can't be deleted", e.getMessage());
}
final ManagedExchange defaultExchange = _jmxUtils.getManagedExchange(defaultExchangeName);
assertNotNull("Exchange should exist", defaultExchange);
}
- /**
- * Tests queue creation with {@link AMQQueueFactory#X_QPID_MAXIMUM_DELIVERY_COUNT} argument. Also tests
- * that the attribute is exposed correctly through {@link ManagedQueue#getMaximumDeliveryCount()}.
- */
- public void testCreateQueueWithMaximumDeliveryCountSet() throws Exception
- {
- final String queueName = getName();
- final ManagedBroker managedBroker = _jmxUtils.getManagedBroker(VIRTUAL_HOST);
-
- final Integer deliveryCount = 1;
- final Map<String, Object> args = Collections.singletonMap(AMQQueueFactory.X_QPID_MAXIMUM_DELIVERY_COUNT, (Object)deliveryCount);
- managedBroker.createNewQueue(queueName, "testowner", true, args);
-
- // Ensure the queue exists
- assertNotNull("Queue object name expected to exist", _jmxUtils.getQueueObjectName("test", queueName));
- assertNotNull("Manager queue expected to be available", _jmxUtils.getManagedQueue(queueName));
-
- final ManagedQueue managedQueue = _jmxUtils.getManagedQueue(queueName);
- assertEquals("Unexpected maximum delivery count", deliveryCount, managedQueue.getMaximumDeliveryCount());
- }
-
}
diff --git a/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/ConnectionManagementTest.java b/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/ConnectionManagementTest.java
new file mode 100644
index 0000000000..28d7bf4aed
--- /dev/null
+++ b/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/ConnectionManagementTest.java
@@ -0,0 +1,283 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.qpid.systest.management.jmx;
+
+import java.io.IOException;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.List;
+
+import javax.jms.Connection;
+import javax.jms.Destination;
+import javax.jms.JMSException;
+import javax.jms.Message;
+import javax.jms.MessageConsumer;
+import javax.jms.Queue;
+import javax.jms.Session;
+import javax.management.JMException;
+import javax.management.openmbean.CompositeData;
+import javax.management.openmbean.CompositeDataSupport;
+import javax.management.openmbean.TabularData;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.qpid.common.QpidProperties;
+import org.apache.qpid.management.common.mbeans.ManagedConnection;
+import org.apache.qpid.management.common.mbeans.ManagedQueue;
+import org.apache.qpid.test.utils.JMXTestUtils;
+import org.apache.qpid.test.utils.QpidBrokerTestCase;
+
+public class ConnectionManagementTest extends QpidBrokerTestCase
+{
+ private static final String VIRTUAL_HOST_NAME = "test";
+
+ private JMXTestUtils _jmxUtils;
+ private Connection _connection;
+
+ public void setUp() throws Exception
+ {
+ _jmxUtils = new JMXTestUtils(this);
+ _jmxUtils.setUp(); // modifies broker config therefore must be done before super.setUp()
+ super.setUp();
+ _jmxUtils.open();
+ }
+
+ public void tearDown() throws Exception
+ {
+ try
+ {
+ if (_jmxUtils != null)
+ {
+ _jmxUtils.close();
+ }
+ }
+ finally
+ {
+ super.tearDown();
+ }
+ }
+
+ public void testNumberOfManagedConnectionsMatchesNumberOfClientConnections() throws Exception
+ {
+ assertEquals("Expected no managed connections", 0, getManagedConnections().size());
+
+ _connection = getConnection();
+ assertEquals("Expected one managed connection", 1, getManagedConnections().size());
+
+ _connection.close();
+ assertEquals("Expected no managed connections after client connection closed", 0, getManagedConnections().size());
+ }
+
+ public void testGetAttributes() throws Exception
+ {
+ _connection = getConnection();
+ final ManagedConnection mBean = getConnectionMBean();
+
+ checkAuthorisedId(mBean);
+ checkClientVersion(mBean);
+ checkClientId(mBean);
+ }
+
+ public void testNonTransactedSession() throws Exception
+ {
+ _connection = getConnection();
+
+ boolean transactional = false;
+ boolean flowBlocked = false;
+
+ _connection.createSession(transactional, Session.AUTO_ACKNOWLEDGE);
+
+ final ManagedConnection mBean = getConnectionMBean();
+ final CompositeDataSupport row = getTheOneChannelRow(mBean);
+ assertChannelRowData(row, 0, transactional, flowBlocked);
+ }
+
+ public void testTransactedSessionWithUnackMessages() throws Exception
+ {
+ _connection = getConnection();
+ _connection.start();
+
+ boolean transactional = true;
+ int numberOfMessages = 2;
+ final Session session = _connection.createSession(transactional, Session.SESSION_TRANSACTED);
+ final Destination destination = session.createQueue(getTestQueueName());
+ final MessageConsumer consumer = session.createConsumer(destination);
+
+ sendMessage(session, destination, numberOfMessages);
+ receiveMessagesWithoutCommit(consumer, numberOfMessages);
+
+ final ManagedConnection mBean = getConnectionMBean();
+ final CompositeDataSupport row = getTheOneChannelRow(mBean);
+ boolean flowBlocked = false;
+ assertChannelRowData(row, numberOfMessages, transactional, flowBlocked);
+
+ // check that commit advances the lastIoTime
+ final Date initialLastIOTime = mBean.getLastIoTime();
+ session.commit();
+ assertTrue("commit should have caused last IO time to advance", mBean.getLastIoTime().after(initialLastIOTime));
+
+ // check that channels() now returns one session with no unacknowledged messages
+ final CompositeDataSupport rowAfterCommit = getTheOneChannelRow(mBean);
+ final Number unackCountAfterCommit = (Number) rowAfterCommit.get(ManagedConnection.UNACKED_COUNT);
+ assertEquals("Unexpected number of unacknowledged messages", 0, unackCountAfterCommit);
+ }
+
+
+ public void testProducerFlowBlocked() throws Exception
+ {
+ _connection = getConnection();
+ _connection.start();
+
+ String queueName = getTestQueueName();
+ Session session = _connection.createSession(true, Session.SESSION_TRANSACTED);
+ Queue queue = session.createQueue(queueName);
+ createQueueOnBroker(session, queue);
+
+ ManagedQueue managedQueue = _jmxUtils.getManagedQueue(queueName);
+ managedQueue.setFlowResumeCapacity(DEFAULT_MESSAGE_SIZE * 2l);
+ managedQueue.setCapacity(DEFAULT_MESSAGE_SIZE * 3l);
+
+ final ManagedConnection managedConnection = getConnectionMBean();
+
+ // Check that producer flow is not block before test
+ final CompositeDataSupport rowBeforeSend = getTheOneChannelRow(managedConnection);
+ assertFlowBlocked(rowBeforeSend, false);
+
+
+ // Check that producer flow does not become block too soon
+ sendMessage(session, queue, 3);
+ final CompositeDataSupport rowBeforeFull = getTheOneChannelRow(managedConnection);
+ assertFlowBlocked(rowBeforeFull, false);
+
+ // Fourth message will over-fill the queue (but as we are not sending more messages, client thread wont't block)
+ sendMessage(session, queue, 1);
+ final CompositeDataSupport rowAfterFull = getTheOneChannelRow(managedConnection);
+ assertFlowBlocked(rowAfterFull, true);
+
+ // Consume two to bring the queue down to the resume capacity
+ MessageConsumer consumer = session.createConsumer(queue);
+ assertNotNull("Could not receive first message", consumer.receive(1000));
+ assertNotNull("Could not receive second message", consumer.receive(1000));
+ session.commit();
+
+ // Check that producer flow is no longer blocked
+ final CompositeDataSupport rowAfterReceive = getTheOneChannelRow(managedConnection);
+ assertFlowBlocked(rowAfterReceive, false);
+ }
+
+ private void createQueueOnBroker(Session session, Destination destination) throws JMSException
+ {
+ session.createConsumer(destination).close(); // Create a consumer only to cause queue creation
+ }
+
+ private void assertChannelRowData(final CompositeData row, int unacknowledgedMessages, boolean isTransactional, boolean flowBlocked)
+ {
+ assertNotNull(row);
+ assertEquals("Unexpected transactional flag", isTransactional, row.get(ManagedConnection.TRANSACTIONAL));
+ assertEquals("Unexpected unacknowledged message count", unacknowledgedMessages, row.get(ManagedConnection.UNACKED_COUNT));
+ assertEquals("Unexpected flow blocked", flowBlocked, row.get(ManagedConnection.FLOW_BLOCKED));
+ }
+
+ private void assertFlowBlocked(final CompositeData row, boolean flowBlocked)
+ {
+ assertNotNull(row);
+ assertEquals("Unexpected flow blocked", flowBlocked, row.get(ManagedConnection.FLOW_BLOCKED));
+ }
+
+ private void checkAuthorisedId(ManagedConnection mBean) throws Exception
+ {
+ assertEquals("Unexpected authorized id", GUEST_USERNAME, mBean.getAuthorizedId());
+ }
+
+ private void checkClientVersion(ManagedConnection mBean) throws Exception
+ {
+ String expectedVersion = QpidProperties.getReleaseVersion();
+ assertTrue(StringUtils.isNotBlank(expectedVersion));
+
+ assertEquals("Unexpected version", expectedVersion, mBean.getVersion());
+ }
+
+ private void checkClientId(ManagedConnection mBean) throws Exception
+ {
+ String expectedClientId = _connection.getClientID();
+ assertTrue(StringUtils.isNotBlank(expectedClientId));
+
+ assertEquals("Unexpected ClientId", expectedClientId, mBean.getClientId());
+ }
+
+ private ManagedConnection getConnectionMBean()
+ {
+ List<ManagedConnection> connections = getManagedConnections();
+ assertNotNull("Connection MBean is not found", connections);
+ assertEquals("Unexpected number of connection mbeans", 1, connections.size());
+ final ManagedConnection mBean = connections.get(0);
+ assertNotNull("Connection MBean is null", mBean);
+ return mBean;
+ }
+
+ private List<ManagedConnection> getManagedConnections()
+ {
+ return _jmxUtils.getManagedConnections(VIRTUAL_HOST_NAME);
+ }
+
+ private CompositeDataSupport getTheOneChannelRow(final ManagedConnection mBean) throws Exception
+ {
+ TabularData channelsData = getChannelsDataWithRetry(mBean);
+
+ assertEquals("Unexpected number of rows in channel table", 1, channelsData.size());
+
+ @SuppressWarnings("unchecked")
+ final Iterator<CompositeDataSupport> rowItr = (Iterator<CompositeDataSupport>) channelsData.values().iterator();
+ final CompositeDataSupport row = rowItr.next();
+ return row;
+ }
+
+ private void receiveMessagesWithoutCommit(final MessageConsumer consumer, int numberOfMessages) throws Exception
+ {
+ for (int i = 0; i < numberOfMessages; i++)
+ {
+ final Message m = consumer.receive(1000l);
+ assertNotNull("Message " + i + " is not received", m);
+ }
+ }
+
+ private TabularData getChannelsDataWithRetry(final ManagedConnection mBean)
+ throws IOException, JMException
+ {
+ TabularData channelsData = mBean.channels();
+ int retries = 0;
+ while(channelsData.size() == 0 && retries < 5)
+ {
+ sleep();
+ channelsData = mBean.channels();
+ retries++;
+ }
+ return channelsData;
+ }
+
+ private void sleep()
+ {
+ try
+ {
+ Thread.sleep(50);
+ }
+ catch (InterruptedException ie)
+ {
+ Thread.currentThread().interrupt();
+ }
+ }}
diff --git a/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/LoggingManagementTest.java b/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/LoggingManagementTest.java
new file mode 100644
index 0000000000..ac6730638e
--- /dev/null
+++ b/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/LoggingManagementTest.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.systest.management.jmx;
+
+import java.io.File;
+import java.util.List;
+
+import javax.management.openmbean.CompositeData;
+import javax.management.openmbean.TabularData;
+
+import org.apache.qpid.management.common.mbeans.LoggingManagement;
+import org.apache.qpid.server.jmx.mbeans.LoggingManagementMBeanTest;
+import org.apache.qpid.server.logging.log4j.LoggingFacadeTest;
+import org.apache.qpid.test.utils.JMXTestUtils;
+import org.apache.qpid.test.utils.QpidBrokerTestCase;
+import org.apache.qpid.util.FileUtils;
+import org.apache.qpid.util.LogMonitor;
+
+/**
+ * System test for Logging Management. <b>These tests rely on value set within
+ * test-profiles/log4j-test.xml</b>.
+ *
+ * @see LoggingManagementMBeanTest
+ * @see LoggingFacadeTest
+ *
+ */
+public class LoggingManagementTest extends QpidBrokerTestCase
+{
+ private JMXTestUtils _jmxUtils;
+ private LoggingManagement _loggingManagement;
+ private LogMonitor _monitor;
+
+ public void setUp() throws Exception
+ {
+ _jmxUtils = new JMXTestUtils(this);
+ _jmxUtils.setUp();
+
+ // System test normally run with log for4j test config from beneath test-profiles. We need to
+ // copy it as some of our tests write to this file.
+
+ File tmpLogFile = File.createTempFile("log4j" + "." + getName(), ".xml");
+ tmpLogFile.deleteOnExit();
+ FileUtils.copy(_logConfigFile, tmpLogFile);
+
+ _logConfigFile = tmpLogFile;
+
+ super.setUp();
+ _jmxUtils.open();
+
+ _loggingManagement = _jmxUtils.getLoggingManagement();
+ _monitor = new LogMonitor(_outputFile);
+ }
+
+ public void tearDown() throws Exception
+ {
+ try
+ {
+ if (_jmxUtils != null)
+ {
+ _jmxUtils.close();
+ }
+ }
+ finally
+ {
+ super.tearDown();
+ }
+ }
+
+ public void testViewEffectiveRuntimeLoggerLevels() throws Exception
+ {
+ final String qpidMainLogger = "org.apache.qpid";
+
+ TabularData table = _loggingManagement.viewEffectiveRuntimeLoggerLevels();
+ final CompositeData row = table.get(new String[] {qpidMainLogger} );
+ assertChannelRow(row, qpidMainLogger, "DEBUG");
+ }
+
+ public void testViewConfigFileLoggerLevels() throws Exception
+ {
+ final String operationalLoggingLogger = "qpid.message";
+
+ TabularData table = _loggingManagement.viewConfigFileLoggerLevels();
+ final CompositeData row = table.get(new String[] {operationalLoggingLogger} );
+ assertChannelRow(row, operationalLoggingLogger, "INFO");
+ }
+
+ public void testTurnOffOrgApacheQpidAtRuntime() throws Exception
+ {
+ final String logger = "org.apache.qpid";
+ _monitor.markDiscardPoint();
+ _loggingManagement.setRuntimeLoggerLevel(logger, "OFF");
+
+ List<String> matches = _monitor.findMatches("Setting level to OFF for logger 'org.apache.qpid'");
+ assertEquals(1, matches.size());
+
+ TabularData table = _loggingManagement.viewEffectiveRuntimeLoggerLevels();
+ final CompositeData row1 = table.get(new String[] {logger} );
+ assertChannelRow(row1, logger, "OFF");
+ }
+
+ public void testChangesToConfigFileBecomeEffectiveAfterReload() throws Exception
+ {
+ final String operationalLoggingLogger = "qpid.message";
+ assertEffectiveLoggingLevel(operationalLoggingLogger, "INFO");
+
+ _monitor.markDiscardPoint();
+ _loggingManagement.setConfigFileLoggerLevel(operationalLoggingLogger, "OFF");
+
+ List<String> matches = _monitor.findMatches("Setting level to OFF for logger 'qpid.message'");
+ assertEquals(1, matches.size());
+
+ assertEffectiveLoggingLevel(operationalLoggingLogger, "INFO");
+
+ _loggingManagement.reloadConfigFile();
+
+ assertEffectiveLoggingLevel(operationalLoggingLogger, "OFF");
+ }
+
+ private void assertEffectiveLoggingLevel(String operationalLoggingLogger, String expectedLevel)
+ {
+ TabularData table = _loggingManagement.viewEffectiveRuntimeLoggerLevels();
+ final CompositeData row1 = table.get(new String[] {operationalLoggingLogger} );
+ assertChannelRow(row1, operationalLoggingLogger, expectedLevel);
+ }
+
+ private void assertChannelRow(final CompositeData row, String logger, String level)
+ {
+ assertNotNull("No row for " + logger, row);
+ assertEquals("Unexpected logger name", logger, row.get(LoggingManagement.LOGGER_NAME));
+ assertEquals("Unexpected level", level, row.get(LoggingManagement.LOGGER_LEVEL));
+ }
+
+}
diff --git a/java/systests/src/main/java/org/apache/qpid/management/jmx/ManagementActorLoggingTest.java b/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/ManagementActorLoggingTest.java
index 0e2875235f..47b38381c5 100644
--- a/java/systests/src/main/java/org/apache/qpid/management/jmx/ManagementActorLoggingTest.java
+++ b/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/ManagementActorLoggingTest.java
@@ -18,7 +18,7 @@
* under the License.
*
*/
-package org.apache.qpid.management.jmx;
+package org.apache.qpid.systest.management.jmx;
import org.apache.qpid.management.common.mbeans.ManagedBroker;
import org.apache.qpid.management.common.mbeans.ManagedConnection;
diff --git a/java/systests/src/main/java/org/apache/qpid/server/logging/ManagementLoggingTest.java b/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/ManagementLoggingTest.java
index c8a6d02761..6100d5a23e 100644
--- a/java/systests/src/main/java/org/apache/qpid/server/logging/ManagementLoggingTest.java
+++ b/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/ManagementLoggingTest.java
@@ -18,10 +18,11 @@
* under the License.
*
*/
-package org.apache.qpid.server.logging;
+package org.apache.qpid.systest.management.jmx;
import org.apache.qpid.server.configuration.ServerConfiguration;
+import org.apache.qpid.server.logging.AbstractTestLogging;
import org.apache.qpid.test.utils.JMXTestUtils;
import org.apache.qpid.util.LogMonitor;
@@ -177,7 +178,7 @@ public class ManagementLoggingTest extends AbstractTestLogging
if (isJavaBroker())
{
startBrokerAndCreateMonitor(true, false);
-
+
List<String> results = waitAndFindMatches("MNG-1002");
// Validation
diff --git a/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/QueueManagementTest.java b/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/QueueManagementTest.java
new file mode 100644
index 0000000000..79d04b239e
--- /dev/null
+++ b/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/QueueManagementTest.java
@@ -0,0 +1,696 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.qpid.systest.management.jmx;
+
+import org.apache.commons.lang.time.FastDateFormat;
+
+import org.apache.log4j.Logger;
+import org.apache.qpid.client.AMQSession;
+import org.apache.qpid.configuration.ClientProperties;
+import org.apache.qpid.framing.AMQShortString;
+import org.apache.qpid.management.common.mbeans.ManagedBroker;
+import org.apache.qpid.management.common.mbeans.ManagedQueue;
+import org.apache.qpid.server.queue.AMQQueueFactory;
+import org.apache.qpid.server.queue.NotificationCheckTest;
+import org.apache.qpid.server.queue.SimpleAMQQueueTest;
+import org.apache.qpid.test.client.destination.AddressBasedDestinationTest;
+import org.apache.qpid.test.utils.JMXTestUtils;
+import org.apache.qpid.test.utils.QpidBrokerTestCase;
+
+import javax.jms.Connection;
+import javax.jms.Destination;
+import javax.jms.JMSException;
+import javax.jms.Message;
+import javax.jms.MessageConsumer;
+import javax.jms.MessageListener;
+import javax.jms.Queue;
+import javax.jms.Session;
+import javax.jms.TextMessage;
+import javax.management.Notification;
+import javax.management.NotificationListener;
+import javax.management.openmbean.CompositeData;
+import javax.management.openmbean.TabularData;
+import javax.naming.NamingException;
+
+import java.util.ArrayList;
+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.SortedSet;
+import java.util.TreeSet;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicReference;
+
+/**
+ * Tests the JMX API for the Managed Queue.
+ *
+ */
+public class QueueManagementTest extends QpidBrokerTestCase
+{
+
+ private static final Logger LOGGER = Logger.getLogger(QueueManagementTest.class);
+
+ private static final String VIRTUAL_HOST = "test";
+ private static final String TEST_QUEUE_DESCRIPTION = "my description";
+
+ private JMXTestUtils _jmxUtils;
+ private Connection _connection;
+ private Session _session;
+
+ private String _sourceQueueName;
+ private String _destinationQueueName;
+ private Destination _sourceQueue;
+ private Destination _destinationQueue;
+ private ManagedQueue _managedSourceQueue;
+ private ManagedQueue _managedDestinationQueue;
+
+ public void setUp() throws Exception
+ {
+ _jmxUtils = new JMXTestUtils(this);
+ _jmxUtils.setUp();
+
+ super.setUp();
+ _sourceQueueName = getTestQueueName() + "_src";
+ _destinationQueueName = getTestQueueName() + "_dest";
+
+ createConnectionAndSession();
+
+ _sourceQueue = _session.createQueue(_sourceQueueName);
+ _destinationQueue = _session.createQueue(_destinationQueueName);
+ createQueueOnBroker(_sourceQueue);
+ createQueueOnBroker(_destinationQueue);
+
+ _jmxUtils.open();
+
+ createManagementInterfacesForQueues();
+ }
+
+ public void tearDown() throws Exception
+ {
+ if (_jmxUtils != null)
+ {
+ _jmxUtils.close();
+ }
+ super.tearDown();
+ }
+
+ public void testQueueAttributes() throws Exception
+ {
+ Queue queue = _session.createQueue(getTestQueueName());
+ createQueueOnBroker(queue);
+
+ final String queueName = queue.getQueueName();
+
+ final ManagedQueue managedQueue = _jmxUtils.getManagedQueue(queueName);
+ assertEquals("Unexpected name", queueName, managedQueue.getName());
+ assertEquals("Unexpected queue type", "standard", managedQueue.getQueueType());
+ }
+
+ public void testExclusiveQueueHasJmsClientIdAsOwner() throws Exception
+ {
+ Queue tmpQueue = _session.createTemporaryQueue();
+
+ final String queueName = tmpQueue.getQueueName();
+
+ final ManagedQueue managedQueue = _jmxUtils.getManagedQueue(queueName);
+ assertNotNull(_connection.getClientID());
+ assertEquals("Unexpected owner", _connection.getClientID(), managedQueue.getOwner());
+ }
+
+ public void testNonExclusiveQueueHasNoOwner() throws Exception
+ {
+ Queue nonExclusiveQueue = _session.createQueue(getTestQueueName());
+ createQueueOnBroker(nonExclusiveQueue);
+
+ final String queueName = nonExclusiveQueue.getQueueName();
+
+ final ManagedQueue managedQueue = _jmxUtils.getManagedQueue(queueName);
+ assertNull("Unexpected owner", managedQueue.getOwner());
+ }
+
+ public void testSetNewQueueDescriptionOnExistingQueue() throws Exception
+ {
+ Queue queue = _session.createQueue(getTestQueueName());
+ createQueueOnBroker(queue);
+
+ final String queueName = queue.getQueueName();
+
+ final ManagedQueue managedQueue = _jmxUtils.getManagedQueue(queueName);
+ assertNull("Unexpected description", managedQueue.getDescription());
+
+ managedQueue.setDescription(TEST_QUEUE_DESCRIPTION);
+ assertEquals(TEST_QUEUE_DESCRIPTION, managedQueue.getDescription());
+ }
+
+ public void testNewQueueWithDescription() throws Exception
+ {
+ String queueName = getTestQueueName();
+ Map<String, Object> arguments = Collections.singletonMap(AMQQueueFactory.X_QPID_DESCRIPTION, (Object)TEST_QUEUE_DESCRIPTION);
+ ((AMQSession<?, ?>)_session).createQueue(AMQShortString.valueOf(queueName), false, true, false, arguments);
+
+ final ManagedQueue managedQueue = _jmxUtils.getManagedQueue(queueName);
+ assertEquals(TEST_QUEUE_DESCRIPTION, managedQueue.getDescription());
+ }
+
+ /**
+ * Requires persistent store.
+ */
+ public void testQueueDescriptionSurvivesRestart() throws Exception
+ {
+ String queueName = getTestQueueName();
+ Map<String, Object> arguments = Collections.singletonMap(AMQQueueFactory.X_QPID_DESCRIPTION, (Object)TEST_QUEUE_DESCRIPTION);
+
+ ((AMQSession<?, ?>)_session).createQueue(AMQShortString.valueOf(queueName), false, true, false, arguments);
+
+ ManagedQueue managedQueue = _jmxUtils.getManagedQueue(queueName);
+ assertEquals(TEST_QUEUE_DESCRIPTION, managedQueue.getDescription());
+
+ restartBroker();
+
+ managedQueue = _jmxUtils.getManagedQueue(queueName);
+ assertEquals(TEST_QUEUE_DESCRIPTION, managedQueue.getDescription());
+ }
+
+ /**
+ * Tests queue creation with {@link AMQQueueFactory#X_QPID_MAXIMUM_DELIVERY_COUNT} argument. Also tests
+ * that the attribute is exposed correctly through {@link ManagedQueue#getMaximumDeliveryCount()}.
+ */
+ public void testCreateQueueWithMaximumDeliveryCountSet() throws Exception
+ {
+ final String queueName = getName();
+ final ManagedBroker managedBroker = _jmxUtils.getManagedBroker(VIRTUAL_HOST);
+
+ final Integer deliveryCount = 1;
+ final Map<String, Object> arguments = Collections.singletonMap(AMQQueueFactory.X_QPID_MAXIMUM_DELIVERY_COUNT, (Object)deliveryCount);
+ managedBroker.createNewQueue(queueName, null, true, arguments);
+
+ // Ensure the queue exists
+ assertNotNull("Queue object name expected to exist", _jmxUtils.getQueueObjectName("test", queueName));
+ assertNotNull("Manager queue expected to be available", _jmxUtils.getManagedQueue(queueName));
+
+ final ManagedQueue managedQueue = _jmxUtils.getManagedQueue(queueName);
+ assertEquals("Unexpected maximum delivery count", deliveryCount, managedQueue.getMaximumDeliveryCount());
+ }
+
+ /**
+ * Requires 0-10 as relies on ADDR addresses.
+ * @see AddressBasedDestinationTest for the testing of message routing to the alternate exchange
+ */
+ public void testGetSetAlternateExchange() throws Exception
+ {
+ String queueName = getTestQueueName();
+ String altExchange = "amq.fanout";
+ String addrWithAltExch = String.format("ADDR:%s;{create:always,node:{type:queue,x-declare:{alternate-exchange:'%s'}}}", queueName, altExchange);
+ Queue queue = _session.createQueue(addrWithAltExch);
+
+ createQueueOnBroker(queue);
+
+ final ManagedQueue managedQueue = _jmxUtils.getManagedQueue(queueName);
+ assertEquals("Newly created queue does not have expected alternate exchange", altExchange, managedQueue.getAlternateExchange());
+
+ String newAltExch = "amq.topic";
+ managedQueue.setAlternateExchange(newAltExch);
+ assertEquals("Unexpected alternate exchange after set", newAltExch, managedQueue.getAlternateExchange());
+ }
+
+ /**
+ * Requires 0-10 as relies on ADDR addresses.
+ */
+ public void testRemoveAlternateExchange() throws Exception
+ {
+ String queueName = getTestQueueName();
+ String altExchange = "amq.fanout";
+ String addrWithAltExch = String.format("ADDR:%s;{create:always,node:{type:queue,x-declare:{alternate-exchange:'%s'}}}", queueName, altExchange);
+ Queue queue = _session.createQueue(addrWithAltExch);
+
+ createQueueOnBroker(queue);
+
+ final ManagedQueue managedQueue = _jmxUtils.getManagedQueue(queueName);
+ assertEquals("Newly created queue does not have expected alternate exchange", altExchange, managedQueue.getAlternateExchange());
+
+ managedQueue.setAlternateExchange("");
+ assertNull("Unexpected alternate exchange after set", managedQueue.getAlternateExchange());
+ }
+
+ /**
+ * Requires persistent store
+ * Requires 0-10 as relies on ADDR addresses.
+ */
+ public void testAlternateExchangeSurvivesRestart() throws Exception
+ {
+ String nonMandatoryExchangeName = "exch" + getName();
+
+ final ManagedBroker managedBroker = _jmxUtils.getManagedBroker(VIRTUAL_HOST);
+ managedBroker.createNewExchange(nonMandatoryExchangeName, "fanout", true);
+
+ String queueName1 = getTestQueueName() + "1";
+ String altExchange1 = "amq.fanout";
+ String addr1WithAltExch = String.format("ADDR:%s;{create:always,node:{durable: true,type:queue,x-declare:{alternate-exchange:'%s'}}}", queueName1, altExchange1);
+ Queue queue1 = _session.createQueue(addr1WithAltExch);
+
+ String queueName2 = getTestQueueName() + "2";
+ String addr2WithoutAltExch = String.format("ADDR:%s;{create:always,node:{durable: true,type:queue}}", queueName2);
+ Queue queue2 = _session.createQueue(addr2WithoutAltExch);
+
+ createQueueOnBroker(queue1);
+ createQueueOnBroker(queue2);
+
+ ManagedQueue managedQueue1 = _jmxUtils.getManagedQueue(queueName1);
+ assertEquals("Newly created queue1 does not have expected alternate exchange", altExchange1, managedQueue1.getAlternateExchange());
+
+ ManagedQueue managedQueue2 = _jmxUtils.getManagedQueue(queueName2);
+ assertNull("Newly created queue2 does not have expected alternate exchange", managedQueue2.getAlternateExchange());
+
+ String altExchange2 = nonMandatoryExchangeName;
+ managedQueue2.setAlternateExchange(altExchange2);
+
+ restartBroker();
+
+ managedQueue1 = _jmxUtils.getManagedQueue(queueName1);
+ assertEquals("Queue1 does not have expected alternate exchange after restart", altExchange1, managedQueue1.getAlternateExchange());
+
+ managedQueue2 = _jmxUtils.getManagedQueue(queueName2);
+ assertEquals("Queue2 does not have expected updated alternate exchange after restart", altExchange2, managedQueue2.getAlternateExchange());
+ }
+
+ /**
+ * Tests the ability to receive queue alerts as JMX notifications.
+ *
+ * @see NotificationCheckTest
+ * @see SimpleAMQQueueTest#testNotificationFiredAsync()
+ * @see SimpleAMQQueueTest#testNotificationFiredOnEnqueue()
+ */
+ public void testQueueNotification() throws Exception
+ {
+ final String queueName = getName();
+ final long maximumMessageCount = 3;
+
+ Queue queue = _session.createQueue(queueName);
+ createQueueOnBroker(queue);
+
+ ManagedQueue managedQueue = _jmxUtils.getManagedQueue(queueName);
+ managedQueue.setMaximumMessageCount(maximumMessageCount);
+
+ RecordingNotificationListener listener = new RecordingNotificationListener(1);
+
+ _jmxUtils.addNotificationListener(_jmxUtils.getQueueObjectName(VIRTUAL_HOST, queueName), listener, null, null);
+
+ // Send two messages - this should *not* trigger the notification
+ sendMessage(_session, queue, 2);
+
+ assertEquals("Premature notification received", 0, listener.getNumberOfNotificationsReceived());
+
+ // A further message should trigger the message count alert
+ sendMessage(_session, queue, 1);
+
+ listener.awaitExpectedNotifications(5, TimeUnit.SECONDS);
+
+ assertEquals("Unexpected number of JMX notifications received", 1, listener.getNumberOfNotificationsReceived());
+
+ Notification notification = listener.getLastNotification();
+ assertEquals("Unexpected notification message", "MESSAGE_COUNT_ALERT 3: Maximum count on queue threshold (3) breached.", notification.getMessage());
+ }
+
+ /**
+ * Tests {@link ManagedQueue#viewMessages(long, long)} interface.
+ */
+ public void testViewSingleMessage() throws Exception
+ {
+ final List<Message> sentMessages = sendMessage(_session, _sourceQueue, 1);
+ syncSession(_session);
+ final Message sentMessage = sentMessages.get(0);
+
+ assertEquals("Unexpected queue depth", 1, _managedSourceQueue.getMessageCount().intValue());
+
+ // Check the contents of the message
+ final TabularData tab = _managedSourceQueue.viewMessages(1l, 1l);
+ assertEquals("Unexpected number of rows in table", 1, tab.size());
+ final Iterator<CompositeData> rowItr = (Iterator<CompositeData>) tab.values().iterator();
+
+ final CompositeData row1 = rowItr.next();
+ assertNotNull("Message should have AMQ message id", row1.get(ManagedQueue.MSG_AMQ_ID));
+ assertEquals("Unexpected queue position", 1l, row1.get(ManagedQueue.MSG_QUEUE_POS));
+ assertEquals("Unexpected redelivered flag", Boolean.FALSE, row1.get(ManagedQueue.MSG_REDELIVERED));
+
+ // Check the contents of header (encoded in a string array)
+ final String[] headerArray = (String[]) row1.get(ManagedQueue.MSG_HEADER);
+ assertNotNull("Expected message header array", headerArray);
+ final Map<String, String> headers = headerArrayToMap(headerArray);
+
+ final String expectedJMSMessageID = isBroker010() ? sentMessage.getJMSMessageID().replace("ID:", "") : sentMessage.getJMSMessageID();
+ final String expectedFormattedJMSTimestamp = FastDateFormat.getInstance(ManagedQueue.JMSTIMESTAMP_DATETIME_FORMAT).format(sentMessage.getJMSTimestamp());
+ assertEquals("Unexpected JMSMessageID within header", expectedJMSMessageID, headers.get("JMSMessageID"));
+ assertEquals("Unexpected JMSPriority within header", String.valueOf(sentMessage.getJMSPriority()), headers.get("JMSPriority"));
+ assertEquals("Unexpected JMSTimestamp within header", expectedFormattedJMSTimestamp, headers.get("JMSTimestamp"));
+ }
+
+ /**
+ * Tests {@link ManagedQueue#moveMessages(long, long, String)} interface.
+ */
+ public void testMoveMessagesBetweenQueues() throws Exception
+ {
+ final int numberOfMessagesToSend = 10;
+
+ sendMessage(_session, _sourceQueue, numberOfMessagesToSend);
+ syncSession(_session);
+ assertEquals("Unexpected queue depth after send", numberOfMessagesToSend, _managedSourceQueue.getMessageCount().intValue());
+
+ List<Long> amqMessagesIds = getAMQMessageIdsOn(_managedSourceQueue, 1, numberOfMessagesToSend);
+
+ // Move first three messages to destination
+ long fromMessageId = amqMessagesIds.get(0);
+ long toMessageId = amqMessagesIds.get(2);
+ _managedSourceQueue.moveMessages(fromMessageId, toMessageId, _destinationQueueName);
+
+ assertEquals("Unexpected queue depth on destination queue after first move", 3, _managedDestinationQueue.getMessageCount().intValue());
+ assertEquals("Unexpected queue depth on source queue after first move", 7, _managedSourceQueue.getMessageCount().intValue());
+
+ // Now move a further two messages to destination
+ fromMessageId = amqMessagesIds.get(7);
+ toMessageId = amqMessagesIds.get(8);
+ _managedSourceQueue.moveMessages(fromMessageId, toMessageId, _destinationQueueName);
+ assertEquals("Unexpected queue depth on destination queue after second move", 5, _managedDestinationQueue.getMessageCount().intValue());
+ assertEquals("Unexpected queue depth on source queue after second move", 5, _managedSourceQueue.getMessageCount().intValue());
+
+ assertMessageIndicesOn(_destinationQueue, 0, 1, 2, 7, 8);
+ }
+
+ /**
+ * Tests {@link ManagedQueue#copyMessages(long, long, String)} interface.
+ */
+ public void testCopyMessagesBetweenQueues() throws Exception
+ {
+ final int numberOfMessagesToSend = 10;
+ sendMessage(_session, _sourceQueue, numberOfMessagesToSend);
+ syncSession(_session);
+ assertEquals("Unexpected queue depth after send", numberOfMessagesToSend, _managedSourceQueue.getMessageCount().intValue());
+
+ List<Long> amqMessagesIds = getAMQMessageIdsOn(_managedSourceQueue, 1, numberOfMessagesToSend);
+
+ // Copy first three messages to destination
+ long fromMessageId = amqMessagesIds.get(0);
+ long toMessageId = amqMessagesIds.get(2);
+ _managedSourceQueue.copyMessages(fromMessageId, toMessageId, _destinationQueueName);
+
+ assertEquals("Unexpected queue depth on destination queue after first copy", 3, _managedDestinationQueue.getMessageCount().intValue());
+ assertEquals("Unexpected queue depth on source queue after first copy", numberOfMessagesToSend, _managedSourceQueue.getMessageCount().intValue());
+
+ // Now copy a further two messages to destination
+ fromMessageId = amqMessagesIds.get(7);
+ toMessageId = amqMessagesIds.get(8);
+ _managedSourceQueue.copyMessages(fromMessageId, toMessageId, _destinationQueueName);
+ assertEquals("Unexpected queue depth on destination queue after second copy", 5, _managedDestinationQueue.getMessageCount().intValue());
+ assertEquals("Unexpected queue depth on source queue after second copy", numberOfMessagesToSend, _managedSourceQueue.getMessageCount().intValue());
+
+ assertMessageIndicesOn(_destinationQueue, 0, 1, 2, 7, 8);
+ }
+
+ public void testMoveMessagesBetweenQueuesWithActiveConsumerOnSourceQueue() throws Exception
+ {
+ setTestClientSystemProperty(ClientProperties.MAX_PREFETCH_PROP_NAME, new Integer(1).toString());
+ Connection asyncConnection = getConnection();
+ asyncConnection.start();
+
+ final int numberOfMessagesToSend = 50;
+ sendMessage(_session, _sourceQueue, numberOfMessagesToSend);
+ syncSession(_session);
+ assertEquals("Unexpected queue depth after send", numberOfMessagesToSend, _managedSourceQueue.getMessageCount().intValue());
+
+ List<Long> amqMessagesIds = getAMQMessageIdsOn(_managedSourceQueue, 1, numberOfMessagesToSend);
+
+ long fromMessageId = amqMessagesIds.get(0);
+ long toMessageId = amqMessagesIds.get(numberOfMessagesToSend - 1);
+
+ CountDownLatch consumerReadToHalfwayLatch = new CountDownLatch(numberOfMessagesToSend / 2);
+ AtomicInteger totalConsumed = new AtomicInteger(0);
+ startAsyncConsumerOn(_sourceQueue, asyncConnection, consumerReadToHalfwayLatch, totalConsumed);
+
+ boolean halfwayPointReached = consumerReadToHalfwayLatch.await(5000, TimeUnit.MILLISECONDS);
+ assertTrue("Did not read half of messages within time allowed", halfwayPointReached);
+
+ _managedSourceQueue.moveMessages(fromMessageId, toMessageId, _destinationQueueName);
+
+ asyncConnection.stop();
+
+ // The exact number of messages moved will be non deterministic, as the number of messages processed
+ // by the consumer cannot be predicted. There is also the possibility that a message can remain
+ // on the source queue. This situation will arise if a message has been acquired by the consumer, but not
+ // yet delivered to the client application (i.e. MessageListener#onMessage()) when the Connection#stop() occurs.
+ //
+ // The number of messages moved + the number consumed + any messages remaining on source should
+ // *always* be equal to the number we originally sent.
+
+ int numberOfMessagesReadByConsumer = totalConsumed.intValue();
+ int numberOfMessagesOnDestinationQueue = _managedDestinationQueue.getMessageCount().intValue();
+ int numberOfMessagesRemainingOnSourceQueue = _managedSourceQueue.getMessageCount().intValue();
+
+ LOGGER.debug("Async consumer read : " + numberOfMessagesReadByConsumer
+ + " Number of messages moved to destination : " + numberOfMessagesOnDestinationQueue
+ + " Number of messages remaining on source : " + numberOfMessagesRemainingOnSourceQueue);
+ assertEquals("Unexpected number of messages after move", numberOfMessagesToSend, numberOfMessagesReadByConsumer + numberOfMessagesOnDestinationQueue + numberOfMessagesRemainingOnSourceQueue);
+ }
+
+ public void testMoveMessagesBetweenQueuesWithActiveConsumerOnDestinationQueue() throws Exception
+ {
+ setTestClientSystemProperty(ClientProperties.MAX_PREFETCH_PROP_NAME, new Integer(1).toString());
+ Connection asyncConnection = getConnection();
+ asyncConnection.start();
+
+ final int numberOfMessagesToSend = 50;
+ sendMessage(_session, _sourceQueue, numberOfMessagesToSend);
+ syncSession(_session);
+ assertEquals("Unexpected queue depth after send", numberOfMessagesToSend, _managedSourceQueue.getMessageCount().intValue());
+
+ List<Long> amqMessagesIds = getAMQMessageIdsOn(_managedSourceQueue, 1, numberOfMessagesToSend);
+ long fromMessageId = amqMessagesIds.get(0);
+ long toMessageId = amqMessagesIds.get(numberOfMessagesToSend - 1);
+
+ AtomicInteger totalConsumed = new AtomicInteger(0);
+ CountDownLatch allMessagesConsumedLatch = new CountDownLatch(numberOfMessagesToSend);
+ startAsyncConsumerOn(_destinationQueue, asyncConnection, allMessagesConsumedLatch, totalConsumed);
+
+ _managedSourceQueue.moveMessages(fromMessageId, toMessageId, _destinationQueueName);
+
+ allMessagesConsumedLatch.await(5000, TimeUnit.MILLISECONDS);
+ assertEquals("Did not consume all messages from destination queue", numberOfMessagesToSend, totalConsumed.intValue());
+ }
+
+ /**
+ * Tests {@link ManagedQueue#moveMessages(long, long, String)} interface.
+ */
+ public void testMoveMessageBetweenQueuesWithBrokerRestart() throws Exception
+ {
+ final int numberOfMessagesToSend = 1;
+
+ sendMessage(_session, _sourceQueue, numberOfMessagesToSend);
+ syncSession(_session);
+ assertEquals("Unexpected queue depth after send", numberOfMessagesToSend, _managedSourceQueue.getMessageCount().intValue());
+
+ restartBroker();
+
+ createManagementInterfacesForQueues();
+ createConnectionAndSession();
+
+ List<Long> amqMessagesIds = getAMQMessageIdsOn(_managedSourceQueue, 1, numberOfMessagesToSend);
+
+ // Move messages to destination
+ long messageId = amqMessagesIds.get(0);
+ _managedSourceQueue.moveMessages(messageId, messageId, _destinationQueueName);
+
+ assertEquals("Unexpected queue depth on destination queue after move", 1, _managedDestinationQueue.getMessageCount().intValue());
+ assertEquals("Unexpected queue depth on source queue after move", 0, _managedSourceQueue.getMessageCount().intValue());
+
+ assertMessageIndicesOn(_destinationQueue, 0);
+ }
+
+ /**
+ * Tests {@link ManagedQueue#copyMessages(long, long, String)} interface.
+ */
+ public void testCopyMessageBetweenQueuesWithBrokerRestart() throws Exception
+ {
+ final int numberOfMessagesToSend = 1;
+
+ sendMessage(_session, _sourceQueue, numberOfMessagesToSend);
+ syncSession(_session);
+ assertEquals("Unexpected queue depth after send", numberOfMessagesToSend, _managedSourceQueue.getMessageCount().intValue());
+
+ restartBroker();
+
+ createManagementInterfacesForQueues();
+ createConnectionAndSession();
+
+ List<Long> amqMessagesIds = getAMQMessageIdsOn(_managedSourceQueue, 1, numberOfMessagesToSend);
+
+ // Move messages to destination
+ long messageId = amqMessagesIds.get(0);
+ _managedSourceQueue.copyMessages(messageId, messageId, _destinationQueueName);
+
+ assertEquals("Unexpected queue depth on destination queue after copy", 1, _managedDestinationQueue.getMessageCount().intValue());
+ assertEquals("Unexpected queue depth on source queue after copy", 1, _managedSourceQueue.getMessageCount().intValue());
+
+ assertMessageIndicesOn(_destinationQueue, 0);
+ }
+
+ @Override
+ public Message createNextMessage(Session session, int messageNumber) throws JMSException
+ {
+ Message message = session.createTextMessage(getContentForMessageNumber(messageNumber));
+ message.setIntProperty(INDEX, messageNumber);
+ return message;
+ }
+
+ private void startAsyncConsumerOn(Destination queue, Connection asyncConnection,
+ final CountDownLatch requiredNumberOfMessagesRead, final AtomicInteger totalConsumed) throws Exception
+ {
+ Session session = asyncConnection.createSession(false, Session.AUTO_ACKNOWLEDGE);
+ MessageConsumer consumer = session.createConsumer(queue);
+ consumer.setMessageListener(new MessageListener()
+ {
+
+ @Override
+ public void onMessage(Message arg0)
+ {
+ totalConsumed.incrementAndGet();
+ requiredNumberOfMessagesRead.countDown();
+ }
+ });
+ }
+
+ private void assertMessageIndicesOn(Destination queue, int... expectedIndices) throws Exception
+ {
+ MessageConsumer consumer = _session.createConsumer(queue);
+
+ for (int i : expectedIndices)
+ {
+ TextMessage message = (TextMessage)consumer.receive(1000);
+ assertNotNull("Expected message with index " + i, message);
+ assertEquals("Expected message with index " + i, i, message.getIntProperty(INDEX));
+ assertEquals("Expected message content", getContentForMessageNumber(i), message.getText());
+ }
+
+ assertNull("Unexpected message encountered", consumer.receive(1000));
+ }
+
+ private List<Long> getAMQMessageIdsOn(ManagedQueue managedQueue, long startIndex, long endIndex) throws Exception
+ {
+ final SortedSet<Long> messageIds = new TreeSet<Long>();
+
+ final TabularData tab = managedQueue.viewMessages(startIndex, endIndex);
+ final Iterator<CompositeData> rowItr = (Iterator<CompositeData>) tab.values().iterator();
+ while(rowItr.hasNext())
+ {
+ final CompositeData row = rowItr.next();
+ long amqMessageId = (Long)row.get(ManagedQueue.MSG_AMQ_ID);
+ messageIds.add(amqMessageId);
+ }
+
+ return new ArrayList<Long>(messageIds);
+ }
+
+ /**
+ *
+ * Utility method to convert array of Strings in the form x = y into a
+ * map with key/value x =&gt; y.
+ *
+ */
+ private Map<String,String> headerArrayToMap(final String[] headerArray)
+ {
+ final Map<String, String> headerMap = new HashMap<String, String>();
+ final List<String> headerList = Arrays.asList(headerArray);
+ for (Iterator<String> iterator = headerList.iterator(); iterator.hasNext();)
+ {
+ final String nameValuePair = iterator.next();
+ final String[] nameValue = nameValuePair.split(" *= *", 2);
+ headerMap.put(nameValue[0], nameValue[1]);
+ }
+ return headerMap;
+ }
+
+ private void createQueueOnBroker(Destination destination) throws JMSException
+ {
+ _session.createConsumer(destination).close(); // Create a consumer only to cause queue creation
+ }
+
+ private void syncSession(Session session) throws Exception
+ {
+ ((AMQSession<?,?>)session).sync();
+ }
+
+ private void createConnectionAndSession() throws JMSException,
+ NamingException
+ {
+ _connection = getConnection();
+ _connection.start();
+ _session = _connection.createSession(true, Session.SESSION_TRANSACTED);
+ }
+
+ private void createManagementInterfacesForQueues()
+ {
+ _managedSourceQueue = _jmxUtils.getManagedQueue(_sourceQueueName);
+ _managedDestinationQueue = _jmxUtils.getManagedQueue(_destinationQueueName);
+ }
+
+ private String getContentForMessageNumber(int msgCount)
+ {
+ return "Message count " + msgCount;
+ }
+
+ private final class RecordingNotificationListener implements NotificationListener
+ {
+ private final CountDownLatch _notificationReceivedLatch;
+ private final AtomicInteger _numberOfNotifications;
+ private final AtomicReference<Notification> _lastNotification;
+
+ private RecordingNotificationListener(int expectedNumberOfNotifications)
+ {
+ _notificationReceivedLatch = new CountDownLatch(expectedNumberOfNotifications);
+ _numberOfNotifications = new AtomicInteger(0);
+ _lastNotification = new AtomicReference<Notification>();
+ }
+
+ @Override
+ public void handleNotification(Notification notification, Object handback)
+ {
+ _lastNotification.set(notification);
+ _numberOfNotifications.incrementAndGet();
+ _notificationReceivedLatch.countDown();
+ }
+
+ public int getNumberOfNotificationsReceived()
+ {
+ return _numberOfNotifications.get();
+ }
+
+ public Notification getLastNotification()
+ {
+ return _lastNotification.get();
+ }
+
+ public void awaitExpectedNotifications(long timeout, TimeUnit timeunit) throws InterruptedException
+ {
+ _notificationReceivedLatch.await(timeout, timeunit);
+ }
+ }
+
+}
diff --git a/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/StatisticsTest.java b/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/StatisticsTest.java
new file mode 100644
index 0000000000..c3fff94923
--- /dev/null
+++ b/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/StatisticsTest.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.systest.management.jmx;
+
+import java.util.List;
+
+import javax.jms.Connection;
+import javax.jms.MessageConsumer;
+import javax.jms.Queue;
+import javax.jms.Session;
+
+import org.apache.qpid.client.AMQConnection;
+import org.apache.qpid.client.AMQSession;
+import org.apache.qpid.management.common.mbeans.ManagedBroker;
+import org.apache.qpid.management.common.mbeans.ManagedConnection;
+import org.apache.qpid.management.common.mbeans.ServerInformation;
+import org.apache.qpid.test.utils.JMXTestUtils;
+import org.apache.qpid.test.utils.QpidBrokerTestCase;
+
+public class StatisticsTest extends QpidBrokerTestCase
+{
+ private static final String TEST_USER = "admin";
+ private static final String TEST_PASSWORD = "admin";
+ private static final int MESSAGE_COUNT_TEST = 5;
+ private static final int MESSAGE_COUNT_DEV = 9;
+
+ private JMXTestUtils _jmxUtils;
+ private Connection _test1, _dev;
+ private Session _testSession, _developmentSession;
+ private Queue _developmentQueue, _testQueue;
+ protected String _brokerUrl;
+
+ @Override
+ public void setUp() throws Exception
+ {
+ _jmxUtils = new JMXTestUtils(this, TEST_USER, TEST_PASSWORD);
+ _jmxUtils.setUp();
+
+ super.setUp();
+
+ _brokerUrl = getBroker().toString();
+ _test1 = new AMQConnection(_brokerUrl, TEST_USER, TEST_PASSWORD, "clientid", "test");
+ _dev = new AMQConnection(_brokerUrl, TEST_USER, TEST_PASSWORD, "clientid", "development");
+ _test1.start();
+ _dev.start();
+
+ _testSession = _test1.createSession(true, Session.SESSION_TRANSACTED);
+ _developmentSession = _dev.createSession(true, Session.SESSION_TRANSACTED);
+
+ _developmentQueue = _developmentSession.createQueue(getTestQueueName());
+ _testQueue = _testSession.createQueue(getTestQueueName());
+
+ //Create queues by opening and closing consumers
+ final MessageConsumer testConsumer = _testSession.createConsumer(_testQueue);
+ testConsumer.close();
+ final MessageConsumer developmentConsumer = _developmentSession.createConsumer(_developmentQueue);
+ developmentConsumer.close();
+
+ _jmxUtils.open();
+ }
+
+ @Override
+ public void tearDown() throws Exception
+ {
+ _jmxUtils.close();
+
+ super.tearDown();
+ }
+
+ public void testInitialStatisticValues() throws Exception
+ {
+ //Check initial values
+ checkSingleConnectionOnVHostStatistics("test", 0, 0, 0, 0);
+ checkVHostStatistics("test", 0, 0, 0, 0);
+ checkSingleConnectionOnVHostStatistics("development", 0, 0, 0, 0);
+ checkVHostStatistics("development", 0, 0, 0, 0);
+ checkBrokerStatistics(0, 0, 0, 0);
+ }
+
+ public void testSendOnSingleVHost() throws Exception
+ {
+ sendMessagesAndSync(_testSession, _testQueue, MESSAGE_COUNT_TEST);
+
+ //Check values
+ checkSingleConnectionOnVHostStatistics("test", MESSAGE_COUNT_TEST, 0, MESSAGE_COUNT_TEST * DEFAULT_MESSAGE_SIZE, 0);
+ checkVHostStatistics("test", MESSAGE_COUNT_TEST, 0, MESSAGE_COUNT_TEST * DEFAULT_MESSAGE_SIZE, 0);
+ checkSingleConnectionOnVHostStatistics("development", 0, 0, 0, 0);
+ checkVHostStatistics("development", 0, 0, 0, 0);
+ checkBrokerStatistics(MESSAGE_COUNT_TEST, 0, MESSAGE_COUNT_TEST * DEFAULT_MESSAGE_SIZE, 0);
+ }
+
+ public void testSendOnTwoVHosts() throws Exception
+ {
+ sendMessagesAndSync(_testSession, _testQueue, MESSAGE_COUNT_TEST);
+ sendMessagesAndSync(_developmentSession, _developmentQueue, MESSAGE_COUNT_DEV);
+
+ //Check values
+ checkSingleConnectionOnVHostStatistics("test", MESSAGE_COUNT_TEST, 0, MESSAGE_COUNT_TEST * DEFAULT_MESSAGE_SIZE, 0);
+ checkVHostStatistics("test", MESSAGE_COUNT_TEST, 0, MESSAGE_COUNT_TEST * DEFAULT_MESSAGE_SIZE, 0);
+ checkSingleConnectionOnVHostStatistics("development", MESSAGE_COUNT_DEV, 0, MESSAGE_COUNT_DEV * DEFAULT_MESSAGE_SIZE, 0);
+ checkVHostStatistics("development", MESSAGE_COUNT_DEV, 0, MESSAGE_COUNT_DEV * DEFAULT_MESSAGE_SIZE, 0);
+ checkBrokerStatistics(MESSAGE_COUNT_TEST + MESSAGE_COUNT_DEV, 0, (MESSAGE_COUNT_TEST + MESSAGE_COUNT_DEV) * DEFAULT_MESSAGE_SIZE, 0);
+ }
+
+ public void testSendAndConsumeOnSingleVHost() throws Exception
+ {
+ sendMessagesAndSync(_testSession, _testQueue, MESSAGE_COUNT_TEST);
+ consumeMessages(_testSession, _testQueue, MESSAGE_COUNT_TEST);
+
+ //Check values
+ checkSingleConnectionOnVHostStatistics("test", MESSAGE_COUNT_TEST, MESSAGE_COUNT_TEST, MESSAGE_COUNT_TEST * DEFAULT_MESSAGE_SIZE, MESSAGE_COUNT_TEST * DEFAULT_MESSAGE_SIZE);
+ checkVHostStatistics("test", MESSAGE_COUNT_TEST, MESSAGE_COUNT_TEST, MESSAGE_COUNT_TEST * DEFAULT_MESSAGE_SIZE, MESSAGE_COUNT_TEST * DEFAULT_MESSAGE_SIZE);
+ checkSingleConnectionOnVHostStatistics("development", 0, 0, 0, 0);
+ checkVHostStatistics("development", 0, 0, 0, 0);
+ checkBrokerStatistics(MESSAGE_COUNT_TEST, MESSAGE_COUNT_TEST, MESSAGE_COUNT_TEST * DEFAULT_MESSAGE_SIZE, MESSAGE_COUNT_TEST * DEFAULT_MESSAGE_SIZE);
+ }
+
+ public void testSendAndConsumeOnTwoVHosts() throws Exception
+ {
+ sendMessagesAndSync(_testSession, _testQueue, MESSAGE_COUNT_TEST);
+ sendMessagesAndSync(_developmentSession, _developmentQueue, MESSAGE_COUNT_DEV);
+ consumeMessages(_testSession, _testQueue, MESSAGE_COUNT_TEST);
+ consumeMessages(_developmentSession, _developmentQueue, MESSAGE_COUNT_DEV);
+
+ //Check values
+ checkSingleConnectionOnVHostStatistics("test", MESSAGE_COUNT_TEST, MESSAGE_COUNT_TEST, MESSAGE_COUNT_TEST * DEFAULT_MESSAGE_SIZE, MESSAGE_COUNT_TEST * DEFAULT_MESSAGE_SIZE);
+ checkVHostStatistics("test", MESSAGE_COUNT_TEST, MESSAGE_COUNT_TEST, MESSAGE_COUNT_TEST * DEFAULT_MESSAGE_SIZE, MESSAGE_COUNT_TEST * DEFAULT_MESSAGE_SIZE);
+ checkSingleConnectionOnVHostStatistics("development", MESSAGE_COUNT_DEV, MESSAGE_COUNT_DEV, MESSAGE_COUNT_DEV * DEFAULT_MESSAGE_SIZE, MESSAGE_COUNT_DEV * DEFAULT_MESSAGE_SIZE);
+ checkVHostStatistics("development", MESSAGE_COUNT_DEV, MESSAGE_COUNT_DEV, MESSAGE_COUNT_DEV * DEFAULT_MESSAGE_SIZE, MESSAGE_COUNT_DEV * DEFAULT_MESSAGE_SIZE);
+ checkBrokerStatistics(MESSAGE_COUNT_TEST + MESSAGE_COUNT_DEV, MESSAGE_COUNT_TEST + MESSAGE_COUNT_DEV, (MESSAGE_COUNT_TEST + MESSAGE_COUNT_DEV) * DEFAULT_MESSAGE_SIZE, (MESSAGE_COUNT_TEST + MESSAGE_COUNT_DEV) * DEFAULT_MESSAGE_SIZE);
+ }
+
+ private void sendMessagesAndSync(Session session, Queue queue, int numberOfMessages) throws Exception
+ {
+ //Send messages via connection on and sync
+ sendMessage(session, queue, numberOfMessages);
+ ((AMQSession<?,?>)session).sync();
+ }
+
+ private void consumeMessages(Session session, Queue queue, int numberOfMessages) throws Exception
+ {
+ //consume the messages on the virtual host
+ final MessageConsumer consumer = session.createConsumer(queue);
+ for (int i = 0 ; i < numberOfMessages ; i++)
+ {
+ assertNotNull("an expected message was not received", consumer.receive(1500));
+ }
+ session.commit();
+ consumer.close();
+ }
+
+ private void checkSingleConnectionOnVHostStatistics(String vHostName, long messagesSent, long messagesReceived, long dataSent, long dataReceived)
+ {
+ List<ManagedConnection> managedConnections = _jmxUtils.getManagedConnections(vHostName);
+ assertEquals(1, managedConnections.size());
+
+ ManagedConnection managedConnection = managedConnections.get(0);
+
+ assertEquals(messagesSent, managedConnection.getTotalMessagesReceived());
+ assertEquals(messagesReceived, managedConnection.getTotalMessagesDelivered());
+
+ assertEquals(dataSent, managedConnection.getTotalDataReceived());
+ assertEquals(dataReceived, managedConnection.getTotalDataDelivered());
+ }
+
+ private void checkVHostStatistics(String vHostName, long messagesSent, long messagesReceived, long dataSent, long dataReceived)
+ {
+ ManagedBroker vhost = _jmxUtils.getManagedBroker(vHostName);
+
+ assertEquals(messagesSent, vhost.getTotalMessagesReceived());
+ assertEquals(messagesReceived, vhost.getTotalMessagesDelivered());
+
+ assertEquals(dataSent, vhost.getTotalDataReceived());
+ assertEquals(dataReceived, vhost.getTotalDataDelivered());
+ }
+
+ private void checkBrokerStatistics(long messagesSent, long messagesReceived, long dataSent, long dataReceived)
+ {
+ ServerInformation broker = _jmxUtils.getServerInformation();
+
+ assertEquals(messagesSent, broker.getTotalMessagesReceived());
+ assertEquals(messagesReceived, broker.getTotalMessagesDelivered());
+
+ assertEquals(dataSent, broker.getTotalDataReceived());
+ assertEquals(dataReceived, broker.getTotalDataDelivered());
+ }
+}
diff --git a/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/UserManagementTest.java b/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/UserManagementTest.java
new file mode 100644
index 0000000000..62b1b554a9
--- /dev/null
+++ b/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/UserManagementTest.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.systest.management.jmx;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.IOException;
+
+import javax.jms.Connection;
+import javax.jms.JMSException;
+
+import org.apache.qpid.management.common.mbeans.UserManagement;
+import org.apache.qpid.server.security.auth.database.PlainPasswordFilePrincipalDatabase;
+import org.apache.qpid.server.security.auth.database.PrincipalDatabase;
+import org.apache.qpid.test.utils.JMXTestUtils;
+import org.apache.qpid.test.utils.QpidBrokerTestCase;
+import org.apache.qpid.tools.security.Passwd;
+
+/**
+ * System test for User Management.
+ *
+ */
+public class UserManagementTest extends QpidBrokerTestCase
+{
+ private static final String TEST_NEWPASSWORD = "newpassword";
+ private static final String TEST_PASSWORD = "password";
+ private JMXTestUtils _jmxUtils;
+ private String _testUserName;
+ private File _passwordFile;
+ private UserManagement _userManagement;
+ private Passwd _passwd;
+
+ public void setUp() throws Exception
+ {
+ _passwd = createPasswordEncodingUtility();
+ _passwordFile = createTemporaryPasswordFileWithJmxAdminUser();
+
+ setConfigurationProperty("security.pd-auth-manager.principal-database.class", getPrincipalDatabaseImplClass().getName());
+ setConfigurationProperty("security.pd-auth-manager.principal-database.attributes.attribute.name", "passwordFile");
+ setConfigurationProperty("security.pd-auth-manager.principal-database.attributes.attribute.value", _passwordFile.getAbsolutePath());
+
+ _jmxUtils = new JMXTestUtils(this);
+ _jmxUtils.setUp();
+
+ super.setUp();
+ _jmxUtils.open();
+
+ _testUserName = getTestName() + System.currentTimeMillis();
+
+ _userManagement = _jmxUtils.getUserManagement();
+ }
+
+
+ public void tearDown() throws Exception
+ {
+ try
+ {
+ if (_jmxUtils != null)
+ {
+ _jmxUtils.close();
+ }
+ }
+ finally
+ {
+ super.tearDown();
+ }
+ }
+
+ public void testCreateUser() throws Exception
+ {
+ final int initialNumberOfUsers = _userManagement.viewUsers().size();
+ assertFileDoesNotContainsPasswordForUser(_testUserName);
+
+ boolean success = _userManagement.createUser(_testUserName, TEST_PASSWORD);
+ assertTrue("Should have been able to create new user " + _testUserName, success);
+ assertEquals("Unexpected number of users after add", initialNumberOfUsers + 1, _userManagement.viewUsers().size());
+
+ assertFileContainsPasswordForUser(_testUserName);
+ }
+
+ public void testJmsLoginForNewUser() throws Exception
+ {
+ assertJmsConnectionFails(_testUserName, TEST_PASSWORD);
+ testCreateUser();
+
+ assertJmsConnectionSucceeds(_testUserName, TEST_PASSWORD);
+ }
+
+ public void testDeleteUser() throws Exception
+ {
+ final int initialNumberOfUsers = _userManagement.viewUsers().size();
+
+ testCreateUser();
+
+ boolean success = _userManagement.deleteUser(_testUserName);
+ assertTrue("Should have been able to delete new user " + _testUserName, success);
+ assertEquals("Unexpected number of users after delete", initialNumberOfUsers, _userManagement.viewUsers().size());
+ assertFileDoesNotContainsPasswordForUser(_testUserName);
+ }
+
+ public void testJmsLoginNotPossibleForDeletedUser() throws Exception
+ {
+ testDeleteUser();
+
+ assertJmsConnectionFails(_testUserName, TEST_PASSWORD);
+ }
+
+ public void testSetPassword() throws Exception
+ {
+ testCreateUser();
+
+ _userManagement.setPassword(_testUserName, TEST_NEWPASSWORD);
+
+ assertFileContainsPasswordForUser(_testUserName);
+ }
+
+ public void testJmsLoginForPasswordChangedUser() throws Exception
+ {
+ testSetPassword();
+
+ assertJmsConnectionSucceeds(_testUserName, TEST_NEWPASSWORD);
+ assertJmsConnectionFails(_testUserName, TEST_PASSWORD);
+ }
+
+ public void testReload() throws Exception
+ {
+ writePasswordFile(_passwordFile, JMXTestUtils.DEFAULT_USERID, JMXTestUtils.DEFAULT_PASSWORD, _testUserName, TEST_PASSWORD);
+
+ assertJmsConnectionFails(_testUserName, TEST_PASSWORD);
+
+ _userManagement.reloadData();
+
+ assertJmsConnectionSucceeds(_testUserName, TEST_PASSWORD);
+ }
+
+ protected Passwd createPasswordEncodingUtility()
+ {
+ return new Passwd()
+ {
+ @Override
+ public String getOutput(String username, String password)
+ {
+ return username + ":" + password;
+ }
+ };
+ }
+
+ protected Class<? extends PrincipalDatabase> getPrincipalDatabaseImplClass()
+ {
+ return PlainPasswordFilePrincipalDatabase.class;
+ }
+
+ private File createTemporaryPasswordFileWithJmxAdminUser() throws Exception
+ {
+ File passwordFile = File.createTempFile("passwd", "pwd");
+ passwordFile.deleteOnExit();
+ writePasswordFile(passwordFile, JMXTestUtils.DEFAULT_USERID, JMXTestUtils.DEFAULT_PASSWORD);
+ return passwordFile;
+ }
+
+ private void writePasswordFile(File passwordFile, String... userNamePasswordPairs) throws Exception
+ {
+ FileWriter writer = null;
+ try
+ {
+ writer = new FileWriter(passwordFile);
+ for (int i = 0; i < userNamePasswordPairs.length; i=i+2)
+ {
+ String username = userNamePasswordPairs[i];
+ String password = userNamePasswordPairs[i+1];
+ writer.append(_passwd.getOutput(username, password) + "\n");
+ }
+ }
+ finally
+ {
+ writer.close();
+ }
+ }
+
+
+ private void assertFileContainsPasswordForUser(String username) throws IOException
+ {
+ assertTrue("Could not find password for user " + username + " within " + _passwordFile, passwordFileContainsUser(username));
+ }
+
+ private void assertFileDoesNotContainsPasswordForUser(String username) throws IOException
+ {
+ assertFalse("Could not find password for user " + username + " within " + _passwordFile, passwordFileContainsUser(username));
+ }
+
+ private boolean passwordFileContainsUser(String username) throws IOException
+ {
+ BufferedReader reader = null;
+ try
+ {
+ reader = new BufferedReader(new FileReader(_passwordFile));
+ String line = reader.readLine();
+ while(line != null)
+ {
+ if (line.startsWith(username))
+ {
+ return true;
+ }
+ line = reader.readLine();
+ }
+
+ return false;
+ }
+ finally
+ {
+ reader.close();
+ }
+ }
+
+ private void assertJmsConnectionSucceeds(String username, String password) throws Exception
+ {
+ Connection connection = getConnection(username, password);
+ assertNotNull(connection);
+ }
+
+ private void assertJmsConnectionFails(String username, String password) throws Exception
+ {
+ try
+ {
+ getConnection(username, password);
+ fail("Exception not thrown");
+ }
+ catch (JMSException e)
+ {
+ // PASS
+ }
+ }
+}
diff --git a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStoreFactory.java b/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/UserManagementWithBase64MD5PasswordsTest.java
index 7e5ef3f94c..84a66232ce 100644
--- a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStoreFactory.java
+++ b/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/UserManagementWithBase64MD5PasswordsTest.java
@@ -15,26 +15,25 @@
* 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;
+package org.apache.qpid.systest.management.jmx;
-import org.apache.qpid.server.store.MessageStore;
-import org.apache.qpid.server.store.MessageStoreFactory;
+import org.apache.qpid.server.security.auth.database.Base64MD5PasswordFilePrincipalDatabase;
+import org.apache.qpid.server.security.auth.database.PrincipalDatabase;
+import org.apache.qpid.tools.security.Passwd;
-public class BDBMessageStoreFactory implements MessageStoreFactory
+public class UserManagementWithBase64MD5PasswordsTest extends UserManagementTest
{
-
@Override
- public MessageStore createMessageStore()
+ protected Passwd createPasswordEncodingUtility()
{
- return new BDBMessageStore();
+ return new Passwd();
}
@Override
- public String getStoreClassName()
+ protected Class<? extends PrincipalDatabase> getPrincipalDatabaseImplClass()
{
- return BDBMessageStore.class.getSimpleName();
+ return Base64MD5PasswordFilePrincipalDatabase.class;
}
}
diff --git a/java/broker/build.xml b/java/broker/build.xml
index 9e8bf12f18..938066728e 100644
--- a/java/broker/build.xml
+++ b/java/broker/build.xml
@@ -33,7 +33,6 @@
<property name="qmf.output.dir" value="${module.precompiled}/org/apache/qpid/qmf/schema"/>
<property name="qmf.output.file" value="BrokerSchema.java"/>
-
<target name="precompile" depends="gen_logging,gen_qmf"/>
<target name="check_qmf_deps">
@@ -83,7 +82,10 @@
<target name="check-bdbstore-requested">
<condition property="bdbstore-requested">
- <contains string="${modules.opt}" substring="bdbstore"/>
+ <or>
+ <contains string="${modules.opt}" substring="bdbstore"/>
+ <istrue value="${optional}"/>
+ </or>
</condition>
</target>
diff --git a/java/broker/etc/broker_example.acl b/java/broker/etc/broker_example.acl
index aae4ee3162..1f32f8463e 100644
--- a/java/broker/etc/broker_example.acl
+++ b/java/broker/etc/broker_example.acl
@@ -24,6 +24,8 @@
#Define a 'messaging-users' group with users 'client' and 'server' in it
GROUP messaging-users client server
+#Define a group for management web console users
+GROUP webadmins webadmin
### MANAGEMENT ####
@@ -74,6 +76,23 @@ ACL ALLOW-LOG server CONSUME QUEUE name="example.RequestQueue"
ACL ALLOW-LOG server BIND EXCHANGE
ACL ALLOW-LOG server PUBLISH EXCHANGE name="amq.direct" routingKey="TempQueue*"
+# ACL for web management console admins
+# All rules below are required for console admin users
+# to perform create/update/delete operations
+ACL ALLOW-LOG webadmins CREATE QUEUE
+ACL ALLOW-LOG webadmins DELETE QUEUE
+ACL ALLOW-LOG webadmins PURGE QUEUE
+ACL ALLOW-LOG webadmins CREATE EXCHANGE
+ACL ALLOW-LOG webadmins DELETE EXCHANGE
+ACL ALLOW-LOG webadmins BIND EXCHANGE
+ACL ALLOW-LOG webadmins UNBIND EXCHANGE
+ACL ALLOW-LOG webadmins UPDATE METHOD
+
+# at the moment only the following UPDATE METHOD rules are supported by web management console
+#ACL ALLOW-LOG webadmins UPDATE METHOD component="VirtualHost.Queue" name="moveMessages"
+#ACL ALLOW-LOG webadmins UPDATE METHOD component="VirtualHost.Queue" name="copyMessages"
+#ACL ALLOW-LOG webadmins UPDATE METHOD component="VirtualHost.Queue" name="deleteMessages"
+
### DEFAULT ###
#Deny all users from performing all operations
diff --git a/java/broker/etc/config.xml b/java/broker/etc/config.xml
index e1aacd43b5..08c7c23d13 100644
--- a/java/broker/etc/config.xml
+++ b/java/broker/etc/config.xml
@@ -57,6 +57,9 @@
<keyStorePath>${conf}/qpid.keystore</keyStorePath>
<keyStorePassword>password</keyStorePassword>
</ssl>
+ <https>
+ <enabled>false</enabled>
+ </https>
</management>
<advanced>
<framesize>65535</framesize>
diff --git a/java/broker/etc/log4j.xml b/java/broker/etc/log4j.xml
index 7dbb1bc87d..b1b31248c1 100644
--- a/java/broker/etc/log4j.xml
+++ b/java/broker/etc/log4j.xml
@@ -87,10 +87,6 @@
</layout>
</appender>
- <category additivity="true" name="org.apache.qpid.server.queue.AMQQueueMBean">
- <priority value="info"/>
- </category>
-
<!-- Provide warnings to standard output -->
<category additivity="true" name="org.apache.qpid">
<priority value="warn"/>
@@ -101,7 +97,16 @@
<level value="info"/>
</logger>
+ <!-- Subscription state may toggle frequently for clients with low prefetch
+ so switch off this operational logging by default-->
+ <logger additivity="true" name="qpid.message.subscription.state">
+ <level value="off"/>
+ </logger>
+ <!-- Enable log messages for the queue notifications -->
+ <logger additivity="true" name="org.apache.qpid.server.queue.NotificationCheck">
+ <level value="info"/>
+ </logger>
<!-- Examples of additional logging settings -->
<!-- Used to generate extra debug. See debug.log4j.xml -->
diff --git a/java/broker/etc/passwd b/java/broker/etc/passwd
index 99f0f05c6a..f0dcb80f25 100644
--- a/java/broker/etc/passwd
+++ b/java/broker/etc/passwd
@@ -21,3 +21,5 @@ client:guest
server:guest
admin:admin
+webadmin:webadmin
+
diff --git a/java/broker/etc/virtualhosts.xml b/java/broker/etc/virtualhosts.xml
index 1f7f91de9a..0f7cc7866f 100644
--- a/java/broker/etc/virtualhosts.xml
+++ b/java/broker/etc/virtualhosts.xml
@@ -25,8 +25,8 @@
<name>localhost</name>
<localhost>
<store>
- <factoryclass>org.apache.qpid.server.store.MemoryMessageStoreFactory</factoryclass>
- <!--<factoryclass>org.apache.qpid.server.store.derby.DerbyMessageStoreFactory</factoryclass>
+ <class>org.apache.qpid.server.store.MemoryMessageStore</class>
+ <!--<class>org.apache.qpid.server.store.derby.DerbyMessageStore</class>
<environment-path>${QPID_WORK}/derbystore</environment-path>-->
</store>
@@ -86,8 +86,8 @@
<name>development</name>
<development>
<store>
- <factoryclass>org.apache.qpid.server.store.MemoryMessageStoreFactory</factoryclass>
- <!--<factoryclass>org.apache.qpid.server.store.derby.DerbyMessageStoreFactory</factoryclass>
+ <class>org.apache.qpid.server.store.MemoryMessageStore</class>
+ <!--<class>org.apache.qpid.server.store.derby.DerbyMessageStore</class>
<environment-path>${QPID_WORK}/derbystore</environment-path>-->
</store>
@@ -125,8 +125,8 @@
<name>test</name>
<test>
<store>
- <factoryclass>org.apache.qpid.server.store.MemoryMessageStoreFactory</factoryclass>
- <!--<factoryclass>org.apache.qpid.server.store.derby.DerbyMessageStoreFactory</factoryclass>
+ <class>org.apache.qpid.server.store.MemoryMessageStore</class>
+ <!--<class>org.apache.qpid.server.store.derby.DerbyMessageStore</class>
<environment-path>${QPID_WORK}/derbystore</environment-path>-->
</store>
diff --git a/java/broker/src/main/java/broker.bnd b/java/broker/src/main/java/broker.bnd
index fa433848a6..4e799a1609 100755
--- a/java/broker/src/main/java/broker.bnd
+++ b/java/broker/src/main/java/broker.bnd
@@ -17,7 +17,7 @@
# under the License.
#
-ver: 0.17.0
+ver: 0.19.0
Bundle-SymbolicName: qpid-broker
Bundle-Version: ${ver}
diff --git a/java/broker/src/main/java/org/apache/log4j/xml/QpidLog4JConfigurator.java b/java/broker/src/main/java/org/apache/log4j/xml/QpidLog4JConfigurator.java
deleted file mode 100644
index dca62f34b4..0000000000
--- a/java/broker/src/main/java/org/apache/log4j/xml/QpidLog4JConfigurator.java
+++ /dev/null
@@ -1,320 +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.log4j.xml;
-
-import org.apache.log4j.Level;
-import org.apache.log4j.Logger;
-import org.xml.sax.ErrorHandler;
-import org.xml.sax.SAXException;
-import org.xml.sax.SAXParseException;
-
-import org.apache.qpid.server.logging.management.LoggingManagementMBean;
-
-import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
-import javax.xml.parsers.ParserConfigurationException;
-import java.io.File;
-import java.io.IOException;
-import java.util.Map;
-import java.util.concurrent.locks.ReentrantLock;
-
-/**
- * Substitute for the Log4J XMLWatchdog (as used by DOMConfigurator.configureAndWatch)
- *
- * Extends the default behaviour with a strict parser check on the XML file before allowing the reconfiguration to proceed,
- * ensuring that any parser error or warning prevents initiation of a configuration update by Log4J, which aborts mid-update
- * upon fatal errors from the parser and proceeds in the event of 'regular' parser errors and warnings, in all cases allowing
- * startup to proceed with whatever half-baked configuration then exists.
- */
-public class QpidLog4JConfigurator
-{
- //lock to protect access to the configuration file
- //shared with LoggingManagementMBean
- public static final ReentrantLock LOCK = new ReentrantLock();
- private static Logger _logger;
- private static DOMConfigurator domConfig = new DOMConfigurator();
-
- private QpidLog4JConfigurator()
- {
- //no instances
- }
-
- public static void configure(String filename) throws IOException, ParserConfigurationException,
- SAXException, IllegalLoggerLevelException
- {
- try
- {
- LOCK.lock();
-
- parseXMLConfigFile(filename);
- checkLoggerLevels(filename);
-
- DOMConfigurator.configure(filename);
-
- if(_logger == null)
- {
- _logger = Logger.getLogger(QpidLog4JConfigurator.class);
- }
- }
- finally
- {
- LOCK.unlock();
- }
- }
-
- public static void configureAndWatch(String filename, long delay) throws IOException, ParserConfigurationException,
- SAXException, IllegalLoggerLevelException
- {
- parseXMLConfigFile(filename);
- checkLoggerLevels(filename);
-
- QpidLog4JXMLWatchdog watchdog = new QpidLog4JXMLWatchdog(filename);
- watchdog.setDelay(delay);
- watchdog.start();
- }
-
- private static void parseXMLConfigFile(String fileName) throws IOException, SAXException,
- ParserConfigurationException
- {
- try
- {
- LOCK.lock();
-
- //check file was specified, exists, and is readable
- if(fileName == null)
- {
- throw new IOException("Provided log4j XML configuration filename was null");
- }
-
- File configFile = new File(fileName);
-
- if (!configFile.exists())
- {
- throw new IOException("The log4j XML configuration file does not exist: " + fileName);
- }
- else if (!configFile.canRead())
- {
- throw new IOException("The log4j XML configuration file is not readable: " + fileName);
- }
-
- //parse it
- DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
- DocumentBuilder docBuilder;
-
- ErrorHandler errHandler = new QpidLog4JSaxErrorHandler();
-
- docFactory.setValidating(true);
- docBuilder = docFactory.newDocumentBuilder();
- docBuilder.setErrorHandler(errHandler);
- docBuilder.setEntityResolver(new Log4jEntityResolver());
- docBuilder.parse(fileName);
- }
- finally
- {
- LOCK.unlock();
- }
- }
-
- public static class QpidLog4JSaxErrorHandler implements ErrorHandler
- {
- public void error(SAXParseException e) throws SAXException
- {
- if(_logger != null)
- {
- _logger.warn(constructMessage("Error parsing XML file", e));
- }
- else
- {
- System.err.println(constructMessage("Error parsing XML file", e));
- }
- }
-
- public void fatalError(SAXParseException e) throws SAXException
- {
- throw new SAXException(constructMessage("Fatal error parsing XML file", e));
- }
-
- public void warning(SAXParseException e) throws SAXException
- {
- if(_logger != null)
- {
- _logger.warn(constructMessage("Warning parsing XML file", e));
- }
- else
- {
- System.err.println(constructMessage("Warning parsing XML file", e));
- }
- }
-
- private static String constructMessage(final String msg, final SAXParseException ex)
- {
- return msg + ": Line " + ex.getLineNumber()+" column " +ex.getColumnNumber() + ": " + ex.getMessage();
- }
- }
-
- private static class QpidLog4JXMLWatchdog extends XMLWatchdog
- {
- public QpidLog4JXMLWatchdog(String filename)
- {
- super(filename);
- }
-
- public void doOnChange()
- {
- try
- {
- LOCK.lock();
-
- try
- {
- parseXMLConfigFile(filename);
- }
- catch (Exception e)
- {
- //logger will be instantiated following first configuration success, which has been pre-validated
- //and so the null check should never actually be required.
- if(_logger != null)
- {
- _logger.warn("Parsing the log4j XML configuration file generated errors/warnings. " +
- "The new configuration was not applied. Correct the issues to prompt " +
- "another update attempt: " + e.getMessage());
- }
- return;
- }
-
- try
- {
- checkLoggerLevels(filename);
- }
- catch (Exception e)
- {
- //logger will be instantiated following first configuration success, which has been pre-validated
- //and so the null check should never actually be required.
- if(_logger != null)
- {
- _logger.warn("Errors were found when validating the logger level values in the " +
- "log4j XML configuration file. The new configuration was not applied. " +
- "Correct the issues to prompt another update attempt: " + e.getMessage());
- }
- return;
- }
-
- //everything checked was ok, let the normal update process proceed
- super.doOnChange();
-
- //a configuration has now been applied, enable logging for future attempts
- if(_logger == null)
- {
- _logger = Logger.getLogger(QpidLog4JConfigurator.class);
- }
-
- _logger.info("Applied log4j configuration from: " + filename);
- }
- finally
- {
- LOCK.unlock();
- }
-
- }
- }
-
- protected static void checkLoggerLevels(String filename) throws IllegalLoggerLevelException, IOException
- {
- //check that the logger levels specified in the XML are actually valid
-
- try
- {
- LOCK.lock();
-
- //get the Logger levels to check
- Map<String, String> loggersLevels;
- loggersLevels = LoggingManagementMBean.retrieveConfigFileLoggersLevels(filename);
- //add the RootLogger to the list too
- String rootLoggerlevelString = LoggingManagementMBean.retrieveConfigFileRootLoggerLevel(filename);
- loggersLevels.put("Root", rootLoggerlevelString);
-
-
- for (Map.Entry<String, String> entry : loggersLevels.entrySet())
- {
- String loggerName = entry.getKey();
- String levelString = entry.getValue();
-
- //let log4j replace any properties in the string
- String log4jConfiguredString = domConfig.subst(levelString);
-
- if(log4jConfiguredString.equals("") && ! log4jConfiguredString.equals(levelString))
- {
- //log4j has returned an empty string but this isnt what we gave it.
- //There may have been an undefined property. Unlike an incorrect
- //literal value, we will allow this case to proceed, but warn users.
-
- if(_logger != null)
- {
- _logger.warn("Unable to detect Level value from '" + levelString
- +"' for logger '" + loggerName + "', Log4J will default this to DEBUG");
- }
- else
- {
- System.err.println("Unable to detect Level value from '" + levelString
- +"' for logger " + loggerName + ", Log4J will default this to DEBUG");
- }
-
- continue;
- }
-
- checkLevel(loggerName,log4jConfiguredString);
- }
- }
- finally
- {
- LOCK.unlock();
- }
- }
-
- private static void checkLevel(String loggerName, String levelString) throws IllegalLoggerLevelException
- {
- if("null".equalsIgnoreCase(levelString) || "inherited".equalsIgnoreCase(levelString))
- {
- //the string "null" signals to inherit from a parent logger
- return;
- }
-
- Level level = Level.toLevel(levelString);
-
- //above Level.toLevel call returns a DEBUG Level if the request fails. Check the result.
- if (level.equals(Level.DEBUG) && !(levelString.equalsIgnoreCase("debug")))
- {
- //received DEBUG but we did not ask for it, the Level request failed.
- throw new IllegalLoggerLevelException("Level '" + levelString + "' specified for Logger '" + loggerName + "' is invalid");
- }
- }
-
- public static class IllegalLoggerLevelException extends Exception
- {
- private static final long serialVersionUID = 1L;
-
- public IllegalLoggerLevelException(String msg)
- {
- super(msg);
- }
- }
-}
-
diff --git a/java/broker/src/main/java/org/apache/qpid/qmf/ManagementExchange.java b/java/broker/src/main/java/org/apache/qpid/qmf/ManagementExchange.java
index 034a4ae53c..27ab580642 100644
--- a/java/broker/src/main/java/org/apache/qpid/qmf/ManagementExchange.java
+++ b/java/broker/src/main/java/org/apache/qpid/qmf/ManagementExchange.java
@@ -70,6 +70,7 @@ public class ManagementExchange implements Exchange, QMFService.Listener
private final Set<Binding> _bindingSet = new CopyOnWriteArraySet<Binding>();
private UUID _id;
+ private UUID _qmfId;
private static final String AGENT_BANK = "0";
private int _bindingCountHigh;
@@ -84,7 +85,7 @@ public class ManagementExchange implements Exchange, QMFService.Listener
private class ManagementQueue implements BaseQueue
{
- private final UUID QUEUE_ID = UUIDGenerator.generateUUID();
+ private final UUID QUEUE_ID = UUIDGenerator.generateRandomUUID();
private final String NAME_AS_STRING = "##__mgmt_pseudo_queue__##" + QUEUE_ID.toString();
private final AMQShortString NAME_AS_SHORT_STRING = new AMQShortString(NAME_AS_STRING);
@@ -196,6 +197,7 @@ public class ManagementExchange implements Exchange, QMFService.Listener
_virtualHost = host;
_id = id;
_virtualHost.scheduleHouseKeepingTask(_virtualHost.getBroker().getManagementPublishInterval(), new UpdateTask(_virtualHost));
+ _qmfId = getConfigStore().createId();
getConfigStore().addConfiguredObject(this);
getQMFService().addListener(this);
}
@@ -205,6 +207,12 @@ public class ManagementExchange implements Exchange, QMFService.Listener
return _id;
}
+ @Override
+ public UUID getQMFId()
+ {
+ return _qmfId;
+ }
+
public ExchangeConfigType getConfigType()
{
return ExchangeConfigType.getInstance();
@@ -540,6 +548,11 @@ public class ManagementExchange implements Exchange, QMFService.Listener
return getMsgReceives();
}
+ public long getMsgDrops()
+ {
+ return 0l;
+ }
+
public long getByteReceives()
{
return _bytesReceived.get();
@@ -550,6 +563,11 @@ public class ManagementExchange implements Exchange, QMFService.Listener
return getByteReceives();
}
+ public long getByteDrops()
+ {
+ return 0l;
+ }
+
public long getCreateTime()
{
return _createTime;
diff --git a/java/broker/src/main/java/org/apache/qpid/qmf/QMFMessage.java b/java/broker/src/main/java/org/apache/qpid/qmf/QMFMessage.java
index 787cede2b7..1b173c7e11 100644
--- a/java/broker/src/main/java/org/apache/qpid/qmf/QMFMessage.java
+++ b/java/broker/src/main/java/org/apache/qpid/qmf/QMFMessage.java
@@ -21,6 +21,8 @@
package org.apache.qpid.qmf;
+import java.util.Collection;
+import java.util.Collections;
import org.apache.commons.lang.NotImplementedException;
import org.apache.qpid.framing.AMQShortString;
@@ -111,6 +113,16 @@ public class QMFMessage implements ServerMessage, InboundMessage, AMQMessageHead
return 0;
}
+ public String getUserId()
+ {
+ return null;
+ }
+
+ public String getAppId()
+ {
+ return null;
+ }
+
public String getMessageId()
{
return null;
@@ -166,6 +178,12 @@ public class QMFMessage implements ServerMessage, InboundMessage, AMQMessageHead
return false;
}
+ @Override
+ public Collection<String> getHeaderNames()
+ {
+ return Collections.EMPTY_SET;
+ }
+
public boolean containsHeader(String name)
{
return false;
diff --git a/java/broker/src/main/java/org/apache/qpid/qmf/QMFObject.java b/java/broker/src/main/java/org/apache/qpid/qmf/QMFObject.java
index 631bd3c7cc..c3604dca44 100644
--- a/java/broker/src/main/java/org/apache/qpid/qmf/QMFObject.java
+++ b/java/broker/src/main/java/org/apache/qpid/qmf/QMFObject.java
@@ -28,7 +28,7 @@ public abstract class QMFObject<C extends QMFClass, D extends QMFObject.Delegate
public interface Delegate
{
- UUID getId();
+ UUID getQMFId();
long getCreateTime();
}
@@ -49,7 +49,7 @@ public abstract class QMFObject<C extends QMFClass, D extends QMFObject.Delegate
public final UUID getId()
{
- return _delegate.getId();
+ return _delegate.getQMFId();
}
public final long getCreateTime()
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 900b722886..d713976919 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
@@ -436,7 +436,7 @@ public class QMFService implements ConfigStore.ConfigEventListener, Closeable
QMFObject qmfObject = classObjects.remove(object);
if(qmfObject != null)
{
- _managedObjectsById.get(qmfClass).remove(object.getId());
+ _managedObjectsById.get(qmfClass).remove(object.getQMFId());
objectRemoved(qmfObject);
}
}
@@ -468,7 +468,7 @@ public class QMFService implements ConfigStore.ConfigEventListener, Closeable
}
}
- classObjectsById.put(object.getId(),qmfObject);
+ classObjectsById.put(object.getQMFId(),qmfObject);
if(classObjects.putIfAbsent(object, qmfObject) == null)
{
@@ -570,7 +570,7 @@ public class QMFService implements ConfigStore.ConfigEventListener, Closeable
public UUID getSystemId()
{
- return _obj.getId();
+ return _obj.getQMFId();
}
public String getOsName()
@@ -598,9 +598,9 @@ public class QMFService implements ConfigStore.ConfigEventListener, Closeable
return _obj.getOSArchitecture();
}
- public UUID getId()
+ public UUID getQMFId()
{
- return _obj.getId();
+ return _obj.getQMFId();
}
public long getCreateTime()
@@ -964,9 +964,9 @@ public class QMFService implements ConfigStore.ConfigEventListener, Closeable
return factory.createResponseCommand(CompletionCode.NOT_IMPLEMENTED);
}
- public UUID getId()
+ public UUID getQMFId()
{
- return _obj.getId();
+ return _obj.getQMFId();
}
public long getCreateTime()
@@ -1004,9 +1004,9 @@ public class QMFService implements ConfigStore.ConfigEventListener, Closeable
return _obj.getFederationTag();
}
- public UUID getId()
+ public UUID getQMFId()
{
- return _obj.getId();
+ return _obj.getQMFId();
}
public long getCreateTime()
@@ -1135,9 +1135,9 @@ public class QMFService implements ConfigStore.ConfigEventListener, Closeable
return _obj.getByteRoutes();
}
- public UUID getId()
+ public UUID getQMFId()
{
- return _obj.getId();
+ return _obj.getQMFId();
}
public long getCreateTime()
@@ -1470,9 +1470,9 @@ public class QMFService implements ConfigStore.ConfigEventListener, Closeable
return _obj.getArguments();
}
- public UUID getId()
+ public UUID getQMFId()
{
- return _obj.getId();
+ return _obj.getQMFId();
}
public long getCreateTime()
@@ -1526,9 +1526,9 @@ public class QMFService implements ConfigStore.ConfigEventListener, Closeable
return _obj.getMatches();
}
- public UUID getId()
+ public UUID getQMFId()
{
- return _obj.getId();
+ return _obj.getQMFId();
}
public long getCreateTime()
@@ -1647,9 +1647,9 @@ public class QMFService implements ConfigStore.ConfigEventListener, Closeable
return factory.createResponseCommand();
}
- public UUID getId()
+ public UUID getQMFId()
{
- return _obj.getId();
+ return _obj.getQMFId();
}
public long getCreateTime()
@@ -1741,6 +1741,12 @@ public class QMFService implements ConfigStore.ConfigEventListener, Closeable
return 0l;
}
+ public Long getUnackedMessages()
+ {
+ // TODO
+ return 0l;
+ }
+
public Long getTxnStarts()
{
return _obj.getTxnStarts();
@@ -1799,9 +1805,9 @@ public class QMFService implements ConfigStore.ConfigEventListener, Closeable
return factory.createResponseCommand();
}
- public UUID getId()
+ public UUID getQMFId()
{
- return _obj.getId();
+ return _obj.getQMFId();
}
public long getCreateTime()
@@ -1870,9 +1876,9 @@ public class QMFService implements ConfigStore.ConfigEventListener, Closeable
return _obj.getDelivered();
}
- public UUID getId()
+ public UUID getQMFId()
{
- return _obj.getId();
+ return _obj.getQMFId();
}
public long getCreateTime()
@@ -1955,14 +1961,20 @@ public class QMFService implements ConfigStore.ConfigEventListener, Closeable
return _obj.getAckBatching();
}
+ /* support TBD */
+ public String getName()
+ {
+ return null;
+ }
+
public BrokerSchema.BridgeClass.CloseMethodResponseCommand close(final BrokerSchema.BridgeClass.CloseMethodResponseCommandFactory factory)
{
return null;
}
- public UUID getId()
+ public UUID getQMFId()
{
- return _obj.getId();
+ return _obj.getQMFId();
}
public long getCreateTime()
@@ -2020,6 +2032,18 @@ public class QMFService implements ConfigStore.ConfigEventListener, Closeable
return _obj.getLastError();
}
+ /* support TBD */
+ public String getName()
+ {
+ return null;
+ }
+
+ /* support TBD */
+ public BrokerSchema.ConnectionObject getConnectionRef()
+ {
+ return (BrokerSchema.ConnectionObject) null;
+ }
+
public BrokerSchema.LinkClass.CloseMethodResponseCommand close(final BrokerSchema.LinkClass.CloseMethodResponseCommandFactory factory)
{
_obj.close();
@@ -2042,9 +2066,9 @@ public class QMFService implements ConfigStore.ConfigEventListener, Closeable
return factory.createResponseCommand();
}
- public UUID getId()
+ public UUID getQMFId()
{
- return _obj.getId();
+ return _obj.getQMFId();
}
public long getCreateTime()
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
deleted file mode 100644
index 0f32b98aa8..0000000000
--- a/java/broker/src/main/java/org/apache/qpid/server/AMQBrokerManagerMBean.java
+++ /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.
- */
-package org.apache.qpid.server;
-
-import org.apache.qpid.AMQException;
-import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpid.framing.FieldTable;
-import org.apache.qpid.management.common.mbeans.ManagedBroker;
-import org.apache.qpid.management.common.mbeans.ManagedQueue;
-import org.apache.qpid.management.common.mbeans.annotations.MBeanConstructor;
-import org.apache.qpid.management.common.mbeans.annotations.MBeanDescription;
-import org.apache.qpid.server.exchange.Exchange;
-import org.apache.qpid.server.exchange.ExchangeFactory;
-import org.apache.qpid.server.exchange.ExchangeRegistry;
-import org.apache.qpid.server.exchange.ExchangeType;
-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 org.apache.qpid.server.model.UUIDGenerator;
-import org.apache.qpid.server.queue.AMQQueue;
-import org.apache.qpid.server.queue.AMQQueueFactory;
-import org.apache.qpid.server.queue.AMQQueueMBean;
-import org.apache.qpid.server.queue.QueueRegistry;
-import org.apache.qpid.server.virtualhost.VirtualHost;
-import org.apache.qpid.server.virtualhost.VirtualHostImpl;
-
-import javax.management.JMException;
-import javax.management.MBeanException;
-import javax.management.MalformedObjectNameException;
-import javax.management.ObjectName;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.UUID;
-
-/**
- * This MBean implements the broker management interface and exposes the
- * Broker level management features like creating and deleting exchanges and queue.
- */
-@MBeanDescription("This MBean exposes the broker level management features")
-public class AMQBrokerManagerMBean extends AMQManagedObject implements ManagedBroker
-{
- private final QueueRegistry _queueRegistry;
- private final ExchangeRegistry _exchangeRegistry;
- private final ExchangeFactory _exchangeFactory;
-
- private final VirtualHostImpl.VirtualHostMBean _virtualHostMBean;
-
- @MBeanConstructor("Creates the Broker Manager MBean")
- public AMQBrokerManagerMBean(VirtualHostImpl.VirtualHostMBean virtualHostMBean) throws JMException
- {
- super(ManagedBroker.class, ManagedBroker.TYPE);
-
- _virtualHostMBean = virtualHostMBean;
- VirtualHost virtualHost = virtualHostMBean.getVirtualHost();
-
- _queueRegistry = virtualHost.getQueueRegistry();
- _exchangeRegistry = virtualHost.getExchangeRegistry();
- _exchangeFactory = virtualHost.getExchangeFactory();
- }
-
- public String getObjectInstanceName()
- {
- return _virtualHostMBean.getVirtualHost().getName();
- }
-
- /**
- * Returns an array of the exchange types available for creation.
- * @since Qpid JMX API 1.3
- * @throws IOException
- */
- public String[] getExchangeTypes() throws IOException
- {
- ArrayList<String> exchangeTypes = new ArrayList<String>();
- for(ExchangeType<? extends Exchange> ex : _exchangeFactory.getPublicCreatableTypes())
- {
- exchangeTypes.add(ex.getName().toString());
- }
-
- return exchangeTypes.toArray(new String[0]);
- }
-
- /**
- * Returns a list containing the names of the attributes available for the Queue mbeans.
- * @since Qpid JMX API 1.3
- * @throws IOException
- */
- public List<String> retrieveQueueAttributeNames() throws IOException
- {
- return ManagedQueue.QUEUE_ATTRIBUTES;
- }
-
- /**
- * Returns a List of Object Lists containing the requested attribute values (in the same sequence requested) for each queue in the virtualhost.
- * If a particular attribute cant be found or raises an mbean/reflection exception whilst being gathered its value is substituted with the String "-".
- * @since Qpid JMX API 1.3
- * @throws IOException
- */
- public List<List<Object>> retrieveQueueAttributeValues(String[] attributes) throws IOException
- {
- if(_queueRegistry.getQueues().size() == 0)
- {
- return new ArrayList<List<Object>>();
- }
-
- List<List<Object>> queueAttributesList = new ArrayList<List<Object>>(_queueRegistry.getQueues().size());
-
- int attributesLength = attributes.length;
-
- for(AMQQueue queue : _queueRegistry.getQueues())
- {
- AMQQueueMBean mbean = (AMQQueueMBean) queue.getManagedObject();
-
- if(mbean == null)
- {
- continue;
- }
-
- List<Object> attributeValues = new ArrayList<Object>(attributesLength);
-
- for(int i=0; i < attributesLength; i++)
- {
- try
- {
- attributeValues.add(mbean.getAttribute(attributes[i]));
- }
- catch (Exception e)
- {
- attributeValues.add("-");
- }
- }
-
- queueAttributesList.add(attributeValues);
- }
-
- return queueAttributesList;
- }
-
- /**
- * Creates new exchange and registers it with the registry.
- *
- * @param exchangeName
- * @param type
- * @param durable
- * @throws JMException
- * @throws MBeanException
- */
- public void createNewExchange(String exchangeName, String type, boolean durable) throws JMException, MBeanException
- {
- CurrentActor.set(new ManagementActor(getLogActor().getRootMessageLogger()));
- try
- {
- synchronized (_exchangeRegistry)
- {
- Exchange exchange = _exchangeRegistry.getExchange(new AMQShortString(exchangeName));
- if (exchange == null)
- {
- exchange = _exchangeFactory.createExchange(new AMQShortString(exchangeName),
- new AMQShortString(type), durable, false, 0);
- _exchangeRegistry.registerExchange(exchange);
- if (durable)
- {
- getVirtualHost().getMessageStore().createExchange(exchange);
- }
- }
- else
- {
- throw new JMException("The exchange \"" + exchangeName + "\" already exists.");
- }
- }
- }
- catch (AMQException ex)
- {
- JMException jme = new JMException(ex.toString());
- throw new MBeanException(jme, "Error in creating exchange " + exchangeName);
- }
- finally
- {
- CurrentActor.remove();
- }
- }
-
- /**
- * Unregisters the exchange from registry.
- *
- * @param exchangeName
- * @throws JMException
- * @throws MBeanException
- */
- public void unregisterExchange(String exchangeName) throws JMException, MBeanException
- {
- // TODO
- // Check if the exchange is in use.
-
- // Check if there are queue-bindings with the exchange and unregister
- // when there are no bindings.
- CurrentActor.set(new ManagementActor(getLogActor().getRootMessageLogger()));
- try
- {
- _exchangeRegistry.unregisterExchange(new AMQShortString(exchangeName), false);
- }
- catch (AMQException ex)
- {
- JMException jme = new JMException(ex.toString());
- throw new MBeanException(jme, "Error in unregistering exchange " + exchangeName);
- }
- finally
- {
- CurrentActor.remove();
- }
- }
-
- /**
- * Creates a new queue and registers it with the registry and puts it
- * in persistance storage if durable queue.
- *
- * @param queueName
- * @param durable
- * @param owner
- * @throws JMException
- * @throws MBeanException
- */
- public void createNewQueue(String queueName, String owner, boolean durable) throws JMException, MBeanException
- {
- createNewQueue(queueName, owner, durable, null);
- }
-
- public void createNewQueue(String queueName, String owner, boolean durable, Map<String,Object> arguments) throws JMException
- {
- final AMQShortString queueNameAsAMQShortString = new AMQShortString(queueName);
- synchronized (_queueRegistry)
- {
- AMQQueue queue = _queueRegistry.getQueue(queueNameAsAMQShortString);
- if (queue != null)
- {
- throw new JMException("The queue \"" + queueName + "\" already exists.");
- }
-
- CurrentActor.set(new ManagementActor(getLogActor().getRootMessageLogger()));
- try
- {
- FieldTable args = null;
- if(arguments != null)
- {
- args = FieldTable.convertToFieldTable(arguments);
- }
- final VirtualHost virtualHost = getVirtualHost();
-
- queue = AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateUUID(), queueName, durable, owner,
- false, false, getVirtualHost(), arguments);
- if (queue.isDurable() && !queue.isAutoDelete())
- {
- getVirtualHost().getMessageStore().createQueue(queue, args);
- }
-
- virtualHost.getBindingFactory().addBinding(queueName, queue, _exchangeRegistry.getDefaultExchange(), null);
- }
- catch (AMQException ex)
- {
- JMException jme = new JMException(ex.toString());
- throw new MBeanException(jme, "Error in creating queue " + queueName);
- }
- finally
- {
- CurrentActor.remove();
- }
- }
- }
-
- private VirtualHost getVirtualHost()
- {
- return _virtualHostMBean.getVirtualHost();
- }
-
- /**
- * Deletes the queue from queue registry and persistant storage.
- *
- * @param queueName
- * @throws JMException
- * @throws MBeanException
- */
- public void deleteQueue(String queueName) throws JMException, MBeanException
- {
- AMQQueue queue = _queueRegistry.getQueue(new AMQShortString(queueName));
- if (queue == null)
- {
- throw new JMException("The Queue " + queueName + " is not a registered queue.");
- }
-
- CurrentActor.set(new ManagementActor(getLogActor().getRootMessageLogger()));
- try
- {
- queue.delete();
- if (queue.isDurable())
- {
- getVirtualHost().getMessageStore().removeQueue(queue);
- }
- }
- catch (AMQException ex)
- {
- JMException jme = new JMException(ex.toString());
- throw new MBeanException(jme, "Error in deleting queue " + queueName);
- }
- finally
- {
- CurrentActor.remove();
- }
- }
-
- @Override
- public ManagedObject getParentObject()
- {
- return _virtualHostMBean;
- }
-
- // This will have a single instance for a virtual host, so not having the name property in the ObjectName
- @Override
- public ObjectName getObjectName() throws MalformedObjectNameException
- {
- 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 8198cec821..e197dddfde 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
@@ -23,7 +23,9 @@ package org.apache.qpid.server;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.Collections;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
@@ -32,9 +34,9 @@ import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.UUID;
-import java.util.concurrent.ConcurrentSkipListSet;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;
+import java.util.concurrent.locks.Lock;
import org.apache.log4j.Logger;
import org.apache.qpid.AMQException;
@@ -89,7 +91,6 @@ import org.apache.qpid.server.subscription.ClientDeliveryMethod;
import org.apache.qpid.server.subscription.RecordDeliveryMethod;
import org.apache.qpid.server.subscription.Subscription;
import org.apache.qpid.server.subscription.SubscriptionFactoryImpl;
-import org.apache.qpid.server.subscription.SubscriptionImpl;
import org.apache.qpid.server.txn.AsyncAutoCommitTransaction;
import org.apache.qpid.server.txn.LocalTransaction;
import org.apache.qpid.server.txn.ServerTransaction;
@@ -137,11 +138,9 @@ public class AMQChannel implements SessionConfig, AMQSessionModel, AsyncAutoComm
private final LinkedList<AsyncCommand> _unfinishedCommandsQueue = new LinkedList<AsyncCommand>();
- private static final int UNFINISHED_COMMAND_QUEUE_THRESHOLD = 500;
-
private UnacknowledgedMessageMap _unacknowledgedMessageMap = new UnacknowledgedMessageMapImpl(DEFAULT_PREFETCH);
- // Set of messages being acknoweledged in the current transaction
+ // Set of messages being acknowledged in the current transaction
private SortedSet<QueueEntry> _acknowledgedMessages = new TreeSet<QueueEntry>();
private final AtomicBoolean _suspended = new AtomicBoolean(false);
@@ -157,7 +156,7 @@ public class AMQChannel implements SessionConfig, AMQSessionModel, AsyncAutoComm
private final AMQProtocolSession _session;
private AtomicBoolean _closing = new AtomicBoolean(false);
- private final Set<AMQQueue> _blockingQueues = new ConcurrentSkipListSet<AMQQueue>();
+ private final Set<Object> _blockingEntities = Collections.synchronizedSet(new HashSet<Object>());
private final AtomicBoolean _blocking = new AtomicBoolean(false);
@@ -170,11 +169,13 @@ public class AMQChannel implements SessionConfig, AMQSessionModel, AsyncAutoComm
private List<QueueEntry> _resendList = new ArrayList<QueueEntry>();
private static final
AMQShortString IMMEDIATE_DELIVERY_REPLY_TEXT = new AMQShortString("Immediate delivery is not possible.");
- private final UUID _id;
+ private final UUID _qmfId;
private long _createTime = System.currentTimeMillis();
private final ClientDeliveryMethod _clientDeliveryMethod;
+ private final TransactionTimeoutHelper _transactionTimeoutHelper;
+
public AMQChannel(AMQProtocolSession session, int channelId, MessageStore messageStore)
throws AMQException
{
@@ -183,7 +184,7 @@ public class AMQChannel implements SessionConfig, AMQSessionModel, AsyncAutoComm
_actor = new AMQPChannelActor(this, session.getLogActor().getRootMessageLogger());
_logSubject = new ChannelLogSubject(this);
- _id = getConfigStore().createId();
+ _qmfId = getConfigStore().createId();
_actor.message(ChannelMessages.CREATE());
getConfigStore().addConfiguredObject(this);
@@ -194,6 +195,8 @@ public class AMQChannel implements SessionConfig, AMQSessionModel, AsyncAutoComm
_transaction = new AsyncAutoCommitTransaction(_messageStore, this);
_clientDeliveryMethod = session.createDeliveryMethod(_channelId);
+
+ _transactionTimeoutHelper = new TransactionTimeoutHelper(_logSubject);
}
public ConfigStore getConfigStore()
@@ -264,6 +267,11 @@ public class AMQChannel implements SessionConfig, AMQSessionModel, AsyncAutoComm
return _txnCount.get();
}
+ public Long getTxnStart()
+ {
+ return _txnStarts.get();
+ }
+
public int getChannelId()
{
return _channelId;
@@ -441,7 +449,7 @@ public class AMQChannel implements SessionConfig, AMQSessionModel, AsyncAutoComm
* @param acks Are acks enabled for this subscriber
* @param filters Filters to apply to this subscriber
*
- * @param noLocal Flag stopping own messages being receivied.
+ * @param noLocal Flag stopping own messages being received.
* @param exclusive Flag requesting exclusive access to the queue
* @return the consumer tag. This is returned to the subscriber and used in subsequent unsubscribe requests
*
@@ -948,9 +956,11 @@ public class AMQChannel implements SessionConfig, AMQSessionModel, AsyncAutoComm
public void commit() throws AMQException
{
- commit(null);
+ commit(null, false);
}
- public void commit(Runnable immediateAction) throws AMQException
+
+
+ public void commit(final Runnable immediateAction, boolean async) throws AMQException
{
if (!isTransactional())
@@ -958,11 +968,29 @@ public class AMQChannel implements SessionConfig, AMQSessionModel, AsyncAutoComm
throw new AMQException("Fatal error: commit called on non-transactional channel");
}
- _transaction.commit(immediateAction);
+ if(async && _transaction instanceof LocalTransaction)
+ {
+
+ ((LocalTransaction)_transaction).commitAsync(new Runnable()
+ {
+ @Override
+ public void run()
+ {
+ immediateAction.run();
+ _txnCommits.incrementAndGet();
+ _txnStarts.incrementAndGet();
+ decrementOutstandingTxnsIfNecessary();
+ }
+ });
+ }
+ else
+ {
+ _transaction.commit(immediateAction);
- _txnCommits.incrementAndGet();
- _txnStarts.incrementAndGet();
- decrementOutstandingTxnsIfNecessary();
+ _txnCommits.incrementAndGet();
+ _txnStarts.incrementAndGet();
+ decrementOutstandingTxnsIfNecessary();
+ }
}
public void rollback() throws AMQException
@@ -1357,9 +1385,34 @@ public class AMQChannel implements SessionConfig, AMQSessionModel, AsyncAutoComm
return _actor;
}
- public void block(AMQQueue queue)
+ public synchronized void block()
{
- if(_blockingQueues.add(queue))
+ if(_blockingEntities.add(this))
+ {
+ if(_blocking.compareAndSet(false,true))
+ {
+ _actor.message(_logSubject, ChannelMessages.FLOW_ENFORCED("** All Queues **"));
+ flow(false);
+ }
+ }
+ }
+
+ public synchronized void unblock()
+ {
+ if(_blockingEntities.remove(this))
+ {
+ if(_blockingEntities.isEmpty() && _blocking.compareAndSet(true,false))
+ {
+ _actor.message(_logSubject, ChannelMessages.FLOW_REMOVED());
+
+ flow(true);
+ }
+ }
+ }
+
+ public synchronized void block(AMQQueue queue)
+ {
+ if(_blockingEntities.add(queue))
{
if(_blocking.compareAndSet(false,true))
@@ -1370,11 +1423,11 @@ public class AMQChannel implements SessionConfig, AMQSessionModel, AsyncAutoComm
}
}
- public void unblock(AMQQueue queue)
+ public synchronized void unblock(AMQQueue queue)
{
- if(_blockingQueues.remove(queue))
+ if(_blockingEntities.remove(queue))
{
- if(_blocking.compareAndSet(true,false) && !isClosing())
+ if(_blockingEntities.isEmpty() && _blocking.compareAndSet(true,false) && !isClosing())
{
_actor.message(_logSubject, ChannelMessages.FLOW_REMOVED());
@@ -1393,6 +1446,11 @@ public class AMQChannel implements SessionConfig, AMQSessionModel, AsyncAutoComm
return false;
}
+ public int getUnacknowledgedMessageCount()
+ {
+ return getUnacknowledgedMessageMap().size();
+ }
+
private void flow(boolean flow)
{
MethodRegistry methodRegistry = _session.getMethodRegistry();
@@ -1400,6 +1458,7 @@ public class AMQChannel implements SessionConfig, AMQSessionModel, AsyncAutoComm
_session.writeFrame(responseBody.generateFrame(_channelId));
}
+ @Override
public boolean getBlocking()
{
return _blocking.get();
@@ -1456,9 +1515,10 @@ public class AMQChannel implements SessionConfig, AMQSessionModel, AsyncAutoComm
return false;
}
- public UUID getId()
+ @Override
+ public UUID getQMFId()
{
- return _id;
+ return _qmfId;
}
public String getSessionName()
@@ -1484,30 +1544,42 @@ public class AMQChannel implements SessionConfig, AMQSessionModel, AsyncAutoComm
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)
+ _transactionTimeoutHelper.logIfNecessary(idleTime, idleWarn, ChannelMessages.IDLE_TXN(idleTime),
+ TransactionTimeoutHelper.IDLE_TRANSACTION_ALERT);
+ if (_transactionTimeoutHelper.isTimedOut(idleTime, idleClose))
{
- CurrentActor.get().message(_logSubject, ChannelMessages.OPEN_TXN(openTime));
- _logger.warn("OPEN TRANSACTION ALERT " + _logSubject.toString() + " " + openTime + " ms");
+ closeConnection("Idle transaction timed out");
+ return;
}
- // Close connection for idle or open transactions that have timed out
- if (idleClose > 0L && idleTime > idleClose)
+ _transactionTimeoutHelper.logIfNecessary(openTime, openWarn, ChannelMessages.OPEN_TXN(openTime),
+ TransactionTimeoutHelper.OPEN_TRANSACTION_ALERT);
+ if (_transactionTimeoutHelper.isTimedOut(openTime, openClose))
{
- 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");
+ closeConnection("Open transaction timed out");
+ return;
}
}
}
+ /**
+ * Typically called from the HouseKeepingThread instead of the main receiver thread,
+ * therefore uses a lock to close the connection in a thread-safe manner.
+ */
+ private void closeConnection(String reason) throws AMQException
+ {
+ Lock receivedLock = _session.getReceivedLock();
+ receivedLock.lock();
+ try
+ {
+ _session.close(AMQConstant.RESOURCE_ERROR, reason);
+ }
+ finally
+ {
+ receivedLock.unlock();
+ }
+ }
+
public void deadLetter(long deliveryTag) throws AMQException
{
final UnacknowledgedMessageMap unackedMap = getUnacknowledgedMessageMap();
@@ -1563,23 +1635,6 @@ public class AMQChannel implements SessionConfig, AMQSessionModel, AsyncAutoComm
_unfinishedCommandsQueue.add(new AsyncCommand(future, action));
}
- public void completeAsyncCommands()
- {
- AsyncCommand cmd;
- while((cmd = _unfinishedCommandsQueue.peek()) != null && cmd.isReadyForCompletion())
- {
- cmd.complete();
- _unfinishedCommandsQueue.poll();
- }
- while(_unfinishedCommandsQueue.size() > UNFINISHED_COMMAND_QUEUE_THRESHOLD)
- {
- cmd = _unfinishedCommandsQueue.poll();
- cmd.awaitReadyForCompletion();
- cmd.complete();
- }
- }
-
-
public void sync()
{
AsyncCommand cmd;
@@ -1588,6 +1643,10 @@ public class AMQChannel implements SessionConfig, AMQSessionModel, AsyncAutoComm
cmd.awaitReadyForCompletion();
cmd.complete();
}
+ if(_transaction instanceof LocalTransaction)
+ {
+ ((LocalTransaction)_transaction).sync();
+ }
}
private static class AsyncCommand
@@ -1624,6 +1683,12 @@ public class AMQChannel implements SessionConfig, AMQSessionModel, AsyncAutoComm
public int compareTo(AMQSessionModel session)
{
- return getId().compareTo(session.getId());
+ return getQMFId().compareTo(session.getQMFId());
+ }
+
+ @Override
+ public int getConsumerCount()
+ {
+ return _tag2SubscriptionMap.size();
}
}
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
index 5004d320c2..d58a0d5bb4 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/Broker.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/Broker.java
@@ -20,19 +20,22 @@
*/
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.*;
+import javax.net.ssl.SSLContext;
import org.apache.log4j.Logger;
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.log4j.LoggingFacade;
import org.apache.qpid.server.logging.messages.BrokerMessages;
import org.apache.qpid.server.protocol.AmqpProtocolVersion;
import org.apache.qpid.server.protocol.MultiVersionProtocolEngineFactory;
@@ -46,30 +49,10 @@ import org.apache.qpid.transport.network.Transport;
import static org.apache.qpid.transport.ConnectionSettings.WILDCARD_ADDRESS;
-import javax.net.ssl.SSLContext;
-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.Formatter;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Properties;
-import java.util.Set;
-import java.util.logging.ConsoleHandler;
-import java.util.logging.FileHandler;
-import java.util.logging.Handler;
-import java.util.logging.Level;
-import java.util.logging.LogRecord;
-
public class Broker
{
private static final Logger LOGGER = Logger.getLogger(Broker.class);
- private static final int IPV4_ADDRESS_LENGTH = 4;
- private static final char IPV4_LITERAL_SEPARATOR = '.';
private volatile Thread _shutdownHookThread;
protected static class InitException extends RuntimeException
@@ -128,6 +111,14 @@ public class Broker
ConfigurationFileApplicationRegistry config = new ConfigurationFileApplicationRegistry(configFile, options.getBundleContext());
ServerConfiguration serverConfig = config.getConfiguration();
+ if (options.getQpidWork() != null)
+ {
+ serverConfig.setQpidWork(options.getQpidWork());
+ }
+ if (options.getQpidHome() != null)
+ {
+ serverConfig.setQpidHome(options.getQpidHome());
+ }
updateManagementPorts(serverConfig, options.getJmxPortRegistryServer(), options.getJmxPortConnectorServer());
ApplicationRegistry.initialise(config);
@@ -145,14 +136,6 @@ public class Broker
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())
{
@@ -165,36 +148,71 @@ public class Broker
parsePortList(sslPorts, serverConfig.getSSLPorts());
}
+ //1-0 excludes and includes
Set<Integer> exclude_1_0 = new HashSet<Integer>(options.getExcludedPorts(ProtocolExclusion.v1_0));
if(exclude_1_0.isEmpty())
{
parsePortList(exclude_1_0, serverConfig.getPortExclude10());
}
+ Set<Integer> include_1_0 = new HashSet<Integer>(options.getIncludedPorts(ProtocolInclusion.v1_0));
+ if(include_1_0.isEmpty())
+ {
+ parsePortList(include_1_0, serverConfig.getPortInclude10());
+ }
+
+ //0-10 excludes and includes
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> include_0_10 = new HashSet<Integer>(options.getIncludedPorts(ProtocolInclusion.v0_10));
+ if(include_0_10.isEmpty())
+ {
+ parsePortList(include_0_10, serverConfig.getPortInclude010());
+ }
+
+ //0-9-1 excludes and includes
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> include_0_9_1 = new HashSet<Integer>(options.getIncludedPorts(ProtocolInclusion.v0_9_1));
+ if(include_0_9_1.isEmpty())
+ {
+ parsePortList(include_0_9_1, serverConfig.getPortInclude091());
+ }
+
+ //0-9 excludes and includes
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> include_0_9 = new HashSet<Integer>(options.getIncludedPorts(ProtocolInclusion.v0_9));
+ if(include_0_9.isEmpty())
+ {
+ parsePortList(include_0_9, serverConfig.getPortInclude09());
+ }
+
+ //0-8 excludes and includes
Set<Integer> exclude_0_8 = new HashSet<Integer>(options.getExcludedPorts(ProtocolExclusion.v0_8));
if(exclude_0_8.isEmpty())
{
parsePortList(exclude_0_8, serverConfig.getPortExclude08());
}
+ Set<Integer> include_0_8 = new HashSet<Integer>(options.getIncludedPorts(ProtocolInclusion.v0_8));
+ if(include_0_8.isEmpty())
+ {
+ parsePortList(include_0_8, serverConfig.getPortInclude08());
+ }
+
String bindAddr = options.getBind();
if (bindAddr == null)
{
@@ -220,8 +238,8 @@ public class Broker
final InetSocketAddress inetSocketAddress = new InetSocketAddress(bindAddress, port);
final Set<AmqpProtocolVersion> supported =
- getSupportedVersions(port, exclude_1_0, exclude_0_10, exclude_0_9_1, exclude_0_9,
- exclude_0_8, serverConfig);
+ getSupportedVersions(port, exclude_1_0, exclude_0_10, exclude_0_9_1, exclude_0_9, exclude_0_8,
+ include_1_0, include_0_10, include_0_9_1, include_0_9, include_0_8,serverConfig);
final NetworkTransportConfiguration settings =
new ServerNetworkTransportConfiguration(serverConfig, inetSocketAddress, Transport.TCP);
@@ -233,7 +251,7 @@ public class Broker
transport.accept(settings, protocolEngineFactory, null);
ApplicationRegistry.getInstance().addAcceptor(inetSocketAddress,
- new QpidAcceptor(transport,"TCP"));
+ new QpidAcceptor(transport,QpidAcceptor.Transport.TCP, supported));
CurrentActor.get().message(BrokerMessages.LISTENING("TCP", port));
}
}
@@ -242,16 +260,31 @@ public class Broker
{
final String keystorePath = serverConfig.getConnectorKeyStorePath();
final String keystorePassword = serverConfig.getConnectorKeyStorePassword();
+ final String keystoreType = serverConfig.getConnectorKeyStoreType();
final String keyManagerFactoryAlgorithm = serverConfig.getConnectorKeyManagerFactoryAlgorithm();
- final SSLContext sslContext = SSLContextFactory.buildServerContext(keystorePath, keystorePassword, keyManagerFactoryAlgorithm);
+ final SSLContext sslContext;
+ if(serverConfig.getConnectorTrustStorePath()!=null)
+ {
+ sslContext = SSLContextFactory.buildClientContext(serverConfig.getConnectorTrustStorePath(),
+ serverConfig.getConnectorTrustStorePassword(),
+ serverConfig.getConnectorTrustStoreType(),
+ serverConfig.getConnectorTrustManagerFactoryAlgorithm(),
+ keystorePath,
+ keystorePassword, keystoreType, keyManagerFactoryAlgorithm,
+ serverConfig.getCertAlias());
+ }
+ else
+ {
+ sslContext = SSLContextFactory.buildServerContext(keystorePath, keystorePassword, keystoreType, keyManagerFactoryAlgorithm);
+ }
for(int sslPort : sslPorts)
{
final InetSocketAddress inetSocketAddress = new InetSocketAddress(bindAddress, sslPort);
final Set<AmqpProtocolVersion> supported =
- getSupportedVersions(sslPort, exclude_1_0, exclude_0_10, exclude_0_9_1,
- exclude_0_9, exclude_0_8, serverConfig);
+ getSupportedVersions(sslPort, exclude_1_0, exclude_0_10, exclude_0_9_1, exclude_0_9, exclude_0_8,
+ include_1_0, include_0_10, include_0_9_1, include_0_9, include_0_8, serverConfig);
final NetworkTransportConfiguration settings =
new ServerNetworkTransportConfiguration(serverConfig, inetSocketAddress, Transport.TCP);
@@ -262,7 +295,7 @@ public class Broker
transport.accept(settings, protocolEngineFactory, sslContext);
ApplicationRegistry.getInstance().addAcceptor(inetSocketAddress,
- new QpidAcceptor(transport,"TCP"));
+ new QpidAcceptor(transport,QpidAcceptor.Transport.SSL, supported));
CurrentActor.get().message(BrokerMessages.LISTENING("TCP/SSL", sslPort));
}
}
@@ -282,27 +315,36 @@ public class Broker
final Set<Integer> exclude_0_9_1,
final Set<Integer> exclude_0_9,
final Set<Integer> exclude_0_8,
+ final Set<Integer> include_1_0,
+ final Set<Integer> include_0_10,
+ final Set<Integer> include_0_9_1,
+ final Set<Integer> include_0_9,
+ final Set<Integer> include_0_8,
final ServerConfiguration serverConfig)
{
final EnumSet<AmqpProtocolVersion> supported = EnumSet.allOf(AmqpProtocolVersion.class);
- if(exclude_1_0.contains(port) || !serverConfig.isAmqp10enabled())
+ if((exclude_1_0.contains(port) || !serverConfig.isAmqp10enabled()) && !include_1_0.contains(port))
{
supported.remove(AmqpProtocolVersion.v1_0_0);
}
- if(exclude_0_10.contains(port) || !serverConfig.isAmqp010enabled())
+
+ if((exclude_0_10.contains(port) || !serverConfig.isAmqp010enabled()) && !include_0_10.contains(port))
{
supported.remove(AmqpProtocolVersion.v0_10);
}
- if(exclude_0_9_1.contains(port) || !serverConfig.isAmqp091enabled())
+
+ if((exclude_0_9_1.contains(port) || !serverConfig.isAmqp091enabled()) && !include_0_9_1.contains(port))
{
supported.remove(AmqpProtocolVersion.v0_9_1);
}
- if(exclude_0_9.contains(port) || !serverConfig.isAmqp09enabled())
+
+ if((exclude_0_9.contains(port) || !serverConfig.isAmqp09enabled()) && !include_0_9.contains(port))
{
supported.remove(AmqpProtocolVersion.v0_9);
}
- if(exclude_0_8.contains(port) || !serverConfig.isAmqp08enabled())
+
+ if((exclude_0_8.contains(port) || !serverConfig.isAmqp08enabled()) && !include_0_8.contains(port))
{
supported.remove(AmqpProtocolVersion.v0_8);
}
@@ -388,7 +430,7 @@ public class Broker
}
}
- private void configureLogging(File logConfigFile, long logWatchTime) throws InitException, IOException
+ private void configureLogging(File logConfigFile, int logWatchTime) throws InitException, IOException
{
if (logConfigFile.exists() && logConfigFile.canRead())
{
@@ -401,7 +443,7 @@ public class Broker
// log4j expects the watch interval in milliseconds
try
{
- QpidLog4JConfigurator.configureAndWatch(logConfigFile.getPath(), logWatchTime * 1000);
+ LoggingFacade.configureAndWatch(logConfigFile.getPath(), logWatchTime * 1000);
}
catch (Exception e)
{
@@ -412,7 +454,7 @@ public class Broker
{
try
{
- QpidLog4JConfigurator.configure(logConfigFile.getPath());
+ LoggingFacade.configure(logConfigFile.getPath());
}
catch (Exception e)
{
@@ -446,12 +488,6 @@ public class Broker
}
}
- private void configureLoggingManagementMBean(File logConfigFile, int logWatchTime) throws Exception
- {
- LoggingManagementMBean blm = new LoggingManagementMBean(logConfigFile.getPath(),logWatchTime);
-
- blm.register();
- }
private void addShutdownHook()
{
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
index d871c724fd..434d40d557 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/BrokerOptions.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/BrokerOptions.java
@@ -33,10 +33,12 @@ public class BrokerOptions
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";
+ public static final String QPID_WORK = "QPID_WORK";
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 final Map<ProtocolInclusion,Set<Integer>> _inclusionMap = new HashMap<ProtocolInclusion, Set<Integer>>();
private String _configFile;
private String _logConfigFile;
@@ -46,6 +48,8 @@ public class BrokerOptions
private BundleContext _bundleContext;
private Integer _logWatchFrequency = 0;
+ private String _qpidWorkFolder;
+ private String _qpidHomeFolder;
public void addPort(final int port)
{
@@ -108,7 +112,7 @@ public class BrokerOptions
}
public String getQpidHome()
{
- return System.getProperty(QPID_HOME);
+ return _qpidHomeFolder == null? System.getProperty(QPID_HOME): _qpidHomeFolder;
}
public Set<Integer> getExcludedPorts(final ProtocolExclusion excludeProtocol)
@@ -161,4 +165,36 @@ public class BrokerOptions
{
_bundleContext = bundleContext;
}
+
+ public Set<Integer> getIncludedPorts(final ProtocolInclusion includeProtocol)
+ {
+ final Set<Integer> includedPorts = _inclusionMap.get(includeProtocol);
+ return includedPorts == null ? Collections.<Integer>emptySet() : includedPorts;
+ }
+
+ public void addIncludedPort(final ProtocolInclusion includeProtocol, final int port)
+ {
+ if (!_inclusionMap.containsKey(includeProtocol))
+ {
+ _inclusionMap.put(includeProtocol, new HashSet<Integer>());
+ }
+
+ Set<Integer> ports = _inclusionMap.get(includeProtocol);
+ ports.add(port);
+ }
+
+ public String getQpidWork()
+ {
+ return _qpidWorkFolder;
+ }
+
+ public void setQpidWork(String qpidWorkFolder)
+ {
+ _qpidWorkFolder = qpidWorkFolder;
+ }
+
+ public void setQpidHome(String qpidHomeFolder)
+ {
+ _qpidHomeFolder = qpidHomeFolder;
+ }
} \ 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 70fa414e3c..9fe7a6619f 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
@@ -85,6 +85,32 @@ public class Main
.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_INCLUDE_1_0 =
+ OptionBuilder.withArgName("port").hasArg()
+ .withDescription("accept AMQP1-0 connections on this port, overriding configuration to the contrary. The specified port must be one specified on the command line")
+ .withLongOpt("include-1-0").create();
+
+private static final Option OPTION_INCLUDE_0_10 =
+ OptionBuilder.withArgName("port").hasArg()
+ .withDescription("accept AMQP0-10 connections on this port, overriding configuration to the contrary. The specified port must be one specified on the command line")
+ .withLongOpt("include-0-10").create();
+
+private static final Option OPTION_INCLUDE_0_9_1 =
+ OptionBuilder.withArgName("port").hasArg()
+ .withDescription("accept AMQP0-9-1 connections on this port, overriding configuration to the contrary. The specified port must be one specified on the command line")
+ .withLongOpt("include-0-9-1").create();
+
+private static final Option OPTION_INCLUDE_0_9 =
+ OptionBuilder.withArgName("port").hasArg()
+ .withDescription("accept AMQP0-9 connections on this port, overriding configuration to the contrary. The specified port must be one specified on the command line")
+ .withLongOpt("include-0-9").create();
+
+private static final Option OPTION_INCLUDE_0_8 =
+ OptionBuilder.withArgName("port").hasArg()
+ .withDescription("accept AMQP0-8 connections on this port, overriding configuration to the contrary. The specified port must be one specified on the command line")
+ .withLongOpt("include-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")
@@ -127,6 +153,11 @@ public class Main
OPTIONS.addOption(OPTION_EXCLUDE_0_9_1);
OPTIONS.addOption(OPTION_EXCLUDE_0_9);
OPTIONS.addOption(OPTION_EXCLUDE_0_8);
+ OPTIONS.addOption(OPTION_INCLUDE_1_0);
+ OPTIONS.addOption(OPTION_INCLUDE_0_10);
+ OPTIONS.addOption(OPTION_INCLUDE_0_9_1);
+ OPTIONS.addOption(OPTION_INCLUDE_0_9);
+ OPTIONS.addOption(OPTION_INCLUDE_0_8);
OPTIONS.addOption(OPTION_BIND);
OPTIONS.addOption(OPTION_JMX_PORT_REGISTRY_SERVER);
@@ -256,6 +287,10 @@ public class Main
{
parsePortArray(options, _commandLine.getOptionValues(pe.getExcludeName()), pe);
}
+ for(ProtocolInclusion pe : ProtocolInclusion.values())
+ {
+ parseProtocolInclusions(options, _commandLine.getOptionValues(pe.getIncludeName()), pe);
+ }
}
String[] sslPortStr = _commandLine.getOptionValues(OPTION_SSLPORT.getOpt());
@@ -266,6 +301,10 @@ public class Main
{
parsePortArray(options, _commandLine.getOptionValues(pe.getExcludeName()), pe);
}
+ for(ProtocolInclusion pe : ProtocolInclusion.values())
+ {
+ parseProtocolInclusions(options, _commandLine.getOptionValues(pe.getIncludeName()), pe);
+ }
}
setExceptionHandler();
@@ -399,4 +438,23 @@ public class Main
}
}
}
+
+ private static void parseProtocolInclusions(final BrokerOptions options, final Object[] ports,
+ final ProtocolInclusion includedProtocol) throws InitException
+ {
+ if(ports != null)
+ {
+ for(int i = 0; i < ports.length; i++)
+ {
+ try
+ {
+ options.addIncludedPort(includedProtocol, Integer.parseInt(String.valueOf(ports[i])));
+ }
+ catch (NumberFormatException e)
+ {
+ throw new InitException("Invalid port for inclusion: " + ports[i], e);
+ }
+ }
+ }
+ }
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/ProtocolInclusion.java b/java/broker/src/main/java/org/apache/qpid/server/ProtocolInclusion.java
new file mode 100644
index 0000000000..85fbe2e02e
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/ProtocolInclusion.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.server;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public enum ProtocolInclusion
+{
+ v0_8("include-0-8","--include-0-8"),
+ v0_9("include-0-9", "--include-0-9"),
+ v0_9_1("include-0-9-1", "--include-0-9-1"),
+ v0_10("include-0-10", "--include-0-10"),
+ v1_0("include-1-0", "--include-1-0");
+
+ private static final Map<String, ProtocolInclusion> MAP = new HashMap<String,ProtocolInclusion>();
+
+ static
+ {
+ for(ProtocolInclusion pe : ProtocolInclusion.values())
+ {
+ MAP.put(pe.getArg(), pe);
+ }
+ }
+
+ private String _arg;
+ private String _includeName;
+
+ private ProtocolInclusion(final String includeName, final String arg)
+ {
+ _includeName = includeName;
+ _arg = arg;
+ }
+
+ public String getArg()
+ {
+ return _arg;
+ }
+
+ public String getIncludeName()
+ {
+ return _includeName;
+ }
+
+ public static ProtocolInclusion lookup(final String arg)
+ {
+ ProtocolInclusion ex = MAP.get(arg);
+
+ if(ex == null)
+ {
+ throw new IllegalArgumentException(arg + " is not a valid protocol inclusion");
+ }
+
+ return ex;
+ }
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/TransactionTimeoutHelper.java b/java/broker/src/main/java/org/apache/qpid/server/TransactionTimeoutHelper.java
new file mode 100644
index 0000000000..0c474cca13
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/TransactionTimeoutHelper.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.server;
+
+import org.apache.log4j.Logger;
+import org.apache.qpid.server.logging.LogActor;
+import org.apache.qpid.server.logging.LogMessage;
+import org.apache.qpid.server.logging.LogSubject;
+import org.apache.qpid.server.logging.actors.CurrentActor;
+import org.apache.qpid.server.logging.messages.ChannelMessages;
+
+public class TransactionTimeoutHelper
+{
+ private static final Logger LOGGER = Logger.getLogger(TransactionTimeoutHelper.class);
+
+ public static final String IDLE_TRANSACTION_ALERT = "IDLE TRANSACTION ALERT";
+ public static final String OPEN_TRANSACTION_ALERT = "OPEN TRANSACTION ALERT";
+
+ private final LogSubject _logSubject;
+
+ public TransactionTimeoutHelper(final LogSubject logSubject)
+ {
+ _logSubject = logSubject;
+ }
+
+ public void logIfNecessary(final long timeSoFar, final long warnTimeout,
+ final LogMessage message, final String alternateLogPrefix)
+ {
+ if (isTimedOut(timeSoFar, warnTimeout))
+ {
+ LogActor logActor = CurrentActor.get();
+ if(logActor.getRootMessageLogger().isMessageEnabled(logActor, _logSubject, message.getLogHierarchy()))
+ {
+ logActor.message(_logSubject, message);
+ }
+ else
+ {
+ LOGGER.warn(alternateLogPrefix + " " + _logSubject.toLogString() + " " + timeSoFar + " ms");
+ }
+ }
+ }
+
+ public boolean isTimedOut(long timeSoFar, long timeout)
+ {
+ return timeout > 0L && timeSoFar > timeout;
+ }
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/binding/Binding.java b/java/broker/src/main/java/org/apache/qpid/server/binding/Binding.java
index 2efd4cee26..9b3be624e0 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/binding/Binding.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/binding/Binding.java
@@ -35,11 +35,13 @@ public class Binding
private final Exchange _exchange;
private final Map<String, Object> _arguments;
private final UUID _id;
+ private final UUID _qmfId;
private final AtomicLong _matches = new AtomicLong();
- public Binding(UUID id, final String bindingKey, final AMQQueue queue, final Exchange exchange, final Map<String, Object> arguments)
+ public Binding(UUID id, UUID qmfId, final String bindingKey, final AMQQueue queue, final Exchange exchange, final Map<String, Object> arguments)
{
_id = id;
+ _qmfId = qmfId;
_bindingKey = bindingKey;
_queue = queue;
_exchange = exchange;
@@ -51,6 +53,11 @@ public class Binding
return _id;
}
+ public UUID getQMFId()
+ {
+ return _qmfId;
+ }
+
public String getBindingKey()
{
return _bindingKey;
diff --git a/java/broker/src/main/java/org/apache/qpid/server/binding/BindingFactory.java b/java/broker/src/main/java/org/apache/qpid/server/binding/BindingFactory.java
index abf252c733..b805056311 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/binding/BindingFactory.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/binding/BindingFactory.java
@@ -60,7 +60,7 @@ public class BindingFactory
private BindingImpl(UUID id, String bindingKey, final AMQQueue queue, final Exchange exchange, final Map<String, Object> arguments)
{
- super(id, bindingKey, queue, exchange, arguments);
+ super(id, queue.getVirtualHost().getConfigStore().createId(), bindingKey, queue, exchange, arguments);
_logSubject = new BindingLogSubject(bindingKey,exchange,queue);
}
@@ -166,7 +166,7 @@ public class BindingFactory
if (id == null)
{
- id = UUIDGenerator.generateUUID();
+ id = UUIDGenerator.generateBindingUUID(exchange.getName(), queue.getName(), bindingKey, _virtualHost.getName());
}
BindingImpl b = new BindingImpl(id, bindingKey, queue, exchange, arguments);
BindingImpl existingMapping = _bindings.putIfAbsent(b, b);
diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/ConfigStore.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/ConfigStore.java
index aff07250f3..c519a0c0fa 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/configuration/ConfigStore.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/configuration/ConfigStore.java
@@ -101,7 +101,7 @@ public class ConfigStore
}
- typeMap.put(object.getId(), object);
+ typeMap.put(object.getQMFId(), object);
sendEvent(Event.CREATED, object);
}
@@ -111,7 +111,7 @@ public class ConfigStore
ConcurrentHashMap typeMap = _typeMap.get(object.getConfigType());
if(typeMap != null)
{
- typeMap.remove(object.getId());
+ typeMap.remove(object.getQMFId());
sendEvent(Event.DELETED, object);
}
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/ConfiguredObject.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/ConfiguredObject.java
index 78666a3f93..ff4e38d9f7 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/configuration/ConfiguredObject.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/configuration/ConfiguredObject.java
@@ -25,7 +25,7 @@ import java.util.UUID;
public interface ConfiguredObject<T extends ConfigObjectType<T,C>, C extends ConfiguredObject<T, C>>
{
- public UUID getId();
+ public UUID getQMFId();
public T getConfigType();
diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/ExchangeConfig.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/ExchangeConfig.java
index 41c51d9684..6633d93adf 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/configuration/ExchangeConfig.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/configuration/ExchangeConfig.java
@@ -49,7 +49,12 @@ public interface ExchangeConfig extends ConfiguredObject<ExchangeConfigType, Exc
long getMsgRoutes();
+ long getMsgDrops();
+
long getByteReceives();
long getByteRoutes();
+
+ long getByteDrops();
+
} \ No newline at end of file
diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/LinkConfigType.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/LinkConfigType.java
index ea4f723dda..847cae87f5 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/configuration/LinkConfigType.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/configuration/LinkConfigType.java
@@ -76,7 +76,7 @@ public final class LinkConfigType extends ConfigObjectType<LinkConfigType, LinkC
}
};
- public static final LinkReadOnlyProperty<Integer> PORT_PROPERTY = new LinkReadOnlyProperty<Integer>("host")
+ public static final LinkReadOnlyProperty<Integer> PORT_PROPERTY = new LinkReadOnlyProperty<Integer>("port")
{
public Integer getValue(LinkConfig object)
{
@@ -134,4 +134,4 @@ public final class LinkConfigType extends ConfigObjectType<LinkConfigType, LinkC
-} \ No newline at end of file
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/QueueConfiguration.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/QueueConfiguration.java
index 40bafb4275..8f03383777 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/configuration/QueueConfiguration.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/configuration/QueueConfiguration.java
@@ -126,6 +126,11 @@ public class QueueConfiguration extends ConfigurationPlugin
return _name;
}
+ public String getDescription()
+ {
+ return getStringValue("description");
+ }
+
public int getMaximumMessageAge()
{
return getIntValue("maximumMessageAge", _vHostConfig.getMaximumMessageAge());
@@ -226,4 +231,5 @@ public class QueueConfiguration extends ConfigurationPlugin
}
+
}
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 46027d02c6..f9e2d93cff 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,6 +20,16 @@
package org.apache.qpid.server.configuration;
+import java.io.File;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Map.Entry;
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.TrustManagerFactory;
import org.apache.commons.configuration.CompositeConfiguration;
import org.apache.commons.configuration.Configuration;
import org.apache.commons.configuration.ConfigurationException;
@@ -28,7 +38,6 @@ 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.plugins.ConfigurationPlugin;
import org.apache.qpid.server.exchange.DefaultExchangeFactory;
import org.apache.qpid.server.protocol.AmqpProtocolVersion;
@@ -40,17 +49,6 @@ import org.apache.qpid.server.virtualhost.VirtualHostRegistry;
import static org.apache.qpid.transport.ConnectionSettings.WILDCARD_ADDRESS;
-import java.io.File;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.Map.Entry;
-
-import javax.net.ssl.KeyManagerFactory;
-
public class ServerConfiguration extends ConfigurationPlugin
{
protected static final Logger _logger = Logger.getLogger(ServerConfiguration.class);
@@ -66,6 +64,9 @@ public class ServerConfiguration extends ConfigurationPlugin
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_HTTP_MANAGEMENT_PORT = 8080;
+ public static final int DEFAULT_HTTPS_MANAGEMENT_PORT = 8443;
+ public static final long DEFAULT_MINIMUM_ALERT_REPEAT_GAP = 30000l;
public static final String QPID_HOME = "QPID_HOME";
public static final String QPID_WORK = "QPID_WORK";
@@ -77,6 +78,8 @@ public class ServerConfiguration extends ConfigurationPlugin
private File _configFile;
private File _vhostsFile;
+ private String _qpidWork;
+ private String _qpidHome;
// Map of environment variables to config items
private static final Map<String, String> envVarMap = new HashMap<String, String>();
@@ -86,6 +89,9 @@ public class ServerConfiguration extends ConfigurationPlugin
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 SECURITY_DEFAULT_AUTH_MANAGER = "security.default-auth-manager";
+ public static final String SECURITY_PORT_MAPPINGS_PORT_MAPPING_AUTH_MANAGER = "security.port-mappings.port-mapping.auth-manager";
+ public static final String SECURITY_PORT_MAPPINGS_PORT_MAPPING_PORT = "security.port-mappings.port-mapping.port";
public static final String STATUS_UPDATES = "status-updates";
public static final String ADVANCED_LOCALE = "advanced.locale";
public static final String CONNECTOR_AMQP10ENABLED = "connector.amqp10enabled";
@@ -94,6 +100,11 @@ public class ServerConfiguration extends ConfigurationPlugin
public static final String CONNECTOR_AMQP09ENABLED = "connector.amqp09enabled";
public static final String CONNECTOR_AMQP08ENABLED = "connector.amqp08enabled";
public static final String CONNECTOR_AMQP_SUPPORTED_REPLY = "connector.amqpDefaultSupportedProtocolReply";
+ public static final String CONNECTOR_INCLUDE_10 = "connector.include10";
+ public static final String CONNECTOR_INCLUDE_010 = "connector.include010";
+ public static final String CONNECTOR_INCLUDE_091 = "connector.include091";
+ public static final String CONNECTOR_INCLUDE_09 = "connector.include09";
+ public static final String CONNECTOR_INCLUDE_08 = "connector.include08";
{
envVarMap.put("QPID_PORT", "connector.port");
@@ -104,6 +115,8 @@ public class ServerConfiguration extends ConfigurationPlugin
envVarMap.put("QPID_MSGAUTH", "security.msg-auth");
envVarMap.put("QPID_AUTOREGISTER", "auto_register");
envVarMap.put("QPID_MANAGEMENTENABLED", "management.enabled");
+ envVarMap.put("QPID_HTTPMANAGEMENTENABLED", "management.http.enabled");
+ envVarMap.put("QPID_HTTPMANAGEMENTPORT", "management.http.port");
envVarMap.put("QPID_HEARTBEATDELAY", "heartbeat.delay");
envVarMap.put("QPID_HEARTBEATTIMEOUTFACTOR", "heartbeat.timeoutFactor");
envVarMap.put("QPID_MAXIMUMMESSAGEAGE", "maximumMessageAge");
@@ -177,7 +190,7 @@ public class ServerConfiguration extends ConfigurationPlugin
* This has been made a two step process to allow the Plugin Manager and
* Configuration Manager to be initialised in the Application Registry.
* <p>
- * If using this ServerConfiguration via an ApplicationRegistry there is no
+ * If using this ServerConfiguration via an ApplicationRegistry there is no
* need to explicitly call {@link #initialise()} as this is done via the
* {@link ApplicationRegistry#initialise()} method.
*
@@ -199,12 +212,12 @@ public class ServerConfiguration extends ConfigurationPlugin
* Called by {@link ApplicationRegistry#initialise()}.
* <p>
* NOTE: A DEFAULT ApplicationRegistry must exist when using this method
- * or a new ApplicationRegistry will be created.
+ * or a new ApplicationRegistry will be created.
*
* @throws ConfigurationException
*/
public void initialise() throws ConfigurationException
- {
+ {
setConfiguration("", getConfig());
setupVirtualHosts(getConfig());
}
@@ -219,10 +232,10 @@ public class ServerConfiguration extends ConfigurationPlugin
{
// 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."
+ 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);
}
@@ -236,7 +249,7 @@ public class ServerConfiguration extends ConfigurationPlugin
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."
+ String message = "Validation error : security/principal-databases is no longer supported within the configuration xml."
+ (_configFile == null ? "" : " Configuration file : " + _configFile);
throw new ConfigurationException(message);
}
@@ -249,6 +262,13 @@ public class ServerConfiguration extends ConfigurationPlugin
throw new ConfigurationException(message);
}
+ String[] ports = getConfig().getStringArray(SECURITY_PORT_MAPPINGS_PORT_MAPPING_PORT);
+ String[] authManagers = getConfig().getStringArray(SECURITY_PORT_MAPPINGS_PORT_MAPPING_AUTH_MANAGER);
+ if (ports.length != authManagers.length)
+ {
+ throw new ConfigurationException("Validation error: Each port-mapping must have exactly one port and exactly one auth-manager.");
+ }
+
// 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",
@@ -280,7 +300,7 @@ public class ServerConfiguration extends ConfigurationPlugin
@SuppressWarnings("unchecked")
protected void setupVirtualHosts(Configuration conf) throws ConfigurationException
{
- List<String> vhostFiles = conf.getList("virtualhosts");
+ List<String> vhostFiles = (List) conf.getList("virtualhosts");
Configuration vhostConfig = conf.subset("virtualhosts");
// Only one configuration mechanism allowed
@@ -470,7 +490,7 @@ public class ServerConfiguration extends ConfigurationPlugin
Configuration newConfig = parseConfig(_configFile);
setConfiguration("", newConfig);
ApplicationRegistry.getInstance().getSecurityManager().configureHostPlugins(this);
-
+
// Reload virtualhosts from correct location
Configuration newVhosts;
if (_vhostsFile == null)
@@ -495,15 +515,29 @@ public class ServerConfiguration extends ConfigurationPlugin
_logger.warn(SECURITY_CONFIG_RELOADED);
}
}
-
+
public String getQpidWork()
{
- return System.getProperty(QPID_WORK, System.getProperty("java.io.tmpdir"));
+ if ( _qpidWork == null )
+ {
+ return System.getProperty(QPID_WORK, System.getProperty("java.io.tmpdir"));
+ }
+ else
+ {
+ return _qpidWork;
+ }
}
-
+
public String getQpidHome()
{
- return System.getProperty(QPID_HOME);
+ if ( _qpidHome == null )
+ {
+ return System.getProperty(QPID_HOME);
+ }
+ else
+ {
+ return _qpidHome;
+ }
}
public void setJMXPortRegistryServer(int registryServerPort)
@@ -541,16 +575,36 @@ public class ServerConfiguration extends ConfigurationPlugin
return getBooleanValue("management.platform-mbeanserver", true);
}
+ public boolean getHTTPManagementEnabled()
+ {
+ return getBooleanValue("management.http.enabled", true);
+ }
+
+ public int getHTTPManagementPort()
+ {
+ return getIntValue("management.http.port", DEFAULT_HTTP_MANAGEMENT_PORT);
+ }
+
+ public boolean getHTTPSManagementEnabled()
+ {
+ return getBooleanValue("management.https.enabled", false);
+ }
+
+ public int getHTTPSManagementPort()
+ {
+ return getIntValue("management.https.port", DEFAULT_HTTPS_MANAGEMENT_PORT);
+ }
+
public String[] getVirtualHosts()
{
return _virtualHosts.keySet().toArray(new String[_virtualHosts.size()]);
}
-
+
public String getPluginDirectory()
{
return getStringValue("plugin-directory");
}
-
+
public String getCacheDirectory()
{
return getStringValue("cache-directory");
@@ -581,6 +635,26 @@ public class ServerConfiguration extends ConfigurationPlugin
return getBooleanValue("security.msg-auth");
}
+ public String getDefaultAuthenticationManager()
+ {
+ return getStringValue(SECURITY_DEFAULT_AUTH_MANAGER);
+ }
+
+ public Map<Integer, String> getPortAuthenticationMappings()
+ {
+ String[] ports = getConfig().getStringArray(SECURITY_PORT_MAPPINGS_PORT_MAPPING_PORT);
+ String[] authManagers = getConfig().getStringArray(SECURITY_PORT_MAPPINGS_PORT_MAPPING_AUTH_MANAGER);
+
+ Map<Integer,String> portMappings = new HashMap<Integer, String>();
+ for(int i = 0; i < ports.length; i++)
+ {
+ portMappings.put(Integer.valueOf(ports[i]), authManagers[i]);
+ }
+
+ return portMappings;
+ }
+
+
public String getManagementKeyStorePath()
{
final String fallback = getStringValue("management.ssl.keystorePath");
@@ -589,7 +663,7 @@ public class ServerConfiguration extends ConfigurationPlugin
public boolean getManagementSSLEnabled()
{
- return getBooleanValue("management.ssl.enabled", true);
+ return getBooleanValue("management.ssl.enabled", false);
}
public String getManagementKeyStorePassword()
@@ -603,16 +677,11 @@ public class ServerConfiguration extends ConfigurationPlugin
return getBooleanValue("queue.auto_register", true);
}
- public boolean getManagementEnabled()
+ public boolean getJMXManagementEnabled()
{
return getBooleanValue("management.enabled", true);
}
- public void setManagementEnabled(boolean enabled)
- {
- getConfig().setProperty("management.enabled", enabled);
- }
-
public int getHeartBeatDelay()
{
return getIntValue("heartbeat.delay", 5);
@@ -645,7 +714,7 @@ public class ServerConfiguration extends ConfigurationPlugin
public long getMinimumAlertRepeatGap()
{
- return getLongValue("minimumAlertRepeatGap");
+ return getLongValue("minimumAlertRepeatGap", DEFAULT_MINIMUM_ALERT_REPEAT_GAP);
}
public long getCapacity()
@@ -693,6 +762,31 @@ public class ServerConfiguration extends ConfigurationPlugin
return getListValue("connector.non08port");
}
+ public List getPortInclude08()
+ {
+ return getListValue(CONNECTOR_INCLUDE_08);
+ }
+
+ public List getPortInclude09()
+ {
+ return getListValue(CONNECTOR_INCLUDE_09);
+ }
+
+ public List getPortInclude091()
+ {
+ return getListValue(CONNECTOR_INCLUDE_091);
+ }
+
+ public List getPortInclude010()
+ {
+ return getListValue(CONNECTOR_INCLUDE_010);
+ }
+
+ public List getPortInclude10()
+ {
+ return getListValue(CONNECTOR_INCLUDE_10);
+ }
+
public String getBind()
{
return getStringValue("connector.bind", WILDCARD_ADDRESS);
@@ -740,6 +834,11 @@ public class ServerConfiguration extends ConfigurationPlugin
return getStringValue("connector.ssl.keyStorePassword", fallback);
}
+ public String getConnectorKeyStoreType()
+ {
+ return getStringValue("connector.ssl.keyStoreType", "JKS");
+ }
+
public String getConnectorKeyManagerFactoryAlgorithm()
{
final String systemFallback = KeyManagerFactory.getDefaultAlgorithm();
@@ -748,6 +847,41 @@ public class ServerConfiguration extends ConfigurationPlugin
return getStringValue("connector.ssl.keyManagerFactoryAlgorithm", fallback);
}
+ public String getConnectorTrustStorePath()
+ {
+ return getStringValue("connector.ssl.trustStorePath", null);
+ }
+
+ public String getConnectorTrustStorePassword()
+ {
+ return getStringValue("connector.ssl.trustStorePassword", null);
+ }
+
+ public String getConnectorTrustStoreType()
+ {
+ return getStringValue("connector.ssl.trustStoreType", "JKS");
+ }
+
+ public String getConnectorTrustManagerFactoryAlgorithm()
+ {
+ return getStringValue("connector.ssl.trustManagerFactoryAlgorithm", TrustManagerFactory.getDefaultAlgorithm());
+ }
+
+ public String getCertAlias()
+ {
+ return getStringValue("connector.ssl.certAlias", null);
+ }
+
+ public boolean needClientAuth()
+ {
+ return getConfig().getBoolean("connector.ssl.needClientAuth", false);
+ }
+
+ public boolean wantClientAuth()
+ {
+ return getConfig().getBoolean("connector.ssl.wantClientAuth", false);
+ }
+
public String getDefaultVirtualHost()
{
return getStringValue("virtualhosts.default");
@@ -756,7 +890,7 @@ public class ServerConfiguration extends ConfigurationPlugin
public void setDefaultVirtualHost(String vhost)
{
getConfig().setProperty("virtualhosts.default", vhost);
- }
+ }
public void setHousekeepingCheckPeriod(long value)
{
@@ -883,4 +1017,15 @@ public class ServerConfiguration extends ConfigurationPlugin
return reply == null ? null : AmqpProtocolVersion.valueOf(reply);
}
+
+ public void setQpidWork(String path)
+ {
+ _qpidWork = path;
+ }
+
+ public void setQpidHome(String path)
+ {
+ _qpidHome = path;
+ }
+
}
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
index f6fe47b996..51dcc38c47 100644
--- 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
@@ -28,7 +28,7 @@ public class ServerNetworkTransportConfiguration implements NetworkTransportConf
private final String _transport;
private InetSocketAddress _address;
- public ServerNetworkTransportConfiguration(final ServerConfiguration serverConfig,
+ public ServerNetworkTransportConfiguration(final ServerConfiguration serverConfig,
final InetSocketAddress address,
final String transport)
{
@@ -76,4 +76,15 @@ public class ServerNetworkTransportConfiguration implements NetworkTransportConf
{
return _address;
}
+
+ public boolean needClientAuth()
+ {
+ return _serverConfig.needClientAuth();
+ }
+
+ @Override
+ public boolean wantClientAuth()
+ {
+ return _serverConfig.wantClientAuth();
+ }
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/SystemConfigImpl.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/SystemConfigImpl.java
index 98109ce1e8..80c2e8b2f1 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/configuration/SystemConfigImpl.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/configuration/SystemConfigImpl.java
@@ -33,7 +33,7 @@ public class SystemConfigImpl implements SystemConfig
private static final String OS_ARCH = System.getProperty("os.arch");
private static final String OS_VERSION = System.getProperty("os.version");
- private final UUID _id;
+ private final UUID _qmfId;
private String _name;
private final String _host;
@@ -48,9 +48,9 @@ public class SystemConfigImpl implements SystemConfig
this(store.createId(), store);
}
- public SystemConfigImpl(UUID id, ConfigStore store)
+ public SystemConfigImpl(UUID qmfId, ConfigStore store)
{
- _id = id;
+ _qmfId = qmfId;
_store = store;
String host;
try
@@ -95,9 +95,10 @@ public class SystemConfigImpl implements SystemConfig
return OS_ARCH;
}
- public UUID getId()
+ @Override
+ public UUID getQMFId()
{
- return _id;
+ return _qmfId;
}
public SystemConfigType getConfigType()
@@ -119,12 +120,12 @@ public class SystemConfigImpl implements SystemConfig
{
broker.setSystem(this);
_store.addConfiguredObject(broker);
- _brokers.put(broker.getId(), broker);
+ _brokers.put(broker.getQMFId(), broker);
}
public void removeBroker(final BrokerConfig broker)
{
- _brokers.remove(broker.getId());
+ _brokers.remove(broker.getQMFId());
_store.removeConfiguredObject(broker);
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/SystemConfigType.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/SystemConfigType.java
index d7c36da4e0..4a383cce7a 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/configuration/SystemConfigType.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/configuration/SystemConfigType.java
@@ -65,7 +65,7 @@ public final class SystemConfigType extends ConfigObjectType<SystemConfigType, S
{
public UUID getValue(SystemConfig object)
{
- return object.getId();
+ return object.getQMFId();
}
};
diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/TopicConfig.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/TopicConfig.java
index 10e40151b0..aaa1766489 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/configuration/TopicConfig.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/configuration/TopicConfig.java
@@ -61,7 +61,6 @@ public class TopicConfig extends ConfigurationPlugin
throw new ConfigurationException("Topic section must have a 'name' or 'subscriptionName' element.");
}
- System.err.println("********* Created TC:"+this);
}
@@ -75,5 +74,5 @@ public class TopicConfig extends ConfigurationPlugin
}
return response;
- }
+ }
} \ No newline at end of file
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 5f472b6ddd..e557085631 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
@@ -32,7 +32,6 @@ import org.apache.qpid.server.configuration.plugins.ConfigurationPlugin;
import org.apache.qpid.server.queue.AMQQueue;
import org.apache.qpid.server.registry.ApplicationRegistry;
import org.apache.qpid.server.store.MemoryMessageStore;
-import org.apache.qpid.server.store.MemoryMessageStoreFactory;
import java.util.ArrayList;
import java.util.Arrays;
@@ -103,14 +102,14 @@ public class VirtualHostConfiguration extends ConfigurationPlugin
return getConfig().subset("store");
}
- public String getMessageStoreFactoryClass()
+ public String getMessageStoreClass()
{
- return getStringValue("store.factoryclass", MemoryMessageStoreFactory.class.getName());
+ return getStringValue("store.class", MemoryMessageStore.class.getName());
}
- public void setMessageStoreFactoryClass(String storeFactoryClass)
+ public void setMessageStoreClass(String storeFactoryClass)
{
- getConfig().setProperty("store.factoryclass", storeFactoryClass);
+ getConfig().setProperty("store.class", storeFactoryClass);
}
public List getExchanges()
@@ -271,7 +270,7 @@ public class VirtualHostConfiguration extends ConfigurationPlugin
public Long getMinimumAlertRepeatGap()
{
- return getLongValue("queues.minimumAlertRepeatGap");
+ return getLongValue("queues.minimumAlertRepeatGap", ApplicationRegistry.getInstance().getConfiguration().getMinimumAlertRepeatGap());
}
public long getCapacity()
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 4a58314f51..451754e6d8 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
@@ -22,13 +22,12 @@ package org.apache.qpid.server.connection;
import org.apache.log4j.Logger;
-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.transport.TransportException;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
@@ -37,6 +36,8 @@ public class ConnectionRegistry implements IConnectionRegistry, Closeable
private List<AMQConnectionModel> _registry = new CopyOnWriteArrayList<AMQConnectionModel>();
private Logger _logger = Logger.getLogger(ConnectionRegistry.class);
+ private final Collection<RegistryChangeListener> _listeners =
+ new ArrayList<RegistryChangeListener>();
public void initialise()
{
@@ -62,34 +63,77 @@ public class ConnectionRegistry implements IConnectionRegistry, Closeable
}
}
- public void closeConnection(AMQConnectionModel connection, AMQConstant cause, String message)
+ private void closeConnection(AMQConnectionModel connection, AMQConstant cause, String message)
{
try
{
connection.close(cause, message);
}
- catch (TransportException e)
+ catch (Exception e)
{
- _logger.warn("Error closing connection:" + e.getMessage());
- }
- catch (AMQException e)
- {
- _logger.warn("Error closing connection:" + e.getMessage());
+ _logger.warn("Exception closing connection", e);
}
}
public void registerConnection(AMQConnectionModel connnection)
{
- _registry.add(connnection);
+ synchronized (this)
+ {
+ _registry.add(connnection);
+ synchronized (_listeners)
+ {
+ for(RegistryChangeListener listener : _listeners)
+ {
+ listener.connectionRegistered(connnection);
+ }
+ }
+ }
+ synchronized (_listeners)
+ {
+ for(RegistryChangeListener listener : _listeners)
+ {
+ listener.connectionRegistered(connnection);
+ }
+ }
}
public void deregisterConnection(AMQConnectionModel connnection)
{
- _registry.remove(connnection);
+ synchronized (this)
+ {
+ _registry.remove(connnection);
+
+ synchronized (_listeners)
+ {
+ for(RegistryChangeListener listener : _listeners)
+ {
+ listener.connectionUnregistered(connnection);
+ }
+ }
+ }
+
+ synchronized (_listeners)
+ {
+ for(RegistryChangeListener listener : _listeners)
+ {
+ listener.connectionUnregistered(connnection);
+ }
+ }
+ }
+
+ public void addRegistryChangeListener(RegistryChangeListener listener)
+ {
+ synchronized (_listeners)
+ {
+ _listeners.add(listener);
+ }
}
public List<AMQConnectionModel> getConnections()
{
- return new ArrayList<AMQConnectionModel>(_registry);
+ synchronized (this)
+ {
+ 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 954c448b72..82adcf4dde 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
@@ -37,11 +37,18 @@ public interface IConnectionRegistry
public void close(String replyText) throws AMQException;
- public void closeConnection(AMQConnectionModel connection, AMQConstant cause, String message);
-
public List<AMQConnectionModel> getConnections();
public void registerConnection(AMQConnectionModel connnection);
public void deregisterConnection(AMQConnectionModel connnection);
+
+ void addRegistryChangeListener(RegistryChangeListener listener);
+
+ interface RegistryChangeListener
+ {
+ void connectionRegistered(AMQConnectionModel connection);
+ void connectionUnregistered(AMQConnectionModel connection);
+
+ }
}
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 9493f400f2..512a8c6996 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
@@ -30,15 +30,12 @@ import org.apache.qpid.server.logging.LogSubject;
import org.apache.qpid.server.logging.actors.CurrentActor;
import org.apache.qpid.server.logging.messages.ExchangeMessages;
import org.apache.qpid.server.logging.subjects.ExchangeLogSubject;
-import org.apache.qpid.server.management.Managable;
-import org.apache.qpid.server.management.ManagedObject;
import org.apache.qpid.server.message.InboundMessage;
import org.apache.qpid.server.queue.AMQQueue;
import org.apache.qpid.server.queue.BaseQueue;
import org.apache.qpid.server.queue.QueueRegistry;
import org.apache.qpid.server.virtualhost.VirtualHost;
-import javax.management.JMException;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
@@ -50,10 +47,8 @@ import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
-public abstract class AbstractExchange implements Exchange, Managable
+public abstract class AbstractExchange implements Exchange
{
-
-
private AMQShortString _name;
private final AtomicBoolean _closed = new AtomicBoolean();
@@ -66,9 +61,6 @@ public abstract class AbstractExchange implements Exchange, Managable
private final List<Exchange.Task> _closeTaskList = new CopyOnWriteArrayList<Exchange.Task>();
-
- private AbstractExchangeMBean _exchangeMbean;
-
/**
* Whether the exchange is automatically deleted once all queues have detached from it
*/
@@ -86,12 +78,16 @@ public abstract class AbstractExchange implements Exchange, Managable
private final AtomicLong _receivedMessageSize = new AtomicLong();
private final AtomicLong _routedMessageCount = new AtomicLong();
private final AtomicLong _routedMessageSize = new AtomicLong();
+ private final AtomicLong _droppedMessageCount = new AtomicLong();
+ private final AtomicLong _droppedMessageSize = new AtomicLong();
private final CopyOnWriteArrayList<Exchange.BindingListener> _listeners = new CopyOnWriteArrayList<Exchange.BindingListener>();
//TODO : persist creation time
private long _createTime = System.currentTimeMillis();
+ private UUID _qmfId;
+
public AbstractExchange(final ExchangeType<? extends Exchange> type)
{
_type = type;
@@ -107,13 +103,6 @@ public abstract class AbstractExchange implements Exchange, Managable
return _type.getName();
}
- /**
- * Concrete exchanges must implement this method in order to create the managed representation. This is
- * called during initialisation (template method pattern).
- * @return the MBean
- */
- protected abstract AbstractExchangeMBean createMBean() throws JMException;
-
public void initialise(UUID id, VirtualHost host, AMQShortString name, boolean durable, int ticket, boolean autoDelete)
throws AMQException
{
@@ -124,28 +113,14 @@ public abstract class AbstractExchange implements Exchange, Managable
_ticket = ticket;
_id = id;
-
+ _qmfId = getConfigStore().createId();
getConfigStore().addConfiguredObject(this);
- createAndRegisterMBean();
_logSubject = new ExchangeLogSubject(this, this.getVirtualHost());
// Log Exchange creation
CurrentActor.get().message(ExchangeMessages.CREATED(String.valueOf(getTypeShortString()), String.valueOf(name), durable));
}
- private void createAndRegisterMBean()
- {
- try
- {
- _exchangeMbean = createMBean();
- _exchangeMbean.register();
- }
- catch (JMException e)
- {
- throw new RuntimeException("Failed to register mbean",e);
- }
- }
-
public ConfigStore getConfigStore()
{
return getVirtualHost().getConfigStore();
@@ -171,10 +146,6 @@ public abstract class AbstractExchange implements Exchange, Managable
if(_closed.compareAndSet(false,true))
{
- if (_exchangeMbean != null)
- {
- _exchangeMbean.unregister();
- }
getConfigStore().removeConfiguredObject(this);
if(_alternateExchange != null)
{
@@ -196,11 +167,6 @@ public abstract class AbstractExchange implements Exchange, Managable
return getClass().getSimpleName() + "[" + getNameShortString() +"]";
}
- public ManagedObject getManagedObject()
- {
- return _exchangeMbean;
- }
-
public VirtualHost getVirtualHost()
{
return _virtualHost;
@@ -332,6 +298,12 @@ public abstract class AbstractExchange implements Exchange, Managable
return _id;
}
+ @Override
+ public UUID getQMFId()
+ {
+ return _qmfId;
+ }
+
public ExchangeConfigType getConfigType()
{
return ExchangeConfigType.getInstance();
@@ -359,6 +331,11 @@ public abstract class AbstractExchange implements Exchange, Managable
_routedMessageCount.incrementAndGet();
_routedMessageSize.addAndGet(message.getSize());
}
+ else
+ {
+ _droppedMessageCount.incrementAndGet();
+ _droppedMessageSize.addAndGet(message.getSize());
+ }
return queues;
}
@@ -374,6 +351,11 @@ public abstract class AbstractExchange implements Exchange, Managable
return _routedMessageCount.get();
}
+ public long getMsgDrops()
+ {
+ return _droppedMessageCount.get();
+ }
+
public long getByteReceives()
{
return _receivedMessageSize.get();
@@ -384,6 +366,11 @@ public abstract class AbstractExchange implements Exchange, Managable
return _routedMessageSize.get();
}
+ public long getByteDrops()
+ {
+ return _droppedMessageSize.get();
+ }
+
public long getCreateTime()
{
return _createTime;
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
deleted file mode 100644
index 034331abd9..0000000000
--- a/java/broker/src/main/java/org/apache/qpid/server/exchange/AbstractExchangeMBean.java
+++ /dev/null
@@ -1,215 +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.exchange;
-
-import org.apache.qpid.AMQException;
-import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpid.management.common.mbeans.ManagedExchange;
-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 org.apache.qpid.server.management.ManagedObjectRegistry;
-import org.apache.qpid.server.queue.AMQQueue;
-import org.apache.qpid.server.registry.ApplicationRegistry;
-import org.apache.qpid.server.virtualhost.VirtualHost;
-
-import javax.management.JMException;
-import javax.management.MBeanException;
-import javax.management.MalformedObjectNameException;
-import javax.management.NotCompliantMBeanException;
-import javax.management.ObjectName;
-import javax.management.openmbean.ArrayType;
-import javax.management.openmbean.CompositeType;
-import javax.management.openmbean.OpenDataException;
-import javax.management.openmbean.OpenType;
-import javax.management.openmbean.SimpleType;
-import javax.management.openmbean.TabularType;
-import java.util.Collections;
-
-
-/**
- * Abstract MBean class. This has some of the methods implemented from
- * management intrerface for exchanges. Any implementaion of an
- * Exchange MBean should extend this class.
- */
-public abstract class AbstractExchangeMBean<T extends AbstractExchange> extends AMQManagedObject implements ManagedExchange
-{
- // open mbean data types for representing exchange bindings
- private OpenType[] _bindingItemTypes;
- private CompositeType _bindingDataType;
- private TabularType _bindinglistDataType;
-
-
- private T _exchange;
-
- public AbstractExchangeMBean(final T abstractExchange) throws NotCompliantMBeanException
- {
- super(ManagedExchange.class, ManagedExchange.TYPE);
- _exchange = abstractExchange;
- }
-
- protected void init() throws OpenDataException
- {
- _bindingItemTypes = new OpenType[2];
- _bindingItemTypes[0] = SimpleType.STRING;
- _bindingItemTypes[1] = new ArrayType(1, SimpleType.STRING);
- _bindingDataType = new CompositeType("Exchange Binding", "Binding key and Queue names",
- COMPOSITE_ITEM_NAMES.toArray(new String[COMPOSITE_ITEM_NAMES.size()]),
- COMPOSITE_ITEM_DESCRIPTIONS.toArray(new String[COMPOSITE_ITEM_DESCRIPTIONS.size()]), _bindingItemTypes);
- _bindinglistDataType = new TabularType("Exchange Bindings", "Exchange Bindings for " + getName(),
- _bindingDataType, TABULAR_UNIQUE_INDEX.toArray(new String[TABULAR_UNIQUE_INDEX.size()]));
- }
-
- public ManagedObject getParentObject()
- {
- return _exchange.getVirtualHost().getManagedObject();
- }
-
- public T getExchange()
- {
- return _exchange;
- }
-
-
- public String getObjectInstanceName()
- {
- return ObjectName.quote(_exchange.getName());
- }
-
- public String getName()
- {
- return _exchange.getName();
- }
-
- public String getExchangeType()
- {
- return _exchange.getTypeShortString().toString();
- }
-
- public Integer getTicketNo()
- {
- return _exchange.getTicket();
- }
-
- public boolean isDurable()
- {
- return _exchange.isDurable();
- }
-
- public boolean isAutoDelete()
- {
- return _exchange.isAutoDelete();
- }
-
- // Added exchangetype in the object name lets maangement apps to do any customization required
- public ObjectName getObjectName() throws MalformedObjectNameException
- {
- String objNameString = super.getObjectName().toString();
- objNameString = objNameString + ",ExchangeType=" + getExchangeType();
- return new ObjectName(objNameString);
- }
-
- protected ManagedObjectRegistry getManagedObjectRegistry()
- {
- return ApplicationRegistry.getInstance().getManagedObjectRegistry();
- }
-
- public void createNewBinding(String queueName, String binding) throws JMException
- {
- VirtualHost vhost = getExchange().getVirtualHost();
- AMQQueue queue = vhost.getQueueRegistry().getQueue(new AMQShortString(queueName));
- if (queue == null)
- {
- throw new JMException("Queue \"" + queueName + "\" is not registered with the virtualhost.");
- }
-
- CurrentActor.set(new ManagementActor(getLogActor().getRootMessageLogger()));
- try
- {
- vhost.getBindingFactory().addBinding(binding,queue,getExchange(),null);
- }
- catch (AMQException ex)
- {
- JMException jme = new JMException(ex.toString());
- throw new MBeanException(jme, "Error creating new binding " + binding);
- }
- CurrentActor.remove();
- }
-
- /**
- * Removes a queue binding from the exchange.
- *
- * @see org.apache.qpid.server.binding.BindingFactory#removeBinding(String, AMQQueue, Exchange, java.util.Map)
- */
- public void removeBinding(String queueName, String binding) throws JMException
- {
- VirtualHost vhost = getExchange().getVirtualHost();
- AMQQueue queue = vhost.getQueueRegistry().getQueue(new AMQShortString(queueName));
- if (queue == null)
- {
- throw new JMException("Queue \"" + queueName + "\" is not registered with the virtualhost.");
- }
-
- CurrentActor.set(new ManagementActor(getLogActor().getRootMessageLogger()));
- try
- {
- vhost.getBindingFactory().removeBinding(binding, queue, _exchange, Collections.<String, Object>emptyMap());
- }
- catch (AMQException ex)
- {
- JMException jme = new JMException(ex.toString());
- throw new MBeanException(jme, "Error removing binding " + binding);
- }
- CurrentActor.remove();
- }
-
-
- protected OpenType[] getBindingItemTypes()
- {
- return _bindingItemTypes;
- }
-
- protected void setBindingItemTypes(OpenType[] bindingItemTypes)
- {
- _bindingItemTypes = bindingItemTypes;
- }
-
- protected CompositeType getBindingDataType()
- {
- return _bindingDataType;
- }
-
- protected void setBindingDataType(CompositeType bindingDataType)
- {
- _bindingDataType = bindingDataType;
- }
-
- protected TabularType getBindinglistDataType()
- {
- return _bindinglistDataType;
- }
-
- protected void setBindinglistDataType(TabularType bindinglistDataType)
- {
- _bindinglistDataType = bindinglistDataType;
- }
-}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/DefaultExchangeRegistry.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/DefaultExchangeRegistry.java
index bf4184bf0b..07813b073b 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/exchange/DefaultExchangeRegistry.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/exchange/DefaultExchangeRegistry.java
@@ -29,7 +29,9 @@ import org.apache.qpid.protocol.AMQConstant;
import org.apache.qpid.server.store.DurableConfigurationStore;
import org.apache.qpid.server.virtualhost.VirtualHost;
+import java.util.ArrayList;
import java.util.Collection;
+import java.util.Collections;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
@@ -46,6 +48,8 @@ public class DefaultExchangeRegistry implements ExchangeRegistry
private Exchange _defaultExchange;
private VirtualHost _host;
+ private final Collection<RegistryChangeListener> _listeners =
+ Collections.synchronizedCollection(new ArrayList<RegistryChangeListener>());
public DefaultExchangeRegistry(VirtualHost host)
{
@@ -68,6 +72,14 @@ public class DefaultExchangeRegistry implements ExchangeRegistry
{
_exchangeMap.put(exchange.getNameShortString(), exchange);
_exchangeMapStr.put(exchange.getNameShortString().toString(), exchange);
+ synchronized (_listeners)
+ {
+ for(RegistryChangeListener listener : _listeners)
+ {
+ listener.exchangeRegistered(exchange);
+ }
+
+ }
}
public void setDefaultExchange(Exchange exchange)
@@ -114,6 +126,15 @@ public class DefaultExchangeRegistry implements ExchangeRegistry
getDurableConfigurationStore().removeExchange(e);
}
e.close();
+
+ synchronized (_listeners)
+ {
+ for(RegistryChangeListener listener : _listeners)
+ {
+ listener.exchangeUnregistered(exchange);
+ }
+ }
+
}
else
{
@@ -126,6 +147,16 @@ public class DefaultExchangeRegistry implements ExchangeRegistry
unregisterExchange(new AMQShortString(name), inUse);
}
+ public Collection<Exchange> getExchanges()
+ {
+ return new ArrayList<Exchange>(_exchangeMap.values());
+ }
+
+ public void addRegistryChangeListener(RegistryChangeListener listener)
+ {
+ _listeners.add(listener);
+ }
+
public Exchange getExchange(AMQShortString name)
{
if ((name == null) || name.length() == 0)
@@ -158,16 +189,14 @@ public class DefaultExchangeRegistry implements ExchangeRegistry
{
final Exchange exchange = getExchange(exchangeName);
- if (exchange instanceof AbstractExchange)
+ //TODO: this is a bit of a hack, what if the listeners aren't aware
+ //that we are just unregistering the MBean because of HA, and aren't
+ //actually removing the exchange as such.
+ synchronized (_listeners)
{
- AbstractExchange abstractExchange = (AbstractExchange) exchange;
- try
+ for(RegistryChangeListener listener : _listeners)
{
- abstractExchange.getManagedObject().unregister();
- }
- catch (AMQException e)
- {
- LOGGER.warn("Failed to unregister mbean", e);
+ listener.exchangeUnregistered(exchange);
}
}
}
@@ -196,4 +225,21 @@ public class DefaultExchangeRegistry implements ExchangeRegistry
}
}
+ public boolean isReservedExchangeName(String name)
+ {
+ if (name == null || "".equals(name) || ExchangeDefaults.DEFAULT_EXCHANGE_NAME.asString().equals(name)
+ || name.startsWith("amq.") || name.startsWith("qpid."))
+ {
+ return true;
+ }
+ Collection<ExchangeType<? extends Exchange>> registeredTypes = _host.getExchangeFactory().getRegisteredTypes();
+ for (ExchangeType<? extends Exchange> type : registeredTypes)
+ {
+ if (type.getDefaultExchangeName().toString().equals(name))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/DirectExchange.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/DirectExchange.java
index af9322764a..92326412c1 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/exchange/DirectExchange.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/exchange/DirectExchange.java
@@ -127,11 +127,6 @@ public class DirectExchange extends AbstractExchange
super(TYPE);
}
- protected AbstractExchangeMBean createMBean() throws JMException
- {
- return new DirectExchangeMBean(this);
- }
-
public List<? extends BaseQueue> doRoute(InboundMessage payload)
{
diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/DirectExchangeMBean.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/DirectExchangeMBean.java
deleted file mode 100644
index 0bfaf7035d..0000000000
--- a/java/broker/src/main/java/org/apache/qpid/server/exchange/DirectExchangeMBean.java
+++ /dev/null
@@ -1,85 +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.exchange;
-
-import org.apache.qpid.management.common.mbeans.annotations.MBeanConstructor;
-import org.apache.qpid.management.common.mbeans.annotations.MBeanDescription;
-import org.apache.qpid.server.binding.Binding;
-
-import javax.management.JMException;
-import javax.management.openmbean.CompositeData;
-import javax.management.openmbean.CompositeDataSupport;
-import javax.management.openmbean.OpenDataException;
-import javax.management.openmbean.TabularData;
-import javax.management.openmbean.TabularDataSupport;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * MBean class implementing the management interfaces.
- */
-@MBeanDescription("Management Bean for Direct Exchange")
-final class DirectExchangeMBean extends AbstractExchangeMBean<DirectExchange>
-{
- @MBeanConstructor("Creates an MBean for AMQ direct exchange")
- public DirectExchangeMBean(final DirectExchange exchange) throws JMException
- {
- super(exchange);
-
- init();
- }
-
- public TabularData bindings() throws OpenDataException
- {
- TabularDataSupport bindingList = new TabularDataSupport(getBindinglistDataType());
-
- Map<String, List<String>> bindingMap = new HashMap<String, List<String>>();
-
- for (Binding binding : getExchange().getBindings())
- {
- String key = binding.getBindingKey();
- List<String> queueList = bindingMap.get(key);
- if(queueList == null)
- {
- queueList = new ArrayList<String>();
- bindingMap.put(key, queueList);
- }
- queueList.add(binding.getQueue().getNameShortString().toString());
-
- }
-
- for(Map.Entry<String, List<String>> entry : bindingMap.entrySet())
- {
- Object[] bindingItemValues = {entry.getKey(), entry.getValue().toArray(new String[0])};
- CompositeData bindingData = new CompositeDataSupport(getBindingDataType(),
- COMPOSITE_ITEM_NAMES.toArray(new String[COMPOSITE_ITEM_NAMES.size()]),
- bindingItemValues);
- bindingList.put(bindingData);
- }
-
- return bindingList;
- }
-
-
-
-}// End of MBean class
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 289cb1a923..762686e68d 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
@@ -147,4 +147,6 @@ public interface Exchange extends ExchangeReferrer, ExchangeConfig
{
public void onClose(Exchange exchange) throws AMQSecurityException, AMQInternalException;
}
+
+ UUID getId();
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/ExchangeRegistry.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/ExchangeRegistry.java
index 795ae2e140..4dcedb4797 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/exchange/ExchangeRegistry.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/exchange/ExchangeRegistry.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
@@ -57,4 +57,21 @@ public interface ExchangeRegistry
void clearAndUnregisterMbeans();
Exchange getExchange(UUID exchangeId);
+
+ Collection<Exchange> getExchanges();
+
+ void addRegistryChangeListener(RegistryChangeListener listener);
+
+ /**
+ * Validates the name of user custom exchange.
+ * <p>
+ * Return true if the exchange name is reserved and false otherwise.
+ */
+ boolean isReservedExchangeName(String name);
+
+ interface RegistryChangeListener
+ {
+ void exchangeRegistered(Exchange exchange);
+ void exchangeUnregistered(Exchange exchange);
+ }
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/FanoutExchange.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/FanoutExchange.java
index 5ebcfd095f..5f4998f77f 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/exchange/FanoutExchange.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/exchange/FanoutExchange.java
@@ -48,11 +48,6 @@ public class FanoutExchange extends AbstractExchange
*/
private final ConcurrentHashMap<AMQQueue,Integer> _queues = new ConcurrentHashMap<AMQQueue,Integer>();
- protected AbstractExchangeMBean createMBean() throws JMException
- {
- return new FanoutExchangeMBean(this);
- }
-
public static final ExchangeType<FanoutExchange> TYPE = new ExchangeType<FanoutExchange>()
{
diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/FanoutExchangeMBean.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/FanoutExchangeMBean.java
deleted file mode 100644
index 61e23c896c..0000000000
--- a/java/broker/src/main/java/org/apache/qpid/server/exchange/FanoutExchangeMBean.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.exchange;
-
-import org.apache.qpid.management.common.mbeans.annotations.MBeanConstructor;
-import org.apache.qpid.management.common.mbeans.annotations.MBeanDescription;
-import org.apache.qpid.server.binding.Binding;
-
-import javax.management.JMException;
-import javax.management.openmbean.CompositeData;
-import javax.management.openmbean.CompositeDataSupport;
-import javax.management.openmbean.OpenDataException;
-import javax.management.openmbean.TabularData;
-import javax.management.openmbean.TabularDataSupport;
-import java.util.ArrayList;
-
-/**
- * MBean class implementing the management interfaces.
- */
-@MBeanDescription("Management Bean for Fanout Exchange")
-final class FanoutExchangeMBean extends AbstractExchangeMBean<FanoutExchange>
-{
- private static final String BINDING_KEY_SUBSTITUTE = "*";
-
- @MBeanConstructor("Creates an MBean for AMQ fanout exchange")
- public FanoutExchangeMBean(final FanoutExchange exchange) throws JMException
- {
- super(exchange);
- init();
- }
-
- public TabularData bindings() throws OpenDataException
- {
-
- TabularDataSupport bindingList = new TabularDataSupport(getBindinglistDataType());
-
-
- ArrayList<String> queueNames = new ArrayList<String>();
-
- for (Binding binding : getExchange().getBindings())
- {
- String queueName = binding.getQueue().getNameShortString().toString();
- queueNames.add(queueName);
- }
-
- Object[] bindingItemValues = {BINDING_KEY_SUBSTITUTE, queueNames.toArray(new String[0])};
- CompositeData bindingData = new CompositeDataSupport(getBindingDataType(),
- COMPOSITE_ITEM_NAMES.toArray(new String[COMPOSITE_ITEM_NAMES.size()]),
- bindingItemValues);
- bindingList.put(bindingData);
-
- return bindingList;
- }
-
-
-} // End of MBean class
diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersExchange.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersExchange.java
index 16ba3c0431..6bad59c2ae 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersExchange.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersExchange.java
@@ -227,11 +227,6 @@ public class HeadersExchange extends AbstractExchange
return !getBindings().isEmpty();
}
- protected AbstractExchangeMBean createMBean() throws JMException
- {
- return new HeadersExchangeMBean(this);
- }
-
protected void onBind(final Binding binding)
{
String bindingKey = binding.getBindingKey();
diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersExchangeMBean.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersExchangeMBean.java
deleted file mode 100644
index 395c6c8a91..0000000000
--- a/java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersExchangeMBean.java
+++ /dev/null
@@ -1,158 +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.exchange;
-
-import org.apache.qpid.AMQException;
-import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpid.management.common.mbeans.annotations.MBeanConstructor;
-import org.apache.qpid.management.common.mbeans.annotations.MBeanDescription;
-import org.apache.qpid.server.binding.Binding;
-import org.apache.qpid.server.logging.actors.CurrentActor;
-import org.apache.qpid.server.logging.actors.ManagementActor;
-import org.apache.qpid.server.queue.AMQQueue;
-import org.apache.qpid.server.virtualhost.VirtualHost;
-
-import javax.management.JMException;
-import javax.management.MBeanException;
-import javax.management.openmbean.ArrayType;
-import javax.management.openmbean.CompositeData;
-import javax.management.openmbean.CompositeDataSupport;
-import javax.management.openmbean.CompositeType;
-import javax.management.openmbean.OpenDataException;
-import javax.management.openmbean.OpenType;
-import javax.management.openmbean.SimpleType;
-import javax.management.openmbean.TabularData;
-import javax.management.openmbean.TabularDataSupport;
-import javax.management.openmbean.TabularType;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * HeadersExchangeMBean class implements the management interface for the
- * Header Exchanges.
- */
-@MBeanDescription("Management Bean for Headers Exchange")
-final class HeadersExchangeMBean extends AbstractExchangeMBean<HeadersExchange>
-{
-
- @MBeanConstructor("Creates an MBean for AMQ Headers exchange")
- public HeadersExchangeMBean(final HeadersExchange headersExchange) throws JMException
- {
- super(headersExchange);
- init();
- }
-
- /**
- * initialises the OpenType objects.
- */
- protected void init() throws OpenDataException
- {
-
- setBindingItemTypes(new OpenType[3]);
- getBindingItemTypes()[0] = SimpleType.INTEGER;
- getBindingItemTypes()[1] = SimpleType.STRING;
- getBindingItemTypes()[2] = new ArrayType(1, SimpleType.STRING);
- setBindingDataType(new CompositeType("Exchange Binding", "Queue name and header bindings",
- HEADERS_COMPOSITE_ITEM_NAMES.toArray(new String[HEADERS_COMPOSITE_ITEM_NAMES.size()]),
- HEADERS_COMPOSITE_ITEM_DESC.toArray(new String[HEADERS_COMPOSITE_ITEM_DESC.size()]), getBindingItemTypes()));
- setBindinglistDataType(new TabularType("Exchange Bindings", "List of exchange bindings for " + getName(),
- getBindingDataType(), HEADERS_TABULAR_UNIQUE_INDEX.toArray(new String[HEADERS_TABULAR_UNIQUE_INDEX.size()])));
- }
-
- public TabularData bindings() throws OpenDataException
- {
- TabularDataSupport bindingList = new TabularDataSupport(getBindinglistDataType());
- int count = 1;
- for (Binding binding : getExchange().getBindings())
- {
-
- String queueName = binding.getQueue().getNameShortString().toString();
-
-
- Map<String,Object> headerMappings = binding.getArguments();
- final List<String> mappingList = new ArrayList<String>();
-
- if(headerMappings != null)
- {
- for(Map.Entry<String,Object> entry : headerMappings.entrySet())
- {
-
- mappingList.add(entry.getKey() + "=" + entry.getValue());
- }
- }
-
-
- Object[] bindingItemValues = {count++, queueName, mappingList.toArray(new String[0])};
- CompositeData bindingData = new CompositeDataSupport(getBindingDataType(),
- HEADERS_COMPOSITE_ITEM_NAMES.toArray(new String[HEADERS_COMPOSITE_ITEM_NAMES.size()]), bindingItemValues);
- bindingList.put(bindingData);
- }
-
- return bindingList;
- }
-
- @Override
- public void createNewBinding(String queueName, String binding) throws JMException
- {
- VirtualHost vhost = getExchange().getVirtualHost();
- AMQQueue queue = vhost.getQueueRegistry().getQueue(new AMQShortString(queueName));
- if (queue == null)
- {
- throw new JMException("Queue \"" + queueName + "\" is not registered with the virtualhost.");
- }
-
- CurrentActor.set(new ManagementActor(getLogActor().getRootMessageLogger()));
-
- final Map<String,Object> arguments = new HashMap<String, Object>();
- final String[] bindings = binding.split(",");
- for (int i = 0; i < bindings.length; i++)
- {
- final String[] keyAndValue = bindings[i].split("=");
- if (keyAndValue == null || keyAndValue.length == 0 || keyAndValue.length > 2 || keyAndValue[0].length() == 0)
- {
- throw new JMException("Format for headers binding should be \"<attribute1>=<value1>,<attribute2>=<value2>\" ");
- }
-
- if(keyAndValue.length == 1)
- {
- //no value was given, only a key. Use an empty value to signal match on key presence alone
- arguments.put(keyAndValue[0], "");
- }
- else
- {
- arguments.put(keyAndValue[0], keyAndValue[1]);
- }
- }
- try
- {
- vhost.getBindingFactory().addBinding(binding,queue,getExchange(),arguments);
- }
- catch (AMQException ex)
- {
- JMException jme = new JMException(ex.toString());
- throw new MBeanException(jme, "Error creating new binding " + binding);
- }
- CurrentActor.remove();
- }
-
-} // End of MBean class
diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/TopicExchange.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/TopicExchange.java
index 7ea7a41826..0ce16bd3f7 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/exchange/TopicExchange.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/exchange/TopicExchange.java
@@ -291,7 +291,7 @@ public class TopicExchange extends AbstractExchange
public boolean isBound(AMQShortString routingKey, FieldTable arguments, AMQQueue queue)
{
- Binding binding = new Binding(null, routingKey.toString(), queue, this, FieldTable.convertToMap(arguments));
+ Binding binding = new Binding(null, null, routingKey.toString(), queue, this, FieldTable.convertToMap(arguments));
if (arguments == null)
{
@@ -314,7 +314,7 @@ public class TopicExchange extends AbstractExchange
public boolean isBound(String bindingKey, Map<String, Object> arguments, AMQQueue queue)
{
- Binding binding = new Binding(null, bindingKey, queue, this, arguments);
+ Binding binding = new Binding(null, null, bindingKey, queue, this, arguments);
if (arguments == null)
{
return _bindings.containsKey(binding);
@@ -403,11 +403,6 @@ public class TopicExchange extends AbstractExchange
}
}
- protected AbstractExchangeMBean createMBean() throws JMException
- {
- return new TopicExchangeMBean(this);
- }
-
private Collection<AMQQueue> getMatchedQueues(InboundMessage message, AMQShortString routingKey)
{
diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/TopicExchangeMBean.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/TopicExchangeMBean.java
deleted file mode 100644
index 481a377fc4..0000000000
--- a/java/broker/src/main/java/org/apache/qpid/server/exchange/TopicExchangeMBean.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.server.exchange;
-
-import org.apache.qpid.management.common.mbeans.annotations.MBeanConstructor;
-import org.apache.qpid.management.common.mbeans.annotations.MBeanDescription;
-import org.apache.qpid.server.binding.Binding;
-
-import javax.management.JMException;
-import javax.management.openmbean.CompositeData;
-import javax.management.openmbean.CompositeDataSupport;
-import javax.management.openmbean.OpenDataException;
-import javax.management.openmbean.TabularData;
-import javax.management.openmbean.TabularDataSupport;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/** TopicExchangeMBean class implements the management interface for the Topic exchanges. */
-@MBeanDescription("Management Bean for Topic Exchange")
-final class TopicExchangeMBean extends AbstractExchangeMBean<TopicExchange>
-{
- private TopicExchange _topicExchange;
-
- @MBeanConstructor("Creates an MBean for AMQ topic exchange")
- public TopicExchangeMBean(final TopicExchange topicExchange) throws JMException
- {
- super(topicExchange);
- init();
- }
-
- /** returns exchange bindings in tabular form */
- public TabularData bindings() throws OpenDataException
- {
- TabularDataSupport bindingList = new TabularDataSupport(getBindinglistDataType());
- Map<String, List<String>> bindingData = new HashMap<String, List<String>>();
- for (Binding binding : getExchange().getBindings())
- {
- String key = binding.getBindingKey();
- List<String> queueNames = bindingData.get(key);
- if(queueNames == null)
- {
- queueNames = new ArrayList<String>();
- bindingData.put(key, queueNames);
- }
- queueNames.add(binding.getQueue().getNameShortString().toString());
-
- }
- for(Map.Entry<String, List<String>> entry : bindingData.entrySet())
- {
- Object[] bindingItemValues = {entry.getKey(), entry.getValue().toArray(new String[entry.getValue().size()]) };
- CompositeData bindingCompositeData =
- new CompositeDataSupport(getBindingDataType(),
- COMPOSITE_ITEM_NAMES.toArray(new String[COMPOSITE_ITEM_NAMES.size()]),
- bindingItemValues);
- bindingList.put(bindingCompositeData);
- }
-
- return bindingList;
- }
-
-} // End of MBean class
diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/topic/TopicMatcherDFAState.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/topic/TopicMatcherDFAState.java
index dfe4d85320..dad951c3ca 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/exchange/topic/TopicMatcherDFAState.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/exchange/topic/TopicMatcherDFAState.java
@@ -1,3 +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.
+ *
+ */
package org.apache.qpid.server.exchange.topic;
import org.apache.qpid.framing.AMQShortString;
@@ -16,26 +36,6 @@ import java.util.SortedSet;
import java.util.TreeSet;
import java.util.concurrent.atomic.AtomicInteger;
-/*
-*
-* Licensed to the Apache Software Foundation (ASF) under one
-* or more contributor license agreements. See the NOTICE file
-* distributed with this work for additional information
-* regarding copyright ownership. The ASF licenses this file
-* to you under the Apache License, Version 2.0 (the
-* "License"); you may not use this file except in compliance
-* with the License. You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing,
-* software distributed under the License is distributed on an
-* "AS IS" BASIS, WITHOUT 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 TopicMatcherDFAState
{
private static final AtomicInteger stateId = new AtomicInteger();
diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/topic/TopicMatcherResult.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/topic/TopicMatcherResult.java
index 71d30adfac..6084b18b31 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/exchange/topic/TopicMatcherResult.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/exchange/topic/TopicMatcherResult.java
@@ -1,5 +1,3 @@
-package org.apache.qpid.server.exchange.topic;
-
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
@@ -20,6 +18,8 @@ package org.apache.qpid.server.exchange.topic;
* under the License.
*
*/
+package org.apache.qpid.server.exchange.topic;
+
public interface TopicMatcherResult
{
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/topic/TopicParser.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/topic/TopicParser.java
index 1cb4301838..6f47e4e7f2 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/exchange/topic/TopicParser.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/exchange/topic/TopicParser.java
@@ -1,3 +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.
+ *
+ */
package org.apache.qpid.server.exchange.topic;
import org.apache.qpid.framing.AMQShortString;
@@ -13,26 +33,6 @@ import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;
-/*
-*
-* Licensed to the Apache Software Foundation (ASF) under one
-* or more contributor license agreements. See the NOTICE file
-* distributed with this work for additional information
-* regarding copyright ownership. The ASF licenses this file
-* to you under the Apache License, Version 2.0 (the
-* "License"); you may not use this file except in compliance
-* with the License. You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing,
-* software distributed under the License is distributed on an
-* "AS IS" BASIS, WITHOUT 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 TopicParser
{
private static final byte TOPIC_DELIMITER = (byte)'.';
diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/topic/TopicWord.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/topic/TopicWord.java
index b23b3db272..7345d30a0a 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/exchange/topic/TopicWord.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/exchange/topic/TopicWord.java
@@ -1,7 +1,3 @@
-package org.apache.qpid.server.exchange.topic;
-
-import org.apache.qpid.framing.AMQShortString;
-
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
@@ -22,6 +18,11 @@ import org.apache.qpid.framing.AMQShortString;
* under the License.
*
*/
+
+package org.apache.qpid.server.exchange.topic;
+
+import org.apache.qpid.framing.AMQShortString;
+
public final class TopicWord
{
public static final TopicWord ANY_WORD = new TopicWord("*");
diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/topic/TopicWordDictionary.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/topic/TopicWordDictionary.java
index 65a0cd3107..181c26dd66 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/exchange/topic/TopicWordDictionary.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/exchange/topic/TopicWordDictionary.java
@@ -1,9 +1,3 @@
-package org.apache.qpid.server.exchange.topic;
-
-import org.apache.qpid.framing.AMQShortString;
-
-import java.util.concurrent.ConcurrentHashMap;
-
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
@@ -24,6 +18,12 @@ import java.util.concurrent.ConcurrentHashMap;
* under the License.
*
*/
+package org.apache.qpid.server.exchange.topic;
+
+import org.apache.qpid.framing.AMQShortString;
+
+import java.util.concurrent.ConcurrentHashMap;
+
public class TopicWordDictionary
{
private final ConcurrentHashMap<AMQShortString,TopicWord> _dictionary =
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 c7046f8e53..7eb476b15a 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
@@ -91,7 +91,7 @@ public class Bridge implements BridgeConfig
private final String _tag;
private final String _excludes;
private final BrokerLink _link;
- private UUID _id;
+ private UUID _qmfId;
private long _createTime = System.currentTimeMillis();
private Session _session;
@@ -124,7 +124,7 @@ public class Bridge implements BridgeConfig
_key = key;
_tag = tag;
_excludes = excludes;
- _id = durable ? brokerLink.getConfigStore().createPersistentId() : brokerLink.getConfigStore().createId();
+ _qmfId = durable ? brokerLink.getConfigStore().createPersistentId() : brokerLink.getConfigStore().createId();
_transaction = new AutoCommitTransaction(getVirtualHost().getMessageStore());
@@ -198,7 +198,7 @@ public class Bridge implements BridgeConfig
{
_link = brokerLink;
_bridgeNo = bridgeNo;
- _id = id;
+ _qmfId = id;
brokerLink.getConfigStore().persistentIdInUse(id);
_createTime = createTime;
@@ -249,9 +249,10 @@ public class Bridge implements BridgeConfig
return Collections.unmodifiableMap(arguments);
}
- public UUID getId()
+ @Override
+ public UUID getQMFId()
{
- return _id;
+ return _qmfId;
}
public BridgeConfigType getConfigType()
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 4bcc0d6136..1ef57c53cb 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
@@ -89,7 +89,7 @@ public class BrokerLink implements LinkConfig, ConnectionListener
private final String _username;
private final String _password;
private final VirtualHost _virtualHost;
- private UUID _id;
+ private UUID _qmfId;
private AtomicBoolean _closing = new AtomicBoolean();
private final long _createTime;
private Connection _qpidConnection;
@@ -133,7 +133,7 @@ public class BrokerLink implements LinkConfig, ConnectionListener
private class ConnectionConfigAdapter implements ConnectionConfig
{
private long _adapterCreateTime = System.currentTimeMillis();
- private UUID _id = BrokerLink.this.getConfigStore().createId();
+ private UUID _qmfId = BrokerLink.this.getConfigStore().createId();
public VirtualHost getVirtualHost()
{
@@ -185,9 +185,10 @@ public class BrokerLink implements LinkConfig, ConnectionListener
return getVirtualHost().getConfigStore();
}
- public UUID getId()
+ @Override
+ public UUID getQMFId()
{
- return _id;
+ return _qmfId;
}
public ConnectionConfigType getConfigType()
@@ -230,11 +231,11 @@ public class BrokerLink implements LinkConfig, ConnectionListener
}
};
- public BrokerLink(final VirtualHost virtualHost, UUID id, long createTime, Map<String, String> arguments)
+ public BrokerLink(final VirtualHost virtualHost, UUID qmfId, long createTime, Map<String, String> arguments)
{
_virtualHost = virtualHost;
- _id = id;
- virtualHost.getConfigStore().persistentIdInUse(id);
+ _qmfId = qmfId;
+ virtualHost.getConfigStore().persistentIdInUse(qmfId);
_createTime = createTime;
_transport = arguments.get(TRANSPORT);
@@ -289,7 +290,7 @@ public class BrokerLink implements LinkConfig, ConnectionListener
_authMechanism = authMechanism;
_username = username;
_password = password;
- _id = durable ? virtualHost.getConfigStore().createPersistentId() : virtualHost.getConfigStore().createId();
+ _qmfId = durable ? virtualHost.getConfigStore().createPersistentId() : virtualHost.getConfigStore().createId();
if(durable)
{
@@ -457,9 +458,10 @@ public class BrokerLink implements LinkConfig, ConnectionListener
return _remoteVhost;
}
- public UUID getId()
+ @Override
+ public UUID getQMFId()
{
- return _id;
+ return _qmfId;
}
public LinkConfigType getConfigType()
@@ -672,7 +674,7 @@ public class BrokerLink implements LinkConfig, ConnectionListener
public String toString()
{
return "BrokerLink{" +
- " _id=" + _id +
+ " _id=" + _qmfId +
", _transport='" + _transport + '\'' +
", _host='" + _host + '\'' +
", _port=" + _port +
diff --git a/java/broker/src/main/java/org/apache/qpid/server/flow/BytesOnlyCreditManager.java b/java/broker/src/main/java/org/apache/qpid/server/flow/BytesOnlyCreditManager.java
index 5a5ef5e6c5..be3a13d2d3 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/flow/BytesOnlyCreditManager.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/flow/BytesOnlyCreditManager.java
@@ -1,8 +1,3 @@
-package org.apache.qpid.server.flow;
-
-
-import java.util.concurrent.atomic.AtomicLong;
-
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
@@ -23,6 +18,11 @@ import java.util.concurrent.atomic.AtomicLong;
* under the License.
*
*/
+package org.apache.qpid.server.flow;
+
+
+import java.util.concurrent.atomic.AtomicLong;
+
public class BytesOnlyCreditManager extends AbstractFlowCreditManager
{
private final AtomicLong _bytesCredit;
diff --git a/java/broker/src/main/java/org/apache/qpid/server/flow/FlowCreditManager.java b/java/broker/src/main/java/org/apache/qpid/server/flow/FlowCreditManager.java
index 8a80262983..280f2851a4 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/flow/FlowCreditManager.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/flow/FlowCreditManager.java
@@ -1,6 +1,3 @@
-package org.apache.qpid.server.flow;
-
-
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
@@ -21,6 +18,10 @@ package org.apache.qpid.server.flow;
* under the License.
*
*/
+package org.apache.qpid.server.flow;
+
+
+
public interface FlowCreditManager
{
long getMessageCredit();
diff --git a/java/broker/src/main/java/org/apache/qpid/server/flow/FlowCreditManager_0_10.java b/java/broker/src/main/java/org/apache/qpid/server/flow/FlowCreditManager_0_10.java
index 48c336c0b1..fea6eaf744 100755
--- a/java/broker/src/main/java/org/apache/qpid/server/flow/FlowCreditManager_0_10.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/flow/FlowCreditManager_0_10.java
@@ -1,5 +1,3 @@
-package org.apache.qpid.server.flow;
-
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
@@ -20,6 +18,8 @@ package org.apache.qpid.server.flow;
* under the License.
*
*/
+package org.apache.qpid.server.flow;
+
public interface FlowCreditManager_0_10 extends FlowCreditManager
{
public void addCredit(long count, long bytes);
diff --git a/java/broker/src/main/java/org/apache/qpid/server/flow/LimitlessCreditManager.java b/java/broker/src/main/java/org/apache/qpid/server/flow/LimitlessCreditManager.java
index 6fcc687440..89fc60666b 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/flow/LimitlessCreditManager.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/flow/LimitlessCreditManager.java
@@ -1,6 +1,3 @@
-package org.apache.qpid.server.flow;
-
-
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
@@ -21,6 +18,9 @@ package org.apache.qpid.server.flow;
* under the License.
*
*/
+package org.apache.qpid.server.flow;
+
+
public class LimitlessCreditManager extends AbstractFlowCreditManager implements FlowCreditManager
{
public long getMessageCredit()
diff --git a/java/broker/src/main/java/org/apache/qpid/server/flow/MessageAndBytesCreditManager.java b/java/broker/src/main/java/org/apache/qpid/server/flow/MessageAndBytesCreditManager.java
index 0e6ce70a60..31c1fda968 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/flow/MessageAndBytesCreditManager.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/flow/MessageAndBytesCreditManager.java
@@ -1,6 +1,3 @@
-package org.apache.qpid.server.flow;
-
-
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
@@ -21,6 +18,9 @@ package org.apache.qpid.server.flow;
* under the License.
*
*/
+package org.apache.qpid.server.flow;
+
+
public class MessageAndBytesCreditManager extends AbstractFlowCreditManager implements FlowCreditManager
{
private long _messageCredit;
diff --git a/java/broker/src/main/java/org/apache/qpid/server/flow/MessageOnlyCreditManager.java b/java/broker/src/main/java/org/apache/qpid/server/flow/MessageOnlyCreditManager.java
index 9b7c40e923..1817e8ad31 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/flow/MessageOnlyCreditManager.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/flow/MessageOnlyCreditManager.java
@@ -1,8 +1,3 @@
-package org.apache.qpid.server.flow;
-
-
-import java.util.concurrent.atomic.AtomicLong;
-
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
@@ -23,6 +18,10 @@ import java.util.concurrent.atomic.AtomicLong;
* under the License.
*
*/
+package org.apache.qpid.server.flow;
+
+import java.util.concurrent.atomic.AtomicLong;
+
public class MessageOnlyCreditManager extends AbstractFlowCreditManager implements FlowCreditManager
{
private final AtomicLong _messageCredit;
diff --git a/java/broker/src/main/java/org/apache/qpid/server/handler/AccessRequestHandler.java b/java/broker/src/main/java/org/apache/qpid/server/handler/AccessRequestHandler.java
index e1c2782dec..84812485fd 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/handler/AccessRequestHandler.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/handler/AccessRequestHandler.java
@@ -1,4 +1,3 @@
-package org.apache.qpid.server.handler;
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
@@ -19,6 +18,7 @@ package org.apache.qpid.server.handler;
* under the License.
*
*/
+package org.apache.qpid.server.handler;
import org.apache.qpid.AMQException;
diff --git a/java/broker/src/main/java/org/apache/qpid/server/handler/BasicRecoverSyncMethodHandler.java b/java/broker/src/main/java/org/apache/qpid/server/handler/BasicRecoverSyncMethodHandler.java
index 1e0c0273df..43ee8da64f 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/handler/BasicRecoverSyncMethodHandler.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/handler/BasicRecoverSyncMethodHandler.java
@@ -1,4 +1,3 @@
-package org.apache.qpid.server.handler;
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
@@ -19,6 +18,7 @@ package org.apache.qpid.server.handler;
* under the License.
*
*/
+package org.apache.qpid.server.handler;
import org.apache.log4j.Logger;
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 2ccf97f17c..b8c8411c5d 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
@@ -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
@@ -61,7 +61,7 @@ public class ConnectionSecureOkMethodHandler implements StateAwareMethodListener
{
AMQProtocolSession session = stateManager.getProtocolSession();
- AuthenticationManager authMgr = ApplicationRegistry.getInstance().getAuthenticationManager();
+ AuthenticationManager authMgr = stateManager.getAuthenticationManager();
SaslServer ss = session.getSaslServer();
if (ss == null)
@@ -92,7 +92,7 @@ public class ConnectionSecureOkMethodHandler implements StateAwareMethodListener
case SUCCESS:
if (_logger.isInfoEnabled())
{
- _logger.info("Connected as: " + UsernamePrincipal.getUsernamePrincipalFromSubject(authResult.getSubject()));
+ _logger.info("Connected as: " + authResult.getSubject());
}
stateManager.changeState(AMQState.CONNECTION_NOT_TUNED);
@@ -102,7 +102,7 @@ public class ConnectionSecureOkMethodHandler implements StateAwareMethodListener
ApplicationRegistry.getInstance().getConfiguration().getHeartBeatDelay());
session.writeFrame(tuneBody.generateFrame(0));
session.setAuthorizedSubject(authResult.getSubject());
- disposeSaslServer(session);
+ disposeSaslServer(session);
break;
case CONTINUE:
stateManager.changeState(AMQState.CONNECTION_NOT_AUTH);
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 162e4e0215..a522b9f60f 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
@@ -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
@@ -61,15 +61,15 @@ public class ConnectionStartOkMethodHandler implements StateAwareMethodListener<
public void methodReceived(AMQStateManager stateManager, ConnectionStartOkBody body, int channelId) throws AMQException
{
AMQProtocolSession session = stateManager.getProtocolSession();
-
+
_logger.info("SASL Mechanism selected: " + body.getMechanism());
_logger.info("Locale selected: " + body.getLocale());
- AuthenticationManager authMgr = ApplicationRegistry.getInstance().getAuthenticationManager();
+ AuthenticationManager authMgr = stateManager.getAuthenticationManager();
SaslServer ss = null;
try
- {
- ss = authMgr.createSaslServer(String.valueOf(body.getMechanism()), session.getLocalFQDN());
+ {
+ ss = authMgr.createSaslServer(String.valueOf(body.getMechanism()), session.getLocalFQDN(), session.getPeerPrincipal());
if (ss == null)
{
@@ -106,7 +106,7 @@ public class ConnectionStartOkMethodHandler implements StateAwareMethodListener<
case SUCCESS:
if (_logger.isInfoEnabled())
{
- _logger.info("Connected as: " + UsernamePrincipal.getUsernamePrincipalFromSubject(authResult.getSubject()));
+ _logger.info("Connected as: " + authResult.getSubject());
}
session.setAuthorizedSubject(authResult.getSubject());
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 396829df91..ae725b9ec1 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
@@ -225,7 +225,10 @@ public class QueueDeclareHandler implements StateAwareMethodListener<QueueDeclar
String owner = body.getExclusive() ? AMQShortString.toString(session.getContextKey()) : null;
Map<String, Object> arguments = FieldTable.convertToMap(body.getArguments());
- final AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateUUID(), AMQShortString.toString(queueName), body.getDurable(), owner, body.getAutoDelete(),
+ String queueNameString = AMQShortString.toString(queueName);
+
+ final AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateQueueUUID(queueNameString, virtualHost.getName()),
+ queueNameString, body.getDurable(), owner, body.getAutoDelete(),
body.getExclusive(),virtualHost, arguments);
if (body.getExclusive() && !body.getDurable())
diff --git a/java/broker/src/main/java/org/apache/qpid/server/handler/QueueUnbindHandler.java b/java/broker/src/main/java/org/apache/qpid/server/handler/QueueUnbindHandler.java
index a8ae2099cc..66a6ff6527 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/handler/QueueUnbindHandler.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/handler/QueueUnbindHandler.java
@@ -1,4 +1,3 @@
-package org.apache.qpid.server.handler;
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
@@ -19,6 +18,7 @@ package org.apache.qpid.server.handler;
* under the License.
*
*/
+package org.apache.qpid.server.handler;
import org.apache.log4j.Logger;
diff --git a/java/broker/src/main/java/org/apache/qpid/server/handler/TxCommitHandler.java b/java/broker/src/main/java/org/apache/qpid/server/handler/TxCommitHandler.java
index 6e8896a023..afa5fdb72a 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/handler/TxCommitHandler.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/handler/TxCommitHandler.java
@@ -46,9 +46,9 @@ public class TxCommitHandler implements StateAwareMethodListener<TxCommitBody>
{
}
- public void methodReceived(AMQStateManager stateManager, TxCommitBody body, int channelId) throws AMQException
+ public void methodReceived(AMQStateManager stateManager, TxCommitBody body, final int channelId) throws AMQException
{
- AMQProtocolSession session = stateManager.getProtocolSession();
+ final AMQProtocolSession session = stateManager.getProtocolSession();
try
{
@@ -62,11 +62,19 @@ public class TxCommitHandler implements StateAwareMethodListener<TxCommitBody>
{
throw body.getChannelNotFoundException(channelId);
}
- channel.commit();
+ channel.commit(new Runnable()
+ {
+
+ @Override
+ public void run()
+ {
+ MethodRegistry methodRegistry = session.getMethodRegistry();
+ AMQMethodBody responseBody = methodRegistry.createTxCommitOkBody();
+ session.writeFrame(responseBody.generateFrame(channelId));
+ }
+ }, true);
+
- MethodRegistry methodRegistry = session.getMethodRegistry();
- AMQMethodBody responseBody = methodRegistry.createTxCommitOkBody();
- session.writeFrame(responseBody.generateFrame(channelId));
}
catch (AMQException e)
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
deleted file mode 100644
index 4d395f625a..0000000000
--- a/java/broker/src/main/java/org/apache/qpid/server/information/management/ServerInformationMBean.java
+++ /dev/null
@@ -1,145 +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.information.management;
-
-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;
-import java.io.IOException;
-
-/** MBean class for the ServerInformationMBean. */
-@MBeanDescription("Server Information Interface")
-public class ServerInformationMBean extends AMQManagedObject implements ServerInformation
-{
- private String buildVersion;
- private String productVersion;
- private ApplicationRegistry registry;
-
- public ServerInformationMBean(ApplicationRegistry applicationRegistry) throws JMException
- {
- super(ServerInformation.class, ServerInformation.TYPE);
-
- registry = applicationRegistry;
- buildVersion = QpidProperties.getBuildVersion();
- productVersion = QpidProperties.getReleaseVersion();
- }
-
- public String getObjectInstanceName()
- {
- return ServerInformation.TYPE;
- }
-
- public Integer getManagementApiMajorVersion() throws IOException
- {
- return QPID_JMX_API_MAJOR_VERSION;
- }
-
- public Integer getManagementApiMinorVersion() throws IOException
- {
- return QPID_JMX_API_MINOR_VERSION;
- }
-
- public String getBuildVersion() throws IOException
- {
- return buildVersion;
- }
-
- public String getProductVersion() throws IOException
- {
- 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/LogRecorder.java b/java/broker/src/main/java/org/apache/qpid/server/logging/LogRecorder.java
new file mode 100644
index 0000000000..a1065319d3
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/logging/LogRecorder.java
@@ -0,0 +1,210 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF 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.logging;
+
+import java.util.Iterator;
+import org.apache.log4j.Appender;
+import org.apache.log4j.Layout;
+import org.apache.log4j.Logger;
+import org.apache.log4j.spi.ErrorHandler;
+import org.apache.log4j.spi.Filter;
+import org.apache.log4j.spi.LoggingEvent;
+
+public class LogRecorder implements Appender, Iterable<LogRecorder.Record>
+{
+ private ErrorHandler _errorHandler;
+ private Filter _filter;
+ private String _name;
+ private long _recordId;
+
+ private final int _bufferSize = 4096;
+ private final int _mask = _bufferSize - 1;
+ private Record[] _records = new Record[_bufferSize];
+
+
+ public static class Record
+ {
+ private final long _id;
+ private final String _logger;
+ private final long _timestamp;
+ private final String _threadName;
+ private final String _level;
+ private final String _message;
+
+
+ public Record(long id, LoggingEvent event)
+ {
+ _id = id;
+ _logger = event.getLoggerName();
+ _timestamp = event.timeStamp;
+ _threadName = event.getThreadName();
+ _level = event.getLevel().toString();
+ _message = event.getRenderedMessage();
+ }
+
+ public long getId()
+ {
+ return _id;
+ }
+
+ public long getTimestamp()
+ {
+ return _timestamp;
+ }
+
+ public String getThreadName()
+ {
+ return _threadName;
+ }
+
+ public String getLevel()
+ {
+ return _level;
+ }
+
+ public String getMessage()
+ {
+ return _message;
+ }
+
+ public String getLogger()
+ {
+ return _logger;
+ }
+ }
+
+ public LogRecorder()
+ {
+
+ Logger.getRootLogger().addAppender(this);
+ }
+
+ @Override
+ public void addFilter(Filter filter)
+ {
+ _filter = filter;
+ }
+
+ @Override
+ public void clearFilters()
+ {
+ _filter = null;
+ }
+
+ @Override
+ public void close()
+ {
+ //TODO - Implement
+ }
+
+ @Override
+ public synchronized void doAppend(LoggingEvent loggingEvent)
+ {
+ _records[((int) (_recordId & _mask))] = new Record(_recordId, loggingEvent);
+ _recordId++;
+ }
+
+ @Override
+ public ErrorHandler getErrorHandler()
+ {
+ return _errorHandler;
+ }
+
+ @Override
+ public Filter getFilter()
+ {
+ return _filter;
+ }
+
+ @Override
+ public Layout getLayout()
+ {
+ return null;
+ }
+
+ @Override
+ public String getName()
+ {
+ return _name;
+ }
+
+ @Override
+ public boolean requiresLayout()
+ {
+ return false;
+ }
+
+ @Override
+ public void setErrorHandler(ErrorHandler errorHandler)
+ {
+ _errorHandler = errorHandler;
+ }
+
+ @Override
+ public void setLayout(Layout layout)
+ {
+
+ }
+
+ @Override
+ public void setName(String name)
+ {
+ _name = name;
+ }
+
+ @Override
+ public Iterator<Record> iterator()
+ {
+ return new RecordIterator(Math.max(_recordId-_bufferSize, 0l));
+ }
+
+ private class RecordIterator implements Iterator<Record>
+ {
+ private long _id;
+
+ public RecordIterator(long currentRecordId)
+ {
+ _id = currentRecordId;
+ }
+
+ @Override
+ public boolean hasNext()
+ {
+ return _id < _recordId;
+ }
+
+ @Override
+ public Record next()
+ {
+ Record record = _records[((int) (_id & _mask))];
+ while(_id < _recordId-_bufferSize)
+ {
+ _id = _recordId-_bufferSize;
+ record = _records[((int) (_id & _mask))];
+ }
+ _id++;
+ return record;
+ }
+
+ @Override
+ public void remove()
+ {
+ throw new UnsupportedOperationException();
+ }
+ }
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/logging/log4j/LoggingFacade.java b/java/broker/src/main/java/org/apache/qpid/server/logging/log4j/LoggingFacade.java
new file mode 100644
index 0000000000..931171b175
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/logging/log4j/LoggingFacade.java
@@ -0,0 +1,579 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.logging.log4j;
+
+import org.apache.log4j.Level;
+import org.apache.log4j.LogManager;
+import org.apache.log4j.Logger;
+import org.apache.log4j.xml.DOMConfigurator;
+import org.apache.log4j.xml.Log4jEntityResolver;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerConfigurationException;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Random;
+
+/**
+ * A facade over log4j that allows both the control of the runtime logging behaviour (that is, the ability to
+ * turn {@link Logger} on, off and control their {@link Level}, and the manipulation and reload
+ * of the log4j configuration file.
+ */
+public class LoggingFacade
+{
+ private static Logger LOGGER;
+ private static transient LoggingFacade _instance;
+ private final String _filename;
+ private final int _delay;
+
+ public static LoggingFacade configure(String filename) throws LoggingFacadeException
+ {
+ _instance = new LoggingFacade(filename);
+ return _instance;
+ }
+
+ public static LoggingFacade configureAndWatch(String filename, int delay) throws LoggingFacadeException
+ {
+ _instance = new LoggingFacade(filename, delay);
+ return _instance;
+ }
+
+ public static LoggingFacade getCurrentInstance()
+ {
+ return _instance;
+ }
+
+ private LoggingFacade(String filename)
+ {
+ DOMConfigurator.configure(filename);
+
+ if(LOGGER == null)
+ {
+ LOGGER = Logger.getLogger(LoggingFacade.class);
+ }
+ _filename = filename;
+ _delay = 0;
+ }
+
+ private LoggingFacade(String filename, int delay)
+ {
+ DOMConfigurator.configureAndWatch(filename, delay);
+
+ if(LOGGER == null)
+ {
+ LOGGER = Logger.getLogger(LoggingFacade.class);
+ }
+
+ _filename = filename;
+ _delay = delay;
+ }
+
+ public int getLog4jLogWatchInterval()
+ {
+ return _delay;
+ }
+
+ public synchronized void reload() throws LoggingFacadeException
+ {
+ DOMConfigurator.configure(_filename);
+ }
+
+ /** The log4j XML configuration file DTD defines three possible element
+ * combinations for specifying optional logger+level settings.
+ * Must account for the following:
+ *
+ * <category name="x"> <priority value="y"/> </category> OR
+ * <category name="x"> <level value="y"/> </category> OR
+ * <logger name="x"> <level value="y"/> </logger>
+ *
+ * Noting also that the level/priority child element is optional too,
+ * and not the only possible child element.
+ */
+ public synchronized Map<String,String> retrieveConfigFileLoggersLevels() throws LoggingFacadeException
+ {
+ try
+ {
+ Map<String,String> loggerLevelList = new HashMap<String,String>();
+ LOGGER.info("Getting logger levels from log4j configuration file");
+
+ Document doc = parseConfigFile(_filename);
+ List<Element> categoryOrLoggerElements = buildListOfCategoryOrLoggerElements(doc);
+
+ for (Element categoryOrLogger : categoryOrLoggerElements)
+ {
+
+ Element priorityOrLevelElement;
+ try
+ {
+ priorityOrLevelElement = getPriorityOrLevelElement(categoryOrLogger);
+ }
+ catch (LoggingFacadeException lfe)
+ {
+ //there is no exiting priority or level to view, move onto next category/logger
+ continue;
+ }
+
+ String categoryName = categoryOrLogger.getAttribute("name");
+ String priorityOrLevelValue = priorityOrLevelElement.getAttribute("value");
+ loggerLevelList.put(categoryName, priorityOrLevelValue);
+ }
+
+ return loggerLevelList;
+ }
+ catch (IOException e)
+ {
+ throw new LoggingFacadeException(e);
+ }
+ }
+
+ /**
+ * The log4j XML configuration file DTD defines 2 possible element
+ * combinations for specifying the optional root logger level settings
+ * Must account for the following:
+ *
+ * <root> <priority value="y"/> </root> OR
+ * <root> <level value="y"/> </root>
+ *
+ * Noting also that the level/priority child element is optional too,
+ * and not the only possible child element.
+ */
+ public synchronized String retrieveConfigFileRootLoggerLevel() throws LoggingFacadeException
+ {
+ try
+ {
+ Document doc = parseConfigFile(_filename);
+
+ //retrieve the optional 'root' element node
+ NodeList rootElements = doc.getElementsByTagName("root");
+
+ if (rootElements.getLength() == 0)
+ {
+ //there is no root logger definition
+ return "N/A";
+ }
+
+ Element rootElement = (Element) rootElements.item(0);
+ Element levelElement = getPriorityOrLevelElement(rootElement);
+
+ if(levelElement != null)
+ {
+ return levelElement.getAttribute("value");
+ }
+ else
+ {
+ return "N/A";
+ }
+ }
+ catch (IOException e)
+ {
+ throw new LoggingFacadeException(e);
+ }
+ }
+
+ public synchronized void setConfigFileLoggerLevel(String logger, String level) throws LoggingFacadeException
+ {
+ LOGGER.info("Setting level to " + level + " for logger '" + logger
+ + "' in log4j xml configuration file: " + _filename);
+
+ try
+ {
+ Document doc = parseConfigFile(_filename);
+
+ List<Element> logElements = buildListOfCategoryOrLoggerElements(doc);
+
+ //try to locate the specified logger/category in the elements retrieved
+ Element logElement = null;
+ for (Element e : logElements)
+ {
+ if (e.getAttribute("name").equals(logger))
+ {
+ logElement = e;
+ break;
+ }
+ }
+
+ if (logElement == null)
+ {
+ throw new LoggingFacadeException("Can't find logger " + logger);
+ }
+
+ Element levelElement = getPriorityOrLevelElement(logElement);
+
+ //update the element with the new level/priority
+ levelElement.setAttribute("value", level);
+
+ //output the new file
+ writeUpdatedConfigFile(_filename, doc);
+ }
+ catch (IOException ioe)
+ {
+ throw new LoggingFacadeException(ioe);
+ }
+ catch (TransformerConfigurationException e)
+ {
+ throw new LoggingFacadeException(e);
+ }
+ }
+
+ public synchronized void setConfigFileRootLoggerLevel(String level) throws LoggingFacadeException
+ {
+ try
+ {
+ LOGGER.info("Setting level to " + level + " for the Root logger in " +
+ "log4j xml configuration file: " + _filename);
+
+ Document doc = parseConfigFile(_filename);
+
+ //retrieve the optional 'root' element node
+ NodeList rootElements = doc.getElementsByTagName("root");
+
+ if (rootElements.getLength() == 0)
+ {
+ throw new LoggingFacadeException("Configuration contains no root element");
+ }
+
+ Element rootElement = (Element) rootElements.item(0);
+ Element levelElement = getPriorityOrLevelElement(rootElement);
+
+ //update the element with the new level/priority
+ levelElement.setAttribute("value", level);
+
+ //output the new file
+ writeUpdatedConfigFile(_filename, doc);
+ }
+ catch (IOException e)
+ {
+ throw new LoggingFacadeException(e);
+ }
+ catch (TransformerConfigurationException e)
+ {
+ throw new LoggingFacadeException(e);
+ }
+ }
+
+ public List<String> getAvailableLoggerLevels()
+ {
+ return new ArrayList<String>()
+ {{
+ add(Level.ALL.toString());
+ add(Level.TRACE.toString());
+ add(Level.DEBUG.toString());
+ add(Level.INFO.toString());
+ add(Level.WARN.toString());
+ add(Level.ERROR.toString());
+ add(Level.FATAL.toString());
+ add(Level.OFF.toString());
+ }};
+ }
+
+ public String retrieveRuntimeRootLoggerLevel()
+ {
+ Logger rootLogger = Logger.getRootLogger();
+ return rootLogger.getLevel().toString();
+ }
+
+ public void setRuntimeRootLoggerLevel(String level)
+ {
+ Level newLevel = Level.toLevel(level);
+
+ LOGGER.info("Setting RootLogger level to " + level);
+
+ Logger log = Logger.getRootLogger();
+ log.setLevel(newLevel);
+ }
+
+ public void setRuntimeLoggerLevel(String loggerName, String level) throws LoggingFacadeException
+ {
+ Level newLevel = level == null ? null : Level.toLevel(level);
+
+ Logger targetLogger = findRuntimeLogger(loggerName);
+
+ if(targetLogger == null)
+ {
+ throw new LoggingFacadeException("Can't find logger " + loggerName);
+ }
+
+ LOGGER.info("Setting level to " + newLevel + " for logger '" + targetLogger.getName() + "'");
+
+ targetLogger.setLevel(newLevel);
+ }
+
+ public Map<String,String> retrieveRuntimeLoggersLevels()
+ {
+ LOGGER.info("Getting levels for currently active log4j loggers");
+
+ Map<String, String> levels = new HashMap<String, String>();
+ @SuppressWarnings("unchecked")
+ Enumeration<Logger> loggers = LogManager.getCurrentLoggers();
+
+ while (loggers.hasMoreElements())
+ {
+ Logger logger = loggers.nextElement();
+ levels.put(logger.getName(), logger.getEffectiveLevel().toString());
+ }
+
+ return levels;
+ }
+
+ private void writeUpdatedConfigFile(String log4jConfigFileName, Document doc) throws IOException, TransformerConfigurationException
+ {
+ File log4jConfigFile = new File(log4jConfigFileName);
+
+ if (!log4jConfigFile.canWrite())
+ {
+ LOGGER.warn("Specified log4j XML configuration file is not writable: " + log4jConfigFile);
+ throw new IOException("Specified log4j XML configuration file is not writable");
+ }
+
+ Transformer transformer = null;
+ transformer = TransformerFactory.newInstance().newTransformer();
+
+ transformer.setOutputProperty(OutputKeys.INDENT, "yes");
+ transformer.setOutputProperty(OutputKeys.DOCTYPE_SYSTEM, "log4j.dtd");
+ DOMSource source = new DOMSource(doc);
+
+ File tmp;
+ Random r = new Random();
+
+ do
+ {
+ tmp = new File(log4jConfigFile.getAbsolutePath() + r.nextInt() + ".tmp");
+ }
+ while(tmp.exists());
+
+ tmp.deleteOnExit();
+
+ try
+ {
+ StreamResult result = new StreamResult(new FileOutputStream(tmp));
+ transformer.transform(source, result);
+ }
+ catch (TransformerException e)
+ {
+ LOGGER.warn("Could not transform the XML into new file: ", e);
+ throw new IOException("Could not transform the XML into new file: ", e);
+ }
+
+ // Swap temp file in to replace existing configuration file.
+ File old = new File(log4jConfigFile.getAbsoluteFile() + ".old");
+ if (old.exists())
+ {
+ old.delete();
+ }
+
+ if(!log4jConfigFile.renameTo(old))
+ {
+ //unable to rename the existing file to the backup name
+ LOGGER.error("Could not backup the existing log4j XML file");
+ throw new IOException("Could not backup the existing log4j XML file");
+ }
+
+ if(!tmp.renameTo(log4jConfigFile))
+ {
+ //failed to rename the new file to the required filename
+
+ if(!old.renameTo(log4jConfigFile))
+ {
+ //unable to return the backup to required filename
+ LOGGER.error("Could not rename the new log4j configuration file into place, and unable to restore original file");
+ throw new IOException("Could not rename the new log4j configuration file into place, and unable to restore original file");
+ }
+
+ LOGGER.error("Could not rename the new log4j configuration file into place");
+ throw new IOException("Could not rename the new log4j configuration file into place");
+ }
+ }
+
+ //method to parse the XML configuration file, validating it in the process, and returning a DOM Document of the content.
+ private static Document parseConfigFile(String fileName) throws IOException
+ {
+ //check file was specified, exists, and is readable
+ if(fileName == null)
+ {
+ LOGGER.warn("Provided log4j XML configuration filename is null");
+ throw new IOException("Provided log4j XML configuration filename is null");
+ }
+
+ File configFile = new File(fileName);
+
+ if (!configFile.exists())
+ {
+ LOGGER.warn("The log4j XML configuration file could not be found: " + fileName);
+ throw new IOException("The log4j XML configuration file could not be found");
+ }
+ else if (!configFile.canRead())
+ {
+ LOGGER.warn("The log4j XML configuration file is not readable: " + fileName);
+ throw new IOException("The log4j XML configuration file is not readable");
+ }
+
+ //parse it
+ DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
+ DocumentBuilder docBuilder;
+ Document doc;
+
+ ErrorHandler errHandler = new QpidLog4JSaxErrorHandler();
+ try
+ {
+ docFactory.setValidating(true);
+ docBuilder = docFactory.newDocumentBuilder();
+ docBuilder.setErrorHandler(errHandler);
+ docBuilder.setEntityResolver(new Log4jEntityResolver());
+ doc = docBuilder.parse(fileName);
+ }
+ catch (ParserConfigurationException e)
+ {
+ LOGGER.warn("Unable to parse the log4j XML file due to possible configuration error: ", e);
+ throw new IOException("Unable to parse the log4j XML file due to possible configuration error: ", e);
+ }
+ catch (SAXException e)
+ {
+ LOGGER.warn("The specified log4j XML file is invalid: ", e);
+ throw new IOException("The specified log4j XML file is invalid: ", e);
+ }
+ catch (IOException e)
+ {
+ LOGGER.warn("Unable to parse the specified log4j XML file", e);
+ throw new IOException("Unable to parse the specified log4j XML file: ", e);
+ }
+
+ return doc;
+ }
+
+ private Logger findRuntimeLogger(String loggerName)
+ {
+ Logger targetLogger = null;
+ @SuppressWarnings("unchecked")
+ Enumeration<Logger> loggers = LogManager.getCurrentLoggers();
+ while(loggers.hasMoreElements())
+ {
+ targetLogger = loggers.nextElement();
+ if (targetLogger.getName().equals(loggerName))
+ {
+ return targetLogger;
+ }
+ }
+ return null;
+ }
+
+ private List<Element> buildListOfCategoryOrLoggerElements(Document doc)
+ {
+ //retrieve the 'category' and 'logger' element nodes
+ NodeList categoryElements = doc.getElementsByTagName("category");
+ NodeList loggerElements = doc.getElementsByTagName("logger");
+
+ //collect them into a single elements list
+ List<Element> logElements = new ArrayList<Element>();
+
+ for (int i = 0; i < categoryElements.getLength(); i++)
+ {
+ logElements.add((Element) categoryElements.item(i));
+ }
+ for (int i = 0; i < loggerElements.getLength(); i++)
+ {
+ logElements.add((Element) loggerElements.item(i));
+ }
+ return logElements;
+ }
+
+ private Element getPriorityOrLevelElement(Element categoryOrLogger) throws LoggingFacadeException
+ {
+ //retrieve the optional 'priority' or 'level' sub-element value.
+ //It may not be the only child node, so request by tag name.
+ NodeList priorityElements = categoryOrLogger.getElementsByTagName("priority");
+ NodeList levelElements = categoryOrLogger.getElementsByTagName("level");
+
+ Element levelElement = null;
+ if (priorityElements.getLength() != 0)
+ {
+ levelElement = (Element) priorityElements.item(0);
+ }
+ else if (levelElements.getLength() != 0)
+ {
+ levelElement = (Element) levelElements.item(0);
+ }
+ else
+ {
+ throw new LoggingFacadeException("Configuration " + categoryOrLogger.getNodeName()
+ + " element contains neither priority nor level child");
+ }
+ return levelElement;
+ }
+
+ private static class QpidLog4JSaxErrorHandler implements ErrorHandler
+ {
+ public void error(SAXParseException e) throws SAXException
+ {
+ if(LOGGER != null)
+ {
+ LOGGER.warn(constructMessage("Error parsing XML file", e));
+ }
+ else
+ {
+ System.err.println(constructMessage("Error parsing XML file", e));
+ }
+ }
+
+ public void fatalError(SAXParseException e) throws SAXException
+ {
+ throw new SAXException(constructMessage("Fatal error parsing XML file", e));
+ }
+
+ public void warning(SAXParseException e) throws SAXException
+ {
+ if(LOGGER != null)
+ {
+ LOGGER.warn(constructMessage("Warning parsing XML file", e));
+ }
+ else
+ {
+ System.err.println(constructMessage("Warning parsing XML file", e));
+ }
+ }
+
+ private static String constructMessage(final String msg, final SAXParseException ex)
+ {
+ return msg + ": Line " + ex.getLineNumber()+" column " +ex.getColumnNumber() + ": " + ex.getMessage();
+ }
+ }
+}
+
diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/exceptions/InfoRequiredException.java b/java/broker/src/main/java/org/apache/qpid/server/logging/log4j/LoggingFacadeException.java
index 672426a59d..468b06be34 100644
--- a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/exceptions/InfoRequiredException.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/logging/log4j/LoggingFacadeException.java
@@ -1,5 +1,4 @@
/*
- *
* Licensed 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,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
@@ -18,19 +17,29 @@
* under the License.
*
*/
-package org.apache.qpid.management.ui.exceptions;
+package org.apache.qpid.server.logging.log4j;
-public class InfoRequiredException extends Exception
+public class LoggingFacadeException extends Exception
{
- private static final long serialVersionUID = 1L;
- public InfoRequiredException(String message)
+ public LoggingFacadeException()
+ {
+ super();
+ }
+
+ public LoggingFacadeException(String message, Throwable cause)
+ {
+ super(message, cause);
+ }
+
+ public LoggingFacadeException(String message)
{
super(message);
}
- public InfoRequiredException(String msg, Throwable t)
+ public LoggingFacadeException(Throwable cause)
{
- super(msg, t);
+ super(cause);
}
+
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/logging/management/LoggingManagementMBean.java b/java/broker/src/main/java/org/apache/qpid/server/logging/management/LoggingManagementMBean.java
deleted file mode 100644
index c699dff175..0000000000
--- a/java/broker/src/main/java/org/apache/qpid/server/logging/management/LoggingManagementMBean.java
+++ /dev/null
@@ -1,822 +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.logging.management;
-
-import org.apache.log4j.Level;
-import org.apache.log4j.LogManager;
-import org.apache.log4j.Logger;
-import org.apache.log4j.xml.Log4jEntityResolver;
-import org.apache.log4j.xml.QpidLog4JConfigurator;
-import org.apache.log4j.xml.QpidLog4JConfigurator.IllegalLoggerLevelException;
-import org.apache.log4j.xml.QpidLog4JConfigurator.QpidLog4JSaxErrorHandler;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.w3c.dom.NodeList;
-import org.xml.sax.ErrorHandler;
-import org.xml.sax.SAXException;
-
-import org.apache.qpid.management.common.mbeans.LoggingManagement;
-import org.apache.qpid.management.common.mbeans.annotations.MBeanDescription;
-import org.apache.qpid.server.management.AMQManagedObject;
-
-import javax.management.JMException;
-import javax.management.openmbean.CompositeData;
-import javax.management.openmbean.CompositeDataSupport;
-import javax.management.openmbean.CompositeType;
-import javax.management.openmbean.OpenDataException;
-import javax.management.openmbean.OpenType;
-import javax.management.openmbean.SimpleType;
-import javax.management.openmbean.TabularData;
-import javax.management.openmbean.TabularDataSupport;
-import javax.management.openmbean.TabularType;
-import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
-import javax.xml.parsers.ParserConfigurationException;
-import javax.xml.transform.OutputKeys;
-import javax.xml.transform.Transformer;
-import javax.xml.transform.TransformerException;
-import javax.xml.transform.TransformerFactory;
-import javax.xml.transform.dom.DOMSource;
-import javax.xml.transform.stream.StreamResult;
-import java.io.File;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Random;
-
-import static org.apache.log4j.xml.QpidLog4JConfigurator.LOCK;
-
-
-/** MBean class for BrokerLoggingManagerMBean. It implements all the management features exposed for managing logging. */
-@MBeanDescription("Logging Management Interface")
-public class LoggingManagementMBean extends AMQManagedObject implements LoggingManagement
-{
-
- private static final Logger _logger = Logger.getLogger(LoggingManagementMBean.class);
- private String _log4jConfigFileName;
- private int _log4jLogWatchInterval;
- private static final String INHERITED = "INHERITED";
- private static final String[] LEVELS = new String[]{Level.ALL.toString(), Level.TRACE.toString(),
- Level.DEBUG.toString(), Level.INFO.toString(),
- Level.WARN.toString(), Level.ERROR.toString(),
- Level.FATAL.toString(),Level.OFF.toString(),
- INHERITED};
- private static TabularType _loggerLevelTabularType;
- private static CompositeType _loggerLevelCompositeType;
-
- static
- {
- try
- {
- OpenType[] loggerLevelItemTypes = new OpenType[]{SimpleType.STRING, SimpleType.STRING};
-
- _loggerLevelCompositeType = new CompositeType("LoggerLevelList", "Logger Level Data",
- COMPOSITE_ITEM_NAMES.toArray(new String[COMPOSITE_ITEM_NAMES.size()]),
- COMPOSITE_ITEM_DESCRIPTIONS.toArray(new String[COMPOSITE_ITEM_DESCRIPTIONS.size()]),
- loggerLevelItemTypes);
-
- _loggerLevelTabularType = new TabularType("LoggerLevel", "List of loggers with levels",
- _loggerLevelCompositeType,
- TABULAR_UNIQUE_INDEX.toArray(new String[TABULAR_UNIQUE_INDEX.size()]));
- }
- catch (OpenDataException e)
- {
- _logger.error("Tabular data setup for viewing logger levels was incorrect.");
- _loggerLevelTabularType = null;
- }
- }
-
- public LoggingManagementMBean(String log4jConfigFileName, int log4jLogWatchInterval) throws JMException
- {
- super(LoggingManagement.class, LoggingManagement.TYPE);
- _log4jConfigFileName = log4jConfigFileName;
- _log4jLogWatchInterval = log4jLogWatchInterval;
- }
-
- public String getObjectInstanceName()
- {
- return LoggingManagement.TYPE;
- }
-
- public Integer getLog4jLogWatchInterval()
- {
- return _log4jLogWatchInterval;
- }
-
- public String[] getAvailableLoggerLevels()
- {
- return LEVELS;
- }
- @SuppressWarnings("unchecked")
- public synchronized boolean setRuntimeLoggerLevel(String logger, String level)
- {
- //check specified level is valid
- Level newLevel;
- try
- {
- newLevel = getLevel(level);
- }
- catch (Exception e)
- {
- return false;
- }
-
- //check specified logger exists
- Enumeration loggers = LogManager.getCurrentLoggers();
- Boolean loggerExists = false;
-
- while(loggers.hasMoreElements())
- {
- Logger log = (Logger) loggers.nextElement();
- if (log.getName().equals(logger))
- {
- loggerExists = true;
- break;
- }
- }
-
- if(!loggerExists)
- {
- return false;
- }
-
- //set the logger to the new level
- _logger.info("Setting level to " + level + " for logger: " + logger);
-
- Logger log = Logger.getLogger(logger);
- log.setLevel(newLevel);
-
- return true;
- }
-
- @SuppressWarnings("unchecked")
- public synchronized TabularData viewEffectiveRuntimeLoggerLevels()
- {
- if (_loggerLevelTabularType == null)
- {
- _logger.warn("TabluarData type not set up correctly");
- return null;
- }
-
- _logger.info("Getting levels for currently active log4j loggers");
-
- Enumeration loggers = LogManager.getCurrentLoggers();
-
- TabularData loggerLevelList = new TabularDataSupport(_loggerLevelTabularType);
-
- Logger logger;
- String loggerName;
- String level;
-
- try
- {
- while(loggers.hasMoreElements()){
- logger = (Logger) loggers.nextElement();
-
- loggerName = logger.getName();
- level = logger.getEffectiveLevel().toString();
-
- Object[] itemData = {loggerName, level};
- CompositeData loggerData = new CompositeDataSupport(_loggerLevelCompositeType,
- COMPOSITE_ITEM_NAMES.toArray(new String[COMPOSITE_ITEM_NAMES.size()]), itemData);
- loggerLevelList.put(loggerData);
- }
- }
- catch (OpenDataException e)
- {
- _logger.warn("Unable to create logger level list due to :" + e);
- return null;
- }
-
- return loggerLevelList;
-
- }
-
- public synchronized String getRuntimeRootLoggerLevel()
- {
- Logger rootLogger = Logger.getRootLogger();
-
- return rootLogger.getLevel().toString();
- }
-
- public synchronized boolean setRuntimeRootLoggerLevel(String level)
- {
- Level newLevel;
- try
- {
- newLevel = getLevel(level);
- }
- catch (Exception e)
- {
- return false;
- }
-
- if(newLevel == null)
- {
- //A null Level reference implies inheritance. Setting the runtime RootLogger
- //to null is catastrophic (and prevented by Log4J at startup and runtime anyway).
- return false;
- }
-
- _logger.info("Setting RootLogger level to " + level);
-
- Logger log = Logger.getRootLogger();
- log.setLevel(newLevel);
-
- return true;
- }
-
- //method to convert from a string to a log4j Level, throws exception if the given value is invalid
- private Level getLevel(String level) throws Exception
- {
- if("null".equalsIgnoreCase(level) || INHERITED.equalsIgnoreCase(level))
- {
- //the string "null" or "inherited" signals to inherit from a parent logger,
- //using a null Level reference for the logger.
- return null;
- }
-
- Level newLevel = Level.toLevel(level);
-
- //above Level.toLevel call returns a DEBUG Level if the request fails. Check the result.
- if (newLevel.equals(Level.DEBUG) && !(level.equalsIgnoreCase("debug")))
- {
- //received DEBUG but we did not ask for it, the Level request failed.
- throw new Exception("Invalid level name");
- }
-
- return newLevel;
- }
-
- //method to parse the XML configuration file, validating it in the process, and returning a DOM Document of the content.
- private static synchronized Document parseConfigFile(String fileName) throws IOException
- {
- try
- {
- LOCK.lock();
-
- //check file was specified, exists, and is readable
- if(fileName == null)
- {
- _logger.warn("Provided log4j XML configuration filename is null");
- throw new IOException("Provided log4j XML configuration filename is null");
- }
-
- File configFile = new File(fileName);
-
- if (!configFile.exists())
- {
- _logger.warn("The log4j XML configuration file could not be found: " + fileName);
- throw new IOException("The log4j XML configuration file could not be found");
- }
- else if (!configFile.canRead())
- {
- _logger.warn("The log4j XML configuration file is not readable: " + fileName);
- throw new IOException("The log4j XML configuration file is not readable");
- }
-
- //parse it
- DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
- DocumentBuilder docBuilder;
- Document doc;
-
- ErrorHandler errHandler = new QpidLog4JSaxErrorHandler();
- try
- {
- docFactory.setValidating(true);
- docBuilder = docFactory.newDocumentBuilder();
- docBuilder.setErrorHandler(errHandler);
- docBuilder.setEntityResolver(new Log4jEntityResolver());
- doc = docBuilder.parse(fileName);
- }
- catch (ParserConfigurationException e)
- {
- _logger.warn("Unable to parse the log4j XML file due to possible configuration error: " + e);
- //recommended that MBeans should use java.* and javax.* exceptions only
- throw new IOException("Unable to parse the log4j XML file due to possible configuration error: " + e.getMessage());
- }
- catch (SAXException e)
- {
- _logger.warn("The specified log4j XML file is invalid: " + e);
- //recommended that MBeans should use standard java.* and javax.* exceptions only
- throw new IOException("The specified log4j XML file is invalid: " + e.getMessage());
- }
- catch (IOException e)
- {
- _logger.warn("Unable to parse the specified log4j XML file" + e);
- throw new IOException("Unable to parse the specified log4j XML file: " + e.getMessage());
- }
-
- return doc;
- }
- finally
- {
- LOCK.unlock();
- }
- }
-
-
- private static synchronized boolean writeUpdatedConfigFile(String log4jConfigFileName, Document doc) throws IOException
- {
- try
- {
- LOCK.lock();
-
- File log4jConfigFile = new File(log4jConfigFileName);
-
- if (!log4jConfigFile.canWrite())
- {
- _logger.warn("Specified log4j XML configuration file is not writable: " + log4jConfigFile);
- throw new IOException("Specified log4j XML configuration file is not writable");
- }
-
- Transformer transformer = null;
- try
- {
- transformer = TransformerFactory.newInstance().newTransformer();
- }
- catch (Exception e)
- {
- _logger.warn("Could not create an XML transformer: " +e);
- return false;
- }
-
- transformer.setOutputProperty(OutputKeys.INDENT, "yes");
- transformer.setOutputProperty(OutputKeys.DOCTYPE_SYSTEM, "log4j.dtd");
- DOMSource source = new DOMSource(doc);
-
- File tmp;
- Random r = new Random();
- do
- {
- tmp = new File(log4jConfigFile.getPath() + r.nextInt() + ".tmp");
- }
- while(tmp.exists());
-
- tmp.deleteOnExit();
-
- try
- {
- StreamResult result = new StreamResult(tmp);
- transformer.transform(source, result);
- }
- catch (TransformerException e)
- {
- _logger.warn("Could not transform the XML into new file: " +e);
- throw new IOException("Could not transform the XML into new file: " +e);
- }
-
- // Swap temp file in to replace existing configuration file.
- File old = new File(log4jConfigFile.getAbsoluteFile() + ".old");
- if (old.exists())
- {
- old.delete();
- }
-
- if(!log4jConfigFile.renameTo(old))
- {
- //unable to rename the existing file to the backup name
- _logger.error("Could not backup the existing log4j XML file");
- throw new IOException("Could not backup the existing log4j XML file");
- }
-
- if(!tmp.renameTo(log4jConfigFile))
- {
- //failed to rename the new file to the required filename
-
- if(!old.renameTo(log4jConfigFile))
- {
- //unable to return the backup to required filename
- _logger.error("Could not rename the new log4j configuration file into place, and unable to restore original file");
- throw new IOException("Could not rename the new log4j configuration file into place, and unable to restore original file");
- }
-
- _logger.error("Could not rename the new log4j configuration file into place");
- throw new IOException("Could not rename the new log4j configuration file into place");
- }
-
- return true;
- }
- finally
- {
- LOCK.unlock();
- }
- }
-
-
- /* The log4j XML configuration file DTD defines three possible element
- * combinations for specifying optional logger+level settings.
- * Must account for the following:
- *
- * <category name="x"> <priority value="y"/> </category> OR
- * <category name="x"> <level value="y"/> </category> OR
- * <logger name="x"> <level value="y"/> </logger>
- *
- * Noting also that the level/priority child element is optional too,
- * and not the only possible child element.
- */
-
- public static synchronized Map<String,String> retrieveConfigFileLoggersLevels(String fileName) throws IOException
- {
- try
- {
- LOCK.lock();
-
- Document doc = parseConfigFile(fileName);
-
- HashMap<String,String> loggerLevelList = new HashMap<String,String>();
-
- //retrieve the 'category' element nodes
- NodeList categoryElements = doc.getElementsByTagName("category");
-
- String categoryName;
- String priority = null;
-
- for (int i = 0; i < categoryElements.getLength(); i++)
- {
- Element categoryElement = (Element) categoryElements.item(i);
- categoryName = categoryElement.getAttribute("name");
-
- //retrieve the category's mandatory 'priority' or 'level' element's value.
- //It may not be the only child node, so request by tag name.
- NodeList priorityElements = categoryElement.getElementsByTagName("priority");
- NodeList levelElements = categoryElement.getElementsByTagName("level");
-
- if (priorityElements.getLength() != 0)
- {
- Element priorityElement = (Element) priorityElements.item(0);
- priority = priorityElement.getAttribute("value");
- }
- else if (levelElements.getLength() != 0)
- {
- Element levelElement = (Element) levelElements.item(0);
- priority = levelElement.getAttribute("value");
- }
- else
- {
- //there is no exiting priority or level to view, move onto next category/logger
- continue;
- }
-
- loggerLevelList.put(categoryName, priority);
- }
-
- //retrieve the 'logger' element nodes
- NodeList loggerElements = doc.getElementsByTagName("logger");
-
- String loggerName;
- String level;
-
- for (int i = 0; i < loggerElements.getLength(); i++)
- {
- Element loggerElement = (Element) loggerElements.item(i);
- loggerName = loggerElement.getAttribute("name");
-
- //retrieve the logger's mandatory 'level' element's value
- //It may not be the only child node, so request by tag name.
- NodeList levelElements = loggerElement.getElementsByTagName("level");
-
- Element levelElement = (Element) levelElements.item(0);
- level = levelElement.getAttribute("value");
-
- loggerLevelList.put(loggerName, level);
- }
-
- return loggerLevelList;
- }
- finally
- {
- LOCK.unlock();
- }
- }
-
- public synchronized TabularData viewConfigFileLoggerLevels() throws IOException
- {
- try
- {
- LOCK.lock();
-
- if (_loggerLevelTabularType == null)
- {
- _logger.warn("TabluarData type not set up correctly");
- return null;
- }
-
- _logger.info("Getting logger levels from log4j configuration file");
-
- TabularData loggerLevelList = new TabularDataSupport(_loggerLevelTabularType);
-
- Map<String,String> levels = retrieveConfigFileLoggersLevels(_log4jConfigFileName);
-
- for (Map.Entry<String,String> entry : levels.entrySet())
- {
- String loggerName = entry.getKey();
- String level = entry.getValue();
-
- try
- {
- Object[] itemData = {loggerName, level.toUpperCase()};
- CompositeData loggerData = new CompositeDataSupport(_loggerLevelCompositeType,
- COMPOSITE_ITEM_NAMES.toArray(new String[COMPOSITE_ITEM_NAMES.size()]), itemData);
- loggerLevelList.put(loggerData);
- }
- catch (OpenDataException e)
- {
- _logger.warn("Unable to create logger level list due to :" + e);
- return null;
- }
- }
-
- return loggerLevelList;
- }
- finally
- {
- LOCK.unlock();
- }
- }
-
- public synchronized boolean setConfigFileLoggerLevel(String logger, String level) throws IOException
- {
- try
- {
- LOCK.lock();
-
- //check that the specified level is a valid log4j Level
- try
- {
- getLevel(level);
- }
- catch (Exception e)
- {
- //it isnt a valid level
- return false;
- }
-
- _logger.info("Setting level to " + level + " for logger '" + logger
- + "' in log4j xml configuration file: " + _log4jConfigFileName);
-
- Document doc = parseConfigFile(_log4jConfigFileName);
-
- //retrieve the 'category' and 'logger' element nodes
- NodeList categoryElements = doc.getElementsByTagName("category");
- NodeList loggerElements = doc.getElementsByTagName("logger");
-
- //collect them into a single elements list
- List<Element> logElements = new ArrayList<Element>();
-
- for (int i = 0; i < categoryElements.getLength(); i++)
- {
- logElements.add((Element) categoryElements.item(i));
- }
- for (int i = 0; i < loggerElements.getLength(); i++)
- {
- logElements.add((Element) loggerElements.item(i));
- }
-
- //try to locate the specified logger/category in the elements retrieved
- Element logElement = null;
- for (Element e : logElements)
- {
- if (e.getAttribute("name").equals(logger))
- {
- logElement = e;
- break;
- }
- }
-
- if (logElement == null)
- {
- //no loggers/categories with given name found, does not exist to update
- _logger.warn("Specified logger does not exist in the configuration file: " +logger);
- return false;
- }
-
- //retrieve the optional 'priority' or 'level' sub-element value.
- //It may not be the only child node, so request by tag name.
- NodeList priorityElements = logElement.getElementsByTagName("priority");
- NodeList levelElements = logElement.getElementsByTagName("level");
-
- Element levelElement = null;
- if (priorityElements.getLength() != 0)
- {
- levelElement = (Element) priorityElements.item(0);
- }
- else if (levelElements.getLength() != 0)
- {
- levelElement = (Element) levelElements.item(0);
- }
- else
- {
- //there is no exiting priority or level element to update
- return false;
- }
-
- //update the element with the new level/priority
- levelElement.setAttribute("value", level.toLowerCase());
-
- //output the new file
- return writeUpdatedConfigFile(_log4jConfigFileName, doc);
- }
- finally
- {
- LOCK.unlock();
- }
- }
-
-
- /* The log4j XML configuration file DTD defines 2 possible element
- * combinations for specifying the optional root logger level settings
- * Must account for the following:
- *
- * <root> <priority value="y"/> </root> OR
- * <root> <level value="y"/> </root>
- *
- * Noting also that the level/priority child element is optional too,
- * and not the only possible child element.
- */
-
- public static synchronized String retrieveConfigFileRootLoggerLevel(String fileName) throws IOException
- {
- try
- {
- LOCK.lock();
-
- Document doc = parseConfigFile(fileName);
-
- //retrieve the optional 'root' element node
- NodeList rootElements = doc.getElementsByTagName("root");
-
- if (rootElements.getLength() == 0)
- {
- //there is no root logger definition
- return "N/A";
- }
-
- Element rootElement = (Element) rootElements.item(0);
-
- //retrieve the optional 'priority' or 'level' element value.
- //It may not be the only child node, so request by tag name.
- NodeList priorityElements = rootElement.getElementsByTagName("priority");
- NodeList levelElements = rootElement.getElementsByTagName("level");
- String priority = null;
-
- if (priorityElements.getLength() != 0)
- {
- Element priorityElement = (Element) priorityElements.item(0);
- priority = priorityElement.getAttribute("value");
- }
- else if(levelElements.getLength() != 0)
- {
- Element levelElement = (Element) levelElements.item(0);
- priority = levelElement.getAttribute("value");
- }
-
- if(priority != null)
- {
- return priority;
- }
- else
- {
- return "N/A";
- }
- }
- finally
- {
- LOCK.unlock();
- }
- }
-
- public synchronized String getConfigFileRootLoggerLevel() throws IOException
- {
- return retrieveConfigFileRootLoggerLevel(_log4jConfigFileName).toUpperCase();
- }
-
- public synchronized boolean setConfigFileRootLoggerLevel(String level) throws IOException
- {
- try
- {
- LOCK.lock();
-
- //check that the specified level is a valid log4j Level
- try
- {
- Level newLevel = getLevel(level);
- if(newLevel == null)
- {
- //A null Level reference implies inheritance. Setting the config file RootLogger
- //to "null" or "inherited" just ensures it defaults to DEBUG at startup as Log4J
- //prevents this catastrophic situation at startup and runtime anyway.
- return false;
- }
- }
- catch (Exception e)
- {
- //it isnt a valid level
- return false;
- }
-
- _logger.info("Setting level to " + level + " for the Root logger in " +
- "log4j xml configuration file: " + _log4jConfigFileName);
-
- Document doc = parseConfigFile(_log4jConfigFileName);
-
- //retrieve the optional 'root' element node
- NodeList rootElements = doc.getElementsByTagName("root");
-
- if (rootElements.getLength() == 0)
- {
- return false;
- }
-
- Element rootElement = (Element) rootElements.item(0);
-
- //retrieve the optional 'priority' or 'level' sub-element value.
- //It may not be the only child node, so request by tag name.
- NodeList priorityElements = rootElement.getElementsByTagName("priority");
- NodeList levelElements = rootElement.getElementsByTagName("level");
-
- Element levelElement = null;
- if (priorityElements.getLength() != 0)
- {
- levelElement = (Element) priorityElements.item(0);
- }
- else if (levelElements.getLength() != 0)
- {
- levelElement = (Element) levelElements.item(0);
- }
- else
- {
- //there is no exiting priority/level to update
- return false;
- }
-
- //update the element with the new level/priority
- levelElement.setAttribute("value", level);
-
- //output the new file
- return writeUpdatedConfigFile(_log4jConfigFileName, doc);
- }
- finally
- {
- LOCK.unlock();
- }
- }
-
- public synchronized void reloadConfigFile() throws IOException
- {
- try
- {
- LOCK.lock();
-
- QpidLog4JConfigurator.configure(_log4jConfigFileName);
- _logger.info("Applied log4j configuration from: " + _log4jConfigFileName);
- }
- catch (IllegalLoggerLevelException e)
- {
- _logger.warn("The log4j configuration reload request was aborted: " + e);
- //recommended that MBeans should use standard java.* and javax.* exceptions only
- throw new IOException("The log4j configuration reload request was aborted: " + e.getMessage());
- }
- catch (ParserConfigurationException e)
- {
- _logger.warn("The log4j configuration reload request was aborted: " + e);
- throw new IOException("The log4j configuration reload request was aborted: " + e.getMessage());
- }
- catch (SAXException e)
- {
- _logger.warn("The log4j configuration reload request was aborted: " + e);
- //recommended that MBeans should use standard java.* and javax.* exceptions only
- throw new IOException("The log4j configuration reload request was aborted: " + e.getMessage());
- }
- catch (IOException e)
- {
- _logger.warn("The log4j configuration reload request was aborted: " + e);
- throw new IOException("The log4j configuration reload request was aborted: " + e.getMessage());
- }
- finally
- {
- LOCK.unlock();
- }
- }
-}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/logging/messages/MessageStore_logmessages.properties b/java/broker/src/main/java/org/apache/qpid/server/logging/messages/MessageStore_logmessages.properties
index 081f2bbca3..d3823a71a0 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/logging/messages/MessageStore_logmessages.properties
+++ b/java/broker/src/main/java/org/apache/qpid/server/logging/messages/MessageStore_logmessages.properties
@@ -26,3 +26,5 @@ RECOVERY_START = MST-1004 : Recovery Start
RECOVERED = MST-1005 : Recovered {0,number} messages
RECOVERY_COMPLETE = MST-1006 : Recovery Complete
PASSIVATE = MST-1007 : Store Passivated
+OVERFULL = MST-1008 : Store overfull, flow control will be enforced
+UNDERFULL = MST-1009 : Store overfull condition cleared
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..5695026cbc 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
@@ -23,4 +23,6 @@ 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
+STATS_MSGS = VHT-1004 : {0} : {1,choice,0#delivered|1#received} : {2,number,#.###} msg/s peak : {3,number,#} msgs total
+
+ERRORED = VHT-1005 : Unexpected fatal error \ No newline at end of file
diff --git a/java/broker/src/main/java/org/apache/qpid/server/management/AbstractAMQManagedConnectionObject.java b/java/broker/src/main/java/org/apache/qpid/server/management/AbstractAMQManagedConnectionObject.java
deleted file mode 100644
index 6cfc827046..0000000000
--- a/java/broker/src/main/java/org/apache/qpid/server/management/AbstractAMQManagedConnectionObject.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.server.management;
-
-import org.apache.qpid.management.common.mbeans.ManagedConnection;
-
-import javax.management.JMException;
-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.CompositeType;
-import javax.management.openmbean.OpenType;
-import javax.management.openmbean.SimpleType;
-import javax.management.openmbean.TabularType;
-
-public abstract class AbstractAMQManagedConnectionObject extends AMQManagedObject implements ManagedConnection
-{
- private final String _name;
-
- protected static final OpenType[] _channelAttributeTypes = { SimpleType.INTEGER, SimpleType.BOOLEAN, SimpleType.STRING, SimpleType.INTEGER, SimpleType.BOOLEAN };
- protected static final CompositeType _channelType;
- protected static final TabularType _channelsType;
-
- protected static final String BROKER_MANAGEMENT_CONSOLE_HAS_CLOSED_THE_CONNECTION_STR =
- "Broker Management Console has closed the connection.";
-
- static
- {
- try
- {
- _channelType = new CompositeType("Channel", "Channel Details", COMPOSITE_ITEM_NAMES_DESC.toArray(new String[COMPOSITE_ITEM_NAMES_DESC.size()]),
- COMPOSITE_ITEM_NAMES_DESC.toArray(new String[COMPOSITE_ITEM_NAMES_DESC.size()]), _channelAttributeTypes);
- _channelsType = new TabularType("Channels", "Channels", _channelType, (String[]) TABULAR_UNIQUE_INDEX.toArray(new String[TABULAR_UNIQUE_INDEX.size()]));
- }
- catch (JMException ex)
- {
- // This is not expected to ever occur.
- throw new RuntimeException("Got JMException in static initializer.", ex);
- }
- }
-
- protected AbstractAMQManagedConnectionObject(final String remoteAddress) throws NotCompliantMBeanException
- {
- super(ManagedConnection.class, ManagedConnection.TYPE);
- _name = "anonymous".equals(remoteAddress) ? (remoteAddress + hashCode()) : remoteAddress;
- }
-
- public String getObjectInstanceName()
- {
- return ObjectName.quote(_name);
- }
-
- public void notifyClients(String notificationMsg)
- {
- final Notification n = new Notification(MonitorNotification.THRESHOLD_VALUE_EXCEEDED, this, incrementAndGetSequenceNumber(),
- System.currentTimeMillis(), notificationMsg);
- getBroadcaster().sendNotification(n);
- }
-
- @Override
- public MBeanNotificationInfo[] getNotificationInfo()
- {
- String[] notificationTypes = new String[] { MonitorNotification.THRESHOLD_VALUE_EXCEEDED };
- String name = MonitorNotification.class.getName();
- String description = "Channel count has reached threshold value";
- MBeanNotificationInfo info1 = new MBeanNotificationInfo(notificationTypes, name, description);
-
- return new MBeanNotificationInfo[] { info1 };
- }
-}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/management/Managable.java b/java/broker/src/main/java/org/apache/qpid/server/management/Managable.java
deleted file mode 100644
index 166a2a376d..0000000000
--- a/java/broker/src/main/java/org/apache/qpid/server/management/Managable.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.server.management;
-
-/**
- * Any object that can return a related MBean should implement this interface.
- *
- * This enables other classes to get the managed object, which in turn is useful when
- * constructing relationships between managed objects without having to maintain
- * separate data structures containing MBeans.
- *
- */
-public interface Managable
-{
- ManagedObject getManagedObject();
-}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/message/AMQMessageHeader.java b/java/broker/src/main/java/org/apache/qpid/server/message/AMQMessageHeader.java
index faac14f8a7..63bd1e45a0 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/message/AMQMessageHeader.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/message/AMQMessageHeader.java
@@ -20,6 +20,7 @@
*/
package org.apache.qpid.server.message;
+import java.util.Collection;
import java.util.Set;
public interface AMQMessageHeader
@@ -28,6 +29,10 @@ public interface AMQMessageHeader
long getExpiration();
+ String getUserId();
+
+ String getAppId();
+
String getMessageId();
String getMimeType();
@@ -52,4 +57,5 @@ public interface AMQMessageHeader
boolean containsHeader(String name);
+ Collection<String> getHeaderNames();
}
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 e87b67d242..01c1021070 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
@@ -20,6 +20,7 @@
*/
package org.apache.qpid.server.message;
+import java.util.Collection;
import org.apache.qpid.framing.BasicContentHeaderProperties;
import org.apache.qpid.framing.ContentHeaderBody;
import org.apache.qpid.framing.FieldTable;
@@ -50,6 +51,16 @@ public class ContentHeaderBodyAdapter implements AMQMessageHeader
return getProperties().getExpiration();
}
+ public String getUserId()
+ {
+ return getProperties().getUserIdAsString();
+ }
+
+ public String getAppId()
+ {
+ return getProperties().getAppIdAsString();
+ }
+
public String getMessageId()
{
return getProperties().getMessageIdAsString();
@@ -117,6 +128,13 @@ public class ContentHeaderBodyAdapter implements AMQMessageHeader
return true;
}
+ @Override
+ public Collection<String> getHeaderNames()
+ {
+ FieldTable ft = getProperties().getHeaders();
+ return ft.keys();
+ }
+
public boolean containsHeader(String name)
{
FieldTable ft = getProperties().getHeaders();
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 583f0c09a7..e890bf5ef8 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
@@ -20,6 +20,7 @@
*/
package org.apache.qpid.server.message;
+import java.util.Collection;
import org.apache.qpid.AMQException;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.framing.BasicContentHeaderProperties;
@@ -242,6 +243,16 @@ public class MessageMetaData implements StorableMessageMetaData
return (BasicContentHeaderProperties) getContentHeaderBody().getProperties();
}
+ public String getUserId()
+ {
+ return getProperties().getUserIdAsString();
+ }
+
+ public String getAppId()
+ {
+ return getProperties().getAppIdAsString();
+ }
+
public String getCorrelationId()
{
return getProperties().getCorrelationIdAsString();
@@ -318,6 +329,12 @@ public class MessageMetaData implements StorableMessageMetaData
return true;
}
+ @Override
+ public Collection<String> getHeaderNames()
+ {
+ return getProperties().getHeaders().keys();
+ }
+
public boolean containsHeader(String name)
{
FieldTable ft = getProperties().getHeaders();
diff --git a/java/broker/src/main/java/org/apache/qpid/server/message/MessageMetaData_1_0.java b/java/broker/src/main/java/org/apache/qpid/server/message/MessageMetaData_1_0.java
index 7d030fe711..2cc1a92853 100755
--- a/java/broker/src/main/java/org/apache/qpid/server/message/MessageMetaData_1_0.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/message/MessageMetaData_1_0.java
@@ -21,11 +21,7 @@
package org.apache.qpid.server.message;
import java.nio.ByteBuffer;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
+import java.util.*;
import org.apache.qpid.amqp_1_0.codec.ValueHandler;
import org.apache.qpid.amqp_1_0.messaging.SectionDecoder;
import org.apache.qpid.amqp_1_0.type.AmqpErrorException;
@@ -486,6 +482,18 @@ public class MessageMetaData_1_0 implements StorableMessageMetaData
return null; //TODO
}
+ public String getAppId()
+ {
+ //TODO
+ return null;
+ }
+
+ public String getUserId()
+ {
+ // TODO
+ return null;
+ }
+
public Object getHeader(final String name)
{
return _appProperties == null ? null : _appProperties.get(name);
@@ -508,6 +516,16 @@ public class MessageMetaData_1_0 implements StorableMessageMetaData
return true;
}
+ @Override
+ public Collection<String> getHeaderNames()
+ {
+ if(_appProperties == null)
+ {
+ return Collections.emptySet();
+ }
+ return Collections.unmodifiableCollection(_appProperties.keySet());
+ }
+
public boolean containsHeader(final String name)
{
return _appProperties != null && _appProperties.containsKey(name);
diff --git a/java/broker/src/main/java/org/apache/qpid/server/message/MessageTransferHeader.java b/java/broker/src/main/java/org/apache/qpid/server/message/MessageTransferHeader.java
index 126e7c28cb..91384f7c22 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/message/MessageTransferHeader.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/message/MessageTransferHeader.java
@@ -20,14 +20,11 @@
*/
package org.apache.qpid.server.message;
+import java.util.*;
import org.apache.qpid.transport.DeliveryProperties;
import org.apache.qpid.transport.MessageDeliveryPriority;
import org.apache.qpid.transport.MessageProperties;
-import java.util.Map;
-import java.util.Set;
-import java.util.UUID;
-
class MessageTransferHeader implements AMQMessageHeader
{
@@ -60,10 +57,22 @@ class MessageTransferHeader implements AMQMessageHeader
return _deliveryProps == null ? 0L : _deliveryProps.getExpiration();
}
+ public String getUserId()
+ {
+ byte[] userIdBytes = _messageProps == null ? null : _messageProps.getUserId();
+ return userIdBytes == null ? null : new String(userIdBytes);
+ }
+
+ public String getAppId()
+ {
+ byte[] appIdBytes = _messageProps == null ? null : _messageProps.getAppId();
+ return appIdBytes == null ? null : new String(appIdBytes);
+ }
+
public String getMessageId()
{
UUID id = _messageProps == null ? null : _messageProps.getMessageId();
-
+
return id == null ? null : String.valueOf(id);
}
@@ -93,7 +102,7 @@ class MessageTransferHeader implements AMQMessageHeader
public String getType()
{
Object type = getHeader(JMS_TYPE);
- return type instanceof String ? (String) type : null;
+ return type instanceof String ? (String) type : null;
}
public String getReplyTo()
@@ -145,6 +154,14 @@ class MessageTransferHeader implements AMQMessageHeader
}
+ @Override
+ public Collection<String> getHeaderNames()
+ {
+ Map<String, Object> appHeaders = _messageProps == null ? null : _messageProps.getApplicationHeaders();
+ return appHeaders != null ? Collections.unmodifiableCollection(appHeaders.keySet()) : Collections.EMPTY_SET ;
+
+ }
+
public boolean containsHeader(String name)
{
Map<String, Object> appHeaders = _messageProps == null ? null : _messageProps.getApplicationHeaders();
diff --git a/java/broker/src/main/java/org/apache/qpid/server/model/Attribute.java b/java/broker/src/main/java/org/apache/qpid/server/model/Attribute.java
new file mode 100644
index 0000000000..4fccf47e0e
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/model/Attribute.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.server.model;
+
+public abstract class Attribute<C extends ConfiguredObject, T>
+{
+ private final String _name;
+ public Attribute(String name)
+ {
+ _name = name;
+ }
+
+ public String getName()
+ {
+ return _name;
+ }
+
+ abstract public Class<T> getType();
+
+ public T getValue(C configuredObject)
+ {
+ Object o = configuredObject.getAttribute(_name);
+ if(getType().isInstance(o))
+ {
+ return (T) o;
+ }
+ return null;
+ }
+
+ public T setValue(T expected, T desired, C configuredObject)
+ {
+ return (T) configuredObject.setAttribute(_name, expected, desired);
+ }
+
+ abstract public T setValue(String stringValue, C configuredObject);
+
+ static class StringAttribute<C extends ConfiguredObject> extends Attribute<C, String>
+ {
+
+ public StringAttribute(String name)
+ {
+ super(name);
+ }
+
+ @Override
+ public Class<String> getType()
+ {
+ return String.class;
+ }
+
+ @Override
+ public String setValue(String stringValue, C configuredObject)
+ {
+ return setValue(getValue(configuredObject), stringValue, configuredObject);
+ }
+
+ }
+
+ static class IntegerAttribute<C extends ConfiguredObject> extends Attribute<C, Integer>
+ {
+
+ public IntegerAttribute(String name)
+ {
+ super(name);
+ }
+
+ @Override
+ public Class<Integer> getType()
+ {
+ return Integer.class;
+ }
+
+ @Override
+ public Integer setValue(String stringValue, C configuredObject)
+ {
+ try
+ {
+ Integer val = Integer.valueOf(stringValue);
+ return setValue(getValue(configuredObject), val, configuredObject);
+ }
+ catch (NumberFormatException e)
+ {
+ throw new IllegalArgumentException(e);
+ }
+ }
+ }
+
+
+ static class LongAttribute<C extends ConfiguredObject> extends Attribute<C, Long>
+ {
+
+ public LongAttribute(String name)
+ {
+ super(name);
+ }
+
+ @Override
+ public Class<Long> getType()
+ {
+ return Long.class;
+ }
+
+ @Override
+ public Long setValue(String stringValue, C configuredObject)
+ {
+ try
+ {
+ Long val = Long.valueOf(stringValue);
+ return setValue(getValue(configuredObject), val, configuredObject);
+ }
+ catch (NumberFormatException e)
+ {
+ throw new IllegalArgumentException(e);
+ }
+ }
+ }
+
+
+ static class DoubleAttribute<C extends ConfiguredObject> extends Attribute<C, Double>
+ {
+
+ public DoubleAttribute(String name)
+ {
+ super(name);
+ }
+
+ @Override
+ public Class<Double> getType()
+ {
+ return Double.class;
+ }
+
+ @Override
+ public Double setValue(String stringValue, C configuredObject)
+ {
+ try
+ {
+ Double val = Double.valueOf(stringValue);
+ return setValue(getValue(configuredObject), val, configuredObject);
+ }
+ catch (NumberFormatException e)
+ {
+ throw new IllegalArgumentException(e);
+ }
+ }
+ }
+
+
+ static class FloatAttribute<C extends ConfiguredObject> extends Attribute<C, Float>
+ {
+
+ public FloatAttribute(String name)
+ {
+ super(name);
+ }
+
+ @Override
+ public Class<Float> getType()
+ {
+ return Float.class;
+ }
+
+ @Override
+ public Float setValue(String stringValue, C configuredObject)
+ {
+ try
+ {
+ Float val = Float.valueOf(stringValue);
+ return setValue(getValue(configuredObject), val, configuredObject);
+ }
+ catch (NumberFormatException e)
+ {
+ throw new IllegalArgumentException(e);
+ }
+ }
+ }
+
+
+
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/model/AuthenticationMethod.java b/java/broker/src/main/java/org/apache/qpid/server/model/AuthenticationMethod.java
new file mode 100644
index 0000000000..7a5927a365
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/model/AuthenticationMethod.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.server.model;
+
+import java.util.Collection;
+
+public interface AuthenticationMethod extends ConfiguredObject
+{
+ // name is the SASL mech where this is a SASL authentication
+
+ // parents
+ VirtualHostAlias getVirtualHostAlias();
+ AuthenticationProvider getAuthenticationProvider();
+
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/model/AuthenticationProvider.java b/java/broker/src/main/java/org/apache/qpid/server/model/AuthenticationProvider.java
new file mode 100644
index 0000000000..6000886956
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/model/AuthenticationProvider.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.server.model;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+
+public interface AuthenticationProvider extends ConfiguredObject
+{
+
+ public static final String ID = "id";
+ public static final String DESCRIPTION = "description";
+ public static final String NAME = "name";
+ public static final String STATE = "state";
+ public static final String DURABLE = "durable";
+ public static final String LIFETIME_POLICY = "lifetimePolicy";
+ public static final String TIME_TO_LIVE = "timeToLive";
+ public static final String CREATED = "created";
+ public static final String UPDATED = "updated";
+ public static final String TYPE = "type";
+
+ public static final Collection<String> AVAILABLE_ATTRIBUTES =
+ Collections.unmodifiableList(
+ Arrays.asList(ID,
+ NAME,
+ DESCRIPTION,
+ STATE,
+ DURABLE,
+ LIFETIME_POLICY,
+ TIME_TO_LIVE,
+ CREATED,
+ UPDATED,
+ TYPE));
+ //children
+ Collection<VirtualHostAlias> getVirtualHostPortBindings();
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/model/Broker.java b/java/broker/src/main/java/org/apache/qpid/server/model/Broker.java
new file mode 100644
index 0000000000..08b01a1b65
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/model/Broker.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.server.model;
+
+import java.security.AccessControlException;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Map;
+
+public interface Broker extends ConfiguredObject
+{
+
+ String BUILD_VERSION = "buildVersion";
+ String BYTES_RETAINED = "bytesRetained";
+ String OPERATING_SYSTEM = "operatingSystem";
+ String PLATFORM = "platform";
+ String PROCESS_PID = "processPid";
+ String PRODUCT_VERSION = "productVersion";
+ String SUPPORTED_STORE_TYPES = "supportedStoreTypes";
+ String CREATED = "created";
+ String DURABLE = "durable";
+ String ID = "id";
+ String LIFETIME_POLICY = "lifetimePolicy";
+ String NAME = "name";
+ String STATE = "state";
+ String TIME_TO_LIVE = "timeToLive";
+ String UPDATED = "updated";
+
+ // Attributes
+ public static final Collection<String> AVAILABLE_ATTRIBUTES =
+ Collections.unmodifiableList(
+ Arrays.asList(BUILD_VERSION,
+ BYTES_RETAINED,
+ OPERATING_SYSTEM,
+ PLATFORM,
+ PROCESS_PID,
+ PRODUCT_VERSION,
+ SUPPORTED_STORE_TYPES,
+ CREATED,
+ DURABLE,
+ ID,
+ LIFETIME_POLICY,
+ NAME,
+ STATE,
+ TIME_TO_LIVE,
+ UPDATED));
+
+ //children
+ Collection < VirtualHost > getVirtualHosts();
+
+ Collection<Port> getPorts();
+
+ Collection<AuthenticationProvider> getAuthenticationProviders();
+
+ VirtualHost createVirtualHost(String name, State initialState, boolean durable,
+ LifetimePolicy lifetime, long ttl, Map<String, Object> attributes)
+ throws AccessControlException, IllegalArgumentException;
+
+ void deleteVirtualHost(VirtualHost virtualHost)
+ throws AccessControlException, IllegalStateException;
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/model/ConfigurationChangeListener.java b/java/broker/src/main/java/org/apache/qpid/server/model/ConfigurationChangeListener.java
index 6477633a9b..78b98faffe 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/model/ConfigurationChangeListener.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/model/ConfigurationChangeListener.java
@@ -30,7 +30,8 @@ public interface ConfigurationChangeListener
* @param newState the state after the change
*/
void stateChanged(ConfiguredObject object, State oldState, State newState);
-
+
+
void childAdded(ConfiguredObject object, ConfiguredObject child);
void childRemoved(ConfiguredObject object, ConfiguredObject child);
diff --git a/java/broker/src/main/java/org/apache/qpid/server/model/ConfiguredObject.java b/java/broker/src/main/java/org/apache/qpid/server/model/ConfiguredObject.java
index fb47a54d0a..414b2d083a 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/model/ConfiguredObject.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/model/ConfiguredObject.java
@@ -22,6 +22,7 @@ package org.apache.qpid.server.model;
import java.security.AccessControlException;
import java.util.Collection;
+import java.util.Map;
import java.util.UUID;
public interface ConfiguredObject
@@ -81,7 +82,7 @@ public interface ConfiguredObject
* @param desiredState the state the caller wishes the object to attain
* @return the new current state
* @throws IllegalStateTransitionException the requested state tranisition is invalid
- * @throws AccessControlException the current context does not have sufficeint permissions to change the state
+ * @throws AccessControlException the current context does not have sufficient permissions to change the state
*/
State setDesiredState(State currentState, State desiredState) throws IllegalStateTransitionException,
AccessControlException;
@@ -89,7 +90,7 @@ public interface ConfiguredObject
/**
* Get the actual state of the object.
*
- * This state is derived fromt the desired state of the object itself and
+ * This state is derived from the desired state of the object itself and
* the actual state of its parents. If an object "desires" to be ACTIVE, but one of its parents is STOPPED, then
* the actual state of the object will be STOPPED
*
@@ -126,7 +127,7 @@ public interface ConfiguredObject
/**
* Returns whether the the object configuration is durably stored
*
- * @return the durablity
+ * @return the durability
*/
boolean isDurable();
@@ -188,7 +189,7 @@ public interface ConfiguredObject
/**
* Get the names of attributes that are set on this object
*
- * Not that the returned collection is correct at the time the method is called, but will not reflect future
+ * Note that the returned collection is correct at the time the method is called, but will not reflect future
* additions or removals when they occur
*
* @return the collection of attribute names
@@ -226,4 +227,20 @@ public interface ConfiguredObject
* @return the Statistics holder for the ConfiguredObject (or null if none exists)
*/
Statistics getStatistics();
+
+ /**
+ * Return children of the ConfiguredObject of the given class
+ *
+ * @param clazz the class of the children to return
+ * @return the children
+ *
+ * @throws NullPointerException if the supplied class null
+ *
+ */
+ <C extends ConfiguredObject> Collection<C> getChildren(Class<C> clazz);
+
+
+ <C extends ConfiguredObject> C createChild(Class<C> childClass,
+ Map<String, Object> attributes,
+ ConfiguredObject... otherParents);
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/store/MemoryMessageStoreFactory.java b/java/broker/src/main/java/org/apache/qpid/server/model/ConfiguredObjectFinder.java
index 8724f102c6..6a7d6f8f7b 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/store/MemoryMessageStoreFactory.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/model/ConfiguredObjectFinder.java
@@ -1,4 +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
@@ -17,21 +18,21 @@
* under the License.
*
*/
-package org.apache.qpid.server.store;
+package org.apache.qpid.server.model;
-public class MemoryMessageStoreFactory implements MessageStoreFactory
-{
+import java.util.Collection;
- @Override
- public MessageStore createMessageStore()
- {
- return new MemoryMessageStore();
- }
-
- @Override
- public String getStoreClassName()
+public class ConfiguredObjectFinder
+{
+ public static <C extends ConfiguredObject> C findConfiguredObjectByName(Collection<C> configuredObjects, String name)
{
- return MemoryMessageStore.class.getSimpleName();
+ for (C configuredObject : configuredObjects)
+ {
+ if (name.equals(configuredObject.getName()))
+ {
+ return configuredObject;
+ }
+ }
+ return null;
}
-
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/model/Connection.java b/java/broker/src/main/java/org/apache/qpid/server/model/Connection.java
new file mode 100644
index 0000000000..aaf6007afd
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/model/Connection.java
@@ -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.
+ *
+ */
+package org.apache.qpid.server.model;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+
+public interface Connection extends ConfiguredObject
+{
+
+ // Statistics
+
+ String BYTES_IN = "bytesIn";
+ String BYTES_OUT = "bytesOut";
+ String LAST_IO_TIME = "lastIoTime";
+ String LOCAL_TRANSACTION_BEGINS = "localTransactionBegins";
+ String LOCAL_TRANSACTION_ROLLBACKS = "localTransactionRollbacks";
+ String MESSAGES_IN = "messagesIn";
+ String MESSAGES_OUT = "messagesOut";
+ String SESSION_COUNT = "sessionCount";
+ String STATE_CHANGED = "stateChanged";
+ String XA_TRANSACTION_BRANCH_ENDS = "xaTransactionBranchEnds";
+ String XA_TRANSACTION_BRANCH_STARTS = "xaTransactionBranchStarts";
+ String XA_TRANSACTION_BRANCH_SUSPENDS = "xaTransactionBranchSuspends";
+
+ public static final Collection<String> AVAILABLE_STATISTICS =
+ Collections.unmodifiableCollection(
+ Arrays.asList(BYTES_IN,
+ BYTES_OUT,
+ LAST_IO_TIME,
+ LOCAL_TRANSACTION_BEGINS,
+ LOCAL_TRANSACTION_ROLLBACKS,
+ MESSAGES_IN,
+ MESSAGES_OUT,
+ SESSION_COUNT,
+ STATE_CHANGED,
+ XA_TRANSACTION_BRANCH_ENDS,
+ XA_TRANSACTION_BRANCH_STARTS,
+ XA_TRANSACTION_BRANCH_SUSPENDS));
+
+ // Attributes
+
+ public static final String ID = "id";
+ public static final String NAME = "name";
+ public static final String STATE = "state";
+ public static final String DURABLE = "durable";
+ public static final String LIFETIME_POLICY = "lifetimePolicy";
+ public static final String TIME_TO_LIVE = "timeToLive";
+ public static final String CREATED = "created";
+ public static final String UPDATED = "updated";
+
+ public static final String CLIENT_ID = "clientId";
+ public static final String CLIENT_VERSION = "clientVersion";
+ public static final String INCOMING = "incoming";
+ public static final String LOCAL_ADDRESS = "localAddress";
+ public static final String PRINCIPAL = "principal";
+ public static final String PROPERTIES = "properties";
+ public static final String REMOTE_ADDRESS = "remoteAddress";
+ public static final String REMOTE_PROCESS_NAME = "remoteProcessName";
+ public static final String REMOTE_PROCESS_PID = "remoteProcessPid";
+ public static final String SESSION_COUNT_LIMIT = "sessionCountLimit";
+
+ public static final Collection<String> AVAILABLE_ATTRIBUTES =
+ Collections.unmodifiableCollection(
+ Arrays.asList( ID,
+ NAME,
+ STATE,
+ DURABLE,
+ LIFETIME_POLICY,
+ TIME_TO_LIVE,
+ CREATED,
+ UPDATED,
+ CLIENT_ID,
+ CLIENT_VERSION,
+ INCOMING,
+ LOCAL_ADDRESS,
+ PRINCIPAL,
+ PROPERTIES,
+ REMOTE_ADDRESS,
+ REMOTE_PROCESS_NAME,
+ REMOTE_PROCESS_PID,
+ SESSION_COUNT_LIMIT));
+
+ //children
+ Collection<Session> getSessions();
+
+ void delete();
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/store/MessageStoreFactory.java b/java/broker/src/main/java/org/apache/qpid/server/model/Event.java
index a35db62b03..91b684f06e 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/store/MessageStoreFactory.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/model/Event.java
@@ -1,4 +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
@@ -17,11 +18,10 @@
* under the License.
*
*/
-package org.apache.qpid.server.store;
-public interface MessageStoreFactory
-{
- MessageStore createMessageStore();
+package org.apache.qpid.server.model;
- String getStoreClassName();
+abstract public class Event<T extends EventType>
+{
+ abstract public T getEventType();
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/model/EventType.java b/java/broker/src/main/java/org/apache/qpid/server/model/EventType.java
new file mode 100644
index 0000000000..edd5ce4250
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/model/EventType.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.server.model;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * A type of event generated by a ConfiguredObject.
+ */
+public abstract class EventType<T extends EventType<T>>
+{
+ private static final Map<Class<? extends EventType>, Integer> EVENT_TYPES =
+ new HashMap<Class<? extends EventType>, Integer>();
+
+ private final int _classId;
+
+ protected EventType()
+ {
+ synchronized (EVENT_TYPES)
+ {
+ if(EVENT_TYPES.containsKey(getClass()))
+ {
+ throw new IllegalArgumentException("Cannot define more one instance of the same EventType " +
+ getClass().getName());
+ }
+ else
+ {
+ _classId = EVENT_TYPES.size();
+ EVENT_TYPES.put(getClass(), _classId);
+ }
+ }
+ }
+
+ public final int getId()
+ {
+ return _classId;
+ }
+
+ abstract public Event<T> newEvent();
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/model/Exchange.java b/java/broker/src/main/java/org/apache/qpid/server/model/Exchange.java
index e872273d05..e63c71e955 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/model/Exchange.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/model/Exchange.java
@@ -77,7 +77,7 @@ public interface Exchange extends ConfiguredObject
//children
Collection<Binding> getBindings();
Collection<Publisher> getPublishers();
-
+
//operations
Binding createBinding(String bindingKey,
Queue queue,
diff --git a/java/broker/src/main/java/org/apache/qpid/server/model/Model.java b/java/broker/src/main/java/org/apache/qpid/server/model/Model.java
new file mode 100644
index 0000000000..fd429321c8
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/model/Model.java
@@ -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.
+ *
+ */
+
+package org.apache.qpid.server.model;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+public class Model
+{
+ private static final Map<Class<? extends ConfiguredObject>, Collection<Class<? extends ConfiguredObject>>>
+ PARENTS = new HashMap<Class<? extends ConfiguredObject>, Collection<Class<? extends ConfiguredObject>>>();
+
+
+ private static final Map<Class<? extends ConfiguredObject>, Collection<Class<? extends ConfiguredObject>>>
+ CHILDREN = new HashMap<Class<? extends ConfiguredObject>, Collection<Class<? extends ConfiguredObject>>>();
+
+ static void addRelationship(Class<? extends ConfiguredObject> parent, Class<? extends ConfiguredObject> child)
+ {
+ Collection<Class<? extends ConfiguredObject>> parents = PARENTS.get(child);
+ if(parents == null)
+ {
+ parents = new ArrayList<Class<? extends ConfiguredObject>>();
+ PARENTS.put(child, parents);
+ }
+ parents.add(parent);
+
+ Collection<Class<? extends ConfiguredObject>> children = CHILDREN.get(parent);
+ if(children == null)
+ {
+ children = new ArrayList<Class<? extends ConfiguredObject>>();
+ CHILDREN.put(parent, children);
+ }
+ children.add(child);
+ }
+
+ static
+ {
+ addRelationship(Broker.class, VirtualHost.class);
+ addRelationship(Broker.class, Port.class);
+ addRelationship(Broker.class, AuthenticationProvider.class);
+
+ addRelationship(VirtualHost.class, Exchange.class);
+ addRelationship(VirtualHost.class, Queue.class);
+ addRelationship(VirtualHost.class, Connection.class);
+ addRelationship(VirtualHost.class, VirtualHostAlias.class);
+
+ addRelationship(AuthenticationProvider.class, User.class);
+
+ addRelationship(Connection.class, Session.class);
+
+ addRelationship(Exchange.class, Binding.class);
+ addRelationship(Exchange.class, Publisher.class);
+
+ addRelationship(Queue.class, Binding.class);
+ addRelationship(Queue.class, Consumer.class);
+
+ addRelationship(Session.class, Consumer.class);
+ addRelationship(Session.class, Publisher.class);
+
+ }
+
+ public static Collection<Class<? extends ConfiguredObject>> getParentTypes(Class<? extends ConfiguredObject> child)
+ {
+ Collection<Class<? extends ConfiguredObject>> parentTypes = PARENTS.get(child);
+ return parentTypes == null ? Collections.EMPTY_LIST
+ : Collections.unmodifiableCollection(parentTypes);
+ }
+
+ public static Collection<Class<? extends ConfiguredObject>> getChildTypes(Class<? extends ConfiguredObject> parent)
+ {
+ Collection<Class<? extends ConfiguredObject>> childTypes = CHILDREN.get(parent);
+ return childTypes == null ? Collections.EMPTY_LIST
+ : Collections.unmodifiableCollection(childTypes);
+ }
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/model/PasswordCredentialManagingAuthenticationProvider.java b/java/broker/src/main/java/org/apache/qpid/server/model/PasswordCredentialManagingAuthenticationProvider.java
new file mode 100644
index 0000000000..1027e5ce8c
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/model/PasswordCredentialManagingAuthenticationProvider.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.server.model;
+
+import java.io.IOException;
+import java.util.Map;
+
+import javax.security.auth.login.AccountNotFoundException;
+
+public interface PasswordCredentialManagingAuthenticationProvider extends AuthenticationProvider
+{
+ boolean createUser(String username, String password, Map<String, String> attributes);
+
+ void deleteUser(String user) throws AccountNotFoundException;
+
+ void setPassword(String username, String password) throws AccountNotFoundException;
+
+ Map<String, Map<String,String>> getUsers();
+
+ /**
+ * Refreshes the cache of user and password data from the underlying storage.
+ *
+ * If there is a failure whilst reloading the data, the implementation must
+ * throw an {@link IOException} and revert to using the previous cached username
+ * and password data. In this way, the broker will remain usable.
+ */
+ void reload() throws IOException;
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/model/Port.java b/java/broker/src/main/java/org/apache/qpid/server/model/Port.java
new file mode 100644
index 0000000000..50c0ebcd14
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/model/Port.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.server.model;
+
+import java.security.AccessControlException;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+
+public interface Port extends ConfiguredObject
+{
+ String CREATED = "created";
+ String DURABLE = "durable";
+ String ID = "id";
+ String LIFETIME_POLICY = "lifetimePolicy";
+ String NAME = "name";
+ String STATE = "state";
+ String TIME_TO_LIVE = "timeToLive";
+ String UPDATED = "updated";
+ String BINDING_ADDRESS = "bindingAddress";
+ String PORT = "port";
+ String PROTOCOLS = "protocols";
+ String TRANSPORTS = "transports";
+
+ // Attributes
+ public static final Collection<String> AVAILABLE_ATTRIBUTES =
+ Collections.unmodifiableList(
+ Arrays.asList(
+ ID,
+ NAME,
+ STATE,
+ DURABLE,
+ LIFETIME_POLICY,
+ TIME_TO_LIVE,
+ CREATED,
+ UPDATED,
+ BINDING_ADDRESS,
+ PORT,
+ PROTOCOLS,
+ TRANSPORTS
+ ));
+
+
+ String getBindingAddress();
+
+ int getPort();
+
+ Collection<Transport> getTransports();
+
+ void addTransport(Transport transport) throws IllegalStateException,
+ AccessControlException,
+ IllegalArgumentException;
+
+ Transport removeTransport(Transport transport) throws IllegalStateException,
+ AccessControlException,
+ IllegalArgumentException;
+
+
+ Collection<Protocol> getProtocols();
+
+ void addProtocol(Protocol protocol) throws IllegalStateException,
+ AccessControlException,
+ IllegalArgumentException;
+
+ Protocol removeProtocol(Protocol protocol) throws IllegalStateException,
+ AccessControlException,
+ IllegalArgumentException;
+
+
+ //children
+ Collection<VirtualHostAlias> getVirtualHostBindings();
+ Collection<Connection> getConnections();
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/model/Protocol.java b/java/broker/src/main/java/org/apache/qpid/server/model/Protocol.java
new file mode 100644
index 0000000000..5d9de69f9a
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/model/Protocol.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.server.model;
+
+public enum Protocol
+{
+ AMQP_0_8,
+ AMQP_0_9,
+ AMQP_0_9_1,
+ AMQP_0_10,
+ AMQP_1_0,
+ JMX,
+ HTTP,
+ HTTPS
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/model/Queue.java b/java/broker/src/main/java/org/apache/qpid/server/model/Queue.java
index 7c4f0de22b..bf703e6fbe 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/model/Queue.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/model/Queue.java
@@ -25,7 +25,6 @@ import java.util.Collection;
import java.util.Collections;
import org.apache.qpid.server.queue.QueueEntryVisitor;
-
public interface Queue extends ConfiguredObject
{
public static final String BINDING_COUNT = "bindingCount";
@@ -71,6 +70,7 @@ public interface Queue extends ConfiguredObject
public static final String ID = "id";
+ public static final String DESCRIPTION = "description";
public static final String NAME = "name";
public static final String STATE = "state";
public static final String DURABLE = "durable";
@@ -78,6 +78,7 @@ public interface Queue extends ConfiguredObject
public static final String TIME_TO_LIVE = "timeToLive";
public static final String CREATED = "created";
public static final String UPDATED = "updated";
+ public static final String ARGUMENTS = "arguments";
public static final String ALERT_REPEAT_GAP = "alertRepeatGap";
public static final String ALERT_THRESHOLD_MESSAGE_AGE = "alertThresholdMessageAge";
@@ -98,7 +99,7 @@ public interface Queue extends ConfiguredObject
public static final String QUEUE_FLOW_STOPPED = "queueFlowStopped";
public static final String SORT_KEY = "sortKey";
public static final String TYPE = "type";
-
+ public static final String PRIORITIES = "priorities";
@@ -106,6 +107,7 @@ public interface Queue extends ConfiguredObject
Collections.unmodifiableList(
Arrays.asList(ID,
NAME,
+ DESCRIPTION,
STATE,
DURABLE,
LIFETIME_POLICY,
@@ -130,7 +132,8 @@ public interface Queue extends ConfiguredObject
ALERT_THRESHOLD_MESSAGE_SIZE,
ALERT_THRESHOLD_QUEUE_DEPTH_BYTES,
ALERT_THRESHOLD_QUEUE_DEPTH_MESSAGES,
- ALERT_REPEAT_GAP
+ ALERT_REPEAT_GAP,
+ PRIORITIES
));
//children
@@ -143,4 +146,6 @@ public interface Queue extends ConfiguredObject
void visit(QueueEntryVisitor visitor);
void delete();
+
+ void setNotificationListener(QueueNotificationListener listener);
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/QueueNotificationListener.java b/java/broker/src/main/java/org/apache/qpid/server/model/QueueNotificationListener.java
index 959ca03c80..ab601f685c 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/queue/QueueNotificationListener.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/model/QueueNotificationListener.java
@@ -18,10 +18,11 @@
* under the License.
*
*/
-package org.apache.qpid.server.queue;
+package org.apache.qpid.server.model;
+import org.apache.qpid.server.queue.NotificationCheck;
public interface QueueNotificationListener
{
- void notifyClients(NotificationCheck notification, AMQQueue queue, String notificationMsg);
+ void notifyClients(NotificationCheck notification, Queue queue, String notificationMsg);
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/model/QueueType.java b/java/broker/src/main/java/org/apache/qpid/server/model/QueueType.java
new file mode 100644
index 0000000000..96f2a7e2e5
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/model/QueueType.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.model;
+
+public enum QueueType
+{
+ STANDARD,
+ PRIORITY,
+ LVQ,
+ SORTED
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/model/Session.java b/java/broker/src/main/java/org/apache/qpid/server/model/Session.java
new file mode 100644
index 0000000000..e813d0c129
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/model/Session.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.server.model;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+
+public interface Session extends ConfiguredObject
+{
+ // Statistics
+
+ public static final String BYTES_IN = "bytesIn";
+ public static final String BYTES_OUT = "bytesOut";
+ public static final String CONSUMER_COUNT = "consumerCount";
+ public static final String LOCAL_TRANSACTION_BEGINS = "localTransactionBegins";
+ public static final String LOCAL_TRANSACTION_OPEN = "localTransactionOpen";
+ public static final String LOCAL_TRANSACTION_ROLLBACKS = "localTransactionRollbacks";
+ public static final String STATE_CHANGED = "stateChanged";
+ public static final String UNACKNOWLEDGED_BYTES = "unacknowledgedBytes";
+ public static final String UNACKNOWLEDGED_MESSAGES = "unacknowledgedMessages";
+ public static final String XA_TRANSACTION_BRANCH_ENDS = "xaTransactionBranchEnds";
+ public static final String XA_TRANSACTION_BRANCH_STARTS = "xaTransactionBranchStarts";
+ public static final String XA_TRANSACTION_BRANCH_SUSPENDS = "xaTransactionBranchSuspends";
+
+ public static final Collection<String> AVAILABLE_STATISTICS =
+ Collections.unmodifiableCollection(Arrays.asList(BYTES_IN, BYTES_OUT, CONSUMER_COUNT,
+ LOCAL_TRANSACTION_BEGINS,
+ LOCAL_TRANSACTION_OPEN,
+ LOCAL_TRANSACTION_ROLLBACKS, STATE_CHANGED,
+ UNACKNOWLEDGED_BYTES, UNACKNOWLEDGED_MESSAGES,
+ XA_TRANSACTION_BRANCH_ENDS, XA_TRANSACTION_BRANCH_STARTS,
+ XA_TRANSACTION_BRANCH_SUSPENDS));
+
+
+ public static final String ID = "id";
+ public static final String NAME = "name";
+ public static final String STATE = "state";
+ public static final String DURABLE = "durable";
+ public static final String LIFETIME_POLICY = "lifetimePolicy";
+ public static final String TIME_TO_LIVE = "timeToLive";
+ public static final String CREATED = "created";
+ public static final String UPDATED = "updated";
+
+ public static final String CHANNEL_ID = "channelId";
+ // PRODUCER_FLOW_BLOCKED is exposed as an interim step. We will expose attribute(s) that exposing
+ // available credit of both producer and consumer sides.
+ public static final String PRODUCER_FLOW_BLOCKED = "producerFlowBlocked";
+
+ public static final Collection<String> AVAILABLE_ATTRIBUTES =
+ Collections.unmodifiableCollection(Arrays.asList(ID,
+ NAME,
+ STATE,
+ DURABLE,
+ LIFETIME_POLICY,
+ TIME_TO_LIVE,
+ CREATED,
+ UPDATED,
+ CHANNEL_ID,
+ PRODUCER_FLOW_BLOCKED));
+
+ Collection<Consumer> getSubscriptions();
+ Collection<Publisher> getPublishers();
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/model/Statistics.java b/java/broker/src/main/java/org/apache/qpid/server/model/Statistics.java
index 2cb81eae82..92d6f47741 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/model/Statistics.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/model/Statistics.java
@@ -1,8 +1,4 @@
-package org.apache.qpid.server.model;
-
-import java.util.Collection;
-
-/**
+/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
@@ -18,6 +14,11 @@ import java.util.Collection;
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
+package org.apache.qpid.server.model;
+
+import java.util.Collection;
+
public interface Statistics
{
Collection<String> getStatisticNames();
diff --git a/java/broker/src/main/java/org/apache/qpid/server/model/Transport.java b/java/broker/src/main/java/org/apache/qpid/server/model/Transport.java
new file mode 100644
index 0000000000..03cd46be01
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/model/Transport.java
@@ -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.
+ *
+ */
+package org.apache.qpid.server.model;
+
+public enum Transport
+{
+ TCP,
+ SSL
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/model/UUIDGenerator.java b/java/broker/src/main/java/org/apache/qpid/server/model/UUIDGenerator.java
index d8493c6df4..36b6a454dc 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/model/UUIDGenerator.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/model/UUIDGenerator.java
@@ -22,33 +22,59 @@ package org.apache.qpid.server.model;
import java.util.UUID;
-import org.apache.qpid.exchange.ExchangeDefaults;
-
-
public class UUIDGenerator
{
-
- public static UUID generateUUID()
+ //Generates a random UUID. Used primarily by tests.
+ public static UUID generateRandomUUID()
{
return UUID.randomUUID();
}
- public static UUID generateUUID(String objectName, String virtualHostName)
+ private static UUID createUUID(String objectType, String... names)
{
StringBuilder sb = new StringBuilder();
- sb.append(virtualHostName).append(objectName);
+ sb.append(objectType);
+
+ for(String name : names)
+ {
+ sb.append("/").append(name);
+ }
+
return UUID.nameUUIDFromBytes(sb.toString().getBytes());
}
- public static UUID generateExchangeUUID(String echangeName, String virtualHostName)
+ public static UUID generateExchangeUUID(String exchangeName, String virtualHostName)
{
- if(ExchangeDefaults.DEFAULT_EXCHANGE_NAME.asString().equals(echangeName) || echangeName.startsWith("amq.") || echangeName.startsWith("qpid."))
- {
- return generateUUID(echangeName, virtualHostName);
- }
- else
- {
- return generateUUID();
- }
+ return createUUID(Exchange.class.getName(), virtualHostName, exchangeName);
+ }
+
+ public static UUID generateQueueUUID(String queueName, String virtualHostName)
+ {
+ return createUUID(Queue.class.getName(), virtualHostName, queueName);
+ }
+
+ public static UUID generateBindingUUID(String exchangeName, String queueName, String bindingKey, String virtualHostName)
+ {
+ return createUUID(Binding.class.getName(), virtualHostName, exchangeName, queueName, bindingKey);
+ }
+
+ public static UUID generateUserUUID(String authenticationProviderName, String userName)
+ {
+ return createUUID(User.class.getName(), authenticationProviderName, userName);
+ }
+
+ public static UUID generateVhostUUID(String virtualHostName)
+ {
+ return createUUID(VirtualHost.class.getName(), virtualHostName);
+ }
+
+ public static UUID generateVhostAliasUUID(String virtualHostName, String portName)
+ {
+ return createUUID(VirtualHostAlias.class.getName(), virtualHostName, portName);
+ }
+
+ public static UUID generateConsumerUUID(String virtualHostName, String queueName, String connectionRemoteAddress, String channelNumber, String consumerName)
+ {
+ return createUUID(Consumer.class.getName(), virtualHostName, queueName, connectionRemoteAddress, channelNumber, consumerName);
}
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/model/User.java b/java/broker/src/main/java/org/apache/qpid/server/model/User.java
new file mode 100644
index 0000000000..d97bf46d31
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/model/User.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.server.model;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+
+public interface User extends ConfiguredObject
+{
+ String CREATED = "created";
+ String DURABLE = "durable";
+ String ID = "id";
+ String LIFETIME_POLICY = "lifetimePolicy";
+ String NAME = "name";
+ String STATE = "state";
+ String TIME_TO_LIVE = "timeToLive";
+ String UPDATED = "updated";
+ String PASSWORD = "password";
+
+ // Attributes
+ public static final Collection<String> AVAILABLE_ATTRIBUTES =
+ Collections.unmodifiableList(
+ Arrays.asList(
+ ID,
+ NAME,
+ STATE,
+ DURABLE,
+ LIFETIME_POLICY,
+ TIME_TO_LIVE,
+ CREATED,
+ UPDATED,
+ PASSWORD
+ ));
+
+ public String getPassword();
+
+ public void setPassword(String password);
+
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/model/VirtualHost.java b/java/broker/src/main/java/org/apache/qpid/server/model/VirtualHost.java
new file mode 100644
index 0000000000..24a3d43386
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/model/VirtualHost.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.server.model;
+
+import org.apache.qpid.server.queue.QueueEntry;
+import java.security.AccessControlException;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Map;
+
+public interface VirtualHost extends ConfiguredObject
+{
+ // Statistics
+
+ public static final String BYTES_IN = "bytesIn";
+ public static final String BYTES_OUT = "bytesOut";
+ public static final String BYTES_RETAINED = "bytesRetained";
+ public static final String LOCAL_TRANSACTION_BEGINS = "localTransactionBegins";
+ public static final String LOCAL_TRANSACTION_ROLLBACKS = "localTransactionRollbacks";
+ public static final String MESSAGES_IN = "messagesIn";
+ public static final String MESSAGES_OUT = "messagesOut";
+ public static final String MESSAGES_RETAINED = "messagesRetained";
+ public static final String STATE_CHANGED = "stateChanged";
+ public static final String XA_TRANSACTION_BRANCH_ENDS = "xaTransactionBranchEnds";
+ public static final String XA_TRANSACTION_BRANCH_STARTS = "xaTransactionBranchStarts";
+ public static final String XA_TRANSACTION_BRANCH_SUSPENDS = "xaTransactionBranchSuspends";
+ public static final String QUEUE_COUNT = "queueCount";
+ public static final String EXCHANGE_COUNT = "exchangeCount";
+ public static final String CONNECTION_COUNT = "connectionCount";
+
+ public static final Collection<String> AVAILABLE_STATISTICS =
+ Collections.unmodifiableList(
+ Arrays.asList(BYTES_IN, BYTES_OUT, BYTES_RETAINED, LOCAL_TRANSACTION_BEGINS,
+ LOCAL_TRANSACTION_ROLLBACKS, MESSAGES_IN, MESSAGES_OUT, MESSAGES_RETAINED, STATE_CHANGED,
+ XA_TRANSACTION_BRANCH_ENDS, XA_TRANSACTION_BRANCH_STARTS, XA_TRANSACTION_BRANCH_SUSPENDS,
+ QUEUE_COUNT, EXCHANGE_COUNT, CONNECTION_COUNT));
+
+ String ALERT_REPEAT_GAP = "alertRepeatGap";
+ String ALERT_THRESHOLD_MESSAGE_AGE = "alertThresholdMessageAge";
+ String ALERT_THRESHOLD_MESSAGE_SIZE = "alertThresholdMessageSize";
+ String ALERT_THRESHOLD_QUEUE_DEPTH_BYTES = "alertThresholdQueueDepthBytes";
+ String ALERT_THRESHOLD_QUEUE_DEPTH_MESSAGES = "alertThresholdQueueDepthMessages";
+ String DEAD_LETTER_QUEUE_ENABLED = "deadLetterQueueEnabled";
+ String FEDERATION_TAG = "federationTag";
+ String HOUSEKEEPING_CHECK_PERIOD = "housekeepingCheckPeriod";
+ String MAXIMUM_DELIVERY_ATTEMPTS = "maximumDeliveryAttempts";
+ String QUEUE_FLOW_CONTROL_SIZE_BYTES = "queueFlowControlSizeBytes";
+ String QUEUE_FLOW_RESUME_SIZE_BYTES = "queueFlowResumeSizeBytes";
+ String STORE_CONFIGURATION = "storeConfiguration";
+ String STORE_TRANSACTION_IDLE_TIMEOUT_CLOSE = "storeTransactionIdleTimeoutClose";
+ String STORE_TRANSACTION_IDLE_TIMEOUT_WARN = "storeTransactionIdleTimeoutWarn";
+ String STORE_TRANSACTION_OPEN_TIMEOUT_CLOSE = "storeTransactionOpenTimeoutClose";
+ String STORE_TRANSACTION_OPEN_TIMEOUT_WARN = "storeTransactionOpenTimeoutWarn";
+ String STORE_TYPE = "storeType";
+ String SUPPORTED_EXCHANGE_TYPES = "supportedExchangeTypes";
+ String SUPPORTED_QUEUE_TYPES = "supportedQueueTypes";
+ String CREATED = "created";
+ String DURABLE = "durable";
+ String ID = "id";
+ String LIFETIME_POLICY = "lifetimePolicy";
+ String NAME = "name";
+ String STATE = "state";
+ String TIME_TO_LIVE = "timeToLive";
+ String UPDATED = "updated";
+ // Attributes
+ public static final Collection<String> AVAILABLE_ATTRIBUTES =
+ Collections.unmodifiableList(
+ Arrays.asList(
+ ID,
+ NAME,
+ STATE,
+ DURABLE,
+ LIFETIME_POLICY,
+ TIME_TO_LIVE,
+ CREATED,
+ UPDATED,
+ SUPPORTED_EXCHANGE_TYPES,
+ SUPPORTED_QUEUE_TYPES,
+ DEAD_LETTER_QUEUE_ENABLED,
+ FEDERATION_TAG,
+ HOUSEKEEPING_CHECK_PERIOD,
+ MAXIMUM_DELIVERY_ATTEMPTS,
+ QUEUE_FLOW_CONTROL_SIZE_BYTES,
+ QUEUE_FLOW_RESUME_SIZE_BYTES,
+ STORE_TYPE,
+ STORE_CONFIGURATION,
+ STORE_TRANSACTION_IDLE_TIMEOUT_CLOSE,
+ STORE_TRANSACTION_IDLE_TIMEOUT_WARN,
+ STORE_TRANSACTION_OPEN_TIMEOUT_CLOSE,
+ STORE_TRANSACTION_OPEN_TIMEOUT_WARN,
+ ALERT_REPEAT_GAP,
+ ALERT_THRESHOLD_MESSAGE_AGE,
+ ALERT_THRESHOLD_MESSAGE_SIZE,
+ ALERT_THRESHOLD_QUEUE_DEPTH_BYTES,
+ ALERT_THRESHOLD_QUEUE_DEPTH_MESSAGES));
+
+
+
+ String getReplicationGroupName();
+
+ //children
+ Collection<VirtualHostAlias> getAliases();
+ Collection<Connection> getConnections();
+ Collection<Queue> getQueues();
+ Collection<Exchange> getExchanges();
+
+ Exchange createExchange(String name, State initialState, boolean durable,
+ LifetimePolicy lifetime, long ttl, String type, Map<String, Object> attributes)
+ throws AccessControlException, IllegalArgumentException;
+
+ Queue createQueue(String name, State initialState, boolean durable,
+ boolean exclusive, LifetimePolicy lifetime, long ttl, Map<String, Object> attributes)
+ throws AccessControlException, IllegalArgumentException;
+
+ Collection<String> getExchangeTypes();
+
+ public static interface Transaction
+ {
+ void dequeue(QueueEntry entry);
+
+ void copy(QueueEntry entry, Queue queue);
+
+ void move(QueueEntry entry, Queue queue);
+
+ }
+
+ public static interface TransactionalOperation
+ {
+ void withinTransaction(Transaction txn);
+ }
+
+ void executeTransaction(TransactionalOperation op);
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/model/VirtualHostAlias.java b/java/broker/src/main/java/org/apache/qpid/server/model/VirtualHostAlias.java
new file mode 100644
index 0000000000..31403d78e5
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/model/VirtualHostAlias.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.server.model;
+
+import java.security.AccessControlException;
+import java.util.Collection;
+
+public interface VirtualHostAlias extends ConfiguredObject
+{
+ // parents
+ Port getPort();
+ VirtualHost getVirtualHost();
+
+ // children
+ Collection<AuthenticationMethod> getAuthenticationMethods();
+
+
+
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AbstractAdapter.java b/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AbstractAdapter.java
new file mode 100644
index 0000000000..7d6aa9b2cb
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AbstractAdapter.java
@@ -0,0 +1,283 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.model.adapter;
+
+import java.security.AccessControlException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+import org.apache.qpid.server.model.ConfigurationChangeListener;
+import org.apache.qpid.server.model.ConfiguredObject;
+import org.apache.qpid.server.model.IllegalStateTransitionException;
+import org.apache.qpid.server.model.State;
+
+abstract class AbstractAdapter implements ConfiguredObject
+{
+ private final Map<String,Object> _attributes = new HashMap<String, Object>();
+ private final Map<Class<? extends ConfiguredObject>, ConfiguredObject> _parents =
+ new HashMap<Class<? extends ConfiguredObject>, ConfiguredObject>();
+ private final Collection<ConfigurationChangeListener> _changeListeners =
+ new ArrayList<ConfigurationChangeListener>();
+
+ private final UUID _id;
+
+ protected AbstractAdapter(UUID id)
+ {
+ _id = id;
+ }
+
+ static String getStringAttribute(String name, Map<String,Object> attributes, String defaultVal)
+ {
+ final Object value = attributes.get(name);
+ return value == null ? defaultVal : String.valueOf(value);
+ }
+
+ static Map getMapAttribute(String name, Map<String,Object> attributes, Map defaultVal)
+ {
+ final Object value = attributes.get(name);
+ if(value == null)
+ {
+ return defaultVal;
+ }
+ else if(value instanceof Map)
+ {
+ return (Map) value;
+ }
+ else
+ {
+ throw new IllegalArgumentException("Value for attribute " + name + " is not of required type Map");
+ }
+ }
+
+
+ static <E extends Enum> E getEnumAttribute(Class<E> clazz, String name, Map<String,Object> attributes, E defaultVal)
+ {
+ Object obj = attributes.get(name);
+ if(obj == null)
+ {
+ return defaultVal;
+ }
+ else if(clazz.isInstance(obj))
+ {
+ return (E) obj;
+ }
+ else if(obj instanceof String)
+ {
+ return (E) Enum.valueOf(clazz, (String)obj);
+ }
+ else
+ {
+ throw new IllegalArgumentException("Value for attribute " + name + " is not of required type " + clazz.getSimpleName());
+ }
+ }
+
+ static Boolean getBooleanAttribute(String name, Map<String,Object> attributes, Boolean defaultValue)
+ {
+ Object obj = attributes.get(name);
+ if(obj == null)
+ {
+ return defaultValue;
+ }
+ else if(obj instanceof Boolean)
+ {
+ return (Boolean) obj;
+ }
+ else if(obj instanceof String)
+ {
+ return Boolean.parseBoolean((String) obj);
+ }
+ else
+ {
+ throw new IllegalArgumentException("Value for attribute " + name + " is not of required type Boolean");
+ }
+ }
+
+ static Integer getIntegerAttribute(String name, Map<String,Object> attributes, Integer defaultValue)
+ {
+ Object obj = attributes.get(name);
+ if(obj == null)
+ {
+ return defaultValue;
+ }
+ else if(obj instanceof Number)
+ {
+ return ((Number) obj).intValue();
+ }
+ else if(obj instanceof String)
+ {
+ return Integer.valueOf((String) obj);
+ }
+ else
+ {
+ throw new IllegalArgumentException("Value for attribute " + name + " is not of required type Integer");
+ }
+ }
+
+ static Long getLongAttribute(String name, Map<String,Object> attributes, Long defaultValue)
+ {
+ Object obj = attributes.get(name);
+ if(obj == null)
+ {
+ return defaultValue;
+ }
+ else if(obj instanceof Number)
+ {
+ return ((Number) obj).longValue();
+ }
+ else if(obj instanceof String)
+ {
+ return Long.valueOf((String) obj);
+ }
+ else
+ {
+ throw new IllegalArgumentException("Value for attribute " + name + " is not of required type Long");
+ }
+ }
+
+ public final UUID getId()
+ {
+ return _id;
+ }
+
+ public State getDesiredState()
+ {
+ return null; //TODO
+ }
+
+ public State setDesiredState(final State currentState, final State desiredState)
+ throws IllegalStateTransitionException, AccessControlException
+ {
+ return null; //TODO
+ }
+
+ public void addChangeListener(final ConfigurationChangeListener listener)
+ {
+ if(listener == null)
+ {
+ throw new NullPointerException("Cannot add a null listener");
+ }
+ synchronized (this)
+ {
+ if(!_changeListeners.contains(listener))
+ {
+ _changeListeners.add(listener);
+ }
+ }
+ }
+
+ public boolean removeChangeListener(final ConfigurationChangeListener listener)
+ {
+ if(listener == null)
+ {
+ throw new NullPointerException("Cannot remove a null listener");
+ }
+ synchronized (this)
+ {
+ return _changeListeners.remove(listener);
+ }
+ }
+
+
+ protected void childAdded(ConfiguredObject child)
+ {
+ synchronized (this)
+ {
+ for(ConfigurationChangeListener listener : _changeListeners)
+ {
+ listener.childAdded(this, child);
+ }
+ }
+ }
+
+
+ protected void childRemoved(ConfiguredObject child)
+ {
+ synchronized (this)
+ {
+ for(ConfigurationChangeListener listener : _changeListeners)
+ {
+ listener.childRemoved(this, child);
+ }
+ }
+ }
+
+ public Object getAttribute(final String name)
+ {
+ synchronized (this)
+ {
+ return _attributes.get(name);
+ }
+ }
+
+ public Object setAttribute(final String name, final Object expected, final Object desired)
+ throws IllegalStateException, AccessControlException, IllegalArgumentException
+ {
+ synchronized (this)
+ {
+ Object currentValue = _attributes.get(name);
+ if((currentValue == null && expected == null)
+ || (currentValue != null && currentValue.equals(expected)))
+ {
+ _attributes.put(name, desired);
+ return desired;
+ }
+ else
+ {
+ return currentValue;
+ }
+ }
+ }
+
+ public <T extends ConfiguredObject> T getParent(final Class<T> clazz)
+ {
+ synchronized (this)
+ {
+ return (T) _parents.get(clazz);
+ }
+ }
+
+ protected <T extends ConfiguredObject> void addParent(Class<T> clazz, T parent)
+ {
+ synchronized (this)
+ {
+ _parents.put(clazz, parent);
+ }
+ }
+
+ protected <T extends ConfiguredObject> void removeParent(Class<T> clazz)
+ {
+ synchronized (this)
+ {
+ _parents.remove(clazz);
+ }
+ }
+
+ public Collection<String> getAttributeNames()
+ {
+ synchronized(_attributes)
+ {
+ return new ArrayList<String>(_attributes.keySet());
+ }
+ }
+
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AuthenticationProviderAdapter.java b/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AuthenticationProviderAdapter.java
new file mode 100644
index 0000000000..8c2bc98ba7
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AuthenticationProviderAdapter.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.qpid.server.model.adapter;
+
+import java.io.IOException;
+import java.security.AccessControlException;
+import java.security.Principal;
+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 javax.security.auth.login.AccountNotFoundException;
+
+import org.apache.log4j.Logger;
+import org.apache.qpid.server.model.*;
+import org.apache.qpid.server.registry.ApplicationRegistry;
+import org.apache.qpid.server.security.access.Operation;
+import org.apache.qpid.server.security.auth.database.PrincipalDatabase;
+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.sasl.UsernamePrincipal;
+
+public abstract class AuthenticationProviderAdapter<T extends AuthenticationManager> extends AbstractAdapter implements AuthenticationProvider
+{
+ private static final Logger LOGGER = Logger.getLogger(AuthenticationProviderAdapter.class);
+
+ private final BrokerAdapter _broker;
+ private final T _authManager;
+
+ private AuthenticationProviderAdapter(BrokerAdapter brokerAdapter,
+ final T authManager)
+ {
+ super(UUIDGenerator.generateRandomUUID());
+ _broker = brokerAdapter;
+ _authManager = authManager;
+ }
+
+ public static AuthenticationProviderAdapter createAuthenticationProviderAdapter(BrokerAdapter brokerAdapter,
+ final AuthenticationManager authManager)
+ {
+ return authManager instanceof PrincipalDatabaseAuthenticationManager
+ ? new PrincipalDatabaseAuthenticationManagerAdapter(brokerAdapter, (PrincipalDatabaseAuthenticationManager) authManager)
+ : new SimpleAuthenticationProviderAdapter(brokerAdapter, authManager);
+ }
+
+ T getAuthManager()
+ {
+ return _authManager;
+ }
+
+ @Override
+ public Collection<VirtualHostAlias> getVirtualHostPortBindings()
+ {
+ return Collections.emptyList();
+ }
+
+ @Override
+ public String getName()
+ {
+ return _authManager.getClass().getSimpleName();
+ }
+
+ @Override
+ public String setName(String currentName, String desiredName) throws IllegalStateException, AccessControlException
+ {
+ return null;
+ }
+
+ @Override
+ public State getActualState()
+ {
+ return null;
+ }
+
+ @Override
+ public boolean isDurable()
+ {
+ return true;
+ }
+
+ @Override
+ public void setDurable(boolean durable)
+ throws IllegalStateException, AccessControlException, IllegalArgumentException
+ {
+ }
+
+ @Override
+ public LifetimePolicy getLifetimePolicy()
+ {
+ return LifetimePolicy.PERMANENT;
+ }
+
+ @Override
+ public LifetimePolicy setLifetimePolicy(LifetimePolicy expected, LifetimePolicy desired)
+ throws IllegalStateException, AccessControlException, IllegalArgumentException
+ {
+ return null;
+ }
+
+ @Override
+ public long getTimeToLive()
+ {
+ return 0;
+ }
+
+ @Override
+ public long setTimeToLive(long expected, long desired)
+ throws IllegalStateException, AccessControlException, IllegalArgumentException
+ {
+ return 0;
+ }
+
+ @Override
+ public Statistics getStatistics()
+ {
+ return NoStatistics.getInstance();
+ }
+
+ @Override
+ public Collection<String> getAttributeNames()
+ {
+ return AuthenticationProvider.AVAILABLE_ATTRIBUTES;
+ }
+
+ @Override
+ public Object getAttribute(String name)
+ {
+ if(TYPE.equals(name))
+ {
+ return _authManager.getClass().getSimpleName();
+ }
+ else if(CREATED.equals(name))
+ {
+ // TODO
+ }
+ else if(DURABLE.equals(name))
+ {
+ return true;
+ }
+ else if(ID.equals(name))
+ {
+ return getId();
+ }
+ else if(LIFETIME_POLICY.equals(name))
+ {
+ return LifetimePolicy.PERMANENT;
+ }
+ else if(NAME.equals(name))
+ {
+ return getName();
+ }
+ else if(STATE.equals(name))
+ {
+ return State.ACTIVE; // TODO
+ }
+ else if(TIME_TO_LIVE.equals(name))
+ {
+ // TODO
+ }
+ else if(UPDATED.equals(name))
+ {
+ // TODO
+ }
+ return super.getAttribute(name);
+ }
+
+ @Override
+ public <C extends ConfiguredObject> Collection<C> getChildren(Class<C> clazz)
+ {
+ return null;
+ }
+
+ @Override
+ public <C extends ConfiguredObject> C createChild(Class<C> childClass,
+ Map<String, Object> attributes,
+ ConfiguredObject... otherParents)
+ {
+ return null;
+ }
+
+ private static class SimpleAuthenticationProviderAdapter extends AuthenticationProviderAdapter<AuthenticationManager>
+ {
+ public SimpleAuthenticationProviderAdapter(
+ BrokerAdapter brokerAdapter, AuthenticationManager authManager)
+ {
+ super(brokerAdapter,authManager);
+ }
+ }
+
+ private static class PrincipalDatabaseAuthenticationManagerAdapter
+ extends AuthenticationProviderAdapter<PrincipalDatabaseAuthenticationManager>
+ implements PasswordCredentialManagingAuthenticationProvider
+ {
+ public PrincipalDatabaseAuthenticationManagerAdapter(
+ BrokerAdapter brokerAdapter, PrincipalDatabaseAuthenticationManager authManager)
+ {
+ super(brokerAdapter, authManager);
+ }
+
+ @Override
+ public boolean createUser(String username, String password, Map<String, String> attributes)
+ {
+ return getPrincipalDatabase().createPrincipal(new UsernamePrincipal(username), password.toCharArray());
+ }
+
+ @Override
+ public void deleteUser(String username) throws AccountNotFoundException
+ {
+ if(getSecurityManager().authoriseMethod(Operation.DELETE,
+ "UserManagement",
+ "deleteUser"))
+ {
+
+ getPrincipalDatabase().deletePrincipal(new UsernamePrincipal(username));
+ }
+ else
+ {
+ throw new AccessControlException("Cannot delete user " + username);
+ }
+ }
+
+ private org.apache.qpid.server.security.SecurityManager getSecurityManager()
+ {
+ return ApplicationRegistry.getInstance().getSecurityManager();
+ }
+
+ private PrincipalDatabase getPrincipalDatabase()
+ {
+ return getAuthManager().getPrincipalDatabase();
+ }
+
+ @Override
+ public void setPassword(String username, String password) throws AccountNotFoundException
+ {
+ getPrincipalDatabase().updatePassword(new UsernamePrincipal(username), password.toCharArray());
+ }
+
+ public void reload() throws IOException
+ {
+ if(getSecurityManager().authoriseMethod(Operation.UPDATE, "UserManagement", "reload"))
+ {
+ getPrincipalDatabase().reload();
+ }
+ else
+ {
+ throw new AccessControlException("Do not have permission to reload principal database");
+ }
+ }
+
+ @Override
+ public Map<String, Map<String, String>> getUsers()
+ {
+
+ Map<String, Map<String,String>> users = new HashMap<String, Map<String, String>>();
+ for(Principal principal : getPrincipalDatabase().getUsers())
+ {
+ users.put(principal.getName(), Collections.EMPTY_MAP);
+ }
+ return users;
+ }
+
+ @Override
+ public <C extends ConfiguredObject> C createChild(Class<C> childClass,
+ Map<String, Object> attributes,
+ ConfiguredObject... otherParents)
+ {
+ if(childClass == User.class)
+ {
+ Principal p = new UsernamePrincipal((String) attributes.get("name"));
+ if(getSecurityManager().authoriseMethod(Operation.UPDATE, "UserManagement", "createUser"))
+ {
+ if(getPrincipalDatabase().createPrincipal(p, ((String)attributes.get("password")).toCharArray()))
+ {
+ return (C) new PrincipalAdapter(p);
+ }
+ }
+ else
+ {
+ throw new AccessControlException("Do not have permission to create a new user");
+ }
+
+ }
+
+ return super.createChild(childClass, attributes, otherParents);
+ }
+
+ @Override
+ public <C extends ConfiguredObject> Collection<C> getChildren(Class<C> clazz)
+ {
+ if(clazz == User.class)
+ {
+ List<Principal> users = getPrincipalDatabase().getUsers();
+ Collection<User> principals = new ArrayList<User>(users.size());
+ for(Principal user : users)
+ {
+ principals.add(new PrincipalAdapter(user));
+ }
+ return (Collection<C>) Collections.unmodifiableCollection(principals);
+ }
+ else
+ {
+ return super.getChildren(clazz);
+ }
+ }
+
+ private class PrincipalAdapter extends AbstractAdapter implements User
+ {
+ private final Principal _user;
+
+
+ public PrincipalAdapter(Principal user)
+ {
+ super(UUIDGenerator.generateUserUUID(PrincipalDatabaseAuthenticationManagerAdapter.this.getName(), user.getName()));
+ _user = user;
+
+ }
+
+ @Override
+ public String getPassword()
+ {
+ return null;
+ }
+
+ @Override
+ public void setPassword(String password)
+ {
+ try
+ {
+ PrincipalDatabaseAuthenticationManagerAdapter.this.setPassword(_user.getName(), password);
+ }
+ catch (AccountNotFoundException e)
+ {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ @Override
+ public String getName()
+ {
+ return _user.getName();
+ }
+
+ @Override
+ public String setName(String currentName, String desiredName)
+ throws IllegalStateException, AccessControlException
+ {
+ throw new IllegalStateException("Names cannot be updated");
+ }
+
+ @Override
+ public State getActualState()
+ {
+ return State.ACTIVE;
+ }
+
+ @Override
+ public boolean isDurable()
+ {
+ return true;
+ }
+
+ @Override
+ public void setDurable(boolean durable)
+ throws IllegalStateException, AccessControlException, IllegalArgumentException
+ {
+ throw new IllegalStateException("Durability cannot be updated");
+ }
+
+ @Override
+ public LifetimePolicy getLifetimePolicy()
+ {
+ return LifetimePolicy.PERMANENT;
+ }
+
+ @Override
+ public LifetimePolicy setLifetimePolicy(LifetimePolicy expected, LifetimePolicy desired)
+ throws IllegalStateException, AccessControlException, IllegalArgumentException
+ {
+ throw new IllegalStateException("LifetimePolicy cannot be updated");
+ }
+
+ @Override
+ public long getTimeToLive()
+ {
+ return 0;
+ }
+
+ @Override
+ public long setTimeToLive(long expected, long desired)
+ throws IllegalStateException, AccessControlException, IllegalArgumentException
+ {
+ throw new IllegalStateException("ttl cannot be updated");
+ }
+
+ @Override
+ public Statistics getStatistics()
+ {
+ return NoStatistics.getInstance();
+ }
+
+ @Override
+ public <C extends ConfiguredObject> Collection<C> getChildren(Class<C> clazz)
+ {
+ return null;
+ }
+
+ @Override
+ public <C extends ConfiguredObject> C createChild(Class<C> childClass,
+ Map<String, Object> attributes,
+ ConfiguredObject... otherParents)
+ {
+ return null;
+ }
+
+ @Override
+ public Collection<String> getAttributeNames()
+ {
+ return User.AVAILABLE_ATTRIBUTES;
+ }
+
+ @Override
+ public Object getAttribute(String name)
+ {
+ if(ID.equals(name))
+ {
+ return getId();
+ }
+ else if(NAME.equals(name))
+ {
+ return getName();
+ }
+ return super.getAttribute(name);
+ }
+
+ @Override
+ public Object setAttribute(String name, Object expected, Object desired)
+ throws IllegalStateException, AccessControlException, IllegalArgumentException
+ {
+ if(name.equals(PASSWORD))
+ {
+ setPassword((String)desired);
+ }
+ return super.setAttribute(name,
+ expected,
+ desired);
+ }
+
+ @Override
+ public State setDesiredState(State currentState, State desiredState)
+ throws IllegalStateTransitionException, AccessControlException
+ {
+ if(desiredState == State.DELETED)
+ {
+ try
+ {
+ deleteUser(_user.getName());
+ }
+ catch (AccountNotFoundException e)
+ {
+ LOGGER.warn("Failed to delete user " + _user, e);
+ }
+ return State.DELETED;
+ }
+ return super.setDesiredState(currentState, desiredState);
+ }
+ }
+ }
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/model/adapter/BindingAdapter.java b/java/broker/src/main/java/org/apache/qpid/server/model/adapter/BindingAdapter.java
new file mode 100644
index 0000000000..abd3160686
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/model/adapter/BindingAdapter.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.server.model.adapter;
+
+import java.security.AccessControlException;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.qpid.AMQInternalException;
+import org.apache.qpid.AMQSecurityException;
+import org.apache.qpid.server.model.Binding;
+import org.apache.qpid.server.model.ConfiguredObject;
+import org.apache.qpid.server.model.Exchange;
+import org.apache.qpid.server.model.IllegalStateTransitionException;
+import org.apache.qpid.server.model.LifetimePolicy;
+import org.apache.qpid.server.model.Queue;
+import org.apache.qpid.server.model.State;
+import org.apache.qpid.server.model.Statistics;
+
+final class BindingAdapter extends AbstractAdapter implements Binding
+{
+ private final org.apache.qpid.server.binding.Binding _binding;
+ private Statistics _statistics = NoStatistics.getInstance();
+ private final ExchangeAdapter _exchange;
+ private QueueAdapter _queue;
+
+ public BindingAdapter(final org.apache.qpid.server.binding.Binding binding,
+ ExchangeAdapter exchangeAdapter,
+ QueueAdapter queueAdapter)
+ {
+ super(binding.getId());
+ _binding = binding;
+ _exchange = exchangeAdapter;
+ _queue = queueAdapter;
+ addParent(Queue.class, queueAdapter);
+ addParent(Exchange.class, exchangeAdapter);
+ }
+
+
+ public ExchangeAdapter getExchange()
+ {
+ return _exchange;
+ }
+
+ public QueueAdapter getQueue()
+ {
+ return _queue;
+ }
+
+ public String getName()
+ {
+ return _binding.getBindingKey();
+ }
+
+ public String setName(final String currentName, final String desiredName)
+ throws IllegalStateException, AccessControlException
+ {
+ return null; //TODO
+ }
+
+ public State getActualState()
+ {
+ return null; //TODO
+ }
+
+ public boolean isDurable()
+ {
+ return _binding.getQueue().isDurable() && _binding.getExchange().isDurable();
+ }
+
+ public void setDurable(final boolean durable)
+ throws IllegalStateException, AccessControlException, IllegalArgumentException
+ {
+ //TODO
+ }
+
+ public LifetimePolicy getLifetimePolicy()
+ {
+ return LifetimePolicy.PERMANENT;
+ }
+
+ public LifetimePolicy setLifetimePolicy(final LifetimePolicy expected, final LifetimePolicy desired)
+ throws IllegalStateException, AccessControlException, IllegalArgumentException
+ {
+ return null; //TODO
+ }
+
+ public long getTimeToLive()
+ {
+ return 0; //TODO
+ }
+
+ public long setTimeToLive(final long expected, final long desired)
+ throws IllegalStateException, AccessControlException, IllegalArgumentException
+ {
+ return 0; //TODO
+ }
+
+ public Statistics getStatistics()
+ {
+ return _statistics;
+ }
+
+ @Override
+ public <C extends ConfiguredObject> Collection<C> getChildren(Class<C> clazz)
+ {
+ return Collections.emptySet();
+ }
+
+ @Override
+ public <C extends ConfiguredObject> C createChild(Class<C> childClass, Map<String, Object> attributes, ConfiguredObject... otherParents)
+ {
+ throw new IllegalArgumentException("Cannot add children to a binding");
+ }
+
+ public Map<String, Object> getArguments()
+ {
+ return new HashMap<String, Object> (_binding.getArguments());
+ }
+
+ public void delete()
+ {
+ try
+ {
+ _queue.getAMQQueue().getVirtualHost().getBindingFactory().removeBinding(_binding);
+ }
+ catch(AMQSecurityException e)
+ {
+ throw new AccessControlException(e.getMessage());
+ }
+ catch(AMQInternalException e)
+ {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ @Override
+ public Object getAttribute(final String name)
+ {
+ if(ID.equals(name))
+ {
+ return getId();
+ }
+ else if(NAME.equals(name))
+ {
+ return getName();
+ }
+ else if(STATE.equals(name))
+ {
+
+ }
+ else if(DURABLE.equals(name))
+ {
+ return _queue.isDurable() && _exchange.isDurable();
+ }
+ else if(LIFETIME_POLICY.equals(name))
+ {
+ return _queue.getLifetimePolicy() == LifetimePolicy.AUTO_DELETE || _exchange.getLifetimePolicy() == LifetimePolicy.AUTO_DELETE ? LifetimePolicy.AUTO_DELETE : LifetimePolicy.PERMANENT;
+ }
+ else if(TIME_TO_LIVE.equals(name))
+ {
+
+ }
+ else if(CREATED.equals(name))
+ {
+
+ }
+ else if(UPDATED.equals(name))
+ {
+
+ }
+ else if(EXCHANGE.equals(name))
+ {
+ return _exchange.getName();
+ }
+ else if(QUEUE.equals(name))
+ {
+ return _queue.getName();
+ }
+ else if(ARGUMENTS.equals(name))
+ {
+ return getArguments();
+ }
+
+ return super.getAttribute(name); //TODO
+ }
+
+ @Override
+ public Object setAttribute(final String name, final Object expected, final Object desired)
+ throws IllegalStateException, AccessControlException, IllegalArgumentException
+ {
+ return super.setAttribute(name, expected, desired); //TODO
+ }
+
+ @Override
+ public Collection<String> getAttributeNames()
+ {
+ return Binding.AVAILABLE_ATTRIBUTES;
+ }
+
+ @Override
+ public State setDesiredState(State currentState, State desiredState) throws IllegalStateTransitionException,
+ AccessControlException
+ {
+ if (desiredState == State.DELETED)
+ {
+ delete();
+ return State.DELETED;
+ }
+ return super.setDesiredState(currentState, desiredState);
+ }
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/model/adapter/BrokerAdapter.java b/java/broker/src/main/java/org/apache/qpid/server/model/adapter/BrokerAdapter.java
new file mode 100644
index 0000000000..f1cce2d45c
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/model/adapter/BrokerAdapter.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.server.model.adapter;
+
+import java.net.InetSocketAddress;
+import java.security.AccessControlException;
+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 org.apache.qpid.common.QpidProperties;
+import org.apache.qpid.server.model.AuthenticationProvider;
+import org.apache.qpid.server.model.Broker;
+import org.apache.qpid.server.model.ConfiguredObject;
+import org.apache.qpid.server.model.LifetimePolicy;
+import org.apache.qpid.server.model.Port;
+import org.apache.qpid.server.model.Protocol;
+import org.apache.qpid.server.model.State;
+import org.apache.qpid.server.model.Statistics;
+import org.apache.qpid.server.model.Transport;
+import org.apache.qpid.server.model.UUIDGenerator;
+import org.apache.qpid.server.model.VirtualHost;
+import org.apache.qpid.server.registry.IApplicationRegistry;
+import org.apache.qpid.server.security.auth.manager.AuthenticationManager;
+import org.apache.qpid.server.security.auth.manager.IAuthenticationManagerRegistry;
+import org.apache.qpid.server.transport.QpidAcceptor;
+import org.apache.qpid.server.virtualhost.VirtualHostRegistry;
+
+public class BrokerAdapter extends AbstractAdapter implements Broker, VirtualHostRegistry.RegistryChangeListener,
+ IApplicationRegistry.PortBindingListener,
+ IAuthenticationManagerRegistry.RegistryChangeListener
+{
+
+
+ private final IApplicationRegistry _applicationRegistry;
+ private String _name;
+ private final Map<org.apache.qpid.server.virtualhost.VirtualHost, VirtualHostAdapter> _vhostAdapters =
+ new HashMap<org.apache.qpid.server.virtualhost.VirtualHost, VirtualHostAdapter>();
+ private final StatisticsAdapter _statistics;
+ private final Map<QpidAcceptor, PortAdapter> _portAdapters = new HashMap<QpidAcceptor, PortAdapter>();
+ private Collection<HTTPPortAdapter> _httpManagementPorts;
+
+ private final Map<AuthenticationManager, AuthenticationProviderAdapter> _authManagerAdapters =
+ new HashMap<AuthenticationManager, AuthenticationProviderAdapter>();
+
+
+ public BrokerAdapter(final IApplicationRegistry instance)
+ {
+ super(UUIDGenerator.generateRandomUUID());
+ _applicationRegistry = instance;
+ _name = "Broker";
+ _statistics = new StatisticsAdapter(instance);
+
+ instance.getVirtualHostRegistry().addRegistryChangeListener(this);
+ populateVhosts();
+ instance.addPortBindingListener(this);
+ populatePorts();
+ instance.addRegistryChangeListener(this);
+ populateAuthenticationManagers();
+ }
+
+ private void populateVhosts()
+ {
+ synchronized(_vhostAdapters)
+ {
+ Collection<org.apache.qpid.server.virtualhost.VirtualHost> actualVhosts =
+ _applicationRegistry.getVirtualHostRegistry().getVirtualHosts();
+ for(org.apache.qpid.server.virtualhost.VirtualHost vh : actualVhosts)
+ {
+ if(!_vhostAdapters.containsKey(vh))
+ {
+ _vhostAdapters.put(vh, new VirtualHostAdapter(this, vh));
+ }
+ }
+
+ }
+ }
+
+
+ public Collection<VirtualHost> getVirtualHosts()
+ {
+ synchronized(_vhostAdapters)
+ {
+ return new ArrayList<VirtualHost>(_vhostAdapters.values());
+ }
+
+ }
+ private void populatePorts()
+ {
+ synchronized (_portAdapters)
+ {
+ Map<InetSocketAddress, QpidAcceptor> acceptors = _applicationRegistry.getAcceptors();
+
+ for(Map.Entry<InetSocketAddress, QpidAcceptor> entry : acceptors.entrySet())
+ {
+ if(!_portAdapters.containsKey(entry.getValue()))
+ {
+ _portAdapters.put(entry.getValue(), new PortAdapter(this, entry.getValue(), entry.getKey()));
+ }
+ }
+ if(_applicationRegistry.useHTTPManagement() || _applicationRegistry.useHTTPSManagement())
+ {
+ ArrayList<HTTPPortAdapter> httpPorts = new ArrayList<HTTPPortAdapter>();
+ if (_applicationRegistry.useHTTPManagement())
+ {
+ httpPorts.add(new HTTPPortAdapter(this, _applicationRegistry.getHTTPManagementPort()));
+ }
+ if (_applicationRegistry.useHTTPSManagement())
+ {
+ httpPorts.add(new HTTPPortAdapter(this, _applicationRegistry.getHTTPSManagementPort(), Protocol.HTTPS, Transport.SSL));
+ }
+ _httpManagementPorts = Collections.unmodifiableCollection(httpPorts);
+ }
+ }
+ }
+
+ public Collection<Port> getPorts()
+ {
+ synchronized (_portAdapters)
+ {
+ final ArrayList<Port> ports = new ArrayList<Port>(_portAdapters.values());
+ if(_httpManagementPorts != null)
+ {
+ ports.addAll(_httpManagementPorts);
+ }
+ return ports;
+ }
+ }
+
+ private void populateAuthenticationManagers()
+ {
+ synchronized (_authManagerAdapters)
+ {
+ IAuthenticationManagerRegistry authenticationManagerRegistry =
+ _applicationRegistry.getAuthenticationManagerRegistry();
+ if(authenticationManagerRegistry != null)
+ {
+ Map<String, AuthenticationManager> authenticationManagers =
+ authenticationManagerRegistry.getAvailableAuthenticationManagers();
+
+ for(Map.Entry<String, AuthenticationManager> entry : authenticationManagers.entrySet())
+ {
+ if(!_authManagerAdapters.containsKey(entry.getValue()))
+ {
+ _authManagerAdapters.put(entry.getValue(),
+ AuthenticationProviderAdapter.createAuthenticationProviderAdapter(this,
+ entry.getValue()));
+ }
+ }
+ }
+ }
+ }
+
+ public Collection<AuthenticationProvider> getAuthenticationProviders()
+ {
+ synchronized (_authManagerAdapters)
+ {
+ final ArrayList<AuthenticationProvider> authManagers =
+ new ArrayList<AuthenticationProvider>(_authManagerAdapters.values());
+ return authManagers;
+ }
+
+ }
+
+ public VirtualHost createVirtualHost(final String name,
+ final State initialState,
+ final boolean durable,
+ final LifetimePolicy lifetime,
+ final long ttl,
+ final Map<String, Object> attributes)
+ throws AccessControlException, IllegalArgumentException
+ {
+ return null; //TODO
+ }
+
+ public VirtualHost createVirtualHost(final Map<String, Object> attributes)
+ throws AccessControlException, IllegalArgumentException
+ {
+ return null; //TODO
+ }
+
+ public void deleteVirtualHost(final VirtualHost vhost)
+ throws AccessControlException, IllegalStateException
+ {
+ //TODO
+ throw new UnsupportedOperationException("Not yet implemented");
+ }
+
+ public String getName()
+ {
+ return _name;
+ }
+
+ public String setName(final String currentName, final String desiredName)
+ throws IllegalStateException, AccessControlException
+ {
+ return null; //TODO
+ }
+
+
+ public State getActualState()
+ {
+ return null; //TODO
+ }
+
+
+ public boolean isDurable()
+ {
+ return true;
+ }
+
+ public void setDurable(final boolean durable)
+ throws IllegalStateException, AccessControlException, IllegalArgumentException
+ {
+ throw new IllegalStateException();
+ }
+
+ public LifetimePolicy getLifetimePolicy()
+ {
+ return LifetimePolicy.PERMANENT;
+ }
+
+ public LifetimePolicy setLifetimePolicy(final LifetimePolicy expected, final LifetimePolicy desired)
+ throws IllegalStateException, AccessControlException, IllegalArgumentException
+ {
+ throw new IllegalStateException();
+ }
+
+ public long getTimeToLive()
+ {
+ return 0;
+ }
+
+ public long setTimeToLive(final long expected, final long desired)
+ throws IllegalStateException, AccessControlException, IllegalArgumentException
+ {
+ throw new IllegalStateException();
+ }
+
+ public Statistics getStatistics()
+ {
+ return _statistics;
+ }
+
+ @Override
+ public <C extends ConfiguredObject> Collection<C> getChildren(Class<C> clazz)
+ {
+ if(clazz == VirtualHost.class)
+ {
+ return (Collection<C>) getVirtualHosts();
+ }
+ else if(clazz == Port.class)
+ {
+ return (Collection<C>) getPorts();
+ }
+ else if(clazz == AuthenticationProvider.class)
+ {
+ return (Collection<C>) getAuthenticationProviders();
+ }
+
+ return Collections.emptySet();
+ }
+
+ @Override
+ public <C extends ConfiguredObject> C createChild(Class<C> childClass, Map<String, Object> attributes, ConfiguredObject... otherParents)
+ {
+ if(childClass == VirtualHost.class)
+ {
+ return (C) createVirtualHost(attributes);
+ }
+ else if(childClass == Port.class)
+ {
+ return (C) createPort(attributes);
+ }
+ else if(childClass == AuthenticationProvider.class)
+ {
+ return (C) createAuthenticationProvider(attributes);
+ }
+ else
+ {
+ throw new IllegalArgumentException("Cannot create child of class " + childClass.getSimpleName());
+ }
+ }
+
+ private Port createPort(Map<String, Object> attributes)
+ {
+ // TODO
+ return null;
+ }
+
+ private AuthenticationProvider createAuthenticationProvider(Map<String,Object> attributes)
+ {
+ // TODO
+ return null;
+ }
+
+
+ public void virtualHostRegistered(org.apache.qpid.server.virtualhost.VirtualHost virtualHost)
+ {
+ VirtualHostAdapter adapter = null;
+ synchronized (_vhostAdapters)
+ {
+ if(!_vhostAdapters.containsKey(virtualHost))
+ {
+ adapter = new VirtualHostAdapter(this, virtualHost);
+ _vhostAdapters.put(virtualHost, adapter);
+ }
+ }
+ if(adapter != null)
+ {
+ childAdded(adapter);
+ }
+ }
+
+ public void virtualHostUnregistered(org.apache.qpid.server.virtualhost.VirtualHost virtualHost)
+ {
+ VirtualHostAdapter adapter = null;
+
+ synchronized (_vhostAdapters)
+ {
+ adapter = _vhostAdapters.remove(virtualHost);
+ }
+ if(adapter != null)
+ {
+ childRemoved(adapter);
+ }
+ }
+
+ @Override
+ public void authenticationManagerRegistered(AuthenticationManager authenticationManager)
+ {
+ AuthenticationProviderAdapter adapter = null;
+ synchronized (_authManagerAdapters)
+ {
+ if(!_authManagerAdapters.containsKey(authenticationManager))
+ {
+ adapter =
+ AuthenticationProviderAdapter.createAuthenticationProviderAdapter(this, authenticationManager);
+ _authManagerAdapters.put(authenticationManager, adapter);
+ }
+ }
+ if(adapter != null)
+ {
+ childAdded(adapter);
+ }
+ }
+
+ @Override
+ public void authenticationManagerUnregistered(AuthenticationManager authenticationManager)
+ {
+ AuthenticationProviderAdapter adapter;
+ synchronized (_authManagerAdapters)
+ {
+ adapter = _authManagerAdapters.remove(authenticationManager);
+ }
+ if(adapter != null)
+ {
+ childRemoved(adapter);
+ }
+ }
+
+
+ @Override
+ public void bound(QpidAcceptor acceptor, InetSocketAddress bindAddress)
+ {
+ synchronized (_portAdapters)
+ {
+ if(!_portAdapters.containsKey(acceptor))
+ {
+ PortAdapter adapter = new PortAdapter(this, acceptor, bindAddress);
+ _portAdapters.put(acceptor, adapter);
+ childAdded(adapter);
+ }
+ }
+ }
+
+ @Override
+ public void unbound(QpidAcceptor acceptor)
+ {
+ PortAdapter adapter = null;
+
+ synchronized (_portAdapters)
+ {
+ adapter = _portAdapters.remove(acceptor);
+ }
+ if(adapter != null)
+ {
+ childRemoved(adapter);
+ }
+ }
+
+ @Override
+ public Collection<String> getAttributeNames()
+ {
+ return AVAILABLE_ATTRIBUTES;
+ }
+
+ @Override
+ public Object getAttribute(String name)
+ {
+ if(ID.equals(name))
+ {
+ return getId();
+ }
+ else if(NAME.equals(name))
+ {
+ return getName();
+ }
+ else if(STATE.equals(name))
+ {
+ return State.ACTIVE;
+ }
+ else if(DURABLE.equals(name))
+ {
+ return isDurable();
+ }
+ else if(LIFETIME_POLICY.equals(name))
+ {
+ return LifetimePolicy.PERMANENT;
+ }
+ else if(TIME_TO_LIVE.equals(name))
+ {
+ // TODO
+ }
+ else if(CREATED.equals(name))
+ {
+ // TODO
+ }
+ else if(UPDATED.equals(name))
+ {
+ // TODO
+ }
+ else if(BUILD_VERSION.equals(name))
+ {
+ return QpidProperties.getBuildVersion();
+ }
+ else if(BYTES_RETAINED.equals(name))
+ {
+ // TODO
+ }
+ else if(OPERATING_SYSTEM.equals(name))
+ {
+ return System.getProperty("os.name") + " "
+ + System.getProperty("os.version") + " "
+ + System.getProperty("os.arch");
+ }
+ else if(PLATFORM.equals(name))
+ {
+ return System.getProperty("java.vendor") + " "
+ + System.getProperty("java.runtime.version", System.getProperty("java.version"));
+ }
+ else if(PROCESS_PID.equals(name))
+ {
+ // TODO
+ }
+ else if(PRODUCT_VERSION.equals(name))
+ {
+ return QpidProperties.getReleaseVersion();
+ }
+ else if(SUPPORTED_STORE_TYPES.equals(name))
+ {
+ // TODO
+ }
+
+ return super.getAttribute(name); //TODO - Implement.
+ }
+
+ @Override
+ public Object setAttribute(String name, Object expected, Object desired)
+ throws IllegalStateException, AccessControlException, IllegalArgumentException
+ {
+ return super.setAttribute(name, expected, desired); //TODO - Implement.
+ }
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/model/adapter/ConnectionAdapter.java b/java/broker/src/main/java/org/apache/qpid/server/model/adapter/ConnectionAdapter.java
new file mode 100644
index 0000000000..5439f6a560
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/model/adapter/ConnectionAdapter.java
@@ -0,0 +1,313 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.model.adapter;
+
+import java.security.AccessControlException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.qpid.AMQException;
+import org.apache.qpid.protocol.AMQConstant;
+import org.apache.qpid.server.model.ConfiguredObject;
+import org.apache.qpid.server.model.Connection;
+import org.apache.qpid.server.model.LifetimePolicy;
+import org.apache.qpid.server.model.Session;
+import org.apache.qpid.server.model.State;
+import org.apache.qpid.server.model.Statistics;
+import org.apache.qpid.server.model.UUIDGenerator;
+import org.apache.qpid.server.protocol.AMQConnectionModel;
+import org.apache.qpid.server.protocol.AMQSessionModel;
+import org.apache.qpid.server.stats.StatisticsGatherer;
+
+final class ConnectionAdapter extends AbstractAdapter implements Connection
+{
+ private AMQConnectionModel _connection;
+
+ private final Map<AMQSessionModel, SessionAdapter> _sessionAdapters =
+ new HashMap<AMQSessionModel, SessionAdapter>();
+ private final Statistics _statistics;
+
+ public ConnectionAdapter(final AMQConnectionModel conn)
+ {
+ super(UUIDGenerator.generateRandomUUID());
+ _connection = conn;
+ _statistics = new ConnectionStatisticsAdapter(conn);
+ }
+
+ public Collection<Session> getSessions()
+ {
+ List<AMQSessionModel> actualSessions = _connection.getSessionModels();
+
+ synchronized (_sessionAdapters)
+ {
+ for(AMQSessionModel session : _sessionAdapters.keySet())
+ {
+ if(!actualSessions.contains(session))
+ {
+ _sessionAdapters.remove(session);
+ }
+ }
+ for(AMQSessionModel session : actualSessions)
+ {
+ if(!_sessionAdapters.containsKey(session))
+ {
+ _sessionAdapters.put(session, new SessionAdapter(session));
+ }
+ }
+ return new ArrayList<Session>(_sessionAdapters.values());
+ }
+ }
+
+ public void delete()
+ {
+ try
+ {
+ _connection.close(AMQConstant.CONNECTION_FORCED, "Connection closed by external action");
+ }
+ catch(AMQException e)
+ {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ public String getName()
+ {
+ final String remoteAddressString = _connection.getRemoteAddressString();
+ return remoteAddressString.replaceAll("/","");
+ }
+
+ public String setName(final String currentName, final String desiredName)
+ throws IllegalStateException, AccessControlException
+ {
+ return null; //TODO
+ }
+
+ public State getActualState()
+ {
+ return null; //TODO
+ }
+
+ public boolean isDurable()
+ {
+ return false; //TODO
+ }
+
+ public void setDurable(final boolean durable)
+ throws IllegalStateException, AccessControlException, IllegalArgumentException
+ {
+ //TODO
+ }
+
+ public LifetimePolicy getLifetimePolicy()
+ {
+ return null; //TODO
+ }
+
+ public LifetimePolicy setLifetimePolicy(final LifetimePolicy expected, final LifetimePolicy desired)
+ throws IllegalStateException, AccessControlException, IllegalArgumentException
+ {
+ return null; //TODO
+ }
+
+ public long getTimeToLive()
+ {
+ return 0; //TODO
+ }
+
+ public long setTimeToLive(final long expected, final long desired)
+ throws IllegalStateException, AccessControlException, IllegalArgumentException
+ {
+ return 0; //TODO
+ }
+
+ @Override
+ public Object getAttribute(String name)
+ {
+
+ if(name.equals(ID))
+ {
+ return getId();
+ }
+ else if (name.equals(NAME))
+ {
+ return getName();
+ }
+ else if(name.equals(CLIENT_ID))
+ {
+ return _connection.getClientId();
+ }
+ else if(name.equals(CLIENT_VERSION))
+ {
+ return _connection.getClientVersion();
+ }
+ else if(name.equals(INCOMING))
+ {
+
+ }
+ else if(name.equals(LOCAL_ADDRESS))
+ {
+
+ }
+ else if(name.equals(PRINCIPAL))
+ {
+ return _connection.getPrincipalAsString();
+ }
+ else if(name.equals(PROPERTIES))
+ {
+
+ }
+ else if(name.equals(REMOTE_ADDRESS))
+ {
+ return _connection.getRemoteAddressString();
+ }
+ else if(name.equals(REMOTE_PROCESS_NAME))
+ {
+
+ }
+ else if(name.equals(REMOTE_PROCESS_PID))
+ {
+
+ }
+ else if(name.equals(SESSION_COUNT_LIMIT))
+ {
+ return _connection.getSessionCountLimit();
+ }
+ return super.getAttribute(name);
+ }
+
+ @Override
+ public Object setAttribute(String name, Object expected, Object desired) throws IllegalStateException, AccessControlException, IllegalArgumentException
+ {
+ if(name.equals(CLIENT_ID))
+ {
+
+ }
+ else if(name.equals(CLIENT_VERSION))
+ {
+
+ }
+ else if(name.equals(INCOMING))
+ {
+
+ }
+ else if(name.equals(LOCAL_ADDRESS))
+ {
+
+ }
+ else if(name.equals(PRINCIPAL))
+ {
+
+ }
+ else if(name.equals(PROPERTIES))
+ {
+
+ }
+ else if(name.equals(REMOTE_ADDRESS))
+ {
+
+ }
+ else if(name.equals(REMOTE_PROCESS_NAME))
+ {
+
+ }
+ else if(name.equals(REMOTE_PROCESS_PID))
+ {
+
+ }
+ else if(name.equals(SESSION_COUNT_LIMIT))
+ {
+
+ }
+ return super.setAttribute(name, expected, desired);
+ }
+
+ @Override
+ public Collection<String> getAttributeNames()
+ {
+ final HashSet<String> attrNames = new HashSet<String>(super.getAttributeNames());
+ attrNames.addAll(Connection.AVAILABLE_ATTRIBUTES);
+ return Collections.unmodifiableCollection(attrNames);
+ }
+
+ public Statistics getStatistics()
+ {
+ return _statistics;
+ }
+
+ @Override
+ public <C extends ConfiguredObject> Collection<C> getChildren(Class<C> clazz)
+ {
+ if(clazz == Session.class)
+ {
+ return (Collection<C>) getSessions();
+ }
+ else
+ {
+ return Collections.emptySet();
+ }
+ }
+
+ public <C extends ConfiguredObject> C createChild(Class<C> childClass, Map<String, Object> attributes, ConfiguredObject... otherParents)
+ {
+ if(childClass == Session.class)
+ {
+ throw new IllegalStateException();
+ }
+ else
+ {
+ throw new IllegalArgumentException("Cannot create a child of class " + childClass.getSimpleName());
+ }
+
+ }
+
+ private class ConnectionStatisticsAdapter extends StatisticsAdapter
+ {
+ public ConnectionStatisticsAdapter(StatisticsGatherer applicationRegistry)
+ {
+ super(applicationRegistry);
+ }
+
+ @Override
+ public Collection<String> getStatisticNames()
+ {
+ return Connection.AVAILABLE_STATISTICS;
+ }
+
+ @Override
+ public Object getStatistic(String name)
+ {
+ if(LAST_IO_TIME.equals(name))
+ {
+ return _connection.getLastIoTime();
+ }
+ else if(SESSION_COUNT.equals(name))
+ {
+ return _connection.getSessionModels().size();
+ }
+ return super.getStatistic(name);
+ }
+ }
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/model/adapter/ConsumerAdapter.java b/java/broker/src/main/java/org/apache/qpid/server/model/adapter/ConsumerAdapter.java
new file mode 100644
index 0000000000..031d518670
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/model/adapter/ConsumerAdapter.java
@@ -0,0 +1,225 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.model.adapter;
+
+import java.util.Map;
+import org.apache.qpid.server.model.ConfiguredObject;
+import org.apache.qpid.server.model.Consumer;
+import org.apache.qpid.server.model.LifetimePolicy;
+import org.apache.qpid.server.model.State;
+import org.apache.qpid.server.model.Statistics;
+import org.apache.qpid.server.model.UUIDGenerator;
+import org.apache.qpid.server.subscription.Subscription;
+
+import java.security.AccessControlException;
+import java.util.Collection;
+import java.util.Collections;
+
+public class ConsumerAdapter extends AbstractAdapter implements Consumer
+{
+ private final Subscription _subscription;
+ private final QueueAdapter _queue;
+ private final ConsumerStatistics _statistics;
+
+ public ConsumerAdapter(final QueueAdapter queueAdapter, final Subscription subscription)
+ {
+ super(UUIDGenerator.generateConsumerUUID(queueAdapter.getVirtualHost().getName(),
+ queueAdapter.getName(),
+ subscription.getSessionModel().getConnectionModel().getRemoteAddressString(),
+ String.valueOf(subscription.getSessionModel().getChannelId()),
+ subscription.getConsumerName()));
+ _subscription = subscription;
+ _queue = queueAdapter;
+ _statistics = new ConsumerStatistics();
+ //TODO
+ }
+
+ public String getName()
+ {
+ return _subscription.getConsumerName();
+ }
+
+ public String setName(final String currentName, final String desiredName)
+ throws IllegalStateException, AccessControlException
+ {
+ return null; //TODO
+ }
+
+ public State getActualState()
+ {
+ return null; //TODO
+ }
+
+ public boolean isDurable()
+ {
+ return false; //TODO
+ }
+
+ public void setDurable(final boolean durable)
+ throws IllegalStateException, AccessControlException, IllegalArgumentException
+ {
+ //TODO
+ }
+
+ public LifetimePolicy getLifetimePolicy()
+ {
+ return null; //TODO
+ }
+
+ public LifetimePolicy setLifetimePolicy(final LifetimePolicy expected, final LifetimePolicy desired)
+ throws IllegalStateException, AccessControlException, IllegalArgumentException
+ {
+ return null; //TODO
+ }
+
+ public long getTimeToLive()
+ {
+ return 0; //TODO
+ }
+
+ public long setTimeToLive(final long expected, final long desired)
+ throws IllegalStateException, AccessControlException, IllegalArgumentException
+ {
+ return 0; //TODO
+ }
+
+ @Override
+ public Collection<String> getAttributeNames()
+ {
+ return Consumer.AVAILABLE_ATTRIBUTES;
+ }
+
+ @Override
+ public Object setAttribute(final String name, final Object expected, final Object desired)
+ throws IllegalStateException, AccessControlException, IllegalArgumentException
+ {
+ return super.setAttribute(name, expected, desired); //TODO
+ }
+
+ @Override
+ public Object getAttribute(final String name)
+ {
+ if(ID.equals(name))
+ {
+ return getId();
+ }
+ else if(NAME.equals(name))
+ {
+ return getName();
+ }
+ else if(STATE.equals(name))
+ {
+
+ }
+ else if(DURABLE.equals(name))
+ {
+ return false;
+ }
+ else if(LIFETIME_POLICY.equals(name))
+ {
+ return LifetimePolicy.AUTO_DELETE;
+ }
+ else if(TIME_TO_LIVE.equals(name))
+ {
+
+ }
+ else if(CREATED.equals(name))
+ {
+
+ }
+ else if(UPDATED.equals(name))
+ {
+
+ }
+ else if(DISTRIBUTION_MODE.equals(name))
+ {
+ return _subscription.acquires() ? "MOVE" : "COPY";
+ }
+ else if(SETTLEMENT_MODE.equals(name))
+ {
+
+ }
+ else if(EXCLUSIVE.equals(name))
+ {
+
+ }
+ else if(NO_LOCAL.equals(name))
+ {
+
+ }
+ else if(SELECTOR.equals(name))
+ {
+
+ }
+ return super.getAttribute(name); //TODO
+ }
+
+ public Statistics getStatistics()
+ {
+ return _statistics;
+ }
+
+ @Override
+ public <C extends ConfiguredObject> Collection<C> getChildren(Class<C> clazz)
+ {
+ return Collections.emptySet();
+ }
+
+ @Override
+ public <C extends ConfiguredObject> C createChild(Class<C> childClass, Map<String, Object> attributes, ConfiguredObject... otherParents)
+ {
+ throw new IllegalArgumentException();
+ }
+
+ private class ConsumerStatistics implements Statistics
+ {
+
+ public Collection<String> getStatisticNames()
+ {
+ return AVAILABLE_STATISTICS;
+ }
+
+ public Object getStatistic(String name)
+ {
+ if(name.equals(BYTES_OUT))
+ {
+ return _subscription.getBytesOut();
+ }
+ else if(name.equals(MESSAGES_OUT))
+ {
+ return _subscription.getMessagesOut();
+ }
+ else if(name.equals(STATE_CHANGED))
+ {
+
+ }
+ else if(name.equals(UNACKNOWLEDGED_BYTES))
+ {
+ return _subscription.getUnacknowledgedBytes();
+ }
+ else if(name.equals(UNACKNOWLEDGED_MESSAGES))
+ {
+ return _subscription.getUnacknowledgedMessages();
+ }
+ return null; // TODO - Implement
+ }
+ }
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/model/adapter/ExchangeAdapter.java b/java/broker/src/main/java/org/apache/qpid/server/model/adapter/ExchangeAdapter.java
new file mode 100644
index 0000000000..df0f29fbc3
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/model/adapter/ExchangeAdapter.java
@@ -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.
+ *
+ */
+package org.apache.qpid.server.model.adapter;
+
+import java.security.AccessControlException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.qpid.AMQException;
+import org.apache.qpid.AMQInternalException;
+import org.apache.qpid.AMQSecurityException;
+import org.apache.qpid.protocol.AMQConstant;
+import org.apache.qpid.server.binding.Binding;
+import org.apache.qpid.server.exchange.ExchangeRegistry;
+import org.apache.qpid.server.exchange.ExchangeType;
+import org.apache.qpid.server.model.ConfiguredObject;
+import org.apache.qpid.server.model.Exchange;
+import org.apache.qpid.server.model.IllegalStateTransitionException;
+import org.apache.qpid.server.model.LifetimePolicy;
+import org.apache.qpid.server.model.Publisher;
+import org.apache.qpid.server.model.Queue;
+import org.apache.qpid.server.model.State;
+import org.apache.qpid.server.model.Statistics;
+import org.apache.qpid.server.queue.AMQQueue;
+import org.apache.qpid.server.virtualhost.VirtualHost;
+
+final class ExchangeAdapter extends AbstractAdapter implements Exchange, org.apache.qpid.server.exchange.Exchange.BindingListener
+{
+
+ private final org.apache.qpid.server.exchange.Exchange _exchange;
+ private final Map<Binding, BindingAdapter> _bindingAdapters =
+ new HashMap<Binding, BindingAdapter>();
+ private VirtualHostAdapter _vhost;
+ private final ExchangeStatistics _statistics;
+
+ public ExchangeAdapter(final VirtualHostAdapter virtualHostAdapter,
+ final org.apache.qpid.server.exchange.Exchange exchange)
+ {
+ super(exchange.getId());
+ _statistics = new ExchangeStatistics();
+ _vhost = virtualHostAdapter;
+ _exchange = exchange;
+ addParent(org.apache.qpid.server.model.VirtualHost.class, virtualHostAdapter);
+
+ exchange.addBindingListener(this);
+ populateBindings();
+ }
+
+ private void populateBindings()
+ {
+ Collection<Binding> actualBindings = _exchange.getBindings();
+ synchronized (_bindingAdapters)
+ {
+ for(Binding binding : actualBindings)
+ {
+ if(!_bindingAdapters.containsKey(binding))
+ {
+ QueueAdapter queueAdapter = _vhost.getQueueAdapter(binding.getQueue());
+ BindingAdapter adapter = new BindingAdapter(binding, this, queueAdapter);
+ _bindingAdapters.put(binding, adapter);
+
+ queueAdapter.bindingRegistered(binding, adapter);
+ }
+ }
+ }
+
+ }
+
+ public String getExchangeType()
+ {
+ return _exchange.getType().getName().toString();
+ }
+
+ public Collection<org.apache.qpid.server.model.Binding> getBindings()
+ {
+ synchronized (_bindingAdapters)
+ {
+ return new ArrayList<org.apache.qpid.server.model.Binding>(_bindingAdapters.values());
+ }
+
+ }
+
+ public Collection<Publisher> getPublishers()
+ {
+ // TODO
+ return Collections.emptyList();
+ }
+
+
+ public org.apache.qpid.server.model.Binding createBinding(Queue queue,
+ Map<String, Object> attributes)
+ throws AccessControlException, IllegalStateException
+ {
+ attributes = new HashMap<String, Object>(attributes);
+ String bindingKey = getStringAttribute(org.apache.qpid.server.model.Binding.NAME, attributes, "");
+ Map<String, Object> bindingArgs = getMapAttribute(org.apache.qpid.server.model.Binding.ARGUMENTS, attributes, Collections.EMPTY_MAP);
+
+ attributes.remove(org.apache.qpid.server.model.Binding.NAME);
+ attributes.remove(org.apache.qpid.server.model.Binding.ARGUMENTS);
+
+ return createBinding(bindingKey, queue, bindingArgs, attributes);
+
+ }
+
+ public org.apache.qpid.server.model.Binding createBinding(String bindingKey, Queue queue,
+ Map<String, Object> bindingArguments,
+ Map<String, Object> attributes)
+ throws AccessControlException, IllegalStateException
+ {
+ VirtualHost virtualHost = _vhost.getVirtualHost();
+
+
+ AMQQueue amqQueue = ((QueueAdapter)queue).getAMQQueue();
+
+ try
+ {
+ if(!virtualHost.getBindingFactory().addBinding(bindingKey, amqQueue, _exchange, bindingArguments))
+ {
+ Binding oldBinding = virtualHost.getBindingFactory().getBinding(bindingKey, amqQueue, _exchange,
+ bindingArguments);
+
+ Map<String, Object> oldArgs = oldBinding.getArguments();
+ if((oldArgs == null && !bindingArguments.isEmpty()) || (oldArgs != null && !oldArgs.equals(bindingArguments)))
+ {
+ virtualHost.getBindingFactory().replaceBinding(oldBinding.getId(), bindingKey, amqQueue, _exchange, bindingArguments);
+ }
+ }
+ Binding binding = virtualHost.getBindingFactory().getBinding(bindingKey, amqQueue, _exchange, bindingArguments);
+
+ synchronized (_bindingAdapters)
+ {
+ return binding == null ? null : _bindingAdapters.get(binding);
+ }
+ }
+ catch(AMQSecurityException e)
+ {
+ throw new AccessControlException(e.toString());
+ }
+ catch(AMQInternalException e)
+ {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ public void delete()
+ {
+ try
+ {
+ ExchangeRegistry exchangeRegistry = _vhost.getVirtualHost().getExchangeRegistry();
+ if (exchangeRegistry.isReservedExchangeName(getName()))
+ {
+ throw new UnsupportedOperationException("'" + getName() + "' is a reserved exchange and can't be deleted");
+ }
+
+ if(_exchange.hasReferrers())
+ {
+ throw new AMQException( AMQConstant.NOT_ALLOWED, "Exchange in use as an alternate exchange", null);
+ }
+
+ synchronized(exchangeRegistry)
+ {
+ exchangeRegistry.unregisterExchange(getName(), false);
+ }
+ }
+ catch(AMQException e)
+ {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ public String getName()
+ {
+ return _exchange.getName();
+ }
+
+ public String setName(final String currentName, final String desiredName)
+ throws IllegalStateException, AccessControlException
+ {
+ return null; //TODO
+ }
+
+ public State getActualState()
+ {
+ return null; //TODO
+ }
+
+ public boolean isDurable()
+ {
+ return _exchange.isDurable();
+ }
+
+ public void setDurable(final boolean durable)
+ throws IllegalStateException, AccessControlException, IllegalArgumentException
+ {
+ //TODO
+ }
+
+ public LifetimePolicy getLifetimePolicy()
+ {
+ return _exchange.isAutoDelete() ? LifetimePolicy.AUTO_DELETE : LifetimePolicy.PERMANENT;
+ }
+
+ public LifetimePolicy setLifetimePolicy(final LifetimePolicy expected, final LifetimePolicy desired)
+ throws IllegalStateException, AccessControlException, IllegalArgumentException
+ {
+ return null; //TODO
+ }
+
+ public long getTimeToLive()
+ {
+ return 0; //TODO
+ }
+
+ public long setTimeToLive(final long expected, final long desired)
+ throws IllegalStateException, AccessControlException, IllegalArgumentException
+ {
+ return 0; //TODO
+ }
+
+ public Statistics getStatistics()
+ {
+ return _statistics;
+ }
+
+ @Override
+ public <C extends ConfiguredObject> Collection<C> getChildren(Class<C> clazz)
+ {
+ if(clazz == org.apache.qpid.server.model.Binding.class)
+ {
+ return (Collection<C>) getBindings();
+ }
+ else
+ {
+ return Collections.emptySet();
+ }
+ }
+
+ @Override
+ public <C extends ConfiguredObject> C createChild(Class<C> childClass, Map<String, Object> attributes, ConfiguredObject... otherParents)
+ {
+ if(childClass == org.apache.qpid.server.model.Binding.class)
+ {
+ if(otherParents != null && otherParents.length == 1 && otherParents[0] instanceof Queue)
+ {
+ Queue queue = (Queue) otherParents[0];
+ if(queue.getParent(org.apache.qpid.server.model.VirtualHost.class) == getParent(org.apache.qpid.server.model.VirtualHost.class))
+ {
+ return (C) createBinding(queue, attributes);
+ }
+ else
+ {
+ throw new IllegalArgumentException("Queue and Exchange parents of a binding must be on same virtual host");
+ }
+ }
+ else
+ {
+ throw new IllegalArgumentException("Other parent must be a queue");
+ }
+ }
+ else
+ {
+ throw new IllegalArgumentException();
+ }
+ }
+
+ public void bindingAdded(org.apache.qpid.server.exchange.Exchange exchange, Binding binding)
+ {
+ BindingAdapter adapter = null;
+ synchronized (_bindingAdapters)
+ {
+ if(!_bindingAdapters.containsKey(binding))
+ {
+ QueueAdapter queueAdapter = _vhost.getQueueAdapter(binding.getQueue());
+ adapter = new BindingAdapter(binding, this, queueAdapter);
+ _bindingAdapters.put(binding,adapter);
+ queueAdapter.bindingRegistered(binding,adapter);
+ }
+ }
+ if(adapter != null)
+ {
+ childAdded(adapter);
+ }
+ }
+
+ public void bindingRemoved(org.apache.qpid.server.exchange.Exchange exchange, Binding binding)
+ {
+ BindingAdapter adapter = null;
+ synchronized (_bindingAdapters)
+ {
+ adapter = _bindingAdapters.remove(binding);
+ }
+ if(adapter != null)
+ {
+ _vhost.getQueueAdapter(binding.getQueue()).bindingUnregistered(binding);
+ childRemoved(adapter);
+ }
+ }
+
+ org.apache.qpid.server.exchange.Exchange getExchange()
+ {
+ return _exchange;
+ }
+
+ @Override
+ public Object getAttribute(String name)
+ {
+ if(ID.equals(name))
+ {
+ return getId();
+ }
+ else if(NAME.equals(name))
+ {
+ return getName();
+ }
+ else if(STATE.equals(name))
+ {
+ return State.ACTIVE;
+ }
+ else if(DURABLE.equals(name))
+ {
+ return isDurable();
+ }
+ else if(LIFETIME_POLICY.equals(name))
+ {
+ return _exchange.isAutoDelete() ? LifetimePolicy.AUTO_DELETE : LifetimePolicy.PERMANENT;
+ }
+ else if(TIME_TO_LIVE.equals(name))
+ {
+
+ }
+ else if(CREATED.equals(name))
+ {
+
+ }
+ else if(UPDATED.equals(name))
+ {
+
+ }
+ else if(ALTERNATE_EXCHANGE.equals(name))
+ {
+ return _exchange.getAlternateExchange();
+ }
+ else if(TYPE.equals(name))
+ {
+ return _exchange.getType().getName().asString();
+ }
+ return super.getAttribute(name);
+ }
+
+ @Override
+ public Object setAttribute(String name, Object expected, Object desired)
+ throws IllegalStateException, AccessControlException, IllegalArgumentException
+ {
+ return super.setAttribute(name, expected, desired); //TODO - Implement
+ }
+
+ @Override
+ public Collection<String> getAttributeNames()
+ {
+ return AVAILABLE_ATTRIBUTES;
+ }
+
+ @Override
+ public State setDesiredState(State currentState, State desiredState) throws IllegalStateTransitionException,
+ AccessControlException
+ {
+ if (desiredState == State.DELETED)
+ {
+ delete();
+ return State.DELETED;
+ }
+ return super.setDesiredState(currentState, desiredState);
+ }
+
+ private class ExchangeStatistics implements Statistics
+ {
+
+ public Collection<String> getStatisticNames()
+ {
+ return AVAILABLE_STATISTICS;
+ }
+
+ public Object getStatistic(String name)
+ {
+ if(BINDING_COUNT.equals(name))
+ {
+ return _exchange.getBindingCount();
+ }
+ else if(BYTES_DROPPED.equals(name))
+ {
+ return _exchange.getByteDrops();
+ }
+ else if(BYTES_IN.equals(name))
+ {
+ return _exchange.getByteReceives();
+ }
+ else if(MESSAGES_DROPPED.equals(name))
+ {
+ return _exchange.getMsgDrops();
+ }
+ else if(MESSAGES_IN.equals(name))
+ {
+ return _exchange.getMsgReceives();
+ }
+ else if(PRODUCER_COUNT.equals(name))
+ {
+
+ }
+ else if(STATE_CHANGED.equals(name))
+ {
+
+ }
+ return null; // TODO - Implement
+ }
+ }
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/model/adapter/HTTPPortAdapter.java b/java/broker/src/main/java/org/apache/qpid/server/model/adapter/HTTPPortAdapter.java
new file mode 100644
index 0000000000..823d27160b
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/model/adapter/HTTPPortAdapter.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.server.model.adapter;
+
+import java.security.AccessControlException;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Map;
+import org.apache.qpid.server.model.ConfiguredObject;
+import org.apache.qpid.server.model.Connection;
+import org.apache.qpid.server.model.LifetimePolicy;
+import org.apache.qpid.server.model.Port;
+import org.apache.qpid.server.model.Protocol;
+import org.apache.qpid.server.model.State;
+import org.apache.qpid.server.model.Statistics;
+import org.apache.qpid.server.model.Transport;
+import org.apache.qpid.server.model.UUIDGenerator;
+import org.apache.qpid.server.model.VirtualHostAlias;
+
+public class HTTPPortAdapter extends AbstractAdapter implements Port
+{
+ private final BrokerAdapter _broker;
+ private final int _port;
+ private final Protocol _protocol;
+ private final Transport _transport;
+
+ public HTTPPortAdapter(BrokerAdapter brokerAdapter, int port)
+ {
+ this(brokerAdapter, port, Protocol.HTTP, Transport.TCP);
+ }
+
+ public HTTPPortAdapter(BrokerAdapter brokerAdapter, int port, Protocol protocol, Transport transport)
+ {
+ super(UUIDGenerator.generateRandomUUID());
+ _broker = brokerAdapter;
+ _port = port;
+ _protocol = protocol;
+ _transport = transport;
+ }
+
+ @Override
+ public String getBindingAddress()
+ {
+ return "0.0.0.0";
+ }
+
+ @Override
+ public int getPort()
+ {
+ return _port;
+ }
+
+ @Override
+ public Collection<Transport> getTransports()
+ {
+ return Collections.singleton(_transport);
+ }
+
+ @Override
+ public void addTransport(Transport transport)
+ throws IllegalStateException, AccessControlException, IllegalArgumentException
+ {
+ throw new IllegalStateException(); // TODO - Implement
+ }
+
+ @Override
+ public Transport removeTransport(Transport transport)
+ throws IllegalStateException, AccessControlException, IllegalArgumentException
+ {
+ throw new IllegalStateException(); // TODO - Implement
+ }
+
+ @Override
+ public Collection<Protocol> getProtocols()
+ {
+ return Collections.singleton(_protocol);
+ }
+
+ @Override
+ public void addProtocol(Protocol protocol)
+ throws IllegalStateException, AccessControlException, IllegalArgumentException
+ {
+ throw new IllegalStateException(); // TODO - Implement
+ }
+
+ @Override
+ public Protocol removeProtocol(Protocol protocol)
+ throws IllegalStateException, AccessControlException, IllegalArgumentException
+ {
+ throw new IllegalStateException(); // TODO - Implement
+ }
+
+ @Override
+ public Collection<VirtualHostAlias> getVirtualHostBindings()
+ {
+ return Collections.emptySet();
+ }
+
+ @Override
+ public Collection<Connection> getConnections()
+ {
+ return Collections.emptySet(); // TODO - Implement
+ }
+
+ @Override
+ public String getName()
+ {
+ return getBindingAddress() + ":" + getPort(); // TODO - Implement
+ }
+
+ @Override
+ public String setName(String currentName, String desiredName) throws IllegalStateException, AccessControlException
+ {
+ throw new IllegalStateException(); // TODO - Implement
+ }
+
+ @Override
+ public State getActualState()
+ {
+ return State.ACTIVE;
+ }
+
+ @Override
+ public boolean isDurable()
+ {
+ return false; // TODO - Implement
+ }
+
+ @Override
+ public void setDurable(boolean durable)
+ throws IllegalStateException, AccessControlException, IllegalArgumentException
+ {
+ throw new IllegalStateException();
+ }
+
+ @Override
+ public LifetimePolicy getLifetimePolicy()
+ {
+ return LifetimePolicy.PERMANENT;
+ }
+
+ @Override
+ public LifetimePolicy setLifetimePolicy(LifetimePolicy expected, LifetimePolicy desired)
+ throws IllegalStateException, AccessControlException, IllegalArgumentException
+ {
+ throw new IllegalStateException(); // TODO - Implement
+ }
+
+ @Override
+ public long getTimeToLive()
+ {
+ return 0; // TODO - Implement
+ }
+
+ @Override
+ public long setTimeToLive(long expected, long desired)
+ throws IllegalStateException, AccessControlException, IllegalArgumentException
+ {
+ throw new IllegalStateException(); // TODO - Implement
+ }
+
+ @Override
+ public Statistics getStatistics()
+ {
+ return NoStatistics.getInstance();
+ }
+
+ @Override
+ public <C extends ConfiguredObject> Collection<C> getChildren(Class<C> clazz)
+ {
+ if(clazz == Connection.class)
+ {
+ return (Collection<C>) getConnections();
+ }
+ else
+ {
+ return Collections.emptySet();
+ }
+ }
+
+ @Override
+ public <C extends ConfiguredObject> C createChild(Class<C> childClass, Map<String, Object> attributes, ConfiguredObject... otherParents)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public Object getAttribute(String name)
+ {
+ if(ID.equals(name))
+ {
+ return getId();
+ }
+ else if(NAME.equals(name))
+ {
+ return getName();
+ }
+ else if(STATE.equals(name))
+ {
+ return getActualState();
+ }
+ else if(DURABLE.equals(name))
+ {
+ return isDurable();
+ }
+ else if(LIFETIME_POLICY.equals(name))
+ {
+ return getLifetimePolicy();
+ }
+ else if(TIME_TO_LIVE.equals(name))
+ {
+ return getTimeToLive();
+ }
+ else if(CREATED.equals(name))
+ {
+
+ }
+ else if(UPDATED.equals(name))
+ {
+
+ }
+ else if(BINDING_ADDRESS.equals(name))
+ {
+ return getBindingAddress();
+ }
+ else if(PORT.equals(name))
+ {
+ return getPort();
+ }
+ else if(PROTOCOLS.equals(name))
+ {
+ return getProtocols();
+ }
+ else if(TRANSPORTS.equals(name))
+ {
+ return getTransports();
+ }
+
+ return super.getAttribute(name); //TODO - Implement
+ }
+
+ @Override
+ public Collection<String> getAttributeNames()
+ {
+ return AVAILABLE_ATTRIBUTES;
+ }
+
+ @Override
+ public Object setAttribute(String name, Object expected, Object desired)
+ throws IllegalStateException, AccessControlException, IllegalArgumentException
+ {
+ return super.setAttribute(name, expected, desired); //TODO - Implement
+ }
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/model/adapter/NoStatistics.java b/java/broker/src/main/java/org/apache/qpid/server/model/adapter/NoStatistics.java
new file mode 100644
index 0000000000..03fdbd1e85
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/model/adapter/NoStatistics.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.server.model.adapter;
+
+import org.apache.qpid.server.model.Statistics;
+
+import java.util.Collection;
+import java.util.Collections;
+
+public class NoStatistics implements Statistics
+{
+ private static final NoStatistics INSTANCE = new NoStatistics();
+
+ private NoStatistics()
+ {
+ }
+
+ public Collection<String> getStatisticNames()
+ {
+ return Collections.emptyList();
+ }
+
+ public Object getStatistic(String name)
+ {
+ return null;
+ }
+
+ public static NoStatistics getInstance()
+ {
+ return INSTANCE;
+ }
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/model/adapter/PortAdapter.java b/java/broker/src/main/java/org/apache/qpid/server/model/adapter/PortAdapter.java
new file mode 100644
index 0000000000..7653fcc9b9
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/model/adapter/PortAdapter.java
@@ -0,0 +1,320 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.model.adapter;
+
+import java.util.Map;
+import org.apache.qpid.server.model.ConfiguredObject;
+import org.apache.qpid.server.model.Connection;
+import org.apache.qpid.server.model.LifetimePolicy;
+import org.apache.qpid.server.model.Port;
+import org.apache.qpid.server.model.Protocol;
+import org.apache.qpid.server.model.State;
+import org.apache.qpid.server.model.Statistics;
+import org.apache.qpid.server.model.Transport;
+import org.apache.qpid.server.model.UUIDGenerator;
+import org.apache.qpid.server.model.VirtualHost;
+import org.apache.qpid.server.model.VirtualHostAlias;
+import org.apache.qpid.server.protocol.AmqpProtocolVersion;
+import org.apache.qpid.server.transport.QpidAcceptor;
+
+import java.net.InetSocketAddress;
+import java.security.AccessControlException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+public class PortAdapter extends AbstractAdapter implements Port
+{
+ private final BrokerAdapter _broker;
+ private final QpidAcceptor _acceptor;
+ private final InetSocketAddress _address;
+ private final Collection<Protocol> _protocols;
+
+ public PortAdapter(BrokerAdapter brokerAdapter, QpidAcceptor acceptor, InetSocketAddress address)
+ {
+ super(UUIDGenerator.generateRandomUUID());
+ _broker = brokerAdapter;
+ _acceptor = acceptor;
+ _address = address;
+
+ List<Protocol> protocols = new ArrayList<Protocol>();
+
+ for(AmqpProtocolVersion pv : _acceptor.getSupported())
+ {
+ switch(pv)
+ {
+ case v0_8:
+ protocols.add(Protocol.AMQP_0_8);
+ break;
+ case v0_9:
+ protocols.add(Protocol.AMQP_0_9);
+ break;
+ case v0_9_1:
+ protocols.add(Protocol.AMQP_0_9_1);
+ break;
+ case v0_10:
+ protocols.add(Protocol.AMQP_0_10);
+ break;
+ case v1_0_0:
+ protocols.add(Protocol.AMQP_1_0);
+ break;
+ }
+ }
+
+ _protocols = Collections.unmodifiableCollection(protocols);
+
+ }
+
+ @Override
+ public String getBindingAddress()
+ {
+ return _address.getHostName();
+ }
+
+ @Override
+ public int getPort()
+ {
+ return _address.getPort();
+ }
+
+ @Override
+ public Collection<Transport> getTransports()
+ {
+ switch (_acceptor.getTransport())
+ {
+ case TCP:
+ return Collections.singleton(Transport.TCP);
+ case SSL:
+ return Collections.singleton(Transport.SSL);
+ }
+
+ return null; // TODO - Implement
+ }
+
+ @Override
+ public void addTransport(Transport transport)
+ throws IllegalStateException, AccessControlException, IllegalArgumentException
+ {
+ throw new IllegalStateException(); // TODO - Implement
+ }
+
+ @Override
+ public Transport removeTransport(Transport transport)
+ throws IllegalStateException, AccessControlException, IllegalArgumentException
+ {
+ throw new IllegalStateException(); // TODO - Implement
+ }
+
+ @Override
+ public Collection<Protocol> getProtocols()
+ {
+ return _protocols;
+ }
+
+ @Override
+ public void addProtocol(Protocol protocol)
+ throws IllegalStateException, AccessControlException, IllegalArgumentException
+ {
+ throw new IllegalStateException(); // TODO - Implement
+ }
+
+ @Override
+ public Protocol removeProtocol(Protocol protocol)
+ throws IllegalStateException, AccessControlException, IllegalArgumentException
+ {
+ throw new IllegalStateException(); // TODO - Implement
+ }
+
+ @Override
+ public Collection<VirtualHostAlias> getVirtualHostBindings()
+ {
+ List<VirtualHostAlias> aliases = new ArrayList<VirtualHostAlias>();
+ for(VirtualHost vh : _broker.getVirtualHosts())
+ {
+ for(VirtualHostAlias alias : vh.getAliases())
+ {
+ if(alias.getPort().equals(this))
+ {
+ aliases.add(alias);
+ }
+ }
+ }
+ return Collections.unmodifiableCollection(aliases);
+ }
+
+ @Override
+ public Collection<Connection> getConnections()
+ {
+ return null; // TODO - Implement
+ }
+
+ @Override
+ public String getName()
+ {
+ return getBindingAddress() + ":" + getPort(); // TODO - Implement
+ }
+
+ @Override
+ public String setName(String currentName, String desiredName) throws IllegalStateException, AccessControlException
+ {
+ throw new IllegalStateException(); // TODO - Implement
+ }
+
+ @Override
+ public State getActualState()
+ {
+ return State.ACTIVE;
+ }
+
+ @Override
+ public boolean isDurable()
+ {
+ return false; // TODO - Implement
+ }
+
+ @Override
+ public void setDurable(boolean durable)
+ throws IllegalStateException, AccessControlException, IllegalArgumentException
+ {
+ throw new IllegalStateException();
+ }
+
+ @Override
+ public LifetimePolicy getLifetimePolicy()
+ {
+ return LifetimePolicy.PERMANENT;
+ }
+
+ @Override
+ public LifetimePolicy setLifetimePolicy(LifetimePolicy expected, LifetimePolicy desired)
+ throws IllegalStateException, AccessControlException, IllegalArgumentException
+ {
+ throw new IllegalStateException(); // TODO - Implement
+ }
+
+ @Override
+ public long getTimeToLive()
+ {
+ return 0; // TODO - Implement
+ }
+
+ @Override
+ public long setTimeToLive(long expected, long desired)
+ throws IllegalStateException, AccessControlException, IllegalArgumentException
+ {
+ throw new IllegalStateException(); // TODO - Implement
+ }
+
+ @Override
+ public Statistics getStatistics()
+ {
+ return NoStatistics.getInstance();
+ }
+
+ @Override
+ public <C extends ConfiguredObject> Collection<C> getChildren(Class<C> clazz)
+ {
+ if(clazz == Connection.class)
+ {
+ return (Collection<C>) getConnections();
+ }
+ else
+ {
+ return Collections.emptySet();
+ }
+ }
+
+ @Override
+ public <C extends ConfiguredObject> C createChild(Class<C> childClass, Map<String, Object> attributes, ConfiguredObject... otherParents)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public Object getAttribute(String name)
+ {
+ if(ID.equals(name))
+ {
+ return getId();
+ }
+ else if(NAME.equals(name))
+ {
+ return getName();
+ }
+ else if(STATE.equals(name))
+ {
+ return getActualState();
+ }
+ else if(DURABLE.equals(name))
+ {
+ return isDurable();
+ }
+ else if(LIFETIME_POLICY.equals(name))
+ {
+ return getLifetimePolicy();
+ }
+ else if(TIME_TO_LIVE.equals(name))
+ {
+ return getTimeToLive();
+ }
+ else if(CREATED.equals(name))
+ {
+
+ }
+ else if(UPDATED.equals(name))
+ {
+
+ }
+ else if(BINDING_ADDRESS.equals(name))
+ {
+ return getBindingAddress();
+ }
+ else if(PORT.equals(name))
+ {
+ return getPort();
+ }
+ else if(PROTOCOLS.equals(name))
+ {
+ return getProtocols();
+ }
+ else if(TRANSPORTS.equals(name))
+ {
+ return getTransports();
+ }
+
+ return super.getAttribute(name); //TODO - Implement
+ }
+
+ @Override
+ public Collection<String> getAttributeNames()
+ {
+ return AVAILABLE_ATTRIBUTES;
+ }
+
+ @Override
+ public Object setAttribute(String name, Object expected, Object desired)
+ throws IllegalStateException, AccessControlException, IllegalArgumentException
+ {
+ return super.setAttribute(name, expected, desired); //TODO - Implement
+ }
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/model/adapter/QueueAdapter.java b/java/broker/src/main/java/org/apache/qpid/server/model/adapter/QueueAdapter.java
new file mode 100644
index 0000000000..78f6d38d93
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/model/adapter/QueueAdapter.java
@@ -0,0 +1,726 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.model.adapter;
+
+import java.security.AccessControlException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.apache.qpid.AMQException;
+import org.apache.qpid.AMQStoreException;
+import org.apache.qpid.server.binding.Binding;
+import org.apache.qpid.server.model.ConfiguredObject;
+import org.apache.qpid.server.model.ConfiguredObjectFinder;
+import org.apache.qpid.server.model.Consumer;
+import org.apache.qpid.server.model.Exchange;
+import org.apache.qpid.server.model.IllegalStateTransitionException;
+import org.apache.qpid.server.model.LifetimePolicy;
+import org.apache.qpid.server.model.Queue;
+import org.apache.qpid.server.model.QueueNotificationListener;
+import org.apache.qpid.server.model.State;
+import org.apache.qpid.server.model.Statistics;
+import org.apache.qpid.server.queue.*;
+import org.apache.qpid.server.subscription.Subscription;
+
+final class QueueAdapter extends AbstractAdapter implements Queue, AMQQueue.SubscriptionRegistrationListener, AMQQueue.NotificationListener
+{
+
+ static final Map<String, String> ATTRIBUTE_MAPPINGS = new HashMap<String, String>();
+ static
+ {
+ QueueAdapter.ATTRIBUTE_MAPPINGS.put(Queue.ALERT_REPEAT_GAP, "x-qpid-minimum-alert-repeat-gap");
+ QueueAdapter.ATTRIBUTE_MAPPINGS.put(Queue.ALERT_THRESHOLD_MESSAGE_AGE, "x-qpid-maximum-message-age");
+ QueueAdapter.ATTRIBUTE_MAPPINGS.put(Queue.ALERT_THRESHOLD_MESSAGE_SIZE, "x-qpid-maximum-message-size");
+ QueueAdapter.ATTRIBUTE_MAPPINGS.put(Queue.ALERT_THRESHOLD_QUEUE_DEPTH_MESSAGES, "x-qpid-maximum-message-count");
+
+ QueueAdapter.ATTRIBUTE_MAPPINGS.put(Queue.MAXIMUM_DELIVERY_ATTEMPTS, "x-qpid-maximum-delivery-count");
+
+ QueueAdapter.ATTRIBUTE_MAPPINGS.put(Queue.QUEUE_FLOW_CONTROL_SIZE_BYTES, "x-qpid-capacity");
+ QueueAdapter.ATTRIBUTE_MAPPINGS.put(Queue.QUEUE_FLOW_RESUME_SIZE_BYTES, "x-qpid-flow-resume-capacity");
+
+ QueueAdapter.ATTRIBUTE_MAPPINGS.put(Queue.SORT_KEY, AMQQueueFactory.QPID_QUEUE_SORT_KEY);
+ QueueAdapter.ATTRIBUTE_MAPPINGS.put(Queue.LVQ_KEY, AMQQueueFactory.QPID_LAST_VALUE_QUEUE_KEY);
+ QueueAdapter.ATTRIBUTE_MAPPINGS.put(Queue.PRIORITIES, AMQQueueFactory.X_QPID_PRIORITIES);
+ }
+
+ private final AMQQueue _queue;
+ private final Map<Binding, BindingAdapter> _bindingAdapters =
+ new HashMap<Binding, BindingAdapter>();
+ private Map<org.apache.qpid.server.subscription.Subscription, ConsumerAdapter> _consumerAdapters =
+ new HashMap<org.apache.qpid.server.subscription.Subscription, ConsumerAdapter>();
+
+
+ private final VirtualHostAdapter _vhost;
+ private QueueStatisticsAdapter _statistics;
+ private QueueNotificationListener _queueNotificationListener;
+
+ public QueueAdapter(final VirtualHostAdapter virtualHostAdapter, final AMQQueue queue)
+ {
+ super(queue.getId());
+ _vhost = virtualHostAdapter;
+ addParent(org.apache.qpid.server.model.VirtualHost.class, virtualHostAdapter);
+
+ _queue = queue;
+ _queue.addSubscriptionRegistrationListener(this);
+ populateConsumers();
+ _statistics = new QueueStatisticsAdapter(queue);
+ _queue.setNotificationListener(this);
+ }
+
+ private void populateConsumers()
+ {
+ Collection<org.apache.qpid.server.subscription.Subscription> actualSubscriptions = _queue.getConsumers();
+
+ synchronized (_consumerAdapters)
+ {
+ Iterator<org.apache.qpid.server.subscription.Subscription> iter = _consumerAdapters.keySet().iterator();
+ for(org.apache.qpid.server.subscription.Subscription subscription : actualSubscriptions)
+ {
+ if(!_consumerAdapters.containsKey(subscription))
+ {
+ _consumerAdapters.put(subscription, new ConsumerAdapter(this, subscription));
+ }
+ }
+ }
+ }
+
+ public Collection<org.apache.qpid.server.model.Binding> getBindings()
+ {
+ synchronized (_bindingAdapters)
+ {
+ return new ArrayList<org.apache.qpid.server.model.Binding>(_bindingAdapters.values());
+ }
+ }
+
+ public Collection<Consumer> getConsumers()
+ {
+ synchronized (_consumerAdapters)
+ {
+ return new ArrayList<Consumer>(_consumerAdapters.values());
+ }
+
+ }
+
+ public void visit(final QueueEntryVisitor visitor)
+ {
+ _queue.visit(visitor);
+ }
+
+ public void delete()
+ {
+ try
+ {
+ QueueRegistry queueRegistry = _queue.getVirtualHost().getQueueRegistry();
+ synchronized(queueRegistry)
+ {
+ _queue.delete();
+ if (_queue.isDurable())
+ {
+ _queue.getVirtualHost().getMessageStore().removeQueue(_queue);
+ }
+ }
+ }
+ catch(AMQException e)
+ {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ public String getName()
+ {
+ return _queue.getName();
+ }
+
+ public String setName(final String currentName, final String desiredName)
+ throws IllegalStateException, AccessControlException
+ {
+ return null; //TODO
+ }
+
+ public State getActualState()
+ {
+ return null; //TODO
+ }
+
+ public boolean isDurable()
+ {
+ return _queue.isDurable();
+ }
+
+ public void setDurable(final boolean durable)
+ throws IllegalStateException, AccessControlException, IllegalArgumentException
+ {
+ //TODO
+ }
+
+ public LifetimePolicy getLifetimePolicy()
+ {
+ return _queue.isAutoDelete() ? LifetimePolicy.AUTO_DELETE : LifetimePolicy.PERMANENT;
+ }
+
+ public LifetimePolicy setLifetimePolicy(final LifetimePolicy expected, final LifetimePolicy desired)
+ throws IllegalStateException, AccessControlException, IllegalArgumentException
+ {
+ return null; //TODO
+ }
+
+ public long getTimeToLive()
+ {
+ return 0; //TODO
+ }
+
+ public long setTimeToLive(final long expected, final long desired)
+ throws IllegalStateException, AccessControlException, IllegalArgumentException
+ {
+ return 0; //TODO
+ }
+
+
+ @Override
+ public Collection<String> getAttributeNames()
+ {
+ return Queue.AVAILABLE_ATTRIBUTES;
+ }
+
+ @Override
+ public Object setAttribute(String name, Object expected, Object desired) throws IllegalStateException, AccessControlException, IllegalArgumentException
+ {
+ try
+ {
+ if(ALERT_REPEAT_GAP.equals(name))
+ {
+ _queue.setMinimumAlertRepeatGap((Long)desired);
+ return desired;
+ }
+ else if(ALERT_THRESHOLD_MESSAGE_AGE.equals(name))
+ {
+ _queue.setMaximumMessageAge((Long)desired);
+ return desired;
+ }
+ else if(ALERT_THRESHOLD_MESSAGE_SIZE.equals(name))
+ {
+ _queue.setMaximumMessageSize((Long)desired);
+ return desired;
+ }
+ else if(ALERT_THRESHOLD_QUEUE_DEPTH_BYTES.equals(name))
+ {
+ _queue.setMaximumQueueDepth((Long)desired);
+ return desired;
+ }
+ else if(ALERT_THRESHOLD_QUEUE_DEPTH_MESSAGES.equals(name))
+ {
+ _queue.setMaximumMessageCount((Long)desired);
+ return desired;
+ }
+ else if(ALTERNATE_EXCHANGE.equals(name))
+ {
+ // In future we may want to accept a UUID as an alternative way to identifying the exchange
+ ExchangeAdapter alternateExchange = (ExchangeAdapter) desired;
+ _queue.setAlternateExchange(alternateExchange == null ? null : alternateExchange.getExchange());
+ return desired;
+ }
+ else if(EXCLUSIVE.equals(name))
+ {
+ Boolean exclusiveFlag = (Boolean) desired;
+ _queue.setExclusive(exclusiveFlag);
+ return desired;
+ }
+ else if(MESSAGE_GROUP_KEY.equals(name))
+ {
+ // TODO
+ }
+ else if(MESSAGE_GROUP_DEFAULT_GROUP.equals(name))
+ {
+ // TODO
+ }
+ else if(MESSAGE_GROUP_SHARED_GROUPS.equals(name))
+ {
+ // TODO
+ }
+ else if(LVQ_KEY.equals(name))
+ {
+ // TODO
+ }
+ else if(MAXIMUM_DELIVERY_ATTEMPTS.equals(name))
+ {
+ _queue.setMaximumDeliveryCount((Integer)desired);
+ return desired;
+ }
+ else if(NO_LOCAL.equals(name))
+ {
+ // TODO
+ }
+ else if(OWNER.equals(name))
+ {
+ // TODO
+ }
+ else if(QUEUE_FLOW_CONTROL_SIZE_BYTES.equals(name))
+ {
+ _queue.setCapacity((Long)desired);
+ return desired;
+ }
+ else if(QUEUE_FLOW_RESUME_SIZE_BYTES.equals(name))
+ {
+ _queue.setFlowResumeCapacity((Long)desired);
+ return desired;
+ }
+ else if(QUEUE_FLOW_STOPPED.equals(name))
+ {
+ // TODO
+ }
+ else if(SORT_KEY.equals(name))
+ {
+ // TODO
+ }
+ else if(TYPE.equals(name))
+ {
+ // TODO
+ }
+ else if (DESCRIPTION.equals(name))
+ {
+ _queue.setDescription((String) desired);
+ return desired;
+ }
+
+ return super.setAttribute(name, expected, desired);
+ }
+ finally
+ {
+ if (_queue.isDurable())
+ {
+ try
+ {
+ _queue.getVirtualHost().getMessageStore().updateQueue(_queue);
+ }
+ catch (AMQStoreException e)
+ {
+ throw new IllegalStateException(e);
+ }
+ }
+ }
+ }
+
+ @Override
+ public Object getAttribute(String name)
+ {
+
+ if(ALERT_REPEAT_GAP.equals(name))
+ {
+ return _queue.getMinimumAlertRepeatGap();
+ }
+ else if(ALERT_THRESHOLD_MESSAGE_AGE.equals(name))
+ {
+ return _queue.getMaximumMessageAge();
+ }
+ else if(ALERT_THRESHOLD_MESSAGE_SIZE.equals(name))
+ {
+ return _queue.getMaximumMessageSize();
+ }
+ else if(ALERT_THRESHOLD_QUEUE_DEPTH_BYTES.equals(name))
+ {
+ return _queue.getMaximumQueueDepth();
+ }
+ else if(ALERT_THRESHOLD_QUEUE_DEPTH_MESSAGES.equals(name))
+ {
+ return _queue.getMaximumMessageCount();
+ }
+ else if(ALTERNATE_EXCHANGE.equals(name))
+ {
+ org.apache.qpid.server.exchange.Exchange alternateExchange = _queue.getAlternateExchange();
+ return alternateExchange == null ? null :
+ ConfiguredObjectFinder.findConfiguredObjectByName(_vhost.getExchanges(),
+ alternateExchange.getName());
+ }
+ else if(EXCLUSIVE.equals(name))
+ {
+ return _queue.isExclusive();
+ }
+ else if(MESSAGE_GROUP_KEY.equals(name))
+ {
+ // TODO
+ }
+ else if(MESSAGE_GROUP_DEFAULT_GROUP.equals(name))
+ {
+ // TODO
+ }
+ else if(MESSAGE_GROUP_SHARED_GROUPS.equals(name))
+ {
+ // TODO
+ }
+ else if(LVQ_KEY.equals(name))
+ {
+ if(_queue instanceof ConflationQueue)
+ {
+ return ((ConflationQueue)_queue).getConflationKey();
+ }
+ }
+ else if(MAXIMUM_DELIVERY_ATTEMPTS.equals(name))
+ {
+ return _queue.getMaximumDeliveryCount();
+ }
+ else if(NO_LOCAL.equals(name))
+ {
+ // TODO
+ }
+ else if(OWNER.equals(name))
+ {
+ return _queue.getOwner() == null ? null : _queue.getOwner().asString();
+ }
+ else if(QUEUE_FLOW_CONTROL_SIZE_BYTES.equals(name))
+ {
+ return _queue.getCapacity();
+ }
+ else if(QUEUE_FLOW_RESUME_SIZE_BYTES.equals(name))
+ {
+ return _queue.getFlowResumeCapacity();
+ }
+ else if(QUEUE_FLOW_STOPPED.equals(name))
+ {
+ return _queue.isOverfull();
+ }
+ else if(SORT_KEY.equals(name))
+ {
+ if(_queue instanceof SortedQueue)
+ {
+ return ((SortedQueue)_queue).getSortedPropertyName();
+ }
+ }
+ else if(TYPE.equals(name))
+ {
+ if(_queue instanceof SortedQueue)
+ {
+ return "sorted";
+ }
+ if(_queue instanceof ConflationQueue)
+ {
+ return "lvq";
+ }
+ if(_queue instanceof AMQPriorityQueue)
+ {
+ return "priority";
+ }
+ return "standard";
+ }
+ else if(CREATED.equals(name))
+ {
+ // TODO
+ }
+ else if(DURABLE.equals(name))
+ {
+ return _queue.isDurable();
+ }
+ else if(ID.equals(name))
+ {
+ return getId();
+ }
+ else if(LIFETIME_POLICY.equals(name))
+ {
+ return _queue.isAutoDelete() ? LifetimePolicy.AUTO_DELETE : LifetimePolicy.PERMANENT;
+ }
+ else if(NAME.equals(name))
+ {
+ return _queue.getName();
+ }
+ else if(STATE.equals(name))
+ {
+ return State.ACTIVE; // TODO
+ }
+ else if(TIME_TO_LIVE.equals(name))
+ {
+ // TODO
+ }
+ else if(UPDATED.equals(name))
+ {
+ // TODO
+ }
+ else if (DESCRIPTION.equals(name))
+ {
+ return _queue.getDescription();
+ }
+ else if(PRIORITIES.equals(name))
+ {
+ if(_queue instanceof AMQPriorityQueue)
+ {
+ return ((AMQPriorityQueue)_queue).getPriorities();
+ }
+ }
+ return super.getAttribute(name);
+ }
+
+ public Statistics getStatistics()
+ {
+ return _statistics;
+ }
+
+ @Override
+ public <C extends ConfiguredObject> Collection<C> getChildren(Class<C> clazz)
+ {
+ if(clazz == Consumer.class)
+ {
+ return (Collection<C>) getConsumers();
+ }
+ else if(clazz == org.apache.qpid.server.model.Binding.class)
+ {
+ return (Collection<C>) getBindings();
+ }
+ else
+ {
+ return Collections.emptySet();
+ }
+ }
+
+ public org.apache.qpid.server.model.Binding createBinding(Exchange exchange, Map<String, Object> attributes)
+ throws AccessControlException, IllegalStateException
+ {
+ attributes = new HashMap<String, Object>(attributes);
+ String bindingKey = getStringAttribute(org.apache.qpid.server.model.Binding.NAME, attributes, "");
+ Map<String, Object> bindingArgs = getMapAttribute(org.apache.qpid.server.model.Binding.ARGUMENTS, attributes, Collections.EMPTY_MAP);
+
+ attributes.remove(org.apache.qpid.server.model.Binding.NAME);
+ attributes.remove(org.apache.qpid.server.model.Binding.ARGUMENTS);
+
+ return exchange.createBinding(bindingKey, this, bindingArgs, attributes);
+
+ }
+
+
+
+ @Override
+ public <C extends ConfiguredObject> C createChild(Class<C> childClass, Map<String, Object> attributes, ConfiguredObject... otherParents)
+ {
+ if(childClass == org.apache.qpid.server.model.Binding.class)
+ {
+ if(otherParents != null && otherParents.length == 1 && otherParents[0] instanceof Exchange)
+ {
+ Exchange exchange = (Exchange) otherParents[0];
+ if(exchange.getParent(org.apache.qpid.server.model.VirtualHost.class) == getParent(org.apache.qpid.server.model.VirtualHost.class))
+ {
+ return (C) createBinding(exchange, attributes);
+ }
+ else
+ {
+ throw new IllegalArgumentException("Queue and Exchange parents of a binding must be on same virtual host");
+ }
+ }
+ else
+ {
+ throw new IllegalArgumentException("Other parent must be an exchange");
+ }
+ }
+ else
+ {
+ throw new IllegalArgumentException();
+ }
+ }
+
+ void bindingRegistered(Binding binding, BindingAdapter adapter)
+ {
+ synchronized (_bindingAdapters)
+ {
+ _bindingAdapters.put(binding, adapter);
+ }
+ childAdded(adapter);
+ }
+
+ void bindingUnregistered(Binding binding)
+ {
+ BindingAdapter adapter = null;
+ synchronized (_bindingAdapters)
+ {
+ adapter = _bindingAdapters.remove(binding);
+ }
+ if(adapter != null)
+ {
+ childRemoved(adapter);
+ }
+ }
+
+ AMQQueue getAMQQueue()
+ {
+ return _queue;
+ }
+
+ public void subscriptionRegistered(final AMQQueue queue, final Subscription subscription)
+ {
+ ConsumerAdapter adapter = null;
+ synchronized (_consumerAdapters)
+ {
+ if(!_consumerAdapters.containsKey(subscription))
+ {
+ adapter = new ConsumerAdapter(this, subscription);
+ _consumerAdapters.put(subscription,adapter);
+ // TODO - register with session
+ }
+ }
+ if(adapter != null)
+ {
+ childAdded(adapter);
+ }
+ }
+
+ public void subscriptionUnregistered(final AMQQueue queue, final Subscription subscription)
+ {
+ ConsumerAdapter adapter = null;
+
+ synchronized (_consumerAdapters)
+ {
+ adapter = _consumerAdapters.remove(subscription);
+ // TODO - register with session
+ }
+ if(adapter != null)
+ {
+ childRemoved(adapter);
+ }
+ }
+
+ VirtualHostAdapter getVirtualHost()
+ {
+ return _vhost;
+ }
+
+
+ private static class QueueStatisticsAdapter implements Statistics
+ {
+
+ private final AMQQueue _queue;
+
+ public QueueStatisticsAdapter(AMQQueue queue)
+ {
+ _queue = queue;
+ }
+
+ public Collection<String> getStatisticNames()
+ {
+ return Queue.AVAILABLE_STATISTICS;
+ }
+
+ public Object getStatistic(String name)
+ {
+ if(BINDING_COUNT.equals(name))
+ {
+ return _queue.getBindingCount();
+ }
+ else if(CONSUMER_COUNT.equals(name))
+ {
+ return _queue.getConsumerCount();
+ }
+ else if(CONSUMER_COUNT_WITH_CREDIT.equals(name))
+ {
+ return _queue.getActiveConsumerCount();
+ }
+ else if(DISCARDS_TTL_BYTES.equals(name))
+ {
+ return null; // TODO
+ }
+ else if(DISCARDS_TTL_MESSAGES.equals(name))
+ {
+ return null; // TODO
+ }
+ else if(PERSISTENT_DEQUEUED_BYTES.equals(name))
+ {
+ return _queue.getPersistentByteDequeues();
+ }
+ else if(PERSISTENT_DEQUEUED_MESSAGES.equals(name))
+ {
+ return _queue.getPersistentMsgDequeues();
+ }
+ else if(PERSISTENT_ENQUEUED_BYTES.equals(name))
+ {
+ return _queue.getPersistentByteEnqueues();
+ }
+ else if(PERSISTENT_ENQUEUED_MESSAGES.equals(name))
+ {
+ return _queue.getPersistentMsgEnqueues();
+ }
+ else if(QUEUE_DEPTH_BYTES.equals(name))
+ {
+ return _queue.getQueueDepth();
+ }
+ else if(QUEUE_DEPTH_MESSAGES.equals(name))
+ {
+ return _queue.getMessageCount();
+ }
+ else if(STATE_CHANGED.equals(name))
+ {
+ return null; // TODO
+ }
+ else if(TOTAL_DEQUEUED_BYTES.equals(name))
+ {
+ return _queue.getTotalDequeueSize();
+ }
+ else if(TOTAL_DEQUEUED_MESSAGES.equals(name))
+ {
+ return _queue.getTotalDequeueCount();
+ }
+ else if(TOTAL_ENQUEUED_BYTES.equals(name))
+ {
+ return _queue.getTotalEnqueueSize();
+ }
+ else if(TOTAL_ENQUEUED_MESSAGES.equals(name))
+ {
+ return _queue.getTotalEnqueueCount();
+ }
+ else if(UNACKNOWLEDGED_BYTES.equals(name))
+ {
+ return _queue.getUnackedMessageBytes();
+ }
+ else if(UNACKNOWLEDGED_MESSAGES.equals(name))
+ {
+ return _queue.getUnackedMessageCount();
+ }
+
+ return null;
+ }
+ }
+
+ @Override
+ public void setNotificationListener(QueueNotificationListener listener)
+ {
+ _queueNotificationListener = listener;
+ }
+
+ @Override
+ public void notifyClients(NotificationCheck notification, AMQQueue queue, String notificationMsg)
+ {
+ QueueNotificationListener listener = _queueNotificationListener;
+ if(listener != null)
+ {
+ listener.notifyClients(notification, this, notificationMsg);
+ }
+ }
+
+ @Override
+ public State setDesiredState(State currentState, State desiredState) throws IllegalStateTransitionException,
+ AccessControlException
+ {
+ if (desiredState == State.DELETED)
+ {
+ delete();
+ return State.DELETED;
+ }
+ return super.setDesiredState(currentState, desiredState);
+ }
+
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/model/adapter/SessionAdapter.java b/java/broker/src/main/java/org/apache/qpid/server/model/adapter/SessionAdapter.java
new file mode 100644
index 0000000000..d802697d67
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/model/adapter/SessionAdapter.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.server.model.adapter;
+
+import java.security.AccessControlException;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+
+import java.util.Map;
+import org.apache.qpid.server.model.ConfiguredObject;
+import org.apache.qpid.server.model.LifetimePolicy;
+import org.apache.qpid.server.model.Publisher;
+import org.apache.qpid.server.model.Session;
+import org.apache.qpid.server.model.State;
+import org.apache.qpid.server.model.Statistics;
+import org.apache.qpid.server.model.Consumer;
+import org.apache.qpid.server.model.UUIDGenerator;
+import org.apache.qpid.server.protocol.AMQSessionModel;
+
+final class SessionAdapter extends AbstractAdapter implements Session
+{
+ // Attributes
+
+
+ private AMQSessionModel _session;
+ private SessionStatistics _statistics;
+
+ public SessionAdapter(final AMQSessionModel session)
+ {
+ super(UUIDGenerator.generateRandomUUID());
+ _session = session;
+ _statistics = new SessionStatistics();
+ }
+
+ public Collection<Consumer> getSubscriptions()
+ {
+ return null; //TODO
+ }
+
+ public Collection<Publisher> getPublishers()
+ {
+ return null; //TODO
+ }
+
+ public String getName()
+ {
+ return String.valueOf(_session.getChannelId());
+ }
+
+ public String setName(final String currentName, final String desiredName)
+ throws IllegalStateException, AccessControlException
+ {
+ return null; //TODO
+ }
+
+ public State getActualState()
+ {
+ return null; //TODO
+ }
+
+ public boolean isDurable()
+ {
+ return false; //TODO
+ }
+
+ public void setDurable(final boolean durable)
+ throws IllegalStateException, AccessControlException, IllegalArgumentException
+ {
+ //TODO
+ }
+
+ public LifetimePolicy getLifetimePolicy()
+ {
+ return null; //TODO
+ }
+
+ public LifetimePolicy setLifetimePolicy(final LifetimePolicy expected, final LifetimePolicy desired)
+ throws IllegalStateException, AccessControlException, IllegalArgumentException
+ {
+ return null; //TODO
+ }
+
+ public long getTimeToLive()
+ {
+ return 0; //TODO
+ }
+
+ public long setTimeToLive(final long expected, final long desired)
+ throws IllegalStateException, AccessControlException, IllegalArgumentException
+ {
+ return 0; //TODO
+ }
+
+ @Override
+ public Collection<String> getAttributeNames()
+ {
+ Collection<String> names = new HashSet<String>(super.getAttributeNames());
+ names.addAll(AVAILABLE_ATTRIBUTES);
+
+ return Collections.unmodifiableCollection(names);
+ }
+
+ @Override
+ public Object getAttribute(String name)
+ {
+ if(name.equals(ID))
+ {
+ return getId();
+ }
+ else if (name.equals(NAME))
+ {
+ return getName();
+ }
+ else if(name.equals(CHANNEL_ID))
+ {
+ return _session.getChannelId();
+ }
+ else if(name.equals(PRODUCER_FLOW_BLOCKED))
+ {
+ return _session.getBlocking();
+ }
+ return super.getAttribute(name); //TODO - Implement
+ }
+
+ @Override
+ public Object setAttribute(String name, Object expected, Object desired)
+ throws IllegalStateException, AccessControlException, IllegalArgumentException
+ {
+ return super.setAttribute(name, expected, desired); //TODO - Implement
+ }
+
+ public Statistics getStatistics()
+ {
+ return _statistics;
+ }
+
+ @Override
+ public <C extends ConfiguredObject> Collection<C> getChildren(Class<C> clazz)
+ {
+ if(clazz == Consumer.class)
+ {
+ return (Collection<C>) getSubscriptions();
+ }
+ else if(clazz == Publisher.class)
+ {
+ return (Collection<C>) getPublishers();
+ }
+ else
+ {
+ return Collections.emptySet();
+ }
+ }
+
+ @Override
+ public <C extends ConfiguredObject> C createChild(Class<C> childClass, Map<String, Object> attributes, ConfiguredObject... otherParents)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ private class SessionStatistics implements Statistics
+ {
+
+ public SessionStatistics()
+ {
+ }
+
+ public Collection<String> getStatisticNames()
+ {
+ return AVAILABLE_STATISTICS;
+ }
+
+ public Object getStatistic(String name)
+ {
+ if(name.equals(BYTES_IN))
+ {
+ }
+ else if(name.equals(BYTES_OUT))
+ {
+ }
+ else if(name.equals(CONSUMER_COUNT))
+ {
+ return _session.getConsumerCount();
+ }
+ else if(name.equals(LOCAL_TRANSACTION_BEGINS))
+ {
+ return _session.getTxnStart();
+ }
+ else if(name.equals(LOCAL_TRANSACTION_OPEN))
+ {
+ long open = _session.getTxnStart() - (_session.getTxnCommits() + _session.getTxnRejects());
+ return (Boolean) (open > 0l);
+ }
+ else if(name.equals(LOCAL_TRANSACTION_ROLLBACKS))
+ {
+ return _session.getTxnRejects();
+ }
+ else if(name.equals(STATE_CHANGED))
+ {
+ }
+ else if(name.equals(UNACKNOWLEDGED_BYTES))
+ {
+ }
+ else if(name.equals(UNACKNOWLEDGED_MESSAGES))
+ {
+ return _session.getUnacknowledgedMessageCount();
+ }
+ else if(name.equals(XA_TRANSACTION_BRANCH_ENDS))
+ {
+ }
+ else if(name.equals(XA_TRANSACTION_BRANCH_STARTS))
+ {
+ }
+ else if(name.equals(XA_TRANSACTION_BRANCH_SUSPENDS))
+ {
+
+ }
+
+ return null; // TODO - Implement
+ }
+ }
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/model/adapter/StatisticsAdapter.java b/java/broker/src/main/java/org/apache/qpid/server/model/adapter/StatisticsAdapter.java
new file mode 100644
index 0000000000..28c46a0339
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/model/adapter/StatisticsAdapter.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.server.model.adapter;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import org.apache.qpid.server.model.Statistics;
+import org.apache.qpid.server.stats.StatisticsCounter;
+import org.apache.qpid.server.stats.StatisticsGatherer;
+
+class StatisticsAdapter implements Statistics
+{
+
+ private final Map<String, StatisticsCounter> _statistics =
+ new HashMap<String, StatisticsCounter>();
+
+
+ private static final String BYTES_IN = "bytesIn";
+ private static final String BYTES_OUT = "bytesOut";
+ private static final String MESSAGES_IN = "messagesIn";
+ private static final String MESSAGES_OUT = "messagesOut";
+
+ private static final Collection<String> STATISTIC_NAMES =
+ Collections.unmodifiableCollection(Arrays.asList(BYTES_IN, BYTES_OUT, MESSAGES_IN, MESSAGES_OUT));
+
+
+
+ public StatisticsAdapter(StatisticsGatherer statGatherer)
+ {
+ _statistics.put(BYTES_OUT, statGatherer.getDataDeliveryStatistics());
+ _statistics.put(BYTES_IN, statGatherer.getDataReceiptStatistics());
+ _statistics.put(MESSAGES_OUT, statGatherer.getMessageDeliveryStatistics());
+ _statistics.put(MESSAGES_IN, statGatherer.getMessageReceiptStatistics());
+ }
+
+
+ public Collection<String> getStatisticNames()
+ {
+ return STATISTIC_NAMES;
+ }
+
+ public Object getStatistic(String name)
+ {
+ StatisticsCounter counter = _statistics.get(name);
+ return counter == null ? null : counter.getTotal();
+
+ }
+
+
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/model/adapter/VirtualHostAdapter.java b/java/broker/src/main/java/org/apache/qpid/server/model/adapter/VirtualHostAdapter.java
new file mode 100644
index 0000000000..35838e51d2
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/model/adapter/VirtualHostAdapter.java
@@ -0,0 +1,892 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.model.adapter;
+
+import java.security.AccessControlException;
+import java.security.Principal;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import org.apache.qpid.AMQException;
+import org.apache.qpid.framing.FieldTable;
+import org.apache.qpid.server.connection.IConnectionRegistry;
+import org.apache.qpid.server.exchange.ExchangeRegistry;
+import org.apache.qpid.server.exchange.ExchangeType;
+import org.apache.qpid.server.message.ServerMessage;
+import org.apache.qpid.server.model.ConfiguredObject;
+import org.apache.qpid.server.model.Connection;
+import org.apache.qpid.server.model.Exchange;
+import org.apache.qpid.server.model.LifetimePolicy;
+import org.apache.qpid.server.model.Port;
+import org.apache.qpid.server.model.Queue;
+import org.apache.qpid.server.model.QueueType;
+import org.apache.qpid.server.model.State;
+import org.apache.qpid.server.model.Statistics;
+import org.apache.qpid.server.model.UUIDGenerator;
+import org.apache.qpid.server.model.VirtualHost;
+import org.apache.qpid.server.model.VirtualHostAlias;
+import org.apache.qpid.server.protocol.AMQConnectionModel;
+import org.apache.qpid.server.queue.AMQQueue;
+import org.apache.qpid.server.queue.AMQQueueFactory;
+import org.apache.qpid.server.queue.QueueEntry;
+import org.apache.qpid.server.queue.QueueRegistry;
+import org.apache.qpid.server.security.SecurityManager;
+import org.apache.qpid.server.store.MessageStore;
+import org.apache.qpid.server.txn.LocalTransaction;
+import org.apache.qpid.server.txn.ServerTransaction;
+
+final class VirtualHostAdapter extends AbstractAdapter implements VirtualHost, ExchangeRegistry.RegistryChangeListener,
+ QueueRegistry.RegistryChangeListener,
+ IConnectionRegistry.RegistryChangeListener
+{
+
+ private final org.apache.qpid.server.virtualhost.VirtualHost _virtualHost;
+
+ private final Map<AMQConnectionModel, ConnectionAdapter> _connectionAdapters =
+ new HashMap<AMQConnectionModel, ConnectionAdapter>();
+
+ private final Map<AMQQueue, QueueAdapter> _queueAdapters =
+ new HashMap<AMQQueue, QueueAdapter>();
+
+ private final Map<org.apache.qpid.server.exchange.Exchange, ExchangeAdapter> _exchangeAdapters =
+ new HashMap<org.apache.qpid.server.exchange.Exchange, ExchangeAdapter>();
+
+ private final StatisticsAdapter _statistics;
+
+ private final BrokerAdapter _broker;
+
+ private final List<VirtualHostAlias> _aliases = new ArrayList<VirtualHostAlias>();
+
+
+ VirtualHostAdapter(BrokerAdapter brokerAdapter,
+ final org.apache.qpid.server.virtualhost.VirtualHost virtualHost)
+ {
+ super(virtualHost.getId());
+ _broker = brokerAdapter;
+ _virtualHost = virtualHost;
+ _statistics = new VirtualHostStatisticsAdapter(virtualHost);
+ virtualHost.getQueueRegistry().addRegistryChangeListener(this);
+ populateQueues();
+ virtualHost.getExchangeRegistry().addRegistryChangeListener(this);
+ populateExchanges();
+ virtualHost.getConnectionRegistry().addRegistryChangeListener(this);
+ populateConnections();
+
+
+
+ for(Port port :_broker.getPorts())
+ {
+ _aliases.add(new VirtualHostAliasAdapter(this, port));
+ }
+ }
+
+
+ private void populateExchanges()
+ {
+ Collection<org.apache.qpid.server.exchange.Exchange> actualExchanges =
+ _virtualHost.getExchangeRegistry().getExchanges();
+
+ synchronized (_exchangeAdapters)
+ {
+ for(org.apache.qpid.server.exchange.Exchange exchange : actualExchanges)
+ {
+ if(!_exchangeAdapters.containsKey(exchange))
+ {
+ _exchangeAdapters.put(exchange, new ExchangeAdapter(this,exchange));
+ }
+ }
+ }
+ }
+
+
+ private void populateQueues()
+ {
+ Collection<AMQQueue> actualQueues = _virtualHost.getQueueRegistry().getQueues();
+
+ synchronized(_queueAdapters)
+ {
+ for(AMQQueue queue : actualQueues)
+ {
+ if(!_queueAdapters.containsKey(queue))
+ {
+ _queueAdapters.put(queue, new QueueAdapter(this,queue));
+ }
+ }
+ }
+ }
+
+ private void populateConnections()
+ {
+
+ List<AMQConnectionModel> actualConnections = _virtualHost.getConnectionRegistry().getConnections();
+
+ synchronized(_connectionAdapters)
+ {
+ for(AMQConnectionModel conn : actualConnections)
+ {
+ if(!_connectionAdapters.containsKey(conn))
+ {
+ _connectionAdapters.put(conn, new ConnectionAdapter(conn));
+ }
+ }
+ }
+
+ }
+
+ public String getReplicationGroupName()
+ {
+ return null; //TODO
+ }
+
+ public Collection<VirtualHostAlias> getAliases()
+ {
+ return Collections.unmodifiableCollection(_aliases);
+ }
+
+ public Collection<Connection> getConnections()
+ {
+ synchronized(_connectionAdapters)
+ {
+ return new ArrayList<Connection>(_connectionAdapters.values());
+ }
+
+ }
+
+ public Collection<Queue> getQueues()
+ {
+ synchronized(_queueAdapters)
+ {
+ return new ArrayList<Queue>(_queueAdapters.values());
+ }
+ }
+
+ public Collection<Exchange> getExchanges()
+ {
+ synchronized (_exchangeAdapters)
+ {
+ return new ArrayList<Exchange>(_exchangeAdapters.values());
+ }
+ }
+
+
+ public Exchange createExchange(Map<String, Object> attributes)
+ throws AccessControlException, IllegalArgumentException
+ {
+ attributes = new HashMap<String, Object>(attributes);
+
+ String name = getStringAttribute(Exchange.NAME, attributes, null);
+ State state = getEnumAttribute(State.class, Exchange.STATE, attributes, State.ACTIVE);
+ boolean durable = getBooleanAttribute(Exchange.DURABLE, attributes, false);
+ LifetimePolicy lifetime = getEnumAttribute(LifetimePolicy.class, Exchange.LIFETIME_POLICY, attributes, LifetimePolicy.PERMANENT);
+ String type = getStringAttribute(Exchange.TYPE, attributes, null);
+ long ttl = getLongAttribute(Exchange.TIME_TO_LIVE, attributes, 0l);
+
+ attributes.remove(Exchange.NAME);
+ attributes.remove(Exchange.STATE);
+ attributes.remove(Exchange.DURABLE);
+ attributes.remove(Exchange.LIFETIME_POLICY);
+ attributes.remove(Exchange.TYPE);
+ attributes.remove(Exchange.TIME_TO_LIVE);
+
+ return createExchange(name, state, durable, lifetime, ttl, type, attributes);
+ }
+
+ public Exchange createExchange(final String name,
+ final State initialState,
+ final boolean durable,
+ final LifetimePolicy lifetime,
+ final long ttl,
+ final String type,
+ final Map<String, Object> attributes)
+ throws AccessControlException, IllegalArgumentException
+ {
+ checkVHostStateIsActive();
+
+ try
+ {
+ ExchangeRegistry exchangeRegistry = _virtualHost.getExchangeRegistry();
+ if (exchangeRegistry.isReservedExchangeName(name))
+ {
+ throw new UnsupportedOperationException("'" + name + "' is a reserved exchange name");
+ }
+ synchronized(exchangeRegistry)
+ {
+ org.apache.qpid.server.exchange.Exchange exchange = exchangeRegistry.getExchange(name);
+ if (exchange != null)
+ {
+ throw new IllegalArgumentException("Exchange with name '" + name + "' already exists");
+ }
+ exchange = _virtualHost.getExchangeFactory().createExchange(name, type, durable,
+ lifetime == LifetimePolicy.AUTO_DELETE);
+ _virtualHost.getExchangeRegistry().registerExchange(exchange);
+ if(durable)
+ {
+ _virtualHost.getMessageStore().createExchange(exchange);
+ }
+ synchronized (_exchangeAdapters)
+ {
+ return _exchangeAdapters.get(exchange);
+ }
+ }
+ }
+ catch(AMQException e)
+ {
+ throw new IllegalArgumentException(e);
+ }
+ }
+
+ public Queue createQueue(Map<String, Object> attributes)
+ throws AccessControlException, IllegalArgumentException
+ {
+ attributes = new HashMap<String, Object>(attributes);
+
+ if (attributes.containsKey(Queue.TYPE))
+ {
+ String typeAttribute = getStringAttribute(Queue.TYPE, attributes, null);
+ QueueType queueType = null;
+ try
+ {
+ queueType = QueueType.valueOf(typeAttribute.toUpperCase());
+ }
+ catch(Exception e)
+ {
+ throw new IllegalArgumentException("Unsupported queue type :" + typeAttribute);
+ }
+ if (queueType == QueueType.LVQ && attributes.get(Queue.LVQ_KEY) == null)
+ {
+ attributes.put(Queue.LVQ_KEY, AMQQueueFactory.QPID_LVQ_KEY);
+ }
+ else if (queueType == QueueType.PRIORITY && attributes.get(Queue.PRIORITIES) == null)
+ {
+ attributes.put(Queue.PRIORITIES, 10);
+ }
+ else if (queueType == QueueType.SORTED && attributes.get(Queue.SORT_KEY) == null)
+ {
+ throw new IllegalArgumentException("Sort key is not specified for sorted queue");
+ }
+ }
+ String name = getStringAttribute(Queue.NAME, attributes, null);
+ State state = getEnumAttribute(State.class, Queue.STATE, attributes, State.ACTIVE);
+ boolean durable = getBooleanAttribute(Queue.DURABLE, attributes, false);
+ LifetimePolicy lifetime = getEnumAttribute(LifetimePolicy.class, Queue.LIFETIME_POLICY, attributes, LifetimePolicy.PERMANENT);
+ long ttl = getLongAttribute(Queue.TIME_TO_LIVE, attributes, 0l);
+ boolean exclusive= getBooleanAttribute(Queue.EXCLUSIVE, attributes, false);
+
+ attributes.remove(Queue.NAME);
+ attributes.remove(Queue.STATE);
+ attributes.remove(Queue.DURABLE);
+ attributes.remove(Queue.LIFETIME_POLICY);
+ attributes.remove(Queue.TIME_TO_LIVE);
+
+ List<String> attrNames = new ArrayList<String>(attributes.keySet());
+ for(String attr : attrNames)
+ {
+ if(QueueAdapter.ATTRIBUTE_MAPPINGS.containsKey(attr))
+ {
+ attributes.put(QueueAdapter.ATTRIBUTE_MAPPINGS.get(attr),attributes.remove(attr));
+ }
+ }
+
+ return createQueue(name, state, durable, exclusive, lifetime, ttl, attributes);
+ }
+
+ public Queue createQueue(final String name,
+ final State initialState,
+ final boolean durable,
+ boolean exclusive,
+ final LifetimePolicy lifetime,
+ final long ttl,
+ final Map<String, Object> attributes)
+ throws AccessControlException, IllegalArgumentException
+ {
+ checkVHostStateIsActive();
+
+ String owner = null;
+ if(exclusive)
+ {
+ Set<Principal> principals =
+ SecurityManager.getThreadSubject().getPrincipals();
+ if(principals != null && !principals.isEmpty())
+ {
+ owner = principals.iterator().next().getName();
+ }
+ }
+ try
+ {
+ QueueRegistry queueRegistry = _virtualHost.getQueueRegistry();
+ synchronized (queueRegistry)
+ {
+ if(_virtualHost.getQueueRegistry().getQueue(name)!=null)
+ {
+ throw new IllegalArgumentException("Queue with name "+name+" already exists");
+ }
+ AMQQueue queue =
+ AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateQueueUUID(name, _virtualHost.getName()), name,
+ durable, owner, lifetime == LifetimePolicy.AUTO_DELETE,
+ exclusive, _virtualHost, attributes);
+ _virtualHost.getBindingFactory().addBinding(name, queue, _virtualHost.getExchangeRegistry().getDefaultExchange(), null);
+
+ if(durable)
+ {
+ _virtualHost.getMessageStore().createQueue(queue, FieldTable.convertToFieldTable(attributes));
+ }
+ synchronized (_queueAdapters)
+ {
+ return _queueAdapters.get(queue);
+ }
+ }
+
+ }
+ catch(AMQException e)
+ {
+ throw new IllegalArgumentException(e);
+ }
+
+ }
+
+ public String getName()
+ {
+ return _virtualHost.getName();
+ }
+
+ public String setName(final String currentName, final String desiredName)
+ throws IllegalStateException, AccessControlException
+ {
+ throw new IllegalStateException();
+ }
+
+ public State getActualState()
+ {
+ return getDesiredState();
+ }
+
+ public boolean isDurable()
+ {
+ return true;
+ }
+
+ public void setDurable(final boolean durable)
+ throws IllegalStateException, AccessControlException, IllegalArgumentException
+ {
+ throw new IllegalStateException();
+ }
+
+ public LifetimePolicy getLifetimePolicy()
+ {
+ return LifetimePolicy.PERMANENT;
+ }
+
+ public LifetimePolicy setLifetimePolicy(final LifetimePolicy expected, final LifetimePolicy desired)
+ throws IllegalStateException, AccessControlException, IllegalArgumentException
+ {
+ throw new IllegalStateException();
+ }
+
+ public long getTimeToLive()
+ {
+ return 0;
+ }
+
+ public long setTimeToLive(final long expected, final long desired)
+ throws IllegalStateException, AccessControlException, IllegalArgumentException
+ {
+ throw new IllegalStateException();
+ }
+
+ public Statistics getStatistics()
+ {
+ return _statistics;
+ }
+
+ @Override
+ public <C extends ConfiguredObject> Collection<C> getChildren(Class<C> clazz)
+ {
+ if(clazz == Exchange.class)
+ {
+ return (Collection<C>) getExchanges();
+ }
+ else if(clazz == Queue.class)
+ {
+ return (Collection<C>) getQueues();
+ }
+ else if(clazz == Connection.class)
+ {
+ return (Collection<C>) getConnections();
+ }
+ else if(clazz == VirtualHostAlias.class)
+ {
+ return (Collection<C>) getAliases();
+ }
+ else
+ {
+ return Collections.emptySet();
+ }
+ }
+
+ @Override
+ public <C extends ConfiguredObject> C createChild(Class<C> childClass, Map<String, Object> attributes, ConfiguredObject... otherParents)
+ {
+ if(childClass == Exchange.class)
+ {
+ return (C) createExchange(attributes);
+ }
+ else if(childClass == Queue.class)
+ {
+ return (C) createQueue(attributes);
+ }
+ else if(childClass == VirtualHostAlias.class)
+ {
+ throw new UnsupportedOperationException();
+ }
+ else if(childClass == Connection.class)
+ {
+ throw new UnsupportedOperationException();
+ }
+ throw new IllegalArgumentException("Cannot create a child of class " + childClass.getSimpleName());
+ }
+
+ public void exchangeRegistered(org.apache.qpid.server.exchange.Exchange exchange)
+ {
+ ExchangeAdapter adapter = null;
+ synchronized (_exchangeAdapters)
+ {
+ if(!_exchangeAdapters.containsKey(exchange))
+ {
+ adapter = new ExchangeAdapter(this, exchange);
+ _exchangeAdapters.put(exchange, adapter);
+
+ }
+
+ }
+ if(adapter != null)
+ {
+ childAdded(adapter);
+ }
+
+ }
+
+
+ public void exchangeUnregistered(org.apache.qpid.server.exchange.Exchange exchange)
+ {
+ ExchangeAdapter adapter;
+ synchronized (_exchangeAdapters)
+ {
+ adapter = _exchangeAdapters.remove(exchange);
+
+ }
+
+ if(adapter != null)
+ {
+ childRemoved(adapter);
+ }
+ }
+
+ public void queueRegistered(AMQQueue queue)
+ {
+ QueueAdapter adapter = null;
+ synchronized (_queueAdapters)
+ {
+ if(!_queueAdapters.containsKey(queue))
+ {
+ adapter = new QueueAdapter(this, queue);
+ _queueAdapters.put(queue, adapter);
+
+ }
+
+ }
+ if(adapter != null)
+ {
+ childAdded(adapter);
+ }
+
+ }
+
+ public void queueUnregistered(AMQQueue queue)
+ {
+
+ QueueAdapter adapter;
+ synchronized (_queueAdapters)
+ {
+ adapter = _queueAdapters.remove(queue);
+
+ }
+
+ if(adapter != null)
+ {
+ childRemoved(adapter);
+ }
+ }
+
+ public void connectionRegistered(AMQConnectionModel connection)
+ {
+ ConnectionAdapter adapter = null;
+ synchronized (_connectionAdapters)
+ {
+ if(!_connectionAdapters.containsKey(connection))
+ {
+ adapter = new ConnectionAdapter(connection);
+ _connectionAdapters.put(connection, adapter);
+
+ }
+
+ }
+ if(adapter != null)
+ {
+ childAdded(adapter);
+ }
+ }
+
+ public void connectionUnregistered(AMQConnectionModel connection)
+ {
+
+ ConnectionAdapter adapter;
+ synchronized (_connectionAdapters)
+ {
+ adapter = _connectionAdapters.remove(connection);
+
+ }
+
+ if(adapter != null)
+ {
+ childRemoved(adapter);
+ }
+ }
+
+ QueueAdapter getQueueAdapter(AMQQueue queue)
+ {
+ synchronized (_queueAdapters)
+ {
+ return _queueAdapters.get(queue);
+ }
+ }
+
+ public Collection<String> getExchangeTypes()
+ {
+ Collection<ExchangeType<? extends org.apache.qpid.server.exchange.Exchange>> types =
+ _virtualHost.getExchangeFactory().getRegisteredTypes();
+
+ Collection<String> exchangeTypes = new ArrayList<String>();
+
+ for(ExchangeType<? extends org.apache.qpid.server.exchange.Exchange> type : types)
+ {
+ exchangeTypes.add(type.getName().asString());
+ }
+ return Collections.unmodifiableCollection(exchangeTypes);
+ }
+
+ public void executeTransaction(TransactionalOperation op)
+ {
+ MessageStore store = _virtualHost.getMessageStore();
+ final LocalTransaction txn = new LocalTransaction(store);
+
+ op.withinTransaction(new Transaction()
+ {
+ public void dequeue(final QueueEntry entry)
+ {
+ if(entry.acquire())
+ {
+ txn.dequeue(entry.getQueue(), entry.getMessage(), new ServerTransaction.Action()
+ {
+ public void postCommit()
+ {
+ entry.discard();
+ }
+
+ public void onRollback()
+ {
+ }
+ });
+ }
+ }
+
+ public void copy(QueueEntry entry, Queue queue)
+ {
+ final ServerMessage message = entry.getMessage();
+ final AMQQueue toQueue = ((QueueAdapter)queue).getAMQQueue();
+
+ txn.enqueue(toQueue, message, new ServerTransaction.Action()
+ {
+ public void postCommit()
+ {
+ try
+ {
+ toQueue.enqueue(message);
+ }
+ catch(AMQException e)
+ {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public void onRollback()
+ {
+ }
+ });
+
+ }
+
+ public void move(final QueueEntry entry, Queue queue)
+ {
+ final ServerMessage message = entry.getMessage();
+ final AMQQueue toQueue = ((QueueAdapter)queue).getAMQQueue();
+ if(entry.acquire())
+ {
+ txn.enqueue(toQueue, message,
+ new ServerTransaction.Action()
+ {
+
+ public void postCommit()
+ {
+ try
+ {
+ toQueue.enqueue(message);
+ }
+ catch (AMQException e)
+ {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public void onRollback()
+ {
+ entry.release();
+ }
+ });
+ txn.dequeue(entry.getQueue(), message,
+ new ServerTransaction.Action()
+ {
+
+ public void postCommit()
+ {
+ entry.discard();
+ }
+
+ public void onRollback()
+ {
+
+ }
+ });
+ }
+ }
+
+ });
+ txn.commit();
+ }
+
+ org.apache.qpid.server.virtualhost.VirtualHost getVirtualHost()
+ {
+ return _virtualHost;
+ }
+
+ @Override
+ public Object getAttribute(String name)
+ {
+ if(ID.equals(name))
+ {
+ return getId();
+ }
+ else if(NAME.equals(name))
+ {
+ return getName();
+ }
+ else if(STATE.equals(name))
+ {
+ return State.ACTIVE;
+ }
+ else if(DURABLE.equals(name))
+ {
+ return isDurable();
+ }
+ else if(LIFETIME_POLICY.equals(name))
+ {
+ return LifetimePolicy.PERMANENT;
+ }
+ else if(TIME_TO_LIVE.equals(name))
+ {
+ // TODO
+ }
+ else if(CREATED.equals(name))
+ {
+ // TODO
+ }
+ else if(UPDATED.equals(name))
+ {
+ // TODO
+ }
+ else if(SUPPORTED_EXCHANGE_TYPES.equals(name))
+ {
+ List<String> types = new ArrayList<String>();
+ for(ExchangeType type : _virtualHost.getExchangeFactory().getRegisteredTypes())
+ {
+ types.add(type.getName().asString());
+ }
+ return Collections.unmodifiableCollection(types);
+ }
+ else if(SUPPORTED_QUEUE_TYPES.equals(name))
+ {
+ // TODO
+ }
+ else if(DEAD_LETTER_QUEUE_ENABLED.equals(name))
+ {
+ return _virtualHost.getConfiguration().isDeadLetterQueueEnabled();
+ }
+ else if(FEDERATION_TAG.equals(name))
+ {
+ return _virtualHost.getFederationTag();
+ }
+ else if(HOUSEKEEPING_CHECK_PERIOD.equals(name))
+ {
+ return _virtualHost.getConfiguration().getHousekeepingCheckPeriod();
+ }
+ else if(MAXIMUM_DELIVERY_ATTEMPTS.equals(name))
+ {
+ return _virtualHost.getConfiguration().getMaxDeliveryCount();
+ }
+ else if(QUEUE_FLOW_CONTROL_SIZE_BYTES.equals(name))
+ {
+ return _virtualHost.getConfiguration().getCapacity();
+ }
+ else if(QUEUE_FLOW_RESUME_SIZE_BYTES.equals(name))
+ {
+ return _virtualHost.getConfiguration().getFlowResumeCapacity();
+ }
+ else if(STORE_TYPE.equals(name))
+ {
+ return _virtualHost.getMessageStore().getStoreType();
+ }
+ else if(STORE_CONFIGURATION.equals(name))
+ {
+ // TODO
+ }
+ else if(STORE_TRANSACTION_IDLE_TIMEOUT_CLOSE.equals(name))
+ {
+ return _virtualHost.getConfiguration().getTransactionTimeoutIdleClose();
+ }
+ else if(STORE_TRANSACTION_IDLE_TIMEOUT_WARN.equals(name))
+ {
+ return _virtualHost.getConfiguration().getTransactionTimeoutIdleWarn();
+ }
+ else if(STORE_TRANSACTION_OPEN_TIMEOUT_CLOSE.equals(name))
+ {
+ return _virtualHost.getConfiguration().getTransactionTimeoutOpenClose();
+ }
+ else if(STORE_TRANSACTION_OPEN_TIMEOUT_WARN.equals(name))
+ {
+ return _virtualHost.getConfiguration().getTransactionTimeoutOpenWarn();
+ }
+ else if(ALERT_REPEAT_GAP.equals(name))
+ {
+ return _virtualHost.getConfiguration().getMinimumAlertRepeatGap();
+ }
+ else if(ALERT_THRESHOLD_MESSAGE_AGE.equals(name))
+ {
+ return _virtualHost.getConfiguration().getMaximumMessageAge();
+ }
+ else if(ALERT_THRESHOLD_MESSAGE_SIZE.equals(name))
+ {
+ return _virtualHost.getConfiguration().getMaximumMessageSize();
+ }
+ else if(ALERT_THRESHOLD_QUEUE_DEPTH_BYTES.equals(name))
+ {
+ return _virtualHost.getConfiguration().getMaximumQueueDepth();
+ }
+ else if(ALERT_THRESHOLD_QUEUE_DEPTH_MESSAGES.equals(name))
+ {
+ return _virtualHost.getConfiguration().getMaximumMessageCount();
+ }
+ return super.getAttribute(name);
+ }
+
+ @Override
+ public Object setAttribute(String name, Object expected, Object desired)
+ throws IllegalStateException, AccessControlException, IllegalArgumentException
+ {
+ return super.setAttribute(name, expected, desired); //TODO - Implement
+ }
+
+ @Override
+ public Collection<String> getAttributeNames()
+ {
+ return AVAILABLE_ATTRIBUTES;
+ }
+
+ private void checkVHostStateIsActive()
+ {
+ if (!org.apache.qpid.server.virtualhost.State.ACTIVE.equals(_virtualHost.getState()))
+ {
+ throw new IllegalStateException("The virtual hosts state of " + _virtualHost.getState()
+ + " does not permit this operation.");
+ }
+ }
+
+
+ private static class VirtualHostStatisticsAdapter extends StatisticsAdapter
+ {
+ private final org.apache.qpid.server.virtualhost.VirtualHost _vhost;
+
+ private static final Collection<String> VHOST_STATS = Arrays.asList(
+ VirtualHost.QUEUE_COUNT,
+ VirtualHost.EXCHANGE_COUNT,
+ VirtualHost.CONNECTION_COUNT);
+
+ public VirtualHostStatisticsAdapter(org.apache.qpid.server.virtualhost.VirtualHost virtualHost)
+ {
+ super(virtualHost);
+ _vhost = virtualHost;
+ }
+
+ @Override
+ public Collection<String> getStatisticNames()
+ {
+ Set<String> stats = new HashSet<String>(super.getStatisticNames());
+ stats.addAll(VHOST_STATS);
+ return stats;
+ }
+
+ @Override
+ public Object getStatistic(String name)
+ {
+ if(VirtualHost.QUEUE_COUNT.equals(name))
+ {
+ return _vhost.getQueueRegistry().getQueues().size();
+ }
+ else if(VirtualHost.EXCHANGE_COUNT.equals(name))
+ {
+ return _vhost.getExchangeRegistry().getExchanges().size();
+ }
+ else if(VirtualHost.CONNECTION_COUNT.equals(name))
+ {
+ return _vhost.getConnectionRegistry().getConnections().size();
+ }
+ else
+ {
+ return super.getStatistic(name);
+ }
+ }
+ }
+
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/model/adapter/VirtualHostAliasAdapter.java b/java/broker/src/main/java/org/apache/qpid/server/model/adapter/VirtualHostAliasAdapter.java
new file mode 100644
index 0000000000..367d1ff518
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/model/adapter/VirtualHostAliasAdapter.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.server.model.adapter;
+
+import java.util.Map;
+import org.apache.qpid.server.model.AuthenticationMethod;
+import org.apache.qpid.server.model.ConfiguredObject;
+import org.apache.qpid.server.model.LifetimePolicy;
+import org.apache.qpid.server.model.Port;
+import org.apache.qpid.server.model.State;
+import org.apache.qpid.server.model.Statistics;
+import org.apache.qpid.server.model.UUIDGenerator;
+import org.apache.qpid.server.model.VirtualHost;
+import org.apache.qpid.server.model.VirtualHostAlias;
+
+import java.security.AccessControlException;
+import java.util.Collection;
+import java.util.Collections;
+
+public class VirtualHostAliasAdapter extends AbstractAdapter implements VirtualHostAlias
+{
+ private VirtualHostAdapter _vhost;
+ private Port _port;
+
+ public VirtualHostAliasAdapter(VirtualHostAdapter virtualHostAdapter, Port port)
+ {
+ super(UUIDGenerator.generateVhostAliasUUID(virtualHostAdapter.getName(), port.getName()));
+ _vhost = virtualHostAdapter;
+ _port = port;
+ }
+
+ @Override
+ public Port getPort()
+ {
+ return _port;
+ }
+
+ @Override
+ public VirtualHost getVirtualHost()
+ {
+ return _vhost;
+ }
+
+ @Override
+ public Collection<AuthenticationMethod> getAuthenticationMethods()
+ {
+ return Collections.emptySet(); // TODO - Implement
+ }
+
+ @Override
+ public String getName()
+ {
+ return _vhost.getName();
+ }
+
+ @Override
+ public String setName(String currentName, String desiredName) throws IllegalStateException, AccessControlException
+ {
+ throw new IllegalStateException(); // TODO - Implement
+ }
+
+ @Override
+ public State getActualState()
+ {
+ return State.ACTIVE; // TODO - Implement
+ }
+
+ @Override
+ public boolean isDurable()
+ {
+ return true; // TODO - Implement
+ }
+
+ @Override
+ public void setDurable(boolean durable)
+ throws IllegalStateException, AccessControlException, IllegalArgumentException
+ {
+ throw new IllegalStateException();
+ }
+
+ @Override
+ public LifetimePolicy getLifetimePolicy()
+ {
+ return LifetimePolicy.PERMANENT; // TODO - Implement
+ }
+
+ @Override
+ public LifetimePolicy setLifetimePolicy(LifetimePolicy expected, LifetimePolicy desired)
+ throws IllegalStateException, AccessControlException, IllegalArgumentException
+ {
+ throw new IllegalStateException(); // TODO - Implement
+ }
+
+ @Override
+ public long getTimeToLive()
+ {
+ return 0; // TODO - Implement
+ }
+
+ @Override
+ public long setTimeToLive(long expected, long desired)
+ throws IllegalStateException, AccessControlException, IllegalArgumentException
+ {
+ throw new IllegalStateException(); // TODO - Implement
+ }
+
+ @Override
+ public Statistics getStatistics()
+ {
+ return NoStatistics.getInstance();
+ }
+
+ @Override
+ public <C extends ConfiguredObject> Collection<C> getChildren(Class<C> clazz)
+ {
+ return Collections.emptySet();
+ }
+
+ @Override
+ public <C extends ConfiguredObject> C createChild(Class<C> childClass, Map<String, Object> attributes, ConfiguredObject... otherParents)
+ {
+ throw new UnsupportedOperationException();
+ }
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/output/ProtocolOutputConverterImpl.java b/java/broker/src/main/java/org/apache/qpid/server/output/ProtocolOutputConverterImpl.java
index cfdcf7fb43..a68ac5439c 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/output/ProtocolOutputConverterImpl.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/output/ProtocolOutputConverterImpl.java
@@ -1,4 +1,3 @@
-package org.apache.qpid.server.output;
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
@@ -19,6 +18,7 @@ package org.apache.qpid.server.output;
* under the License.
*
*/
+package org.apache.qpid.server.output;
import org.apache.qpid.AMQException;
import org.apache.qpid.framing.AMQBody;
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
index badeffca05..6479546355 100644
--- 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
@@ -31,12 +31,24 @@
javax.management.openmbean=1.0.0
javax.management=1.0.0
+javax.management.remote.rmi=1.0.0
+javax.management.remote=1.0.0
+javax.management.monitor=1.0.0
+
+javax.crypto=1
+javax.crypto.spec=1
+
+javax.servlet=2
+javax.servlet.http=2
javax.security.auth=1.0.0
javax.security.auth.callback=1.0.0
+javax.security.auth.login=1.0.0
javax.security.sasl=1.0.0
javax.security=1.0.0
+javax.rmi.ssl=1.0.0
+
org.xml.sax=1.0.0
org.xml.sax.helpers=1.0.0
@@ -46,41 +58,66 @@ org.osgi.service.startlevel=1.0.0
org.osgi.service.url=1.0.0
org.osgi.util.tracker=1.0.0
+org.apache.commons.codec=1.3.0
+org.apache.commons.codec.binary=1.3.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.lang.time=1.0.0
org.apache.commons.logging=1.0.0
-org.apache.log4j=1.2.12
+org.apache.log4j=1.2.16
org.slf4j=1.6.1
+org.eclipse.jetty=7.6.3
+org.eclipse.jetty.http=7.6.3
+org.eclipse.jetty.io=7.6.3
+org.eclipse.jetty.io.nio=7.6.3
+org.eclipse.jetty.security=7.6.3
+org.eclipse.jetty.server=7.6.3
+org.eclipse.jetty.server.session=7.6.3
+org.eclipse.jetty.server.ssl=7.6.3
+org.eclipse.jetty.server.nio=7.6.3
+org.eclipse.jetty.servlet=7.6.3
+org.eclipse.jetty.util.ssl=7.6.3
+
+org.codehaus.jackson=1.9.0
+org.codehaus.jackson.map=1.9.0
+
# 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.management.common.mbeans=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.model=0.0.0
+org.apache.qpid.server.model.adapter=0.0.0
+org.apache.qpid.server.model.impl=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.connection=0.0.0
org.apache.qpid.server.exchange=0.0.0
org.apache.qpid.server.logging=0.0.0
+org.apache.qpid.server.logging.log4j=0.0.0
org.apache.qpid.server.logging.actors=0.0.0
+org.apache.qpid.server.logging.messages=0.0.0
org.apache.qpid.server.logging.subjects=0.0.0
org.apache.qpid.server.message=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.subscription=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
@@ -88,7 +125,11 @@ 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.security.auth.rmi=0.0.0
+org.apache.qpid.server.stats=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
+org.apache.qpid.server.store.berkeleydb=0.0.0
+
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 407ce57ad6..74abbccd2b 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,17 +18,20 @@
*/
package org.apache.qpid.server.plugins;
+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.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;
-
import org.apache.qpid.common.Closeable;
import org.apache.qpid.common.QpidProperties;
import org.apache.qpid.server.configuration.TopicConfiguration;
@@ -40,24 +43,23 @@ 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.LegacyAccess;
+import org.apache.qpid.server.security.auth.manager.AnonymousAuthenticationManager;
import org.apache.qpid.server.security.auth.manager.AuthenticationManagerPluginFactory;
+import org.apache.qpid.server.security.auth.manager.ExternalAuthenticationManager;
+import org.apache.qpid.server.security.auth.manager.KerberosAuthenticationManager;
import org.apache.qpid.server.security.auth.manager.PrincipalDatabaseAuthenticationManager;
+import org.apache.qpid.server.security.auth.manager.SimpleLDAPAuthenticationManager;
import org.apache.qpid.server.virtualhost.plugins.SlowConsumerDetection;
import org.apache.qpid.server.virtualhost.plugins.VirtualHostPluginFactory;
import org.apache.qpid.server.virtualhost.plugins.policies.TopicDeletePolicy;
import org.apache.qpid.slowconsumerdetection.policies.SlowConsumerPolicyPluginFactory;
import org.apache.qpid.util.FileUtils;
-
-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.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;
import static org.apache.felix.framework.util.FelixConstants.SYSTEMBUNDLE_ACTIVATORS_PROP;
import static org.apache.felix.main.AutoProcessor.AUTO_DEPLOY_ACTION_PROPERY;
@@ -100,18 +102,18 @@ public class PluginManager implements Closeable
/** 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
+
+ static
{
final String filename = System.getProperty(FILE_PROPERTY);
final InputStream is = FileUtils.openFileOrDefaultResource(filename, DEFAULT_RESOURCE_NAME,
PluginManager.class.getClassLoader());
-
+
try
{
Version qpidReleaseVersion;
@@ -123,14 +125,14 @@ public class PluginManager implements Closeable
{
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)
@@ -139,8 +141,8 @@ public class PluginManager implements Closeable
throw new ExceptionInInitializerError(e);
}
}
-
-
+
+
public PluginManager(String pluginPath, String cachePath, BundleContext bundleContext) throws Exception
{
// Store all non-OSGi plugins
@@ -156,7 +158,12 @@ public class PluginManager implements Closeable
new SlowConsumerDetectionConfigurationFactory(),
new SlowConsumerDetectionPolicyConfigurationFactory(),
new SlowConsumerDetectionQueueConfigurationFactory(),
- PrincipalDatabaseAuthenticationManager.PrincipalDatabaseAuthenticationManagerConfiguration.FACTORY))
+ PrincipalDatabaseAuthenticationManager.PrincipalDatabaseAuthenticationManagerConfiguration.FACTORY,
+ AnonymousAuthenticationManager.AnonymousAuthenticationManagerConfiguration.FACTORY,
+ KerberosAuthenticationManager.KerberosAuthenticationManagerConfiguration.FACTORY,
+ SimpleLDAPAuthenticationManager.SimpleLDAPAuthenticationManagerConfiguration.FACTORY,
+ ExternalAuthenticationManager.ExternalAuthenticationManagerConfiguration.FACTORY
+ ))
{
_configPlugins.put(configFactory.getParentPaths(), configFactory);
}
@@ -172,7 +179,9 @@ public class PluginManager implements Closeable
}
for (AuthenticationManagerPluginFactory<? extends Plugin> pluginFactory : Arrays.asList(
- PrincipalDatabaseAuthenticationManager.FACTORY))
+ PrincipalDatabaseAuthenticationManager.FACTORY, AnonymousAuthenticationManager.FACTORY,
+ KerberosAuthenticationManager.FACTORY, SimpleLDAPAuthenticationManager.FACTORY,
+ ExternalAuthenticationManager.FACTORY))
{
_authenticationManagerPlugins.put(pluginFactory.getPluginName(), pluginFactory);
}
@@ -265,7 +274,7 @@ public class PluginManager implements Closeable
_virtualHostTracker = new ServiceTracker(bundleContext, VirtualHostPluginFactory.class.getName(), null);
_virtualHostTracker.open();
_trackers.add(_virtualHostTracker);
-
+
_policyTracker = new ServiceTracker(bundleContext, SlowConsumerPolicyPluginFactory.class.getName(), null);
_policyTracker.open();
_trackers.add(_policyTracker);
@@ -278,9 +287,9 @@ public class PluginManager implements Closeable
}
private static <T> Map<String, T> getServices(ServiceTracker tracker)
- {
+ {
Map<String, T> services = new HashMap<String, T>();
-
+
if ((tracker != null) && (tracker.getServices() != null))
{
for (Object service : tracker.getServices())
@@ -300,16 +309,16 @@ public class PluginManager implements Closeable
}
public static <T> Map<String, T> getServices(ServiceTracker tracker, Map<String, T> plugins)
- {
+ {
Map<String, T> services = getServices(tracker);
services.putAll(plugins);
return services;
}
public Map<List<String>, ConfigurationPluginFactory> getConfigurationPlugins()
- {
+ {
Map<List<String>, ConfigurationPluginFactory> services = new IdentityHashMap<List<String>, ConfigurationPluginFactory>();
-
+
if (_configTracker != null && _configTracker.getServices() != null)
{
for (Object service : _configTracker.getServices())
@@ -318,19 +327,19 @@ public class PluginManager implements Closeable
services.put(factory.getParentPaths(), factory);
}
}
-
+
services.putAll(_configPlugins);
return services;
}
public Map<String, VirtualHostPluginFactory> getVirtualHostPlugins()
- {
+ {
return getServices(_virtualHostTracker, _vhostPlugins);
}
public Map<String, SlowConsumerPolicyPluginFactory> getSlowConsumerPlugins()
- {
+ {
return getServices(_policyTracker, _policyPlugins);
}
@@ -338,7 +347,7 @@ public class PluginManager implements Closeable
{
return getServices(_exchangeTracker);
}
-
+
public Map<String, SecurityPluginFactory> getSecurityPlugins()
{
return getServices(_securityTracker, _securityPlugins);
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 5af3899890..36fafba1cd 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
@@ -31,24 +31,21 @@ import java.util.UUID;
public interface AMQConnectionModel extends StatisticsGatherer
{
/**
- * 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;
+ public void block();
+
+ public void unblock();
+
/**
* Close the given requested Session
- *
+ *
* @param session
* @param cause
* @param message
@@ -57,10 +54,10 @@ 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();
@@ -73,4 +70,16 @@ public interface AMQConnectionModel extends StatisticsGatherer
public String getUserName();
public boolean isSessionNameUnique(byte[] name);
+
+ String getRemoteAddressString();
+
+ String getClientId();
+
+ String getClientVersion();
+
+ String getPrincipalAsString();
+
+ long getSessionCountLimit();
+
+ long getLastIoTime();
}
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 b750b29952..1e649c3cb7 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,8 +20,26 @@
*/
package org.apache.qpid.server.protocol;
-import org.apache.log4j.Logger;
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.net.SocketAddress;
+import java.nio.ByteBuffer;
+import java.security.Principal;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+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.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+import javax.security.auth.Subject;
+import javax.security.sasl.SaslServer;
+import org.apache.log4j.Logger;
import org.apache.qpid.AMQChannelException;
import org.apache.qpid.AMQConnectionException;
import org.apache.qpid.AMQException;
@@ -46,13 +64,10 @@ import org.apache.qpid.server.logging.actors.CurrentActor;
import org.apache.qpid.server.logging.actors.ManagementActor;
import org.apache.qpid.server.logging.messages.ConnectionMessages;
import org.apache.qpid.server.logging.subjects.ConnectionLogSubject;
-import org.apache.qpid.server.management.Managable;
-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.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.state.AMQStateManager;
import org.apache.qpid.server.stats.StatisticsCounter;
@@ -66,25 +81,7 @@ import org.apache.qpid.transport.TransportException;
import org.apache.qpid.transport.network.NetworkConnection;
import org.apache.qpid.util.BytesDataOutput;
-import javax.management.JMException;
-import javax.security.auth.Subject;
-import javax.security.sasl.SaslServer;
-import java.io.IOException;
-import java.net.InetSocketAddress;
-import java.net.SocketAddress;
-import java.nio.ByteBuffer;
-import java.security.Principal;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.UUID;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.CopyOnWriteArrayList;
-import java.util.concurrent.CopyOnWriteArraySet;
-import java.util.concurrent.atomic.AtomicBoolean;
-
-public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQProtocolSession, ConnectionConfig
+public class AMQProtocolEngine implements ServerProtocolEngine, AMQProtocolSession, ConnectionConfig
{
private static final Logger _logger = Logger.getLogger(AMQProtocolEngine.class);
@@ -109,8 +106,6 @@ public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQPr
private AMQCodecFactory _codecFactory;
- private AMQProtocolSessionMBean _managedObject;
-
private SaslServer _saslServer;
private Object _lastReceived;
@@ -147,12 +142,10 @@ public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQPr
private long _maxFrameSize;
private final AtomicBoolean _closing = new AtomicBoolean(false);
- private final UUID _id;
+ private final UUID _qmfId;
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;
@@ -160,14 +153,13 @@ public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQPr
private volatile boolean _deferFlush;
private long _lastReceivedTime;
+ private boolean _blocking;
- public ManagedObject getManagedObject()
- {
- return _managedObject;
- }
+ private final Lock _receivedLock;
public AMQProtocolEngine(VirtualHostRegistry virtualHostRegistry, NetworkConnection network, final long connectionId)
{
+ _receivedLock = new ReentrantLock();
_stateManager = new AMQStateManager(virtualHostRegistry, this);
_codecFactory = new AMQCodecFactory(true, this);
@@ -179,12 +171,12 @@ public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQPr
_logSubject = new ConnectionLogSubject(this);
_configStore = virtualHostRegistry.getConfigStore();
- _id = _configStore.createId();
+ _qmfId = _configStore.createId();
_actor.message(ConnectionMessages.OPEN(null, null, null, false, false, false));
- _registry = virtualHostRegistry.getApplicationRegistry();
initialiseStatistics();
+
}
public void setNetworkConnection(NetworkConnection network)
@@ -198,11 +190,6 @@ public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQPr
_sender = sender;
}
- private AMQProtocolSessionMBean createMBean() throws JMException
- {
- return new AMQProtocolSessionMBean(this);
- }
-
public long getSessionID()
{
return _connectionID;
@@ -244,6 +231,8 @@ public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQPr
final long arrivalTime = System.currentTimeMillis();
_lastReceivedTime = arrivalTime;
_lastIoTime = arrivalTime;
+
+ _receivedLock.lock();
try
{
final ArrayList<AMQDataBlock> dataBlocks = _codecFactory.getDecoder().decodeBuffer(msg);
@@ -268,6 +257,10 @@ public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQPr
_logger.error("Unexpected exception when processing datablock", e);
closeProtocolSession();
}
+ finally
+ {
+ _receivedLock.unlock();
+ }
}
private void receiveComplete()
@@ -374,7 +367,7 @@ public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQPr
// This sets the protocol version (and hence framing classes) for this session.
setProtocolVersion(pv);
- String mechanisms = ApplicationRegistry.getInstance().getAuthenticationManager().getMechanisms();
+ String mechanisms = ApplicationRegistry.getInstance().getAuthenticationManager(getLocalAddress()).getMechanisms();
String locales = "en_US";
@@ -576,7 +569,10 @@ public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQPr
public List<AMQChannel> getChannels()
{
- return new ArrayList<AMQChannel>(_channelMap.values());
+ synchronized (_channelMap)
+ {
+ return new ArrayList<AMQChannel>(_channelMap.values());
+ }
}
public AMQChannel getAndAssertChannel(int channelId) throws AMQException
@@ -633,24 +629,21 @@ public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQPr
}
else
{
- _channelMap.put(channel.getChannelId(), channel);
+ synchronized (_channelMap)
+ {
+ _channelMap.put(channel.getChannelId(), channel);
+
+ if(_blocking)
+ {
+ channel.block();
+ }
+ }
}
if (((channelId & CHANNEL_CACHE_SIZE) == channelId))
{
_cachedChannels[channelId] = channel;
}
-
- checkForNotification();
- }
-
- private void checkForNotification()
- {
- int channelsCount = _channelMap.size();
- if (_managedObject != null && channelsCount >= _maxNoOfChannels)
- {
- _managedObject.notifyClients("Channel count (" + channelsCount + ") has reached the threshold value");
- }
}
public Long getMaximumNumberOfChannels()
@@ -735,10 +728,14 @@ public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQPr
*/
public void removeChannel(int channelId)
{
- _channelMap.remove(channelId);
- if ((channelId & CHANNEL_CACHE_SIZE) == channelId)
+ synchronized (_channelMap)
{
- _cachedChannels[channelId] = null;
+ _channelMap.remove(channelId);
+
+ if ((channelId & CHANNEL_CACHE_SIZE) == channelId)
+ {
+ _cachedChannels[channelId] = null;
+ }
}
}
@@ -763,12 +760,14 @@ public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQPr
*/
private void closeAllChannels() throws AMQException
{
- for (AMQChannel channel : _channelMap.values())
+ for (AMQChannel channel : getChannels())
{
channel.close();
}
-
- _channelMap.clear();
+ synchronized (_channelMap)
+ {
+ _channelMap.clear();
+ }
for (int i = 0; i <= CHANNEL_CACHE_SIZE; i++)
{
_cachedChannels[i] = null;
@@ -780,6 +779,9 @@ public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQPr
{
if(_closing.compareAndSet(false,true))
{
+ // force sync of outstanding async work
+ receiveComplete();
+
// REMOVE THIS SHOULD NOT BE HERE.
if (CurrentActor.get() == null)
{
@@ -796,13 +798,6 @@ public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQPr
getConfigStore().removeConfiguredObject(this);
- if (_managedObject != null)
- {
- _managedObject.unregister();
- // Ensure we only do this once.
- _managedObject = null;
- }
-
for (Task task : _taskList)
{
task.doTask(this);
@@ -835,7 +830,7 @@ public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQPr
}
}
- public void closeConnection(int channelId, AMQConnectionException e) throws AMQException
+ private void closeConnection(int channelId, AMQConnectionException e) throws AMQException
{
try
{
@@ -846,12 +841,18 @@ public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQPr
markChannelAwaitingCloseOk(channelId);
closeSession();
- _stateManager.changeState(AMQState.CONNECTION_CLOSING);
- writeFrame(e.getCloseFrame(channelId));
}
finally
{
- closeProtocolSession();
+ try
+ {
+ _stateManager.changeState(AMQState.CONNECTION_CLOSING);
+ writeFrame(e.getCloseFrame(channelId));
+ }
+ finally
+ {
+ closeProtocolSession();
+ }
}
@@ -983,16 +984,6 @@ public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQPr
_virtualHost.getConnectionRegistry().registerConnection(this);
_configStore.addConfiguredObject(this);
-
- try
- {
- _managedObject = createMBean();
- _managedObject.register();
- }
- catch (JMException e)
- {
- _logger.error(e);
- }
}
public void addSessionCloseTask(Task task)
@@ -1026,7 +1017,7 @@ public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQPr
public Principal getAuthorizedPrincipal()
{
- return _authorizedSubject == null ? null : UsernamePrincipal.getUsernamePrincipalFromSubject(_authorizedSubject);
+ return _authorizedSubject == null ? null : _authorizedSubject.getPrincipals().iterator().next();
}
public SocketAddress getRemoteAddress()
@@ -1039,6 +1030,11 @@ public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQPr
return _network.getLocalAddress();
}
+ public Principal getPeerPrincipal()
+ {
+ return _network.getPeerPrincipal();
+ }
+
public MethodRegistry getMethodRegistry()
{
return _methodRegistry;
@@ -1144,6 +1140,16 @@ public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQPr
return _clientVersion;
}
+ public String getPrincipalAsString()
+ {
+ return getAuthId();
+ }
+
+ public long getSessionCountLimit()
+ {
+ return getMaximumNumberOfChannels();
+ }
+
public Boolean isIncoming()
{
return true;
@@ -1199,9 +1205,10 @@ public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQPr
return false;
}
- public UUID getId()
+ @Override
+ public UUID getQMFId()
{
- return _id;
+ return _qmfId;
}
public long getConnectionId()
@@ -1337,6 +1344,36 @@ public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQPr
(Throwable) null));
}
+ public void block()
+ {
+ synchronized (_channelMap)
+ {
+ if(!_blocking)
+ {
+ _blocking = true;
+ for(AMQChannel channel : _channelMap.values())
+ {
+ channel.block();
+ }
+ }
+ }
+ }
+
+ public void unblock()
+ {
+ synchronized (_channelMap)
+ {
+ if(_blocking)
+ {
+ _blocking = false;
+ for(AMQChannel channel : _channelMap.values())
+ {
+ channel.unblock();
+ }
+ }
+ }
+ }
+
public boolean isClosed()
{
return _closed;
@@ -1344,12 +1381,7 @@ public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQPr
public List<AMQSessionModel> getSessionModels()
{
- List<AMQSessionModel> sessions = new ArrayList<AMQSessionModel>();
- for (AMQChannel channel : getChannels())
- {
- sessions.add((AMQSessionModel) channel);
- }
- return sessions;
+ return new ArrayList<AMQSessionModel>(getChannels());
}
public LogSubject getLogSubject()
@@ -1359,21 +1391,15 @@ public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQPr
public void registerMessageDelivered(long messageSize)
{
- if (isStatisticsEnabled())
- {
- _messagesDelivered.registerEvent(1L);
- _dataDelivered.registerEvent(messageSize);
- }
+ _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);
- }
+ _messagesReceived.registerEvent(1L, timestamp);
+ _dataReceived.registerEvent(messageSize, timestamp);
_virtualHost.registerMessageReceived(messageSize, timestamp);
}
@@ -1407,29 +1433,26 @@ public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQPr
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()
+ public boolean isSessionNameUnique(byte[] name)
{
- return _statisticsEnabled;
+ // 0-8/0-9/0-9-1 sessions don't have names
+ return true;
}
- public void setStatisticsEnabled(boolean enabled)
+ public String getRemoteAddressString()
{
- _statisticsEnabled = enabled;
+ return String.valueOf(getRemoteAddress());
}
- public boolean isSessionNameUnique(byte[] name)
+ public String getClientId()
{
- // 0-8/0-9/0-9-1 sessions don't have names
- return true;
+ return String.valueOf(getContextKey());
}
public void setDeferFlush(boolean deferFlush)
@@ -1466,4 +1489,9 @@ public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQPr
{
return _reference;
}
+
+ public Lock getReceivedLock()
+ {
+ return _receivedLock;
+ }
}
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 6cd5b21f89..ba806c04bd 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,12 +20,14 @@
*/
package org.apache.qpid.server.protocol;
+import java.net.SocketAddress;
+import java.security.Principal;
import java.util.List;
+import java.util.concurrent.locks.Lock;
import javax.security.auth.Subject;
import javax.security.sasl.SaslServer;
-import org.apache.qpid.AMQConnectionException;
import org.apache.qpid.AMQException;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.framing.FieldTable;
@@ -60,6 +62,13 @@ public interface AMQProtocolSession extends AMQVersionAwareProtocolSession, Auth
long getLastReceivedTime();
+ /**
+ * Return the local socket address for the connection
+ *
+ * @return the socket address
+ */
+ SocketAddress getLocalAddress();
+
public static interface Task
{
public void doTask(AMQProtocolSession session) throws AMQException;
@@ -145,10 +154,6 @@ public interface AMQProtocolSession extends AMQVersionAwareProtocolSession, Auth
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;
-
-
/** @return a key that uniquely identifies this session */
Object getKey();
@@ -210,4 +215,7 @@ public interface AMQProtocolSession extends AMQVersionAwareProtocolSession, Auth
void mgmtCloseChannel(int channelId);
+ public Principal getPeerPrincipal();
+
+ Lock getReceivedLock();
}
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
deleted file mode 100644
index e70720600e..0000000000
--- a/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolSessionMBean.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.
- *
- */
-/*
- *
- * 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.qpid.server.protocol;
-
-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.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.AbstractAMQManagedConnectionObject;
-import org.apache.qpid.server.management.ManagedObject;
-
-import javax.management.JMException;
-import javax.management.MBeanException;
-import javax.management.NotCompliantMBeanException;
-import javax.management.openmbean.CompositeData;
-import javax.management.openmbean.CompositeDataSupport;
-import javax.management.openmbean.OpenDataException;
-import javax.management.openmbean.TabularData;
-import javax.management.openmbean.TabularDataSupport;
-import java.util.Date;
-import java.util.List;
-
-/**
- * This MBean class implements the management interface. In order to make more attributes, operations and notifications
- * available over JMX simply augment the ManagedConnection interface and add the appropriate implementation here.
- */
-@MBeanDescription("Management Bean for an AMQ Broker 0-9-1/0-9/0-8 Connections")
-public class AMQProtocolSessionMBean extends AbstractAMQManagedConnectionObject
-{
- private AMQProtocolSession _protocolSession = null;
-
- private static final AMQShortString BROKER_MANAGEMENT_CONSOLE_HAS_CLOSED_THE_CONNECTION =
- new AMQShortString(BROKER_MANAGEMENT_CONSOLE_HAS_CLOSED_THE_CONNECTION_STR);
-
- @MBeanConstructor("Creates an MBean exposing an AMQ Broker 0-9-1/0-9/0-8 Connection")
- public AMQProtocolSessionMBean(AMQProtocolSession amqProtocolSession) throws NotCompliantMBeanException, OpenDataException
- {
- super(amqProtocolSession.getRemoteAddress().toString());
- _protocolSession = amqProtocolSession;
- }
-
- public String getClientId()
- {
- return String.valueOf(_protocolSession.getContextKey());
- }
-
- public String getAuthorizedId()
- {
- return (_protocolSession.getAuthorizedPrincipal() != null ) ? _protocolSession.getAuthorizedPrincipal().getName() : null;
- }
-
- public String getVersion()
- {
- return _protocolSession.getClientVersion();
- }
-
- public Date getLastIoTime()
- {
- return new Date(_protocolSession.getLastIoTime());
- }
-
- public String getRemoteAddress()
- {
- return _protocolSession.getRemoteAddress().toString();
- }
-
- public ManagedObject getParentObject()
- {
- return _protocolSession.getVirtualHost().getManagedObject();
- }
-
- public Long getWrittenBytes()
- {
- return _protocolSession.getWrittenBytes();
- }
-
- public Long getReadBytes()
- {
- return _protocolSession.getWrittenBytes();
- }
-
- public Long getMaximumNumberOfChannels()
- {
- return _protocolSession.getMaximumNumberOfChannels();
- }
-
- /**
- * commits transactions for a transactional channel
- *
- * @param channelId
- * @throws JMException if channel with given id doesn't exist or if commit fails
- */
- public void commitTransactions(int channelId) throws JMException
- {
- CurrentActor.set(new ManagementActor(getLogActor().getRootMessageLogger()));
- try
- {
- AMQChannel channel = _protocolSession.getChannel(channelId);
- if (channel == null)
- {
- throw new JMException("The channel (channel Id = " + channelId + ") does not exist");
- }
-
- _protocolSession.commitTransactions(channel);
- }
- catch (AMQException ex)
- {
- throw new MBeanException(ex, ex.toString());
- }
- finally
- {
- CurrentActor.remove();
- }
- }
-
- /**
- * rollsback the transactions for a transactional channel
- *
- * @param channelId
- * @throws JMException if channel with given id doesn't exist or if rollback fails
- */
- public void rollbackTransactions(int channelId) throws JMException
- {
- CurrentActor.set(new ManagementActor(getLogActor().getRootMessageLogger()));
- try
- {
- AMQChannel channel = _protocolSession.getChannel(channelId);
- if (channel == null)
- {
- throw new JMException("The channel (channel Id = " + channelId + ") does not exist");
- }
-
- _protocolSession.rollbackTransactions(channel);
- }
- catch (AMQException ex)
- {
- throw new MBeanException(ex, ex.toString());
- }
- finally
- {
- CurrentActor.remove();
- }
- }
-
- /**
- * Creates the list of channels in tabular form from the _channelMap.
- *
- * @return list of channels in tabular form.
- * @throws OpenDataException
- */
- public TabularData channels() throws OpenDataException
- {
- TabularDataSupport channelsList = new TabularDataSupport(_channelsType);
- List<AMQChannel> list = _protocolSession.getChannels();
-
- for (AMQChannel channel : list)
- {
- Object[] itemValues =
- {
- channel.getChannelId(), channel.isTransactional(),
- (channel.getDefaultQueue() != null) ? channel.getDefaultQueue().getNameShortString().asString() : null,
- channel.getUnacknowledgedMessageMap().size(), channel.getBlocking()
- };
-
- CompositeData channelData = new CompositeDataSupport(_channelType,
- COMPOSITE_ITEM_NAMES_DESC.toArray(new String[COMPOSITE_ITEM_NAMES_DESC.size()]), itemValues);
- channelsList.put(channelData);
- }
-
- return channelsList;
- }
-
- /**
- * closes the connection. The administrator can use this management operation to close connection to free up
- * resources.
- * @throws JMException
- */
- public void closeConnection() throws JMException
- {
-
- MethodRegistry methodRegistry = _protocolSession.getMethodRegistry();
- ConnectionCloseBody responseBody =
- methodRegistry.createConnectionCloseBody(AMQConstant.REPLY_SUCCESS.getCode(),
- // replyCode
- BROKER_MANAGEMENT_CONSOLE_HAS_CLOSED_THE_CONNECTION,
- // replyText,
- 0,
- 0);
-
- // This seems ugly but because we use closeConnection in both normal
- // broker operation and as part of the management interface it cannot
- // be avoided. The Current Actor will be null when this method is
- // called via the Management interface. This is because we allow the
- // Local API connection with JConsole. If we did not allow that option
- // then the CurrentActor could be set in our JMX Proxy object.
- // As it is we need to set the CurrentActor on all MBean methods
- // Ideally we would not have a single method that can be called from
- // two contexts.
- boolean removeActor = false;
- if (CurrentActor.get() == null)
- {
- removeActor = true;
- CurrentActor.set(new ManagementActor(getLogActor().getRootMessageLogger()));
- }
-
- try
- {
- _protocolSession.writeFrame(responseBody.generateFrame(0));
-
- try
- {
-
- _protocolSession.closeSession();
- }
- catch (AMQException ex)
- {
- throw new MBeanException(ex, ex.toString());
- }
- }
- finally
- {
- if (removeActor)
- {
- CurrentActor.remove();
- }
- }
- }
-
- 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);
- }
-}
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 fa171815ca..a8f62b0fa2 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
@@ -37,26 +37,26 @@ import org.apache.qpid.server.queue.SimpleAMQQueue;
public interface AMQSessionModel extends Comparable<AMQSessionModel>
{
/** Unique session ID across entire broker*/
- public UUID getId();
+ public UUID getQMFId();
public AMQConnectionModel getConnectionModel();
public String getClientID();
-
+
public void close() throws AMQException;
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.
- *
+ * from the time the transaction was started. An idle transaction is one that
+ * has had no activity, such as publishing or acknowledging 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
@@ -68,6 +68,22 @@ public interface AMQSessionModel extends Comparable<AMQSessionModel>
void unblock(AMQQueue queue);
+ void block();
+
+ void unblock();
+
+ boolean getBlocking();
boolean onSameConnection(InboundMessage inbound);
+
+ int getUnacknowledgedMessageCount();
+
+ Long getTxnCount();
+ Long getTxnStart();
+ Long getTxnCommits();
+ Long getTxnRejects();
+
+ int getChannelId();
+
+ int getConsumerCount();
}
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 652ffee004..5c92aa95b6 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
@@ -302,7 +302,7 @@ public class MultiVersionProtocolEngine implements ServerProtocolEngine
public ServerProtocolEngine getProtocolEngine()
{
final ConnectionDelegate connDelegate =
- new org.apache.qpid.server.transport.ServerConnectionDelegate(_appRegistry, _fqdn);
+ new org.apache.qpid.server.transport.ServerConnectionDelegate(_appRegistry, _fqdn, _appRegistry.getAuthenticationManager(getLocalAddress()));
ServerConnection conn = new ServerConnection(_id);
conn.setConnectionDelegate(connDelegate);
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 182ef1ed82..fd6e9300ec 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
@@ -47,7 +47,7 @@ public class ProtocolEngine_0_10 extends InputHandler implements ServerProtocol
private long _readBytes;
private long _writtenBytes;
private ServerConnection _connection;
- private final UUID _id;
+ private final UUID _qmfId;
private final IApplicationRegistry _appRegistry;
private long _createTime = System.currentTimeMillis();
@@ -59,7 +59,7 @@ public class ProtocolEngine_0_10 extends InputHandler implements ServerProtocol
_connection = conn;
_connection.setConnectionConfig(this);
- _id = appRegistry.getConfigStore().createId();
+ _qmfId = appRegistry.getConfigStore().createId();
_appRegistry = appRegistry;
if(network != null)
@@ -88,7 +88,7 @@ public class ProtocolEngine_0_10 extends InputHandler implements ServerProtocol
_network = network;
_connection.setSender(new Disassembler(sender, MAX_FRAME_SIZE));
-
+ _connection.setPeerPrincipal(_network.getPeerPrincipal());
// FIXME Two log messages to maintain compatibility with earlier protocol versions
_connection.getLogActor().message(ConnectionMessages.OPEN(null, null, null, false, false, false));
_connection.getLogActor().message(ConnectionMessages.OPEN(null, "0-10", null, false, true, false));
@@ -180,9 +180,10 @@ public class ProtocolEngine_0_10 extends InputHandler implements ServerProtocol
return _appRegistry.getConfigStore();
}
- public UUID getId()
+ @Override
+ public UUID getQMFId()
{
- return _id;
+ return _qmfId;
}
public ConnectionConfigType getConfigType()
diff --git a/java/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngine_1_0_0.java b/java/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngine_1_0_0.java
index f31ad5052b..e6282315c6 100755
--- a/java/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngine_1_0_0.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngine_1_0_0.java
@@ -26,12 +26,13 @@ import java.util.UUID;
import java.util.concurrent.atomic.AtomicLong;
import java.util.logging.Level;
import java.util.logging.Logger;
-import javax.security.auth.callback.CallbackHandler;
+import javax.security.sasl.SaslException;
+import javax.security.sasl.SaslServer;
import org.apache.qpid.amqp_1_0.codec.FrameWriter;
import org.apache.qpid.amqp_1_0.framing.AMQFrame;
import org.apache.qpid.amqp_1_0.framing.FrameHandler;
import org.apache.qpid.amqp_1_0.framing.OversizeFrameException;
-import org.apache.qpid.amqp_1_0.transport.CallbackHandlerSource;
+import org.apache.qpid.amqp_1_0.transport.SaslServerProvider;
import org.apache.qpid.amqp_1_0.transport.ConnectionEndpoint;
import org.apache.qpid.amqp_1_0.transport.Container;
import org.apache.qpid.amqp_1_0.transport.FrameOutputHandler;
@@ -95,7 +96,7 @@ public class ProtocolEngine_1_0_0 implements ServerProtocolEngine, FrameOutputHa
}
private State _state = State.A;
-
+
public ProtocolEngine_1_0_0(final IApplicationRegistry appRegistry, long id)
@@ -143,8 +144,9 @@ public class ProtocolEngine_1_0_0 implements ServerProtocolEngine, FrameOutputHa
Container container = new Container(_appRegistry.getBrokerId().toString());
- _conn = new ConnectionEndpoint(container,asCallbackHandlerSource(_appRegistry.getAuthenticationManager()));
- _conn.setConnectionEventListener(new Connection_1_0(_appRegistry));
+ _conn = new ConnectionEndpoint(container, asSaslServerProvider(_appRegistry.getAuthenticationManager(
+ getLocalAddress())));
+ _conn.setConnectionEventListener(new Connection_1_0(_appRegistry, _conn, _connectionId));
_conn.setFrameOutputHandler(this);
_conn.setRemoteAddress(_network.getRemoteAddress());
@@ -155,14 +157,14 @@ public class ProtocolEngine_1_0_0 implements ServerProtocolEngine, FrameOutputHa
_sender.flush();
}
- private CallbackHandlerSource asCallbackHandlerSource(final AuthenticationManager authenticationManager)
+ private SaslServerProvider asSaslServerProvider(final AuthenticationManager authenticationManager)
{
- return new CallbackHandlerSource()
+ return new SaslServerProvider()
{
@Override
- public CallbackHandler getHandler(String mechanism)
+ public SaslServer getSaslServer(String mechanism, String fqdn) throws SaslException
{
- return authenticationManager.getHandler(mechanism);
+ return authenticationManager.createSaslServer(mechanism, fqdn, null);
}
};
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngine_1_0_0_SASL.java b/java/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngine_1_0_0_SASL.java
index ffd5e750b4..a48441bf30 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngine_1_0_0_SASL.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngine_1_0_0_SASL.java
@@ -26,13 +26,14 @@ import java.nio.ByteBuffer;
import java.util.UUID;
import java.util.logging.Level;
import java.util.logging.Logger;
-import javax.security.auth.callback.CallbackHandler;
+import javax.security.sasl.SaslException;
+import javax.security.sasl.SaslServer;
import org.apache.qpid.amqp_1_0.codec.FrameWriter;
import org.apache.qpid.amqp_1_0.codec.ProtocolHandler;
import org.apache.qpid.amqp_1_0.framing.AMQFrame;
import org.apache.qpid.amqp_1_0.framing.OversizeFrameException;
import org.apache.qpid.amqp_1_0.framing.SASLFrameHandler;
-import org.apache.qpid.amqp_1_0.transport.CallbackHandlerSource;
+import org.apache.qpid.amqp_1_0.transport.SaslServerProvider;
import org.apache.qpid.amqp_1_0.transport.ConnectionEndpoint;
import org.apache.qpid.amqp_1_0.transport.Container;
import org.apache.qpid.amqp_1_0.transport.FrameOutputHandler;
@@ -57,7 +58,7 @@ public class ProtocolEngine_1_0_0_SASL implements ServerProtocolEngine, FrameOut
private long _createTime = System.currentTimeMillis();
private ConnectionEndpoint _conn;
private long _connectionId;
-
+
private static final ByteBuffer HEADER =
ByteBuffer.wrap(new byte[]
{
@@ -163,9 +164,9 @@ public class ProtocolEngine_1_0_0_SASL implements ServerProtocolEngine, FrameOut
Container container = new Container(_appRegistry.getBrokerId().toString());
- _conn = new ConnectionEndpoint(container, asCallbackHandlerSource(ApplicationRegistry.getInstance()
- .getAuthenticationManager()));
- _conn.setConnectionEventListener(new Connection_1_0(_appRegistry));
+ _conn = new ConnectionEndpoint(container, asSaslServerProvider(ApplicationRegistry.getInstance()
+ .getAuthenticationManager(getLocalAddress())));
+ _conn.setConnectionEventListener(new Connection_1_0(_appRegistry, _conn, _connectionId));
_conn.setRemoteAddress(getRemoteAddress());
@@ -200,14 +201,14 @@ public class ProtocolEngine_1_0_0_SASL implements ServerProtocolEngine, FrameOut
}
- private CallbackHandlerSource asCallbackHandlerSource(final AuthenticationManager authenticationManager)
+ private SaslServerProvider asSaslServerProvider(final AuthenticationManager authenticationManager)
{
- return new CallbackHandlerSource()
+ return new SaslServerProvider()
{
@Override
- public CallbackHandler getHandler(String mechanism)
+ public SaslServer getSaslServer(String mechanism, String fqdn) throws SaslException
{
- return authenticationManager.getHandler(mechanism);
+ return authenticationManager.createSaslServer(mechanism, fqdn, null);
}
};
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/Connection_1_0.java b/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/Connection_1_0.java
index 318a240b27..f429d8ba9f 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/Connection_1_0.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/Connection_1_0.java
@@ -20,21 +20,35 @@
*/
package org.apache.qpid.server.protocol.v1_0;
+import java.text.MessageFormat;
+import java.util.Collection;
+import org.apache.qpid.AMQException;
+import org.apache.qpid.amqp_1_0.transport.ConnectionEndpoint;
import org.apache.qpid.amqp_1_0.transport.ConnectionEventListener;
import org.apache.qpid.amqp_1_0.transport.SessionEndpoint;
+import org.apache.qpid.protocol.AMQConstant;
+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.registry.IApplicationRegistry;
+import org.apache.qpid.server.stats.StatisticsCounter;
import org.apache.qpid.server.virtualhost.VirtualHost;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import static org.apache.qpid.server.logging.subjects.LogSubjectFormat.CONNECTION_FORMAT;
+
public class Connection_1_0 implements ConnectionEventListener
{
private IApplicationRegistry _appRegistry;
private VirtualHost _vhost;
+ private final ConnectionEndpoint _conn;
+ private final long _connectionId;
+ private final Collection<Session_1_0> _sessions = Collections.synchronizedCollection(new ArrayList<Session_1_0>());
public static interface Task
@@ -48,18 +62,27 @@ public class Connection_1_0 implements ConnectionEventListener
- public Connection_1_0(IApplicationRegistry appRegistry)
+ public Connection_1_0(IApplicationRegistry appRegistry, ConnectionEndpoint conn, long connectionId)
{
_appRegistry = appRegistry;
_vhost = _appRegistry.getVirtualHostRegistry().getDefaultVirtualHost();
+ _conn = conn;
+ _connectionId = connectionId;
+ _vhost.getConnectionRegistry().registerConnection(_model);
+
}
public void remoteSessionCreation(SessionEndpoint endpoint)
{
Session_1_0 session = new Session_1_0(_vhost, _appRegistry, this);
+ _sessions.add(session);
endpoint.setSessionEventListener(session);
}
+ void sessionEnded(Session_1_0 session)
+ {
+ _sessions.remove(session);
+ }
void removeConnectionCloseTask(final Task task)
{
@@ -86,6 +109,8 @@ public class Connection_1_0 implements ConnectionEventListener
{
_closeTasks.clear();
}
+ _vhost.getConnectionRegistry().deregisterConnection(_model);
+
}
@@ -94,5 +119,174 @@ public class Connection_1_0 implements ConnectionEventListener
closeReceived();
}
+ private final AMQConnectionModel _model = new AMQConnectionModel()
+ {
+ private final StatisticsCounter _messageDeliveryStatistics = new StatisticsCounter();
+ private final StatisticsCounter _messageReceiptStatistics = new StatisticsCounter();
+ private final StatisticsCounter _dataDeliveryStatistics = new StatisticsCounter();
+ private final StatisticsCounter _dataReceiptStatistics = new StatisticsCounter();
+
+ private final LogSubject _logSubject = new LogSubject()
+ {
+ @Override
+ public String toLogString()
+ {
+ return "[" +
+ MessageFormat.format(CONNECTION_FORMAT,
+ getConnectionId(),
+ getClientId(),
+ getRemoteAddressString(),
+ _vhost.getName())
+ + "] ";
+
+ }
+ };
+
+ @Override
+ public void close(AMQConstant cause, String message) throws AMQException
+ {
+ // TODO
+ }
+
+ @Override
+ public void block()
+ {
+ // TODO
+ }
+
+ @Override
+ public void unblock()
+ {
+ // TODO
+ }
+
+ @Override
+ public void closeSession(AMQSessionModel session, AMQConstant cause, String message) throws AMQException
+ {
+ // TODO
+ }
+
+ @Override
+ public long getConnectionId()
+ {
+ return _connectionId;
+ }
+
+ @Override
+ public List<AMQSessionModel> getSessionModels()
+ {
+ return new ArrayList<AMQSessionModel>(_sessions);
+ }
+
+ @Override
+ public LogSubject getLogSubject()
+ {
+ return _logSubject;
+ }
+
+ @Override
+ public String getUserName()
+ {
+ return getPrincipalAsString();
+ }
+
+ @Override
+ public boolean isSessionNameUnique(byte[] name)
+ {
+ return true; // TODO
+ }
+
+ @Override
+ public String getRemoteAddressString()
+ {
+ return String.valueOf(_conn.getRemoteAddress());
+ }
+
+ @Override
+ public String getClientId()
+ {
+ return _conn.getRemoteContainerId();
+ }
+
+ @Override
+ public String getClientVersion()
+ {
+ return ""; //TODO
+ }
+
+ @Override
+ public String getPrincipalAsString()
+ {
+ return String.valueOf(_conn.getUser());
+ }
+
+ @Override
+ public long getSessionCountLimit()
+ {
+ return 0; // TODO
+ }
+
+ @Override
+ public long getLastIoTime()
+ {
+ return 0; // TODO
+ }
+
+ @Override
+ public void initialiseStatistics()
+ {
+ // TODO
+ }
+
+ @Override
+ public void registerMessageReceived(long messageSize, long timestamp)
+ {
+ // TODO
+ }
+
+ @Override
+ public void registerMessageDelivered(long messageSize)
+ {
+ // TODO
+ }
+
+ @Override
+ public StatisticsCounter getMessageDeliveryStatistics()
+ {
+ return _messageDeliveryStatistics;
+ }
+
+ @Override
+ public StatisticsCounter getMessageReceiptStatistics()
+ {
+ return _messageReceiptStatistics;
+ }
+
+ @Override
+ public StatisticsCounter getDataDeliveryStatistics()
+ {
+ return _dataDeliveryStatistics;
+ }
+
+ @Override
+ public StatisticsCounter getDataReceiptStatistics()
+ {
+ return _dataReceiptStatistics;
+ }
+
+ @Override
+ public void resetStatistics()
+ {
+ // TODO
+ }
+
+
+ };
+
+ AMQConnectionModel getModel()
+ {
+ return _model;
+ }
+
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/LinkRegistry.java b/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/LinkRegistry.java
index 42eea05d37..0bb9a15968 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/LinkRegistry.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/LinkRegistry.java
@@ -1,3 +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.
+ *
+ */
package org.apache.qpid.server.protocol.v1_0;
import java.util.HashMap;
diff --git a/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/ReceivingLinkAttachment.java b/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/ReceivingLinkAttachment.java
index 6da5081185..46b9682c74 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/ReceivingLinkAttachment.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/ReceivingLinkAttachment.java
@@ -1,3 +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.
+ *
+ */
package org.apache.qpid.server.protocol.v1_0;
import org.apache.qpid.amqp_1_0.transport.DeliveryStateHandler;
diff --git a/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/SendingLinkAttachment.java b/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/SendingLinkAttachment.java
index 9d7af24135..09a2ddea3a 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/SendingLinkAttachment.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/SendingLinkAttachment.java
@@ -1,3 +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.
+ *
+ */
package org.apache.qpid.server.protocol.v1_0;
import org.apache.qpid.amqp_1_0.transport.DeliveryStateHandler;
diff --git a/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/SendingLink_1_0.java b/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/SendingLink_1_0.java
index b3e9a74d04..75235c7ef0 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/SendingLink_1_0.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/SendingLink_1_0.java
@@ -200,7 +200,7 @@ public class SendingLink_1_0 implements SendingLinkListener, Link_1_0, DeliveryS
if(queue == null)
{
queue = AMQQueueFactory.createAMQQueueImpl(
- UUIDGenerator.generateUUID(),
+ UUIDGenerator.generateQueueUUID(name, _vhost.getName()),
name,
isDurable,
null,
diff --git a/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/Session_1_0.java b/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/Session_1_0.java
index 48a551e42a..999ffc55e5 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/Session_1_0.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/Session_1_0.java
@@ -20,6 +20,7 @@
*/
package org.apache.qpid.server.protocol.v1_0;
+import java.text.MessageFormat;
import org.apache.qpid.amqp_1_0.transport.LinkEndpoint;
import org.apache.qpid.amqp_1_0.transport.ReceivingLinkEndpoint;
import org.apache.qpid.amqp_1_0.transport.SendingLinkEndpoint;
@@ -35,18 +36,26 @@ import org.apache.qpid.amqp_1_0.type.transport.*;
import org.apache.qpid.amqp_1_0.type.transport.Error;
import org.apache.qpid.AMQException;
import org.apache.qpid.AMQSecurityException;
+import org.apache.qpid.protocol.ProtocolEngine;
import org.apache.qpid.server.exchange.Exchange;
+import org.apache.qpid.server.logging.LogSubject;
+import org.apache.qpid.server.message.InboundMessage;
import org.apache.qpid.server.model.UUIDGenerator;
+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.registry.IApplicationRegistry;
+import org.apache.qpid.server.transport.ServerConnection;
import org.apache.qpid.server.txn.AutoCommitTransaction;
import org.apache.qpid.server.txn.ServerTransaction;
import org.apache.qpid.server.virtualhost.VirtualHost;
import java.util.*;
-public class Session_1_0 implements SessionEventListener
+import static org.apache.qpid.server.logging.subjects.LogSubjectFormat.CHANNEL_FORMAT;
+
+public class Session_1_0 implements SessionEventListener, AMQSessionModel, LogSubject
{
private static final Symbol LIFETIME_POLICY = Symbol.valueOf("lifetime-policy");
private IApplicationRegistry _appRegistry;
@@ -56,6 +65,7 @@ public class Session_1_0 implements SessionEventListener
private final LinkedHashMap<Integer, ServerTransaction> _openTransactions =
new LinkedHashMap<Integer, ServerTransaction>();
private final Connection_1_0 _connection;
+ private UUID _id = UUID.randomUUID();
public Session_1_0(VirtualHost vhost, IApplicationRegistry appRegistry, final Connection_1_0 connection)
@@ -319,7 +329,7 @@ public class Session_1_0 implements SessionEventListener
? null
: (LifetimePolicy) properties.get(LIFETIME_POLICY);
- final AMQQueue tempQueue = queue = AMQQueueFactory.createAMQQueueImpl( UUIDGenerator.generateUUID(),
+ final AMQQueue tempQueue = queue = AMQQueueFactory.createAMQQueueImpl( UUIDGenerator.generateQueueUUID(queueName, _vhost.getName()),
queueName,
false, // durable
null, // owner
@@ -405,6 +415,8 @@ public class Session_1_0 implements SessionEventListener
iter.remove();
}
+ _connection.sessionEnded(this);
+
}
Integer binaryToInteger(final Binary txnId)
@@ -443,4 +455,153 @@ public class Session_1_0 implements SessionEventListener
public void forceEnd()
{
}
+
+ @Override
+ public UUID getQMFId()
+ {
+ return _id;
+ }
+
+ @Override
+ public AMQConnectionModel getConnectionModel()
+ {
+ return _connection.getModel();
+ }
+
+ @Override
+ public String getClientID()
+ {
+ // TODO
+ return "";
+ }
+
+ @Override
+ public void close() throws AMQException
+ {
+ // TODO - required for AMQSessionModel / management initiated closing
+ }
+
+ @Override
+ public LogSubject getLogSubject()
+ {
+ return this;
+ }
+
+ @Override
+ public void checkTransactionStatus(long openWarn, long openClose, long idleWarn, long idleClose) throws AMQException
+ {
+ // TODO - required for AMQSessionModel / long running transaction detection
+ }
+
+ @Override
+ public void block(AMQQueue queue)
+ {
+ // TODO - required for AMQSessionModel / producer side flow control
+ }
+
+ @Override
+ public void unblock(AMQQueue queue)
+ {
+ // TODO - required for AMQSessionModel / producer side flow control
+ }
+
+ @Override
+ public void block()
+ {
+ // TODO - required for AMQSessionModel / producer side flow control
+ }
+
+ @Override
+ public void unblock()
+ {
+ // TODO - required for AMQSessionModel / producer side flow control
+ }
+
+ @Override
+ public boolean getBlocking()
+ {
+ // TODO
+ return false;
+ }
+
+ @Override
+ public boolean onSameConnection(InboundMessage inbound)
+ {
+ // TODO
+ return false;
+ }
+
+ @Override
+ public int getUnacknowledgedMessageCount()
+ {
+ // TODO
+ return 0;
+ }
+
+ @Override
+ public Long getTxnCount()
+ {
+ // TODO
+ return 0l;
+ }
+
+ @Override
+ public Long getTxnStart()
+ {
+ // TODO
+ return 0l;
+ }
+
+ @Override
+ public Long getTxnCommits()
+ {
+ // TODO
+ return 0l;
+ }
+
+ @Override
+ public Long getTxnRejects()
+ {
+ // TODO
+ return 0l;
+ }
+
+ @Override
+ public int getChannelId()
+ {
+ // TODO
+ return 0;
+ }
+
+ @Override
+ public int getConsumerCount()
+ {
+ // TODO
+ return 0;
+ }
+
+ @Override
+ public int compareTo(AMQSessionModel o)
+ {
+ return getQMFId().compareTo(o.getQMFId());
+ }
+
+
+
+ public String toLogString()
+ {
+ long connectionId = getConnectionModel().getConnectionId();
+
+ String remoteAddress = getConnectionModel().getRemoteAddressString();
+
+ return "[" +
+ MessageFormat.format(CHANNEL_FORMAT,
+ connectionId,
+ getClientID(),
+ remoteAddress,
+ _vhost.getName(), // TODO - virtual host
+ 0) // TODO - channel)
+ + "] ";
+ }
+
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/Subscription_1_0.java b/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/Subscription_1_0.java
index 08926d000d..8a3d3716c7 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/Subscription_1_0.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/Subscription_1_0.java
@@ -49,6 +49,7 @@ import org.apache.qpid.amqp_1_0.type.transport.Transfer;
import org.apache.qpid.server.filter.FilterManager;
import org.apache.qpid.server.logging.LogActor;
import org.apache.qpid.server.message.ServerMessage;
+import org.apache.qpid.server.protocol.AMQSessionModel;
import org.apache.qpid.server.queue.AMQQueue;
import org.apache.qpid.server.queue.QueueEntry;
import org.apache.qpid.server.subscription.Subscription;
@@ -66,7 +67,7 @@ class Subscription_1_0 implements Subscription
private final QueueEntry.SubscriptionAssignedState _assignedState = new QueueEntry.SubscriptionAssignedState(this);
private final long _id;
private final boolean _acquires;
- private AMQQueue.Context _queueContext;
+ private volatile AMQQueue.Context _queueContext;
private Map<String, Object> _properties = new ConcurrentHashMap<String, Object>();
private ReentrantLock _stateChangeLock = new ReentrantLock();
@@ -631,4 +632,46 @@ class Subscription_1_0 implements Subscription
{
_filters = filters;
}
+
+ @Override
+ public AMQSessionModel getSessionModel()
+ {
+ // TODO
+ return getSession();
+ }
+
+ @Override
+ public long getBytesOut()
+ {
+ // TODO
+ return 0;
+ }
+
+ @Override
+ public long getMessagesOut()
+ {
+ // TODO
+ return 0;
+ }
+
+ @Override
+ public long getUnacknowledgedBytes()
+ {
+ // TODO
+ return 0;
+ }
+
+ @Override
+ public long getUnacknowledgedMessages()
+ {
+ // TODO
+ return 0;
+ }
+
+ @Override
+ public String getConsumerName()
+ {
+ //TODO
+ return "TODO";
+ }
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/UnsettledAction.java b/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/UnsettledAction.java
index c497cc5146..0fee4086b4 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/UnsettledAction.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/UnsettledAction.java
@@ -1,3 +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.
+ *
+ */
package org.apache.qpid.server.protocol.v1_0;
import org.apache.qpid.amqp_1_0.type.DeliveryState;
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 e643338c3d..d3efd63ee0 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
@@ -28,21 +28,25 @@ import org.apache.qpid.server.configuration.plugins.ConfigurationPlugin;
import org.apache.qpid.server.exchange.Exchange;
import org.apache.qpid.server.exchange.ExchangeReferrer;
import org.apache.qpid.server.logging.LogSubject;
-import org.apache.qpid.server.management.Managable;
-import org.apache.qpid.server.management.ManagedObject;
import org.apache.qpid.server.protocol.AMQSessionModel;
import org.apache.qpid.server.security.AuthorizationHolder;
import org.apache.qpid.server.store.TransactionLogResource;
import org.apache.qpid.server.subscription.Subscription;
import org.apache.qpid.server.virtualhost.VirtualHost;
+import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
-public interface AMQQueue extends Managable, Comparable<AMQQueue>, ExchangeReferrer, TransactionLogResource, BaseQueue,
+public interface AMQQueue extends Comparable<AMQQueue>, ExchangeReferrer, TransactionLogResource, BaseQueue,
QueueConfig
{
+ public interface NotificationListener
+ {
+ void notifyClients(NotificationCheck notification, AMQQueue queue, String notificationMsg);
+ }
+
boolean getDeleteOnNoConsumers();
void setDeleteOnNoConsumers(boolean b);
@@ -57,6 +61,12 @@ public interface AMQQueue extends Managable, Comparable<AMQQueue>, ExchangeRefer
LogSubject getLogSubject();
+ long getUnackedMessageBytes();
+
+ long getTotalDequeueCount();
+
+ long getTotalEnqueueCount();
+
public interface Context
{
QueueEntry getLastSeenEntry();
@@ -79,6 +89,17 @@ public interface AMQQueue extends Managable, Comparable<AMQQueue>, ExchangeRefer
void unregisterSubscription(final Subscription subscription) throws AMQException;
+ Collection<Subscription> getConsumers();
+
+ interface SubscriptionRegistrationListener
+ {
+ void subscriptionRegistered(AMQQueue queue, Subscription subscription);
+ void subscriptionUnregistered(AMQQueue queue, Subscription subscription);
+ }
+
+ void addSubscriptionRegistrationListener(SubscriptionRegistrationListener listener);
+ void removeSubscriptionRegistrationListener(SubscriptionRegistrationListener listener);
+
int getConsumerCount();
@@ -109,7 +130,7 @@ public interface AMQQueue extends Managable, Comparable<AMQQueue>, ExchangeRefer
void dequeue(QueueEntry entry, Subscription sub);
- void decrementUnackedMsgCount();
+ void decrementUnackedMsgCount(QueueEntry queueEntry);
boolean resend(final QueueEntry entry, final Subscription subscription) throws AMQException;
@@ -139,20 +160,8 @@ public interface AMQQueue extends Managable, Comparable<AMQQueue>, ExchangeRefer
*/
public List<QueueEntry> getMessagesRangeOnTheQueue(final long fromPosition, final long toPosition);
+ void visit(QueueEntryVisitor visitor);
- void moveMessagesToAnotherQueue(long fromMessageId, long toMessageId, String queueName);
-
- void copyMessagesToAnotherQueue(long fromMessageId, long toMessageId, String queueName);
-
- void removeMessagesFromQueue(long fromMessageId, long toMessageId);
-
- static interface Visitor
- {
- boolean visit(QueueEntry entry);
- }
-
- void visit(Visitor visitor);
-
long getMaximumMessageSize();
@@ -216,8 +225,6 @@ public interface AMQQueue extends Managable, Comparable<AMQQueue>, ExchangeRefer
void setAlternateExchange(Exchange exchange);
- void setAlternateExchange(String exchangeName);
-
Map<String, Object> getArguments();
void checkCapacity(AMQSessionModel channel);
@@ -245,12 +252,12 @@ public interface AMQQueue extends Managable, Comparable<AMQQueue>, ExchangeRefer
}
/**
- * ExistingSubscriptionPreventsExclusive signals a failure to create an exclusize subscription, as a subscription
+ * ExistingSubscriptionPreventsExclusive signals a failure to create an exclusive subscription, as a subscription
* already exists.
*
* <p/><table id="crc"><caption>CRC Card</caption>
* <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Represent failure to create an exclusize subscription, as a subscription already exists.
+ * <tr><td> Represent failure to create an exclusive subscription, as a subscription already exists.
* </table>
*
* @todo Not an AMQP exception as no status code.
@@ -274,9 +281,7 @@ public interface AMQQueue extends Managable, Comparable<AMQQueue>, ExchangeRefer
ConfigurationPlugin getConfiguration();
- ManagedObject getManagedObject();
-
- void setExclusive(boolean exclusive) throws AMQException;
+ void setExclusive(boolean exclusive);
/**
* Gets the maximum delivery count. If a message on this queue
@@ -295,4 +300,19 @@ public interface AMQQueue extends Managable, Comparable<AMQQueue>, ExchangeRefer
*/
public void setMaximumDeliveryCount(final int maximumDeliveryCount);
+ void setNotificationListener(NotificationListener listener);
+
+ /**
+ * Sets the free text description of this queue.
+ *
+ * @param description
+ *
+ */
+ void setDescription(String description);
+
+ /**
+ * Gets the free text description of this queue.
+ */
+ String getDescription();
+
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueFactory.java b/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueFactory.java
index f2b7d7c56b..3a18fae2ec 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueFactory.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueFactory.java
@@ -20,6 +20,7 @@
*/
package org.apache.qpid.server.queue;
+import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
@@ -41,6 +42,7 @@ import org.apache.qpid.server.virtualhost.VirtualHost;
public class AMQQueueFactory
{
public static final String X_QPID_PRIORITIES = "x-qpid-priorities";
+ public static final String X_QPID_DESCRIPTION = "x-qpid-description";
public static final String QPID_LVQ_KEY = "qpid.LVQ_key";
public static final String QPID_LAST_VALUE_QUEUE = "qpid.last_value_queue";
public static final String QPID_LAST_VALUE_QUEUE_KEY = "qpid.last_value_queue_key";
@@ -169,29 +171,7 @@ public class AMQQueueFactory
};
/**
- * Creates a new queue with a random id.
- *
- * @see #createAMQQueueImpl(UUID, String, boolean, String, boolean, boolean, VirtualHost, Map)
- * @deprecated because only called from unit tests
- * */
- @Deprecated
- public static AMQQueue createAMQQueueImpl(AMQShortString name,
- boolean durable,
- AMQShortString owner,
- boolean autoDelete,
- boolean exclusive,
- VirtualHost virtualHost, final FieldTable arguments) throws AMQException
- {
- return createAMQQueueImpl(UUIDGenerator.generateUUID(),
- name == null ? null : name.toString(),
- durable,
- owner == null ? null : owner.toString(),
- autoDelete,
- exclusive, virtualHost, FieldTable.convertToMap(arguments));
- }
-
- /**
- * @param id the id to use. If default then one is generated from queueName. TODO check correctness of calls that pass a null value.
+ * @param id the id to use.
*/
public static AMQQueue createAMQQueueImpl(UUID id,
String queueName,
@@ -300,7 +280,7 @@ public class AMQQueueFactory
if(dlExchange == null)
{
- dlExchange = exchangeFactory.createExchange(UUIDGenerator.generateUUID(dlExchangeName, virtualHost.getName()), new AMQShortString(dlExchangeName), ExchangeDefaults.FANOUT_EXCHANGE_CLASS, true, false, 0);
+ dlExchange = exchangeFactory.createExchange(UUIDGenerator.generateExchangeUUID(dlExchangeName, virtualHost.getName()), new AMQShortString(dlExchangeName), ExchangeDefaults.FANOUT_EXCHANGE_CLASS, true, false, 0);
exchangeRegistry.registerExchange(dlExchange);
@@ -322,7 +302,7 @@ public class AMQQueueFactory
args.put(X_QPID_DLQ_ENABLED, false);
args.put(X_QPID_MAXIMUM_DELIVERY_COUNT, 0);
- dlQueue = createAMQQueueImpl(UUIDGenerator.generateUUID(dlQueueName, virtualHost.getName()), dlQueueName, true, owner, false, exclusive, virtualHost, args);
+ dlQueue = createAMQQueueImpl(UUIDGenerator.generateQueueUUID(dlQueueName, virtualHost.getName()), dlQueueName, true, owner, false, exclusive, virtualHost, args);
//enter the dlq in the persistent store
virtualHost.getMessageStore().createQueue(dlQueue, FieldTable.convertToFieldTable(args));
@@ -350,42 +330,16 @@ public class AMQQueueFactory
boolean autodelete = config.getAutoDelete();
boolean exclusive = config.getExclusive();
String owner = config.getOwner();
- Map<String,Object> arguments = null;
-
- if(config.isLVQ() || config.getLVQKey() != null)
- {
- arguments = new HashMap<String,Object>();
- arguments.put(QPID_LAST_VALUE_QUEUE, 1);
- arguments.put(QPID_LAST_VALUE_QUEUE_KEY, config.getLVQKey() == null ? QPID_LVQ_KEY : config.getLVQKey());
- }
- else if (config.getPriority() || config.getPriorities() > 0)
- {
- arguments = new HashMap<String,Object>();
- arguments.put(X_QPID_PRIORITIES, config.getPriorities() < 0 ? 10 : config.getPriorities());
- }
- else if (config.getQueueSortKey() != null && !"".equals(config.getQueueSortKey()))
- {
- arguments = new HashMap<String,Object>();
- arguments.put(QPID_QUEUE_SORT_KEY, config.getQueueSortKey());
- }
- if (!config.getAutoDelete() && config.isDeadLetterQueueEnabled())
- {
- if (arguments == null)
- {
- arguments = new HashMap<String,Object>();
- }
- arguments.put(X_QPID_DLQ_ENABLED, true);
- }
+ Map<String, Object> arguments = createQueueArgumentsFromConfig(config);
// we need queues that are defined in config to have deterministic ids.
- UUID id = UUIDGenerator.generateUUID(queueName, host.getName());
+ UUID id = UUIDGenerator.generateQueueUUID(queueName, host.getName());
AMQQueue q = createAMQQueueImpl(id, queueName, durable, owner, autodelete, exclusive, host, arguments);
q.configure(config);
return q;
}
-
/**
* Validates DLQ and DLE names
* <p>
@@ -475,4 +429,43 @@ public class AMQQueueFactory
String dlExchangeName = name + serverConfig.getDeadLetterExchangeSuffix();
return dlExchangeName;
}
+
+ private static Map<String, Object> createQueueArgumentsFromConfig(QueueConfiguration config)
+ {
+ Map<String,Object> arguments = new HashMap<String,Object>();
+
+ if(config.isLVQ() || config.getLVQKey() != null)
+ {
+ arguments.put(QPID_LAST_VALUE_QUEUE, 1);
+ arguments.put(QPID_LAST_VALUE_QUEUE_KEY, config.getLVQKey() == null ? QPID_LVQ_KEY : config.getLVQKey());
+ }
+ else if (config.getPriority() || config.getPriorities() > 0)
+ {
+ arguments.put(X_QPID_PRIORITIES, config.getPriorities() < 0 ? 10 : config.getPriorities());
+ }
+ else if (config.getQueueSortKey() != null && !"".equals(config.getQueueSortKey()))
+ {
+ arguments.put(QPID_QUEUE_SORT_KEY, config.getQueueSortKey());
+ }
+
+ if (!config.getAutoDelete() && config.isDeadLetterQueueEnabled())
+ {
+ arguments.put(X_QPID_DLQ_ENABLED, true);
+ }
+
+ if (config.getDescription() != null && !"".equals(config.getDescription()))
+ {
+ arguments.put(X_QPID_DESCRIPTION, config.getDescription());
+ }
+
+ if (arguments.isEmpty())
+ {
+ return Collections.emptyMap();
+ }
+ else
+ {
+ return arguments;
+ }
+ }
+
}
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
deleted file mode 100644
index b0d4cb3486..0000000000
--- a/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueMBean.java
+++ /dev/null
@@ -1,664 +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.commons.lang.time.FastDateFormat;
-import org.apache.log4j.Logger;
-
-import org.apache.qpid.AMQException;
-import org.apache.qpid.framing.BasicContentHeaderProperties;
-import org.apache.qpid.framing.ContentHeaderBody;
-import org.apache.qpid.management.common.mbeans.ManagedQueue;
-import org.apache.qpid.management.common.mbeans.annotations.MBeanConstructor;
-import org.apache.qpid.management.common.mbeans.annotations.MBeanDescription;
-import org.apache.qpid.server.exchange.Exchange;
-import org.apache.qpid.server.management.AMQManagedObject;
-import org.apache.qpid.server.management.ManagedObject;
-import org.apache.qpid.server.message.AMQMessage;
-import org.apache.qpid.server.message.AMQMessageHeader;
-import org.apache.qpid.server.message.MessageTransferMessage;
-import org.apache.qpid.server.message.ServerMessage;
-import org.apache.qpid.transport.MessageProperties;
-
-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;
-import javax.management.openmbean.CompositeData;
-import javax.management.openmbean.CompositeDataSupport;
-import javax.management.openmbean.CompositeType;
-import javax.management.openmbean.OpenDataException;
-import javax.management.openmbean.OpenType;
-import javax.management.openmbean.SimpleType;
-import javax.management.openmbean.TabularData;
-import javax.management.openmbean.TabularDataSupport;
-import javax.management.openmbean.TabularType;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Set;
-
-
-/**
- * AMQQueueMBean is the management bean for an {@link AMQQueue}.
- *
- * <p/><table id="crc"><caption>CRC Caption</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * </table>
- */
-@MBeanDescription("Management Interface for AMQQueue")
-public class AMQQueueMBean extends AMQManagedObject implements ManagedQueue, QueueNotificationListener
-{
-
- /** Used for debugging purposes. */
- private static final Logger LOGGER = Logger.getLogger(AMQQueueMBean.class);
-
- /** Date/time format used for message expiration and message timestamp formatting */
- public static final String JMSTIMESTAMP_DATETIME_FORMAT = "MM-dd-yy HH:mm:ss.SSS z";
-
- private static final FastDateFormat FAST_DATE_FORMAT = FastDateFormat.getInstance(JMSTIMESTAMP_DATETIME_FORMAT);
-
- private final AMQQueue _queue;
- private final String _queueName;
- // OpenMBean data types for viewMessages method
-
- private static OpenType[] _msgAttributeTypes = new OpenType[6]; // AMQ message attribute types.
- private static CompositeType _messageDataType = null; // Composite type for representing AMQ Message data.
- private static TabularType _messagelistDataType = null; // Datatype for representing AMQ messages list.
-
- // OpenMBean data types for viewMessageContent method
- private static CompositeType _msgContentType = null;
- private static OpenType[] _msgContentAttributeTypes = new OpenType[4];
-
- private final long[] _lastNotificationTimes = new long[NotificationCheck.values().length];
- private Notification _lastNotification = null;
-
-
-
-
- @MBeanConstructor("Creates an MBean exposing an AMQQueue")
- public AMQQueueMBean(AMQQueue queue) throws JMException
- {
- super(ManagedQueue.class, ManagedQueue.TYPE);
- _queue = queue;
- _queueName = queue.getName();
- }
-
- public ManagedObject getParentObject()
- {
- return _queue.getVirtualHost().getManagedObject();
- }
-
- static
- {
- try
- {
- init();
- }
- catch (JMException ex)
- {
- // This is not expected to ever occur.
- throw new RuntimeException("Got JMException in static initializer.", ex);
- }
- }
-
- /**
- * initialises the openmbean data types
- */
- private static void init() throws OpenDataException
- {
- _msgContentAttributeTypes[0] = SimpleType.LONG; // For message id
- _msgContentAttributeTypes[1] = SimpleType.STRING; // For MimeType
- _msgContentAttributeTypes[2] = SimpleType.STRING; // For Encoding
- _msgContentAttributeTypes[3] = new ArrayType(1, SimpleType.BYTE); // For message content
- _msgContentType = new CompositeType("Message Content", "AMQ Message Content",
- VIEW_MSG_CONTENT_COMPOSITE_ITEM_NAMES_DESC.toArray(new String[VIEW_MSG_CONTENT_COMPOSITE_ITEM_NAMES_DESC.size()]),
- VIEW_MSG_CONTENT_COMPOSITE_ITEM_NAMES_DESC.toArray(new String[VIEW_MSG_CONTENT_COMPOSITE_ITEM_NAMES_DESC.size()]),
- _msgContentAttributeTypes);
-
- _msgAttributeTypes[0] = SimpleType.LONG; // For message id
- _msgAttributeTypes[1] = new ArrayType(1, SimpleType.STRING); // For header attributes
- _msgAttributeTypes[2] = SimpleType.LONG; // For size
- _msgAttributeTypes[3] = SimpleType.BOOLEAN; // For redelivered
- _msgAttributeTypes[4] = SimpleType.LONG; // For queue position
- _msgAttributeTypes[5] = SimpleType.INTEGER; // For delivery count
-
- _messageDataType = new CompositeType("Message", "AMQ Message",
- VIEW_MSGS_COMPOSITE_ITEM_NAMES_DESC.toArray(new String[VIEW_MSGS_COMPOSITE_ITEM_NAMES_DESC.size()]),
- VIEW_MSGS_COMPOSITE_ITEM_NAMES_DESC.toArray(new String[VIEW_MSGS_COMPOSITE_ITEM_NAMES_DESC.size()]), _msgAttributeTypes);
- _messagelistDataType = new TabularType("Messages", "List of messages", _messageDataType,
- VIEW_MSGS_TABULAR_UNIQUE_INDEX.toArray(new String[VIEW_MSGS_TABULAR_UNIQUE_INDEX.size()]));
- }
-
- public String getObjectInstanceName()
- {
- return ObjectName.quote(_queueName);
- }
-
- public String getName()
- {
- return _queueName;
- }
-
- public boolean isDurable()
- {
- return _queue.isDurable();
- }
-
- public String getOwner()
- {
- return String.valueOf(_queue.getOwner());
- }
-
- public boolean isAutoDelete()
- {
- return _queue.isAutoDelete();
- }
-
- public Integer getMessageCount()
- {
- return _queue.getMessageCount();
- }
-
- public Integer getMaximumDeliveryCount()
- {
- return _queue.getMaximumDeliveryCount();
- }
-
- public Long getMaximumMessageSize()
- {
- return _queue.getMaximumMessageSize();
- }
-
- public Long getMaximumMessageAge()
- {
- return _queue.getMaximumMessageAge();
- }
-
- public void setMaximumMessageAge(Long maximumMessageAge)
- {
- _queue.setMaximumMessageAge(maximumMessageAge);
- }
-
- public void setMaximumMessageSize(Long value)
- {
- _queue.setMaximumMessageSize(value);
- }
-
- public Integer getConsumerCount()
- {
- return _queue.getConsumerCount();
- }
-
- public Integer getActiveConsumerCount()
- {
- return _queue.getActiveConsumerCount();
- }
-
- public Long getReceivedMessageCount()
- {
- return _queue.getReceivedMessageCount();
- }
-
- public Long getMaximumMessageCount()
- {
- return _queue.getMaximumMessageCount();
- }
-
- public void setMaximumMessageCount(Long value)
- {
- _queue.setMaximumMessageCount(value);
- }
-
- /**
- * returns the maximum total size of messages(bytes) in the queue.
- */
- public Long getMaximumQueueDepth()
- {
- return _queue.getMaximumQueueDepth();
- }
-
- public void setMaximumQueueDepth(Long value)
- {
- _queue.setMaximumQueueDepth(value);
- }
-
- /**
- * returns the total size of messages(bytes) in the queue.
- */
- public Long getQueueDepth() throws JMException
- {
- return _queue.getQueueDepth();
- }
-
- public Long getCapacity()
- {
- return _queue.getCapacity();
- }
-
- public void setCapacity(Long capacity) throws IllegalArgumentException
- {
- if( _queue.getFlowResumeCapacity() > capacity )
- {
- throw new IllegalArgumentException("Capacity must not be less than FlowResumeCapacity");
- }
-
- _queue.setCapacity(capacity);
- }
-
- public Long getFlowResumeCapacity()
- {
- return _queue.getFlowResumeCapacity();
- }
-
- public void setFlowResumeCapacity(Long flowResumeCapacity) throws IllegalArgumentException
- {
- if( _queue.getCapacity() < flowResumeCapacity )
- {
- throw new IllegalArgumentException("FlowResumeCapacity must not exceed Capacity");
- }
-
- _queue.setFlowResumeCapacity(flowResumeCapacity);
- }
-
- public boolean isFlowOverfull()
- {
- return _queue.isOverfull();
- }
-
- public boolean isExclusive()
- {
- return _queue.isExclusive();
- }
-
- public void setExclusive(boolean exclusive) throws JMException
- {
- try
- {
- _queue.setExclusive(exclusive);
- }
- catch (AMQException e)
- {
- throw new JMException(e.toString());
- }
- }
-
- public void setAlternateExchange(String exchangeName)
- {
- _queue.setAlternateExchange(exchangeName);
- }
-
- public String getAlternateExchange()
- {
- Exchange exchange = _queue.getAlternateExchange();
- String name = exchange == null ? null : exchange.getName();
- return name == null ? null : name;
- }
-
- /**
- * Checks if there is any notification to be send to the listeners
- */
- public void checkForNotification(ServerMessage msg) throws AMQException
- {
-
- final Set<NotificationCheck> notificationChecks = _queue.getNotificationChecks();
-
- if(!notificationChecks.isEmpty())
- {
- final long currentTime = System.currentTimeMillis();
- final long thresholdTime = currentTime - _queue.getMinimumAlertRepeatGap();
-
- for (NotificationCheck check : notificationChecks)
- {
- if (check.isMessageSpecific() || (_lastNotificationTimes[check.ordinal()] < thresholdTime))
- {
- if (check.notifyIfNecessary(msg, _queue, this))
- {
- _lastNotificationTimes[check.ordinal()] = currentTime;
- }
- }
- }
- }
-
- }
-
- /**
- * Sends the notification to the listeners
- */
- public void notifyClients(NotificationCheck notification, AMQQueue queue, String notificationMsg)
- {
- // important : add log to the log file - monitoring tools may be looking for this
- LOGGER.info(notification.name() + " On Queue " + queue.getNameShortString() + " - " + notificationMsg);
- notificationMsg = notification.name() + " " + notificationMsg;
-
- _lastNotification =
- new Notification(MonitorNotification.THRESHOLD_VALUE_EXCEEDED, this, incrementAndGetSequenceNumber(),
- System.currentTimeMillis(), notificationMsg);
-
- getBroadcaster().sendNotification(_lastNotification);
- }
-
- public Notification getLastNotification()
- {
- return _lastNotification;
- }
-
- /**
- * @see AMQQueue#deleteMessageFromTop
- */
- public void deleteMessageFromTop() throws JMException
- {
- _queue.deleteMessageFromTop();
- }
-
- /**
- * Clears the queue of non-acquired messages
- *
- * @return the number of messages deleted
- * @see AMQQueue#clearQueue
- */
- public Long clearQueue() throws JMException
- {
- try
- {
- return _queue.clearQueue();
- }
- catch (AMQException ex)
- {
- throw new MBeanException(ex, "Error clearing queue " + _queueName);
- }
- }
-
- /**
- * returns message content as byte array and related attributes for the given message id.
- */
- public CompositeData viewMessageContent(long msgId) throws JMException
- {
- QueueEntry entry = _queue.getMessageOnTheQueue(msgId);
-
- if (entry == null)
- {
- throw new OperationsException("AMQMessage with message id = " + msgId + " is not in the " + _queueName);
- }
-
- ServerMessage serverMsg = entry.getMessage();
- final int bodySize = (int) serverMsg.getSize();
-
-
- List<Byte> msgContent = new ArrayList<Byte>();
-
- java.nio.ByteBuffer buf = java.nio.ByteBuffer.allocate(bodySize);
- int position = 0;
-
- while(position < bodySize)
- {
- position += serverMsg.getContent(buf, position);
- buf.flip();
- for(int i = 0; i < buf.limit(); i++)
- {
- msgContent.add(buf.get(i));
- }
- buf.clear();
- }
-
- AMQMessageHeader header = serverMsg.getMessageHeader();
-
- String mimeType = null, encoding = null;
- if (header != null)
- {
- mimeType = header.getMimeType();
-
- encoding = header.getEncoding();
- }
-
-
- Object[] itemValues = { msgId, mimeType, encoding, msgContent.toArray(new Byte[0]) };
-
- return new CompositeDataSupport(_msgContentType,
- VIEW_MSG_CONTENT_COMPOSITE_ITEM_NAMES_DESC.toArray(
- new String[VIEW_MSG_CONTENT_COMPOSITE_ITEM_NAMES_DESC.size()]), itemValues);
-
- }
-
- /**
- * Returns the header contents of the messages stored in this queue in tabular form.
- * Deprecated as of Qpid JMX API 1.3
- */
- @Deprecated
- public TabularData viewMessages(int beginIndex, int endIndex) throws JMException
- {
- return viewMessages((long)beginIndex,(long)endIndex);
- }
-
-
- /**
- * Returns the header contents of the messages stored in this queue in tabular form.
- * @param startPosition The queue position of the first message to be viewed
- * @param endPosition The queue position of the last message to be viewed
- */
- public TabularData viewMessages(long startPosition, long endPosition) throws JMException
- {
- if ((startPosition > endPosition) || (startPosition < 1))
- {
- throw new OperationsException("From Index = " + startPosition + ", To Index = " + endPosition
- + "\n\"From Index\" should be greater than 0 and less than \"To Index\"");
- }
-
- if ((endPosition - startPosition) > Integer.MAX_VALUE)
- {
- throw new OperationsException("Specified MessageID interval is too large. Intervals must be less than 2^31 in size");
- }
-
- List<QueueEntry> list = _queue.getMessagesRangeOnTheQueue(startPosition,endPosition);
- TabularDataSupport _messageList = new TabularDataSupport(_messagelistDataType);
-
- try
- {
- // Create the tabular list of message header contents
- int size = list.size();
-
- for (int i = 0; i < size ; i++)
- {
- long position = startPosition + i;
- final QueueEntry queueEntry = list.get(i);
- ServerMessage serverMsg = queueEntry.getMessage();
-
- String[] headerAttributes = null;
- Object[] itemValues = null;
-
- if(serverMsg instanceof AMQMessage)
- {
- AMQMessage msg = (AMQMessage) serverMsg;
- ContentHeaderBody headerBody = msg.getContentHeaderBody();
- // Create header attributes list
- headerAttributes = getMessageHeaderProperties(headerBody);
- itemValues = new Object[]{msg.getMessageId(), headerAttributes, headerBody.getBodySize(), queueEntry.isRedelivered(), position, queueEntry.getDeliveryCount()};
- }
- else if(serverMsg instanceof MessageTransferMessage)
- {
- // We have a 0-10 message
- MessageTransferMessage msg = (MessageTransferMessage) serverMsg;
-
- // Create header attributes list
- headerAttributes = getMessageTransferMessageHeaderProps(msg);
- itemValues = new Object[]{msg.getMessageNumber(), headerAttributes, msg.getSize(), queueEntry.isRedelivered(), position, queueEntry.getDeliveryCount()};
- }
- else
- {
- //unknown message
- headerAttributes = new String[]{"N/A"};
- itemValues = new Object[]{serverMsg.getMessageNumber(), headerAttributes, serverMsg.getSize(), queueEntry.isRedelivered(), position, queueEntry.getDeliveryCount()};
- }
-
- CompositeData messageData = new CompositeDataSupport(_messageDataType,
- VIEW_MSGS_COMPOSITE_ITEM_NAMES_DESC.toArray(new String[VIEW_MSGS_COMPOSITE_ITEM_NAMES_DESC.size()]), itemValues);
- _messageList.put(messageData);
- }
- }
- catch (AMQException e)
- {
- JMException jme = new JMException("Error creating message contents: " + e);
- jme.initCause(e);
- throw jme;
- }
-
- return _messageList;
- }
-
- private String[] getMessageHeaderProperties(ContentHeaderBody headerBody)
- {
- List<String> list = new ArrayList<String>();
- BasicContentHeaderProperties headerProperties = (BasicContentHeaderProperties) headerBody.getProperties();
- list.add("reply-to = " + headerProperties.getReplyToAsString());
- list.add("propertyFlags = " + headerProperties.getPropertyFlags());
- list.add("ApplicationID = " + headerProperties.getAppIdAsString());
- list.add("ClusterID = " + headerProperties.getClusterIdAsString());
- list.add("UserId = " + headerProperties.getUserIdAsString());
- list.add("JMSMessageID = " + headerProperties.getMessageIdAsString());
- list.add("JMSCorrelationID = " + headerProperties.getCorrelationIdAsString());
-
- int delMode = headerProperties.getDeliveryMode();
- list.add("JMSDeliveryMode = " +
- ((delMode == BasicContentHeaderProperties.PERSISTENT) ? "Persistent" : "Non_Persistent"));
-
- list.add("JMSPriority = " + headerProperties.getPriority());
- list.add("JMSType = " + headerProperties.getType());
-
- final long expirationDate = headerProperties.getExpiration();
- final long timestampDate = headerProperties.getTimestamp();
-
- addStringifiedJMSTimestamoAndJMSExpiration(list, expirationDate,
- timestampDate);
-
- return list.toArray(new String[list.size()]);
- }
-
- private String[] getMessageTransferMessageHeaderProps(MessageTransferMessage msg)
- {
- List<String> list = new ArrayList<String>();
-
- AMQMessageHeader header = msg.getMessageHeader();
- MessageProperties msgProps = msg.getHeader().getMessageProperties();
-
- String appID = null;
- String userID = null;
-
- if(msgProps != null)
- {
- appID = msgProps.getAppId() == null ? "null" : new String(msgProps.getAppId());
- userID = msgProps.getUserId() == null ? "null" : new String(msgProps.getUserId());
- }
-
- list.add("reply-to = " + header.getReplyTo());
- list.add("propertyFlags = "); //TODO
- list.add("ApplicationID = " + appID);
- list.add("ClusterID = "); //TODO
- list.add("UserId = " + userID);
- list.add("JMSMessageID = " + header.getMessageId());
- list.add("JMSCorrelationID = " + header.getCorrelationId());
- list.add("JMSDeliveryMode = " + (msg.isPersistent() ? "Persistent" : "Non_Persistent"));
- list.add("JMSPriority = " + header.getPriority());
- list.add("JMSType = " + header.getType());
-
- final long expirationDate = header.getExpiration();
- final long timestampDate = header.getTimestamp();
- addStringifiedJMSTimestamoAndJMSExpiration(list, expirationDate, timestampDate);
-
- return list.toArray(new String[list.size()]);
- }
-
- private void addStringifiedJMSTimestamoAndJMSExpiration(final List<String> list,
- final long expirationDate, final long timestampDate)
- {
- final String formattedExpirationDate = (expirationDate != 0) ? FAST_DATE_FORMAT.format(expirationDate) : null;
- final String formattedTimestampDate = (timestampDate != 0) ? FAST_DATE_FORMAT.format(timestampDate) : null;
- list.add("JMSExpiration = " + formattedExpirationDate);
- list.add("JMSTimestamp = " + formattedTimestampDate);
- }
-
- /**
- * @see ManagedQueue#moveMessages
- * @param fromMessageId
- * @param toMessageId
- * @param toQueueName
- * @throws JMException
- */
- public void moveMessages(long fromMessageId, long toMessageId, String toQueueName) throws JMException
- {
- if ((fromMessageId > toMessageId) || (fromMessageId < 1))
- {
- throw new OperationsException("\"From MessageId\" should be greater than 0 and less than \"To MessageId\"");
- }
-
- _queue.moveMessagesToAnotherQueue(fromMessageId, toMessageId, toQueueName);
- }
-
- /**
- * @see ManagedQueue#deleteMessages
- * @param fromMessageId
- * @param toMessageId
- * @throws JMException
- */
- public void deleteMessages(long fromMessageId, long toMessageId) throws JMException
- {
- if ((fromMessageId > toMessageId) || (fromMessageId < 1))
- {
- throw new OperationsException("\"From MessageId\" should be greater than 0 and less than \"To MessageId\"");
- }
-
- _queue.removeMessagesFromQueue(fromMessageId, toMessageId);
- }
-
- /**
- * @see ManagedQueue#copyMessages
- * @param fromMessageId
- * @param toMessageId
- * @param toQueueName
- * @throws JMException
- */
- public void copyMessages(long fromMessageId, long toMessageId, String toQueueName) throws JMException
- {
- if ((fromMessageId > toMessageId) || (fromMessageId < 1))
- {
- throw new OperationsException("\"From MessageId\" should be greater than 0 and less than \"To MessageId\"");
- }
-
- _queue.copyMessagesToAnotherQueue(fromMessageId, toMessageId, toQueueName);
- }
-
- /**
- * returns Notifications sent by this MBean.
- */
- @Override
- public MBeanNotificationInfo[] getNotificationInfo()
- {
- String[] notificationTypes = new String[] { MonitorNotification.THRESHOLD_VALUE_EXCEEDED };
- String name = MonitorNotification.class.getName();
- String description = "Either Message count or Queue depth or Message size has reached threshold high value";
- MBeanNotificationInfo info1 = new MBeanNotificationInfo(notificationTypes, name, description);
-
- return new MBeanNotificationInfo[] { info1 };
- }
-
-} // End of AMQQueueMBean class
diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/ConflationQueueList.java b/java/broker/src/main/java/org/apache/qpid/server/queue/ConflationQueueList.java
index 6a2e4f155d..53420ded9b 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/queue/ConflationQueueList.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/queue/ConflationQueueList.java
@@ -24,17 +24,25 @@ package org.apache.qpid.server.queue;
import org.apache.qpid.server.message.ServerMessage;
import org.apache.qpid.server.txn.AutoCommitTransaction;
import org.apache.qpid.server.txn.ServerTransaction;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import java.util.Collections;
+import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicReference;
public class ConflationQueueList extends SimpleQueueEntryList
{
+ private static final Logger LOGGER = LoggerFactory.getLogger(ConflationQueueList.class);
private final String _conflationKey;
private final ConcurrentHashMap<Object, AtomicReference<QueueEntry>> _latestValuesMap =
new ConcurrentHashMap<Object, AtomicReference<QueueEntry>>();
+ private final QueueEntry _deleteInProgress = new SimpleQueueEntryImpl(this);
+ private final QueueEntry _newerEntryAlreadyBeenAndGone = new SimpleQueueEntryImpl(this);
+
public ConflationQueueList(AMQQueue queue, String conflationKey)
{
super(queue);
@@ -52,48 +60,98 @@ public class ConflationQueueList extends SimpleQueueEntryList
return new ConflationQueueEntry(this, message);
}
-
+ /**
+ * Updates the list using super.add and also updates {@link #_latestValuesMap} and discards entries as necessary.
+ */
@Override
public ConflationQueueEntry add(final ServerMessage message)
{
- ConflationQueueEntry entry = (ConflationQueueEntry) (super.add(message));
- AtomicReference<QueueEntry> latestValueReference = null;
+ final ConflationQueueEntry addedEntry = (ConflationQueueEntry) (super.add(message));
- Object value = message.getMessageHeader().getHeader(_conflationKey);
- if(value != null)
+ final Object keyValue = message.getMessageHeader().getHeader(_conflationKey);
+ if (keyValue != null)
{
- latestValueReference = _latestValuesMap.get(value);
- if(latestValueReference == null)
+ if(LOGGER.isDebugEnabled())
{
- _latestValuesMap.putIfAbsent(value, new AtomicReference<QueueEntry>(entry));
- latestValueReference = _latestValuesMap.get(value);
+ LOGGER.debug("Adding entry " + addedEntry + " for message " + message.getMessageNumber() + " with conflation key " + keyValue);
}
- QueueEntry oldEntry;
+ final AtomicReference<QueueEntry> referenceToEntry = new AtomicReference<QueueEntry>(addedEntry);
+ AtomicReference<QueueEntry> entryReferenceFromMap = null;
+ QueueEntry entryFromMap;
+
+ // Iterate until we have got a valid atomic reference object and either the referent is newer than the current
+ // entry, or the current entry has replaced it in the reference. Note that the _deletedEntryPlaceholder is a special value
+ // indicating that the reference object is no longer valid (it is being removed from the map).
+ boolean keepTryingToUpdateEntryReference = true;
do
{
- oldEntry = latestValueReference.get();
+ do
+ {
+ entryReferenceFromMap = getOrPutIfAbsent(keyValue, referenceToEntry);
+
+ // entryFromMap can be either an older entry, a newer entry (added recently by another thread), or addedEntry (if it's for a new key value)
+ entryFromMap = entryReferenceFromMap.get();
+ }
+ while(entryFromMap == _deleteInProgress);
+
+ boolean entryFromMapIsOlder = entryFromMap != _newerEntryAlreadyBeenAndGone && entryFromMap.compareTo(addedEntry) < 0;
+
+ keepTryingToUpdateEntryReference = entryFromMapIsOlder
+ && !entryReferenceFromMap.compareAndSet(entryFromMap, addedEntry);
}
- while(oldEntry.compareTo(entry) < 0 && !latestValueReference.compareAndSet(oldEntry, entry));
+ while(keepTryingToUpdateEntryReference);
- if(oldEntry.compareTo(entry) < 0)
+ if (entryFromMap == _newerEntryAlreadyBeenAndGone)
+ {
+ discardEntry(addedEntry);
+ }
+ else if (entryFromMap.compareTo(addedEntry) > 0)
{
- // We replaced some other entry to become the newest value
- if(oldEntry.acquire())
+ if(LOGGER.isDebugEnabled())
{
- discardEntry(oldEntry);
+ LOGGER.debug("New entry " + addedEntry.getEntryId() + " for message " + addedEntry.getMessage().getMessageNumber() + " being immediately discarded because a newer entry arrived. The newer entry is: " + entryFromMap + " for message " + entryFromMap.getMessage().getMessageNumber());
}
+ discardEntry(addedEntry);
}
- else if (oldEntry.compareTo(entry) > 0)
+ else if (entryFromMap.compareTo(addedEntry) < 0)
{
- // A newer entry came along
- discardEntry(entry);
-
+ if(LOGGER.isDebugEnabled())
+ {
+ LOGGER.debug("Entry " + addedEntry + " for message " + addedEntry.getMessage().getMessageNumber() + " replacing older entry " + entryFromMap + " for message " + entryFromMap.getMessage().getMessageNumber());
+ }
+ discardEntry(entryFromMap);
}
+
+ addedEntry.setLatestValueReference(entryReferenceFromMap);
}
- entry.setLatestValueReference(latestValueReference);
- return entry;
+ return addedEntry;
+ }
+
+ /**
+ * Returns:
+ *
+ * <ul>
+ * <li>the existing entry reference if the value already exists in the map, or</li>
+ * <li>referenceToValue if none exists, or</li>
+ * <li>a reference to {@link #_newerEntryAlreadyBeenAndGone} if another thread concurrently
+ * adds and removes during execution of this method.</li>
+ * </ul>
+ */
+ private AtomicReference<QueueEntry> getOrPutIfAbsent(final Object key, final AtomicReference<QueueEntry> referenceToAddedValue)
+ {
+ AtomicReference<QueueEntry> latestValueReference = _latestValuesMap.putIfAbsent(key, referenceToAddedValue);
+
+ if(latestValueReference == null)
+ {
+ latestValueReference = _latestValuesMap.get(key);
+ if(latestValueReference == null)
+ {
+ return new AtomicReference<QueueEntry>(_newerEntryAlreadyBeenAndGone);
+ }
+ }
+ return latestValueReference;
}
private void discardEntry(final QueueEntry entry)
@@ -104,11 +162,13 @@ public class ConflationQueueList extends SimpleQueueEntryList
txn.dequeue(entry.getQueue(),entry.getMessage(),
new ServerTransaction.Action()
{
+ @Override
public void postCommit()
{
entry.discard();
}
+ @Override
public void onRollback()
{
@@ -120,7 +180,6 @@ public class ConflationQueueList extends SimpleQueueEntryList
private final class ConflationQueueEntry extends SimpleQueueEntryImpl
{
-
private AtomicReference<QueueEntry> _latestValueReference;
public ConflationQueueEntry(SimpleQueueEntryList queueEntryList, ServerMessage message)
@@ -128,25 +187,56 @@ public class ConflationQueueList extends SimpleQueueEntryList
super(queueEntryList, message);
}
-
+ @Override
public void release()
{
super.release();
- if(_latestValueReference != null)
+ discardIfReleasedEntryIsNoLongerLatest();
+ }
+
+ @Override
+ public boolean delete()
+ {
+ if(super.delete())
{
- if(_latestValueReference.get() != this)
+ if(_latestValueReference != null && _latestValueReference.compareAndSet(this, _deleteInProgress))
{
- discardEntry(this);
+ Object key = getMessageHeader().getHeader(_conflationKey);
+ _latestValuesMap.remove(key,_latestValueReference);
}
+ return true;
+ }
+ else
+ {
+ return false;
}
-
}
public void setLatestValueReference(final AtomicReference<QueueEntry> latestValueReference)
{
_latestValueReference = latestValueReference;
}
+
+ private void discardIfReleasedEntryIsNoLongerLatest()
+ {
+ if(_latestValueReference != null)
+ {
+ if(_latestValueReference.get() != this)
+ {
+ discardEntry(this);
+ }
+ }
+ }
+
+ }
+
+ /**
+ * Exposed purposes of unit test only.
+ */
+ Map<Object, AtomicReference<QueueEntry>> getLatestValuesMap()
+ {
+ return Collections.unmodifiableMap(_latestValuesMap);
}
static class Factory implements QueueEntryListFactory
@@ -163,5 +253,4 @@ public class ConflationQueueList extends SimpleQueueEntryList
return new ConflationQueueList(queue, _conflationKey);
}
}
-
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/DefaultQueueRegistry.java b/java/broker/src/main/java/org/apache/qpid/server/queue/DefaultQueueRegistry.java
index 2493974d45..27a9e13617 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/queue/DefaultQueueRegistry.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/queue/DefaultQueueRegistry.java
@@ -20,12 +20,10 @@
*/
package org.apache.qpid.server.queue;
-import org.apache.log4j.Logger;
-import org.apache.qpid.AMQException;
import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpid.server.exchange.DefaultExchangeRegistry;
import org.apache.qpid.server.virtualhost.VirtualHost;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
@@ -33,11 +31,11 @@ import java.util.concurrent.ConcurrentMap;
public class DefaultQueueRegistry implements QueueRegistry
{
- private static final Logger LOGGER = Logger.getLogger(DefaultExchangeRegistry.class);
-
private ConcurrentMap<AMQShortString, AMQQueue> _queueMap = new ConcurrentHashMap<AMQShortString, AMQQueue>();
private final VirtualHost _virtualHost;
+ private final Collection<RegistryChangeListener> _listeners =
+ new ArrayList<RegistryChangeListener>();
public DefaultQueueRegistry(VirtualHost virtualHost)
{
@@ -52,11 +50,28 @@ public class DefaultQueueRegistry implements QueueRegistry
public void registerQueue(AMQQueue queue)
{
_queueMap.put(queue.getNameShortString(), queue);
+ synchronized (_listeners)
+ {
+ for(RegistryChangeListener listener : _listeners)
+ {
+ listener.queueRegistered(queue);
+ }
+ }
}
public void unregisterQueue(AMQShortString name)
{
- _queueMap.remove(name);
+ AMQQueue q = _queueMap.remove(name);
+ if(q != null)
+ {
+ synchronized (_listeners)
+ {
+ for(RegistryChangeListener listener : _listeners)
+ {
+ listener.queueUnregistered(q);
+ }
+ }
+ }
}
public AMQQueue getQueue(AMQShortString name)
@@ -79,19 +94,30 @@ public class DefaultQueueRegistry implements QueueRegistry
return getQueue(new AMQShortString(queue));
}
+ public void addRegistryChangeListener(RegistryChangeListener listener)
+ {
+ synchronized(_listeners)
+ {
+ _listeners.add(listener);
+ }
+ }
+
@Override
public void stopAllAndUnregisterMBeans()
{
for (final AMQQueue queue : getQueues())
{
queue.stop();
- try
- {
- queue.getManagedObject().unregister();
- }
- catch (AMQException e)
+
+ //TODO: this is a bit of a hack, what if the listeners aren't aware
+ //that we are just unregistering the MBean because of HA, and aren't
+ //actually removing the queue as such.
+ synchronized (_listeners)
{
- LOGGER.warn("Failed to unregister mbean", e);
+ for(RegistryChangeListener listener : _listeners)
+ {
+ listener.queueUnregistered(queue);
+ }
}
}
_queueMap.clear();
diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/NotificationCheck.java b/java/broker/src/main/java/org/apache/qpid/server/queue/NotificationCheck.java
index c1ebbe412f..3efef9ab98 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/queue/NotificationCheck.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/queue/NotificationCheck.java
@@ -20,6 +20,7 @@
*/
package org.apache.qpid.server.queue;
+import org.apache.log4j.Logger;
import org.apache.qpid.server.message.ServerMessage;
public enum NotificationCheck
@@ -27,13 +28,16 @@ public enum NotificationCheck
MESSAGE_COUNT_ALERT
{
- boolean notifyIfNecessary(ServerMessage msg, AMQQueue queue, QueueNotificationListener listener)
+ public boolean notifyIfNecessary(ServerMessage<?> msg, AMQQueue queue, AMQQueue.NotificationListener listener)
{
int msgCount;
final long maximumMessageCount = queue.getMaximumMessageCount();
if (maximumMessageCount!= 0 && (msgCount = queue.getMessageCount()) >= maximumMessageCount)
{
- listener.notifyClients(this, queue, msgCount + ": Maximum count on queue threshold ("+ maximumMessageCount +") breached.");
+ String notificationMsg = msgCount + ": Maximum count on queue threshold ("+ maximumMessageCount +") breached.";
+
+ logNotification(this, queue, notificationMsg);
+ listener.notifyClients(this, queue, notificationMsg);
return true;
}
return false;
@@ -41,7 +45,7 @@ public enum NotificationCheck
},
MESSAGE_SIZE_ALERT(true)
{
- boolean notifyIfNecessary(ServerMessage msg, AMQQueue queue, QueueNotificationListener listener)
+ public boolean notifyIfNecessary(ServerMessage<?> msg, AMQQueue queue, AMQQueue.NotificationListener listener)
{
final long maximumMessageSize = queue.getMaximumMessageSize();
if(maximumMessageSize != 0)
@@ -50,10 +54,12 @@ public enum NotificationCheck
long messageSize;
messageSize = (msg == null) ? 0 : msg.getSize();
-
if (messageSize >= maximumMessageSize)
{
- listener.notifyClients(this, queue, messageSize + "b : Maximum message size threshold ("+ maximumMessageSize +") breached. [Message ID=" + msg.getMessageNumber() + "]");
+ String notificationMsg = messageSize + "b : Maximum message size threshold ("+ maximumMessageSize +") breached. [Message ID=" + msg.getMessageNumber() + "]";
+
+ logNotification(this, queue, notificationMsg);
+ listener.notifyClients(this, queue, notificationMsg);
return true;
}
}
@@ -63,7 +69,7 @@ public enum NotificationCheck
},
QUEUE_DEPTH_ALERT
{
- boolean notifyIfNecessary(ServerMessage msg, AMQQueue queue, QueueNotificationListener listener)
+ public boolean notifyIfNecessary(ServerMessage<?> msg, AMQQueue queue, AMQQueue.NotificationListener listener)
{
// Check for threshold queue depth in bytes
final long maximumQueueDepth = queue.getMaximumQueueDepth();
@@ -74,7 +80,10 @@ public enum NotificationCheck
if (queueDepth >= maximumQueueDepth)
{
- listener.notifyClients(this, queue, (queueDepth>>10) + "Kb : Maximum queue depth threshold ("+(maximumQueueDepth>>10)+"Kb) breached.");
+ String notificationMsg = (queueDepth>>10) + "Kb : Maximum queue depth threshold ("+(maximumQueueDepth>>10)+"Kb) breached.";
+
+ logNotification(this, queue, notificationMsg);
+ listener.notifyClients(this, queue, notificationMsg);
return true;
}
}
@@ -84,7 +93,7 @@ public enum NotificationCheck
},
MESSAGE_AGE_ALERT
{
- boolean notifyIfNecessary(ServerMessage msg, AMQQueue queue, QueueNotificationListener listener)
+ public boolean notifyIfNecessary(ServerMessage<?> msg, AMQQueue queue, AMQQueue.NotificationListener listener)
{
final long maxMessageAge = queue.getMaximumMessageAge();
@@ -97,7 +106,10 @@ public enum NotificationCheck
if(firstArrivalTime < thresholdTime)
{
long oldestAge = currentTime - firstArrivalTime;
- listener.notifyClients(this, queue, (oldestAge/1000) + "s : Maximum age on queue threshold ("+(maxMessageAge /1000)+"s) breached.");
+ String notificationMsg = (oldestAge/1000) + "s : Maximum age on queue threshold ("+(maxMessageAge /1000)+"s) breached.";
+
+ logNotification(this, queue, notificationMsg);
+ listener.notifyClients(this, queue, notificationMsg);
return true;
}
@@ -109,6 +121,8 @@ public enum NotificationCheck
}
;
+ private static final Logger LOGGER = Logger.getLogger(NotificationCheck.class);
+
private final boolean _messageSpecific;
NotificationCheck()
@@ -126,6 +140,11 @@ public enum NotificationCheck
return _messageSpecific;
}
- abstract boolean notifyIfNecessary(ServerMessage msg, AMQQueue queue, QueueNotificationListener listener);
+ public abstract boolean notifyIfNecessary(ServerMessage<?> msg, AMQQueue queue, AMQQueue.NotificationListener listener);
+ //A bit of a hack, only for use until we do the logging listener
+ private static void logNotification(NotificationCheck notification, AMQQueue queue, String notificationMsg)
+ {
+ LOGGER.info(notification.name() + " On Queue " + queue.getNameShortString() + " - " + notificationMsg);
+ }
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/PriorityQueueList.java b/java/broker/src/main/java/org/apache/qpid/server/queue/PriorityQueueList.java
index 1d13ee66c0..66315af9fb 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/queue/PriorityQueueList.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/queue/PriorityQueueList.java
@@ -37,7 +37,7 @@ public class PriorityQueueList implements QueueEntryList<SimpleQueueEntryImpl>
_priorityOffset = 5-((priorities + 1)/2);
for(int i = 0; i < priorities; i++)
{
- _priorityLists[i] = new PriorityQueueEntrySubList(queue);
+ _priorityLists[i] = new PriorityQueueEntrySubList(queue, i);
}
}
@@ -164,9 +164,12 @@ public class PriorityQueueList implements QueueEntryList<SimpleQueueEntryImpl>
private static class PriorityQueueEntrySubList extends SimpleQueueEntryList
{
- public PriorityQueueEntrySubList(AMQQueue queue)
+ private int _listPriority;
+
+ public PriorityQueueEntrySubList(AMQQueue queue, int listPriority)
{
super(queue);
+ _listPriority = listPriority;
}
@Override
@@ -174,6 +177,11 @@ public class PriorityQueueList implements QueueEntryList<SimpleQueueEntryImpl>
{
return new PriorityQueueEntryImpl(this, message);
}
+
+ public int getListPriority()
+ {
+ return _listPriority;
+ }
}
private static class PriorityQueueEntryImpl extends SimpleQueueEntryImpl
@@ -186,8 +194,9 @@ public class PriorityQueueList implements QueueEntryList<SimpleQueueEntryImpl>
@Override
public int compareTo(final QueueEntry o)
{
- byte thisPriority = getMessageHeader().getPriority();
- byte otherPriority = o.getMessageHeader().getPriority();
+ PriorityQueueEntrySubList pqel = (PriorityQueueEntrySubList)((PriorityQueueEntryImpl)o).getQueueEntryList();
+ int otherPriority = pqel.getListPriority();
+ int thisPriority = ((PriorityQueueEntrySubList) getQueueEntryList()).getListPriority();
if(thisPriority != otherPriority)
{
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 c33309b6d3..be2ab8b3ae 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
@@ -1,9 +1,3 @@
-package org.apache.qpid.server.queue;
-
-import org.apache.qpid.AMQException;
-import org.apache.qpid.server.message.ServerMessage;
-import org.apache.qpid.server.subscription.Subscription;
-
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
@@ -24,6 +18,12 @@ import org.apache.qpid.server.subscription.Subscription;
* under the License.
*
*/
+package org.apache.qpid.server.queue;
+
+import org.apache.qpid.AMQException;
+import org.apache.qpid.server.message.ServerMessage;
+import org.apache.qpid.server.subscription.Subscription;
+
public interface QueueEntry extends Comparable<QueueEntry>, Filterable
{
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 209553e8fa..25e771a9cf 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
@@ -233,7 +233,7 @@ public abstract class QueueEntryImpl implements QueueEntry
if(state instanceof SubscriptionAcquiredState)
{
- getQueue().decrementUnackedMsgCount();
+ getQueue().decrementUnackedMsgCount(this);
Subscription subscription = ((SubscriptionAcquiredState)state).getSubscription();
if (subscription != null)
{
@@ -369,7 +369,7 @@ public abstract class QueueEntryImpl implements QueueEntry
Subscription s = null;
if (state instanceof SubscriptionAcquiredState)
{
- getQueue().decrementUnackedMsgCount();
+ getQueue().decrementUnackedMsgCount(this);
s = ((SubscriptionAcquiredState) state).getSubscription();
s.onDequeue(this);
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntryVisitor.java b/java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntryVisitor.java
index 1578d21321..9ecaf6dafd 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntryVisitor.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntryVisitor.java
@@ -1,21 +1,21 @@
-package org.apache.qpid.server.queue;
-
-/**
+/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
-* <p/>
+*
* http://www.apache.org/licenses/LICENSE-2.0
-* <p/>
+*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF 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;
+
public interface QueueEntryVisitor
{
boolean visit(QueueEntry entry);
diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/QueueRegistry.java b/java/broker/src/main/java/org/apache/qpid/server/queue/QueueRegistry.java
index 72a54c9889..e8c34128e9 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/queue/QueueRegistry.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/queue/QueueRegistry.java
@@ -42,7 +42,15 @@ public interface QueueRegistry
AMQQueue getQueue(String queue);
+ void addRegistryChangeListener(RegistryChangeListener listener);
+
void stopAllAndUnregisterMBeans();
AMQQueue getQueue(UUID queueId);
+
+ interface RegistryChangeListener
+ {
+ void queueRegistered(AMQQueue queue);
+ void queueUnregistered(AMQQueue queue);
+ }
}
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 d7eb304c92..d42bd6cf03 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
@@ -19,8 +19,10 @@
package org.apache.qpid.server.queue;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.Collections;
import java.util.EnumSet;
+import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -28,12 +30,11 @@ import java.util.UUID;
import java.util.concurrent.ConcurrentSkipListSet;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.Executor;
+import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
-import javax.management.JMException;
-
import org.apache.log4j.Logger;
import org.apache.qpid.AMQException;
import org.apache.qpid.AMQSecurityException;
@@ -52,7 +53,6 @@ import org.apache.qpid.server.logging.actors.CurrentActor;
import org.apache.qpid.server.logging.actors.QueueActor;
import org.apache.qpid.server.logging.messages.QueueMessages;
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.protocol.AMQSessionModel;
import org.apache.qpid.server.registry.ApplicationRegistry;
@@ -70,6 +70,7 @@ import org.apache.qpid.server.virtualhost.VirtualHost;
public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, MessageGroupManager.SubscriptionResetHelper
{
private static final Logger _logger = Logger.getLogger(SimpleAMQQueue.class);
+
private static final String QPID_GROUP_HEADER_KEY = "qpid.group_header_key";
private static final String QPID_SHARED_MSG_GROUP = "qpid.shared_msg_group";
private static final String QPID_DEFAULT_MESSAGE_GROUP = "qpid.default-message-group";
@@ -77,11 +78,9 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
// TODO - should make this configurable at the vhost / broker level
private static final int DEFAULT_MAX_GROUPS = 255;
-
private final VirtualHost _virtualHost;
private final AMQShortString _name;
- private final String _resourceName;
/** null means shared */
private final AMQShortString _owner;
@@ -118,6 +117,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
private final AtomicLong _dequeueCount = new AtomicLong();
private final AtomicLong _dequeueSize = new AtomicLong();
+ private final AtomicLong _enqueueCount = new AtomicLong();
private final AtomicLong _enqueueSize = new AtomicLong();
private final AtomicLong _persistentMessageEnqueueSize = new AtomicLong();
private final AtomicLong _persistentMessageDequeueSize = new AtomicLong();
@@ -130,6 +130,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
private final AtomicLong _byteTxnDequeues = new AtomicLong(0);
private final AtomicLong _unackedMsgCount = new AtomicLong(0);
private final AtomicLong _unackedMsgCountHigh = new AtomicLong(0);
+ private final AtomicLong _unackedMsgBytes = new AtomicLong();
private final AtomicInteger _bindingCountHigh = new AtomicInteger();
@@ -173,7 +174,6 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
private LogSubject _logSubject;
private LogActor _logActor;
- private AMQQueueMBean _managedObject;
private static final String SUB_FLUSH_RUNNER = "SUB_FLUSH_RUNNER";
private boolean _nolocal;
@@ -185,12 +185,19 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
//TODO : persist creation time
private long _createTime = System.currentTimeMillis();
+ private UUID _qmfId;
private ConfigurationPlugin _queueConfiguration;
/** the maximum delivery count for each message on this queue or 0 if maximum delivery count is not to be enforced. */
private int _maximumDeliveryCount = ApplicationRegistry.getInstance().getConfiguration().getMaxDeliveryCount();
private final MessageGroupManager _messageGroupManager;
+ private final Collection<SubscriptionRegistrationListener> _subscriptionListeners =
+ new ArrayList<SubscriptionRegistrationListener>();
+
+ private AMQQueue.NotificationListener _notificationListener;
+ private final long[] _lastNotificationTimes = new long[NotificationCheck.values().length];
+
protected SimpleAMQQueue(UUID id, AMQShortString name, boolean durable, AMQShortString owner, boolean autoDelete, boolean exclusive, VirtualHost virtualHost, Map<String,Object> arguments)
{
this(id, name, durable, owner, autoDelete, exclusive,virtualHost, new SimpleQueueEntryList.Factory(), arguments);
@@ -227,17 +234,16 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
}
_name = name;
- _resourceName = String.valueOf(name);
_durable = durable;
_owner = owner;
_autoDelete = autoDelete;
_exclusive = exclusive;
_virtualHost = virtualHost;
_entries = entryListFactory.createQueueEntryList(this);
- _arguments = arguments;
+ _arguments = arguments == null ? new HashMap<String, Object>() : new HashMap<String, Object>(arguments);
_id = id;
-
+ _qmfId = getConfigStore().createId();
_asyncDelivery = ReferenceCountingExecutorService.getInstance().acquireExecutorService();
_logSubject = new QueueLogSubject(this);
@@ -255,16 +261,6 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
getConfigStore().addConfiguredObject(this);
- try
- {
- _managedObject = new AMQQueueMBean(this);
- _managedObject.register();
- }
- catch (JMException e)
- {
- _logger.error("AMQQueue MBean creation has failed ", e);
- }
-
if(arguments != null && arguments.containsKey(QPID_GROUP_HEADER_KEY))
{
if(arguments.containsKey(QPID_SHARED_MSG_GROUP) && String.valueOf(arguments.get(QPID_SHARED_MSG_GROUP)).equals("1"))
@@ -302,7 +298,22 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
public void execute(Runnable runnable)
{
- _asyncDelivery.execute(runnable);
+ try
+ {
+ _asyncDelivery.execute(runnable);
+ }
+ catch (RejectedExecutionException ree)
+ {
+ if (_stopped.get())
+ {
+ // Ignore - SubFlusherRunner or QueueRunner submitted execution as queue was being stopped.
+ }
+ else
+ {
+ _logger.error("Unexpected rejected execution", ree);
+ throw ree;
+ }
+ }
}
public AMQShortString getNameShortString()
@@ -320,6 +331,12 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
return _id;
}
+ @Override
+ public UUID getQMFId()
+ {
+ return _qmfId;
+ }
+
public QueueConfigType getConfigType()
{
return QueueConfigType.getInstance();
@@ -339,15 +356,10 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
{
return _exclusive;
}
-
- public void setExclusive(boolean exclusive) throws AMQException
+
+ public void setExclusive(boolean exclusive)
{
_exclusive = exclusive;
-
- if(isDurable())
- {
- getVirtualHost().getMessageStore().updateQueue(this);
- }
}
public Exchange getAlternateExchange()
@@ -368,22 +380,10 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
_alternateExchange = exchange;
}
- public void setAlternateExchange(String exchangeName)
- {
- if(exchangeName == null || exchangeName.equals(""))
- {
- _alternateExchange = null;
- return;
- }
-
- Exchange exchange = getVirtualHost().getExchangeRegistry().getExchange(new AMQShortString(exchangeName));
- if (exchange == null)
- {
- throw new RuntimeException("Exchange '" + exchangeName + "' is not registered with the VirtualHost.");
- }
- setAlternateExchange(exchange);
- }
-
+ /**
+ * Arguments used to create this queue. The caller is assured
+ * that null will never be returned.
+ */
public Map<String, Object> getArguments()
{
return _arguments;
@@ -430,8 +430,8 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
{
throw new AMQSecurityException("Permission denied");
}
-
-
+
+
if (hasExclusiveSubscriber())
{
throw new ExistingExclusiveSubscription();
@@ -463,15 +463,24 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
{
subscription.setNoLocal(_nolocal);
}
+
+ synchronized (_subscriptionListeners)
+ {
+ for(SubscriptionRegistrationListener listener : _subscriptionListeners)
+ {
+ listener.subscriptionRegistered(this, subscription);
+ }
+ }
+
_subscriptionList.add(subscription);
-
+
//Increment consumerCountHigh if necessary. (un)registerSubscription are both
//synchronized methods so we don't need additional synchronization here
if(_counsumerCountHigh.get() < getConsumerCount())
{
_counsumerCountHigh.incrementAndGet();
}
-
+
if (isDeleted())
{
subscription.queueDeleted(this);
@@ -507,6 +516,14 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
resetSubPointersForGroups(subscription, true);
}
+ synchronized (_subscriptionListeners)
+ {
+ for(SubscriptionRegistrationListener listener : _subscriptionListeners)
+ {
+ listener.subscriptionUnregistered(this, subscription);
+ }
+ }
+
// auto-delete queues must be deleted if there are no remaining subscribers
if (_autoDelete && getDeleteOnNoConsumers() && !subscription.isTransient() && getConsumerCount() == 0 )
@@ -526,6 +543,34 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
}
+ public Collection<Subscription> getConsumers()
+ {
+ List<Subscription> consumers = new ArrayList<Subscription>();
+ SubscriptionList.SubscriptionNodeIterator iter = _subscriptionList.iterator();
+ while(iter.advance())
+ {
+ consumers.add(iter.getNode().getSubscription());
+ }
+ return consumers;
+
+ }
+
+ public void addSubscriptionRegistrationListener(final SubscriptionRegistrationListener listener)
+ {
+ synchronized (_subscriptionListeners)
+ {
+ _subscriptionListeners.add(listener);
+ }
+ }
+
+ public void removeSubscriptionRegistrationListener(final SubscriptionRegistrationListener listener)
+ {
+ synchronized (_subscriptionListeners)
+ {
+ _subscriptionListeners.remove(listener);
+ }
+ }
+
public void resetSubPointersForGroups(Subscription subscription, boolean clearAssignments)
{
QueueEntry entry = _messageGroupManager.findEarliestAssignedAvailableEntry(subscription);
@@ -576,10 +621,10 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
break;
}
}
-
+
reconfigure();
}
-
+
private void reconfigure()
{
//Reconfigure the queue for to reflect this new binding.
@@ -604,7 +649,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
public void removeBinding(final Binding binding)
{
_bindings.remove(binding);
-
+
reconfigure();
}
@@ -718,10 +763,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
}
}
- if(_managedObject != null)
- {
- _managedObject.checkForNotification(entry.getMessage());
- }
+ checkForNotification(entry.getMessage());
if(action != null)
{
@@ -738,8 +780,8 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
{
try
{
- if (!sub.isSuspended()
- && subscriptionReadyAndHasInterest(sub, entry)
+ if (!sub.isSuspended()
+ && subscriptionReadyAndHasInterest(sub, entry)
&& mightAssign(sub, entry)
&& !sub.wouldSuspend(entry))
{
@@ -788,6 +830,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
{
long size = message.getSize();
getAtomicQueueSize().addAndGet(size);
+ _enqueueCount.incrementAndGet();
_enqueueSize.addAndGet(size);
if(message.isPersistent() && isDurable())
{
@@ -796,19 +839,29 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
}
}
+ public long getTotalDequeueCount()
+ {
+ return _dequeueCount.get();
+ }
+
+ public long getTotalEnqueueCount()
+ {
+ return _enqueueCount.get();
+ }
+
private void incrementQueueCount()
{
getAtomicQueueCount().incrementAndGet();
}
-
+
private void incrementTxnEnqueueStats(final ServerMessage message)
{
_msgTxnEnqueues.incrementAndGet();
_byteTxnEnqueues.addAndGet(message.getSize());
}
-
+
private void incrementTxnDequeueStats(QueueEntry entry)
- {
+ {
_msgTxnDequeues.incrementAndGet();
_byteTxnDequeues.addAndGet(entry.getSize());
}
@@ -819,7 +872,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
setLastSeenEntry(sub, entry);
_deliveredMessages.incrementAndGet();
- incrementUnackedMsgCount();
+ incrementUnackedMsgCount(entry);
sub.send(entry, batch);
}
@@ -833,12 +886,15 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
private void setLastSeenEntry(final Subscription sub, final QueueEntry entry)
{
QueueContext subContext = (QueueContext) sub.getQueueContext();
- QueueEntry releasedEntry = subContext.getReleasedEntry();
-
- QueueContext._lastSeenUpdater.set(subContext, entry);
- if(releasedEntry == entry)
+ if (subContext != null)
{
- QueueContext._releasedUpdater.compareAndSet(subContext, releasedEntry, null);
+ QueueEntry releasedEntry = subContext.getReleasedEntry();
+
+ QueueContext._lastSeenUpdater.set(subContext, entry);
+ if(releasedEntry == entry)
+ {
+ QueueContext._releasedUpdater.compareAndSet(subContext, releasedEntry, null);
+ }
}
}
@@ -887,7 +943,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
{
_deliveredMessages.decrementAndGet();
}
-
+
if(sub != null && sub.isSessionTransactional())
{
incrementTxnDequeueStats(entry);
@@ -940,11 +996,13 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
}
}
+
+
public int getConsumerCount()
{
return _subscriptionList.size();
}
-
+
public int getConsumerCountHigh()
{
return _counsumerCountHigh.get();
@@ -1148,7 +1206,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
}
- public void visit(final Visitor visitor)
+ public void visit(final QueueEntryVisitor visitor)
{
QueueEntryIterator queueListIterator = _entries.iterator();
@@ -1195,192 +1253,6 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
}
- public void moveMessagesToAnotherQueue(final long fromMessageId,
- final long toMessageId,
- String destinationQueueName) throws IllegalArgumentException
- {
-
- final AMQQueue toQueue = getValidatedDestinationQueue(destinationQueueName);
-
- List<QueueEntry> entries = getMessagesOnTheQueue(new QueueEntryFilter()
- {
-
- public boolean accept(QueueEntry entry)
- {
- final long messageId = entry.getMessage().getMessageNumber();
- return (messageId >= fromMessageId)
- && (messageId <= toMessageId)
- && entry.acquire();
- }
-
- public boolean filterComplete()
- {
- return false;
- }
- });
-
-
- final ServerTransaction txn = new LocalTransaction(getVirtualHost().getMessageStore());
- boolean shouldRollback = true;
- try
- {
- // Move the messages in on the message store.
- for (final QueueEntry entry : entries)
- {
- final ServerMessage message = entry.getMessage();
- txn.enqueue(toQueue, message,
- new ServerTransaction.Action()
- {
-
- public void postCommit()
- {
- try
- {
- toQueue.enqueue(message);
- }
- catch (AMQException e)
- {
- throw new RuntimeException(e);
- }
- }
-
- public void onRollback()
- {
- entry.release();
- }
- });
- txn.dequeue(this, message,
- new ServerTransaction.Action()
- {
-
- public void postCommit()
- {
- entry.discard();
- }
-
- public void onRollback()
- {
-
- }
- });
- }
- txn.commit();
- shouldRollback = false;
- }
- finally
- {
- if (shouldRollback)
- {
- txn.rollback();
- }
- }
-
- }
-
- public void copyMessagesToAnotherQueue(final long fromMessageId,
- final long toMessageId,
- String destinationQueueName) throws IllegalArgumentException
- {
- final AMQQueue toQueue = getValidatedDestinationQueue(destinationQueueName);
-
- List<QueueEntry> entries = getMessagesOnTheQueue(new QueueEntryFilter()
- {
-
- public boolean accept(QueueEntry entry)
- {
- final long messageId = entry.getMessage().getMessageNumber();
- return ((messageId >= fromMessageId)
- && (messageId <= toMessageId));
- }
-
- public boolean filterComplete()
- {
- return false;
- }
- });
-
- final ServerTransaction txn = new LocalTransaction(_virtualHost.getMessageStore());
- boolean shouldRollback = true;
- try
- {
- // Copy the messages in on the message store.
- for (QueueEntry entry : entries)
- {
- final ServerMessage message = entry.getMessage();
-
- txn.enqueue(toQueue, message, new ServerTransaction.Action()
- {
- public void postCommit()
- {
- try
- {
- toQueue.enqueue(message);
- }
- catch (AMQException e)
- {
- throw new RuntimeException(e);
- }
- }
-
- public void onRollback()
- {
- }
- });
-
- }
-
- txn.commit();
- shouldRollback = false;
- }
- finally
- {
- if (shouldRollback)
- {
- txn.rollback();
- }
- }
-
- }
-
- private AMQQueue getValidatedDestinationQueue(String queueName)
- {
- final AMQQueue toQueue = getVirtualHost().getQueueRegistry().getQueue(new AMQShortString(queueName));
- if (toQueue == null)
- {
- throw new IllegalArgumentException("Queue '" + queueName + "' is not registered with the virtualhost.");
- }
- else if (toQueue == this)
- {
- throw new IllegalArgumentException("The destination queue can't be the same as the source queue");
- }
- return toQueue;
- }
-
- public void removeMessagesFromQueue(long fromMessageId, long toMessageId)
- {
-
- QueueEntryIterator queueListIterator = _entries.iterator();
-
- while (queueListIterator.advance())
- {
- QueueEntry node = queueListIterator.getNode();
-
- final ServerMessage message = node.getMessage();
- if(message != null)
- {
- final long messageId = message.getMessageNumber();
-
- if ((messageId >= fromMessageId)
- && (messageId <= toMessageId)
- && node.acquire())
- {
- dequeueEntry(node);
- }
- }
- }
-
- }
-
public void purge(final long request) throws AMQException
{
clear(request);
@@ -1393,6 +1265,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
// ------ Management functions
+ // TODO - now only used by the tests
public void deleteMessageFromTop()
{
QueueEntryIterator queueListIterator = _entries.iterator();
@@ -1411,7 +1284,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
}
public long clearQueue() throws AMQException
- {
+ {
return clear(0l);
}
@@ -1422,7 +1295,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
{
throw new AMQSecurityException("Permission denied: queue " + getName());
}
-
+
QueueEntryIterator queueListIterator = _entries.iterator();
long count = 0;
@@ -1489,7 +1362,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
{
throw new AMQSecurityException("Permission denied: " + getName());
}
-
+
if (!_deleted.getAndSet(true))
{
@@ -1617,12 +1490,6 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
txn.commit();
-
- if(_managedObject!=null)
- {
- _managedObject.unregister();
- }
-
for (Task task : _deleteTaskList)
{
task.doTask(this);
@@ -2101,16 +1968,13 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
}
else
{
- if (_managedObject != null)
+ // There is a chance that the node could be deleted by
+ // the time the check actually occurs. So verify we
+ // can actually get the message to perform the check.
+ ServerMessage msg = node.getMessage();
+ if (msg != null)
{
- // There is a chance that the node could be deleted by
- // the time the check actually occurs. So verify we
- // can actually get the message to perform the check.
- ServerMessage msg = node.getMessage();
- if (msg != null)
- {
- _managedObject.checkForNotification(msg);
- }
+ checkForNotification(msg);
}
}
}
@@ -2235,11 +2099,6 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
return _notificationChecks;
}
- public ManagedObject getManagedObject()
- {
- return _managedObject;
- }
-
private final class QueueEntryListener implements QueueEntry.StateChangeListener
{
@@ -2330,12 +2189,6 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
return _queueConfiguration;
}
- public String getResourceName()
- {
- return _resourceName;
- }
-
-
public ConfigStore getConfigStore()
{
return getVirtualHost().getConfigStore();
@@ -2355,22 +2208,22 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
{
return _dequeueSize.get();
}
-
+
public long getByteTxnEnqueues()
{
return _byteTxnEnqueues.get();
}
-
+
public long getByteTxnDequeues()
{
return _byteTxnDequeues.get();
}
-
+
public long getMsgTxnEnqueues()
{
return _msgTxnEnqueues.get();
}
-
+
public long getMsgTxnDequeues()
{
return _msgTxnDequeues.get();
@@ -2407,21 +2260,28 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
{
return _unackedMsgCountHigh.get();
}
-
+
public long getUnackedMessageCount()
{
return _unackedMsgCount.get();
}
-
- public void decrementUnackedMsgCount()
+
+ public long getUnackedMessageBytes()
+ {
+ return _unackedMsgBytes.get();
+ }
+
+ public void decrementUnackedMsgCount(QueueEntry queueEntry)
{
_unackedMsgCount.decrementAndGet();
+ _unackedMsgBytes.addAndGet(-queueEntry.getSize());
}
-
- private void incrementUnackedMsgCount()
+
+ private void incrementUnackedMsgCount(QueueEntry entry)
{
long unackedMsgCount = _unackedMsgCount.incrementAndGet();
-
+ _unackedMsgBytes.addAndGet(entry.getSize());
+
long unackedMsgCountHigh;
while(unackedMsgCount > (unackedMsgCountHigh = _unackedMsgCountHigh.get()))
{
@@ -2447,4 +2307,54 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
_maximumDeliveryCount = maximumDeliveryCount;
}
+ /**
+ * Checks if there is any notification to send to the listeners
+ */
+ private void checkForNotification(ServerMessage<?> msg) throws AMQException
+ {
+ final Set<NotificationCheck> notificationChecks = getNotificationChecks();
+ final AMQQueue.NotificationListener listener = _notificationListener;
+
+ if(listener != null && !notificationChecks.isEmpty())
+ {
+ final long currentTime = System.currentTimeMillis();
+ final long thresholdTime = currentTime - getMinimumAlertRepeatGap();
+
+ for (NotificationCheck check : notificationChecks)
+ {
+ if (check.isMessageSpecific() || (_lastNotificationTimes[check.ordinal()] < thresholdTime))
+ {
+ if (check.notifyIfNecessary(msg, this, listener))
+ {
+ _lastNotificationTimes[check.ordinal()] = currentTime;
+ }
+ }
+ }
+ }
+ }
+
+ public void setNotificationListener(AMQQueue.NotificationListener listener)
+ {
+ _notificationListener = listener;
+ }
+
+ @Override
+ public void setDescription(String description)
+ {
+ if (description == null)
+ {
+ _arguments.remove(AMQQueueFactory.X_QPID_DESCRIPTION);
+ }
+ else
+ {
+ _arguments.put(AMQQueueFactory.X_QPID_DESCRIPTION, description);
+ }
+ }
+
+ @Override
+ public String getDescription()
+ {
+ return (String) _arguments.get(AMQQueueFactory.X_QPID_DESCRIPTION);
+ }
+
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/SubFlushRunner.java b/java/broker/src/main/java/org/apache/qpid/server/queue/SubFlushRunner.java
index 8f3b7ae4ce..47a7d733dd 100755
--- a/java/broker/src/main/java/org/apache/qpid/server/queue/SubFlushRunner.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/queue/SubFlushRunner.java
@@ -1,4 +1,3 @@
-package org.apache.qpid.server.queue;
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
@@ -19,6 +18,7 @@ package org.apache.qpid.server.queue;
* under the License.
*
*/
+package org.apache.qpid.server.queue;
import org.apache.log4j.Logger;
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 4ed28b965d..e0e317f75d 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
@@ -22,9 +22,9 @@ package org.apache.qpid.server.registry;
import org.apache.commons.configuration.ConfigurationException;
import org.apache.log4j.Logger;
+import org.apache.qpid.server.logging.*;
import org.osgi.framework.BundleContext;
-import org.apache.qpid.AMQException;
import org.apache.qpid.common.Closeable;
import org.apache.qpid.common.QpidProperties;
import org.apache.qpid.qmf.QMFService;
@@ -35,24 +35,18 @@ import org.apache.qpid.server.configuration.ServerConfiguration;
import org.apache.qpid.server.configuration.SystemConfig;
import org.apache.qpid.server.configuration.SystemConfigImpl;
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.LogActor;
-import org.apache.qpid.server.logging.RootMessageLogger;
-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.model.Broker;
+import org.apache.qpid.server.model.adapter.BrokerAdapter;
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.manager.AuthenticationManager;
-import org.apache.qpid.server.security.auth.manager.AuthenticationManagerPluginFactory;
+import org.apache.qpid.server.security.auth.manager.AuthenticationManagerRegistry;
+import org.apache.qpid.server.security.auth.manager.IAuthenticationManagerRegistry;
import org.apache.qpid.server.stats.StatisticsCounter;
import org.apache.qpid.server.transport.QpidAcceptor;
import org.apache.qpid.server.virtualhost.VirtualHost;
@@ -60,13 +54,8 @@ import org.apache.qpid.server.virtualhost.VirtualHostImpl;
import org.apache.qpid.server.virtualhost.VirtualHostRegistry;
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.net.SocketAddress;
+import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
@@ -78,19 +67,19 @@ import java.util.concurrent.atomic.AtomicReference;
*/
public abstract class ApplicationRegistry implements IApplicationRegistry
{
+
private static final Logger _logger = Logger.getLogger(ApplicationRegistry.class);
private static AtomicReference<IApplicationRegistry> _instance = new AtomicReference<IApplicationRegistry>(null);
private final ServerConfiguration _configuration;
- private final Map<InetSocketAddress, QpidAcceptor> _acceptors = new HashMap<InetSocketAddress, QpidAcceptor>();
-
- private ManagedObjectRegistry _managedObjectRegistry;
+ private final Map<InetSocketAddress, QpidAcceptor> _acceptors =
+ Collections.synchronizedMap(new HashMap<InetSocketAddress, QpidAcceptor>());
- private AuthenticationManager _authenticationManager;
+ private IAuthenticationManagerRegistry _authenticationManagerRegistry;
- private VirtualHostRegistry _virtualHostRegistry;
+ private final VirtualHostRegistry _virtualHostRegistry = new VirtualHostRegistry(this);
private SecurityManager _securityManager;
@@ -106,39 +95,32 @@ public abstract class ApplicationRegistry implements IApplicationRegistry
private QMFService _qmfService;
- private BrokerConfig _broker;
+ private BrokerConfig _brokerConfig;
+
+ private Broker _broker;
private ConfigStore _configStore;
-
+
private Timer _reportingTimer;
- private boolean _statisticsEnabled = false;
private StatisticsCounter _messagesDelivered, _dataDelivered, _messagesReceived, _dataReceived;
private BundleContext _bundleContext;
- protected static Logger get_logger()
- {
- return _logger;
- }
+ private final List<PortBindingListener> _portBindingListeners = new ArrayList<PortBindingListener>();
- protected Map<InetSocketAddress, QpidAcceptor> getAcceptors()
- {
- return _acceptors;
- }
+ private int _httpManagementPort = -1, _httpsManagementPort = -1;
- protected void setManagedObjectRegistry(ManagedObjectRegistry managedObjectRegistry)
- {
- _managedObjectRegistry = managedObjectRegistry;
- }
+ private LogRecorder _logRecorder;
- protected void setAuthenticationManager(AuthenticationManager authenticationManager)
- {
- _authenticationManager = authenticationManager;
- }
+ private List<IAuthenticationManagerRegistry.RegistryChangeListener> _authManagerChangeListeners =
+ new ArrayList<IAuthenticationManagerRegistry.RegistryChangeListener>();
- protected void setVirtualHostRegistry(VirtualHostRegistry virtualHostRegistry)
+ public Map<InetSocketAddress, QpidAcceptor> getAcceptors()
{
- _virtualHostRegistry = virtualHostRegistry;
+ synchronized (_acceptors)
+ {
+ return new HashMap<InetSocketAddress, QpidAcceptor>(_acceptors);
+ }
}
protected void setSecurityManager(SecurityManager securityManager)
@@ -205,11 +187,11 @@ public abstract class ApplicationRegistry implements IApplicationRegistry
store.setRoot(new SystemConfigImpl(store));
instance.setConfigStore(store);
- BrokerConfig broker = new BrokerConfigAdapter(instance);
+ final BrokerConfig brokerConfig = new BrokerConfigAdapter(instance);
- SystemConfig system = store.getRoot();
- system.addBroker(broker);
- instance.setBroker(broker);
+ final SystemConfig system = store.getRoot();
+ system.addBroker(brokerConfig);
+ instance.setBrokerConfig(brokerConfig);
try
{
@@ -222,7 +204,7 @@ public abstract class ApplicationRegistry implements IApplicationRegistry
//remove the Broker instance, then re-throw
try
{
- system.removeBroker(broker);
+ system.removeBroker(brokerConfig);
}
catch(Throwable t)
{
@@ -297,18 +279,32 @@ public abstract class ApplicationRegistry implements IApplicationRegistry
public void initialise() throws Exception
{
+ _logRecorder = new LogRecorder();
//Create the RootLogger to be used during broker operation
_rootMessageLogger = new Log4jMessageLogger(_configuration);
//Create the composite (log4j+SystemOut MessageLogger to be used during startup
RootMessageLogger[] messageLoggers = {new SystemOutMessageLogger(), _rootMessageLogger};
_startupMessageLogger = new CompositeStartupMessageLogger(messageLoggers);
-
- CurrentActor.set(new BrokerActor(_startupMessageLogger));
+
+ BrokerActor actor = new BrokerActor(_startupMessageLogger);
+ CurrentActor.setDefault(actor);
+ CurrentActor.set(actor);
try
{
- initialiseManagedObjectRegistry();
+ initialiseStatistics();
+
+ if(_configuration.getHTTPManagementEnabled())
+ {
+ _httpManagementPort = _configuration.getHTTPManagementPort();
+ }
+ if (_configuration.getHTTPSManagementEnabled())
+ {
+ _httpsManagementPort = _configuration.getHTTPSManagementPort();
+ }
+
+ _broker = new BrokerAdapter(this);
configure();
@@ -316,13 +312,23 @@ public abstract class ApplicationRegistry implements IApplicationRegistry
logStartupMessages(CurrentActor.get());
- _virtualHostRegistry = new VirtualHostRegistry(this);
-
_securityManager = new SecurityManager(_configuration, _pluginManager);
- _authenticationManager = createAuthenticationManager();
+ _authenticationManagerRegistry = createAuthenticationManagerRegistry(_configuration, _pluginManager);
- _managedObjectRegistry.start();
+ if(!_authManagerChangeListeners.isEmpty())
+ {
+ for(IAuthenticationManagerRegistry.RegistryChangeListener listener : _authManagerChangeListeners)
+ {
+
+ _authenticationManagerRegistry.addRegistryChangeListener(listener);
+ for(AuthenticationManager authMgr : _authenticationManagerRegistry.getAvailableAuthenticationManagers().values())
+ {
+ listener.authenticationManagerRegistered(authMgr);
+ }
+ }
+ _authManagerChangeListeners.clear();
+ }
}
finally
{
@@ -333,7 +339,6 @@ public abstract class ApplicationRegistry implements IApplicationRegistry
try
{
initialiseVirtualHosts();
- initialiseStatistics();
initialiseStatisticsReporting();
}
finally
@@ -343,52 +348,10 @@ 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 IAuthenticationManagerRegistry createAuthenticationManagerRegistry(ServerConfiguration _configuration, PluginManager _pluginManager)
+ throws ConfigurationException
{
- 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;
+ return new AuthenticationManagerRegistry(_configuration, _pluginManager);
}
protected void initialiseVirtualHosts() throws Exception
@@ -400,23 +363,18 @@ public abstract class ApplicationRegistry implements IApplicationRegistry
getVirtualHostRegistry().setDefaultVirtualHostName(_configuration.getDefaultVirtualHost());
}
- protected void initialiseManagedObjectRegistry() throws AMQException
- {
- _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);
-
+
_reportingTimer.scheduleAtFixedRate(new StatisticsReportingTask(broker, virtualhost, reset),
@@ -545,15 +503,13 @@ public abstract class ApplicationRegistry implements IApplicationRegistry
//Shutdown virtualhosts
close(_virtualHostRegistry);
- close(_authenticationManager);
+ close(_authenticationManagerRegistry);
close(_qmfService);
close(_pluginManager);
- close(_managedObjectRegistry);
-
- BrokerConfig broker = getBroker();
+ BrokerConfig broker = getBrokerConfig();
if(broker != null)
{
broker.getSystem().removeBroker(broker);
@@ -569,12 +525,14 @@ public abstract class ApplicationRegistry implements IApplicationRegistry
private void unbind()
{
+ List<QpidAcceptor> removedAcceptors = new ArrayList<QpidAcceptor>();
synchronized (_acceptors)
{
for (InetSocketAddress bindAddress : _acceptors.keySet())
{
QpidAcceptor acceptor = _acceptors.get(bindAddress);
+ removedAcceptors.add(acceptor);
try
{
acceptor.getNetworkTransport().close();
@@ -587,6 +545,16 @@ public abstract class ApplicationRegistry implements IApplicationRegistry
CurrentActor.get().message(BrokerMessages.SHUTTING_DOWN(acceptor.toString(), bindAddress.getPort()));
}
}
+ synchronized (_portBindingListeners)
+ {
+ for(QpidAcceptor acceptor : removedAcceptors)
+ {
+ for(PortBindingListener listener : _portBindingListeners)
+ {
+ listener.unbound(acceptor);
+ }
+ }
+ }
}
public ServerConfiguration getConfiguration()
@@ -600,6 +568,13 @@ public abstract class ApplicationRegistry implements IApplicationRegistry
{
_acceptors.put(bindAddress, acceptor);
}
+ synchronized (_portBindingListeners)
+ {
+ for(PortBindingListener listener : _portBindingListeners)
+ {
+ listener.bound(acceptor, bindAddress);
+ }
+ }
}
public VirtualHostRegistry getVirtualHostRegistry()
@@ -612,14 +587,16 @@ public abstract class ApplicationRegistry implements IApplicationRegistry
return _securityManager;
}
- public ManagedObjectRegistry getManagedObjectRegistry()
+ @Override
+ public AuthenticationManager getAuthenticationManager(SocketAddress address)
{
- return _managedObjectRegistry;
+ return _authenticationManagerRegistry.getAuthenticationManager(address);
}
- public AuthenticationManager getAuthenticationManager()
+ @Override
+ public IAuthenticationManagerRegistry getAuthenticationManagerRegistry()
{
- return _authenticationManager;
+ return _authenticationManagerRegistry;
}
public PluginManager getPluginManager()
@@ -636,7 +613,7 @@ public abstract class ApplicationRegistry implements IApplicationRegistry
{
return _rootMessageLogger;
}
-
+
public RootMessageLogger getCompositeStartupMessageLogger()
{
return _startupMessageLogger;
@@ -652,69 +629,63 @@ public abstract class ApplicationRegistry implements IApplicationRegistry
return _qmfService;
}
- public BrokerConfig getBroker()
+ public BrokerConfig getBrokerConfig()
{
- return _broker;
+ return _brokerConfig;
}
- public void setBroker(final BrokerConfig broker)
+ public void setBrokerConfig(final BrokerConfig broker)
{
- _broker = broker;
+ _brokerConfig = broker;
}
public VirtualHost createVirtualHost(final VirtualHostConfiguration vhostConfig) throws Exception
{
VirtualHostImpl virtualHost = new VirtualHostImpl(this, vhostConfig);
_virtualHostRegistry.registerVirtualHost(virtualHost);
- getBroker().addVirtualHost(virtualHost);
+ getBrokerConfig().addVirtualHost(virtualHost);
return virtualHost;
}
-
+
public void registerMessageDelivered(long messageSize)
{
- if (isStatisticsEnabled())
- {
- _messagesDelivered.registerEvent(1L);
- _dataDelivered.registerEvent(messageSize);
- }
+ _messagesDelivered.registerEvent(1L);
+ _dataDelivered.registerEvent(messageSize);
}
-
+
public void registerMessageReceived(long messageSize, long timestamp)
{
- if (isStatisticsEnabled())
- {
- _messagesReceived.registerEvent(1L, timestamp);
- _dataReceived.registerEvent(messageSize, timestamp);
- }
+ _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();
@@ -723,25 +694,12 @@ public abstract class ApplicationRegistry implements IApplicationRegistry
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;
- }
-
private void logStartupMessages(LogActor logActor)
{
logActor.message(BrokerMessages.STARTUP(QpidProperties.getReleaseVersion(), QpidProperties.getBuildVersion()));
@@ -755,4 +713,60 @@ public abstract class ApplicationRegistry implements IApplicationRegistry
logActor.message(BrokerMessages.MAX_MEMORY(Runtime.getRuntime().maxMemory()));
}
+ public Broker getBroker()
+ {
+ return _broker;
+ }
+
+ @Override
+ public void addPortBindingListener(PortBindingListener listener)
+ {
+ synchronized (_portBindingListeners)
+ {
+ _portBindingListeners.add(listener);
+ }
+ }
+
+
+ @Override
+ public boolean useHTTPManagement()
+ {
+ return _httpManagementPort != -1;
+ }
+
+ @Override
+ public int getHTTPManagementPort()
+ {
+ return _httpManagementPort;
+ }
+
+ @Override
+ public boolean useHTTPSManagement()
+ {
+ return _httpsManagementPort != -1;
+ }
+
+ @Override
+ public int getHTTPSManagementPort()
+ {
+ return _httpsManagementPort;
+ }
+
+ public LogRecorder getLogRecorder()
+ {
+ return _logRecorder;
+ }
+
+ @Override
+ public void addRegistryChangeListener(IAuthenticationManagerRegistry.RegistryChangeListener registryChangeListener)
+ {
+ if(_authenticationManagerRegistry == null)
+ {
+ _authManagerChangeListeners.add(registryChangeListener);
+ }
+ else
+ {
+ _authenticationManagerRegistry.addRegistryChangeListener(registryChangeListener);
+ }
+ }
}
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 db436b99e8..950a090b43 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
@@ -44,13 +44,13 @@ public class BrokerConfigAdapter implements BrokerConfig
private final Map<UUID, VirtualHostConfig> _vhosts = new ConcurrentHashMap<UUID, VirtualHostConfig>();
private final long _createTime = System.currentTimeMillis();
- private UUID _id;
+ private UUID _qmfId;
private String _federationTag;
public BrokerConfigAdapter(final IApplicationRegistry instance)
{
_instance = instance;
- _id = instance.getConfigStore().createId();
+ _qmfId = instance.getConfigStore().createId();
_federationTag = UUID.randomUUID().toString();
}
@@ -114,7 +114,7 @@ public class BrokerConfigAdapter implements BrokerConfig
public void addVirtualHost(final VirtualHostConfig virtualHost)
{
- _vhosts.put(virtualHost.getId(), virtualHost);
+ _vhosts.put(virtualHost.getQMFId(), virtualHost);
getConfigStore().addConfiguredObject(virtualHost);
}
@@ -141,9 +141,10 @@ public class BrokerConfigAdapter implements BrokerConfig
vhost.createBrokerConnection(transport, host, port, "", durable, authMechanism, username, password);
}
- public UUID getId()
+ @Override
+ public UUID getQMFId()
{
- return _id;
+ return _qmfId;
}
public BrokerConfigType getConfigType()
@@ -184,7 +185,7 @@ public class BrokerConfigAdapter implements BrokerConfig
public String toString()
{
return "BrokerConfigAdapter{" +
- "_id=" + _id +
+ "_id=" + _qmfId +
", _system=" + _system +
", _vhosts=" + _vhosts +
", _createTime=" + _createTime +
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 b28e3d6c89..774d0338ef 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
@@ -25,8 +25,6 @@ import org.osgi.framework.BundleContext;
import org.apache.qpid.AMQException;
import org.apache.qpid.server.configuration.ServerConfiguration;
-import org.apache.qpid.server.management.JMXManagedObjectRegistry;
-import org.apache.qpid.server.management.NoopManagedObjectRegistry;
import java.io.File;
@@ -41,18 +39,4 @@ public class ConfigurationFileApplicationRegistry extends ApplicationRegistry
{
super(new ServerConfiguration(configurationURL), bundleContext);
}
-
- @Override
- protected void initialiseManagedObjectRegistry() throws AMQException
- {
- if (getConfiguration().getManagementEnabled())
- {
- setManagedObjectRegistry(new JMXManagedObjectRegistry());
- }
- else
- {
- setManagedObjectRegistry(new NoopManagedObjectRegistry());
- }
- }
-
}
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 59bf250590..88c3c93156 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
@@ -27,16 +27,19 @@ import org.apache.qpid.server.configuration.ConfigurationManager;
import org.apache.qpid.server.configuration.ServerConfiguration;
import org.apache.qpid.server.configuration.VirtualHostConfiguration;
import org.apache.qpid.server.logging.RootMessageLogger;
-import org.apache.qpid.server.management.ManagedObjectRegistry;
+import org.apache.qpid.server.model.Broker;
import org.apache.qpid.server.plugins.PluginManager;
import org.apache.qpid.server.security.SecurityManager;
import org.apache.qpid.server.security.auth.manager.AuthenticationManager;
+import org.apache.qpid.server.security.auth.manager.IAuthenticationManagerRegistry;
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;
import java.net.InetSocketAddress;
+import java.net.SocketAddress;
+import java.util.Map;
import java.util.UUID;
public interface IApplicationRegistry extends StatisticsGatherer
@@ -60,9 +63,18 @@ public interface IApplicationRegistry extends StatisticsGatherer
*/
ServerConfiguration getConfiguration();
- ManagedObjectRegistry getManagedObjectRegistry();
+ /**
+ * Get the AuthenticationManager for the given socket address
+ *
+ * If no AuthenticationManager has been specifically set for the given address, then use the default
+ * AuthenticationManager
+ *
+ * @param address The (listening) socket address for which the AuthenticationManager is required
+ * @return the AuthenticationManager
+ */
+ AuthenticationManager getAuthenticationManager(SocketAddress address);
- AuthenticationManager getAuthenticationManager();
+ IAuthenticationManagerRegistry getAuthenticationManagerRegistry();
VirtualHostRegistry getVirtualHostRegistry();
@@ -85,15 +97,39 @@ public interface IApplicationRegistry extends StatisticsGatherer
QMFService getQMFService();
- void setBroker(BrokerConfig broker);
+ void setBrokerConfig(BrokerConfig broker);
- BrokerConfig getBroker();
+ BrokerConfig getBrokerConfig();
+
+ Broker getBroker();
VirtualHost createVirtualHost(VirtualHostConfiguration vhostConfig) throws Exception;
ConfigStore getConfigStore();
void setConfigStore(ConfigStore store);
-
+
void initialiseStatisticsReporting();
+
+ Map<InetSocketAddress, QpidAcceptor> getAcceptors();
+
+ void addPortBindingListener(PortBindingListener listener);
+
+ boolean useHTTPManagement();
+
+ int getHTTPManagementPort();
+
+ boolean useHTTPSManagement();
+
+ int getHTTPSManagementPort();
+
+ void addRegistryChangeListener(IAuthenticationManagerRegistry.RegistryChangeListener registryChangeListener);
+
+ public interface PortBindingListener
+ {
+ public void bound(QpidAcceptor acceptor, InetSocketAddress bindAddress);
+ public void unbound(QpidAcceptor acceptor);
+
+ }
+
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/AbstractPasswordFilePrincipalDatabase.java b/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/AbstractPasswordFilePrincipalDatabase.java
index 7088fae50c..cac60a5283 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/AbstractPasswordFilePrincipalDatabase.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/AbstractPasswordFilePrincipalDatabase.java
@@ -198,7 +198,7 @@ public abstract class AbstractPasswordFilePrincipalDatabase<U extends PasswordPr
try
{
_userUpdate.lock();
- _userMap.clear();
+ final Map<String, U> newUserMap = new HashMap<String, U>();
BufferedReader reader = null;
try
@@ -216,7 +216,7 @@ public abstract class AbstractPasswordFilePrincipalDatabase<U extends PasswordPr
U user = createUserFromFileData(result);
getLogger().info("Created user:" + user);
- _userMap.put(user.getName(), user);
+ newUserMap.put(user.getName(), user);
}
}
finally
@@ -226,6 +226,9 @@ public abstract class AbstractPasswordFilePrincipalDatabase<U extends PasswordPr
reader.close();
}
}
+
+ _userMap.clear();
+ _userMap.putAll(newUserMap);
}
finally
{
diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AnonymousAuthenticationManager.java b/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AnonymousAuthenticationManager.java
new file mode 100644
index 0000000000..5676c43754
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AnonymousAuthenticationManager.java
@@ -0,0 +1,192 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.security.Principal;
+import java.util.Arrays;
+import java.util.List;
+import javax.security.auth.Subject;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.sasl.SaslException;
+import javax.security.sasl.SaslServer;
+import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration.ConfigurationException;
+import org.apache.log4j.Logger;
+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.sasl.UsernamePrincipal;
+import org.apache.qpid.server.security.auth.sasl.anonymous.AnonymousInitialiser;
+import org.apache.qpid.server.security.auth.sasl.anonymous.AnonymousSaslServer;
+
+public class AnonymousAuthenticationManager implements AuthenticationManager
+{
+ private static final Logger _logger = Logger.getLogger(AnonymousAuthenticationManager.class);
+
+ private static final AnonymousInitialiser SASL_INITIALISER = new AnonymousInitialiser();
+
+ private static final String ANONYMOUS = SASL_INITIALISER.getMechanismName();
+
+ private static final Principal ANONYMOUS_PRINCIPAL = new UsernamePrincipal("ANONYMOUS");
+
+ public static final Subject ANONYMOUS_SUBJECT = new Subject();
+ static
+ {
+ ANONYMOUS_SUBJECT.getPrincipals().add(ANONYMOUS_PRINCIPAL);
+ }
+
+ private static final AuthenticationResult ANONYMOUS_AUTHENTICATION = new AuthenticationResult(ANONYMOUS_SUBJECT);
+
+
+ private static CallbackHandler _callbackHandler = SASL_INITIALISER.getCallbackHandler();
+
+ static final AnonymousAuthenticationManager INSTANCE = new AnonymousAuthenticationManager();
+
+ public static class AnonymousAuthenticationManagerConfiguration extends ConfigurationPlugin
+ {
+
+ public static final ConfigurationPluginFactory FACTORY =
+ new ConfigurationPluginFactory()
+ {
+ public List<String> getParentPaths()
+ {
+ return Arrays.asList("security.anonymous-auth-manager");
+ }
+
+ public ConfigurationPlugin newInstance(final String path, final Configuration config) throws ConfigurationException
+ {
+ final ConfigurationPlugin instance = new AnonymousAuthenticationManagerConfiguration();
+
+ instance.setConfiguration(path, config);
+ return instance;
+ }
+ };
+
+ public String[] getElementsProcessed()
+ {
+ return new String[0];
+ }
+
+ public void validateConfiguration() throws ConfigurationException
+ {
+ }
+
+ }
+
+
+ public static final AuthenticationManagerPluginFactory<AnonymousAuthenticationManager> FACTORY = new AuthenticationManagerPluginFactory<AnonymousAuthenticationManager>()
+ {
+ public AnonymousAuthenticationManager newInstance(final ConfigurationPlugin config) throws ConfigurationException
+ {
+ AnonymousAuthenticationManagerConfiguration configuration =
+ config == null
+ ? null
+ : (AnonymousAuthenticationManagerConfiguration) config.getConfiguration(AnonymousAuthenticationManagerConfiguration.class.getName());
+
+ // If there is no configuration for this plugin then don't load it.
+ if (configuration == null)
+ {
+ _logger.info("No authentication-manager configuration found for AnonymousAuthenticationManager");
+ return null;
+ }
+ return INSTANCE;
+ }
+
+ public Class<AnonymousAuthenticationManager> getPluginClass()
+ {
+ return AnonymousAuthenticationManager.class;
+ }
+
+ public String getPluginName()
+ {
+ return AnonymousAuthenticationManager.class.getName();
+ }
+ };
+
+
+ private AnonymousAuthenticationManager()
+ {
+ }
+
+ @Override
+ public void initialise()
+ {
+
+ }
+
+ @Override
+ public String getMechanisms()
+ {
+ return ANONYMOUS;
+ }
+
+ @Override
+ public SaslServer createSaslServer(String mechanism, String localFQDN, Principal externalPrincipal) throws SaslException
+ {
+ if(ANONYMOUS.equals(mechanism))
+ {
+ return new AnonymousSaslServer();
+ }
+ else
+ {
+ throw new SaslException("Unknown mechanism: " + mechanism);
+ }
+ }
+
+ @Override
+ public AuthenticationResult authenticate(SaslServer server, byte[] response)
+ {
+ try
+ {
+ // Process response from the client
+ byte[] challenge = server.evaluateResponse(response != null ? response : new byte[0]);
+
+ if (server.isComplete())
+ {
+ return ANONYMOUS_AUTHENTICATION;
+ }
+ else
+ {
+ return new AuthenticationResult(challenge, AuthenticationResult.AuthenticationStatus.CONTINUE);
+ }
+ }
+ catch (SaslException e)
+ {
+ return new AuthenticationResult(AuthenticationResult.AuthenticationStatus.ERROR, e);
+ }
+ }
+
+ @Override
+ public AuthenticationResult authenticate(String username, String password)
+ {
+ return ANONYMOUS_AUTHENTICATION;
+ }
+
+ @Override
+ public void close()
+ {
+ }
+
+ @Override
+ public void configure(ConfigurationPlugin config) throws ConfigurationException
+ {
+ }
+}
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 6c1a917d5b..ccddcb7669 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
@@ -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
@@ -20,25 +20,24 @@
*/
package org.apache.qpid.server.security.auth.manager;
+import java.security.Principal;
+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;
-import javax.security.auth.callback.CallbackHandler;
-import javax.security.sasl.SaslException;
-import javax.security.sasl.SaslServer;
-
/**
* 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 javax.security.auth.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
{
@@ -64,11 +63,11 @@ public interface AuthenticationManager extends Closeable, Plugin
*
* @param mechanism mechanism name
* @param localFQDN domain name
- *
+ * @param externalPrincipal externally authenticated Principal
* @return SASL server
* @throws SaslException
*/
- SaslServer createSaslServer(String mechanism, String localFQDN) throws SaslException;
+ SaslServer createSaslServer(String mechanism, String localFQDN, Principal externalPrincipal) throws SaslException;
/**
* Authenticates a user using SASL negotiation.
@@ -90,5 +89,4 @@ public interface AuthenticationManager extends Closeable, Plugin
*/
AuthenticationResult authenticate(String username, String password);
- CallbackHandler getHandler(String mechanism);
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AuthenticationManagerRegistry.java b/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AuthenticationManagerRegistry.java
new file mode 100644
index 0000000000..89a4d8ae66
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AuthenticationManagerRegistry.java
@@ -0,0 +1,203 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.net.InetSocketAddress;
+import java.net.SocketAddress;
+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 org.apache.commons.configuration.ConfigurationException;
+import org.apache.qpid.common.Closeable;
+import org.apache.qpid.server.configuration.ServerConfiguration;
+import org.apache.qpid.server.plugins.Plugin;
+import org.apache.qpid.server.plugins.PluginManager;
+import org.apache.qpid.server.security.SecurityManager.SecurityConfiguration;
+
+/**
+ * A concrete implementation of {@link IAuthenticationManagerRegistry} that registers all {@link AuthenticationManager}
+ * instances defined in the configuration, building an optional mapping between port number and AuthenticationManager.
+ *
+ * <p>The default AuthenticationManager is either the one nominated as default within the configuration with
+ * {@link ServerConfiguration#getDefaultAuthenticationManager()}, or if there is only one, it is implicitly
+ * the default.</p>
+ *
+ * <p>It is important to {@link #close()} the registry after use and this allows the AuthenticationManagers
+ * to reverse any security registrations they have performed.</p>
+ */
+public class AuthenticationManagerRegistry implements Closeable, IAuthenticationManagerRegistry
+{
+ private final Map<String,AuthenticationManager> _classToAuthManagerMap = new HashMap<String,AuthenticationManager>();
+ private final AuthenticationManager _defaultAuthenticationManager;
+ private final Map<Integer,AuthenticationManager> _portToAuthenticationManagerMap;
+ private final List<RegistryChangeListener> _listeners =
+ Collections.synchronizedList(new ArrayList<RegistryChangeListener>());
+
+ public AuthenticationManagerRegistry(ServerConfiguration serverConfiguration, PluginManager _pluginManager)
+ throws ConfigurationException
+ {
+ 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.");
+ }
+
+ final SecurityConfiguration securityConfiguration = serverConfiguration.getConfiguration(SecurityConfiguration.class.getName());
+
+ boolean willClose = true;
+ try
+ {
+ createAuthenticationManagersRejectingDuplicates(factories, securityConfiguration);
+
+ if(_classToAuthManagerMap.isEmpty())
+ {
+ throw new ConfigurationException("No authentication managers configured within the configuration file.");
+ }
+
+ _defaultAuthenticationManager = getDefaultAuthenticationManager(serverConfiguration);
+
+ _portToAuthenticationManagerMap = getPortToAuthenticationManagerMap(serverConfiguration);
+ willClose = false;
+ }
+ finally
+ {
+ // if anything went wrong whilst configuring the registry, try to close all the AuthentcationManagers instantiated so far.
+ // This is done to allow the AuthenticationManager to undo any security registrations that they have performed.
+ if (willClose)
+ {
+ close();
+ }
+ }
+ }
+
+ @Override
+ public AuthenticationManager getAuthenticationManager(SocketAddress address)
+ {
+ AuthenticationManager authManager =
+ address instanceof InetSocketAddress
+ ? _portToAuthenticationManagerMap.get(((InetSocketAddress)address).getPort())
+ : null;
+
+ return authManager == null ? _defaultAuthenticationManager : authManager;
+ }
+
+ @Override
+ public void close()
+ {
+ for (AuthenticationManager authManager : _classToAuthManagerMap.values())
+ {
+ authManager.close();
+ }
+ }
+
+ private void createAuthenticationManagersRejectingDuplicates(
+ final Collection<AuthenticationManagerPluginFactory<? extends Plugin>> factories,
+ final SecurityConfiguration securityConfiguration)
+ throws ConfigurationException
+ {
+ for(AuthenticationManagerPluginFactory<? extends Plugin> factory : factories)
+ {
+ final AuthenticationManager tmp = factory.newInstance(securityConfiguration);
+ if (tmp != null)
+ {
+ if(_classToAuthManagerMap.containsKey(tmp.getClass().getSimpleName()))
+ {
+ throw new ConfigurationException("Cannot configure more than one authentication manager of type "
+ + tmp.getClass().getSimpleName() + "."
+ + " Remove configuration for one of the authentication managers.");
+ }
+ _classToAuthManagerMap.put(tmp.getClass().getSimpleName(),tmp);
+
+ for(RegistryChangeListener listener : _listeners)
+ {
+ listener.authenticationManagerRegistered(tmp);
+ }
+ }
+ }
+ }
+
+ private AuthenticationManager getDefaultAuthenticationManager(
+ ServerConfiguration serverConfiguration)
+ throws ConfigurationException
+ {
+ final AuthenticationManager defaultAuthenticationManager;
+ if(_classToAuthManagerMap.size() == 1)
+ {
+ defaultAuthenticationManager = _classToAuthManagerMap.values().iterator().next();
+ }
+ else if(serverConfiguration.getDefaultAuthenticationManager() != null)
+ {
+ defaultAuthenticationManager = _classToAuthManagerMap.get(serverConfiguration.getDefaultAuthenticationManager());
+ if(defaultAuthenticationManager == null)
+ {
+ throw new ConfigurationException("No authentication managers configured of type "
+ + serverConfiguration.getDefaultAuthenticationManager()
+ + " which is specified as the default. Available managers are: "
+ + _classToAuthManagerMap.keySet());
+ }
+ }
+ else
+ {
+ throw new ConfigurationException("If more than one authentication manager is configured a default MUST be specified.");
+ }
+ return defaultAuthenticationManager;
+ }
+
+ private Map<Integer,AuthenticationManager> getPortToAuthenticationManagerMap(
+ ServerConfiguration serverConfiguration)
+ throws ConfigurationException
+ {
+ Map<Integer,AuthenticationManager> portToAuthenticationManagerMap = new HashMap<Integer, AuthenticationManager>();
+
+ for(Map.Entry<Integer,String> portMapping : serverConfiguration.getPortAuthenticationMappings().entrySet())
+ {
+
+ AuthenticationManager authenticationManager = _classToAuthManagerMap.get(portMapping.getValue());
+ if(authenticationManager == null)
+ {
+ throw new ConfigurationException("Unknown authentication manager class " + portMapping.getValue() +
+ " configured for port " + portMapping.getKey());
+ }
+ portToAuthenticationManagerMap.put(portMapping.getKey(), authenticationManager);
+ }
+
+ return portToAuthenticationManagerMap;
+ }
+
+ @Override
+ public Map<String, AuthenticationManager> getAvailableAuthenticationManagers()
+ {
+ return Collections.unmodifiableMap(new HashMap<String, AuthenticationManager>(_classToAuthManagerMap));
+ }
+
+ @Override
+ public void addRegistryChangeListener(RegistryChangeListener listener)
+ {
+ _listeners.add(listener);
+ }
+
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/ExternalAuthenticationManager.java b/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/ExternalAuthenticationManager.java
new file mode 100644
index 0000000000..2d6866b657
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/ExternalAuthenticationManager.java
@@ -0,0 +1,177 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.qpid.server.security.auth.manager;
+
+import java.security.Principal;
+import java.util.Arrays;
+import java.util.List;
+import javax.security.auth.Subject;
+import javax.security.sasl.SaslException;
+import javax.security.sasl.SaslServer;
+import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration.ConfigurationException;
+import org.apache.log4j.Logger;
+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.sasl.external.ExternalSaslServer;
+
+public class ExternalAuthenticationManager implements AuthenticationManager
+{
+ private static final Logger _logger = Logger.getLogger(ExternalAuthenticationManager.class);
+
+ private static final String EXTERNAL = "EXTERNAL";
+
+ static final ExternalAuthenticationManager INSTANCE = new ExternalAuthenticationManager();
+
+ public static class ExternalAuthenticationManagerConfiguration extends ConfigurationPlugin
+ {
+
+ public static final ConfigurationPluginFactory FACTORY =
+ new ConfigurationPluginFactory()
+ {
+ public List<String> getParentPaths()
+ {
+ return Arrays.asList("security.external-auth-manager");
+ }
+
+ public ConfigurationPlugin newInstance(final String path, final Configuration config) throws ConfigurationException
+ {
+ final ConfigurationPlugin instance = new ExternalAuthenticationManagerConfiguration();
+
+ instance.setConfiguration(path, config);
+ return instance;
+ }
+ };
+
+ public String[] getElementsProcessed()
+ {
+ return new String[0];
+ }
+
+ public void validateConfiguration() throws ConfigurationException
+ {
+ }
+
+ }
+
+
+ public static final AuthenticationManagerPluginFactory<ExternalAuthenticationManager> FACTORY = new AuthenticationManagerPluginFactory<ExternalAuthenticationManager>()
+ {
+ public ExternalAuthenticationManager newInstance(final ConfigurationPlugin config) throws ConfigurationException
+ {
+ ExternalAuthenticationManagerConfiguration configuration =
+ config == null
+ ? null
+ : (ExternalAuthenticationManagerConfiguration) config.getConfiguration(ExternalAuthenticationManagerConfiguration.class.getName());
+
+ // If there is no configuration for this plugin then don't load it.
+ if (configuration == null)
+ {
+ _logger.info("No authentication-manager configuration found for ExternalAuthenticationManager");
+ return null;
+ }
+ return INSTANCE;
+ }
+
+ public Class<ExternalAuthenticationManager> getPluginClass()
+ {
+ return ExternalAuthenticationManager.class;
+ }
+
+ public String getPluginName()
+ {
+ return ExternalAuthenticationManager.class.getName();
+ }
+ };
+
+
+ private ExternalAuthenticationManager()
+ {
+ }
+
+ @Override
+ public void initialise()
+ {
+
+ }
+
+ @Override
+ public String getMechanisms()
+ {
+ return EXTERNAL;
+ }
+
+ @Override
+ public SaslServer createSaslServer(String mechanism, String localFQDN, Principal externalPrincipal) throws SaslException
+ {
+ if(EXTERNAL.equals(mechanism))
+ {
+ return new ExternalSaslServer(externalPrincipal);
+ }
+ else
+ {
+ throw new SaslException("Unknown mechanism: " + mechanism);
+ }
+ }
+
+ @Override
+ public AuthenticationResult authenticate(SaslServer server, byte[] response)
+ {
+ // Process response from the client
+ try
+ {
+ byte[] challenge = server.evaluateResponse(response != null ? response : new byte[0]);
+
+ Principal principal = ((ExternalSaslServer)server).getAuthenticatedPrincipal();
+
+ if(principal != null)
+ {
+ final Subject subject = new Subject();
+ subject.getPrincipals().add(principal);
+ return new AuthenticationResult(subject);
+ }
+ else
+ {
+ return new AuthenticationResult(AuthenticationResult.AuthenticationStatus.ERROR);
+ }
+ }
+ catch (SaslException e)
+ {
+ return new AuthenticationResult(AuthenticationResult.AuthenticationStatus.ERROR,e);
+ }
+
+ }
+
+ @Override
+ public AuthenticationResult authenticate(String username, String password)
+ {
+ return new AuthenticationResult(AuthenticationResult.AuthenticationStatus.ERROR);
+ }
+
+ @Override
+ public void close()
+ {
+ }
+
+ @Override
+ public void configure(ConfigurationPlugin config) throws ConfigurationException
+ {
+ }
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/IAuthenticationManagerRegistry.java b/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/IAuthenticationManagerRegistry.java
new file mode 100644
index 0000000000..485ca2e1e9
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/IAuthenticationManagerRegistry.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.server.security.auth.manager;
+
+import java.net.SocketAddress;
+
+import java.util.Map;
+import org.apache.qpid.common.Closeable;
+import org.apache.qpid.server.virtualhost.VirtualHost;
+
+/**
+ * Registry for {@link AuthenticationManager} instances.
+ *
+ * <p>A lookup method {@link #getAuthenticationManager(SocketAddress)} allows a caller to determine
+ * the AuthenticationManager associated with a particular port number.</p>
+ *
+ * <p>It is important to {@link #close()} the registry after use and this allows the AuthenticationManagers
+ * to reverse any security registrations they have performed.</p>
+ */
+public interface IAuthenticationManagerRegistry extends Closeable
+{
+ /**
+ * Returns the {@link AuthenticationManager} associated with a particular {@link SocketAddress}.
+ * If no authentication manager is associated with this address, a default authentication manager will be
+ * returned. Null is never returned.
+ *
+ * @param address
+ * @return authentication manager.
+ */
+ public AuthenticationManager getAuthenticationManager(SocketAddress address);
+
+ Map<String, AuthenticationManager> getAvailableAuthenticationManagers();
+
+ public static interface RegistryChangeListener
+ {
+ void authenticationManagerRegistered(AuthenticationManager authenticationManager);
+ void authenticationManagerUnregistered(AuthenticationManager authenticationManager);
+ }
+
+ public void addRegistryChangeListener(RegistryChangeListener listener);
+
+} \ No newline at end of file
diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/KerberosAuthenticationManager.java b/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/KerberosAuthenticationManager.java
new file mode 100644
index 0000000000..d735ecb1d4
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/KerberosAuthenticationManager.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.server.security.auth.manager;
+
+import java.io.IOException;
+import java.security.Principal;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import javax.security.auth.Subject;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.sasl.AuthorizeCallback;
+import javax.security.sasl.Sasl;
+import javax.security.sasl.SaslException;
+import javax.security.sasl.SaslServer;
+import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration.ConfigurationException;
+import org.apache.log4j.Logger;
+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.sasl.UsernamePrincipal;
+
+public class KerberosAuthenticationManager implements AuthenticationManager
+{
+ private static final Logger _logger = Logger.getLogger(KerberosAuthenticationManager.class);
+
+ private static final String GSSAPI_MECHANISM = "GSSAPI";
+ private final CallbackHandler _callbackHandler = new GssApiCallbackHandler();
+
+ public static class KerberosAuthenticationManagerConfiguration extends ConfigurationPlugin
+ {
+
+ public static final ConfigurationPluginFactory FACTORY =
+ new ConfigurationPluginFactory()
+ {
+ public List<String> getParentPaths()
+ {
+ return Arrays.asList("security.kerberos-auth-manager");
+ }
+
+ public ConfigurationPlugin newInstance(final String path, final Configuration config) throws ConfigurationException
+ {
+ final ConfigurationPlugin instance = new KerberosAuthenticationManagerConfiguration();
+
+ instance.setConfiguration(path, config);
+ return instance;
+ }
+ };
+
+ public String[] getElementsProcessed()
+ {
+ return new String[0];
+ }
+
+ public void validateConfiguration() throws ConfigurationException
+ {
+ }
+
+ }
+
+
+ public static final AuthenticationManagerPluginFactory<KerberosAuthenticationManager> FACTORY = new AuthenticationManagerPluginFactory<KerberosAuthenticationManager>()
+ {
+ public KerberosAuthenticationManager newInstance(final ConfigurationPlugin config) throws ConfigurationException
+ {
+ KerberosAuthenticationManagerConfiguration configuration =
+ config == null
+ ? null
+ : (KerberosAuthenticationManagerConfiguration) config.getConfiguration(KerberosAuthenticationManagerConfiguration.class.getName());
+
+ // If there is no configuration for this plugin then don't load it.
+ if (configuration == null)
+ {
+ _logger.info("No authentication-manager configuration found for KerberosAuthenticationManager");
+ return null;
+ }
+ KerberosAuthenticationManager kerberosAuthenticationManager = new KerberosAuthenticationManager();
+ kerberosAuthenticationManager.configure(configuration);
+ return kerberosAuthenticationManager;
+ }
+
+ public Class<KerberosAuthenticationManager> getPluginClass()
+ {
+ return KerberosAuthenticationManager.class;
+ }
+
+ public String getPluginName()
+ {
+ return KerberosAuthenticationManager.class.getName();
+ }
+ };
+
+
+ private KerberosAuthenticationManager()
+ {
+ }
+
+ @Override
+ public void initialise()
+ {
+
+ }
+
+ @Override
+ public String getMechanisms()
+ {
+ return GSSAPI_MECHANISM;
+ }
+
+ @Override
+ public SaslServer createSaslServer(String mechanism, String localFQDN, Principal externalPrincipal) throws SaslException
+ {
+ if(GSSAPI_MECHANISM.equals(mechanism))
+ {
+ try
+ {
+ return Sasl.createSaslServer(GSSAPI_MECHANISM, "AMQP", localFQDN,
+ new HashMap<String, Object>(), _callbackHandler);
+ }
+ catch (SaslException e)
+ {
+ e.printStackTrace(System.err);
+ throw e;
+ }
+ }
+ else
+ {
+ throw new SaslException("Unknown mechanism: " + mechanism);
+ }
+ }
+
+ @Override
+ public AuthenticationResult authenticate(SaslServer server, byte[] response)
+ {
+ try
+ {
+ // Process response from the client
+ byte[] challenge = server.evaluateResponse(response != null ? response : new byte[0]);
+
+ if (server.isComplete())
+ {
+ final Subject subject = new Subject();
+ _logger.debug("Authenticated as " + server.getAuthorizationID());
+ subject.getPrincipals().add(new UsernamePrincipal(server.getAuthorizationID()));
+ return new AuthenticationResult(subject);
+ }
+ else
+ {
+ return new AuthenticationResult(challenge, AuthenticationResult.AuthenticationStatus.CONTINUE);
+ }
+ }
+ catch (SaslException e)
+ {
+ e.printStackTrace(System.err);
+ return new AuthenticationResult(AuthenticationResult.AuthenticationStatus.ERROR, e);
+ }
+ }
+
+ @Override
+ public AuthenticationResult authenticate(String username, String password)
+ {
+ return new AuthenticationResult(AuthenticationResult.AuthenticationStatus.ERROR);
+ }
+
+ @Override
+ public void close()
+ {
+ }
+
+ @Override
+ public void configure(ConfigurationPlugin config) throws ConfigurationException
+ {
+ }
+
+ private static class GssApiCallbackHandler implements CallbackHandler
+ {
+
+ @Override
+ public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException
+ {
+ for(Callback callback : callbacks)
+ {
+ if (callback instanceof AuthorizeCallback)
+ {
+ ((AuthorizeCallback) callback).setAuthorized(true);
+ }
+ else
+ {
+ throw new UnsupportedCallbackException(callback);
+ }
+ }
+ }
+ }
+}
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 b5d70d9200..e6498919a1 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
@@ -14,12 +14,13 @@
* "AS IS" BASIS, WITHOUT 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.server.security.auth.manager;
+import java.security.Principal;
import org.apache.commons.configuration.Configuration;
import org.apache.commons.configuration.ConfigurationException;
import org.apache.log4j.Logger;
@@ -31,7 +32,6 @@ 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.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;
@@ -60,9 +60,9 @@ import java.util.TreeMap;
* 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>
@@ -97,13 +97,14 @@ public class PrincipalDatabaseAuthenticationManager implements AuthenticationMan
private PrincipalDatabase _principalDatabase = null;
- private AMQUserManagementMBean _mbean = null;
-
public static final AuthenticationManagerPluginFactory<PrincipalDatabaseAuthenticationManager> FACTORY = new AuthenticationManagerPluginFactory<PrincipalDatabaseAuthenticationManager>()
{
public PrincipalDatabaseAuthenticationManager newInstance(final ConfigurationPlugin config) throws ConfigurationException
{
- final PrincipalDatabaseAuthenticationManagerConfiguration configuration = config.getConfiguration(PrincipalDatabaseAuthenticationManagerConfiguration.class.getName());
+ final PrincipalDatabaseAuthenticationManagerConfiguration configuration =
+ config == null
+ ? null
+ : (PrincipalDatabaseAuthenticationManagerConfiguration) config.getConfiguration(PrincipalDatabaseAuthenticationManagerConfiguration.class.getName());
// If there is no configuration for this plugin then don't load it.
if (configuration == null)
@@ -130,7 +131,7 @@ public class PrincipalDatabaseAuthenticationManager implements AuthenticationMan
};
public static class PrincipalDatabaseAuthenticationManagerConfiguration extends ConfigurationPlugin {
-
+
public static final ConfigurationPluginFactory FACTORY = new ConfigurationPluginFactory()
{
public List<String> getParentPaths()
@@ -141,7 +142,7 @@ public class PrincipalDatabaseAuthenticationManager implements AuthenticationMan
public ConfigurationPlugin newInstance(final String path, final Configuration config) throws ConfigurationException
{
final ConfigurationPlugin instance = new PrincipalDatabaseAuthenticationManagerConfiguration();
-
+
instance.setConfiguration(path, config);
return instance;
}
@@ -157,16 +158,16 @@ public class PrincipalDatabaseAuthenticationManager implements AuthenticationMan
public void validateConfiguration() throws ConfigurationException
{
}
-
+
public String getPrincipalDatabaseClass()
{
return getConfig().getString("principal-database.class");
}
-
+
public Map<String,String> getPdClassAttributeMap() throws ConfigurationException
{
- final List<String> argumentNames = getConfig().getList("principal-database.attributes.attribute.name");
- final List<String> argumentValues = getConfig().getList("principal-database.attributes.attribute.value");
+ final List<String> argumentNames = (List) getConfig().getList("principal-database.attributes.attribute.name");
+ final List<String> argumentValues = (List) getConfig().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++)
@@ -181,7 +182,7 @@ public class PrincipalDatabaseAuthenticationManager implements AuthenticationMan
}
}
- protected PrincipalDatabaseAuthenticationManager()
+ protected PrincipalDatabaseAuthenticationManager()
{
}
@@ -207,11 +208,9 @@ public class PrincipalDatabaseAuthenticationManager implements AuthenticationMan
{
_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, PrincipalDatabase database)
{
if (database == null || database.getMechanisms().size() == 0)
{
@@ -259,7 +258,7 @@ public class PrincipalDatabaseAuthenticationManager implements AuthenticationMan
_principalDatabase = createPrincipalDatabaseImpl(pdClazz);
- configPrincipalDatabase(_principalDatabase, pdamConfig);
+ configPrincipalDatabase(_principalDatabase, pdamConfig);
}
public String getMechanisms()
@@ -267,7 +266,7 @@ public class PrincipalDatabaseAuthenticationManager implements AuthenticationMan
return _mechanisms;
}
- public SaslServer createSaslServer(String mechanism, String localFQDN) throws SaslException
+ public SaslServer createSaslServer(String mechanism, String localFQDN, Principal externalPrincipal) throws SaslException
{
return Sasl.createSaslServer(mechanism, "AMQP", localFQDN, _serverCreationProperties.get(mechanism),
_callbackHandlerMap.get(mechanism));
@@ -300,11 +299,6 @@ public class PrincipalDatabaseAuthenticationManager implements AuthenticationMan
}
}
- public CallbackHandler getHandler(String mechanism)
- {
- return _callbackHandlerMap.get(mechanism);
- }
-
/**
* @see org.apache.qpid.server.security.auth.manager.AuthenticationManager#authenticate(String, String)
*/
@@ -333,8 +327,6 @@ public class PrincipalDatabaseAuthenticationManager implements AuthenticationMan
{
_mechanisms = null;
Security.removeProvider(PROVIDER_NAME);
-
- unregisterManagement();
}
private PrincipalDatabase createPrincipalDatabaseImpl(final String pdClazz) throws ConfigurationException
@@ -408,6 +400,11 @@ public class PrincipalDatabaseAuthenticationManager implements AuthenticationMan
}
}
+ public PrincipalDatabase getPrincipalDatabase()
+ {
+ return _principalDatabase;
+ }
+
private String generateSetterName(String argName) throws ConfigurationException
{
if ((argName == null) || (argName.length() == 0))
@@ -428,41 +425,4 @@ public class PrincipalDatabaseAuthenticationManager implements AuthenticationMan
{
_principalDatabase = principalDatabase;
}
-
- protected void registerManagement()
- {
- try
- {
- _logger.info("Registering UserManagementMBean");
-
- _mbean = new AMQUserManagementMBean();
- _mbean.setPrincipalDatabase(_principalDatabase);
- _mbean.register();
- }
- catch (Exception e)
- {
- _logger.warn("User management disabled as unable to create MBean:", e);
- _mbean = null;
- }
- }
-
- protected void unregisterManagement()
- {
- 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;
- }
- }
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/SimpleLDAPAuthenticationManager.java b/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/SimpleLDAPAuthenticationManager.java
new file mode 100644
index 0000000000..64b24e28bc
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/SimpleLDAPAuthenticationManager.java
@@ -0,0 +1,389 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.IOException;
+import java.security.Principal;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.List;
+import javax.naming.Context;
+import javax.naming.NamingEnumeration;
+import javax.naming.NamingException;
+import javax.naming.directory.DirContext;
+import javax.naming.directory.InitialDirContext;
+import javax.naming.directory.SearchControls;
+import javax.naming.directory.SearchResult;
+import javax.security.auth.Subject;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.sasl.AuthorizeCallback;
+import javax.security.sasl.Sasl;
+import javax.security.sasl.SaslException;
+import javax.security.sasl.SaslServer;
+import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration.ConfigurationException;
+import org.apache.log4j.Logger;
+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.sasl.UsernamePrincipal;
+import org.apache.qpid.server.security.auth.sasl.plain.PlainPasswordCallback;
+
+public class SimpleLDAPAuthenticationManager implements AuthenticationManager
+{
+ private static final Logger _logger = Logger.getLogger(SimpleLDAPAuthenticationManager.class);
+
+ private static final String PLAIN_MECHANISM = "PLAIN";
+ private static final String DEFAULT_LDAP_CONTEXT_FACTORY = "com.sun.jndi.ldap.LdapCtxFactory";
+ private String _providerSearchURL;
+ private String _searchContext;
+ private String _searchFilter;
+ private String _providerAuthURL;
+ private String _ldapContextFactory;
+
+ public static class SimpleLDAPAuthenticationManagerConfiguration extends ConfigurationPlugin
+ {
+
+ public static final ConfigurationPluginFactory FACTORY =
+ new ConfigurationPluginFactory()
+ {
+ public List<String> getParentPaths()
+ {
+ return Arrays.asList("security.simple-ldap-auth-manager");
+ }
+
+ public ConfigurationPlugin newInstance(final String path, final Configuration config) throws ConfigurationException
+ {
+ final ConfigurationPlugin instance = new SimpleLDAPAuthenticationManagerConfiguration();
+
+ instance.setConfiguration(path, config);
+ return instance;
+ }
+ };
+
+ private static final String PROVIDER_URL = "provider-url";
+ private static final String PROVIDER_SEARCH_URL = "provider-search-url";
+ private static final String PROVIDER_AUTH_URL = "provider-auth-url";
+ private static final String SEARCH_CONTEXT = "search-context";
+ private static final String SEARCH_FILTER = "search-filter";
+ private static final String LDAP_CONTEXT_FACTORY = "ldap-context-factory";
+
+ public String[] getElementsProcessed()
+ {
+ return new String[] {PROVIDER_URL, PROVIDER_SEARCH_URL, PROVIDER_AUTH_URL, SEARCH_CONTEXT, SEARCH_FILTER,
+ LDAP_CONTEXT_FACTORY};
+ }
+
+ public void validateConfiguration() throws ConfigurationException
+ {
+ }
+
+ public String getLDAPContextFactory()
+ {
+ return getConfig().getString(LDAP_CONTEXT_FACTORY, DEFAULT_LDAP_CONTEXT_FACTORY);
+ }
+
+
+ public String getProviderURL()
+ {
+ return getConfig().getString(PROVIDER_URL);
+ }
+
+ public String getProviderSearchURL()
+ {
+ return getConfig().getString(PROVIDER_SEARCH_URL, getProviderURL());
+ }
+
+ public String getSearchContext()
+ {
+ return getConfig().getString(SEARCH_CONTEXT);
+ }
+
+ public String getSearchFilter()
+ {
+ return getConfig().getString(SEARCH_FILTER);
+ }
+
+ public String getProviderAuthURL()
+ {
+ return getConfig().getString(PROVIDER_AUTH_URL, getProviderURL());
+ }
+ }
+
+
+ public static final AuthenticationManagerPluginFactory<SimpleLDAPAuthenticationManager> FACTORY = new AuthenticationManagerPluginFactory<SimpleLDAPAuthenticationManager>()
+ {
+ public SimpleLDAPAuthenticationManager newInstance(final ConfigurationPlugin config) throws ConfigurationException
+ {
+ SimpleLDAPAuthenticationManagerConfiguration configuration =
+ config == null
+ ? null
+ : (SimpleLDAPAuthenticationManagerConfiguration) config.getConfiguration(SimpleLDAPAuthenticationManagerConfiguration.class.getName());
+
+ // If there is no configuration for this plugin then don't load it.
+ if (configuration == null)
+ {
+ _logger.info("No authentication-manager configuration found for SimpleLDAPAuthenticationManager");
+ return null;
+ }
+ SimpleLDAPAuthenticationManager simpleLDAPAuthenticationManager = new SimpleLDAPAuthenticationManager();
+ simpleLDAPAuthenticationManager.configure(configuration);
+ return simpleLDAPAuthenticationManager;
+ }
+
+ public Class<SimpleLDAPAuthenticationManager> getPluginClass()
+ {
+ return SimpleLDAPAuthenticationManager.class;
+ }
+
+ public String getPluginName()
+ {
+ return SimpleLDAPAuthenticationManager.class.getName();
+ }
+ };
+
+
+ private SimpleLDAPAuthenticationManager()
+ {
+ }
+
+ @Override
+ public void initialise()
+ {
+
+ }
+
+ @Override
+ public String getMechanisms()
+ {
+ return PLAIN_MECHANISM;
+ }
+
+ @Override
+ public SaslServer createSaslServer(String mechanism, String localFQDN, Principal externalPrincipal) throws SaslException
+ {
+ if(PLAIN_MECHANISM.equals(mechanism))
+ {
+ return Sasl.createSaslServer(PLAIN_MECHANISM, "AMQP", localFQDN,
+ new HashMap<String, Object>(), new PlainCallbackHandler());
+
+ }
+ else
+ {
+ throw new SaslException("Unknown mechanism: " + mechanism);
+ }
+ }
+
+ @Override
+ public AuthenticationResult authenticate(SaslServer server, byte[] response)
+ {
+ try
+ {
+ // Process response from the client
+ byte[] challenge = server.evaluateResponse(response != null ? response : new byte[0]);
+
+ if (server.isComplete())
+ {
+ final Subject subject = new Subject();
+ _logger.debug("Authenticated as " + server.getAuthorizationID());
+ subject.getPrincipals().add(new UsernamePrincipal(server.getAuthorizationID()));
+ return new AuthenticationResult(subject);
+ }
+ else
+ {
+ return new AuthenticationResult(challenge, AuthenticationResult.AuthenticationStatus.CONTINUE);
+ }
+ }
+ catch (SaslException e)
+ {
+ return new AuthenticationResult(AuthenticationResult.AuthenticationStatus.ERROR, e);
+ }
+ }
+
+ @Override
+ public AuthenticationResult authenticate(String username, String password)
+ {
+
+ try
+ {
+ return doLDAPNameAuthentication(getNameFromId(username), password);
+ }
+ catch (NamingException e)
+ {
+
+ return new AuthenticationResult(AuthenticationResult.AuthenticationStatus.ERROR, e);
+
+ }
+ }
+
+ private AuthenticationResult doLDAPNameAuthentication(String username, String password) throws NamingException
+ {
+ Hashtable<Object,Object> env = new Hashtable<Object,Object>();
+ env.put(Context.INITIAL_CONTEXT_FACTORY, _ldapContextFactory);
+ env.put(Context.PROVIDER_URL, _providerAuthURL);
+
+ env.put(Context.SECURITY_AUTHENTICATION, "simple");
+
+ env.put(Context.SECURITY_PRINCIPAL, username);
+ env.put(Context.SECURITY_CREDENTIALS, password);
+ DirContext ctx = new InitialDirContext(env);
+ ctx.close();
+ final Subject subject = new Subject();
+ subject.getPrincipals().add(new UsernamePrincipal(username));
+ return new AuthenticationResult(subject);
+ }
+
+ @Override
+ public void close()
+ {
+ }
+
+ @Override
+ public void configure(ConfigurationPlugin config) throws ConfigurationException
+ {
+ SimpleLDAPAuthenticationManagerConfiguration ldapConfig = (SimpleLDAPAuthenticationManagerConfiguration) config;
+
+ _ldapContextFactory = ldapConfig.getLDAPContextFactory();
+ _providerSearchURL = ldapConfig.getProviderSearchURL();
+ _providerAuthURL = ldapConfig.getProviderAuthURL();
+ _searchContext = ldapConfig.getSearchContext();
+ _searchFilter = ldapConfig.getSearchFilter();
+
+ Hashtable<String,Object> env = new Hashtable<String, Object>();
+ env.put(Context.INITIAL_CONTEXT_FACTORY, _ldapContextFactory);
+ env.put(Context.PROVIDER_URL, _providerSearchURL);
+ env.put(Context.SECURITY_AUTHENTICATION, "none");
+
+ try
+ {
+ new InitialDirContext(env);
+ }
+ catch (NamingException e)
+ {
+ throw new ConfigurationException("Unable to establish anonymous connection to the ldap server at " + _providerSearchURL, e);
+ }
+ }
+
+ private class PlainCallbackHandler implements CallbackHandler
+ {
+
+ @Override
+ public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException
+ {
+ String name = null;
+ String password = null;
+ AuthenticationResult authenticated = null;
+ for(Callback callback : callbacks)
+ {
+ if (callback instanceof NameCallback)
+ {
+ String id = ((NameCallback) callback).getDefaultName();
+ try
+ {
+ name = getNameFromId(id);
+ }
+ catch (NamingException e)
+ {
+ _logger.info("SASL Authentication Error", e);
+ }
+ if(password != null)
+ {
+ try
+ {
+ authenticated = doLDAPNameAuthentication(name, password);
+
+ }
+ catch (NamingException e)
+ {
+ authenticated = new AuthenticationResult(AuthenticationResult.AuthenticationStatus.ERROR, e);
+ }
+ }
+ }
+ else if (callback instanceof PlainPasswordCallback)
+ {
+ password = ((PlainPasswordCallback)callback).getPlainPassword();
+ if(name != null)
+ {
+ try
+ {
+ authenticated = doLDAPNameAuthentication(name, password);
+ if(authenticated.getStatus()== AuthenticationResult.AuthenticationStatus.SUCCESS)
+ {
+ ((PlainPasswordCallback)callback).setAuthenticated(true);
+ }
+ }
+ catch (NamingException e)
+ {
+ authenticated = new AuthenticationResult(AuthenticationResult.AuthenticationStatus.ERROR, e);
+ }
+ }
+ }
+ else if (callback instanceof AuthorizeCallback)
+ {
+ ((AuthorizeCallback) callback).setAuthorized(authenticated != null && authenticated.getStatus() == AuthenticationResult.AuthenticationStatus.SUCCESS);
+ }
+ else
+ {
+ throw new UnsupportedCallbackException(callback);
+ }
+ }
+ }
+ }
+
+ private String getNameFromId(String id) throws NamingException
+ {
+ Hashtable<Object,Object> env = new Hashtable<Object,Object>();
+ env.put(Context.INITIAL_CONTEXT_FACTORY, _ldapContextFactory);
+ env.put(Context.PROVIDER_URL, _providerSearchURL);
+
+
+ env.put(Context.SECURITY_AUTHENTICATION, "none");
+ DirContext ctx = null;
+
+ ctx = new InitialDirContext(env);
+
+ try
+ {
+ SearchControls searchControls = new SearchControls();
+ searchControls.setReturningAttributes(new String[] {});
+ searchControls.setCountLimit(1l);
+ searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);
+ NamingEnumeration<?> namingEnum = null;
+ String name = null;
+
+ namingEnum = ctx.search(_searchContext, _searchFilter, new String[] { id }, searchControls);
+ if(namingEnum.hasMore())
+ {
+ SearchResult result = (SearchResult) namingEnum.next();
+ name = result.getNameInNamespace();
+ }
+ return name;
+ }
+ finally
+ {
+ ctx.close();
+ }
+
+ }
+}
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 e27fd99f90..2e21cfbb07 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,6 +20,9 @@
*/
package org.apache.qpid.server.security.auth.rmi;
+import java.net.SocketAddress;
+
+import org.apache.qpid.server.registry.ApplicationRegistry;
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;
@@ -37,11 +40,13 @@ public class RMIPasswordAuthenticator implements JMXAuthenticator
static final String INVALID_CREDENTIALS = "Invalid user details supplied";
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 SocketAddress _socketAddress;
- public RMIPasswordAuthenticator()
+ public RMIPasswordAuthenticator(SocketAddress socketAddress)
{
+ _socketAddress = socketAddress;
}
public void setAuthenticationManager(final AuthenticationManager authenticationManager)
@@ -79,11 +84,25 @@ public class RMIPasswordAuthenticator implements JMXAuthenticator
{
throw new SecurityException(SHOULD_BE_NON_NULL);
}
-
+
// Verify that an AuthenticationManager has been set.
if (_authenticationManager == null)
{
- throw new SecurityException(UNABLE_TO_LOOKUP);
+ try
+ {
+ if(ApplicationRegistry.getInstance().getAuthenticationManager(_socketAddress) != null)
+ {
+ _authenticationManager = ApplicationRegistry.getInstance().getAuthenticationManager(_socketAddress);
+ }
+ else
+ {
+ throw new SecurityException(UNABLE_TO_LOOKUP);
+ }
+ }
+ catch(IllegalStateException e)
+ {
+ throw new SecurityException(UNABLE_TO_LOOKUP);
+ }
}
final AuthenticationResult result = _authenticationManager.authenticate(username, password);
diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/external/ExternalSaslServer.java b/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/external/ExternalSaslServer.java
new file mode 100644
index 0000000000..9c2bca2d0b
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/external/ExternalSaslServer.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.server.security.auth.sasl.external;
+
+import java.security.Principal;
+import javax.security.sasl.SaslException;
+import javax.security.sasl.SaslServer;
+
+
+public class ExternalSaslServer implements SaslServer
+{
+ public static final String MECHANISM = "EXTERNAL";
+
+ private boolean _complete = false;
+ private final Principal _externalPrincipal;
+
+ public ExternalSaslServer(Principal externalPrincipal)
+ {
+ _externalPrincipal = externalPrincipal;
+ }
+
+ public String getMechanismName()
+ {
+ return MECHANISM;
+ }
+
+ public byte[] evaluateResponse(byte[] response) throws SaslException
+ {
+ _complete = true;
+ return null;
+ }
+
+ public boolean isComplete()
+ {
+ return _complete;
+ }
+
+ public String getAuthorizationID()
+ {
+ return null;
+ }
+
+ public byte[] unwrap(byte[] incoming, int offset, int len) throws SaslException
+ {
+ throw new SaslException("Unsupported operation");
+ }
+
+ public byte[] wrap(byte[] outgoing, int offset, int len) throws SaslException
+ {
+ throw new SaslException("Unsupported operation");
+ }
+
+ public Object getNegotiatedProperty(String propName)
+ {
+ return null;
+ }
+
+ public void dispose() throws SaslException
+ {
+ }
+
+ public Principal getAuthenticatedPrincipal()
+ {
+ return _externalPrincipal;
+ }
+} \ No newline at end of file
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 f97b77a4fe..f352bbdd2c 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
@@ -32,7 +32,9 @@ import org.apache.qpid.protocol.AMQConstant;
import org.apache.qpid.protocol.AMQMethodEvent;
import org.apache.qpid.protocol.AMQMethodListener;
import org.apache.qpid.server.protocol.AMQProtocolSession;
+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.virtualhost.VirtualHostRegistry;
import java.util.concurrent.CopyOnWriteArraySet;
@@ -61,6 +63,18 @@ public class AMQStateManager implements AMQMethodListener
}
+ /**
+ * Get the ApplicationRegistry associated with this AMQStateManager
+ *
+ * returns the application registry associated with the VirtualHostRegistry of the AMQStateManager
+ *
+ * @return the ApplicationRegistry
+ */
+ public IApplicationRegistry getApplicationRegistry()
+ {
+ return _virtualHostRegistry.getApplicationRegistry();
+ }
+
public AMQState getCurrentState()
{
return _currentState;
@@ -142,4 +156,14 @@ public class AMQStateManager implements AMQMethodListener
SecurityManager.setThreadSubject(_protocolSession.getAuthorizedSubject());
return _protocolSession;
}
+
+ /**
+ * Get the AuthenticationManager associated with the ProtocolSession of the AMQStateManager
+ *
+ * @return the AuthenticationManager
+ */
+ public AuthenticationManager getAuthenticationManager()
+ {
+ return getApplicationRegistry().getAuthenticationManager(getProtocolSession().getLocalAddress());
+ }
}
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
index 2bd17cfa2f..f382f90010 100644
--- 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
@@ -33,8 +33,7 @@ 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);
@@ -78,11 +77,6 @@ public class StatisticsCounter
public void registerEvent(long value, long timestamp)
{
- if (DISABLE_STATISTICS)
- {
- return;
- }
-
long thisSample = (timestamp / _period);
synchronized (this)
{
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
index 36fec4025a..37d87bb628 100644
--- 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
@@ -103,16 +103,4 @@ public interface StatisticsGatherer
* 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/ConfigurationRecoveryHandler.java b/java/broker/src/main/java/org/apache/qpid/server/store/ConfigurationRecoveryHandler.java
index 1307b1dbd4..ede01d247e 100755
--- a/java/broker/src/main/java/org/apache/qpid/server/store/ConfigurationRecoveryHandler.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/store/ConfigurationRecoveryHandler.java
@@ -28,20 +28,21 @@ import java.util.UUID;
public interface ConfigurationRecoveryHandler
{
- QueueRecoveryHandler begin(MessageStore store);
+ ExchangeRecoveryHandler begin(MessageStore store);
- public static interface QueueRecoveryHandler
+ public static interface ExchangeRecoveryHandler
{
- void queue(UUID id, String queueName, String owner, boolean exclusive, FieldTable arguments);
- ExchangeRecoveryHandler completeQueueRecovery();
+ void exchange(UUID id, String exchangeName, String type, boolean autoDelete);
+ QueueRecoveryHandler completeExchangeRecovery();
}
- public static interface ExchangeRecoveryHandler
+ public static interface QueueRecoveryHandler
{
- void exchange(UUID id, String exchangeName, String type, boolean autoDelete);
- BindingRecoveryHandler completeExchangeRecovery();
+ void queue(UUID id, String queueName, String owner, boolean exclusive, FieldTable arguments, UUID alternateExchangeId);
+ BindingRecoveryHandler completeQueueRecovery();
}
+
public static interface BindingRecoveryHandler
{
void binding(UUID bindingId, UUID exchangeId, UUID queueId, String bindingName, ByteBuffer buf);
diff --git a/java/broker/src/main/java/org/apache/qpid/server/store/ConfiguredObjectHelper.java b/java/broker/src/main/java/org/apache/qpid/server/store/ConfiguredObjectHelper.java
index 1a67fdf540..7356e1ae83 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/store/ConfiguredObjectHelper.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/store/ConfiguredObjectHelper.java
@@ -40,12 +40,7 @@ import org.apache.qpid.server.util.MapJsonSerializer;
public class ConfiguredObjectHelper
{
- /**
- * Name of queue attribute to store queue creation arguments.
- * <p>
- * This attribute is not defined yet on Queue configured object interface.
- */
- private static final String QUEUE_ARGUMENTS = "ARGUMENTS";
+
private MapJsonSerializer _serializer = new MapJsonSerializer();
@@ -57,14 +52,15 @@ public class ConfiguredObjectHelper
String queueName = (String) attributeMap.get(Queue.NAME);
String owner = (String) attributeMap.get(Queue.OWNER);
boolean exclusive = (Boolean) attributeMap.get(Queue.EXCLUSIVE);
+ UUID alternateExchangeId = attributeMap.get(Queue.ALTERNATE_EXCHANGE) == null ? null : UUID.fromString((String)attributeMap.get(Queue.ALTERNATE_EXCHANGE));
@SuppressWarnings("unchecked")
- Map<String, Object> queueArgumentsMap = (Map<String, Object>) attributeMap.get(QUEUE_ARGUMENTS);
+ Map<String, Object> queueArgumentsMap = (Map<String, Object>) attributeMap.get(Queue.ARGUMENTS);
FieldTable arguments = null;
if (queueArgumentsMap != null)
{
arguments = FieldTable.convertToFieldTable(queueArgumentsMap);
}
- qrh.queue(configuredObject.getId(), queueName, owner, exclusive, arguments);
+ qrh.queue(configuredObject.getId(), queueName, owner, exclusive, arguments, alternateExchangeId);
}
}
@@ -73,6 +69,24 @@ public class ConfiguredObjectHelper
Map<String, Object> attributesMap = _serializer.deserialize(queueRecord.getAttributes());
attributesMap.put(Queue.NAME, queue.getName());
attributesMap.put(Queue.EXCLUSIVE, queue.isExclusive());
+ if (queue.getAlternateExchange() != null)
+ {
+ attributesMap.put(Queue.ALTERNATE_EXCHANGE, queue.getAlternateExchange().getId());
+ }
+ else
+ {
+ attributesMap.remove(Queue.ALTERNATE_EXCHANGE);
+ }
+ if (attributesMap.containsKey(Queue.ARGUMENTS))
+ {
+ // We wouldn't need this if createQueueConfiguredObject took only AMQQueue
+ Map<String, Object> currentArgs = (Map<String, Object>) attributesMap.get(Queue.ARGUMENTS);
+ currentArgs.putAll(queue.getArguments());
+ }
+ else
+ {
+ attributesMap.put(Queue.ARGUMENTS, queue.getArguments());
+ }
String newJson = _serializer.serialize(attributesMap);
ConfiguredObjectRecord newQueueRecord = new ConfiguredObjectRecord(queue.getId(), queueRecord.getType(), newJson);
return newQueueRecord;
@@ -84,9 +98,15 @@ public class ConfiguredObjectHelper
attributesMap.put(Queue.NAME, queue.getName());
attributesMap.put(Queue.OWNER, AMQShortString.toString(queue.getOwner()));
attributesMap.put(Queue.EXCLUSIVE, queue.isExclusive());
+ if (queue.getAlternateExchange() != null)
+ {
+ attributesMap.put(Queue.ALTERNATE_EXCHANGE, queue.getAlternateExchange().getId());
+ }
+ // TODO KW i think the arguments could come from the queue itself removing the need for the parameter arguments.
+ // It would also do away with the need for the if/then/else within updateQueueConfiguredObject
if (arguments != null)
{
- attributesMap.put(QUEUE_ARGUMENTS, FieldTable.convertToMap(arguments));
+ attributesMap.put(Queue.ARGUMENTS, FieldTable.convertToMap(arguments));
}
String json = _serializer.serialize(attributesMap);
ConfiguredObjectRecord configuredObject = new ConfiguredObjectRecord(queue.getId(), Queue.class.getName(), json);
diff --git a/java/broker/src/main/java/org/apache/qpid/server/store/Event.java b/java/broker/src/main/java/org/apache/qpid/server/store/Event.java
index bbde11ab4c..c681126c11 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/store/Event.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/store/Event.java
@@ -23,10 +23,20 @@ public enum Event
{
BEFORE_INIT,
AFTER_INIT,
+
BEFORE_ACTIVATE,
AFTER_ACTIVATE,
+
BEFORE_PASSIVATE,
AFTER_PASSIVATE,
+
BEFORE_CLOSE,
- AFTER_CLOSE
+ AFTER_CLOSE,
+
+ BEFORE_QUIESCE,
+ AFTER_QUIESCE,
+ BEFORE_RESTART,
+
+ PERSISTENT_MESSAGE_SIZE_OVERFULL,
+ PERSISTENT_MESSAGE_SIZE_UNDERFULL
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/store/EventManager.java b/java/broker/src/main/java/org/apache/qpid/server/store/EventManager.java
index 21ae3924b8..bf3de2611d 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/store/EventManager.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/store/EventManager.java
@@ -24,9 +24,12 @@ import java.util.EnumMap;
import java.util.List;
import java.util.Map;
+import org.apache.log4j.Logger;
+
public class EventManager
{
private Map<Event, List<EventListener>> _listeners = new EnumMap<Event, List<EventListener>> (Event.class);
+ private static final Logger _LOGGER = Logger.getLogger(EventManager.class);
public synchronized void addEventListener(EventListener listener, Event... events)
{
@@ -46,6 +49,11 @@ public class EventManager
{
if (_listeners.containsKey(event))
{
+ if(_LOGGER.isDebugEnabled())
+ {
+ _LOGGER.debug("Received event " + event);
+ }
+
for (EventListener listener : _listeners.get(event))
{
listener.event(event);
diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/exceptions/ManagementConsoleException.java b/java/broker/src/main/java/org/apache/qpid/server/store/HAMessageStore.java
index 17c127c01a..59483751ca 100644
--- a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/exceptions/ManagementConsoleException.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/store/HAMessageStore.java
@@ -1,5 +1,4 @@
/*
- *
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
@@ -18,14 +17,13 @@
* under the License.
*
*/
+package org.apache.qpid.server.store;
-package org.apache.qpid.management.ui.exceptions;
-
-@SuppressWarnings("serial")
-public class ManagementConsoleException extends Exception
+public interface HAMessageStore extends MessageStore
{
- public ManagementConsoleException(String message)
- {
- super(message);
- }
+ /**
+ * Used to indicate that a store requires to make itself unavailable for read and read/write
+ * operations.
+ */
+ void passivate();
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/store/MemoryMessageStore.java b/java/broker/src/main/java/org/apache/qpid/server/store/MemoryMessageStore.java
index 59624b7a75..262d7d0213 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/store/MemoryMessageStore.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/store/MemoryMessageStore.java
@@ -83,19 +83,19 @@ public class MemoryMessageStore extends NullMessageStore
@Override
public void configureConfigStore(String name, ConfigurationRecoveryHandler recoveryHandler, Configuration config) throws Exception
{
- _stateManager.attainState(State.CONFIGURING);
+ _stateManager.attainState(State.INITIALISING);
}
@Override
public void configureMessageStore(String name, MessageStoreRecoveryHandler recoveryHandler, TransactionLogRecoveryHandler tlogRecoveryHandler, Configuration config) throws Exception
{
- _stateManager.attainState(State.CONFIGURED);
+ _stateManager.attainState(State.INITIALISED);
}
@Override
public void activate() throws Exception
{
- _stateManager.attainState(State.RECOVERING);
+ _stateManager.attainState(State.ACTIVATING);
_stateManager.attainState(State.ACTIVE);
}
@@ -134,4 +134,10 @@ public class MemoryMessageStore extends NullMessageStore
{
_eventManager.addEventListener(eventListener, events);
}
+
+ @Override
+ public String getStoreType()
+ {
+ return "Memory";
+ }
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/store/MessageStore.java b/java/broker/src/main/java/org/apache/qpid/server/store/MessageStore.java
index cf08ee00ff..0acaf164d9 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/store/MessageStore.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/store/MessageStore.java
@@ -67,4 +67,6 @@ public interface MessageStore extends DurableConfigurationStore
void addEventListener(EventListener eventListener, Event... events);
String getStoreLocation();
+
+ String getStoreType();
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/store/MessageStoreConstants.java b/java/broker/src/main/java/org/apache/qpid/server/store/MessageStoreConstants.java
index aba7456a44..728da23f28 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/store/MessageStoreConstants.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/store/MessageStoreConstants.java
@@ -23,5 +23,7 @@ public class MessageStoreConstants
{
public static final String ENVIRONMENT_PATH_PROPERTY = "environment-path";
+ public static final String OVERFULL_SIZE_PROPERTY = "overfull-size";
+ public static final String UNDERFULL_SIZE_PROPERTY = "underfull-size";
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/store/NullMessageStore.java b/java/broker/src/main/java/org/apache/qpid/server/store/NullMessageStore.java
index 34c7d2d933..be08e309e6 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/store/NullMessageStore.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/store/NullMessageStore.java
@@ -28,7 +28,7 @@ import org.apache.qpid.server.federation.Bridge;
import org.apache.qpid.server.federation.BrokerLink;
import org.apache.qpid.server.queue.AMQQueue;
-public class NullMessageStore implements MessageStore
+public abstract class NullMessageStore implements MessageStore
{
@Override
public void configureConfigStore(String name,
diff --git a/java/broker/src/main/java/org/apache/qpid/server/store/OperationalLoggingListener.java b/java/broker/src/main/java/org/apache/qpid/server/store/OperationalLoggingListener.java
index caff17daa5..4ab1a3ab05 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/store/OperationalLoggingListener.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/store/OperationalLoggingListener.java
@@ -33,7 +33,14 @@ public class OperationalLoggingListener implements EventListener
private OperationalLoggingListener(final MessageStore store, LogSubject logSubject)
{
_logSubject = logSubject;
- store.addEventListener(this, Event.BEFORE_INIT, Event.AFTER_INIT, Event.BEFORE_ACTIVATE, Event.AFTER_ACTIVATE, Event.AFTER_CLOSE);
+ store.addEventListener(this,
+ Event.BEFORE_INIT,
+ Event.AFTER_INIT,
+ Event.BEFORE_ACTIVATE,
+ Event.AFTER_ACTIVATE,
+ Event.AFTER_CLOSE,
+ Event.PERSISTENT_MESSAGE_SIZE_OVERFULL,
+ Event.PERSISTENT_MESSAGE_SIZE_UNDERFULL);
_store = store;
}
@@ -62,7 +69,13 @@ public class OperationalLoggingListener implements EventListener
case AFTER_CLOSE:
CurrentActor.get().message(_logSubject,MessageStoreMessages.CLOSED());
break;
-
+ case PERSISTENT_MESSAGE_SIZE_OVERFULL:
+ CurrentActor.get().message(_logSubject,MessageStoreMessages.OVERFULL());
+ break;
+ case PERSISTENT_MESSAGE_SIZE_UNDERFULL:
+ CurrentActor.get().message(_logSubject,MessageStoreMessages.UNDERFULL());
+ break;
+
}
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/store/State.java b/java/broker/src/main/java/org/apache/qpid/server/store/State.java
index 7cbdede85e..2783637b2a 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/store/State.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/store/State.java
@@ -20,19 +20,30 @@
*/
package org.apache.qpid.server.store;
+import org.apache.qpid.server.configuration.ConfiguredObject;
+
public enum State
{
-
+ /** The initial state of the store. In practice, the store immediately transitions to the subsequent states. */
INITIAL,
- CONFIGURING,
- CONFIGURED,
- RECOVERING,
+
+ INITIALISING,
+ /**
+ * The initial set-up of the store has completed.
+ * If the store is persistent, it has not yet loaded configuration for {@link ConfiguredObject}'s from disk.
+ *
+ * From the point of view of the user, the store is essentially stopped.
+ */
+ INITIALISED,
+
+ ACTIVATING,
ACTIVE,
- QUIESCING,
- QUIESCED,
+
CLOSING,
- CLOSED;
-
+ CLOSED,
+ QUIESCING,
+ /** The virtual host (and implicitly also the store) has been manually paused by the user to allow configuration changes to take place */
+ QUIESCED;
} \ No newline at end of file
diff --git a/java/broker/src/main/java/org/apache/qpid/server/store/StateManager.java b/java/broker/src/main/java/org/apache/qpid/server/store/StateManager.java
index 5998be5bb6..613b329beb 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/store/StateManager.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/store/StateManager.java
@@ -24,6 +24,8 @@ package org.apache.qpid.server.store;
import java.util.EnumMap;
import java.util.Map;
+import org.apache.qpid.server.store.StateManager.Transition;
+
public class StateManager
{
private State _state = State.INITIAL;
@@ -70,16 +72,23 @@ public class StateManager
}
- public static final Transition CONFIGURE = new Transition(State.INITIAL, State.CONFIGURING, Event.BEFORE_INIT);
- public static final Transition CONFIGURE_COMPLETE = new Transition(State.CONFIGURING, State.CONFIGURED, Event.AFTER_INIT);
- public static final Transition RECOVER = new Transition(State.CONFIGURED, State.RECOVERING, Event.BEFORE_ACTIVATE);
- public static final Transition ACTIVATE = new Transition(State.RECOVERING, State.ACTIVE, Event.AFTER_ACTIVATE);
+ public static final Transition INITIALISE = new Transition(State.INITIAL, State.INITIALISING, Event.BEFORE_INIT);
+ public static final Transition INITALISE_COMPLETE = new Transition(State.INITIALISING, State.INITIALISED, Event.AFTER_INIT);
+
+ public static final Transition ACTIVATE = new Transition(State.INITIALISED, State.ACTIVATING, Event.BEFORE_ACTIVATE);
+ public static final Transition ACTIVATE_COMPLETE = new Transition(State.ACTIVATING, State.ACTIVE, Event.AFTER_ACTIVATE);
+
+ public static final Transition CLOSE_INITIALISED = new Transition(State.INITIALISED, State.CLOSING, Event.BEFORE_CLOSE);;
public static final Transition CLOSE_ACTIVE = new Transition(State.ACTIVE, State.CLOSING, Event.BEFORE_CLOSE);
public static final Transition CLOSE_QUIESCED = new Transition(State.QUIESCED, State.CLOSING, Event.BEFORE_CLOSE);
public static final Transition CLOSE_COMPLETE = new Transition(State.CLOSING, State.CLOSED, Event.AFTER_CLOSE);
- public static final Transition QUIESCE = new Transition(State.ACTIVE, State.QUIESCING, Event.BEFORE_PASSIVATE);
- public static final Transition QUIESCE_COMPLETE = new Transition(State.QUIESCING, State.QUIESCED, Event.BEFORE_PASSIVATE);
- public static final Transition RESTART = new Transition(State.QUIESCED, State.RECOVERING, Event.BEFORE_ACTIVATE);
+
+ public static final Transition PASSIVATE = new Transition(State.ACTIVE, State.INITIALISED, Event.BEFORE_PASSIVATE);
+
+ public static final Transition QUIESCE = new Transition(State.ACTIVE, State.QUIESCING, Event.BEFORE_QUIESCE);
+ public static final Transition QUIESCE_COMPLETE = new Transition(State.QUIESCING, State.QUIESCED, Event.AFTER_QUIESCE);
+
+ public static final Transition RESTART = new Transition(State.QUIESCED, State.ACTIVATING, Event.BEFORE_RESTART);
public StateManager(final EventManager eventManager)
@@ -105,16 +114,6 @@ public class StateManager
return _state;
}
- public synchronized void stateTransition(final State current, final State desired)
- {
- if (_state != current)
- {
- throw new IllegalStateException("Cannot transition to the state: " + desired + "; need to be in state: " + current
- + "; currently in state: " + _state);
- }
- attainState(desired);
- }
-
public synchronized void attainState(State desired)
{
Transition transition = null;
diff --git a/java/broker/src/main/java/org/apache/qpid/server/store/derby/DerbyMessageStore.java b/java/broker/src/main/java/org/apache/qpid/server/store/derby/DerbyMessageStore.java
index 0371cdcfcb..154d7e6535 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/store/derby/DerbyMessageStore.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/store/derby/DerbyMessageStore.java
@@ -31,6 +31,7 @@ import java.lang.ref.SoftReference;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.sql.Blob;
+import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.Driver;
import java.sql.DriverManager;
@@ -59,6 +60,7 @@ import org.apache.qpid.server.federation.BrokerLink;
import org.apache.qpid.server.message.EnqueableMessage;
import org.apache.qpid.server.queue.AMQQueue;
import org.apache.qpid.server.store.ConfigurationRecoveryHandler;
+import org.apache.qpid.server.store.ConfigurationRecoveryHandler.BrokerLinkRecoveryHandler;
import org.apache.qpid.server.store.ConfiguredObjectHelper;
import org.apache.qpid.server.store.ConfiguredObjectRecord;
import org.apache.qpid.server.store.Event;
@@ -77,6 +79,9 @@ import org.apache.qpid.server.store.StoredMessage;
import org.apache.qpid.server.store.Transaction;
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;
/**
* An implementation of a {@link MessageStore} that uses Apache Derby as the persistence
@@ -111,6 +116,7 @@ public class DerbyMessageStore implements MessageStore
private static Class<Driver> DRIVER_CLASS;
+ public static final String MEMORY_STORE_LOCATION = ":memory:";
private final AtomicLong _messageId = new AtomicLong(0);
private AtomicBoolean _closed = new AtomicBoolean(false);
@@ -230,10 +236,17 @@ public class DerbyMessageStore implements MessageStore
private static final String DERBY_SINGLE_DB_SHUTDOWN_CODE = "08006";
+ private static final String DERBY_STORE_TYPE = "DERBY";
+
private final StateManager _stateManager;
-
+
private final EventManager _eventManager = new EventManager();
+ private long _totalStoreSize;
+ private boolean _limitBusted;
+ private long _persistentSizeLowThreshold;
+ private long _persistentSizeHighThreshold;
+
private MessageStoreRecoveryHandler _messageRecoveryHandler;
private TransactionLogRecoveryHandler _tlogRecoveryHandler;
@@ -253,7 +266,7 @@ public class DerbyMessageStore implements MessageStore
ConfigurationRecoveryHandler configRecoveryHandler,
Configuration storeConfiguration) throws Exception
{
- _stateManager.attainState(State.CONFIGURING);
+ _stateManager.attainState(State.INITIALISING);
_configRecoveryHandler = configRecoveryHandler;
commonConfiguration(name, storeConfiguration);
@@ -269,13 +282,13 @@ public class DerbyMessageStore implements MessageStore
_tlogRecoveryHandler = tlogRecoveryHandler;
_messageRecoveryHandler = recoveryHandler;
- _stateManager.attainState(State.CONFIGURED);
+ _stateManager.attainState(State.INITIALISED);
}
@Override
public void activate() throws Exception
{
- _stateManager.attainState(State.RECOVERING);
+ _stateManager.attainState(State.ACTIVATING);
// this recovers durable exchanges, queues, and bindings
recoverConfiguration(_configRecoveryHandler);
@@ -296,19 +309,39 @@ public class DerbyMessageStore implements MessageStore
final String databasePath = storeConfiguration.getString(MessageStoreConstants.ENVIRONMENT_PATH_PROPERTY, System.getProperty("QPID_WORK")
+ File.separator + "derbyDB");
- File environmentPath = new File(databasePath);
- if (!environmentPath.exists())
+ if(!MEMORY_STORE_LOCATION.equals(databasePath))
{
- if (!environmentPath.mkdirs())
+ File environmentPath = new File(databasePath);
+ if (!environmentPath.exists())
{
- throw new IllegalArgumentException("Environment path " + environmentPath + " could not be read or created. "
- + "Ensure the path is correct and that the permissions are correct.");
+ 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.");
+ }
}
}
_storeLocation = databasePath;
+ _persistentSizeHighThreshold = storeConfiguration.getLong(MessageStoreConstants.OVERFULL_SIZE_PROPERTY, -1l);
+ _persistentSizeLowThreshold = storeConfiguration.getLong(MessageStoreConstants.UNDERFULL_SIZE_PROPERTY, _persistentSizeHighThreshold);
+ if(_persistentSizeLowThreshold > _persistentSizeHighThreshold || _persistentSizeLowThreshold < 0l)
+ {
+ _persistentSizeLowThreshold = _persistentSizeHighThreshold;
+ }
+
createOrOpenDatabase(name, databasePath);
+
+ Connection conn = newAutoCommitConnection();;
+ try
+ {
+ _totalStoreSize = getSizeOnDisk(conn);
+ }
+ finally
+ {
+ conn.close();
+ }
}
private static synchronized void initialiseDriver() throws ClassNotFoundException
@@ -322,7 +355,7 @@ public class DerbyMessageStore implements MessageStore
private void createOrOpenDatabase(String name, final String environmentPath) throws SQLException
{
//FIXME this the _vhost name should not be added here, but derby wont use an empty directory as was possibly just created.
- _connectionURL = "jdbc:derby:" + environmentPath + "/" + name + ";create=true";
+ _connectionURL = "jdbc:derby" + (environmentPath.equals(MEMORY_STORE_LOCATION) ? environmentPath : ":" + environmentPath + "/") + name + ";create=true";
Connection conn = newAutoCommitConnection();
@@ -529,16 +562,17 @@ public class DerbyMessageStore implements MessageStore
try
{
List<ConfiguredObjectRecord> configuredObjects = loadConfiguredObjects();
- ConfigurationRecoveryHandler.QueueRecoveryHandler qrh = recoveryHandler.begin(this);
- _configuredObjectHelper.recoverQueues(qrh, configuredObjects);
- ConfigurationRecoveryHandler.ExchangeRecoveryHandler erh = qrh.completeQueueRecovery();
+ ExchangeRecoveryHandler erh = recoveryHandler.begin(this);
_configuredObjectHelper.recoverExchanges(erh, configuredObjects);
- ConfigurationRecoveryHandler.BindingRecoveryHandler brh = erh.completeExchangeRecovery();
+ QueueRecoveryHandler qrh = erh.completeExchangeRecovery();
+ _configuredObjectHelper.recoverQueues(qrh, configuredObjects);
+
+ BindingRecoveryHandler brh = qrh.completeQueueRecovery();
_configuredObjectHelper.recoverBindings(brh, configuredObjects);
- ConfigurationRecoveryHandler.BrokerLinkRecoveryHandler lrh = brh.completeBindingRecovery();
+ BrokerLinkRecoveryHandler lrh = brh.completeBindingRecovery();
recoverBrokerLinks(lrh);
}
catch (SQLException e)
@@ -689,7 +723,7 @@ public class DerbyMessageStore implements MessageStore
public void close() throws Exception
{
_closed.getAndSet(true);
- _stateManager.stateTransition(State.ACTIVE, State.CLOSING);
+ _stateManager.attainState(State.CLOSING);
try
{
@@ -710,7 +744,7 @@ public class DerbyMessageStore implements MessageStore
}
}
- _stateManager.stateTransition(State.CLOSING, State.CLOSED);
+ _stateManager.attainState(State.CLOSED);
}
@Override
@@ -956,8 +990,8 @@ public class DerbyMessageStore implements MessageStore
try
{
- stmt.setLong(1, link.getId().getLeastSignificantBits());
- stmt.setLong(2, link.getId().getMostSignificantBits());
+ stmt.setLong(1, link.getQMFId().getLeastSignificantBits());
+ stmt.setLong(2, link.getQMFId().getMostSignificantBits());
ResultSet rs = stmt.executeQuery();
try
{
@@ -970,8 +1004,8 @@ public class DerbyMessageStore implements MessageStore
try
{
- insertStmt.setLong(1, link.getId().getLeastSignificantBits());
- insertStmt.setLong(2, link.getId().getMostSignificantBits());
+ insertStmt.setLong(1, link.getQMFId().getLeastSignificantBits());
+ insertStmt.setLong(2, link.getQMFId().getMostSignificantBits());
insertStmt.setLong(3, link.getCreateTime());
byte[] argumentBytes = convertStringMapToBytes(link.getArguments());
@@ -1048,8 +1082,8 @@ public class DerbyMessageStore implements MessageStore
{
conn = newAutoCommitConnection();
stmt = conn.prepareStatement(DELETE_FROM_LINKS);
- stmt.setLong(1, link.getId().getLeastSignificantBits());
- stmt.setLong(2, link.getId().getMostSignificantBits());
+ stmt.setLong(1, link.getQMFId().getLeastSignificantBits());
+ stmt.setLong(2, link.getQMFId().getMostSignificantBits());
int results = stmt.executeUpdate();
if (results == 0)
@@ -1085,7 +1119,7 @@ public class DerbyMessageStore implements MessageStore
try
{
- UUID id = bridge.getId();
+ UUID id = bridge.getQMFId();
stmt.setLong(1, id.getLeastSignificantBits());
stmt.setLong(2, id.getMostSignificantBits());
ResultSet rs = stmt.executeQuery();
@@ -1105,7 +1139,7 @@ public class DerbyMessageStore implements MessageStore
insertStmt.setLong(3, bridge.getCreateTime());
- UUID linkId = bridge.getLink().getId();
+ UUID linkId = bridge.getLink().getQMFId();
insertStmt.setLong(4, linkId.getLeastSignificantBits());
insertStmt.setLong(5, linkId.getMostSignificantBits());
@@ -1151,8 +1185,8 @@ public class DerbyMessageStore implements MessageStore
{
conn = newAutoCommitConnection();
stmt = conn.prepareStatement(DELETE_FROM_BRIDGES);
- stmt.setLong(1, bridge.getId().getLeastSignificantBits());
- stmt.setLong(2, bridge.getId().getMostSignificantBits());
+ stmt.setLong(1, bridge.getQMFId().getLeastSignificantBits());
+ stmt.setLong(2, bridge.getQMFId().getMostSignificantBits());
int results = stmt.executeUpdate();
if (results == 0)
@@ -1541,7 +1575,7 @@ public class DerbyMessageStore implements MessageStore
buf = buf.slice();
MessageMetaDataType type = MessageMetaDataType.values()[dataAsBytes[0]];
StorableMessageMetaData metaData = type.getFactory().createMetaData(buf);
- StoredDerbyMessage message = new StoredDerbyMessage(messageId, metaData, false);
+ StoredDerbyMessage message = new StoredDerbyMessage(messageId, metaData, true);
messageHandler.message(message);
}
@@ -1921,6 +1955,7 @@ public class DerbyMessageStore implements MessageStore
private class DerbyTransaction implements Transaction
{
private final ConnectionWrapper _connWrapper;
+ private int _storeSizeIncrease;
private DerbyTransaction()
@@ -1938,18 +1973,19 @@ public class DerbyMessageStore implements MessageStore
@Override
public void enqueueMessage(TransactionLogResource queue, EnqueableMessage message) throws AMQStoreException
{
- if(message.getStoredMessage() instanceof StoredDerbyMessage)
+ final StoredMessage storedMessage = message.getStoredMessage();
+ if(storedMessage instanceof StoredDerbyMessage)
{
try
{
- ((StoredDerbyMessage)message.getStoredMessage()).store(_connWrapper.getConnection());
+ ((StoredDerbyMessage) storedMessage).store(_connWrapper.getConnection());
}
catch (SQLException e)
{
throw new AMQStoreException("Exception on enqueuing message " + _messageId, e);
}
}
-
+ _storeSizeIncrease += storedMessage.getMetaData().getContentSize();
DerbyMessageStore.this.enqueueMessage(_connWrapper, queue, message.getMessageNumber());
}
@@ -1964,12 +2000,15 @@ public class DerbyMessageStore implements MessageStore
public void commitTran() throws AMQStoreException
{
DerbyMessageStore.this.commitTran(_connWrapper);
+ storedSizeChange(_storeSizeIncrease);
}
@Override
public StoreFuture commitTranAsync() throws AMQStoreException
{
- return DerbyMessageStore.this.commitTranAsync(_connWrapper);
+ final StoreFuture storeFuture = DerbyMessageStore.this.commitTranAsync(_connWrapper);
+ storedSizeChange(_storeSizeIncrease);
+ return storeFuture;
}
@Override
@@ -1998,6 +2037,8 @@ public class DerbyMessageStore implements MessageStore
{
private final long _messageId;
+ private final boolean _isRecovered;
+
private StorableMessageMetaData _metaData;
private volatile SoftReference<StorableMessageMetaData> _metaDataRef;
private byte[] _data;
@@ -2006,21 +2047,21 @@ public class DerbyMessageStore implements MessageStore
StoredDerbyMessage(long messageId, StorableMessageMetaData metaData)
{
- this(messageId, metaData, true);
+ this(messageId, metaData, false);
}
StoredDerbyMessage(long messageId,
- StorableMessageMetaData metaData, boolean persist)
+ StorableMessageMetaData metaData, boolean isRecovered)
{
_messageId = messageId;
+ _isRecovered = isRecovered;
-
- _metaDataRef = new SoftReference<StorableMessageMetaData>(metaData);
- if(persist)
+ if(!_isRecovered)
{
_metaData = metaData;
}
+ _metaDataRef = new SoftReference<StorableMessageMetaData>(metaData);
}
@Override
@@ -2101,16 +2142,17 @@ public class DerbyMessageStore implements MessageStore
@Override
public synchronized StoreFuture flushToStore()
{
+ Connection conn = null;
try
{
- if(_metaData != null)
+ if(!stored())
{
- Connection conn = newConnection();
+ conn = newConnection();
store(conn);
conn.commit();
- conn.close();
+ storedSizeChange(getMetaData().getContentSize());
}
}
catch (SQLException e)
@@ -2121,12 +2163,24 @@ public class DerbyMessageStore implements MessageStore
}
throw new RuntimeException(e);
}
+ finally
+ {
+ closeConnection(conn);
+ }
return StoreFuture.IMMEDIATE_FUTURE;
}
+ @Override
+ public void remove()
+ {
+ int delta = getMetaData().getContentSize();
+ DerbyMessageStore.this.removeMessage(_messageId);
+ storedSizeChange(-delta);
+ }
+
private synchronized void store(final Connection conn) throws SQLException
{
- if(_metaData != null)
+ if (!stored())
{
try
{
@@ -2139,18 +2193,17 @@ public class DerbyMessageStore implements MessageStore
_metaData = null;
_data = null;
}
- }
- if(_logger.isDebugEnabled())
- {
- _logger.debug("Storing message " + _messageId + " to store");
+ if(_logger.isDebugEnabled())
+ {
+ _logger.debug("Storing message " + _messageId + " to store");
+ }
}
}
- @Override
- public void remove()
+ private boolean stored()
{
- DerbyMessageStore.this.removeMessage(_messageId);
+ return _metaData == null || _isRecovered;
}
}
@@ -2446,4 +2499,181 @@ public class DerbyMessageStore implements MessageStore
}
return results;
}
+
+ private synchronized void storedSizeChange(final int delta)
+ {
+ if(getPersistentSizeHighThreshold() > 0)
+ {
+ synchronized(this)
+ {
+ // the delta supplied is an approximation of a store size change. we don;t want to check the statistic every
+ // time, so we do so only when there's been enough change that it is worth looking again. We do this by
+ // assuming the total size will change by less than twice the amount of the message data change.
+ long newSize = _totalStoreSize += 3*delta;
+
+ Connection conn = null;
+ try
+ {
+
+ if(!_limitBusted && newSize > getPersistentSizeHighThreshold())
+ {
+ conn = newAutoCommitConnection();
+ _totalStoreSize = getSizeOnDisk(conn);
+ if(_totalStoreSize > getPersistentSizeHighThreshold())
+ {
+ _limitBusted = true;
+ _eventManager.notifyEvent(Event.PERSISTENT_MESSAGE_SIZE_OVERFULL);
+ }
+ }
+ else if(_limitBusted && newSize < getPersistentSizeLowThreshold())
+ {
+ long oldSize = _totalStoreSize;
+ conn = newAutoCommitConnection();
+ _totalStoreSize = getSizeOnDisk(conn);
+ if(oldSize <= _totalStoreSize)
+ {
+
+ reduceSizeOnDisk(conn);
+
+ _totalStoreSize = getSizeOnDisk(conn);
+ }
+
+ if(_totalStoreSize < getPersistentSizeLowThreshold())
+ {
+ _limitBusted = false;
+ _eventManager.notifyEvent(Event.PERSISTENT_MESSAGE_SIZE_UNDERFULL);
+ }
+
+
+ }
+ }
+ catch (SQLException e)
+ {
+ closeConnection(conn);
+ throw new RuntimeException("Exception will processing store size change", e);
+ }
+ }
+ }
+ }
+
+ private void reduceSizeOnDisk(Connection conn)
+ {
+ CallableStatement cs = null;
+ PreparedStatement stmt = null;
+ try
+ {
+ String tableQuery =
+ "SELECT S.SCHEMANAME, T.TABLENAME FROM SYS.SYSSCHEMAS S, SYS.SYSTABLES T WHERE S.SCHEMAID = T.SCHEMAID AND T.TABLETYPE='T'";
+ stmt = conn.prepareStatement(tableQuery);
+ ResultSet rs = null;
+
+ List<String> schemas = new ArrayList<String>();
+ List<String> tables = new ArrayList<String>();
+
+ try
+ {
+ rs = stmt.executeQuery();
+ while(rs.next())
+ {
+ schemas.add(rs.getString(1));
+ tables.add(rs.getString(2));
+ }
+ }
+ finally
+ {
+ if(rs != null)
+ {
+ rs.close();
+ }
+ }
+
+
+ cs = conn.prepareCall
+ ("CALL SYSCS_UTIL.SYSCS_COMPRESS_TABLE(?, ?, ?)");
+
+ for(int i = 0; i < schemas.size(); i++)
+ {
+ cs.setString(1, schemas.get(i));
+ cs.setString(2, tables.get(i));
+ cs.setShort(3, (short) 0);
+ cs.execute();
+ }
+ }
+ catch (SQLException e)
+ {
+ closeConnection(conn);
+ throw new RuntimeException("Error reducing on disk size", e);
+ }
+ finally
+ {
+ closePreparedStatement(stmt);
+ closePreparedStatement(cs);
+ }
+
+ }
+
+ private long getSizeOnDisk(Connection conn)
+ {
+ PreparedStatement stmt = null;
+ try
+ {
+ String sizeQuery = "SELECT SUM(T2.NUMALLOCATEDPAGES * T2.PAGESIZE) TOTALSIZE" +
+ " FROM " +
+ " SYS.SYSTABLES systabs," +
+ " TABLE (SYSCS_DIAG.SPACE_TABLE(systabs.tablename)) AS T2" +
+ " WHERE systabs.tabletype = 'T'";
+
+ stmt = conn.prepareStatement(sizeQuery);
+
+ ResultSet rs = null;
+ long size = 0l;
+
+ try
+ {
+ rs = stmt.executeQuery();
+ while(rs.next())
+ {
+ size = rs.getLong(1);
+ }
+ }
+ finally
+ {
+ if(rs != null)
+ {
+ rs.close();
+ }
+ }
+
+ return size;
+
+ }
+ catch (SQLException e)
+ {
+ closeConnection(conn);
+ throw new RuntimeException("Error establishing on disk size", e);
+ }
+ finally
+ {
+ closePreparedStatement(stmt);
+ }
+
+ }
+
+
+ private long getPersistentSizeLowThreshold()
+ {
+ return _persistentSizeLowThreshold;
+ }
+
+ private long getPersistentSizeHighThreshold()
+ {
+ return _persistentSizeHighThreshold;
+ }
+
+ @Override
+ public String getStoreType()
+ {
+ return DERBY_STORE_TYPE;
+ }
+
} \ No newline at end of file
diff --git a/java/broker/src/main/java/org/apache/qpid/server/subscription/AssignedSubscriptionMessageGroupManager.java b/java/broker/src/main/java/org/apache/qpid/server/subscription/AssignedSubscriptionMessageGroupManager.java
index 6b2dff7165..efedad1181 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/subscription/AssignedSubscriptionMessageGroupManager.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/subscription/AssignedSubscriptionMessageGroupManager.java
@@ -20,10 +20,10 @@
*/
package org.apache.qpid.server.subscription;
+import org.apache.qpid.server.queue.QueueEntryVisitor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import org.apache.qpid.server.queue.AMQQueue;
import org.apache.qpid.server.queue.QueueEntry;
import java.util.Iterator;
@@ -102,7 +102,7 @@ public class AssignedSubscriptionMessageGroupManager implements MessageGroupMana
return visitor.getEntry();
}
- private class EntryFinder implements AMQQueue.Visitor
+ private class EntryFinder implements QueueEntryVisitor
{
private QueueEntry _entry;
private Subscription _sub;
diff --git a/java/broker/src/main/java/org/apache/qpid/server/subscription/DefinedGroupMessageGroupManager.java b/java/broker/src/main/java/org/apache/qpid/server/subscription/DefinedGroupMessageGroupManager.java
index 62e94f6f2e..f38e23b342 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/subscription/DefinedGroupMessageGroupManager.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/subscription/DefinedGroupMessageGroupManager.java
@@ -20,12 +20,12 @@
*/
package org.apache.qpid.server.subscription;
+import org.apache.qpid.server.queue.QueueEntryVisitor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.qpid.server.message.AMQMessageHeader;
import org.apache.qpid.server.message.ServerMessage;
-import org.apache.qpid.server.queue.AMQQueue;
import org.apache.qpid.server.queue.QueueEntry;
import java.util.HashMap;
@@ -176,7 +176,7 @@ public class DefinedGroupMessageGroupManager implements MessageGroupManager
return visitor.getEntry();
}
- private class EntryFinder implements AMQQueue.Visitor
+ private class EntryFinder implements QueueEntryVisitor
{
private QueueEntry _entry;
private Subscription _sub;
diff --git a/java/broker/src/main/java/org/apache/qpid/server/subscription/ExplicitAcceptDispositionChangeListener.java b/java/broker/src/main/java/org/apache/qpid/server/subscription/ExplicitAcceptDispositionChangeListener.java
index cf2754862d..8f3822be6c 100755
--- a/java/broker/src/main/java/org/apache/qpid/server/subscription/ExplicitAcceptDispositionChangeListener.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/subscription/ExplicitAcceptDispositionChangeListener.java
@@ -45,7 +45,7 @@ class ExplicitAcceptDispositionChangeListener implements ServerSession.MessageDi
final Subscription_0_10 subscription = getSubscription();
if(subscription != null && _entry.isAcquiredBy(_sub))
{
- subscription.getSession().acknowledge(subscription, _entry);
+ subscription.getSessionModel().acknowledge(subscription, _entry);
}
else
{
diff --git a/java/broker/src/main/java/org/apache/qpid/server/subscription/ImplicitAcceptDispositionChangeListener.java b/java/broker/src/main/java/org/apache/qpid/server/subscription/ImplicitAcceptDispositionChangeListener.java
index 1e37675c98..826082cc65 100755
--- a/java/broker/src/main/java/org/apache/qpid/server/subscription/ImplicitAcceptDispositionChangeListener.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/subscription/ImplicitAcceptDispositionChangeListener.java
@@ -72,6 +72,10 @@ class ImplicitAcceptDispositionChangeListener implements ServerSession.MessageDi
public boolean acquire()
{
boolean acquired = _entry.acquire(getSubscription());
+ if(acquired)
+ {
+ getSubscription().recordUnacknowledged(_entry);
+ }
return acquired;
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/subscription/Subscription.java b/java/broker/src/main/java/org/apache/qpid/server/subscription/Subscription.java
index 66825caa24..8911754a66 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/subscription/Subscription.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/subscription/Subscription.java
@@ -23,6 +23,7 @@ package org.apache.qpid.server.subscription;
import org.apache.qpid.AMQException;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.server.logging.LogActor;
+import org.apache.qpid.server.protocol.AMQSessionModel;
import org.apache.qpid.server.queue.AMQQueue;
import org.apache.qpid.server.queue.QueueEntry;
@@ -32,6 +33,14 @@ public interface Subscription
boolean isTransient();
+ long getBytesOut();
+
+ long getMessagesOut();
+
+ long getUnacknowledgedBytes();
+
+ long getUnacknowledgedMessages();
+
public static enum State
{
ACTIVE,
@@ -45,6 +54,7 @@ public interface Subscription
}
AMQQueue getQueue();
+ AMQSessionModel getSessionModel();
QueueEntry.SubscriptionAcquiredState getOwningState();
QueueEntry.SubscriptionAssignedState getAssignedState();
@@ -108,4 +118,6 @@ public interface Subscription
boolean isSessionTransactional();
void queueEmpty() throws AMQException;
+
+ String getConsumerName();
}
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 1f25c215cc..c92853e400 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
@@ -44,6 +44,7 @@ import org.apache.qpid.server.logging.subjects.SubscriptionLogSubject;
import org.apache.qpid.server.message.AMQMessage;
import org.apache.qpid.server.output.ProtocolOutputConverter;
import org.apache.qpid.server.protocol.AMQProtocolSession;
+import org.apache.qpid.server.protocol.AMQSessionModel;
import org.apache.qpid.server.queue.AMQQueue;
import org.apache.qpid.server.queue.QueueEntry;
@@ -75,7 +76,7 @@ public abstract class SubscriptionImpl implements Subscription, FlowCreditManage
private final AtomicReference<State> _state = new AtomicReference<State>(State.ACTIVE);
- private AMQQueue.Context _queueContext;
+ private volatile AMQQueue.Context _queueContext;
private final ClientDeliveryMethod _deliveryMethod;
private final RecordDeliveryMethod _recordMethod;
@@ -90,10 +91,15 @@ public abstract class SubscriptionImpl implements Subscription, FlowCreditManage
private final long _subscriptionID;
private LogSubject _logSubject;
private LogActor _logActor;
- private UUID _id;
+ private UUID _qmfId;
private final AtomicLong _deliveredCount = new AtomicLong(0);
- private long _createTime = System.currentTimeMillis();
+ private final AtomicLong _deliveredBytes = new AtomicLong(0);
+
+ private final AtomicLong _unacknowledgedCount = new AtomicLong(0);
+ private final AtomicLong _unacknowledgedBytes = new AtomicLong(0);
+ private long _createTime = System.currentTimeMillis();
+
static final class BrowserSubscription extends SubscriptionImpl
{
@@ -276,22 +282,13 @@ public abstract class SubscriptionImpl implements Subscription, FlowCreditManage
public void send(QueueEntry entry, boolean batch) throws AMQException
{
- // if we do not need to wait for client acknowledgements
- // we can decrement the reference count immediately.
-
- // By doing this _before_ the send we ensure that it
- // doesn't get sent if it can't be dequeued, preventing
- // duplicate delivery on recovery.
-
- // The send may of course still fail, in which case, as
- // the message is unacked, it will be lost.
-
+
synchronized (getChannel())
{
getChannel().getProtocolSession().setDeferFlush(batch);
long deliveryTag = getChannel().getNextDeliveryTag();
-
+ addUnacknowledgedMessage(entry);
recordMessageDelivery(entry, deliveryTag);
sendToClient(entry, deliveryTag);
@@ -371,6 +368,11 @@ public abstract class SubscriptionImpl implements Subscription, FlowCreditManage
}
+ public AMQSessionModel getSessionModel()
+ {
+ return _channel;
+ }
+
public ConfigStore getConfigStore()
{
return getQueue().getConfigStore();
@@ -389,7 +391,7 @@ public abstract class SubscriptionImpl implements Subscription, FlowCreditManage
}
_queue = queue;
- _id = getConfigStore().createId();
+ _qmfId = getConfigStore().createId();
getConfigStore().addConfiguredObject(this);
_logSubject = new SubscriptionLogSubject(this);
@@ -468,11 +470,6 @@ public abstract class SubscriptionImpl implements Subscription, FlowCreditManage
_deleted.set(true);
}
- public boolean filtersMessages()
- {
- return _filters != null || _noLocal;
- }
-
public boolean hasInterest(QueueEntry entry)
{
//check that the message hasn't been rejected
@@ -508,13 +505,6 @@ public abstract class SubscriptionImpl implements Subscription, FlowCreditManage
}
- private String id = String.valueOf(System.identityHashCode(this));
-
- private String debugIdentity()
- {
- return id;
- }
-
private boolean checkFilters(QueueEntry msg)
{
return (_filters == null) || _filters.allAllow(msg);
@@ -599,6 +589,11 @@ public abstract class SubscriptionImpl implements Subscription, FlowCreditManage
return _consumerTag;
}
+ public String getConsumerName()
+ {
+ return _consumerTag == null ? null : _consumerTag.asString();
+ }
+
public long getSubscriptionID()
{
return _subscriptionID;
@@ -687,6 +682,7 @@ public abstract class SubscriptionImpl implements Subscription, FlowCreditManage
{
_deliveryMethod.deliverToClient(this,entry,deliveryTag);
_deliveredCount.incrementAndGet();
+ _deliveredBytes.addAndGet(entry.getSize());
}
@@ -771,9 +767,10 @@ public abstract class SubscriptionImpl implements Subscription, FlowCreditManage
return true;
}
- public UUID getId()
+ @Override
+ public UUID getQMFId()
{
- return _id;
+ return _qmfId;
}
public boolean isDurable()
@@ -832,4 +829,44 @@ public abstract class SubscriptionImpl implements Subscription, FlowCreditManage
_channel.getProtocolSession().flushBatched();
}
+
+ public long getBytesOut()
+ {
+ return _deliveredBytes.longValue();
+ }
+
+ public long getMessagesOut()
+ {
+ return _deliveredCount.longValue();
+ }
+
+
+ protected void addUnacknowledgedMessage(QueueEntry entry)
+ {
+ final long size = entry.getSize();
+ _unacknowledgedBytes.addAndGet(size);
+ _unacknowledgedCount.incrementAndGet();
+ entry.addStateChangeListener(new QueueEntry.StateChangeListener()
+ {
+ public void stateChanged(QueueEntry entry, QueueEntry.State oldState, QueueEntry.State newState)
+ {
+ if(oldState.equals(QueueEntry.State.ACQUIRED) && !newState.equals(QueueEntry.State.ACQUIRED))
+ {
+ _unacknowledgedBytes.addAndGet(-size);
+ _unacknowledgedCount.decrementAndGet();
+ entry.removeStateChangeListener(this);
+ }
+ }
+ });
+ }
+
+ public long getUnacknowledgedBytes()
+ {
+ return _unacknowledgedBytes.longValue();
+ }
+
+ public long getUnacknowledgedMessages()
+ {
+ return _unacknowledgedCount.longValue();
+ }
}
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 76d975a789..dfd9315226 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
@@ -98,7 +98,7 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr
private final Lock _stateChangeLock = new ReentrantLock();
private final AtomicReference<State> _state = new AtomicReference<State>(State.ACTIVE);
- private AMQQueue.Context _queueContext;
+ private volatile AMQQueue.Context _queueContext;
private final AtomicBoolean _deleted = new AtomicBoolean(false);
@@ -125,11 +125,15 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr
private LogActor _logActor;
private final Map<String, Object> _properties = new ConcurrentHashMap<String, Object>();
- private UUID _id;
+ private UUID _qmfId;
private String _traceExclude;
private String _trace;
private final long _createTime = System.currentTimeMillis();
private final AtomicLong _deliveredCount = new AtomicLong(0);
+ private final AtomicLong _deliveredBytes = new AtomicLong(0);
+ private final AtomicLong _unacknowledgedCount = new AtomicLong(0);
+ private final AtomicLong _unacknowledgedBytes = new AtomicLong(0);
+
private final Map<String, Object> _arguments;
private int _deferredMessageCredit;
private long _deferredSizeCredit;
@@ -185,10 +189,10 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr
}
_queue = queue;
- Map<String, Object> arguments = queue.getArguments() == null ? Collections.EMPTY_MAP : queue.getArguments();
+ Map<String, Object> arguments = queue.getArguments();
_traceExclude = (String) arguments.get("qpid.trace.exclude");
_trace = (String) arguments.get("qpid.trace.id");
- _id = getConfigStore().createId();
+ _qmfId = getConfigStore().createId();
getConfigStore().addConfiguredObject(this);
String filterLogString = null;
@@ -199,9 +203,13 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr
CurrentActor.get().message(this, SubscriptionMessages.CREATE(filterLogString, queue.isDurable() && exclusive,
filterLogString.length() > 0));
}
-
}
+ public String getConsumerName()
+ {
+ return _destination;
+ }
+
public boolean isSuspended()
{
return !isActive() || _deleted.get() || _session.isClosing(); // TODO check for Session suspension
@@ -620,10 +628,15 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr
_session.sendMessage(xfr, _postIdSettingAction);
entry.incrementDeliveryCount();
_deliveredCount.incrementAndGet();
+ _deliveredBytes.addAndGet(entry.getSize());
if(_acceptMode == MessageAcceptMode.NONE && _acquireMode == MessageAcquireMode.PRE_ACQUIRED)
{
forceDequeue(entry, false);
}
+ else if(_acquireMode == MessageAcquireMode.PRE_ACQUIRED)
+ {
+ recordUnacknowledged(entry);
+ }
}
else
{
@@ -632,6 +645,12 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr
}
}
+ void recordUnacknowledged(QueueEntry entry)
+ {
+ _unacknowledgedCount.incrementAndGet();
+ _unacknowledgedBytes.addAndGet(entry.getSize());
+ }
+
private void deferredAddCredit(final int deferredMessageCredit, final long deferredSizeCredit)
{
_deferredMessageCredit += deferredMessageCredit;
@@ -653,7 +672,7 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr
private void forceDequeue(final QueueEntry entry, final boolean restoreCredit)
{
- AutoCommitTransaction dequeueTxn = new AutoCommitTransaction(getQueue().getVirtualHost().getMessageStore());
+ AutoCommitTransaction dequeueTxn = new AutoCommitTransaction(getQueue().getVirtualHost().getMessageStore());
dequeueTxn.dequeue(entry.getQueue(), entry.getMessage(),
new ServerTransaction.Action()
{
@@ -690,7 +709,7 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr
entry.setRedelivered();
}
- if (getSession().isClosing() || !setRedelivered)
+ if (getSessionModel().isClosing() || !setRedelivered)
{
entry.decrementDeliveryCount();
}
@@ -918,6 +937,8 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr
// TODO Fix Store Context / cleanup
if(entry.isAcquiredBy(this))
{
+ _unacknowledgedBytes.addAndGet(-entry.getSize());
+ _unacknowledgedCount.decrementAndGet();
entry.discard();
}
}
@@ -944,7 +965,7 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr
return false;
}
- ServerSession getSession()
+ public ServerSession getSessionModel()
{
return _session;
}
@@ -952,7 +973,7 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr
public SessionConfig getSessionConfig()
{
- return getSession();
+ return getSessionModel();
}
public boolean isBrowsing()
@@ -990,9 +1011,10 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr
return _flowMode.toString();
}
- public UUID getId()
+ @Override
+ public UUID getQMFId()
{
- return _id;
+ return _qmfId;
}
public String getName()
@@ -1073,4 +1095,24 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr
{
_session.getConnection().flush();
}
+
+ public long getBytesOut()
+ {
+ return _deliveredBytes.longValue();
+ }
+
+ public long getMessagesOut()
+ {
+ return _deliveredCount.longValue();
+ }
+
+ public long getUnacknowledgedBytes()
+ {
+ return _unacknowledgedBytes.longValue();
+ }
+
+ public long getUnacknowledgedMessages()
+ {
+ return _unacknowledgedCount.longValue();
+ }
}
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 637ea7dffc..7c4188bfcd 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,25 +20,62 @@
*/
package org.apache.qpid.server.transport;
+import org.apache.qpid.server.protocol.AmqpProtocolVersion;
import org.apache.qpid.transport.network.NetworkTransport;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
public class QpidAcceptor
{
- private NetworkTransport _transport;
- private String _protocol;
- public QpidAcceptor(NetworkTransport transport, String protocol)
+ public enum Transport
{
- _transport = transport;
- _protocol = protocol;
+ TCP("TCP"),
+ SSL("TCP/SSL");
+
+ private final String _asString;
+
+ Transport(String asString)
+ {
+ _asString = asString;
+ }
+
+ public String toString()
+ {
+ return _asString;
+ }
+ }
+
+ private NetworkTransport _networkTransport;
+ private Transport _transport;
+ private Set<AmqpProtocolVersion> _supported;
+
+
+ public QpidAcceptor(NetworkTransport transport, Transport protocol, Set<AmqpProtocolVersion> supported)
+ {
+ _networkTransport = transport;
+ _transport = protocol;
+ _supported = Collections.unmodifiableSet(new HashSet<AmqpProtocolVersion>(supported));
}
public NetworkTransport getNetworkTransport()
{
+ return _networkTransport;
+ }
+
+ public Transport getTransport()
+ {
return _transport;
}
+ public Set<AmqpProtocolVersion> getSupported()
+ {
+ return _supported;
+ }
+
public String toString()
{
- return _protocol;
+ return _transport.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 c38f3d0761..f21026794f 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,6 +20,14 @@
*/
package org.apache.qpid.server.transport;
+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 java.util.concurrent.atomic.AtomicLong;
+import javax.security.auth.Subject;
import org.apache.qpid.AMQException;
import org.apache.qpid.protocol.AMQConstant;
import org.apache.qpid.server.configuration.ConnectionConfig;
@@ -28,12 +36,9 @@ import org.apache.qpid.server.logging.LogSubject;
import org.apache.qpid.server.logging.actors.CurrentActor;
import org.apache.qpid.server.logging.actors.GenericActor;
import org.apache.qpid.server.logging.messages.ConnectionMessages;
-import org.apache.qpid.server.management.Managable;
-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.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;
@@ -48,17 +53,7 @@ import static org.apache.qpid.server.logging.subjects.LogSubjectFormat.CONNECTIO
import static org.apache.qpid.server.logging.subjects.LogSubjectFormat.SOCKET_FORMAT;
import static org.apache.qpid.server.logging.subjects.LogSubjectFormat.USER_FORMAT;
-import javax.management.JMException;
-import javax.security.auth.Subject;
-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 java.util.concurrent.atomic.AtomicLong;
-
-public class ServerConnection extends Connection implements Managable, AMQConnectionModel, LogSubject, AuthorizationHolder
+public class ServerConnection extends Connection implements AMQConnectionModel, LogSubject, AuthorizationHolder
{
private ConnectionConfig _config;
private Runnable _onOpenTask;
@@ -67,24 +62,19 @@ public class ServerConnection extends Connection implements Managable, AMQConnec
private Subject _authorizedSubject = null;
private Principal _authorizedPrincipal = null;
- private boolean _statisticsEnabled = false;
private StatisticsCounter _messagesDelivered, _dataDelivered, _messagesReceived, _dataReceived;
private final long _connectionId;
private final Object _reference = new Object();
- private ServerConnectionMBean _mBean;
private VirtualHost _virtualHost;
private AtomicLong _lastIoTime = new AtomicLong();
-
+ private boolean _blocking;
+ private Principal _peerPrincipal;
+
public ServerConnection(final long connectionId)
{
_connectionId = connectionId;
}
- public UUID getId()
- {
- return _config.getId();
- }
-
public Object getReference()
{
return _reference;
@@ -100,12 +90,12 @@ public class ServerConnection extends Connection implements Managable, AMQConnec
protected void setState(State state)
{
super.setState(state);
-
+
if (state == State.OPEN)
{
if (_onOpenTask != null)
{
- _onOpenTask.run();
+ _onOpenTask.run();
}
_actor.message(ConnectionMessages.OPEN(getClientId(), "0-10", getClientVersion(), true, true, true));
@@ -118,7 +108,6 @@ public class ServerConnection extends Connection implements Managable, AMQConnec
{
_virtualHost.getConnectionRegistry().deregisterConnection(this);
}
- unregisterConnectionMbean();
}
if (state == State.CLOSED)
@@ -156,8 +145,6 @@ public class ServerConnection extends Connection implements Managable, AMQConnec
_virtualHost = virtualHost;
initialiseStatistics();
-
- registerConnectionMbean();
}
public void setConnectionConfig(final ConnectionConfig config)
@@ -193,7 +180,7 @@ public class ServerConnection extends Connection implements Managable, AMQConnec
((ServerSession)session).close();
}
-
+
public LogSubject getLogSubject()
{
return (LogSubject) this;
@@ -273,7 +260,6 @@ public class ServerConnection extends Connection implements Managable, AMQConnec
public void close(AMQConstant cause, String message) throws AMQException
{
closeSubscriptions();
- unregisterConnectionMbean();
ConnectionCloseCode replyCode = ConnectionCloseCode.NORMAL;
try
{
@@ -286,6 +272,46 @@ public class ServerConnection extends Connection implements Managable, AMQConnec
close(replyCode, message);
}
+ public synchronized void block()
+ {
+ if(!_blocking)
+ {
+ _blocking = true;
+ for(AMQSessionModel ssn : getSessionModels())
+ {
+ ssn.block();
+ }
+ }
+ }
+
+ public synchronized void unblock()
+ {
+ if(_blocking)
+ {
+ _blocking = false;
+ for(AMQSessionModel ssn : getSessionModels())
+ {
+ ssn.unblock();
+ }
+ }
+ }
+
+ @Override
+ public synchronized void registerSession(final Session ssn)
+ {
+ super.registerSession(ssn);
+ if(_blocking)
+ {
+ ((ServerSession)ssn).block();
+ }
+ }
+
+ @Override
+ public synchronized void removeSession(final Session ssn)
+ {
+ super.removeSession(ssn);
+ }
+
public List<AMQSessionModel> getSessionModels()
{
List<AMQSessionModel> sessions = new ArrayList<AMQSessionModel>();
@@ -298,44 +324,38 @@ public class ServerConnection extends Connection implements Managable, AMQConnec
public void registerMessageDelivered(long messageSize)
{
- if (isStatisticsEnabled())
- {
- _messagesDelivered.registerEvent(1L);
- _dataDelivered.registerEvent(messageSize);
- }
+ _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);
- }
+ _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();
@@ -346,25 +366,12 @@ public class ServerConnection extends Connection implements Managable, AMQConnec
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
*/
@@ -389,7 +396,7 @@ public class ServerConnection extends Connection implements Managable, AMQConnec
else
{
_authorizedSubject = authorizedSubject;
- _authorizedPrincipal = UsernamePrincipal.getUsernamePrincipalFromSubject(_authorizedSubject);
+ _authorizedPrincipal = authorizedSubject.getPrincipals().iterator().next();
}
}
@@ -408,6 +415,11 @@ public class ServerConnection extends Connection implements Managable, AMQConnec
return !super.hasSessionWithName(name);
}
+ public String getRemoteAddressString()
+ {
+ return getConfig().getAddress();
+ }
+
public String getUserName()
{
return _authorizedPrincipal.getName();
@@ -436,12 +448,6 @@ public class ServerConnection extends Connection implements Managable, AMQConnec
}
}
-
- public ManagedObject getManagedObject()
- {
- return _mBean;
- }
-
@Override
public void send(ProtocolEvent event)
{
@@ -449,53 +455,38 @@ public class ServerConnection extends Connection implements Managable, AMQConnec
super.send(event);
}
- public AtomicLong getLastIoTime()
+ public long getLastIoTime()
{
- return _lastIoTime;
+ return _lastIoTime.longValue();
}
- void checkForNotification()
+ public String getClientId()
{
- int channelsCount = getSessionModels().size();
- if (_mBean != null && channelsCount >= getConnectionDelegate().getChannelMax())
- {
- _mBean.notifyClients("Channel count (" + channelsCount + ") has reached the threshold value");
- }
+ return getConnectionDelegate().getClientId();
}
- private void registerConnectionMbean()
+ public String getClientVersion()
{
- try
- {
- _mBean = new ServerConnectionMBean(this);
- _mBean.register();
- }
- catch (JMException jme)
- {
- log.error("Unable to register mBean for ServerConnection", jme);
- }
+ return getConnectionDelegate().getClientVersion();
}
- private void unregisterConnectionMbean()
+ public String getPrincipalAsString()
{
- if (_mBean != null)
- {
- if (log.isDebugEnabled())
- {
- log.debug("Unregistering mBean for ServerConnection" + _mBean);
- }
- _mBean.unregister();
- _mBean = null;
- }
+ return getAuthorizedPrincipal().getName();
}
- public String getClientId()
+ public long getSessionCountLimit()
{
- return getConnectionDelegate().getClientId();
+ return getChannelMax();
}
- public String getClientVersion()
+ public Principal getPeerPrincipal()
{
- return getConnectionDelegate().getClientVersion();
+ return _peerPrincipal;
+ }
+
+ public void setPeerPrincipal(Principal peerPrincipal)
+ {
+ _peerPrincipal = peerPrincipal;
}
}
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 5460c89eab..c13f63b44d 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,18 +20,26 @@
*/
package org.apache.qpid.server.transport;
-import static org.apache.qpid.transport.Connection.State.CLOSE_RCVD;
-
+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.common.ServerPropertyNames;
import org.apache.qpid.properties.ConnectionStartProperties;
import org.apache.qpid.protocol.ProtocolEngine;
import org.apache.qpid.server.configuration.BrokerConfig;
import org.apache.qpid.server.protocol.AMQConnectionModel;
-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.security.auth.manager.AuthenticationManager;
import org.apache.qpid.server.subscription.Subscription_0_10;
import org.apache.qpid.server.virtualhost.State;
import org.apache.qpid.server.virtualhost.VirtualHost;
@@ -39,16 +47,7 @@ import org.apache.qpid.transport.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import javax.security.sasl.SaslException;
-import javax.security.sasl.SaslServer;
-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 static org.apache.qpid.transport.Connection.State.CLOSE_RCVD;
public class ServerConnectionDelegate extends ServerDelegate
{
@@ -58,22 +57,25 @@ public class ServerConnectionDelegate extends ServerDelegate
private final IApplicationRegistry _appRegistry;
private int _maxNoOfChannels;
private Map<String,Object> _clientProperties;
+ private final AuthenticationManager _authManager;
- public ServerConnectionDelegate(IApplicationRegistry appRegistry, String localFQDN)
+ public ServerConnectionDelegate(IApplicationRegistry appRegistry, String localFQDN, AuthenticationManager authManager)
{
- this(createConnectionProperties(appRegistry.getBroker()), Collections.singletonList((Object)"en_US"), appRegistry, localFQDN);
+ this(createConnectionProperties(appRegistry.getBrokerConfig()), Collections.singletonList((Object)"en_US"), appRegistry, localFQDN, authManager);
}
- public ServerConnectionDelegate(Map<String, Object> properties,
+ private ServerConnectionDelegate(Map<String, Object> properties,
List<Object> locales,
IApplicationRegistry appRegistry,
- String localFQDN)
+ String localFQDN,
+ AuthenticationManager authManager)
{
- super(properties, parseToList(appRegistry.getAuthenticationManager().getMechanisms()), locales);
-
+ super(properties, parseToList(authManager.getMechanisms()), locales);
+
_appRegistry = appRegistry;
_localFQDN = localFQDN;
- _maxNoOfChannels = ApplicationRegistry.getInstance().getConfiguration().getMaxChannelCount();
+ _maxNoOfChannels = appRegistry.getConfiguration().getMaxChannelCount();
+ _authManager = authManager;
}
private static Map<String, Object> createConnectionProperties(final BrokerConfig brokerConfig)
@@ -108,18 +110,17 @@ public class ServerConnectionDelegate extends ServerDelegate
return ssn;
}
- protected SaslServer createSaslServer(String mechanism) throws SaslException
+ protected SaslServer createSaslServer(Connection conn, String mechanism) throws SaslException
{
- return _appRegistry.getAuthenticationManager().createSaslServer(mechanism, _localFQDN);
+ return _authManager.createSaslServer(mechanism, _localFQDN, ((ServerConnection) conn).getPeerPrincipal());
}
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;
-
-
+ final AuthenticationResult authResult = _authManager.authenticate(ss, response);
+
if (AuthenticationStatus.SUCCESS.equals(authResult.getStatus()))
{
tuneAuthorizedConnection(sconn);
@@ -168,7 +169,7 @@ public class ServerConnectionDelegate extends ServerDelegate
vhost = _appRegistry.getVirtualHostRegistry().getVirtualHost(vhostName);
SecurityManager.setThreadSubject(sconn.getAuthorizedSubject());
-
+
if(vhost != null)
{
sconn.setVirtualHost(vhost);
@@ -194,7 +195,7 @@ public class ServerConnectionDelegate extends ServerDelegate
sconn.setState(Connection.State.CLOSING);
sconn.invoke(new ConnectionClose(ConnectionCloseCode.INVALID_PATH, "Unknown virtualhost '"+vhostName+"'"));
}
-
+
}
@Override
@@ -216,7 +217,7 @@ public class ServerConnectionDelegate extends ServerDelegate
setConnectionTuneOkChannelMax(sconn, okChannelMax);
}
-
+
@Override
protected int getHeartbeatMax()
{
@@ -225,7 +226,7 @@ public class ServerConnectionDelegate extends ServerDelegate
}
@Override
- protected int getChannelMax()
+ public int getChannelMax()
{
return _maxNoOfChannels;
}
@@ -265,7 +266,6 @@ public class ServerConnectionDelegate extends ServerDelegate
if(isSessionNameUnique(atc.getName(), conn))
{
super.sessionAttach(conn, atc);
- ((ServerConnection)conn).checkForNotification();
}
else
{
diff --git a/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnectionMBean.java b/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnectionMBean.java
deleted file mode 100644
index bb545164fb..0000000000
--- a/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnectionMBean.java
+++ /dev/null
@@ -1,263 +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.transport;
-
-import org.apache.qpid.management.common.mbeans.annotations.MBeanConstructor;
-import org.apache.qpid.management.common.mbeans.annotations.MBeanDescription;
-import org.apache.qpid.server.logging.actors.CurrentActor;
-import org.apache.qpid.server.logging.actors.ManagementActor;
-import org.apache.qpid.server.management.AbstractAMQManagedConnectionObject;
-import org.apache.qpid.server.management.ManagedObject;
-import org.apache.qpid.server.protocol.AMQSessionModel;
-
-import javax.management.JMException;
-import javax.management.NotCompliantMBeanException;
-import javax.management.openmbean.CompositeData;
-import javax.management.openmbean.CompositeDataSupport;
-import javax.management.openmbean.TabularData;
-import javax.management.openmbean.TabularDataSupport;
-import java.io.IOException;
-import java.util.Date;
-import java.util.List;
-
-/**
- * This MBean class implements the management interface. In order to make more attributes, operations and notifications
- * available over JMX simply augment the ManagedConnection interface and add the appropriate implementation here.
- */
-@MBeanDescription("Management Bean for an AMQ Broker 0-10 Connection")
-public class ServerConnectionMBean extends AbstractAMQManagedConnectionObject
-{
- private final ServerConnection _serverConnection;
-
- @MBeanConstructor("Creates an MBean exposing an AMQ Broker 0-10 Connection")
- protected ServerConnectionMBean(final ServerConnection serverConnection) throws NotCompliantMBeanException
- {
- super(serverConnection.getConfig().getAddress());
- _serverConnection = serverConnection;
- }
-
- @Override
- public ManagedObject getParentObject()
- {
- return _serverConnection.getVirtualHost().getManagedObject();
- }
-
- @Override
- public String getClientId()
- {
- return _serverConnection.getClientId();
- }
-
- @Override
- public String getAuthorizedId()
- {
- return _serverConnection.getAuthorizedPrincipal().getName();
- }
-
- @Override
- public String getVersion()
- {
- return String.valueOf(_serverConnection.getClientVersion());
- }
-
- @Override
- public String getRemoteAddress()
- {
- return _serverConnection.getConfig().getAddress();
- }
-
- @Override
- public Date getLastIoTime()
- {
- return new Date(_serverConnection.getLastIoTime().longValue());
- }
-
- @Override
- public Long getMaximumNumberOfChannels()
- {
- return (long) _serverConnection.getConnectionDelegate().getChannelMax();
- }
-
- @Override
- public TabularData channels() throws IOException, JMException
- {
- final TabularDataSupport channelsList = new TabularDataSupport(_channelsType);
- final List<AMQSessionModel> list = _serverConnection.getSessionModels();
-
- for (final AMQSessionModel channel : list)
- {
- final ServerSession session = (ServerSession)channel;
- Object[] itemValues =
- {
- session.getChannel(),
- session.isTransactional(),
- null,
- session.getUnacknowledgedMessageCount(),
- session.getBlocking()
- };
-
- final CompositeData channelData = new CompositeDataSupport(_channelType,
- COMPOSITE_ITEM_NAMES_DESC.toArray(new String[COMPOSITE_ITEM_NAMES_DESC.size()]), itemValues);
- channelsList.put(channelData);
- }
- return channelsList;
- }
-
- @Override
- public void commitTransactions(int channelId) throws JMException
- {
- final ServerSession session = (ServerSession)_serverConnection.getSession(channelId);
- if (session == null)
- {
- throw new JMException("The channel (channel Id = " + channelId + ") does not exist");
- }
- else if (session.isTransactional())
- {
- CurrentActor.set(new ManagementActor(getLogActor().getRootMessageLogger()));
- try
- {
- session.commit();
- }
- finally
- {
- CurrentActor.remove();
- }
- }
- }
-
- @Override
- public void rollbackTransactions(int channelId) throws JMException
- {
- final ServerSession session = (ServerSession)_serverConnection.getSession(channelId);
- if (session == null)
- {
- throw new JMException("The channel (channel Id = " + channelId + ") does not exist");
- }
- else if (session.isTransactional())
- {
- CurrentActor.set(new ManagementActor(getLogActor().getRootMessageLogger()));
- try
- {
- session.rollback();
- }
- finally
- {
- CurrentActor.remove();
- }
- }
- }
-
- @Override
- public void closeConnection() throws Exception
- {
- _serverConnection.mgmtClose();
- }
-
- @Override
- public void resetStatistics() throws Exception
- {
- _serverConnection.resetStatistics();
- }
-
- @Override
- public double getPeakMessageDeliveryRate()
- {
- return _serverConnection.getMessageDeliveryStatistics().getPeak();
- }
-
- @Override
- public double getPeakDataDeliveryRate()
- {
- return _serverConnection.getDataDeliveryStatistics().getPeak();
- }
-
- @Override
- public double getMessageDeliveryRate()
- {
- return _serverConnection.getMessageDeliveryStatistics().getRate();
- }
-
- @Override
- public double getDataDeliveryRate()
- {
- return _serverConnection.getDataDeliveryStatistics().getRate();
- }
-
- @Override
- public long getTotalMessagesDelivered()
- {
- return _serverConnection.getMessageDeliveryStatistics().getTotal();
- }
-
- @Override
- public long getTotalDataDelivered()
- {
- return _serverConnection.getDataDeliveryStatistics().getTotal();
- }
-
- @Override
- public double getPeakMessageReceiptRate()
- {
- return _serverConnection.getMessageReceiptStatistics().getPeak();
- }
-
- @Override
- public double getPeakDataReceiptRate()
- {
- return _serverConnection.getDataReceiptStatistics().getPeak();
- }
-
- @Override
- public double getMessageReceiptRate()
- {
- return _serverConnection.getMessageReceiptStatistics().getRate();
- }
-
- @Override
- public double getDataReceiptRate()
- {
- return _serverConnection.getDataReceiptStatistics().getRate();
- }
-
- @Override
- public long getTotalMessagesReceived()
- {
- return _serverConnection.getMessageReceiptStatistics().getTotal();
- }
-
- @Override
- public long getTotalDataReceived()
- {
- return _serverConnection.getDataReceiptStatistics().getTotal();
- }
-
- @Override
- public boolean isStatisticsEnabled()
- {
- return _serverConnection.isStatisticsEnabled();
- }
-
- @Override
- public void setStatisticsEnabled(boolean enabled)
- {
- _serverConnection.setStatisticsEnabled(enabled);
- }
-}
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 6f979e035e..f82b25b3d6 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
@@ -20,17 +20,11 @@
*/
package org.apache.qpid.server.transport;
-import static org.apache.qpid.server.logging.subjects.LogSubjectFormat.CHANNEL_FORMAT;
-import org.apache.qpid.server.message.InboundMessage;
-import org.apache.qpid.server.message.MessageMetaData_0_10;
-import org.apache.qpid.server.message.MessageTransferMessage;
-import org.apache.qpid.server.txn.RollbackOnlyDtxException;
-import org.apache.qpid.server.txn.TimeoutDtxException;
-import static org.apache.qpid.util.Serial.gt;
-
import java.security.Principal;
import java.text.MessageFormat;
import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
@@ -40,18 +34,16 @@ import java.util.SortedMap;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentSkipListMap;
-import java.util.concurrent.ConcurrentSkipListSet;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.atomic.AtomicBoolean;
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.AMQStoreException;
import org.apache.qpid.protocol.AMQConstant;
import org.apache.qpid.protocol.ProtocolEngine;
+import org.apache.qpid.server.TransactionTimeoutHelper;
import org.apache.qpid.server.configuration.ConfigStore;
import org.apache.qpid.server.configuration.ConfiguredObject;
import org.apache.qpid.server.configuration.ConnectionConfig;
@@ -63,7 +55,10 @@ 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.logging.subjects.ChannelLogSubject;
+import org.apache.qpid.server.message.InboundMessage;
+import org.apache.qpid.server.message.MessageMetaData_0_10;
import org.apache.qpid.server.message.MessageReference;
+import org.apache.qpid.server.message.MessageTransferMessage;
import org.apache.qpid.server.message.ServerMessage;
import org.apache.qpid.server.protocol.AMQConnectionModel;
import org.apache.qpid.server.protocol.AMQSessionModel;
@@ -82,20 +77,25 @@ import org.apache.qpid.server.txn.IncorrectDtxStateException;
import org.apache.qpid.server.txn.JoinAndResumeDtxException;
import org.apache.qpid.server.txn.LocalTransaction;
import org.apache.qpid.server.txn.NotAssociatedDtxException;
+import org.apache.qpid.server.txn.RollbackOnlyDtxException;
import org.apache.qpid.server.txn.ServerTransaction;
import org.apache.qpid.server.txn.SuspendAndFailDtxException;
+import org.apache.qpid.server.txn.TimeoutDtxException;
import org.apache.qpid.server.txn.UnknownDtxBranchException;
import org.apache.qpid.server.virtualhost.VirtualHost;
import org.apache.qpid.transport.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-public class ServerSession extends Session
- implements AuthorizationHolder, SessionConfig,
+import static org.apache.qpid.server.logging.subjects.LogSubjectFormat.CHANNEL_FORMAT;
+import static org.apache.qpid.util.Serial.gt;
+
+public class ServerSession extends Session
+ implements AuthorizationHolder, SessionConfig,
AMQSessionModel, LogSubject, AsyncAutoCommitTransaction.FutureRecorder
{
private static final Logger _logger = LoggerFactory.getLogger(ServerSession.class);
-
+
private static final String NULL_DESTINTATION = UUID.randomUUID().toString();
private static final int PRODUCER_CREDIT_TOPUP_THRESHOLD = 1 << 30;
private static final int UNFINISHED_COMMAND_QUEUE_THRESHOLD = 500;
@@ -105,7 +105,7 @@ public class ServerSession extends Session
private long _createTime = System.currentTimeMillis();
private LogActor _actor = GenericActor.getInstance(this);
- private final Set<AMQQueue> _blockingQueues = new ConcurrentSkipListSet<AMQQueue>();
+ private final Set<Object> _blockingEntities = Collections.synchronizedSet(new HashSet<Object>());
private final AtomicBoolean _blocking = new AtomicBoolean(false);
private ChannelLogSubject _logSubject;
@@ -145,6 +145,8 @@ public class ServerSession extends Session
private final List<Task> _taskList = new CopyOnWriteArrayList<Task>();
+ private final TransactionTimeoutHelper _transactionTimeoutHelper;
+
ServerSession(Connection connection, SessionDelegate delegate, Binary name, long expiry)
{
this(connection, delegate, name, expiry, ((ServerConnection)connection).getConfig());
@@ -158,6 +160,8 @@ public class ServerSession extends Session
_logSubject = new ChannelLogSubject(this);
_id = getConfigStore().createId();
getConfigStore().addConfiguredObject(this);
+
+ _transactionTimeoutHelper = new TransactionTimeoutHelper(_logSubject);
}
protected void setState(State state)
@@ -167,9 +171,19 @@ public class ServerSession extends Session
if (state == State.OPEN)
{
_actor.message(ChannelMessages.CREATE());
+ if(_blocking.get())
+ {
+ invokeBlock();
+ }
}
}
+ private void invokeBlock()
+ {
+ invoke(new MessageSetFlowMode("", MessageFlowMode.CREDIT));
+ invoke(new MessageStop(""));
+ }
+
private ConfigStore getConfigStore()
{
return getConnectionConfig().getConfigStore();
@@ -455,7 +469,7 @@ public class ServerSession extends Session
{
return _transaction.isTransactional();
}
-
+
public boolean inTransaction()
{
return isTransactional() && _txnUpdateTime.get() > 0 && _transaction.getTransactionStartTime() > 0;
@@ -621,16 +635,26 @@ public class ServerSession extends Session
return _txnRejects.get();
}
+ public int getChannelId()
+ {
+ return getChannel();
+ }
+
public Long getTxnCount()
{
return _txnCount.get();
}
+ public Long getTxnStart()
+ {
+ return _txnStarts.get();
+ }
+
public Principal getAuthorizedPrincipal()
{
return getConnection().getAuthorizedPrincipal();
}
-
+
public Subject getAuthorizedSubject()
{
return getConnection().getAuthorizedSubject();
@@ -661,7 +685,8 @@ public class ServerSession extends Session
return (VirtualHost) _connectionConfig.getVirtualHost();
}
- public UUID getId()
+ @Override
+ public UUID getQMFId()
{
return _id;
}
@@ -755,63 +780,85 @@ public class ServerSession extends Session
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)
+ _transactionTimeoutHelper.logIfNecessary(idleTime, idleWarn, ChannelMessages.IDLE_TXN(idleTime),
+ TransactionTimeoutHelper.IDLE_TRANSACTION_ALERT);
+ if (_transactionTimeoutHelper.isTimedOut(idleTime, idleClose))
{
getConnectionModel().closeSession(this, AMQConstant.RESOURCE_ERROR, "Idle transaction timed out");
+ return;
}
- else if (openClose > 0L && openTime > openClose)
+
+ _transactionTimeoutHelper.logIfNecessary(openTime, openWarn, ChannelMessages.OPEN_TXN(openTime),
+ TransactionTimeoutHelper.OPEN_TRANSACTION_ALERT);
+ if (_transactionTimeoutHelper.isTimedOut(openTime, openClose))
{
getConnectionModel().closeSession(this, AMQConstant.RESOURCE_ERROR, "Open transaction timed out");
+ return;
}
}
}
public void block(AMQQueue queue)
{
+ block(queue, queue.getName());
+ }
+
+ public void block()
+ {
+ block(this, "** All Queues **");
+ }
- if(_blockingQueues.add(queue))
- {
- if(_blocking.compareAndSet(false,true))
+ private void block(Object queue, String name)
+ {
+ synchronized (_blockingEntities)
+ {
+ if(_blockingEntities.add(queue))
{
- invoke(new MessageSetFlowMode("", MessageFlowMode.CREDIT));
- invoke(new MessageStop(""));
- _actor.message(_logSubject, ChannelMessages.FLOW_ENFORCED(queue.getNameShortString().toString()));
- }
+
+ if(_blocking.compareAndSet(false,true))
+ {
+ if(getState() == State.OPEN)
+ {
+ invokeBlock();
+ }
+ _actor.message(_logSubject, ChannelMessages.FLOW_ENFORCED(name));
+ }
+ }
}
}
public void unblock(AMQQueue queue)
{
- if(_blockingQueues.remove(queue) && _blockingQueues.isEmpty())
+ unblock((Object)queue);
+ }
+
+ public void unblock()
+ {
+ unblock(this);
+ }
+
+ private void unblock(Object queue)
+ {
+ synchronized(_blockingEntities)
{
- if(_blocking.compareAndSet(true,false) && !isClosing())
+ if(_blockingEntities.remove(queue) && _blockingEntities.isEmpty())
{
+ if(_blocking.compareAndSet(true,false) && !isClosing())
+ {
- _actor.message(_logSubject, ChannelMessages.FLOW_REMOVED());
- MessageFlow mf = new MessageFlow();
- mf.setUnit(MessageCreditUnit.MESSAGE);
- mf.setDestination("");
- _outstandingCredit.set(Integer.MAX_VALUE);
- mf.setValue(Integer.MAX_VALUE);
- invoke(mf);
+ _actor.message(_logSubject, ChannelMessages.FLOW_REMOVED());
+ MessageFlow mf = new MessageFlow();
+ mf.setUnit(MessageCreditUnit.MESSAGE);
+ mf.setDestination("");
+ _outstandingCredit.set(Integer.MAX_VALUE);
+ mf.setValue(Integer.MAX_VALUE);
+ invoke(mf);
+ }
}
}
}
@@ -1020,7 +1067,12 @@ public class ServerSession extends Session
public int compareTo(AMQSessionModel session)
{
- return getId().compareTo(session.getId());
+ return getQMFId().compareTo(session.getQMFId());
}
+ @Override
+ public int getConsumerCount()
+ {
+ return _subscriptions.values().size();
+ }
}
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 79a8bc0e4c..05963ee874 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
@@ -99,9 +99,9 @@ public class ServerSessionDelegate extends SessionDelegate
Object newOutstanding = ((ServerSession)session).getAsyncCommandMark();
if(newOutstanding == null || newOutstanding == asyncCommandMark)
{
- session.processed(method);
+ session.processed(method);
}
-
+
if(newOutstanding != null)
{
((ServerSession)session).completeAsyncCommands();
@@ -240,13 +240,13 @@ public class ServerSessionDelegate extends SessionDelegate
}
FlowCreditManager_0_10 creditManager = new WindowCreditManager(0L,0L);
-
+
FilterManager filterManager = null;
- try
+ try
{
filterManager = FilterManagerFactory.createManager(method.getArguments());
- }
- catch (AMQException amqe)
+ }
+ catch (AMQException amqe)
{
exception(session, method, ExecutionErrorCode.ILLEGAL_ARGUMENT, "Exception Creating FilterManager");
return;
@@ -257,7 +257,7 @@ public class ServerSessionDelegate extends SessionDelegate
method.getAcceptMode(),
method.getAcquireMode(),
MessageFlowMode.WINDOW,
- creditManager,
+ creditManager,
filterManager,
method.getArguments());
@@ -297,13 +297,13 @@ public class ServerSessionDelegate extends SessionDelegate
final MessageMetaData_0_10 messageMetaData = new MessageMetaData_0_10(xfr);
messageMetaData.setConnectionReference(((ServerSession)ssn).getReference());
-
+
if (!getVirtualHost(ssn).getSecurityManager().authorisePublish(messageMetaData.isImmediate(), messageMetaData.getRoutingKey(), exchange.getName()))
{
ExecutionErrorCode errorCode = ExecutionErrorCode.UNAUTHORIZED_ACCESS;
String description = "Permission denied: exchange-name '" + exchange.getName() + "'";
exception(ssn, xfr, errorCode, description);
-
+
return;
}
@@ -807,7 +807,7 @@ public class ServerSessionDelegate extends SessionDelegate
}
}
- // TODO decouple AMQException and AMQConstant error codes
+ // TODO decouple AMQException and AMQConstant error codes
private void exception(Session session, Method method, AMQException exception, String message)
{
ExecutionErrorCode errorCode = ExecutionErrorCode.INTERNAL_ERROR;
@@ -823,7 +823,7 @@ public class ServerSessionDelegate extends SessionDelegate
}
}
String description = message + "': " + exception.getMessage();
-
+
exception(session, method, errorCode, description);
}
@@ -1226,11 +1226,7 @@ public class ServerSessionDelegate extends SessionDelegate
try
{
queue = createQueue(queueName, method, virtualHost, (ServerSession)session);
- if(method.getExclusive())
- {
- queue.setExclusive(true);
- }
- else if(method.getAutoDelete())
+ if(!method.getExclusive() && method.getAutoDelete())
{
queue.setDeleteOnNoConsumers(true);
}
@@ -1349,9 +1345,9 @@ public class ServerSessionDelegate extends SessionDelegate
+ " as exclusive queue with same name "
+ "declared on another session";
ExecutionErrorCode errorCode = ExecutionErrorCode.RESOURCE_LOCKED;
-
+
exception(session, method, errorCode, description);
-
+
return;
}
}
@@ -1389,7 +1385,7 @@ public class ServerSessionDelegate extends SessionDelegate
{
String owner = body.getExclusive() ? session.getClientID() : null;
- final AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateUUID(), queueName, body.getDurable(), owner,
+ final AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateQueueUUID(queueName, virtualHost.getName()), queueName, body.getDurable(), owner,
body.getAutoDelete(), body.getExclusive(), virtualHost, body.getArguments());
return queue;
@@ -1436,7 +1432,7 @@ public class ServerSessionDelegate extends SessionDelegate
else
{
VirtualHost virtualHost = getVirtualHost(session);
-
+
try
{
queue.delete();
diff --git a/java/broker/src/main/java/org/apache/qpid/server/txn/AsyncAutoCommitTransaction.java b/java/broker/src/main/java/org/apache/qpid/server/txn/AsyncAutoCommitTransaction.java
index d446434d24..efd7850a49 100755
--- a/java/broker/src/main/java/org/apache/qpid/server/txn/AsyncAutoCommitTransaction.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/txn/AsyncAutoCommitTransaction.java
@@ -44,11 +44,16 @@ import java.util.List;
*/
public class AsyncAutoCommitTransaction implements ServerTransaction
{
+ static final String QPID_STRICT_ORDER_WITH_MIXED_DELIVERY_MODE = "qpid.strict_order_with_mixed_delivery_mode";
+
protected static final Logger _logger = Logger.getLogger(AsyncAutoCommitTransaction.class);
private final MessageStore _messageStore;
private final FutureRecorder _futureRecorder;
+ //Set true to ensure strict ordering when enqueing messages with mixed delivery mode, i.e. disable async persistence
+ private boolean _strictOrderWithMixedDeliveryMode = Boolean.getBoolean(QPID_STRICT_ORDER_WITH_MIXED_DELIVERY_MODE);
+
public static interface FutureRecorder
{
public void recordFuture(StoreFuture future, Action action);
@@ -129,6 +134,23 @@ public class AsyncAutoCommitTransaction implements ServerTransaction
}
}
+ private void addEnqueueFuture(final StoreFuture future, final Action action, boolean persistent)
+ {
+ if(action != null)
+ {
+ // For persistent messages, do not synchronously invoke postCommit even if the future is completed.
+ // Otherwise, postCommit (which actually does the enqueuing) might be called on successive messages out of order.
+ if(future.isComplete() && !persistent && !_strictOrderWithMixedDeliveryMode)
+ {
+ action.postCommit();
+ }
+ else
+ {
+ _futureRecorder.recordFuture(future, action);
+ }
+ }
+ }
+
public void dequeue(Collection<QueueEntry> queueEntries, Action postTransactionAction)
{
Transaction txn = null;
@@ -203,7 +225,7 @@ public class AsyncAutoCommitTransaction implements ServerTransaction
{
future = StoreFuture.IMMEDIATE_FUTURE;
}
- addFuture(future, postTransactionAction);
+ addEnqueueFuture(future, postTransactionAction, message.isPersistent());
postTransactionAction = null;
}
catch (AMQException e)
@@ -257,7 +279,7 @@ public class AsyncAutoCommitTransaction implements ServerTransaction
{
future = StoreFuture.IMMEDIATE_FUTURE;
}
- addFuture(future, postTransactionAction);
+ addEnqueueFuture(future, postTransactionAction, message.isPersistent());
postTransactionAction = null;
diff --git a/java/broker/src/main/java/org/apache/qpid/server/txn/DtxBranch.java b/java/broker/src/main/java/org/apache/qpid/server/txn/DtxBranch.java
index 3ac71fc6a6..fb32b654ce 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/txn/DtxBranch.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/txn/DtxBranch.java
@@ -98,12 +98,29 @@ public class DtxBranch
public void setTimeout(long timeout)
{
+ if(_logger.isDebugEnabled())
+ {
+ _logger.debug("Setting timeout to " + timeout + "s for DtxBranch " + _xid);
+ }
+
if(_timeoutFuture != null)
{
- _timeoutFuture.cancel(false);
+ if(_logger.isDebugEnabled())
+ {
+ _logger.debug("Attempting to cancel previous timeout task future for DtxBranch " + _xid);
+ }
+
+ boolean succeeded = _timeoutFuture.cancel(false);
+
+ if(_logger.isDebugEnabled())
+ {
+ _logger.debug("Cancelling previous timeout task " + (succeeded ? "succeeded" : "failed")
+ + " for DtxBranch " + _xid);
+ }
}
+
_timeout = timeout;
- _expiration = timeout == 0 ? 0 : System.currentTimeMillis() + timeout;
+ _expiration = timeout == 0 ? 0 : System.currentTimeMillis() + (1000 * timeout);
if(_timeout == 0)
{
@@ -111,10 +128,23 @@ public class DtxBranch
}
else
{
- _timeoutFuture = _vhost.scheduleTask(_timeout, new Runnable()
+ long delay = 1000*_timeout;
+
+ if(_logger.isDebugEnabled())
+ {
+ _logger.debug("Scheduling timeout and rollback after " + delay/1000 +
+ "s for DtxBranch " + _xid);
+ }
+
+ _timeoutFuture = _vhost.scheduleTask(delay, new Runnable()
{
public void run()
{
+ if(_logger.isDebugEnabled())
+ {
+ _logger.debug("Timing out DtxBranch " + _xid);
+ }
+
setState(State.TIMEDOUT);
try
{
@@ -122,8 +152,7 @@ public class DtxBranch
}
catch (AMQStoreException e)
{
- _logger.error("Unexpected error when attempting to rollback XA transaction ("+
- _xid + ") due to timeout", e);
+ _logger.error("Unexpected error when attempting to rollback DtxBranch "+ _xid + " due to timeout", e);
throw new RuntimeException(e);
}
}
@@ -199,6 +228,10 @@ public class DtxBranch
public void prepare() throws AMQStoreException
{
+ if(_logger.isDebugEnabled())
+ {
+ _logger.debug("Performing prepare for DtxBranch " + _xid);
+ }
Transaction txn = _store.newTransaction();
txn.recordXid(_xid.getFormat(),
@@ -213,12 +246,27 @@ public class DtxBranch
public synchronized void rollback() throws AMQStoreException
{
+ if(_logger.isDebugEnabled())
+ {
+ _logger.debug("Performing rollback for DtxBranch " + _xid);
+ }
+
if(_timeoutFuture != null)
{
- _timeoutFuture.cancel(false);
+ if(_logger.isDebugEnabled())
+ {
+ _logger.debug("Attempting to cancel previous timeout task future for DtxBranch " + _xid);
+ }
+
+ boolean succeeded = _timeoutFuture.cancel(false);
_timeoutFuture = null;
- }
+ if(_logger.isDebugEnabled())
+ {
+ _logger.debug("Cancelling previous timeout task " + (succeeded ? "succeeded" : "failed")
+ + " for DtxBranch " + _xid);
+ }
+ }
if(_transaction != null)
{
@@ -240,10 +288,26 @@ public class DtxBranch
public void commit() throws AMQStoreException
{
+ if(_logger.isDebugEnabled())
+ {
+ _logger.debug("Performing commit for DtxBranch " + _xid);
+ }
+
if(_timeoutFuture != null)
{
- _timeoutFuture.cancel(false);
+ if(_logger.isDebugEnabled())
+ {
+ _logger.debug("Attempting to cancel previous timeout task future for DtxBranch " + _xid);
+ }
+
+ boolean succeeded = _timeoutFuture.cancel(false);
_timeoutFuture = null;
+
+ if(_logger.isDebugEnabled())
+ {
+ _logger.debug("Cancelling previous timeout task " + (succeeded ? "succeeded" : "failed")
+ + " for DtxBranch " + _xid);
+ }
}
if(_transaction == null)
@@ -342,7 +406,7 @@ public class DtxBranch
}
catch(AMQStoreException e)
{
- _logger.error("Error while closing XA branch", e);
+ _logger.error("Error while closing DtxBranch " + _xid, e);
}
}
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/txn/DtxRegistry.java b/java/broker/src/main/java/org/apache/qpid/server/txn/DtxRegistry.java
index 5c54c1164f..117beb82ef 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/txn/DtxRegistry.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/txn/DtxRegistry.java
@@ -37,7 +37,7 @@ public class DtxRegistry
private static final class ComparableXid
{
private final Xid _xid;
-
+
private ComparableXid(Xid xid)
{
_xid = xid;
@@ -58,7 +58,7 @@ public class DtxRegistry
ComparableXid that = (ComparableXid) o;
return compareBytes(_xid.getBranchId(), that._xid.getBranchId())
- && compareBytes(_xid.getGlobalId(), that._xid.getGlobalId());
+ && compareBytes(_xid.getGlobalId(), that._xid.getGlobalId());
}
private static boolean compareBytes(byte[] a, byte[] b)
@@ -94,7 +94,7 @@ public class DtxRegistry
return result;
}
}
-
+
public synchronized DtxBranch getBranch(Xid xid)
{
return _branches.get(new ComparableXid(xid));
@@ -116,7 +116,7 @@ public class DtxRegistry
return (_branches.remove(new ComparableXid(branch.getXid())) != null);
}
- public void commit(Xid id, boolean onePhase)
+ public synchronized void commit(Xid id, boolean onePhase)
throws IncorrectDtxStateException, UnknownDtxBranchException, AMQStoreException, RollbackOnlyDtxException, TimeoutDtxException
{
DtxBranch branch = getBranch(id);
@@ -204,7 +204,7 @@ public class DtxRegistry
}
}
- public void rollback(Xid id)
+ public synchronized void rollback(Xid id)
throws IncorrectDtxStateException,
UnknownDtxBranchException,
AMQStoreException, TimeoutDtxException
@@ -318,6 +318,7 @@ public class DtxRegistry
branch.disassociateSession(session);
}
}
+
}
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 11401ebd65..3fbcff7e2c 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
@@ -1,4 +1,3 @@
-package org.apache.qpid.server.txn;
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
@@ -19,7 +18,9 @@ package org.apache.qpid.server.txn;
* under the License.
*
*/
+package org.apache.qpid.server.txn;
+import org.apache.qpid.server.store.StoreFuture;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -50,6 +51,7 @@ public class LocalTransaction implements ServerTransaction
private volatile Transaction _transaction;
private MessageStore _transactionLog;
private long _txnStartTime = 0L;
+ private StoreFuture _asyncTran;
public LocalTransaction(MessageStore transactionLog)
{
@@ -68,11 +70,13 @@ public class LocalTransaction implements ServerTransaction
public void addPostTransactionAction(Action postTransactionAction)
{
+ sync();
_postTransactionActions.add(postTransactionAction);
}
public void dequeue(BaseQueue queue, EnqueableMessage message, Action postTransactionAction)
{
+ sync();
_postTransactionActions.add(postTransactionAction);
if(message.isPersistent() && queue.isDurable())
@@ -98,6 +102,7 @@ public class LocalTransaction implements ServerTransaction
public void dequeue(Collection<QueueEntry> queueEntries, Action postTransactionAction)
{
+ sync();
_postTransactionActions.add(postTransactionAction);
try
@@ -131,10 +136,7 @@ public class LocalTransaction implements ServerTransaction
{
try
{
- for(Action action : _postTransactionActions)
- {
- action.onRollback();
- }
+ doRollbackActions();
}
finally
{
@@ -151,7 +153,7 @@ public class LocalTransaction implements ServerTransaction
}
finally
{
- resetDetails();
+ resetDetails();
}
}
@@ -176,6 +178,7 @@ public class LocalTransaction implements ServerTransaction
public void enqueue(BaseQueue queue, EnqueableMessage message, Action postTransactionAction)
{
+ sync();
_postTransactionActions.add(postTransactionAction);
if(message.isPersistent() && queue.isDurable())
@@ -201,6 +204,7 @@ public class LocalTransaction implements ServerTransaction
public void enqueue(List<? extends BaseQueue> queues, EnqueableMessage message, Action postTransactionAction, long currentTime)
{
+ sync();
_postTransactionActions.add(postTransactionAction);
if (_txnStartTime == 0L)
@@ -239,11 +243,13 @@ public class LocalTransaction implements ServerTransaction
public void commit()
{
+ sync();
commit(null);
}
public void commit(Runnable immediateAction)
{
+ sync();
try
{
if(_transaction != null)
@@ -256,29 +262,137 @@ public class LocalTransaction implements ServerTransaction
immediateAction.run();
}
- for(int i = 0; i < _postTransactionActions.size(); i++)
+ doPostTransactionActions();
+ }
+ catch (Exception e)
+ {
+ _logger.error("Failed to commit transaction", e);
+
+ doRollbackActions();
+ throw new RuntimeException("Failed to commit transaction", e);
+ }
+ finally
+ {
+ resetDetails();
+ }
+ }
+
+ private void doRollbackActions()
+ {
+ for(Action action : _postTransactionActions)
+ {
+ action.onRollback();
+ }
+ }
+
+ public StoreFuture commitAsync(final Runnable deferred)
+ {
+ sync();
+ try
+ {
+ StoreFuture future = StoreFuture.IMMEDIATE_FUTURE;
+ if(_transaction != null)
{
- _postTransactionActions.get(i).postCommit();
+ future = new StoreFuture()
+ {
+ private volatile boolean _completed = false;
+ private StoreFuture _underlying = _transaction.commitTranAsync();
+
+ @Override
+ public boolean isComplete()
+ {
+ return _completed || checkUnderlyingCompletion();
+ }
+
+ @Override
+ public void waitForCompletion()
+ {
+ if(!_completed)
+ {
+ _underlying.waitForCompletion();
+ checkUnderlyingCompletion();
+ }
+ }
+
+ private synchronized boolean checkUnderlyingCompletion()
+ {
+ if(!_completed && _underlying.isComplete())
+ {
+ completeDeferredWork();
+ _completed = true;
+ }
+ return _completed;
+
+ }
+
+ private void completeDeferredWork()
+ {
+ try
+ {
+ doPostTransactionActions();
+ deferred.run();
+
+ }
+ catch (Exception e)
+ {
+ _logger.error("Failed to commit transaction", e);
+
+ doRollbackActions();
+ throw new RuntimeException("Failed to commit transaction", e);
+ }
+ finally
+ {
+ resetDetails();
+ }
+ }
+
+ };
+ _asyncTran = future;
}
+ else
+ {
+ try
+ {
+ doPostTransactionActions();
+
+ deferred.run();
+ }
+ finally
+ {
+ resetDetails();
+ }
+ }
+
+ return future;
}
catch (Exception e)
{
_logger.error("Failed to commit transaction", e);
-
- for(Action action : _postTransactionActions)
+ try
{
- action.onRollback();
+ doRollbackActions();
+ }
+ finally
+ {
+ resetDetails();
}
throw new RuntimeException("Failed to commit transaction", e);
}
- finally
+
+
+ }
+
+ private void doPostTransactionActions()
+ {
+ for(int i = 0; i < _postTransactionActions.size(); i++)
{
- resetDetails();
+ _postTransactionActions.get(i).postCommit();
}
}
public void rollback()
{
+ sync();
try
{
if(_transaction != null)
@@ -295,10 +409,7 @@ public class LocalTransaction implements ServerTransaction
{
try
{
- for(Action action : _postTransactionActions)
- {
- action.onRollback();
- }
+ doRollbackActions();
}
finally
{
@@ -306,9 +417,19 @@ public class LocalTransaction implements ServerTransaction
}
}
}
-
+
+ public void sync()
+ {
+ if(_asyncTran != null)
+ {
+ _asyncTran.waitForCompletion();
+ _asyncTran = null;
+ }
+ }
+
private void resetDetails()
{
+ _asyncTran = null;
_transaction = null;
_postTransactionActions.clear();
_txnStartTime = 0L;
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 523bafb8e1..1b0e50fd34 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
@@ -44,9 +44,9 @@ public abstract class HouseKeepingTask implements Runnable
final public void run()
{
- // Don't need to undo this as this is a thread pool thread so will
- // always go through here before we do any real work.
+ String originalThreadName = Thread.currentThread().getName();
Thread.currentThread().setName(_name);
+
CurrentActor.set(new AbstractActor(_rootLogger)
{
@Override
@@ -67,6 +67,9 @@ public abstract class HouseKeepingTask implements Runnable
finally
{
CurrentActor.remove();
+
+ // eagerly revert the thread name to make thread dumps more meaningful if captured after task has finished
+ Thread.currentThread().setName(originalThreadName);
}
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/virtualhost/State.java b/java/broker/src/main/java/org/apache/qpid/server/virtualhost/State.java
index fb50b3e289..55e2539dcf 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/virtualhost/State.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/virtualhost/State.java
@@ -25,5 +25,7 @@ public enum State
INITIALISING,
ACTIVE,
PASSIVE,
- STOPPED
+ STOPPED,
+ /** Terminal state that signifies the virtual host has experienced an unexpected condition. */
+ ERRORED
}
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 489b985222..f810360662 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
@@ -32,7 +32,6 @@ 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.protocol.v1_0.LinkRegistry;
import org.apache.qpid.server.queue.QueueRegistry;
import org.apache.qpid.server.registry.IApplicationRegistry;
@@ -62,10 +61,10 @@ public interface VirtualHost extends DurableConfigurationStore.Source, VirtualHo
void close();
- ManagedObject getManagedObject();
-
UUID getBrokerId();
+ UUID getId();
+
void scheduleHouseKeepingTask(long period, HouseKeepingTask task);
long getHouseKeepingTaskCount();
@@ -74,7 +73,7 @@ public interface VirtualHost extends DurableConfigurationStore.Source, VirtualHo
int getHouseKeepingPoolSize();
- void setHouseKeepingPoolSize(int newSize);
+ void setHouseKeepingPoolSize(int newSize);
int getHouseKeepingActiveCount();
@@ -102,4 +101,8 @@ public interface VirtualHost extends DurableConfigurationStore.Source, VirtualHo
ScheduledFuture<?> scheduleTask(long delay, Runnable timeoutTask);
State getState();
+
+ public void block();
+
+ public void unblock();
}
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 e956806823..ea2f0f15e4 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
@@ -76,15 +76,12 @@ public class VirtualHostConfigRecoveryHandler implements ConfigurationRecoveryHa
private final VirtualHost _virtualHost;
- private MessageStoreLogSubject _logSubject;
-
- private MessageStore _store;
-
private final Map<String, Integer> _queueRecoveries = new TreeMap<String, Integer>();
- private Map<Long, AbstractServerMessageImpl> _recoveredMessages = new HashMap<Long, AbstractServerMessageImpl>();
- private Map<Long, StoredMessage> _unusedMessages = new HashMap<Long, StoredMessage>();
-
+ private final Map<Long, AbstractServerMessageImpl> _recoveredMessages = new HashMap<Long, AbstractServerMessageImpl>();
+ private final Map<Long, StoredMessage> _unusedMessages = new HashMap<Long, StoredMessage>();
+ private MessageStoreLogSubject _logSubject;
+ private MessageStore _store;
public VirtualHostConfigRecoveryHandler(VirtualHost virtualHost)
{
@@ -100,7 +97,7 @@ public class VirtualHostConfigRecoveryHandler implements ConfigurationRecoveryHa
return this;
}
- public void queue(UUID id, String queueName, String owner, boolean exclusive, FieldTable arguments)
+ public void queue(UUID id, String queueName, String owner, boolean exclusive, FieldTable arguments, UUID alternateExchangeId)
{
try
{
@@ -111,6 +108,17 @@ public class VirtualHostConfigRecoveryHandler implements ConfigurationRecoveryHa
q = AMQQueueFactory.createAMQQueueImpl(id, queueName, true, owner, false, exclusive, _virtualHost,
FieldTable.convertToMap(arguments));
_virtualHost.getQueueRegistry().registerQueue(q);
+
+ if (alternateExchangeId != null)
+ {
+ Exchange altExchange = _virtualHost.getExchangeRegistry().getExchange(alternateExchangeId);
+ if (altExchange == null)
+ {
+ _logger.error("Unknown exchange id " + alternateExchangeId + ", cannot set alternate exchange on queue with id " + id);
+ return;
+ }
+ q.setAlternateExchange(altExchange);
+ }
}
CurrentActor.get().message(_logSubject, TransactionLogMessages.RECOVERY_START(queueName, true));
@@ -120,12 +128,12 @@ public class VirtualHostConfigRecoveryHandler implements ConfigurationRecoveryHa
}
catch (AMQException e)
{
- // TODO
- throw new RuntimeException(e);
+ throw new RuntimeException("Error recovering queue uuid " + id + " name " + queueName, e);
}
}
- public ExchangeRecoveryHandler completeQueueRecovery()
+ @Override
+ public BindingRecoveryHandler completeQueueRecovery()
{
return this;
}
@@ -145,19 +153,17 @@ public class VirtualHostConfigRecoveryHandler implements ConfigurationRecoveryHa
}
catch (AMQException e)
{
- // TODO
- throw new RuntimeException(e);
+ throw new RuntimeException("Error recovering exchange uuid " + id + " name " + exchangeName, e);
}
}
- public BindingRecoveryHandler completeExchangeRecovery()
+ public QueueRecoveryHandler completeExchangeRecovery()
{
return this;
}
public StoredMessageRecoveryHandler begin()
{
- // TODO - log begin
return this;
}
@@ -182,7 +188,6 @@ public class VirtualHostConfigRecoveryHandler implements ConfigurationRecoveryHa
public void completeMessageRecovery()
{
- //TODO - log end
}
public BridgeRecoveryHandler brokerLink(final UUID id,
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 9b113525d4..d9dc0aa64e 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,12 +20,20 @@
*/
package org.apache.qpid.server.virtualhost;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.ScheduledThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
import org.apache.commons.configuration.ConfigurationException;
import org.apache.log4j.Logger;
import org.apache.qpid.AMQException;
import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpid.server.AMQBrokerManagerMBean;
import org.apache.qpid.server.binding.BindingFactory;
import org.apache.qpid.server.configuration.BrokerConfig;
import org.apache.qpid.server.configuration.ConfigStore;
@@ -45,11 +53,10 @@ import org.apache.qpid.server.federation.BrokerLink;
import org.apache.qpid.server.logging.actors.CurrentActor;
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.v1_0.LinkRegistry;
+import org.apache.qpid.server.model.UUIDGenerator;
import org.apache.qpid.server.protocol.AMQConnectionModel;
import org.apache.qpid.server.protocol.AMQSessionModel;
+import org.apache.qpid.server.protocol.v1_0.LinkRegistry;
import org.apache.qpid.server.queue.AMQQueue;
import org.apache.qpid.server.queue.AMQQueueFactory;
import org.apache.qpid.server.queue.DefaultQueueRegistry;
@@ -59,37 +66,25 @@ import org.apache.qpid.server.security.SecurityManager;
import org.apache.qpid.server.stats.StatisticsCounter;
import org.apache.qpid.server.store.Event;
import org.apache.qpid.server.store.EventListener;
+import org.apache.qpid.server.store.HAMessageStore;
import org.apache.qpid.server.store.MessageStore;
-import org.apache.qpid.server.store.MessageStoreFactory;
import org.apache.qpid.server.store.OperationalLoggingListener;
import org.apache.qpid.server.txn.DtxRegistry;
import org.apache.qpid.server.virtualhost.plugins.VirtualHostPlugin;
import org.apache.qpid.server.virtualhost.plugins.VirtualHostPluginFactory;
-import javax.management.JMException;
-import javax.management.NotCompliantMBeanException;
-import javax.management.ObjectName;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.UUID;
-import java.util.concurrent.BlockingQueue;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ScheduledFuture;
-import java.util.concurrent.ScheduledThreadPoolExecutor;
-import java.util.concurrent.TimeUnit;
-
-
-public class VirtualHostImpl implements VirtualHost
+public class VirtualHostImpl implements VirtualHost, IConnectionRegistry.RegistryChangeListener, EventListener
{
private static final Logger _logger = Logger.getLogger(VirtualHostImpl.class);
private static final int HOUSEKEEPING_SHUTDOWN_TIMEOUT = 5;
- private final UUID _id;
+ private final UUID _qmfId;
private final String _name;
+ private final UUID _id;
+
private final long _createTime = System.currentTimeMillis();
private final ConcurrentHashMap<BrokerLink,BrokerLink> _links = new ConcurrentHashMap<BrokerLink, BrokerLink>();
@@ -104,10 +99,6 @@ public class VirtualHostImpl implements VirtualHost
private final VirtualHostConfiguration _vhostConfig;
- private final VirtualHostMBean _virtualHostMBean;
-
- private final AMQBrokerManagerMBean _brokerMBean;
-
private final QueueRegistry _queueRegistry;
private final ExchangeRegistry _exchangeRegistry;
@@ -122,13 +113,12 @@ public class VirtualHostImpl implements VirtualHost
private final MessageStore _messageStore;
- private State _state = State.INITIALISING;
-
- private boolean _statisticsEnabled = false;
+ private volatile State _state = State.INITIALISING;
private StatisticsCounter _messagesDelivered, _dataDelivered, _messagesReceived, _dataReceived;
private final Map<String, LinkRegistry> _linkRegistry = new HashMap<String, LinkRegistry>();
+ private boolean _blocked;
public VirtualHostImpl(IApplicationRegistry appRegistry, VirtualHostConfiguration hostConfig) throws Exception
{
@@ -143,20 +133,21 @@ public class VirtualHostImpl implements VirtualHost
}
_appRegistry = appRegistry;
- _brokerConfig = _appRegistry.getBroker();
+ _brokerConfig = _appRegistry.getBrokerConfig();
_vhostConfig = hostConfig;
_name = _vhostConfig.getName();
_dtxRegistry = new DtxRegistry();
- _id = _appRegistry.getConfigStore().createId();
+ _qmfId = _appRegistry.getConfigStore().createId();
+ _id = UUIDGenerator.generateVhostUUID(_name);
CurrentActor.get().message(VirtualHostMessages.CREATED(_name));
- _virtualHostMBean = new VirtualHostMBean();
_securityManager = new SecurityManager(_appRegistry.getSecurityManager());
_securityManager.configureHostPlugins(_vhostConfig);
_connectionRegistry = new ConnectionRegistry();
+ _connectionRegistry.addRegistryChangeListener(this);
_houseKeepingTasks = new ScheduledThreadPoolExecutor(_vhostConfig.getHouseKeepingThreadCount());
@@ -169,15 +160,16 @@ public class VirtualHostImpl implements VirtualHost
_bindingFactory = new BindingFactory(this);
- _brokerMBean = new AMQBrokerManagerMBean(_virtualHostMBean);
-
- _messageStore = initialiseMessageStore(hostConfig.getMessageStoreFactoryClass());
+ _messageStore = initialiseMessageStore(hostConfig.getMessageStoreClass());
configureMessageStore(hostConfig);
activateNonHAMessageStore();
initialiseStatistics();
+
+ _messageStore.addEventListener(this, Event.PERSISTENT_MESSAGE_SIZE_OVERFULL);
+ _messageStore.addEventListener(this, Event.PERSISTENT_MESSAGE_SIZE_UNDERFULL);
}
public IConnectionRegistry getConnectionRegistry()
@@ -195,6 +187,12 @@ public class VirtualHostImpl implements VirtualHost
return _id;
}
+ @Override
+ public UUID getQMFId()
+ {
+ return _qmfId;
+ }
+
public VirtualHostConfigType getConfigType()
{
return VirtualHostConfigType.getInstance();
@@ -324,20 +322,19 @@ public class VirtualHostImpl implements VirtualHost
}
- private MessageStore initialiseMessageStore(final String messageStoreFactoryClass) throws Exception
+ private MessageStore initialiseMessageStore(final String messageStoreClass) throws Exception
{
- final Class<?> clazz = Class.forName(messageStoreFactoryClass);
+ final Class<?> clazz = Class.forName(messageStoreClass);
final Object o = clazz.newInstance();
- if (!(o instanceof MessageStoreFactory))
+ if (!(o instanceof MessageStore))
{
- throw new ClassCastException("Message store factory class must implement " + MessageStoreFactory.class +
+ throw new ClassCastException("Message store factory class must implement " + MessageStore.class +
". Class " + clazz + " does not.");
}
- final MessageStoreFactory messageStoreFactory = (MessageStoreFactory) o;
- final MessageStore messageStore = messageStoreFactory.createMessageStore();
- final MessageStoreLogSubject storeLogSubject = new MessageStoreLogSubject(this, messageStoreFactory.getStoreClassName());
+ final MessageStore messageStore = (MessageStore) o;
+ final MessageStoreLogSubject storeLogSubject = new MessageStoreLogSubject(this, clazz.getSimpleName());
OperationalLoggingListener.listen(messageStore, storeLogSubject);
messageStore.addEventListener(new BeforeActivationListener(), Event.BEFORE_ACTIVATE);
@@ -361,7 +358,10 @@ public class VirtualHostImpl implements VirtualHost
private void activateNonHAMessageStore() throws Exception
{
- _messageStore.activate();
+ if (!(_messageStore instanceof HAMessageStore))
+ {
+ _messageStore.activate();
+ }
}
private void initialiseModel(VirtualHostConfiguration config) throws ConfigurationException, AMQException
@@ -534,16 +534,6 @@ public class VirtualHostImpl implements VirtualHost
CurrentActor.get().message(VirtualHostMessages.CLOSED());
}
- public ManagedObject getBrokerMBean()
- {
- return _brokerMBean;
- }
-
- public ManagedObject getManagedObject()
- {
- return _virtualHostMBean;
- }
-
public UUID getBrokerId()
{
return _appRegistry.getBrokerId();
@@ -558,54 +548,48 @@ public class VirtualHostImpl implements VirtualHost
{
return _bindingFactory;
}
-
+
public void registerMessageDelivered(long messageSize)
{
- if (isStatisticsEnabled())
- {
- _messagesDelivered.registerEvent(1L);
- _dataDelivered.registerEvent(messageSize);
- }
+ _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);
- }
+ _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();
@@ -614,25 +598,12 @@ public class VirtualHostImpl implements VirtualHost
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 BrokerLink createBrokerConnection(UUID id, long createTime, Map<String,String> arguments)
{
BrokerLink blink = new BrokerLink(this, id, createTime, arguments);
@@ -699,107 +670,155 @@ public class VirtualHostImpl implements VirtualHost
return _dtxRegistry;
}
- @Override
public String toString()
{
return _name;
}
- @Override
public State getState()
{
return _state;
}
-
- /**
- * Virtual host JMX MBean class.
- *
- * This has some of the methods implemented from management interface for exchanges. Any
- * Implementation of an Exchange MBean should extend this class.
- */
- public class VirtualHostMBean extends AMQManagedObject implements ManagedVirtualHost
+ public void block()
{
- public VirtualHostMBean() throws NotCompliantMBeanException
+ synchronized (_connectionRegistry)
{
- super(ManagedVirtualHost.class, ManagedVirtualHost.TYPE);
+ if(!_blocked)
+ {
+ _blocked = true;
+ for(AMQConnectionModel conn : _connectionRegistry.getConnections())
+ {
+ conn.block();
+ }
+ }
}
+ }
- public String getObjectInstanceName()
- {
- return ObjectName.quote(_name);
- }
- public String getName()
+ public void unblock()
+ {
+ synchronized (_connectionRegistry)
{
- return _name;
+ if(_blocked)
+ {
+ _blocked = false;
+ for(AMQConnectionModel conn : _connectionRegistry.getConnections())
+ {
+ conn.unblock();
+ }
+ }
}
+ }
- public VirtualHostImpl getVirtualHost()
+ public void connectionRegistered(final AMQConnectionModel connection)
+ {
+ if(_blocked)
{
- return VirtualHostImpl.this;
+ connection.block();
}
}
- private final class BeforeActivationListener implements EventListener
+ public void connectionUnregistered(final AMQConnectionModel connection)
{
- @Override
- public void event(Event event)
+ }
+
+ public void event(final Event event)
+ {
+ switch(event)
{
- try
- {
- _exchangeRegistry.initialise();
- initialiseModel(_vhostConfig);
- } catch (Exception e)
- {
- throw new RuntimeException("Failed to initialise virtual host after state change", e);
- }
+ case PERSISTENT_MESSAGE_SIZE_OVERFULL:
+ block();
+ break;
+ case PERSISTENT_MESSAGE_SIZE_UNDERFULL:
+ unblock();
+ break;
}
}
- private final class AfterActivationListener implements EventListener
+ private final class BeforeActivationListener implements EventListener
+ {
+ @Override
+ public void event(Event event)
+ {
+ try
+ {
+ _exchangeRegistry.initialise();
+ initialiseModel(_vhostConfig);
+ }
+ catch (Exception e)
+ {
+ throw new RuntimeException("Failed to initialise virtual host after state change", e);
+ }
+ }
+ }
+
+ private final class AfterActivationListener implements EventListener
+ {
+ @Override
+ public void event(Event event)
+ {
+ State finalState = State.ERRORED;
+
+ try
+ {
+ initialiseHouseKeeping(_vhostConfig.getHousekeepingCheckPeriod());
+ finalState = State.ACTIVE;
+ }
+ finally
+ {
+ _state = finalState;
+ reportIfError(_state);
+ }
+ }
+ }
+
+ private final class BeforePassivationListener implements EventListener
{
- @Override
public void event(Event event)
{
- initialiseHouseKeeping(_vhostConfig.getHousekeepingCheckPeriod());
+ State finalState = State.ERRORED;
+
try
{
- _brokerMBean.register();
- } catch (JMException e)
+ /* the approach here is not ideal as there is a race condition where a
+ * queue etc could be created while the virtual host is on the way to
+ * the passivated state. However the store state change from MASTER to UNKNOWN
+ * is documented as exceptionally rare..
+ */
+
+ _connectionRegistry.close(IConnectionRegistry.VHOST_PASSIVATE_REPLY_TEXT);
+ removeHouseKeepingTasks();
+
+ _queueRegistry.stopAllAndUnregisterMBeans();
+ _exchangeRegistry.clearAndUnregisterMbeans();
+ _dtxRegistry.close();
+
+ finalState = State.PASSIVE;
+ }
+ finally
{
- throw new RuntimeException("Failed to register virtual host mbean for virtual host " + getName(), e);
+ _state = finalState;
+ reportIfError(_state);
}
-
- _state = State.ACTIVE;
}
+
}
- public class BeforePassivationListener implements EventListener
+ private final class BeforeCloseListener implements EventListener
{
-
@Override
public void event(Event event)
{
- _connectionRegistry.close(IConnectionRegistry.VHOST_PASSIVATE_REPLY_TEXT);
- _brokerMBean.unregister();
- removeHouseKeepingTasks();
-
- _queueRegistry.stopAllAndUnregisterMBeans();
- _exchangeRegistry.clearAndUnregisterMbeans();
- _dtxRegistry.close();
-
- _state = State.PASSIVE;
+ shutdownHouseKeeping();
}
}
- private final class BeforeCloseListener implements EventListener
+ private void reportIfError(State state)
{
- @Override
- public void event(Event event)
+ if (state == State.ERRORED)
{
- _brokerMBean.unregister();
- shutdownHouseKeeping();
+ CurrentActor.get().message(VirtualHostMessages.ERRORED());
}
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostRegistry.java b/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostRegistry.java
index ef621a166a..1be472844a 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostRegistry.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostRegistry.java
@@ -22,10 +22,12 @@ package org.apache.qpid.server.virtualhost;
import org.apache.qpid.common.Closeable;
import org.apache.qpid.server.configuration.ConfigStore;
+import org.apache.qpid.server.exchange.ExchangeRegistry;
import org.apache.qpid.server.registry.ApplicationRegistry;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.Collections;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@@ -37,6 +39,8 @@ public class VirtualHostRegistry implements Closeable
private String _defaultVirtualHostName;
private ApplicationRegistry _applicationRegistry;
+ private final Collection<RegistryChangeListener> _listeners =
+ Collections.synchronizedCollection(new ArrayList<RegistryChangeListener>());
public VirtualHostRegistry(ApplicationRegistry applicationRegistry)
{
@@ -50,11 +54,25 @@ public class VirtualHostRegistry implements Closeable
throw new Exception("Virtual Host with name " + host.getName() + " already registered.");
}
_registry.put(host.getName(),host);
+ synchronized (_listeners)
+ {
+ for(RegistryChangeListener listener : _listeners)
+ {
+ listener.virtualHostRegistered(host);
+ }
+ }
}
public synchronized void unregisterVirtualHost(VirtualHost host)
{
_registry.remove(host.getName());
+ synchronized (_listeners)
+ {
+ for(RegistryChangeListener listener : _listeners)
+ {
+ listener.virtualHostUnregistered(host);
+ }
+ }
}
public VirtualHost getVirtualHost(String name)
@@ -106,4 +124,17 @@ public class VirtualHostRegistry implements Closeable
}
}
+
+ public static interface RegistryChangeListener
+ {
+ void virtualHostRegistered(VirtualHost virtualHost);
+ void virtualHostUnregistered(VirtualHost virtualHost);
+
+ }
+
+ public void addRegistryChangeListener(RegistryChangeListener listener)
+ {
+ _listeners.add(listener);
+ }
+
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/virtualhost/plugins/SlowConsumerDetection.java b/java/broker/src/main/java/org/apache/qpid/server/virtualhost/plugins/SlowConsumerDetection.java
index 2c6705bb3b..bd2e30449a 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/virtualhost/plugins/SlowConsumerDetection.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/virtualhost/plugins/SlowConsumerDetection.java
@@ -1,5 +1,6 @@
/*
*
+ * Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
diff --git a/java/broker/src/test/java/org/apache/log4j/xml/QpidLog4JConfiguratorTest.java b/java/broker/src/test/java/org/apache/log4j/xml/QpidLog4JConfiguratorTest.java
deleted file mode 100644
index c06ce5e31a..0000000000
--- a/java/broker/src/test/java/org/apache/log4j/xml/QpidLog4JConfiguratorTest.java
+++ /dev/null
@@ -1,395 +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.log4j.xml;
-
-
-import junit.framework.TestCase;
-import org.apache.log4j.xml.QpidLog4JConfigurator.IllegalLoggerLevelException;
-
-import java.io.BufferedWriter;
-import java.io.File;
-import java.io.FileWriter;
-import java.io.IOException;
-
-public class QpidLog4JConfiguratorTest extends TestCase
-{
- private static final String NEWLINE = System.getProperty("line.separator");
-
- private File _testConfigFile;
-
- private File createTempTestLog4JConfig(String loggerLevel,String rootLoggerLevel, boolean missingTagClose, boolean incorrectAttribute)
- {
- File tmpFile = null;
- try
- {
- tmpFile = File.createTempFile("QpidLog4JConfiguratorTestLog4jConfig", ".tmp");
- tmpFile.deleteOnExit();
-
- FileWriter fstream = new FileWriter(tmpFile);
- BufferedWriter writer = new BufferedWriter(fstream);
-
- writer.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"+NEWLINE);
- writer.write("<!DOCTYPE log4j:configuration SYSTEM \"log4j.dtd\">"+NEWLINE);
-
- writer.write("<log4j:configuration xmlns:log4j=\"http://jakarta.apache.org/log4j/\" debug=\"null\" " +
- "threshold=\"null\">"+NEWLINE);
-
- writer.write(" <appender class=\"org.apache.log4j.ConsoleAppender\" name=\"STDOUT\">"+NEWLINE);
- writer.write(" <layout class=\"org.apache.log4j.PatternLayout\">"+NEWLINE);
- writer.write(" <param name=\"ConversionPattern\" value=\"%d %-5p [%t] %C{2} (%F:%L) - %m%n\"/>"+NEWLINE);
- writer.write(" </layout>"+NEWLINE);
- writer.write(" </appender>"+NEWLINE);
-
- String closeTag="/";
- if(missingTagClose)
- {
- closeTag="";
- }
-
- //Example of a 'category' with a 'priority'
- writer.write(" <category additivity=\"true\" name=\"logger1\">"+NEWLINE);
- writer.write(" <priority value=\"" + loggerLevel+ "\"" + closeTag + ">"+NEWLINE);
- writer.write(" <appender-ref ref=\"STDOUT\"/>"+NEWLINE);
- writer.write(" </category>"+NEWLINE);
-
- String attributeName="value";
- if(incorrectAttribute)
- {
- attributeName="values";
- }
-
- //Example of a 'category' with a 'level'
- writer.write(" <category additivity=\"true\" name=\"logger2\">"+NEWLINE);
- writer.write(" <level " + attributeName + "=\"" + loggerLevel+ "\"/>"+NEWLINE);
- writer.write(" <appender-ref ref=\"STDOUT\"/>"+NEWLINE);
- writer.write(" </category>"+NEWLINE);
-
- //Example of a 'logger' with a 'level'
- writer.write(" <logger additivity=\"true\" name=\"logger3\">"+NEWLINE);
- writer.write(" <level value=\"" + loggerLevel+ "\"/>"+NEWLINE);
- writer.write(" <appender-ref ref=\"STDOUT\"/>"+NEWLINE);
- writer.write(" </logger>"+NEWLINE);
-
- //'root' logger
- writer.write(" <root>"+NEWLINE);
- writer.write(" <priority value=\"" + rootLoggerLevel+ "\"/>"+NEWLINE);
- writer.write(" <appender-ref ref=\"STDOUT\"/>"+NEWLINE);
- writer.write(" </root>"+NEWLINE);
-
- writer.write("</log4j:configuration>"+NEWLINE);
-
- writer.flush();
- writer.close();
- }
- catch (IOException e)
- {
- fail("Unable to create temporary test log4j configuration");
- }
-
- return tmpFile;
- }
-
-
-
- //******* Test Methods ******* //
-
- public void testCheckLevelsAndStrictParser()
- {
- //try the valid logger levels
- _testConfigFile = createTempTestLog4JConfig("all", "info", false, false);
- try
- {
- QpidLog4JConfigurator.checkLoggerLevels(_testConfigFile.getAbsolutePath());
- }
- catch (Exception e)
- {
- fail("No exception expected, valid levels and xml were used");
- }
-
- _testConfigFile = createTempTestLog4JConfig("trace", "info", false, false);
- try
- {
- QpidLog4JConfigurator.checkLoggerLevels(_testConfigFile.getAbsolutePath());
- }
- catch (Exception e)
- {
- fail("No exception expected, valid levels and xml were used");
- }
-
- _testConfigFile = createTempTestLog4JConfig("debug", "info", false, false);
- try
- {
- QpidLog4JConfigurator.checkLoggerLevels(_testConfigFile.getAbsolutePath());
- }
- catch (Exception e)
- {
- fail("No exception expected, valid levels and xml were used");
- }
-
- _testConfigFile = createTempTestLog4JConfig("info", "info", false, false);
- try
- {
- QpidLog4JConfigurator.checkLoggerLevels(_testConfigFile.getAbsolutePath());
- }
- catch (Exception e)
- {
- fail("No exception expected, valid levels and xml were used");
- }
-
- _testConfigFile = createTempTestLog4JConfig("warn", "info", false, false);
- try
- {
- QpidLog4JConfigurator.checkLoggerLevels(_testConfigFile.getAbsolutePath());
- }
- catch (Exception e)
- {
- fail("No exception expected, valid levels and xml were used");
- }
-
- _testConfigFile = createTempTestLog4JConfig("error", "info", false, false);
- try
- {
- QpidLog4JConfigurator.checkLoggerLevels(_testConfigFile.getAbsolutePath());
- }
- catch (Exception e)
- {
- fail("No exception expected, valid levels and xml were used");
- }
-
- _testConfigFile = createTempTestLog4JConfig("fatal", "info", false, false);
- try
- {
- QpidLog4JConfigurator.checkLoggerLevels(_testConfigFile.getAbsolutePath());
- }
- catch (Exception e)
- {
- fail("No exception expected, valid levels and xml were used");
- }
-
- _testConfigFile = createTempTestLog4JConfig("off", "info", false, false);
- try
- {
- QpidLog4JConfigurator.checkLoggerLevels(_testConfigFile.getAbsolutePath());
- }
- catch (Exception e)
- {
- fail("No exception expected, valid levels and xml were used");
- }
-
- _testConfigFile = createTempTestLog4JConfig("null", "info", false, false);
- try
- {
- QpidLog4JConfigurator.checkLoggerLevels(_testConfigFile.getAbsolutePath());
- }
- catch (Exception e)
- {
- fail("No exception expected, valid levels and xml were used");
- }
-
- _testConfigFile = createTempTestLog4JConfig("inherited", "info", false, false);
- try
- {
- QpidLog4JConfigurator.checkLoggerLevels(_testConfigFile.getAbsolutePath());
- }
- catch (Exception e)
- {
- fail("No exception expected, valid levels and xml were used");
- }
-
- //now try an invalid logger level
- _testConfigFile = createTempTestLog4JConfig("madeup", "info", false, false);
- try
- {
- QpidLog4JConfigurator.checkLoggerLevels(_testConfigFile.getAbsolutePath());
- fail("IllegalLoggerLevelException expected, invalid levels used");
- }
- catch (IllegalLoggerLevelException e)
- {
- //expected, ignore
- }
- catch (IOException e)
- {
- fail("Incorrect Exception, expected an IllegalLoggerLevelException");
- }
-
-
-
- //now try the valid rootLogger levels
- _testConfigFile = createTempTestLog4JConfig("info", "all", false, false);
- try
- {
- QpidLog4JConfigurator.checkLoggerLevels(_testConfigFile.getAbsolutePath());
- }
- catch (Exception e)
- {
- fail("No exception expected, valid levels and xml were used");
- }
-
- _testConfigFile = createTempTestLog4JConfig("info", "trace", false, false);
- try
- {
- QpidLog4JConfigurator.checkLoggerLevels(_testConfigFile.getAbsolutePath());
- }
- catch (Exception e)
- {
- fail("No exception expected, valid levels and xml were used");
- }
-
- _testConfigFile = createTempTestLog4JConfig("info", "debug", false, false);
- try
- {
- QpidLog4JConfigurator.checkLoggerLevels(_testConfigFile.getAbsolutePath());
- }
- catch (Exception e)
- {
- fail("No exception expected, valid levels and xml were used");
- }
-
- _testConfigFile = createTempTestLog4JConfig("info", "info", false, false);
- try
- {
- QpidLog4JConfigurator.checkLoggerLevels(_testConfigFile.getAbsolutePath());
- }
- catch (Exception e)
- {
- fail("No exception expected, valid levels and xml were used");
- }
-
- _testConfigFile = createTempTestLog4JConfig("info", "warn", false, false);
- try
- {
- QpidLog4JConfigurator.checkLoggerLevels(_testConfigFile.getAbsolutePath());
- }
- catch (Exception e)
- {
- fail("No exception expected, valid levels and xml were used");
- }
-
- _testConfigFile = createTempTestLog4JConfig("info", "error", false, false);
- try
- {
- QpidLog4JConfigurator.checkLoggerLevels(_testConfigFile.getAbsolutePath());
- }
- catch (Exception e)
- {
- fail("No exception expected, valid levels and xml were used");
- }
-
- _testConfigFile = createTempTestLog4JConfig("info", "fatal", false, false);
- try
- {
- QpidLog4JConfigurator.checkLoggerLevels(_testConfigFile.getAbsolutePath());
- }
- catch (Exception e)
- {
- fail("No exception expected, valid levels and xml were used");
- }
-
- _testConfigFile = createTempTestLog4JConfig("info", "off", false, false);
- try
- {
- QpidLog4JConfigurator.checkLoggerLevels(_testConfigFile.getAbsolutePath());
- }
- catch (Exception e)
- {
- fail("No exception expected, valid levels and xml were used");
- }
-
- _testConfigFile = createTempTestLog4JConfig("info", "null", false, false);
- try
- {
- QpidLog4JConfigurator.checkLoggerLevels(_testConfigFile.getAbsolutePath());
- }
- catch (Exception e)
- {
- fail("No exception expected, valid levels and xml were used");
- }
-
- _testConfigFile = createTempTestLog4JConfig("info", "inherited", false, false);
- try
- {
- QpidLog4JConfigurator.checkLoggerLevels(_testConfigFile.getAbsolutePath());
- }
- catch (Exception e)
- {
- fail("No exception expected, valid levels and xml were used");
- }
-
- _testConfigFile = createTempTestLog4JConfig("info", "debug", false, false);
- try
- {
- QpidLog4JConfigurator.checkLoggerLevels(_testConfigFile.getAbsolutePath());
- }
- catch (Exception e)
- {
- fail("No exception expected, valid levels and xml were used");
- }
-
- //now try an invalid logger level
- _testConfigFile = createTempTestLog4JConfig("info", "madeup", false, false);
- try
- {
- QpidLog4JConfigurator.checkLoggerLevels(_testConfigFile.getAbsolutePath());
- fail("IllegalLoggerLevelException expected, invalid levels used");
- }
- catch (IllegalLoggerLevelException e)
- {
- //expected, ignore
- }
- catch (IOException e)
- {
- fail("Incorrect Exception, expected an IllegalLoggerLevelException");
- }
-
-
-
- //now try invalid xml
- _testConfigFile = createTempTestLog4JConfig("info", "info", true, false);
- try
- {
- QpidLog4JConfigurator.checkLoggerLevels(_testConfigFile.getAbsolutePath());
- fail("IOException expected, malformed XML used");
- }
- catch (IllegalLoggerLevelException e)
- {
- fail("Incorrect Exception, expected an IOException");
- }
- catch (IOException e)
- {
- //expected, ignore
- }
-
- _testConfigFile = createTempTestLog4JConfig("info", "info", false, true);
- try
- {
- QpidLog4JConfigurator.checkLoggerLevels(_testConfigFile.getAbsolutePath());
- fail("IOException expected, malformed XML used");
- }
- catch (IllegalLoggerLevelException e)
- {
- //expected, ignore
- }
- catch (IOException e)
- {
- fail("Incorrect Exception, expected an IllegalLoggerLevelException");
- }
- }
-}
diff --git a/java/broker/src/test/java/org/apache/qpid/server/AMQBrokerManagerMBeanTest.java b/java/broker/src/test/java/org/apache/qpid/server/AMQBrokerManagerMBeanTest.java
deleted file mode 100644
index 5c500771c2..0000000000
--- a/java/broker/src/test/java/org/apache/qpid/server/AMQBrokerManagerMBeanTest.java
+++ /dev/null
@@ -1,195 +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 org.apache.commons.configuration.XMLConfiguration;
-
-import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpid.management.common.mbeans.ManagedBroker;
-import org.apache.qpid.server.configuration.ServerConfiguration;
-import org.apache.qpid.server.exchange.Exchange;
-import org.apache.qpid.server.exchange.ExchangeRegistry;
-import org.apache.qpid.server.logging.SystemOutMessageLogger;
-import org.apache.qpid.server.logging.actors.CurrentActor;
-import org.apache.qpid.server.logging.actors.TestLogActor;
-import org.apache.qpid.server.queue.AMQPriorityQueue;
-import org.apache.qpid.server.queue.AMQQueue;
-import org.apache.qpid.server.queue.AMQQueueFactory;
-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.store.TestableMemoryMessageStore;
-import org.apache.qpid.server.store.TestableMemoryMessageStoreFactory;
-import org.apache.qpid.server.util.TestApplicationRegistry;
-import org.apache.qpid.server.virtualhost.VirtualHost;
-import org.apache.qpid.server.virtualhost.VirtualHostImpl;
-import org.apache.qpid.test.utils.QpidTestCase;
-
-import java.util.HashMap;
-import java.util.Map;
-
-public class AMQBrokerManagerMBeanTest extends QpidTestCase
-{
- private QueueRegistry _queueRegistry;
- private ExchangeRegistry _exchangeRegistry;
- private VirtualHost _vHost;
-
- public void testExchangeOperations() throws Exception
- {
- String exchange1 = "testExchange1_" + System.currentTimeMillis();
- String exchange2 = "testExchange2_" + System.currentTimeMillis();
- String exchange3 = "testExchange3_" + System.currentTimeMillis();
-
- assertTrue(_exchangeRegistry.getExchange(new AMQShortString(exchange1)) == null);
- assertTrue(_exchangeRegistry.getExchange(new AMQShortString(exchange2)) == null);
- assertTrue(_exchangeRegistry.getExchange(new AMQShortString(exchange3)) == null);
-
-
- ManagedBroker mbean = new AMQBrokerManagerMBean((VirtualHostImpl.VirtualHostMBean) _vHost.getManagedObject());
- mbean.createNewExchange(exchange1, "direct", false);
- mbean.createNewExchange(exchange2, "topic", false);
- mbean.createNewExchange(exchange3, "headers", false);
-
- assertTrue(_exchangeRegistry.getExchange(new AMQShortString(exchange1)) != null);
- assertTrue(_exchangeRegistry.getExchange(new AMQShortString(exchange2)) != null);
- assertTrue(_exchangeRegistry.getExchange(new AMQShortString(exchange3)) != null);
-
- mbean.unregisterExchange(exchange1);
- mbean.unregisterExchange(exchange2);
- mbean.unregisterExchange(exchange3);
-
- assertTrue(_exchangeRegistry.getExchange(new AMQShortString(exchange1)) == null);
- assertTrue(_exchangeRegistry.getExchange(new AMQShortString(exchange2)) == null);
- assertTrue(_exchangeRegistry.getExchange(new AMQShortString(exchange3)) == null);
- }
-
- public void testQueueOperations() throws Exception
- {
- String queueName = "testQueue_" + System.currentTimeMillis();
-
- ManagedBroker mbean = new AMQBrokerManagerMBean((VirtualHostImpl.VirtualHostMBean) _vHost.getManagedObject());
-
- assertTrue(_queueRegistry.getQueue(new AMQShortString(queueName)) == null);
-
- mbean.createNewQueue(queueName, "test", false);
- assertTrue(_queueRegistry.getQueue(new AMQShortString(queueName)) != null);
-
- mbean.deleteQueue(queueName);
- assertTrue(_queueRegistry.getQueue(new AMQShortString(queueName)) == null);
- }
-
- public void testCreateNewQueueBindsToDefaultExchange() throws Exception
- {
- String queueName = "testQueue_" + System.currentTimeMillis();
-
- ManagedBroker mbean = new AMQBrokerManagerMBean((VirtualHostImpl.VirtualHostMBean) _vHost.getManagedObject());
- ExchangeRegistry exReg = _vHost.getExchangeRegistry();
- Exchange defaultExchange = exReg.getDefaultExchange();
-
- mbean.createNewQueue(queueName, "test", false);
- assertTrue(_queueRegistry.getQueue(new AMQShortString(queueName)) != null);
-
- assertTrue("New queue should be bound to default exchange", defaultExchange.isBound(new AMQShortString(queueName)));
- }
-
- /**
- * Tests that setting the {@link AMQQueueFactory#X_QPID_MAXIMUM_DELIVERY_COUNT} argument does cause the
- * maximum delivery count to be set on the Queue.
- */
- public void testCreateNewQueueWithMaximumDeliveryCount() throws Exception
- {
- final Map<String,Object> args = new HashMap<String, Object>();
- args.put(AMQQueueFactory.X_QPID_MAXIMUM_DELIVERY_COUNT, 5);
-
- final AMQShortString queueName = new AMQShortString("testCreateNewQueueWithMaximumDeliveryCount");
-
- final QueueRegistry qReg = _vHost.getQueueRegistry();
-
- assertNull("The queue should not yet exist", qReg.getQueue(queueName));
-
- final ManagedBroker mbean = new AMQBrokerManagerMBean((VirtualHostImpl.VirtualHostMBean) _vHost.getManagedObject());
- mbean.createNewQueue(queueName.asString(), "test", false, args);
-
- final AMQQueue createdQueue = qReg.getQueue(queueName);
- assertNotNull("The queue was not registered as expected", createdQueue);
- assertEquals("Unexpected maximum delivery count", 5, createdQueue.getMaximumDeliveryCount());
- }
-
- /**
- * Tests that setting the {@link AMQQueueFactory#X_QPID_PRIORITIES} argument prompts creation of
- * a Priority Queue.
- */
- public void testCreatePriorityQueue() throws Exception
- {
- int numPriorities = 7;
- Map<String,Object> args = new HashMap<String, Object>();
- args.put(AMQQueueFactory.X_QPID_PRIORITIES, numPriorities);
-
- AMQShortString queueName = new AMQShortString("testCreatePriorityQueue");
-
- QueueRegistry qReg = _vHost.getQueueRegistry();
-
- assertNull("The queue should not yet exist", qReg.getQueue(queueName));
-
- ManagedBroker mbean = new AMQBrokerManagerMBean((VirtualHostImpl.VirtualHostMBean) _vHost.getManagedObject());
- mbean.createNewQueue(queueName.asString(), "test", false, args);
-
- AMQQueue queue = qReg.getQueue(queueName);
- assertEquals("Queue is not a priorty queue", AMQPriorityQueue.class, queue.getClass());
- assertEquals("Number of priorities supported was not as expected", numPriorities, ((AMQPriorityQueue)queue).getPriorities());
- }
-
- @Override
- public void setUp() throws Exception
- {
- super.setUp();
-
- CurrentActor.set(new TestLogActor(new SystemOutMessageLogger()));
-
- XMLConfiguration configXml = new XMLConfiguration();
- configXml.addProperty("virtualhosts.virtualhost(-1).name", "test");
- configXml.addProperty("virtualhosts.virtualhost(-1).test.store.factoryclass", TestableMemoryMessageStoreFactory.class.getName());
-
- ServerConfiguration configuration = new ServerConfiguration(configXml);
-
- ApplicationRegistry registry = new TestApplicationRegistry(configuration);
- ApplicationRegistry.initialise(registry);
- registry.getVirtualHostRegistry().setDefaultVirtualHostName("test");
-
- IApplicationRegistry appRegistry = ApplicationRegistry.getInstance();
- _vHost = appRegistry.getVirtualHostRegistry().getVirtualHost("test");
- _queueRegistry = _vHost.getQueueRegistry();
- _exchangeRegistry = _vHost.getExchangeRegistry();
- }
-
- @Override
- public void tearDown() throws Exception
- {
- try
- {
- super.tearDown();
- }
- finally
- {
- ApplicationRegistry.remove();
- }
- }
-}
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
index bb20e0200b..43824e713f 100644
--- a/java/broker/src/test/java/org/apache/qpid/server/BrokerOptionsTest.java
+++ b/java/broker/src/test/java/org/apache/qpid/server/BrokerOptionsTest.java
@@ -199,4 +199,31 @@ public class BrokerOptionsTest extends QpidTestCase
_options.setLogWatchFrequency(myFreq);
assertEquals(myFreq, _options.getLogWatchFrequency());
}
+
+ public void testDefaultIncludesPortFor0_10()
+ {
+ assertEquals(Collections.EMPTY_SET, _options.getIncludedPorts(ProtocolInclusion.v0_10));
+ }
+
+ public void testOverriddenIncludesPortFor0_10()
+ {
+ _options.addIncludedPort(ProtocolInclusion.v0_10, TEST_PORT1);
+ assertEquals(Collections.singleton(TEST_PORT1), _options.getIncludedPorts(ProtocolInclusion.v0_10));
+ }
+
+ public void testManyOverriddenIncludedPortFor0_10()
+ {
+ _options.addIncludedPort(ProtocolInclusion.v0_10, TEST_PORT1);
+ _options.addIncludedPort(ProtocolInclusion.v0_10, TEST_PORT2);
+ final Set<Integer> expectedPorts = new HashSet<Integer>(Arrays.asList(new Integer[] {TEST_PORT1, TEST_PORT2}));
+ assertEquals(expectedPorts, _options.getIncludedPorts(ProtocolInclusion.v0_10));
+ }
+
+ public void testDuplicatedOverriddenIncludedPortFor0_10AreSilentlyIgnored()
+ {
+ _options.addIncludedPort(ProtocolInclusion.v0_10, TEST_PORT1);
+ _options.addIncludedPort(ProtocolInclusion.v0_10, TEST_PORT2);
+ final Set<Integer> expectedPorts = new HashSet<Integer>(Arrays.asList(new Integer[] {TEST_PORT1, TEST_PORT2}));
+ assertEquals(expectedPorts, _options.getIncludedPorts(ProtocolInclusion.v0_10));
+ }
}
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
index 31d5028536..ffd607574e 100644
--- a/java/broker/src/test/java/org/apache/qpid/server/MainTest.java
+++ b/java/broker/src/test/java/org/apache/qpid/server/MainTest.java
@@ -47,6 +47,11 @@ public class MainTest extends QpidTestCase
{
assertEquals(0, options.getExcludedPorts(pe).size());
}
+
+ for(ProtocolInclusion pe : EnumSet.allOf(ProtocolInclusion.class))
+ {
+ assertEquals(0, options.getIncludedPorts(pe).size());
+ }
}
public void testPortOverriddenSingle()
@@ -162,6 +167,20 @@ public class MainTest extends QpidTestCase
assertTrue("Parsed command line didnt pick up help option", main.getCommandLine().hasOption("h"));
}
+ public void testInclude010()
+ {
+ BrokerOptions options = startDummyMain("-p 5678 --include-0-10 5678");
+
+ assertTrue(options.getPorts().contains(5678));
+ assertEquals(1, options.getPorts().size());
+ assertTrue(options.getIncludedPorts(ProtocolInclusion.v0_10).contains(5678));
+ assertEquals(1, options.getIncludedPorts(ProtocolInclusion.v0_10).size());
+ assertEquals(0, options.getIncludedPorts(ProtocolInclusion.v0_9_1).size());
+ assertEquals(0, options.getIncludedPorts(ProtocolInclusion.v0_9).size());
+ assertEquals(0, options.getIncludedPorts(ProtocolInclusion.v0_8).size());
+ assertEquals(0, options.getIncludedPorts(ProtocolInclusion.v1_0).size());
+ }
+
private BrokerOptions startDummyMain(String commandLine)
{
return (new TestMain(commandLine.split("\\s"))).getOptions();
diff --git a/java/broker/src/test/java/org/apache/qpid/server/TransactionTimeoutHelperTest.java b/java/broker/src/test/java/org/apache/qpid/server/TransactionTimeoutHelperTest.java
new file mode 100644
index 0000000000..9081dc49d6
--- /dev/null
+++ b/java/broker/src/test/java/org/apache/qpid/server/TransactionTimeoutHelperTest.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.server;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.same;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
+import static org.mockito.Mockito.when;
+
+import org.apache.qpid.server.logging.LogActor;
+import org.apache.qpid.server.logging.LogMessage;
+import org.apache.qpid.server.logging.LogSubject;
+import org.apache.qpid.server.logging.RootMessageLogger;
+import org.apache.qpid.server.logging.actors.CurrentActor;
+import org.apache.qpid.test.utils.QpidTestCase;
+
+public class TransactionTimeoutHelperTest extends QpidTestCase
+{
+ private final LogMessage _logMessage = mock(LogMessage.class);
+ private final LogActor _logActor = mock(LogActor.class);
+ private final LogSubject _logSubject = mock(LogSubject.class);
+ private TransactionTimeoutHelper _transactionTimeoutHelper;
+ private RootMessageLogger _rootMessageLogger;
+
+ public void testLogIfNecessary()
+ {
+ _transactionTimeoutHelper.logIfNecessary(99, 100, _logMessage, "");
+ verifyZeroInteractions(_logActor, _logMessage);
+
+ _transactionTimeoutHelper.logIfNecessary(101, 100, _logMessage, "");
+ verify(_logActor).message(_logSubject, _logMessage);
+ }
+
+ public void testLogIfNecessaryWhenOperationalLoggingDisabled()
+ {
+ //disable the operational logging
+ when(_rootMessageLogger.isMessageEnabled(
+ same(_logActor), any(LogSubject.class), any(String.class)))
+ .thenReturn(false);
+
+ //verify the actor is never asked to log a message
+ _transactionTimeoutHelper.logIfNecessary(101, 100, _logMessage, "");
+ verify(_logActor, never()).message(any(LogMessage.class));
+ verify(_logActor, never()).message(any(LogSubject.class), any(LogMessage.class));
+ }
+
+ public void testIsTimedOut()
+ {
+ assertFalse("Shouldn't have timed out", _transactionTimeoutHelper.isTimedOut(199,200));
+ assertTrue("Should have timed out", _transactionTimeoutHelper.isTimedOut(201,200));
+ }
+
+ /**
+ * If TransactionTimeout is disabled, the timeout will be 0. This test verifies
+ * that the helper methods respond negatively in this scenario.
+ */
+ public void testTransactionTimeoutDisabled()
+ {
+ assertFalse("Shouldn't have timed out", _transactionTimeoutHelper.isTimedOut(201,0));
+
+ _transactionTimeoutHelper.logIfNecessary(99, 0, _logMessage, "");
+ verifyZeroInteractions(_logActor, _logMessage);
+ }
+
+ @Override
+ protected void setUp() throws Exception
+ {
+ super.setUp();
+
+ CurrentActor.set(_logActor);
+
+ _rootMessageLogger = mock(RootMessageLogger.class);
+ when(_logActor.getRootMessageLogger()).thenReturn(_rootMessageLogger);
+
+ when(_rootMessageLogger.isMessageEnabled(
+ same(_logActor), any(LogSubject.class), any(String.class)))
+ .thenReturn(true);
+
+ _transactionTimeoutHelper = new TransactionTimeoutHelper(_logSubject);
+ }
+
+}
diff --git a/java/broker/src/test/java/org/apache/qpid/server/configuration/MockConnectionConfig.java b/java/broker/src/test/java/org/apache/qpid/server/configuration/MockConnectionConfig.java
index c0777d2f8f..00e5cd1222 100644
--- a/java/broker/src/test/java/org/apache/qpid/server/configuration/MockConnectionConfig.java
+++ b/java/broker/src/test/java/org/apache/qpid/server/configuration/MockConnectionConfig.java
@@ -25,14 +25,14 @@ import java.util.UUID;
public class MockConnectionConfig implements ConnectionConfig
{
- public MockConnectionConfig(UUID _id, ConnectionConfigType _configType,
+ public MockConnectionConfig(UUID _qmfId, ConnectionConfigType _configType,
ConfiguredObject<ConnectionConfigType, ConnectionConfig> _parent, boolean _durable,
long _createTime, VirtualHostConfig _virtualHost, String _address, Boolean _incoming,
Boolean _systemConnection, Boolean _federationLink, String _authId, String _remoteProcessName,
Integer _remotePID, Integer _remoteParentPID, ConfigStore _configStore, Boolean _shadow)
{
super();
- this._id = _id;
+ this._qmfId = _qmfId;
this._configType = _configType;
this._parent = _parent;
this._durable = _durable;
@@ -50,7 +50,7 @@ public class MockConnectionConfig implements ConnectionConfig
this._shadow = _shadow;
}
- private UUID _id;
+ private UUID _qmfId;
private ConnectionConfigType _configType;
private ConfiguredObject<ConnectionConfigType, ConnectionConfig> _parent;
private boolean _durable;
@@ -68,9 +68,9 @@ public class MockConnectionConfig implements ConnectionConfig
private Boolean _shadow;
@Override
- public UUID getId()
+ public UUID getQMFId()
{
- return _id;
+ return _qmfId;
}
@Override
diff --git a/java/broker/src/test/java/org/apache/qpid/server/configuration/QueueConfigurationTest.java b/java/broker/src/test/java/org/apache/qpid/server/configuration/QueueConfigurationTest.java
index 36f131a30f..3c5b85cd90 100644
--- a/java/broker/src/test/java/org/apache/qpid/server/configuration/QueueConfigurationTest.java
+++ b/java/broker/src/test/java/org/apache/qpid/server/configuration/QueueConfigurationTest.java
@@ -176,20 +176,29 @@ public class QueueConfigurationTest extends TestCase
assertEquals(1, qConf.getMaximumMessageCount());
}
- public void testGetMinimumAlertRepeatGap() throws ConfigurationException
+ public void testGetMinimumAlertRepeatGap() throws Exception
{
- // Check default value
- QueueConfiguration qConf = new QueueConfiguration("test", _emptyConf);
- assertEquals(0, qConf.getMinimumAlertRepeatGap());
+ try
+ {
+ ApplicationRegistry registry = new TestApplicationRegistry(new ServerConfiguration(_env));
+ ApplicationRegistry.initialise(registry);
+ // Check default value
+ QueueConfiguration qConf = new QueueConfiguration("test", _emptyConf);
+ assertEquals(ServerConfiguration.DEFAULT_MINIMUM_ALERT_REPEAT_GAP, qConf.getMinimumAlertRepeatGap());
- // Check explicit value
- VirtualHostConfiguration vhostConfig = overrideConfiguration("minimumAlertRepeatGap", 2);
- qConf = new QueueConfiguration("test", vhostConfig);
- assertEquals(2, qConf.getMinimumAlertRepeatGap());
+ // Check explicit value
+ VirtualHostConfiguration vhostConfig = overrideConfiguration("minimumAlertRepeatGap", 2);
+ qConf = new QueueConfiguration("test", vhostConfig);
+ assertEquals(2, qConf.getMinimumAlertRepeatGap());
- // Check inherited value
- qConf = new QueueConfiguration("test", _fullHostConf);
- assertEquals(1, qConf.getMinimumAlertRepeatGap());
+ // Check inherited value
+ qConf = new QueueConfiguration("test", _fullHostConf);
+ assertEquals(1, qConf.getMinimumAlertRepeatGap());
+ }
+ finally
+ {
+ ApplicationRegistry.remove();
+ }
}
public void testSortQueueConfiguration() throws ConfigurationException
@@ -204,6 +213,18 @@ public class QueueConfigurationTest extends TestCase
assertEquals("test-sort-key", qConf.getQueueSortKey());
}
+ public void testQueueDescription() throws ConfigurationException
+ {
+ //Check default value
+ QueueConfiguration qConf = new QueueConfiguration("test", _emptyConf);
+ assertNull(qConf.getDescription());
+
+ // Check explicit value
+ final VirtualHostConfiguration vhostConfig = overrideConfiguration("description", "mydescription");
+ qConf = new QueueConfiguration("test", vhostConfig);
+ assertEquals("mydescription", qConf.getDescription());
+ }
+
private VirtualHostConfiguration overrideConfiguration(String property, Object value)
throws ConfigurationException
{
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 4caefc2f18..660ff5e7d4 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
@@ -25,6 +25,7 @@ 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.AmqpProtocolVersion;
import org.apache.qpid.server.registry.ApplicationRegistry;
import org.apache.qpid.server.registry.ConfigurationFileApplicationRegistry;
import org.apache.qpid.server.util.TestApplicationRegistry;
@@ -251,13 +252,13 @@ public class ServerConfigurationTest extends QpidTestCase
{
// Check default
_serverConfig.initialise();
- assertEquals(true, _serverConfig.getManagementSSLEnabled());
+ assertEquals(false, _serverConfig.getManagementSSLEnabled());
// Check value we set
- _config.setProperty("management.ssl.enabled", false);
+ _config.setProperty("management.ssl.enabled", true);
_serverConfig = new ServerConfiguration(_config);
_serverConfig.initialise();
- assertEquals(false, _serverConfig.getManagementSSLEnabled());
+ assertEquals(true, _serverConfig.getManagementSSLEnabled());
}
public void testGetManagementKeystorePassword() throws ConfigurationException
@@ -286,25 +287,17 @@ public class ServerConfigurationTest extends QpidTestCase
assertEquals(false, _serverConfig.getQueueAutoRegister());
}
- public void testGetManagementEnabled() throws ConfigurationException
+ public void testGetJMXManagementEnabled() throws ConfigurationException
{
// Check default
_serverConfig.initialise();
- assertEquals(true, _serverConfig.getManagementEnabled());
+ assertEquals(true, _serverConfig.getJMXManagementEnabled());
// Check value we set
_config.setProperty("management.enabled", false);
_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());
+ assertEquals(false, _serverConfig.getJMXManagementEnabled());
}
public void testGetManagementRightsInferAllAccess() throws Exception
@@ -401,7 +394,7 @@ public class ServerConfigurationTest extends QpidTestCase
{
// Check default
_serverConfig.initialise();
- assertEquals(0, _serverConfig.getMinimumAlertRepeatGap());
+ assertEquals(30000l, _serverConfig.getMinimumAlertRepeatGap());
// Check value we set
_config.setProperty("minimumAlertRepeatGap", 10L);
@@ -1588,6 +1581,168 @@ public class ServerConfigurationTest extends QpidTestCase
assertEquals(false, _serverConfig.isAmqp08enabled());
}
+ public void testPortInclude08() throws ConfigurationException
+ {
+ // Check default
+ _serverConfig.initialise();
+ assertEquals(true, _serverConfig.getPortInclude08().isEmpty());
+
+ // Check values we set
+ _config.addProperty(ServerConfiguration.CONNECTOR_INCLUDE_08, "1");
+ _config.addProperty(ServerConfiguration.CONNECTOR_INCLUDE_08, "2");
+ _serverConfig = new ServerConfiguration(_config);
+ _serverConfig.initialise();
+ assertEquals(2, _serverConfig.getPortInclude08().size());
+ assertTrue(_serverConfig.getPortInclude08().contains("1"));
+ assertTrue(_serverConfig.getPortInclude08().contains("2"));
+ }
+
+ public void testPortInclude09() throws ConfigurationException
+ {
+ // Check default
+ _serverConfig.initialise();
+ assertEquals(true, _serverConfig.getPortInclude09().isEmpty());
+
+ // Check values we set
+ _config.addProperty(ServerConfiguration.CONNECTOR_INCLUDE_09, "3");
+ _config.addProperty(ServerConfiguration.CONNECTOR_INCLUDE_09, "4");
+ _serverConfig = new ServerConfiguration(_config);
+ _serverConfig.initialise();
+ assertEquals(2, _serverConfig.getPortInclude09().size());
+ assertTrue(_serverConfig.getPortInclude09().contains("3"));
+ assertTrue(_serverConfig.getPortInclude09().contains("4"));
+ }
+
+ public void testPortInclude091() throws ConfigurationException
+ {
+ // Check default
+ _serverConfig.initialise();
+ assertEquals(true, _serverConfig.getPortInclude091().isEmpty());
+
+ // Check values we set
+ _config.addProperty(ServerConfiguration.CONNECTOR_INCLUDE_091, "5");
+ _config.addProperty(ServerConfiguration.CONNECTOR_INCLUDE_091, "6");
+ _serverConfig = new ServerConfiguration(_config);
+ _serverConfig.initialise();
+ assertEquals(2, _serverConfig.getPortInclude091().size());
+ assertTrue(_serverConfig.getPortInclude091().contains("5"));
+ assertTrue(_serverConfig.getPortInclude091().contains("6"));
+ }
+
+ public void testPortInclude010() throws ConfigurationException
+ {
+ // Check default
+ _serverConfig.initialise();
+ assertEquals(true, _serverConfig.getPortInclude010().isEmpty());
+
+ // Check values we set
+ _config.addProperty(ServerConfiguration.CONNECTOR_INCLUDE_010, "7");
+ _config.addProperty(ServerConfiguration.CONNECTOR_INCLUDE_010, "8");
+ _serverConfig = new ServerConfiguration(_config);
+ _serverConfig.initialise();
+ assertEquals(2, _serverConfig.getPortInclude010().size());
+ assertTrue(_serverConfig.getPortInclude010().contains("7"));
+ assertTrue(_serverConfig.getPortInclude010().contains("8"));
+ }
+
+ public void testPortInclude10() throws ConfigurationException
+ {
+ // Check default
+ _serverConfig.initialise();
+ assertEquals(true, _serverConfig.getPortInclude10().isEmpty());
+
+ // Check values we set
+ _config.addProperty(ServerConfiguration.CONNECTOR_INCLUDE_10, "9");
+ _config.addProperty(ServerConfiguration.CONNECTOR_INCLUDE_10, "10");
+ _serverConfig = new ServerConfiguration(_config);
+ _serverConfig.initialise();
+ assertEquals(2, _serverConfig.getPortInclude10().size());
+ assertTrue(_serverConfig.getPortInclude10().contains("9"));
+ assertTrue(_serverConfig.getPortInclude10().contains("10"));
+ }
+
+ public void testGetDefaultSupportedProtocolReply() throws Exception
+ {
+ // Check default
+ _serverConfig.initialise();
+ assertNull("unexpected default value", _serverConfig.getDefaultSupportedProtocolReply());
+
+ // Check values we set
+ _config.addProperty(ServerConfiguration.CONNECTOR_AMQP_SUPPORTED_REPLY, "v0_10");
+ _serverConfig = new ServerConfiguration(_config);
+ _serverConfig.initialise();
+ assertEquals(AmqpProtocolVersion.v0_10, _serverConfig.getDefaultSupportedProtocolReply());
+ }
+
+ public void testDefaultAuthenticationManager() throws Exception
+ {
+ // Check default
+ _serverConfig.initialise();
+ assertNull("unexpected default value", _serverConfig.getDefaultAuthenticationManager());
+
+ // Check values we set
+ String testAuthManager = "myauthmanager";
+ _config.addProperty("security.default-auth-manager", testAuthManager);
+ _serverConfig = new ServerConfiguration(_config);
+ _serverConfig.initialise();
+ assertEquals(testAuthManager, _serverConfig.getDefaultAuthenticationManager());
+ }
+
+ public void testPortAuthenticationMappingsDefault() throws Exception
+ {
+ _serverConfig.initialise();
+ assertEquals("unexpected default number of port/authmanager mappings", 0, _serverConfig.getPortAuthenticationMappings().size());
+ }
+
+ public void testPortAuthenticationMappingsWithSingleMapping() throws Exception
+ {
+ String testAuthManager = "myauthmanager";
+ _config.addProperty("security.port-mappings.port-mapping.port", 1234);
+ _config.addProperty("security.port-mappings.port-mapping.auth-manager", testAuthManager);
+
+ _serverConfig = new ServerConfiguration(_config);
+ _serverConfig.initialise();
+ assertEquals("unexpected number of port/authmanager mappings", 1, _serverConfig.getPortAuthenticationMappings().size());
+ assertEquals("unexpected mapping for port", testAuthManager, _serverConfig.getPortAuthenticationMappings().get(1234));
+ }
+
+ public void testPortAuthenticationMappingsWithManyMapping() throws Exception
+ {
+ String testAuthManager1 = "myauthmanager1";
+ String testAuthManager2 = "myauthmanager2";
+ _config.addProperty("security.port-mappings.port-mapping(-1).port", 1234);
+ _config.addProperty("security.port-mappings.port-mapping.auth-manager", testAuthManager1);
+
+ _config.addProperty("security.port-mappings.port-mapping(-1).port", 2345);
+ _config.addProperty("security.port-mappings.port-mapping.auth-manager", testAuthManager2);
+
+ _serverConfig = new ServerConfiguration(_config);
+ _serverConfig.initialise();
+
+ assertEquals("unexpected number of port/authmanager mappings", 2, _serverConfig.getPortAuthenticationMappings().size());
+ assertEquals("unexpected mapping for port", testAuthManager1, _serverConfig.getPortAuthenticationMappings().get(1234));
+ assertEquals("unexpected mapping for port", testAuthManager2, _serverConfig.getPortAuthenticationMappings().get(2345));
+ }
+
+ public void testPortAuthenticationMappingWithMissingAuthManager() throws Exception
+ {
+ _config.addProperty("security.port-mappings.port-mapping(-1).port", 1234);
+ // no auth manager defined for port
+ _serverConfig = new ServerConfiguration(_config);
+ try
+ {
+ _serverConfig.initialise();
+ fail("Exception not thrown");
+ }
+ catch(ConfigurationException ce)
+ {
+ // PASS
+ assertEquals("Incorrect error message",
+ "Validation error: Each port-mapping must have exactly one port and exactly one auth-manager.",
+ ce.getMessage());
+ }
+ }
+
/**
* Convenience method to output required security preamble for broker config
*/
@@ -1605,7 +1760,6 @@ 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\t<jmx-access>/dev/null</jmx-access>\n");
out.write("\t\t</pd-auth-manager>\n");
out.write("\t</security>\n");
}
diff --git a/java/broker/src/test/java/org/apache/qpid/server/configuration/TopicConfigurationTest.java b/java/broker/src/test/java/org/apache/qpid/server/configuration/TopicConfigurationTest.java
index 59cd0cf1db..caf74a89ec 100644
--- a/java/broker/src/test/java/org/apache/qpid/server/configuration/TopicConfigurationTest.java
+++ b/java/broker/src/test/java/org/apache/qpid/server/configuration/TopicConfigurationTest.java
@@ -26,8 +26,8 @@ import org.apache.qpid.AMQException;
import org.apache.qpid.AMQInternalException;
import org.apache.qpid.AMQSecurityException;
import org.apache.qpid.exchange.ExchangeDefaults;
-import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.server.exchange.Exchange;
+import org.apache.qpid.server.model.UUIDGenerator;
import org.apache.qpid.server.queue.AMQQueue;
import org.apache.qpid.server.queue.AMQQueueFactory;
import org.apache.qpid.server.util.InternalBrokerBaseCase;
@@ -77,7 +77,7 @@ public class TopicConfigurationTest extends InternalBrokerBaseCase
public void testSubscriptionWithTopicCreation() throws ConfigurationException, AMQException
{
- AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(new AMQShortString(getName()+":stockSubscription"), false, new AMQShortString("testowner"),
+ AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), getName()+":stockSubscription", false, "testowner",
false, false, getVirtualHost(), null);
getVirtualHost().getQueueRegistry().registerQueue(queue);
@@ -107,7 +107,7 @@ public class TopicConfigurationTest extends InternalBrokerBaseCase
public void testSubscriptionCreation() throws ConfigurationException, AMQException
{
- AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(new AMQShortString(getName()+":stockSubscription"), false, new AMQShortString("testowner"),
+ AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID() ,getName()+":stockSubscription", false, "testowner",
false, false, getVirtualHost(), null);
getVirtualHost().getQueueRegistry().registerQueue(queue);
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 c4c93acfb6..50e7f0588b 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
@@ -27,7 +27,6 @@ import org.apache.qpid.server.queue.AMQPriorityQueue;
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.store.TestableMemoryMessageStoreFactory;
import org.apache.qpid.server.util.InternalBrokerBaseCase;
import org.apache.qpid.server.virtualhost.VirtualHost;
@@ -162,7 +161,7 @@ public class VirtualHostConfigurationTest extends InternalBrokerBaseCase
getConfigXml().addProperty("virtualhosts.virtualhost." + getName() + "Extra.queues(-1).queue(-1).name", "r2d2");
getConfigXml().addProperty("virtualhosts.virtualhost." + getName() + "Extra.queues.queue.r2d2.deadLetterQueues", "true");
getConfigXml().addProperty("virtualhosts.virtualhost." + getName() + "Extra.queues(-1).queue(-1).name", "c3p0");
- getConfigXml().addProperty("virtualhosts.virtualhost." + getName() + "Extra.store.factoryclass", TestableMemoryMessageStoreFactory.class.getName());
+ getConfigXml().addProperty("virtualhosts.virtualhost." + getName() + "Extra.store.class", TestableMemoryMessageStore.class.getName());
// Start the broker now.
super.createBroker();
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 afd8fd9ed2..4befd26ece 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
@@ -83,7 +83,7 @@ public class AbstractHeadersExchangeTestBase extends InternalBrokerBaseCase
protected void unbind(TestQueue queue, String... bindings) throws AMQException
{
String queueName = queue.getName();
- exchange.onUnbind(new Binding(null,queueName, queue, exchange, getHeadersMap(bindings)));
+ exchange.onUnbind(new Binding(null, null, queueName, queue, exchange, getHeadersMap(bindings)));
}
protected int getCount()
@@ -95,7 +95,7 @@ public class AbstractHeadersExchangeTestBase extends InternalBrokerBaseCase
{
TestQueue queue = new TestQueue(new AMQShortString(queueName));
queues.add(queue);
- exchange.onBind(new Binding(null,key, queue, exchange, args));
+ exchange.onBind(new Binding(null, null, key, queue, exchange, args));
return queue;
}
@@ -276,7 +276,7 @@ public class AbstractHeadersExchangeTestBase extends InternalBrokerBaseCase
public TestQueue(AMQShortString name) throws AMQException
{
- super(UUIDGenerator.generateUUID(), name, false, new AMQShortString("test"), true, false,ApplicationRegistry.getInstance().getVirtualHostRegistry().getVirtualHost("test"), Collections.EMPTY_MAP);
+ super(UUIDGenerator.generateRandomUUID(), name, false, new AMQShortString("test"), true, false,ApplicationRegistry.getInstance().getVirtualHostRegistry().getVirtualHost("test"), Collections.EMPTY_MAP);
ApplicationRegistry.getInstance().getVirtualHostRegistry().getVirtualHost("test").getQueueRegistry().registerQueue(this);
}
diff --git a/java/broker/src/test/java/org/apache/qpid/server/exchange/ExchangeMBeanTest.java b/java/broker/src/test/java/org/apache/qpid/server/exchange/ExchangeMBeanTest.java
deleted file mode 100644
index 9034bf9c3a..0000000000
--- a/java/broker/src/test/java/org/apache/qpid/server/exchange/ExchangeMBeanTest.java
+++ /dev/null
@@ -1,235 +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.exchange;
-
-import org.apache.commons.lang.ArrayUtils;
-
-import org.apache.qpid.exchange.ExchangeDefaults;
-import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpid.management.common.mbeans.ManagedExchange;
-import org.apache.qpid.server.management.ManagedObject;
-import org.apache.qpid.server.model.UUIDGenerator;
-import org.apache.qpid.server.queue.AMQQueue;
-import org.apache.qpid.server.queue.AMQQueueFactory;
-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.util.InternalBrokerBaseCase;
-import org.apache.qpid.server.virtualhost.VirtualHost;
-
-import javax.management.JMException;
-import javax.management.openmbean.CompositeDataSupport;
-import javax.management.openmbean.TabularData;
-import java.util.ArrayList;
-import java.util.Iterator;
-
-/**
- * Unit test class for testing different Exchange MBean operations
- */
-public class ExchangeMBeanTest extends InternalBrokerBaseCase
-{
- private AMQQueue _queue;
- private QueueRegistry _queueRegistry;
- private VirtualHost _virtualHost;
-
- public void testGeneralProperties() throws Exception
- {
- DirectExchange exchange = new DirectExchange();
- exchange.initialise(UUIDGenerator.generateUUID(), _virtualHost, ExchangeDefaults.DIRECT_EXCHANGE_NAME, false, 0, true);
- ManagedObject managedObj = exchange.getManagedObject();
- ManagedExchange mbean = (ManagedExchange)managedObj;
-
- // test general exchange properties
- assertEquals("Unexpected exchange name", "amq.direct", mbean.getName());
- assertEquals("Unexpected exchange type", "direct", mbean.getExchangeType());
- assertEquals("Unexpected ticket number", Integer.valueOf(0), mbean.getTicketNo());
- assertFalse("Unexpected durable flag", mbean.isDurable());
- assertTrue("Unexpected auto delete flag", mbean.isAutoDelete());
- }
-
- public void testDirectExchangeMBean() throws Exception
- {
- DirectExchange exchange = new DirectExchange();
- exchange.initialise(UUIDGenerator.generateUUID(), _virtualHost, ExchangeDefaults.DIRECT_EXCHANGE_NAME, false, 0, true);
- ManagedObject managedObj = exchange.getManagedObject();
- ManagedExchange mbean = (ManagedExchange)managedObj;
-
- mbean.createNewBinding(_queue.getNameShortString().toString(), "binding1");
- mbean.createNewBinding(_queue.getNameShortString().toString(), "binding2");
-
- TabularData data = mbean.bindings();
- ArrayList<Object> list = new ArrayList<Object>(data.values());
- assertTrue(list.size() == 2);
- }
-
- public void testTopicExchangeMBean() throws Exception
- {
- TopicExchange exchange = new TopicExchange();
- exchange.initialise(UUIDGenerator.generateUUID(), _virtualHost,ExchangeDefaults.TOPIC_EXCHANGE_NAME, false, 0, true);
- ManagedObject managedObj = exchange.getManagedObject();
- ManagedExchange mbean = (ManagedExchange)managedObj;
-
- mbean.createNewBinding(_queue.getNameShortString().toString(), "binding1");
- mbean.createNewBinding(_queue.getNameShortString().toString(), "binding2");
-
- TabularData data = mbean.bindings();
- ArrayList<Object> list = new ArrayList<Object>(data.values());
- assertTrue(list.size() == 2);
- }
-
- public void testHeadersExchangeMBean() throws Exception
- {
- HeadersExchange exchange = new HeadersExchange();
- exchange.initialise(UUIDGenerator.generateUUID(), _virtualHost,ExchangeDefaults.HEADERS_EXCHANGE_NAME, false, 0, true);
- ManagedObject managedObj = exchange.getManagedObject();
- ManagedExchange mbean = (ManagedExchange)managedObj;
-
- mbean.createNewBinding(_queue.getNameShortString().toString(), "x-match=any,key1=binding1,key2=binding2");
-
- TabularData data = mbean.bindings();
- ArrayList<Object> list = new ArrayList<Object>(data.values());
- assertEquals("Unexpected number of bindings", 1, list.size());
-
- final Iterator<CompositeDataSupport> rowItr = (Iterator<CompositeDataSupport>) data.values().iterator();
- CompositeDataSupport row = rowItr.next();
- assertBinding(1, _queue.getName(), new String[]{"x-match=any","key1=binding1","key2=binding2"}, row);
- }
-
- /**
- * Included to ensure 0-10 Specification compliance:
- * 2.3.1.4 "the field in the bind arguments has no value and a field of the same name is present in the message headers
- */
- public void testHeadersExchangeMBeanMatchPropertyNoValue() throws Exception
- {
- HeadersExchange exchange = new HeadersExchange();
- exchange.initialise(UUIDGenerator.generateUUID(), _virtualHost,ExchangeDefaults.HEADERS_EXCHANGE_NAME, false, 0, true);
- ManagedObject managedObj = exchange.getManagedObject();
- ManagedExchange mbean = (ManagedExchange)managedObj;
-
- mbean.createNewBinding(_queue.getNameShortString().toString(), "x-match=any,key4,key5=");
-
- TabularData data = mbean.bindings();
- ArrayList<Object> list = new ArrayList<Object>(data.values());
- assertEquals("Unexpected number of bindings", 1, list.size());
-
- final Iterator<CompositeDataSupport> rowItr = (Iterator<CompositeDataSupport>) data.values().iterator();
- CompositeDataSupport row = rowItr.next();
- assertBinding(1, _queue.getName(), new String[]{"x-match=any","key4=","key5="}, row);
- }
-
- public void testInvalidHeaderBindingMalformed() throws Exception
- {
- HeadersExchange exchange = new HeadersExchange();
- exchange.initialise(UUIDGenerator.generateUUID(), _virtualHost,ExchangeDefaults.HEADERS_EXCHANGE_NAME, false, 0, true);
- ManagedObject managedObj = exchange.getManagedObject();
- ManagedExchange mbean = (ManagedExchange)managedObj;
-
- try
- {
- mbean.createNewBinding(_queue.getNameShortString().toString(), "x-match=any,=value4");
- fail("Exception not thrown");
- }
- catch (JMException jme)
- {
- //pass
- }
- }
-
- private void assertBinding(final int expectedBindingNo, final String expectedQueueName, final String[] expectedBindingArray,
- final CompositeDataSupport row)
- {
- final Number bindingNumber = (Number) row.get(ManagedExchange.HDR_BINDING_NUMBER);
- final String queueName = (String) row.get(ManagedExchange.HDR_QUEUE_NAME);
- final String[] bindings = (String[]) row.get(ManagedExchange.HDR_QUEUE_BINDINGS);
- assertEquals("Unexpected binding number", expectedBindingNo, bindingNumber);
- assertEquals("Unexpected queue name", expectedQueueName, queueName);
- assertEquals("Unexpected no of bindings", expectedBindingArray.length, bindings.length);
- for(String binding : bindings)
- {
- assertTrue("Expected binding not found: " + binding, ArrayUtils.contains(expectedBindingArray, binding));
- }
- }
-
- /**
- * Test adding bindings and removing them from the default exchange via JMX.
- * <p>
- * QPID-2700
- */
- public void testDefaultBindings() throws Exception
- {
- int bindings = _queue.getBindingCount();
-
- Exchange exchange = _queue.getVirtualHost().getExchangeRegistry().getDefaultExchange();
- ManagedExchange mbean = (ManagedExchange) ((AbstractExchange) exchange).getManagedObject();
-
- mbean.createNewBinding(_queue.getName(), "robot");
- mbean.createNewBinding(_queue.getName(), "kitten");
-
- assertEquals("Should have added two bindings", bindings + 2, _queue.getBindingCount());
-
- mbean.removeBinding(_queue.getName(), "robot");
-
- assertEquals("Should have one extra binding", bindings + 1, _queue.getBindingCount());
-
- mbean.removeBinding(_queue.getName(), "kitten");
-
- assertEquals("Should have original number of binding", bindings, _queue.getBindingCount());
- }
-
- /**
- * Test adding bindings and removing them from the topic exchange via JMX.
- * <p>
- * QPID-2700
- */
- public void testTopicBindings() throws Exception
- {
- int bindings = _queue.getBindingCount();
-
- Exchange exchange = _queue.getVirtualHost().getExchangeRegistry().getExchange(new AMQShortString("amq.topic"));
- ManagedExchange mbean = (ManagedExchange) ((AbstractExchange) exchange).getManagedObject();
-
- mbean.createNewBinding(_queue.getName(), "robot.#");
- mbean.createNewBinding(_queue.getName(), "#.kitten");
-
- assertEquals("Should have added two bindings", bindings + 2, _queue.getBindingCount());
-
- mbean.removeBinding(_queue.getName(), "robot.#");
-
- assertEquals("Should have one extra binding", bindings + 1, _queue.getBindingCount());
-
- mbean.removeBinding(_queue.getName(), "#.kitten");
-
- assertEquals("Should have original number of binding", bindings, _queue.getBindingCount());
- }
-
- @Override
- public void setUp() throws Exception
- {
- super.setUp();
-
- IApplicationRegistry applicationRegistry = ApplicationRegistry.getInstance();
- _virtualHost = applicationRegistry.getVirtualHostRegistry().getVirtualHost("test");
- _queueRegistry = _virtualHost.getQueueRegistry();
- _queue = AMQQueueFactory.createAMQQueueImpl(new AMQShortString("testQueue"), false, new AMQShortString("ExchangeMBeanTest"), false, false,
- _virtualHost, null);
- _queueRegistry.registerQueue(_queue);
- }
-}
diff --git a/java/broker/src/test/java/org/apache/qpid/server/exchange/HeadersBindingTest.java b/java/broker/src/test/java/org/apache/qpid/server/exchange/HeadersBindingTest.java
index 4305cdadc6..3988edcb3c 100644
--- a/java/broker/src/test/java/org/apache/qpid/server/exchange/HeadersBindingTest.java
+++ b/java/broker/src/test/java/org/apache/qpid/server/exchange/HeadersBindingTest.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
@@ -20,6 +20,7 @@
*/
package org.apache.qpid.server.exchange;
+import java.util.Collection;
import junit.framework.TestCase;
import org.apache.qpid.server.binding.Binding;
@@ -50,6 +51,16 @@ public class HeadersBindingTest extends TestCase
return 0;
}
+ public String getUserId()
+ {
+ return null;
+ }
+
+ public String getAppId()
+ {
+ return null;
+ }
+
public String getMessageId()
{
return null;
@@ -57,7 +68,7 @@ public class HeadersBindingTest extends TestCase
public String getMimeType()
{
- return null; //To change body of implemented methods use File | Settings | File Templates.
+ return null;
}
public String getEncoding()
@@ -105,6 +116,12 @@ public class HeadersBindingTest extends TestCase
return _headers.keySet().containsAll(names);
}
+ @Override
+ public Collection<String> getHeaderNames()
+ {
+ return _headers.keySet();
+ }
+
public boolean containsHeader(String name)
{
return _headers.containsKey(name);
@@ -125,13 +142,13 @@ public class HeadersBindingTest extends TestCase
private MockHeader matchHeaders = new MockHeader();
private int _count = 0;
private MockAMQQueue _queue;
-
+
protected void setUp()
{
_count++;
_queue = new MockAMQQueue(getQueueName());
}
-
+
protected String getQueueName()
{
return "Queue" + _count;
@@ -143,7 +160,7 @@ public class HeadersBindingTest extends TestCase
matchHeaders.setString("A", "Value of A");
- Binding b = new Binding(null, getQueueName(), _queue, null, bindHeaders);
+ Binding b = new Binding(null, null, getQueueName(), _queue, null, bindHeaders);
assertTrue(new HeadersBinding(b).matches(matchHeaders));
}
@@ -154,7 +171,7 @@ public class HeadersBindingTest extends TestCase
matchHeaders.setString("A", "Value of A");
matchHeaders.setString("B", "Value of B");
- Binding b = new Binding(null, getQueueName(), _queue, null, bindHeaders);
+ Binding b = new Binding(null, null, getQueueName(), _queue, null, bindHeaders);
assertTrue(new HeadersBinding(b).matches(matchHeaders));
}
@@ -164,7 +181,7 @@ public class HeadersBindingTest extends TestCase
matchHeaders.setString("A", "Altered value of A");
- Binding b = new Binding(null, getQueueName(), _queue, null, bindHeaders);
+ Binding b = new Binding(null, null, getQueueName(), _queue, null, bindHeaders);
assertFalse(new HeadersBinding(b).matches(matchHeaders));
}
@@ -175,7 +192,7 @@ public class HeadersBindingTest extends TestCase
matchHeaders.setString("A", "Value of A");
- Binding b = new Binding(null, getQueueName(), _queue, null, bindHeaders);
+ Binding b = new Binding(null, null, getQueueName(), _queue, null, bindHeaders);
assertTrue(new HeadersBinding(b).matches(matchHeaders));
}
@@ -187,7 +204,7 @@ public class HeadersBindingTest extends TestCase
matchHeaders.setString("A", "Value of A");
- Binding b = new Binding(null, getQueueName(), _queue, null, bindHeaders);
+ Binding b = new Binding(null, null, getQueueName(), _queue, null, bindHeaders);
assertFalse(new HeadersBinding(b).matches(matchHeaders));
}
@@ -200,7 +217,7 @@ public class HeadersBindingTest extends TestCase
matchHeaders.setString("A", "Value of A");
matchHeaders.setString("B", "Value of B");
- Binding b = new Binding(null, getQueueName(), _queue, null, bindHeaders);
+ Binding b = new Binding(null, null, getQueueName(), _queue, null, bindHeaders);
assertTrue(new HeadersBinding(b).matches(matchHeaders));
}
@@ -214,7 +231,7 @@ public class HeadersBindingTest extends TestCase
matchHeaders.setString("B", "Value of B");
matchHeaders.setString("C", "Value of C");
- Binding b = new Binding(null, getQueueName(), _queue, null, bindHeaders);
+ Binding b = new Binding(null, null, getQueueName(), _queue, null, bindHeaders);
assertTrue(new HeadersBinding(b).matches(matchHeaders));
}
@@ -228,7 +245,7 @@ public class HeadersBindingTest extends TestCase
matchHeaders.setString("B", "Altered value of B");
matchHeaders.setString("C", "Value of C");
- Binding b = new Binding(null, getQueueName(), _queue, null, bindHeaders);
+ Binding b = new Binding(null, null, getQueueName(), _queue, null, bindHeaders);
assertFalse(new HeadersBinding(b).matches(matchHeaders));
}
@@ -239,7 +256,7 @@ public class HeadersBindingTest extends TestCase
matchHeaders.setString("A", "Value of A");
- Binding b = new Binding(null, getQueueName(), _queue, null, bindHeaders);
+ Binding b = new Binding(null, null, getQueueName(), _queue, null, bindHeaders);
assertTrue(new HeadersBinding(b).matches(matchHeaders));
}
@@ -251,7 +268,7 @@ public class HeadersBindingTest extends TestCase
matchHeaders.setString("A", "Value of A");
- Binding b = new Binding(null, getQueueName(), _queue, null, bindHeaders);
+ Binding b = new Binding(null, null, getQueueName(), _queue, null, bindHeaders);
assertTrue(new HeadersBinding(b).matches(matchHeaders));
}
@@ -264,7 +281,7 @@ public class HeadersBindingTest extends TestCase
matchHeaders.setString("A", "Value of A");
matchHeaders.setString("B", "Value of B");
- Binding b = new Binding(null, getQueueName(), _queue, null, bindHeaders);
+ Binding b = new Binding(null, null, getQueueName(), _queue, null, bindHeaders);
assertTrue(new HeadersBinding(b).matches(matchHeaders));
}
@@ -278,7 +295,7 @@ public class HeadersBindingTest extends TestCase
matchHeaders.setString("B", "Value of B");
matchHeaders.setString("C", "Value of C");
- Binding b = new Binding(null, getQueueName(), _queue, null, bindHeaders);
+ Binding b = new Binding(null, null, getQueueName(), _queue, null, bindHeaders);
assertTrue(new HeadersBinding(b).matches(matchHeaders));
}
@@ -292,7 +309,7 @@ public class HeadersBindingTest extends TestCase
matchHeaders.setString("B", "Altered value of B");
matchHeaders.setString("C", "Value of C");
- Binding b = new Binding(null, getQueueName(), _queue, null, bindHeaders);
+ Binding b = new Binding(null, null, getQueueName(), _queue, null, bindHeaders);
assertTrue(new HeadersBinding(b).matches(matchHeaders));
}
@@ -306,7 +323,7 @@ public class HeadersBindingTest extends TestCase
matchHeaders.setString("B", "Altered value of B");
matchHeaders.setString("C", "Value of C");
- Binding b = new Binding(null, getQueueName(), _queue, null, bindHeaders);
+ Binding b = new Binding(null, null, getQueueName(), _queue, null, bindHeaders);
assertFalse(new HeadersBinding(b).matches(matchHeaders));
}
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 00c8a18d9f..92274afece 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
@@ -30,6 +30,7 @@ import org.apache.qpid.framing.abstraction.MessagePublishInfo;
import org.apache.qpid.server.binding.Binding;
import org.apache.qpid.server.message.AMQMessage;
import org.apache.qpid.server.message.MessageMetaData;
+import org.apache.qpid.server.model.UUIDGenerator;
import org.apache.qpid.server.protocol.InternalTestProtocolSession;
import org.apache.qpid.server.queue.AMQQueue;
import org.apache.qpid.server.queue.AMQQueueFactory;
@@ -64,8 +65,8 @@ public class TopicExchangeTest extends InternalBrokerBaseCase
public void testNoRoute() throws AMQException
{
- AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(new AMQShortString("a*#b"), false, null, false, false, _vhost, null);
- _exchange.registerQueue(new Binding(null,"a.*.#.b", queue,_exchange, null));
+ AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), "a*#b", false, null, false, false, _vhost, null);
+ _exchange.registerQueue(new Binding(null, null, "a.*.#.b",queue, _exchange, null));
IncomingMessage message = createMessage("a.b");
@@ -76,8 +77,8 @@ public class TopicExchangeTest extends InternalBrokerBaseCase
public void testDirectMatch() throws AMQException
{
- AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(new AMQShortString("ab"), false, null, false, false, _vhost, null);
- _exchange.registerQueue(new Binding(null,"a.b", queue,_exchange, null));
+ AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), "ab", false, null, false, false, _vhost, null);
+ _exchange.registerQueue(new Binding(null, null, "a.b",queue, _exchange, null));
IncomingMessage message = createMessage("a.b");
@@ -103,8 +104,8 @@ public class TopicExchangeTest extends InternalBrokerBaseCase
public void testStarMatch() throws AMQException
{
- AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(new AMQShortString("a*"), false, null, false, false, _vhost, null);
- _exchange.registerQueue(new Binding(null,"a.*", queue,_exchange, null));
+ AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), "a*", false, null, false, false, _vhost, null);
+ _exchange.registerQueue(new Binding(null, null, "a.*",queue, _exchange, null));
IncomingMessage message = createMessage("a.b");
@@ -142,8 +143,8 @@ public class TopicExchangeTest extends InternalBrokerBaseCase
public void testHashMatch() throws AMQException
{
- AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(new AMQShortString("a#"), false, null, false, false, _vhost, null);
- _exchange.registerQueue(new Binding(null,"a.#", queue,_exchange, null));
+ AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), "a#", false, null, false, false, _vhost, null);
+ _exchange.registerQueue(new Binding(null, null, "a.#",queue, _exchange, null));
IncomingMessage message = createMessage("a.b.c");
@@ -205,8 +206,8 @@ public class TopicExchangeTest extends InternalBrokerBaseCase
public void testMidHash() throws AMQException
{
- AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(new AMQShortString("a"), false, null, false, false, _vhost, null);
- _exchange.registerQueue(new Binding(null,"a.*.#.b", queue,_exchange, null));
+ AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), "a", false, null, false, false, _vhost, null);
+ _exchange.registerQueue(new Binding(null, null, "a.*.#.b",queue, _exchange, null));
IncomingMessage message = createMessage("a.c.d.b");
@@ -235,8 +236,8 @@ public class TopicExchangeTest extends InternalBrokerBaseCase
public void testMatchafterHash() throws AMQException
{
- AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(new AMQShortString("a#"), false, null, false, false, _vhost, null);
- _exchange.registerQueue(new Binding(null,"a.*.#.b.c", queue,_exchange, null));
+ AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), "a#", false, null, false, false, _vhost, null);
+ _exchange.registerQueue(new Binding(null, null, "a.*.#.b.c",queue, _exchange, null));
IncomingMessage message = createMessage("a.c.b.b");
@@ -281,8 +282,8 @@ public class TopicExchangeTest extends InternalBrokerBaseCase
public void testHashAfterHash() throws AMQException
{
- AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(new AMQShortString("a#"), false, null, false, false, _vhost, null);
- _exchange.registerQueue(new Binding(null,"a.*.#.b.c.#.d", queue,_exchange, null));
+ AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), "a#", false, null, false, false, _vhost, null);
+ _exchange.registerQueue(new Binding(null, null, "a.*.#.b.c.#.d",queue, _exchange, null));
IncomingMessage message = createMessage("a.c.b.b.c");
@@ -308,8 +309,8 @@ public class TopicExchangeTest extends InternalBrokerBaseCase
public void testHashHash() throws AMQException
{
- AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(new AMQShortString("a#"), false, null, false, false, _vhost, null);
- _exchange.registerQueue(new Binding(null,"a.#.*.#.d", queue,_exchange, null));
+ AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), "a#", false, null, false, false, _vhost, null);
+ _exchange.registerQueue(new Binding(null, null, "a.#.*.#.d",queue, _exchange, null));
IncomingMessage message = createMessage("a.c.b.b.c");
@@ -334,8 +335,8 @@ public class TopicExchangeTest extends InternalBrokerBaseCase
public void testSubMatchFails() throws AMQException
{
- AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(new AMQShortString("a"), false, null, false, false, _vhost, null);
- _exchange.registerQueue(new Binding(null,"a.b.c.d", queue,_exchange, null));
+ AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), "a", false, null, false, false, _vhost, null);
+ _exchange.registerQueue(new Binding(null, null, "a.b.c.d",queue, _exchange, null));
IncomingMessage message = createMessage("a.b.c");
@@ -364,8 +365,8 @@ public class TopicExchangeTest extends InternalBrokerBaseCase
public void testMoreRouting() throws AMQException
{
- AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(new AMQShortString("a"), false, null, false, false, _vhost, null);
- _exchange.registerQueue(new Binding(null,"a.b", queue,_exchange, null));
+ AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), "a", false, null, false, false, _vhost, null);
+ _exchange.registerQueue(new Binding(null, null, "a.b",queue, _exchange, null));
IncomingMessage message = createMessage("a.b.c");
@@ -379,8 +380,8 @@ public class TopicExchangeTest extends InternalBrokerBaseCase
public void testMoreQueue() throws AMQException
{
- AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(new AMQShortString("a"), false, null, false, false, _vhost, null);
- _exchange.registerQueue(new Binding(null,"a.b", queue,_exchange, null));
+ AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), "a", false, null, false, false, _vhost, null);
+ _exchange.registerQueue(new Binding(null, null, "a.b",queue, _exchange, null));
IncomingMessage message = createMessage("a");
diff --git a/java/broker/src/test/java/org/apache/qpid/server/logging/log4j/LoggingFacadeTest.java b/java/broker/src/test/java/org/apache/qpid/server/logging/log4j/LoggingFacadeTest.java
new file mode 100644
index 0000000000..f871baffe6
--- /dev/null
+++ b/java/broker/src/test/java/org/apache/qpid/server/logging/log4j/LoggingFacadeTest.java
@@ -0,0 +1,245 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.logging.log4j;
+
+import java.io.File;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.log4j.Level;
+import org.apache.qpid.util.FileUtils;
+
+import junit.framework.TestCase;
+
+public class LoggingFacadeTest extends TestCase
+{
+ private LoggingFacade _loggingFacade;
+ private String _log4jXmlFile;
+
+ @Override
+ protected void setUp() throws Exception
+ {
+ super.setUp();
+ _log4jXmlFile = createTestLog4jXml();
+ _loggingFacade = LoggingFacade.configure(_log4jXmlFile);
+ }
+
+ public void testGetAvailableLoggerLevels() throws Exception
+ {
+ List<String> levels = _loggingFacade.getAvailableLoggerLevels();
+ assertTrue(levels.contains("ALL"));
+ assertTrue(levels.contains("TRACE"));
+ assertTrue(levels.contains("DEBUG"));
+ assertTrue(levels.contains("INFO"));
+ assertTrue(levels.contains("WARN"));
+ assertTrue(levels.contains("ERROR"));
+ assertTrue(levels.contains("FATAL"));
+ assertTrue(levels.contains("OFF"));
+ assertEquals(8, levels.size());
+ }
+
+ public void testRetrieveConfigFileRootLoggerLevel() throws Exception
+ {
+ String level = _loggingFacade.retrieveConfigFileRootLoggerLevel();
+ assertEquals(Level.WARN.toString(), level);
+ }
+
+ public void testSetConfigFileRootLoggerLevel() throws Exception
+ {
+ String oldLevel = _loggingFacade.retrieveConfigFileRootLoggerLevel();
+ assertEquals("WARN", oldLevel);
+
+ _loggingFacade.setConfigFileRootLoggerLevel("INFO");
+
+ String level = _loggingFacade.retrieveConfigFileRootLoggerLevel();
+ assertEquals("INFO", level);
+ }
+
+ public void testRetrieveConfigFileLoggerLevels() throws Exception
+ {
+ Map<String, String> levels = _loggingFacade.retrieveConfigFileLoggersLevels();
+ assertEquals(3, levels.size());
+ String abcLevel = levels.get("a.b.c");
+ String abc1Level = levels.get("a.b.c.1");
+ String abc2Level = levels.get("a.b.c.2");
+ assertEquals("INFO", abcLevel);
+ assertEquals("DEBUG", abc1Level);
+ assertEquals("TRACE", abc2Level);
+ }
+
+ public void testSetConfigFileLoggerLevels() throws Exception
+ {
+ final String loggerName = "a.b.c";
+
+ assertConfigFileLoggingLevel(loggerName, "INFO");
+
+ _loggingFacade.setConfigFileLoggerLevel(loggerName, "WARN");
+
+ Map<String, String> levels = _loggingFacade.retrieveConfigFileLoggersLevels();
+ String abcLevel = levels.get(loggerName);
+ assertEquals("WARN", abcLevel);
+ }
+
+ public void testSetConfigFileLoggerLevelsWhereLoggerDoesNotExist() throws Exception
+ {
+ try
+ {
+ _loggingFacade.setConfigFileLoggerLevel("does.not.exist", "WARN");
+ fail("Exception not thrown");
+ }
+ catch (LoggingFacadeException lfe)
+ {
+ // PASS
+ assertEquals("Can't find logger does.not.exist", lfe.getMessage());
+ }
+ }
+
+ public void testRetrieveRuntimeRootLoggerLevel() throws Exception
+ {
+ String level = _loggingFacade.retrieveRuntimeRootLoggerLevel();
+ assertEquals(Level.WARN.toString(), level);
+ }
+
+ public void testSetRuntimeRootLoggerLevel() throws Exception
+ {
+ String oldLevel = _loggingFacade.retrieveRuntimeRootLoggerLevel();
+ assertEquals("WARN", oldLevel);
+
+ _loggingFacade.setRuntimeRootLoggerLevel("INFO");
+
+ String level = _loggingFacade.retrieveRuntimeRootLoggerLevel();
+ assertEquals("INFO", level);
+ }
+
+ public void testRetrieveRuntimeLoggersLevels() throws Exception
+ {
+ Map<String, String> levels = _loggingFacade.retrieveRuntimeLoggersLevels();
+ // Don't assert size as implementation itself uses logging and we'd count its loggers too
+ String abcLevel = levels.get("a.b.c");
+ String abc1Level = levels.get("a.b.c.1");
+ String abc2Level = levels.get("a.b.c.2");
+ assertEquals("INFO", abcLevel);
+ assertEquals("DEBUG", abc1Level);
+ assertEquals("TRACE", abc2Level);
+ }
+
+ public void testSetRuntimeLoggerLevel() throws Exception
+ {
+ final String loggerName = "a.b.c";
+
+ assertRuntimeLoggingLevel(loggerName, "INFO");
+
+ _loggingFacade.setRuntimeLoggerLevel(loggerName, "WARN");
+
+ assertRuntimeLoggingLevel(loggerName, "WARN");
+ }
+
+ public void testSetRuntimeLoggerToInheritFromParent() throws Exception
+ {
+ final String parentLoggerName = "a.b.c";
+ final String childLoggerName = "a.b.c.1";
+
+ assertRuntimeLoggingLevel(parentLoggerName, "INFO");
+ assertRuntimeLoggingLevel(childLoggerName, "DEBUG");
+
+ _loggingFacade.setRuntimeLoggerLevel(childLoggerName, null);
+
+ assertRuntimeLoggingLevel(parentLoggerName, "INFO");
+ assertRuntimeLoggingLevel(childLoggerName, "INFO");
+ }
+
+ public void testSetRuntimeLoggerLevelsWhereLoggerDoesNotExist() throws Exception
+ {
+ final String loggerName = "does.not.exist2";
+
+ Map<String, String> oldLevels = _loggingFacade.retrieveRuntimeLoggersLevels();
+ assertFalse(oldLevels.containsKey(loggerName));
+
+ try
+ {
+ _loggingFacade.setRuntimeLoggerLevel(loggerName, "WARN");
+ fail("Exception not thrown");
+ }
+ catch (LoggingFacadeException lfe)
+ {
+ // PASS
+ assertEquals("Can't find logger " + loggerName, lfe.getMessage());
+ }
+
+ Map<String, String> levels = _loggingFacade.retrieveRuntimeLoggersLevels();
+ assertFalse(levels.containsKey(loggerName));
+ }
+
+ public void testReloadOfChangedLog4JFileUpdatesRuntimeLogLevel() throws Exception
+ {
+ final String loggerName = "a.b.c";
+
+ assertRuntimeLoggingLevel(loggerName, "INFO");
+ assertConfigFileLoggingLevel(loggerName, "INFO");
+
+ _loggingFacade.setConfigFileLoggerLevel(loggerName, "WARN");
+
+ assertRuntimeLoggingLevel(loggerName, "INFO");
+
+ _loggingFacade.reload();
+
+ assertRuntimeLoggingLevel(loggerName, "WARN");
+ }
+
+
+ public void testReloadOfLog4JFileRevertsRuntimeChanges() throws Exception
+ {
+ final String loggerName = "a.b.c";
+
+ assertRuntimeLoggingLevel(loggerName, "INFO");
+ assertConfigFileLoggingLevel(loggerName, "INFO");
+
+ _loggingFacade.setRuntimeLoggerLevel(loggerName, "WARN");
+
+ assertRuntimeLoggingLevel(loggerName, "WARN");
+
+ _loggingFacade.reload();
+
+ assertRuntimeLoggingLevel(loggerName, "INFO");
+ }
+
+ private void assertConfigFileLoggingLevel(final String loggerName, String expectedLevel) throws Exception
+ {
+ Map<String, String> levels = _loggingFacade.retrieveConfigFileLoggersLevels();
+ String actualLevel = levels.get(loggerName);
+ assertEquals(expectedLevel, actualLevel);
+ }
+
+ private void assertRuntimeLoggingLevel(final String loggerName, String expectedLevel) throws Exception
+ {
+ Map<String, String> levels = _loggingFacade.retrieveRuntimeLoggersLevels();
+ String actualLevel = levels.get(loggerName);
+ assertEquals(expectedLevel, actualLevel);
+ }
+
+ private String createTestLog4jXml() throws Exception
+ {
+ File dst = File.createTempFile("log4j." + getName(), "xml");
+ File filename = new File(getClass().getResource("LoggingFacadeTest.log4j.xml").toURI());
+ FileUtils.copy(filename, dst);
+ dst.deleteOnExit();
+ return dst.getAbsolutePath();
+ }
+}
diff --git a/java/broker/src/test/java/org/apache/qpid/server/logging/log4j/LoggingFacadeTest.log4j.xml b/java/broker/src/test/java/org/apache/qpid/server/logging/log4j/LoggingFacadeTest.log4j.xml
new file mode 100644
index 0000000000..62ec877d3d
--- /dev/null
+++ b/java/broker/src/test/java/org/apache/qpid/server/logging/log4j/LoggingFacadeTest.log4j.xml
@@ -0,0 +1,41 @@
+<?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">
+
+<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/" debug="null" threshold="null">
+
+ <category additivity="true" name="a.b.c">
+ <priority value="INFO"/>
+ </category>
+
+ <logger additivity="true" name="a.b.c.1">
+ <level value="DEBUG"/>
+ </logger>
+
+ <logger additivity="true" name="a.b.c.2">
+ <level value="TRACE"/>
+ </logger>
+
+ <root>
+ <priority value="WARN"/>
+ </root>
+
+</log4j:configuration>
diff --git a/java/broker/src/test/java/org/apache/qpid/server/logging/management/LoggingManagementMBeanTest.java b/java/broker/src/test/java/org/apache/qpid/server/logging/management/LoggingManagementMBeanTest.java
deleted file mode 100644
index f9ad81ae74..0000000000
--- a/java/broker/src/test/java/org/apache/qpid/server/logging/management/LoggingManagementMBeanTest.java
+++ /dev/null
@@ -1,428 +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.logging.management;
-
-import org.apache.log4j.Level;
-import org.apache.log4j.Logger;
-
-import org.apache.qpid.server.util.InternalBrokerBaseCase;
-
-import static org.apache.qpid.management.common.mbeans.LoggingManagement.LOGGER_LEVEL;
-import static org.apache.qpid.management.common.mbeans.LoggingManagement.LOGGER_NAME;
-
-import javax.management.JMException;
-import javax.management.openmbean.CompositeData;
-import javax.management.openmbean.TabularDataSupport;
-import java.io.BufferedWriter;
-import java.io.File;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Map;
-
-public class LoggingManagementMBeanTest extends InternalBrokerBaseCase
-{
- private static final String TEST_LOGGER = "LoggingManagementMBeanTestLogger";
- private static final String TEST_LOGGER_CHILD1 = "LoggingManagementMBeanTestLogger.child1";
- private static final String TEST_LOGGER_CHILD2 = "LoggingManagementMBeanTestLogger.child2";
-
- private static final String TEST_CATEGORY_PRIORITY = "LogManMBeanTest.category.priority";
- private static final String TEST_CATEGORY_LEVEL = "LogManMBeanTest.category.level";
- private static final String TEST_LOGGER_LEVEL = "LogManMBeanTest.logger.level";
-
- private static final String NEWLINE = System.getProperty("line.separator");
-
- private File _testConfigFile;
-
- @Override
- public void setUp() throws Exception
- {
- super.setUp();
- _testConfigFile = createTempTestLog4JConfig();
- }
-
- @Override
- public void tearDown() throws Exception
- {
- File oldTestConfigFile = new File(_testConfigFile.getAbsolutePath() + ".old");
- if(oldTestConfigFile.exists())
- {
- oldTestConfigFile.delete();
- }
-
- _testConfigFile.delete();
-
- super.tearDown();
- }
-
- private File createTempTestLog4JConfig()
- {
- File tmpFile = null;
- try
- {
- tmpFile = File.createTempFile("LogManMBeanTestLog4jConfig", ".tmp");
- tmpFile.deleteOnExit();
-
- FileWriter fstream = new FileWriter(tmpFile);
- BufferedWriter writer = new BufferedWriter(fstream);
-
- writer.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"+NEWLINE);
- writer.write("<!DOCTYPE log4j:configuration SYSTEM \"log4j.dtd\">"+NEWLINE);
-
- writer.write("<log4j:configuration xmlns:log4j=\"http://jakarta.apache.org/log4j/\" debug=\"null\" " +
- "threshold=\"null\">"+NEWLINE);
-
- writer.write(" <appender class=\"org.apache.log4j.ConsoleAppender\" name=\"STDOUT\">"+NEWLINE);
- writer.write(" <layout class=\"org.apache.log4j.PatternLayout\">"+NEWLINE);
- writer.write(" <param name=\"ConversionPattern\" value=\"%d %-5p [%t] %C{2} (%F:%L) - %m%n\"/>"+NEWLINE);
- writer.write(" </layout>"+NEWLINE);
- writer.write(" </appender>"+NEWLINE);
-
- //Example of a 'category' with a 'priority'
- writer.write(" <category additivity=\"true\" name=\"" + TEST_CATEGORY_PRIORITY +"\">"+NEWLINE);
- writer.write(" <priority value=\"info\"/>"+NEWLINE);
- writer.write(" <appender-ref ref=\"STDOUT\"/>"+NEWLINE);
- writer.write(" </category>"+NEWLINE);
-
- //Example of a 'category' with a 'level'
- writer.write(" <category additivity=\"true\" name=\"" + TEST_CATEGORY_LEVEL +"\">"+NEWLINE);
- writer.write(" <level value=\"warn\"/>"+NEWLINE);
- writer.write(" <appender-ref ref=\"STDOUT\"/>"+NEWLINE);
- writer.write(" </category>"+NEWLINE);
-
- //Example of a 'logger' with a 'level'
- writer.write(" <logger additivity=\"true\" name=\"" + TEST_LOGGER_LEVEL + "\">"+NEWLINE);
- writer.write(" <level value=\"error\"/>"+NEWLINE);
- writer.write(" <appender-ref ref=\"STDOUT\"/>"+NEWLINE);
- writer.write(" </logger>"+NEWLINE);
-
- //'root' logger
- writer.write(" <root>"+NEWLINE);
- writer.write(" <priority value=\"info\"/>"+NEWLINE);
- writer.write(" <appender-ref ref=\"STDOUT\"/>"+NEWLINE);
- writer.write(" </root>"+NEWLINE);
-
- writer.write("</log4j:configuration>"+NEWLINE);
-
- writer.flush();
- writer.close();
- }
- catch (IOException e)
- {
- fail("Unable to create temporary test log4j configuration");
- }
-
- return tmpFile;
- }
-
-
-
- //******* Test Methods ******* //
-
- public void testSetRuntimeLoggerLevel()
- {
- LoggingManagementMBean lm = null;
- try
- {
- lm = new LoggingManagementMBean(_testConfigFile.getAbsolutePath(), 0);
- }
- catch (JMException e)
- {
- fail("Could not create test LoggingManagementMBean");
- }
-
- //create a parent test logger, set its level explicitly
- Logger log = Logger.getLogger(TEST_LOGGER);
- log.setLevel(Level.toLevel("info"));
-
- //create child1 test logger, check its *effective* level is the same as the parent, "info"
- Logger log1 = Logger.getLogger(TEST_LOGGER_CHILD1);
- assertTrue("Test logger's level was not the expected value",
- log1.getEffectiveLevel().toString().equalsIgnoreCase("info"));
-
- //now change its level to "warn"
- assertTrue("Failed to set logger level", lm.setRuntimeLoggerLevel(TEST_LOGGER_CHILD1, "warn"));
-
- //check the change, see its actual level is "warn
- assertTrue("Test logger's level was not the expected value",
- log1.getLevel().toString().equalsIgnoreCase("warn"));
-
- //try an invalid level
- assertFalse("Trying to set an invalid level succeded", lm.setRuntimeLoggerLevel(TEST_LOGGER_CHILD1, "made.up.level"));
- }
-
- public void testSetRuntimeRootLoggerLevel()
- {
- LoggingManagementMBean lm = null;
- try
- {
- lm = new LoggingManagementMBean(_testConfigFile.getAbsolutePath(), 0);
- }
- catch (JMException e)
- {
- fail("Could not create test LoggingManagementMBean");
- }
-
- Logger log = Logger.getRootLogger();
-
- //get current root logger level
- Level origLevel = log.getLevel();
-
- //change level twice to ensure a new level is actually selected
-
- //set root loggers level to info
- assertTrue("Failed to set root logger level", lm.setRuntimeRootLoggerLevel("debug"));
- //check it is now actually info
- Level currentLevel = log.getLevel();
- assertTrue("Logger level was not expected value", currentLevel.equals(Level.toLevel("debug")));
-
- //try an invalid level
- assertFalse("Trying to set an invalid level succeded", lm.setRuntimeRootLoggerLevel("made.up.level"));
-
- //set root loggers level to warn
- assertTrue("Failed to set logger level", lm.setRuntimeRootLoggerLevel("info"));
- //check it is now actually warn
- currentLevel = log.getLevel();
- assertTrue("Logger level was not expected value", currentLevel.equals(Level.toLevel("info")));
-
- //restore original level
- log.setLevel(origLevel);
- }
-
- public void testGetRuntimeRootLoggerLevel()
- {
- LoggingManagementMBean lm = null;
- try
- {
- lm = new LoggingManagementMBean(_testConfigFile.getAbsolutePath(), 0);
- }
- catch (JMException e)
- {
- fail("Could not create test LoggingManagementMBean");
- }
-
- Logger log = Logger.getRootLogger();
-
- //get current root logger level
- Level origLevel = log.getLevel();
-
- //change level twice to ensure a new level is actually selected
-
- //set root loggers level to debug
- log.setLevel(Level.toLevel("debug"));
- //check it is now actually debug
- assertTrue("Logger level was not expected value", lm.getRuntimeRootLoggerLevel().equalsIgnoreCase("debug"));
-
-
- //set root loggers level to warn
- log.setLevel(Level.toLevel("info"));
- //check it is now actually warn
- assertTrue("Logger level was not expected value", lm.getRuntimeRootLoggerLevel().equalsIgnoreCase("info"));
-
- //restore original level
- log.setLevel(origLevel);
- }
-
- public void testViewEffectiveRuntimeLoggerLevels()
- {
- LoggingManagementMBean lm = null;
- try
- {
- lm = new LoggingManagementMBean(_testConfigFile.getAbsolutePath(), 0);
- }
- catch (JMException e)
- {
- fail("Could not create test LoggingManagementMBean");
- }
-
- //(re)create a parent test logger, set its level explicitly
- Logger log = Logger.getLogger(TEST_LOGGER);
- log.setLevel(Level.toLevel("info"));
-
- //retrieve the current effective runtime logger level values
- TabularDataSupport levels = (TabularDataSupport) lm.viewEffectiveRuntimeLoggerLevels();
- Collection<Object> records = levels.values();
- Map<String,String> list = new HashMap<String,String>();
- for (Object o : records)
- {
- CompositeData data = (CompositeData) o;
- list.put(data.get(LOGGER_NAME).toString(), data.get(LOGGER_LEVEL).toString());
- }
-
- //check child2 does not exist already
- assertFalse("Did not expect this logger to exist already", list.containsKey(TEST_LOGGER_CHILD2));
-
- //create child2 test logger
- Logger log2 = Logger.getLogger(TEST_LOGGER_CHILD2);
-
- //retrieve the current effective runtime logger level values
- levels = (TabularDataSupport) lm.viewEffectiveRuntimeLoggerLevels();
- records = levels.values();
- list = new HashMap<String,String>();
- for (Object o : records)
- {
- CompositeData data = (CompositeData) o;
- list.put(data.get(LOGGER_NAME).toString(), data.get(LOGGER_LEVEL).toString());
- }
-
- //verify the parent and child2 loggers are present in returned values
- assertTrue(TEST_LOGGER + " logger was not in the returned list", list.containsKey(TEST_LOGGER));
- assertTrue(TEST_LOGGER_CHILD2 + " logger was not in the returned list", list.containsKey(TEST_LOGGER_CHILD2));
-
- //check child2's effective level is the same as the parent, "info"
- assertTrue("Test logger's level was not the expected value",
- list.get(TEST_LOGGER_CHILD2).equalsIgnoreCase("info"));
-
- //now change its level explicitly to "warn"
- log2.setLevel(Level.toLevel("warn"));
-
- //retrieve the current effective runtime logger level values
- levels = (TabularDataSupport) lm.viewEffectiveRuntimeLoggerLevels();
- records = levels.values();
- list = new HashMap<String,String>();
- for (Object o : records)
- {
- CompositeData data = (CompositeData) o;
- list.put(data.get(LOGGER_NAME).toString(), data.get(LOGGER_LEVEL).toString());
- }
-
- //check child2's effective level is now "warn"
- assertTrue("Test logger's level was not the expected value",
- list.get(TEST_LOGGER_CHILD2).equalsIgnoreCase("warn"));
- }
-
- public void testViewAndSetConfigFileLoggerLevel() throws Exception
- {
- LoggingManagementMBean lm =null;
- try
- {
- lm = new LoggingManagementMBean(_testConfigFile.getAbsolutePath(), 0);
- }
- catch (JMException e)
- {
- fail("Could not create test LoggingManagementMBean");
- }
-
- //retrieve the current values
- TabularDataSupport levels = (TabularDataSupport) lm.viewConfigFileLoggerLevels();
- Collection<Object> records = levels.values();
- Map<String,String> list = new HashMap<String,String>();
- for (Object o : records)
- {
- CompositeData data = (CompositeData) o;
- list.put(data.get(LOGGER_NAME).toString(), data.get(LOGGER_LEVEL).toString());
- }
-
- //check the 3 different types of logger definition are successfully retrieved before update
- assertTrue("Wrong number of items in returned list", list.size() == 3);
- assertTrue(TEST_CATEGORY_PRIORITY + " logger was not in the returned list", list.containsKey(TEST_CATEGORY_PRIORITY));
- assertTrue(TEST_CATEGORY_LEVEL + " logger was not in the returned list", list.containsKey(TEST_CATEGORY_LEVEL));
- assertTrue(TEST_LOGGER_LEVEL + " logger was not in the returned list", list.containsKey(TEST_LOGGER_LEVEL));
-
- //check that their level is as expected
- assertTrue(TEST_CATEGORY_PRIORITY + " logger's level was incorrect", list.get(TEST_CATEGORY_PRIORITY).equalsIgnoreCase("info"));
- assertTrue(TEST_CATEGORY_LEVEL + " logger's level was incorrect", list.get(TEST_CATEGORY_LEVEL).equalsIgnoreCase("warn"));
- assertTrue(TEST_LOGGER_LEVEL + " logger's level was incorrect", list.get(TEST_LOGGER_LEVEL).equalsIgnoreCase("error"));
-
- //increase their levels a notch to test the 3 different types of logger definition are successfully updated
- //change the category+priority to warn
- assertTrue("failed to set new level", lm.setConfigFileLoggerLevel(TEST_CATEGORY_PRIORITY, "warn"));
- //change the category+level to error
- assertTrue("failed to set new level", lm.setConfigFileLoggerLevel(TEST_CATEGORY_LEVEL, "error"));
- //change the logger+level to trace
- assertTrue("failed to set new level", lm.setConfigFileLoggerLevel(TEST_LOGGER_LEVEL, "trace"));
-
- //try an invalid level
- assertFalse("Use of an invalid logger level was successfull", lm.setConfigFileLoggerLevel(TEST_LOGGER_LEVEL, "made.up.level"));
-
- //try an invalid logger name
- assertFalse("Use of an invalid logger name was successfull", lm.setConfigFileLoggerLevel("made.up.logger.name", "info"));
-
- //retrieve the new values from the file and check them
- levels = (TabularDataSupport) lm.viewConfigFileLoggerLevels();
- records = levels.values();
- list = new HashMap<String,String>();
- for (Object o : records)
- {
- CompositeData data = (CompositeData) o;
- list.put(data.get(LOGGER_NAME).toString(), data.get(LOGGER_LEVEL).toString());
- }
-
- //check the 3 different types of logger definition are successfully retrieved after update
- assertTrue("Wrong number of items in returned list", list.size() == 3);
- assertTrue(TEST_CATEGORY_PRIORITY + " logger was not in the returned list", list.containsKey(TEST_CATEGORY_PRIORITY));
- assertTrue(TEST_CATEGORY_LEVEL + " logger was not in the returned list", list.containsKey(TEST_CATEGORY_LEVEL));
- assertTrue(TEST_LOGGER_LEVEL + " logger was not in the returned list", list.containsKey(TEST_LOGGER_LEVEL));
-
- //check that their level is as expected after the changes
- assertTrue(TEST_CATEGORY_PRIORITY + " logger's level was incorrect", list.get(TEST_CATEGORY_PRIORITY).equalsIgnoreCase("warn"));
- assertTrue(TEST_CATEGORY_LEVEL + " logger's level was incorrect", list.get(TEST_CATEGORY_LEVEL).equalsIgnoreCase("error"));
- assertTrue(TEST_LOGGER_LEVEL + " logger's level was incorrect", list.get(TEST_LOGGER_LEVEL).equalsIgnoreCase("trace"));
- }
-
- public void testGetAndSetConfigFileRootLoggerLevel() throws Exception
- {
- LoggingManagementMBean lm =null;
- try
- {
- lm = new LoggingManagementMBean(_testConfigFile.getAbsolutePath(), 0);
- }
- catch (JMException e)
- {
- fail("Could not create test LoggingManagementMBean");
- }
-
- //retrieve the current value
- String level = lm.getConfigFileRootLoggerLevel();
-
- //check the value was successfully retrieved before update
- assertTrue("Retrieved RootLogger level was incorrect", level.equalsIgnoreCase("info"));
-
- //try an invalid level
- assertFalse("Use of an invalid RootLogger level was successfull", lm.setConfigFileRootLoggerLevel("made.up.level"));
-
- //change the level to warn
- assertTrue("Failed to set new RootLogger level", lm.setConfigFileRootLoggerLevel("warn"));
-
- //retrieve the current value
- level = lm.getConfigFileRootLoggerLevel();
-
- //check the value was successfully retrieved after update
- assertTrue("Retrieved RootLogger level was incorrect", level.equalsIgnoreCase("warn"));
- }
-
- public void testGetLog4jLogWatchInterval()
- {
- LoggingManagementMBean lm =null;
- try
- {
- lm = new LoggingManagementMBean(_testConfigFile.getAbsolutePath(), 5000);
- }
- catch (JMException e)
- {
- fail("Could not create test LoggingManagementMBean");
- }
-
- assertTrue("Wrong value returned for logWatch period", lm.getLog4jLogWatchInterval() == 5000);
- }
-
-}
diff --git a/java/broker/src/test/java/org/apache/qpid/server/logging/messages/BrokerMessagesTest.java b/java/broker/src/test/java/org/apache/qpid/server/logging/messages/BrokerMessagesTest.java
index e87d292471..6571d20711 100644
--- a/java/broker/src/test/java/org/apache/qpid/server/logging/messages/BrokerMessagesTest.java
+++ b/java/broker/src/test/java/org/apache/qpid/server/logging/messages/BrokerMessagesTest.java
@@ -20,10 +20,9 @@
*/
package org.apache.qpid.server.logging.messages;
+import java.text.NumberFormat;
import java.util.List;
-import org.apache.derby.iapi.services.io.FileUtil;
-
/**
* Test BRK log Messages
*/
@@ -139,7 +138,7 @@ public class BrokerMessagesTest extends AbstractTestMessages
_logMessage = BrokerMessages.MAX_MEMORY(oneGiga);
List<Object> log = performLog();
- String[] expected = {"Maximum Memory :", "1,073,741,824", "bytes"};
+ String[] expected = {"Maximum Memory :", NumberFormat.getNumberInstance().format(oneGiga), "bytes"};
validateLogMessage(log, "BRK-1011", 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
deleted file mode 100644
index f7d85c11a8..0000000000
--- a/java/broker/src/test/java/org/apache/qpid/server/management/AMQUserManagementMBeanTest.java
+++ /dev/null
@@ -1,153 +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.management;
-
-import org.apache.qpid.management.common.mbeans.UserManagement;
-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;
-
-import javax.management.openmbean.CompositeData;
-import javax.management.openmbean.TabularData;
-import java.io.BufferedWriter;
-import java.io.File;
-import java.io.FileWriter;
-import java.io.IOException;
-
-/**
- *
- * Tests the AMQUserManagementMBean and its interaction with the PrincipalDatabase.
- *
- */
-public class AMQUserManagementMBeanTest extends InternalBrokerBaseCase
-{
- private PlainPasswordFilePrincipalDatabase _database;
- private AMQUserManagementMBean _amqumMBean;
-
- private File _passwordFile;
-
- private static final String TEST_USERNAME = "testuser";
- private static final String TEST_PASSWORD = "password";
-
- @Override
- public void setUp() throws Exception
- {
- super.setUp();
-
- _database = new PlainPasswordFilePrincipalDatabase();
- _amqumMBean = new AMQUserManagementMBean();
- loadFreshTestPasswordFile();
- }
-
- @Override
- public void tearDown() throws Exception
- {
- //clean up test password/access files
- File _oldPasswordFile = new File(_passwordFile.getAbsolutePath() + ".old");
- _oldPasswordFile.delete();
- _passwordFile.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());
-
- }
-
- public void testCreateUser()
- {
- 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());
- }
-
- 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());
- }
-
- public void testSetPassword()
- {
- assertTrue("Set password should return true to flag successful change", _amqumMBean.setPassword(TEST_USERNAME, "newpassword"));
- }
-
- public void testSetPasswordWhereUserDoesNotExist()
- {
- assertFalse("Set password should return false to flag successful change", _amqumMBean.setPassword("made.up.username", "newpassword"));
- }
-
- public void testViewUsers()
- {
- TabularData userList = _amqumMBean.viewUsers();
-
- 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));
- }
-
- // ============================ Utility methods =========================
-
- private void loadFreshTestPasswordFile()
- {
- try
- {
- if(_passwordFile == null)
- {
- _passwordFile = File.createTempFile(this.getClass().getName(),".password");
- }
-
- BufferedWriter passwordWriter = new BufferedWriter(new FileWriter(_passwordFile, false));
- passwordWriter.write(TEST_USERNAME + ":" + TEST_PASSWORD);
- passwordWriter.newLine();
- passwordWriter.flush();
- passwordWriter.close();
- _database.setPasswordFile(_passwordFile.toString());
- _amqumMBean.setPrincipalDatabase(_database);
- }
- catch (IOException e)
- {
- fail("Unable to create test password file: " + e.getMessage());
- }
- }
-}
diff --git a/java/broker/src/test/java/org/apache/qpid/server/model/UUIDGeneratorTest.java b/java/broker/src/test/java/org/apache/qpid/server/model/UUIDGeneratorTest.java
new file mode 100644
index 0000000000..643132d371
--- /dev/null
+++ b/java/broker/src/test/java/org/apache/qpid/server/model/UUIDGeneratorTest.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.server.model;
+
+import java.util.HashSet;
+import java.util.Set;
+import java.util.UUID;
+
+import org.apache.qpid.test.utils.QpidTestCase;
+
+public class UUIDGeneratorTest extends QpidTestCase
+{
+ private static final String VIRTUAL_HOST_NAME_1 = "virtualHost1";
+ private static final String VIRTUAL_HOST_NAME_2 = "virtualHost2";
+ private static final String VHOST_ALIAS_1 = "alias1";
+ private static final String VHOST_ALIAS_2 = "alias2";
+ private static final String QUEUE_NAME_1 = "queue1";
+ private static final String QUEUE_NAME_2 = "queue2";
+ private static final String EXCHANGE_NAME_1 = "exchange1";
+ private static final String EXCHANGE_NAME_2 = "exchange2";
+ private static final String BINDING_KEY_1 = "bindingKey1";
+ private static final String BINDING_KEY_2 = "bindingKey2";
+ private static final String PORT_1 = "port1";
+ private static final String PORT_2 = "port2";
+ private static final String CONN_REMOTE_ADDR_1 = "localhost:1234";
+ private static final String CONN_REMOTE_ADDR_2 = "localhost:5678";
+ private static final String CHANNEL_NUMBER_1 = "1";
+ private static final String CHANNEL_NUMBER_2 = "2";
+ private static final String CONSUMER_NAME_1 = "consumer1";
+ private static final String CONSUMER_NAME_2 = "consumer2";
+ private static final String PROVIDER_1 = "provider1";
+ private static final String PROVIDER_2 = "provider2";
+ private static final String USER_1 = "user1";
+ private static final String USER_2 = "user2";
+
+ public void testDifferentObjectTypeReturnDifferentIdFromSameValues() throws Exception
+ {
+ String value = "name";
+ Set<UUID> idSet = new HashSet<UUID>();
+
+ UUID id1 = UUIDGenerator.generateQueueUUID(value, value);
+ idSet.add(id1);
+ UUID id2 = UUIDGenerator.generateExchangeUUID(value, value);
+ idSet.add(id2);
+ UUID id3 = UUIDGenerator.generateBindingUUID(value, value, value, value);
+ idSet.add(id3);
+ UUID id4 = UUIDGenerator.generateConsumerUUID(value, value, value, value, value);
+ idSet.add(id4);
+ UUID id5 = UUIDGenerator.generateUserUUID(value, value);
+ idSet.add(id5);
+ UUID id6 = UUIDGenerator.generateVhostUUID(value);
+ idSet.add(id6);
+ UUID id7 = UUIDGenerator.generateVhostAliasUUID(value, value);
+ idSet.add(id7);
+
+ assertEquals("The produced UUIDs were not all unique", 7, idSet.size());
+ }
+
+ public void testQueueIdGeneration() throws Exception
+ {
+ //check repeated generation is deterministic
+ UUID queue1 = UUIDGenerator.generateQueueUUID(QUEUE_NAME_1, VIRTUAL_HOST_NAME_1);
+ UUID queue2 = UUIDGenerator.generateQueueUUID(QUEUE_NAME_1, VIRTUAL_HOST_NAME_1);
+ assertEquals("Queue IDs should be equal", queue1, queue2);
+
+ //check different name gives different ID
+ queue1 = UUIDGenerator.generateQueueUUID(QUEUE_NAME_1, VIRTUAL_HOST_NAME_1);
+ queue2 = UUIDGenerator.generateQueueUUID(QUEUE_NAME_2, VIRTUAL_HOST_NAME_1);
+ assertFalse("Queue IDs should not be equal", queue1.equals(queue2));
+
+ //check different vhost name gives different ID
+ queue1 = UUIDGenerator.generateQueueUUID(QUEUE_NAME_1, VIRTUAL_HOST_NAME_1);
+ queue2 = UUIDGenerator.generateQueueUUID(QUEUE_NAME_1, VIRTUAL_HOST_NAME_2);
+ assertFalse("Queue IDs should not be equal", queue1.equals(queue2));
+ }
+
+ public void testExchangeIdGeneration() throws Exception
+ {
+ //check repeated generation is deterministic
+ UUID exchange1 = UUIDGenerator.generateExchangeUUID(EXCHANGE_NAME_1, VIRTUAL_HOST_NAME_1);
+ UUID exchange2 = UUIDGenerator.generateExchangeUUID(EXCHANGE_NAME_1, VIRTUAL_HOST_NAME_1);
+ assertEquals("Exchange IDs should be equal", exchange1, exchange2);
+
+ //check different name gives different ID
+ exchange1 = UUIDGenerator.generateExchangeUUID(EXCHANGE_NAME_1, VIRTUAL_HOST_NAME_1);
+ exchange2 = UUIDGenerator.generateExchangeUUID(EXCHANGE_NAME_2, VIRTUAL_HOST_NAME_1);
+ assertFalse("Exchange IDs should not be equal", exchange1.equals(exchange2));
+
+ //check different vhost name gives different ID
+ exchange1 = UUIDGenerator.generateExchangeUUID(EXCHANGE_NAME_1, VIRTUAL_HOST_NAME_1);
+ exchange2 = UUIDGenerator.generateExchangeUUID(EXCHANGE_NAME_1, VIRTUAL_HOST_NAME_2);
+ assertFalse("Exchange IDs should not be equal", exchange1.equals(exchange2));
+ }
+
+ public void testBindingIdGeneration() throws Exception
+ {
+ //check repeated generation is deterministic
+ UUID binding1 = UUIDGenerator.generateBindingUUID(EXCHANGE_NAME_1, QUEUE_NAME_1, BINDING_KEY_1, VIRTUAL_HOST_NAME_1);
+ UUID binding2 = UUIDGenerator.generateBindingUUID(EXCHANGE_NAME_1, QUEUE_NAME_1, BINDING_KEY_1, VIRTUAL_HOST_NAME_1);
+ assertEquals("Binding IDs should be equal", binding1, binding2);
+
+ //check different name gives different ID
+ binding1 = UUIDGenerator.generateBindingUUID(EXCHANGE_NAME_1, QUEUE_NAME_1, BINDING_KEY_1, VIRTUAL_HOST_NAME_1);
+ binding2 = UUIDGenerator.generateBindingUUID(EXCHANGE_NAME_1, QUEUE_NAME_1, BINDING_KEY_2, VIRTUAL_HOST_NAME_1);
+ assertFalse("Binding IDs should not be equal", binding1.equals(binding2));
+
+ //check different vhost name gives different ID
+ binding1 = UUIDGenerator.generateBindingUUID(EXCHANGE_NAME_1, QUEUE_NAME_1, BINDING_KEY_1, VIRTUAL_HOST_NAME_1);
+ binding2 = UUIDGenerator.generateBindingUUID(EXCHANGE_NAME_1, QUEUE_NAME_1, BINDING_KEY_1, VIRTUAL_HOST_NAME_2);
+ assertFalse("Binding IDs should not be equal", binding1.equals(binding2));
+ }
+
+ public void testVhostIdGeneration() throws Exception
+ {
+ //check repeated generation is deterministic
+ UUID vhost1 = UUIDGenerator.generateVhostUUID(VIRTUAL_HOST_NAME_1);
+ UUID vhost2 = UUIDGenerator.generateVhostUUID(VIRTUAL_HOST_NAME_1);
+ assertTrue("Virtualhost IDs should be equal", vhost1.equals(vhost2));
+
+ //check different vhost name gives different ID
+ vhost1 = UUIDGenerator.generateVhostUUID(VIRTUAL_HOST_NAME_1);
+ vhost2 = UUIDGenerator.generateVhostUUID(VIRTUAL_HOST_NAME_2);
+ assertFalse("Virtualhost IDs should not be equal", vhost1.equals(vhost2));
+ }
+
+ public void testVhostAliasIdGeneration() throws Exception
+ {
+ //check repeated generation is deterministic
+ UUID alias1 = UUIDGenerator.generateVhostAliasUUID(VHOST_ALIAS_1, PORT_1);
+ UUID alias2 = UUIDGenerator.generateVhostAliasUUID(VHOST_ALIAS_1, PORT_1);
+ assertTrue("Virtualhost Alias IDs should be equal", alias1.equals(alias2));
+
+ //check different port name gives different ID
+ alias1 = UUIDGenerator.generateVhostAliasUUID(VHOST_ALIAS_1, PORT_1);
+ alias2 = UUIDGenerator.generateVhostAliasUUID(VHOST_ALIAS_2, PORT_1);
+ assertFalse("Virtualhost Alias IDs should not be equal", alias1.equals(alias2));
+
+ //check different alias name gives different ID
+ alias1 = UUIDGenerator.generateVhostAliasUUID(VHOST_ALIAS_1, PORT_1);
+ alias2 = UUIDGenerator.generateVhostAliasUUID(VHOST_ALIAS_1, PORT_2);
+ assertFalse("Virtualhost Alias IDs should not be equal", alias1.equals(alias2));
+ }
+
+ public void testConsumerIdGeneration() throws Exception
+ {
+ //check repeated generation is deterministic
+ UUID consumer1 = UUIDGenerator.generateConsumerUUID(VIRTUAL_HOST_NAME_1, QUEUE_NAME_1, CONN_REMOTE_ADDR_1, CHANNEL_NUMBER_1, CONSUMER_NAME_1);
+ UUID consumer2 = UUIDGenerator.generateConsumerUUID(VIRTUAL_HOST_NAME_1, QUEUE_NAME_1, CONN_REMOTE_ADDR_1, CHANNEL_NUMBER_1, CONSUMER_NAME_1);
+ assertTrue("Consumer IDs should be equal", consumer1.equals(consumer2));
+
+ //check different name gives different ID
+ consumer1 = UUIDGenerator.generateConsumerUUID(VIRTUAL_HOST_NAME_1, QUEUE_NAME_1, CONN_REMOTE_ADDR_1, CHANNEL_NUMBER_1, CONSUMER_NAME_1);
+ consumer2 = UUIDGenerator.generateConsumerUUID(VIRTUAL_HOST_NAME_1, QUEUE_NAME_1, CONN_REMOTE_ADDR_1, CHANNEL_NUMBER_1, CONSUMER_NAME_2);
+ assertFalse("Consumer IDs should not be equal", consumer1.equals(consumer2));
+
+ //check different vhost name gives different ID
+ consumer1 = UUIDGenerator.generateConsumerUUID(VIRTUAL_HOST_NAME_1, QUEUE_NAME_1, CONN_REMOTE_ADDR_1, CHANNEL_NUMBER_1, CONSUMER_NAME_1);
+ consumer2 = UUIDGenerator.generateConsumerUUID(VIRTUAL_HOST_NAME_2, QUEUE_NAME_1, CONN_REMOTE_ADDR_1, CHANNEL_NUMBER_1, CONSUMER_NAME_1);
+ assertFalse("Consumer IDs should not be equal", consumer1.equals(consumer2));
+
+ //check different consumer name gives different ID
+ consumer1 = UUIDGenerator.generateConsumerUUID(VIRTUAL_HOST_NAME_1, QUEUE_NAME_1, CONN_REMOTE_ADDR_1, CHANNEL_NUMBER_1, CONSUMER_NAME_1);
+ consumer2 = UUIDGenerator.generateConsumerUUID(VIRTUAL_HOST_NAME_1, QUEUE_NAME_1, CONN_REMOTE_ADDR_1, CHANNEL_NUMBER_2, CONSUMER_NAME_1);
+ assertFalse("Consumer IDs should not be equal", consumer1.equals(consumer2));
+
+ //check different address name gives different ID
+ consumer1 = UUIDGenerator.generateConsumerUUID(VIRTUAL_HOST_NAME_1, QUEUE_NAME_1, CONN_REMOTE_ADDR_1, CHANNEL_NUMBER_1, CONSUMER_NAME_1);
+ consumer2 = UUIDGenerator.generateConsumerUUID(VIRTUAL_HOST_NAME_1, QUEUE_NAME_1, CONN_REMOTE_ADDR_2, CHANNEL_NUMBER_1, CONSUMER_NAME_1);
+ assertFalse("Consumer IDs should not be equal", consumer1.equals(consumer2));
+
+ //check different queue name gives different ID
+ consumer1 = UUIDGenerator.generateConsumerUUID(VIRTUAL_HOST_NAME_1, QUEUE_NAME_1, CONN_REMOTE_ADDR_1, CHANNEL_NUMBER_1, CONSUMER_NAME_1);
+ consumer2 = UUIDGenerator.generateConsumerUUID(VIRTUAL_HOST_NAME_1, QUEUE_NAME_2, CONN_REMOTE_ADDR_1, CHANNEL_NUMBER_1, CONSUMER_NAME_1);
+ assertFalse("Consumer IDs should not be equal", consumer1.equals(consumer2));
+ }
+
+ public void testUserIdGeneration() throws Exception
+ {
+ //check repeated generation is deterministic
+ UUID user1 = UUIDGenerator.generateUserUUID(PROVIDER_1, USER_1);
+ UUID user2 = UUIDGenerator.generateUserUUID(PROVIDER_1, USER_1);
+ assertTrue("User IDs should be equal", user1.equals(user2));
+
+ //check different name gives different ID
+ user1 = UUIDGenerator.generateUserUUID(PROVIDER_1, USER_1);
+ user2 = UUIDGenerator.generateUserUUID(PROVIDER_1, USER_2);
+ assertFalse("User IDs should not be equal", user1.equals(user2));
+
+ //check different provider gives different ID
+ user1 = UUIDGenerator.generateUserUUID(PROVIDER_1, USER_1);
+ user2 = UUIDGenerator.generateUserUUID(PROVIDER_2, USER_1);
+ assertFalse("User IDs should not be equal", user1.equals(user2));
+ }
+
+}
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
index 267545c656..20abdd48cd 100644
--- 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
@@ -73,11 +73,11 @@ public class OsgiSystemPackageUtilTest extends QpidTestCase
_map.put("org.apache.qpid.xyz", "1.0.0");
_map.put("org.abc", "1.2.3");
- _util = new OsgiSystemPackageUtil(new Version("0.17"), _map);
+ _util = new OsgiSystemPackageUtil(new Version("0.19"), _map);
final String systemPackageString = _util.getFormattedSystemPackageString();
- assertEquals("org.abc; version=1.2.3, org.apache.qpid.xyz; version=0.17.0", systemPackageString);
+ assertEquals("org.abc; version=1.2.3, org.apache.qpid.xyz; version=0.19.0", systemPackageString);
}
public void testWithQpidPackageWithoutQpidReleaseNumberSet() throws Exception
diff --git a/java/broker/src/test/java/org/apache/qpid/server/protocol/AMQProtocolSessionMBeanTest.java b/java/broker/src/test/java/org/apache/qpid/server/protocol/AMQProtocolSessionMBeanTest.java
deleted file mode 100644
index fe9bcc57a6..0000000000
--- a/java/broker/src/test/java/org/apache/qpid/server/protocol/AMQProtocolSessionMBeanTest.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 org.apache.log4j.Logger;
-
-import org.apache.qpid.AMQException;
-import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpid.management.common.mbeans.ManagedConnection;
-import org.apache.qpid.server.AMQChannel;
-import org.apache.qpid.server.queue.AMQQueue;
-import org.apache.qpid.server.queue.AMQQueueFactory;
-import org.apache.qpid.server.registry.ApplicationRegistry;
-import org.apache.qpid.server.store.MessageStore;
-import org.apache.qpid.server.store.TestableMemoryMessageStore;
-import org.apache.qpid.server.util.InternalBrokerBaseCase;
-import org.apache.qpid.server.virtualhost.VirtualHost;
-
-import javax.management.JMException;
-import javax.management.openmbean.CompositeData;
-import javax.management.openmbean.TabularData;
-
-
-/** Test class to test MBean operations for AMQMinaProtocolSession. */
-public class AMQProtocolSessionMBeanTest extends InternalBrokerBaseCase
-{
- /** Used for debugging. */
- private static final Logger log = Logger.getLogger(AMQProtocolSessionMBeanTest.class);
-
- private MessageStore _messageStore = new TestableMemoryMessageStore();
- private AMQProtocolEngine _protocolSession;
- private AMQChannel _channel;
- private AMQProtocolSessionMBean _mbean;
-
- public void testChannels() throws Exception
- {
- // check the channel count is correct
- int channelCount = _mbean.channels().size();
- assertTrue(channelCount == 1);
- AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(new AMQShortString("testQueue_" + System.currentTimeMillis()),
- false,
- new AMQShortString("test"),
- true,
- false, _protocolSession.getVirtualHost(), null);
- AMQChannel channel = new AMQChannel(_protocolSession, 2, _messageStore);
- channel.setDefaultQueue(queue);
- _protocolSession.addChannel(channel);
- channelCount = _mbean.channels().size();
- assertTrue(channelCount == 2);
-
- // general properties test
- _protocolSession.setMaximumNumberOfChannels(1000L);
- assertTrue(_mbean.getMaximumNumberOfChannels() == 1000L);
-
- // check APIs
- AMQChannel channel3 = new AMQChannel(_protocolSession, 3, _messageStore);
- channel3.setLocalTransactional();
- _protocolSession.addChannel(channel3);
- _mbean.rollbackTransactions(2);
- _mbean.rollbackTransactions(3);
- _mbean.commitTransactions(2);
- _mbean.commitTransactions(3);
-
- // This should throw exception, because the channel does't exist
- try
- {
- _mbean.commitTransactions(4);
- fail();
- }
- catch (JMException ex)
- {
- log.debug("expected exception is thrown :" + ex.getMessage());
- }
-
- // check channels() return type conveys flow control blocking status correctly
- AMQChannel channel4 = new AMQChannel(_protocolSession, 4, _messageStore);
- _protocolSession.addChannel(channel4);
- channel4.setDefaultQueue(queue);
-
- final String blocking = ManagedConnection.FLOW_BLOCKED;
- TabularData channels = _mbean.channels();
- CompositeData chan4result = channels.get(new Integer[]{4});
- assertNotNull(chan4result);
- assertEquals("Flow should not have been blocked", false, chan4result.get(blocking));
-
- channel4.block(queue);
- channels = _mbean.channels();
- chan4result = channels.get(new Integer[]{4});
- assertNotNull(chan4result);
- assertEquals("Flow should have been blocked", true, chan4result.get(blocking));
-
- channel4.unblock(queue);
- channels = _mbean.channels();
- chan4result = channels.get(new Integer[]{4});
- assertNotNull(chan4result);
- assertEquals("Flow should have been unblocked", false, chan4result.get(blocking));
-
- // check if closing of session works
- _protocolSession.addChannel(new AMQChannel(_protocolSession, 5, _messageStore));
- _mbean.closeConnection();
- try
- {
- channelCount = _mbean.channels().size();
- assertTrue(channelCount == 0);
- // session is now closed so adding another channel should throw an exception
- _protocolSession.addChannel(new AMQChannel(_protocolSession, 6, _messageStore));
- fail();
- }
- catch (AMQException ex)
- {
- log.debug("expected exception is thrown :" + ex.getMessage());
- }
- }
-
- @Override
- public void setUp() throws Exception
- {
- super.setUp();
-
- VirtualHost vhost = ApplicationRegistry.getInstance().getVirtualHostRegistry().getVirtualHost("test");
- _protocolSession = new InternalTestProtocolSession(vhost);
-
- _channel = new AMQChannel(_protocolSession, 1, _messageStore);
- _protocolSession.addChannel(_channel);
- _mbean = (AMQProtocolSessionMBean) _protocolSession.getManagedObject();
- }
-
-}
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 01a2178911..c3d58f3bdc 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
@@ -1,4 +1,3 @@
-package org.apache.qpid.server.queue;
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
@@ -19,6 +18,7 @@ package org.apache.qpid.server.queue;
* under the License.
*
*/
+package org.apache.qpid.server.queue;
import junit.framework.AssertionFailedError;
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
deleted file mode 100644
index 25d35aab16..0000000000
--- a/java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueAlertTest.java
+++ /dev/null
@@ -1,348 +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.qpid.AMQException;
-import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpid.framing.BasicContentHeaderProperties;
-import org.apache.qpid.framing.ContentHeaderBody;
-import org.apache.qpid.framing.abstraction.ContentChunk;
-import org.apache.qpid.framing.abstraction.MessagePublishInfo;
-import org.apache.qpid.server.AMQChannel;
-import org.apache.qpid.server.message.AMQMessage;
-import org.apache.qpid.server.message.MessageMetaData;
-import org.apache.qpid.server.protocol.InternalTestProtocolSession;
-import org.apache.qpid.server.subscription.Subscription;
-import org.apache.qpid.server.subscription.SubscriptionFactoryImpl;
-import org.apache.qpid.server.util.InternalBrokerBaseCase;
-
-import javax.management.Notification;
-
-import java.nio.ByteBuffer;
-import java.util.ArrayList;
-
-/** This class tests all the alerts an AMQQueue can throw based on threshold values of different parameters */
-public class AMQQueueAlertTest extends InternalBrokerBaseCase
-{
- private final static long MAX_MESSAGE_COUNT = 50;
- private final static long MAX_MESSAGE_AGE = 250; // 0.25 sec
- private final static long MAX_MESSAGE_SIZE = 2000; // 2 KB
- private final static long MAX_QUEUE_DEPTH = 10000; // 10 KB
- private AMQQueueMBean _queueMBean;
- private static final SubscriptionFactoryImpl SUBSCRIPTION_FACTORY = SubscriptionFactoryImpl.INSTANCE;
-
- /**
- * Tests if the alert gets thrown when message count increases the threshold limit
- *
- * @throws Exception
- */
- public void testMessageCountAlert() throws Exception
- {
- setSession(new InternalTestProtocolSession(getVirtualHost()));
- AMQChannel channel = new AMQChannel(getSession(), 2, getMessageStore());
- getSession().addChannel(channel);
-
- setQueue(AMQQueueFactory.createAMQQueueImpl(new AMQShortString("testQueue1"), false, new AMQShortString("AMQueueAlertTest"),
- false, false,
- getVirtualHost(), null));
- _queueMBean = (AMQQueueMBean) getQueue().getManagedObject();
-
- _queueMBean.setMaximumMessageCount(MAX_MESSAGE_COUNT);
-
- sendMessages(channel, MAX_MESSAGE_COUNT, 256l);
- assertTrue(_queueMBean.getMessageCount() == MAX_MESSAGE_COUNT);
-
- Notification lastNotification = _queueMBean.getLastNotification();
- assertNotNull(lastNotification);
-
- String notificationMsg = lastNotification.getMessage();
- assertTrue(notificationMsg.startsWith(NotificationCheck.MESSAGE_COUNT_ALERT.name()));
- }
-
- /**
- * Tests if the Message Size alert gets thrown when message of higher than threshold limit is sent
- *
- * @throws Exception
- */
- public void testMessageSizeAlert() throws Exception
- {
- setSession(new InternalTestProtocolSession(getVirtualHost()));
- AMQChannel channel = new AMQChannel(getSession(), 2, getMessageStore());
- getSession().addChannel(channel);
-
- setQueue(AMQQueueFactory.createAMQQueueImpl(new AMQShortString("testQueue2"), false, new AMQShortString("AMQueueAlertTest"),
- false, false,
- getVirtualHost(), null));
- _queueMBean = (AMQQueueMBean) getQueue().getManagedObject();
- _queueMBean.setMaximumMessageCount(MAX_MESSAGE_COUNT);
- _queueMBean.setMaximumMessageSize(MAX_MESSAGE_SIZE);
-
- sendMessages(channel, 1, MAX_MESSAGE_SIZE * 2);
- assertTrue(_queueMBean.getMessageCount() == 1);
-
- Notification lastNotification = _queueMBean.getLastNotification();
- assertNotNull(lastNotification);
-
- String notificationMsg = lastNotification.getMessage();
- assertTrue(notificationMsg.startsWith(NotificationCheck.MESSAGE_SIZE_ALERT.name()));
- }
-
- /**
- * Tests if Queue Depth alert is thrown when queue depth reaches the threshold value
- *
- * Based on FT-402 subbmitted by client
- *
- * @throws Exception
- */
- public void testQueueDepthAlertNoSubscriber() throws Exception
- {
- setSession(new InternalTestProtocolSession(getVirtualHost()));
- AMQChannel channel = new AMQChannel(getSession(), 2, getMessageStore());
- getSession().addChannel(channel);
-
- setQueue(AMQQueueFactory.createAMQQueueImpl(new AMQShortString("testQueue3"), false, new AMQShortString("AMQueueAlertTest"),
- false, false,
- getVirtualHost(), null));
- _queueMBean = (AMQQueueMBean) getQueue().getManagedObject();
- _queueMBean.setMaximumMessageCount(MAX_MESSAGE_COUNT);
- _queueMBean.setMaximumQueueDepth(MAX_QUEUE_DEPTH);
-
- while (getQueue().getQueueDepth() < MAX_QUEUE_DEPTH)
- {
- sendMessages(channel, 1, MAX_MESSAGE_SIZE);
- }
-
- Notification lastNotification = _queueMBean.getLastNotification();
- assertNotNull(lastNotification);
-
- String notificationMsg = lastNotification.getMessage();
- assertTrue(notificationMsg.startsWith(NotificationCheck.QUEUE_DEPTH_ALERT.name()));
- }
-
- /**
- * Tests if MESSAGE AGE alert is thrown, when a message is in the queue for time higher than threshold value of
- * message age
- *
- * Alternative test to FT-401 provided by client
- *
- * @throws Exception
- */
- public void testMessageAgeAlert() throws Exception
- {
- setSession(new InternalTestProtocolSession(getVirtualHost()));
- AMQChannel channel = new AMQChannel(getSession(), 2, getMessageStore());
- getSession().addChannel(channel);
-
- setQueue(AMQQueueFactory.createAMQQueueImpl(new AMQShortString("testQueue4"), false, new AMQShortString("AMQueueAlertTest"),
- false, false,
- getVirtualHost(), null));
- _queueMBean = (AMQQueueMBean) getQueue().getManagedObject();
- _queueMBean.setMaximumMessageCount(MAX_MESSAGE_COUNT);
- _queueMBean.setMaximumMessageAge(MAX_MESSAGE_AGE);
-
- sendMessages(channel, 1, MAX_MESSAGE_SIZE);
-
- // Ensure message sits on queue long enough to age.
- Thread.sleep(MAX_MESSAGE_AGE * 2);
-
- Notification lastNotification = _queueMBean.getLastNotification();
- assertNotNull("Last notification was null", lastNotification);
-
- String notificationMsg = lastNotification.getMessage();
- assertTrue(notificationMsg.startsWith(NotificationCheck.MESSAGE_AGE_ALERT.name()));
- }
-
- /*
- This test sends some messages to the queue with subscribers needing message to be acknowledged.
- The messages will not be acknowledged and will be required twice. Why we are checking this is because
- the bug reported said that the queueDepth keeps increasing when messages are requeued.
- // TODO - queue depth now includes unacknowledged messages so does not go down when messages are delivered
-
- The QueueDepth should decrease when messages are delivered from the queue (QPID-408)
- */
- public void testQueueDepthAlertWithSubscribers() throws Exception
- {
- AMQChannel channel = new AMQChannel(getSession(), 2, getMessageStore());
- getSession().addChannel(channel);
-
- // Create queue
- setQueue(getNewQueue());
- Subscription subscription =
- SUBSCRIPTION_FACTORY.createSubscription(channel.getChannelId(), getSession(), new AMQShortString("consumer_tag"), true, null, false, channel.getCreditManager());
-
- getQueue().registerSubscription(
- subscription, false);
-
- _queueMBean = (AMQQueueMBean) getQueue().getManagedObject();
- _queueMBean.setMaximumMessageCount(9999l); // Set a high value, because this is not being tested
- _queueMBean.setMaximumQueueDepth(MAX_QUEUE_DEPTH);
-
- // Send messages(no of message to be little more than what can cause a Queue_Depth alert)
- int messageCount = Math.round(MAX_QUEUE_DEPTH / MAX_MESSAGE_SIZE) + 10;
- long totalSize = (messageCount * MAX_MESSAGE_SIZE);
- sendMessages(channel, messageCount, MAX_MESSAGE_SIZE);
-
- // Check queueDepth. There should be no messages on the queue and as the subscriber is listening
- // so there should be no Queue_Deoth alert raised
- assertEquals(new Long(totalSize), new Long(_queueMBean.getQueueDepth()));
- Notification lastNotification = _queueMBean.getLastNotification();
-// assertNull(lastNotification);
-
- // Kill the subscriber and check for the queue depth values.
- // Messages are unacknowledged, so those should get requeued. All messages should be on the Queue
- getQueue().unregisterSubscription(subscription);
- channel.requeue();
-
- assertEquals(new Long(totalSize), new Long(_queueMBean.getQueueDepth()));
-
- lastNotification = _queueMBean.getLastNotification();
- assertNotNull(lastNotification);
- String notificationMsg = lastNotification.getMessage();
- assertTrue(notificationMsg.startsWith(NotificationCheck.QUEUE_DEPTH_ALERT.name()));
-
- // Connect a consumer again and check QueueDepth values. The queue should get emptied.
- // Messages will get delivered but still are unacknowledged.
- Subscription subscription2 =
- SUBSCRIPTION_FACTORY.createSubscription(channel.getChannelId(), getSession(), new AMQShortString("consumer_tag"), true, null, false, channel.getCreditManager());
-
- getQueue().registerSubscription(
- subscription2, false);
-
- while (getQueue().getUndeliveredMessageCount()!= 0)
- {
- Thread.sleep(100);
- }
-// assertEquals(new Long(0), new Long(_queueMBean.getQueueDepth()));
-
- // Kill the subscriber again. Now those messages should get requeued again. Check if the queue depth
- // value is correct.
- getQueue().unregisterSubscription(subscription2);
- channel.requeue();
-
- assertEquals(new Long(totalSize), new Long(_queueMBean.getQueueDepth()));
- getSession().closeSession();
-
- // Check the clear queue
- _queueMBean.clearQueue();
- assertEquals(new Long(0), new Long(_queueMBean.getQueueDepth()));
- }
-
- protected IncomingMessage message(final boolean immediate, long size) throws AMQException
- {
- MessagePublishInfo publish = new MessagePublishInfo()
- {
-
- public AMQShortString getExchange()
- {
- return null;
- }
-
- public void setExchange(AMQShortString exchange)
- {
- //To change body of implemented methods use File | Settings | File Templates.
- }
-
- public boolean isImmediate()
- {
- return immediate;
- }
-
- public boolean isMandatory()
- {
- return false;
- }
-
- public AMQShortString getRoutingKey()
- {
- return null;
- }
- };
-
- ContentHeaderBody contentHeaderBody = new ContentHeaderBody();
- BasicContentHeaderProperties props = new BasicContentHeaderProperties();
- contentHeaderBody.setProperties(props);
- contentHeaderBody.setBodySize(size); // in bytes
- IncomingMessage message = new IncomingMessage(publish);
- message.setContentHeaderBody(contentHeaderBody);
-
- return message;
- }
-
- @Override
- protected void configure()
- {
- // Increase Alert Check period
- getConfiguration().setHousekeepingCheckPeriod(200);
- }
-
- private void sendMessages(AMQChannel channel, long messageCount, final long size) throws AMQException
- {
- IncomingMessage[] messages = new IncomingMessage[(int) messageCount];
- MessageMetaData[] metaData = new MessageMetaData[(int) messageCount];
- for (int i = 0; i < messages.length; i++)
- {
- messages[i] = message(false, size);
- ArrayList<AMQQueue> qs = new ArrayList<AMQQueue>();
- qs.add(getQueue());
- metaData[i] = messages[i].headersReceived(System.currentTimeMillis());
- messages[i].setStoredMessage(getMessageStore().addMessage(metaData[i]));
-
- messages[i].enqueue(qs);
-
- }
-
- for (int i = 0; i < messageCount; i++)
- {
- ContentChunk contentChunk = new ContentChunk()
- {
- private byte[] _data = new byte[(int)size];
-
- public int getSize()
- {
- return (int) size;
- }
-
- public byte[] getData()
- {
- return _data;
- }
-
- public void reduceToFit()
- {
- }
- };
-
- messages[i].addContentBodyFrame(contentChunk);
- messages[i].getStoredMessage().addContent(0, ByteBuffer.wrap(contentChunk.getData()));
-
- getQueue().enqueue(new AMQMessage(messages[i].getStoredMessage()));
- }
- }
-
- private AMQQueue getNewQueue() throws AMQException
- {
- return AMQQueueFactory.createAMQQueueImpl(new AMQShortString("testQueue" + Math.random()),
- false,
- new AMQShortString("AMQueueAlertTest"),
- false,
- false, getVirtualHost(), null);
- }
-}
diff --git a/java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueFactoryTest.java b/java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueFactoryTest.java
index e123a968a4..186be4dff7 100644
--- a/java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueFactoryTest.java
+++ b/java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueFactoryTest.java
@@ -20,8 +20,6 @@
*/
package org.apache.qpid.server.queue;
-import java.util.UUID;
-
import org.apache.commons.configuration.XMLConfiguration;
import org.apache.qpid.AMQException;
@@ -35,9 +33,9 @@ import org.apache.qpid.server.exchange.ExchangeRegistry;
import org.apache.qpid.server.logging.SystemOutMessageLogger;
import org.apache.qpid.server.logging.actors.CurrentActor;
import org.apache.qpid.server.logging.actors.TestLogActor;
+import org.apache.qpid.server.model.UUIDGenerator;
import org.apache.qpid.server.registry.ApplicationRegistry;
import org.apache.qpid.server.store.TestableMemoryMessageStore;
-import org.apache.qpid.server.store.TestableMemoryMessageStoreFactory;
import org.apache.qpid.server.util.TestApplicationRegistry;
import org.apache.qpid.server.virtualhost.VirtualHost;
import org.apache.qpid.test.utils.QpidTestCase;
@@ -56,7 +54,7 @@ public class AMQQueueFactoryTest extends QpidTestCase
XMLConfiguration configXml = new XMLConfiguration();
configXml.addProperty("virtualhosts.virtualhost(-1).name", getName());
- configXml.addProperty("virtualhosts.virtualhost(-1)."+getName()+".store.factoryclass", TestableMemoryMessageStoreFactory.class.getName());
+ configXml.addProperty("virtualhosts.virtualhost(-1)."+getName()+".store.class", TestableMemoryMessageStore.class.getName());
ServerConfiguration configuration = new ServerConfiguration(configXml);
@@ -100,8 +98,8 @@ public class AMQQueueFactoryTest extends QpidTestCase
fieldTable.put(new AMQShortString(AMQQueueFactory.X_QPID_PRIORITIES), 5);
- AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(new AMQShortString("testPriorityQueue"), false, new AMQShortString("owner"), false,
- false, _virtualHost, fieldTable);
+ AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), "testPriorityQueue", false, "owner", false,
+ false, _virtualHost, FieldTable.convertToMap(fieldTable));
assertEquals("Queue not a priorty queue", AMQPriorityQueue.class, queue.getClass());
verifyQueueRegistered("testPriorityQueue");
@@ -111,13 +109,13 @@ public class AMQQueueFactoryTest extends QpidTestCase
public void testSimpleQueueRegistration() throws Exception
{
- AMQShortString queueName = new AMQShortString("testSimpleQueueRegistration");
+ String queueName = getName();
AMQShortString dlQueueName = new AMQShortString(queueName + AMQQueueFactory.DEFAULT_DLQ_NAME_SUFFIX);
- AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(queueName, false, new AMQShortString("owner"), false,
+ AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), queueName, false, "owner", false,
false, _virtualHost, null);
assertEquals("Queue not a simple queue", SimpleAMQQueue.class, queue.getClass());
- verifyQueueRegistered("testSimpleQueueRegistration");
+ verifyQueueRegistered(queueName);
//verify that no alternate exchange or DLQ were produced
QueueRegistry qReg = _virtualHost.getQueueRegistry();
@@ -138,7 +136,7 @@ public class AMQQueueFactoryTest extends QpidTestCase
FieldTable fieldTable = new FieldTable();
fieldTable.setBoolean(AMQQueueFactory.X_QPID_DLQ_ENABLED, true);
- AMQShortString queueName = new AMQShortString("testDeadLetterQueueEnabled");
+ String queueName = "testDeadLetterQueueEnabled";
AMQShortString dlExchangeName = new AMQShortString(queueName + DefaultExchangeFactory.DEFAULT_DLE_NAME_SUFFIX);
AMQShortString dlQueueName = new AMQShortString(queueName + AMQQueueFactory.DEFAULT_DLQ_NAME_SUFFIX);
@@ -148,8 +146,8 @@ public class AMQQueueFactoryTest extends QpidTestCase
assertNull("The DLQ should not yet exist", qReg.getQueue(dlQueueName));
assertNull("The alternate exchange should not yet exist", exReg.getExchange(dlExchangeName));
- AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(queueName, false, new AMQShortString("owner"), false, false,
- _virtualHost, fieldTable);
+ AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), queueName, false, "owner", false, false,
+ _virtualHost, FieldTable.convertToMap(fieldTable));
Exchange altExchange = queue.getAlternateExchange();
assertNotNull("Queue should have an alternate exchange as DLQ is enabled", altExchange);
@@ -179,7 +177,7 @@ public class AMQQueueFactoryTest extends QpidTestCase
ApplicationRegistry.getInstance().getConfiguration().getConfig().addProperty("deadLetterQueues","true");
ApplicationRegistry.getInstance().getConfiguration().getConfig().addProperty("maximumDeliveryCount","5");
- AMQShortString queueName = new AMQShortString("testDeadLetterQueueEnabled");
+ String queueName = "testDeadLetterQueueEnabled";
AMQShortString dlExchangeName = new AMQShortString(queueName + DefaultExchangeFactory.DEFAULT_DLE_NAME_SUFFIX);
AMQShortString dlQueueName = new AMQShortString(queueName + AMQQueueFactory.DEFAULT_DLQ_NAME_SUFFIX);
@@ -189,7 +187,7 @@ public class AMQQueueFactoryTest extends QpidTestCase
assertNull("The DLQ should not yet exist", qReg.getQueue(dlQueueName));
assertNull("The alternate exchange should not yet exist", exReg.getExchange(dlExchangeName));
- AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(queueName, false, new AMQShortString("owner"), false, false,
+ AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), queueName, false, "owner", false, false,
_virtualHost, null);
assertEquals("Unexpected maximum delivery count", 5, queue.getMaximumDeliveryCount());
@@ -221,7 +219,7 @@ public class AMQQueueFactoryTest extends QpidTestCase
FieldTable fieldTable = new FieldTable();
fieldTable.setBoolean(AMQQueueFactory.X_QPID_DLQ_ENABLED, false);
- AMQShortString queueName = new AMQShortString("testDeadLetterQueueDisabled");
+ String queueName = "testDeadLetterQueueDisabled";
AMQShortString dlExchangeName = new AMQShortString(queueName + DefaultExchangeFactory.DEFAULT_DLE_NAME_SUFFIX);
AMQShortString dlQueueName = new AMQShortString(queueName + AMQQueueFactory.DEFAULT_DLQ_NAME_SUFFIX);
@@ -231,8 +229,8 @@ public class AMQQueueFactoryTest extends QpidTestCase
assertNull("The DLQ should not yet exist", qReg.getQueue(dlQueueName));
assertNull("The alternate exchange should not exist", exReg.getExchange(dlExchangeName));
- AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(queueName, false, new AMQShortString("owner"), false, false,
- _virtualHost, fieldTable);
+ AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), queueName, false, "owner", false, false,
+ _virtualHost, FieldTable.convertToMap(fieldTable));
assertNull("Queue should not have an alternate exchange as DLQ is disabled", queue.getAlternateExchange());
assertNull("The alternate exchange should still not exist", exReg.getExchange(dlExchangeName));
@@ -254,7 +252,7 @@ public class AMQQueueFactoryTest extends QpidTestCase
FieldTable fieldTable = new FieldTable();
fieldTable.setBoolean(AMQQueueFactory.X_QPID_DLQ_ENABLED, true);
- AMQShortString queueName = new AMQShortString("testDeadLetterQueueNotCreatedForAutodeleteQueues");
+ String queueName = "testDeadLetterQueueNotCreatedForAutodeleteQueues";
AMQShortString dlExchangeName = new AMQShortString(queueName + DefaultExchangeFactory.DEFAULT_DLE_NAME_SUFFIX);
AMQShortString dlQueueName = new AMQShortString(queueName + AMQQueueFactory.DEFAULT_DLQ_NAME_SUFFIX);
@@ -265,8 +263,8 @@ public class AMQQueueFactoryTest extends QpidTestCase
assertNull("The alternate exchange should not exist", exReg.getExchange(dlExchangeName));
//create an autodelete queue
- AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(queueName, false, new AMQShortString("owner"), true, false,
- _virtualHost, fieldTable);
+ AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), queueName, false, "owner", true, false,
+ _virtualHost, FieldTable.convertToMap(fieldTable));
assertTrue("Queue should be autodelete", queue.isAutoDelete());
//ensure that the autodelete property overrides the request to enable DLQ
@@ -287,10 +285,8 @@ public class AMQQueueFactoryTest extends QpidTestCase
final FieldTable fieldTable = new FieldTable();
fieldTable.setInteger(AMQQueueFactory.X_QPID_MAXIMUM_DELIVERY_COUNT, 5);
- final AMQShortString queueName = new AMQShortString("testMaximumDeliveryCount");
-
- final AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(queueName, false, new AMQShortString("owner"), false, false,
- _virtualHost, fieldTable);
+ final AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), "testMaximumDeliveryCount", false, "owner", false, false,
+ _virtualHost, FieldTable.convertToMap(fieldTable));
assertNotNull("The queue was not registered as expected ", queue);
assertEquals("Maximum delivery count not as expected", 5, queue.getMaximumDeliveryCount());
@@ -304,10 +300,7 @@ public class AMQQueueFactoryTest extends QpidTestCase
*/
public void testMaximumDeliveryCountDefault() throws Exception
{
-
- final AMQShortString queueName = new AMQShortString("testMaximumDeliveryCount");
-
- final AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(queueName, false, new AMQShortString("owner"), false, false,
+ final AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), "testMaximumDeliveryCount", false, "owner", false, false,
_virtualHost, null);
assertNotNull("The queue was not registered as expected ", queue);
@@ -323,7 +316,7 @@ public class AMQQueueFactoryTest extends QpidTestCase
{
try
{
- AMQQueueFactory.createAMQQueueImpl(null, false, new AMQShortString("owner"), true, false, _virtualHost, null);
+ AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), null, false, "owner", true, false, _virtualHost, null);
fail("queue with null name can not be created!");
}
catch (Exception e)
@@ -350,8 +343,8 @@ public class AMQQueueFactoryTest extends QpidTestCase
FieldTable fieldTable = new FieldTable();
fieldTable.setBoolean(AMQQueueFactory.X_QPID_DLQ_ENABLED, true);
- AMQQueueFactory.createAMQQueueImpl(new AMQShortString(queueName), false, new AMQShortString("owner"),
- false, false, _virtualHost, fieldTable);
+ AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), queueName, false, "owner",
+ false, false, _virtualHost, FieldTable.convertToMap(fieldTable));
fail("queue with DLQ name having more than 255 characters can not be created!");
}
catch (Exception e)
@@ -386,8 +379,8 @@ public class AMQQueueFactoryTest extends QpidTestCase
FieldTable fieldTable = new FieldTable();
fieldTable.setBoolean(AMQQueueFactory.X_QPID_DLQ_ENABLED, true);
- AMQQueueFactory.createAMQQueueImpl(new AMQShortString(queueName), false, new AMQShortString("owner"),
- false, false, _virtualHost, fieldTable);
+ AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), queueName, false, "owner",
+ false, false, _virtualHost, FieldTable.convertToMap(fieldTable));
fail("queue with DLE name having more than 255 characters can not be created!");
}
catch (Exception e)
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
deleted file mode 100644
index 45933e7064..0000000000
--- a/java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueMBeanTest.java
+++ /dev/null
@@ -1,553 +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.commons.lang.time.FastDateFormat;
-
-import org.apache.qpid.AMQException;
-import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpid.framing.BasicContentHeaderProperties;
-import org.apache.qpid.framing.ContentBody;
-import org.apache.qpid.framing.ContentHeaderBody;
-import org.apache.qpid.framing.abstraction.ContentChunk;
-import org.apache.qpid.framing.abstraction.MessagePublishInfo;
-import org.apache.qpid.management.common.mbeans.ManagedQueue;
-import org.apache.qpid.server.AMQChannel;
-import org.apache.qpid.server.message.AMQMessage;
-import org.apache.qpid.server.message.MessageMetaData;
-import org.apache.qpid.server.protocol.InternalTestProtocolSession;
-import org.apache.qpid.server.registry.ApplicationRegistry;
-import org.apache.qpid.server.store.TestableMemoryMessageStore;
-import org.apache.qpid.server.subscription.Subscription;
-import org.apache.qpid.server.subscription.SubscriptionFactory;
-import org.apache.qpid.server.subscription.SubscriptionFactoryImpl;
-import org.apache.qpid.server.util.InternalBrokerBaseCase;
-
-import javax.management.JMException;
-import javax.management.openmbean.CompositeData;
-import javax.management.openmbean.CompositeDataSupport;
-import javax.management.openmbean.TabularData;
-import java.io.IOException;
-import java.nio.ByteBuffer;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-
-/**
- * Test class to test AMQQueueMBean attributes and operations
- */
-public class AMQQueueMBeanTest extends InternalBrokerBaseCase
-{
- private static long MESSAGE_SIZE = 1000;
- private AMQQueueMBean _queueMBean;
- private static final SubscriptionFactoryImpl SUBSCRIPTION_FACTORY = SubscriptionFactoryImpl.INSTANCE;
-
- public void testMessageCountTransient() throws Exception
- {
- int messageCount = 10;
- sendMessages(messageCount, false);
- assertTrue(_queueMBean.getMessageCount() == messageCount);
- assertTrue(_queueMBean.getReceivedMessageCount() == messageCount);
- long queueDepth = (messageCount * MESSAGE_SIZE);
- assertTrue(_queueMBean.getQueueDepth() == queueDepth);
-
- _queueMBean.deleteMessageFromTop();
- assertTrue(_queueMBean.getMessageCount() == (messageCount - 1));
- assertTrue(_queueMBean.getReceivedMessageCount() == messageCount);
-
- _queueMBean.clearQueue();
- assertEquals(0,(int)_queueMBean.getMessageCount());
- assertTrue(_queueMBean.getReceivedMessageCount() == messageCount);
-
- //Ensure that the data has been removed from the Store
- verifyBrokerState();
- }
-
- public void testMessageCountPersistent() throws Exception
- {
- int messageCount = 10;
- sendMessages(messageCount, true);
- assertEquals("", messageCount, _queueMBean.getMessageCount().intValue());
- assertTrue(_queueMBean.getReceivedMessageCount() == messageCount);
- long queueDepth = (messageCount * MESSAGE_SIZE);
- assertTrue(_queueMBean.getQueueDepth() == queueDepth);
-
- _queueMBean.deleteMessageFromTop();
- assertTrue(_queueMBean.getMessageCount() == (messageCount - 1));
- assertTrue(_queueMBean.getReceivedMessageCount() == messageCount);
-
- _queueMBean.clearQueue();
- assertTrue(_queueMBean.getMessageCount() == 0);
- assertTrue(_queueMBean.getReceivedMessageCount() == messageCount);
-
- //Ensure that the data has been removed from the Store
- verifyBrokerState();
- }
-
- public void testDeleteMessages() throws Exception
- {
- int messageCount = 10;
- sendMessages(messageCount, true);
- assertEquals("", messageCount, _queueMBean.getMessageCount().intValue());
- assertTrue(_queueMBean.getReceivedMessageCount() == messageCount);
- long queueDepth = (messageCount * MESSAGE_SIZE);
- assertTrue(_queueMBean.getQueueDepth() == queueDepth);
-
- //delete first message
- _queueMBean.deleteMessages(1L,1L);
- assertTrue(_queueMBean.getMessageCount() == (messageCount - 1));
- assertTrue(_queueMBean.getReceivedMessageCount() == messageCount);
- try
- {
- _queueMBean.viewMessageContent(1L);
- fail("Message should no longer be on the queue");
- }
- catch(Exception e)
- {
-
- }
-
- //delete last message, leaving 2nd to 9th
- _queueMBean.deleteMessages(10L,10L);
- assertTrue(_queueMBean.getMessageCount() == (messageCount - 2));
- assertTrue(_queueMBean.getReceivedMessageCount() == messageCount);
- try
- {
- _queueMBean.viewMessageContent(10L);
- fail("Message should no longer be on the queue");
- }
- catch(Exception e)
- {
-
- }
-
- //delete remaining messages, leaving none
- _queueMBean.deleteMessages(2L,9L);
- assertTrue(_queueMBean.getMessageCount() == (0));
- assertTrue(_queueMBean.getReceivedMessageCount() == messageCount);
-
- //Ensure that the data has been removed from the Store
- verifyBrokerState();
- }
-
-
- // todo: collect to a general testing class -duplicated from Systest/MessageReturntest
- private void verifyBrokerState()
- {
-
- TestableMemoryMessageStore store = (TestableMemoryMessageStore) getVirtualHost().getMessageStore();
-
- // Unlike MessageReturnTest there is no need for a delay as there this thread does the clean up.
-
- assertEquals("Store should have no messages:" + store.getMessageCount(), 0, store.getMessageCount());
- }
-
- public void testConsumerCount() throws AMQException
- {
-
- assertTrue(getQueue().getActiveConsumerCount() == 0);
- assertTrue(_queueMBean.getActiveConsumerCount() == 0);
-
-
- InternalTestProtocolSession protocolSession = new InternalTestProtocolSession(getVirtualHost());
-
- AMQChannel channel = new AMQChannel(protocolSession, 1, getMessageStore());
- protocolSession.addChannel(channel);
-
- Subscription subscription =
- SUBSCRIPTION_FACTORY.createSubscription(channel.getChannelId(), protocolSession, new AMQShortString("test"), false, null, false, channel.getCreditManager());
-
- getQueue().registerSubscription(subscription, false);
- assertEquals(1,(int)_queueMBean.getActiveConsumerCount());
-
-
- SubscriptionFactory subscriptionFactory = SUBSCRIPTION_FACTORY;
- Subscription s1 = subscriptionFactory.createSubscription(channel.getChannelId(),
- protocolSession,
- new AMQShortString("S1"),
- false,
- null,
- true,
- channel.getCreditManager());
-
- Subscription s2 = subscriptionFactory.createSubscription(channel.getChannelId(),
- protocolSession,
- new AMQShortString("S2"),
- false,
- null,
- true,
- channel.getCreditManager());
- getQueue().registerSubscription(s1,false);
- getQueue().registerSubscription(s2,false);
- assertTrue(_queueMBean.getActiveConsumerCount() == 3);
- assertTrue(_queueMBean.getConsumerCount() == 3);
-
- s1.close();
- assertEquals(2, (int) _queueMBean.getActiveConsumerCount());
- assertTrue(_queueMBean.getConsumerCount() == 3);
- }
-
- public void testGeneralProperties() throws Exception
- {
- long maxQueueDepth = 1000; // in bytes
- _queueMBean.setMaximumMessageCount(50000l);
- _queueMBean.setMaximumMessageSize(2000l);
- _queueMBean.setMaximumQueueDepth(maxQueueDepth);
-
- assertEquals("Max MessageCount not set",50000,_queueMBean.getMaximumMessageCount().longValue());
- assertEquals("Max MessageSize not set",2000, _queueMBean.getMaximumMessageSize().longValue());
- assertEquals("Max QueueDepth not set",maxQueueDepth, _queueMBean.getMaximumQueueDepth().longValue());
-
- assertEquals("Queue Name does not match", new AMQShortString(getName()), _queueMBean.getName());
- assertFalse("AutoDelete should not be set.",_queueMBean.isAutoDelete());
- assertFalse("Queue should not be durable.",_queueMBean.isDurable());
-
- //set+get exclusivity using the mbean, and also verify it is actually updated in the queue
- _queueMBean.setExclusive(true);
- assertTrue("Exclusive property should be true.",_queueMBean.isExclusive());
- assertTrue("Exclusive property should be true.", getQueue().isExclusive());
- _queueMBean.setExclusive(false);
- assertFalse("Exclusive property should be false.",_queueMBean.isExclusive());
- assertFalse("Exclusive property should be false.", getQueue().isExclusive());
- }
-
- /**
- * Tests view messages with two test messages. The first message is non-persistent, the second persistent
- * and has timestamp/expiration.
- *
- */
- public void testViewMessages() throws Exception
- {
- sendMessages(1, false);
- final Date msg2Timestamp = new Date();
- final Date msg2Expiration = new Date(msg2Timestamp.getTime() + 1000);
- sendMessages(1, true, msg2Timestamp.getTime(), msg2Expiration.getTime());
-
- final TabularData tab = _queueMBean.viewMessages(1l, 2l);
- assertEquals("Unexpected number of rows in table", 2, tab.size());
- final Iterator<CompositeDataSupport> rowItr = (Iterator<CompositeDataSupport>) tab.values().iterator();
-
- // Check row1
- final CompositeDataSupport row1 = rowItr.next();
- assertEquals("Message should have AMQ message id", 1l, row1.get(ManagedQueue.MSG_AMQ_ID));
- assertNotNull("Expected message header array", row1.get(ManagedQueue.MSG_HEADER));
- final Map<String, String> row1Headers = headerArrayToMap((String[])row1.get(ManagedQueue.MSG_HEADER));
- assertEquals("Unexpected JMSPriority within header", "Non_Persistent", row1Headers.get("JMSDeliveryMode"));
- assertEquals("Unexpected JMSTimestamp within header", "null", row1Headers.get("JMSTimestamp"));
- assertEquals("Unexpected JMSExpiration within header", "null", row1Headers.get("JMSExpiration"));
-
- final CompositeDataSupport row2 = rowItr.next();
- assertEquals("Message should have AMQ message id", 2l, row2.get(ManagedQueue.MSG_AMQ_ID));
- assertNotNull("Expected message header array", row2.get(ManagedQueue.MSG_HEADER));
- final Map<String, String> row2Headers = headerArrayToMap((String[])row2.get(ManagedQueue.MSG_HEADER));
- assertEquals("Unexpected JMSPriority within header", "Persistent", row2Headers.get("JMSDeliveryMode"));
- assertEquals("Unexpected JMSTimestamp within header", FastDateFormat.getInstance(AMQQueueMBean.JMSTIMESTAMP_DATETIME_FORMAT).format(msg2Timestamp),
- row2Headers.get("JMSTimestamp"));
- assertEquals("Unexpected JMSExpiration within header", FastDateFormat.getInstance(AMQQueueMBean.JMSTIMESTAMP_DATETIME_FORMAT).format(msg2Expiration),
- row2Headers.get("JMSExpiration"));
- }
-
- public void testViewMessageWithIllegalStartEndRanges() throws Exception
- {
- try
- {
- _queueMBean.viewMessages(0L, 3L);
- fail();
- }
- catch (JMException ex)
- {
- // PASS
- }
-
- try
- {
- _queueMBean.viewMessages(2L, 1L);
- fail();
- }
- catch (JMException ex)
- {
- // PASS
- }
-
- try
- {
- _queueMBean.viewMessages(-1L, 1L);
- fail();
- }
- catch (JMException ex)
- {
- // PASS
- }
-
- try
- {
- long end = Integer.MAX_VALUE;
- end+=2;
- _queueMBean.viewMessages(1L, end);
- fail("Expected Exception due to oversized(> 2^31) message range");
- }
- catch (JMException ex)
- {
- // PASS
- }
- }
-
- public void testViewMessageContent() throws Exception
- {
- final List<AMQMessage> sentMessages = sendMessages(1, true);
- final Long id = sentMessages.get(0).getMessageId();
-
- final CompositeData messageData = _queueMBean.viewMessageContent(id);
- assertNotNull(messageData);
- }
-
- public void testViewMessageContentWithUnknownMessageId() throws Exception
- {
- final List<AMQMessage> sentMessages = sendMessages(1, true);
- final Long id = sentMessages.get(0).getMessageId();
-
- try
- {
- _queueMBean.viewMessageContent(id + 1);
- fail();
- }
- catch (JMException ex)
- {
- // PASS
- }
- }
-
- public void testFlowControlProperties() throws Exception
- {
- assertTrue(_queueMBean.getCapacity() == 0);
- assertTrue(_queueMBean.getFlowResumeCapacity() == 0);
- assertFalse(_queueMBean.isFlowOverfull());
-
- //capacity currently 0, try setting FlowResumeCapacity above this
- try
- {
- _queueMBean.setFlowResumeCapacity(1L);
- fail("Should have failed to allow setting FlowResumeCapacity above Capacity");
- }
- catch (IllegalArgumentException ex)
- {
- //expected exception
- assertTrue(_queueMBean.getFlowResumeCapacity() == 0);
- }
-
- //add a message to the queue
- sendMessages(1, true);
-
- //(FlowResume)Capacity currently 0, set both to 2
- _queueMBean.setCapacity(2L);
- assertTrue(_queueMBean.getCapacity() == 2L);
- _queueMBean.setFlowResumeCapacity(2L);
- assertTrue(_queueMBean.getFlowResumeCapacity() == 2L);
-
- //Try setting Capacity below FlowResumeCapacity
- try
- {
- _queueMBean.setCapacity(1L);
- fail("Should have failed to allow setting Capacity below FlowResumeCapacity");
- }
- catch (IllegalArgumentException ex)
- {
- //expected exception
- assertTrue(_queueMBean.getCapacity() == 2);
- }
-
- //create a channel and use it to exercise the capacity check mechanism
- AMQChannel channel = new AMQChannel(getSession(), 1, getMessageStore());
- getQueue().checkCapacity(channel);
-
- assertTrue(_queueMBean.isFlowOverfull());
- assertTrue(channel.getBlocking());
-
- //set FlowResumeCapacity to MESSAGE_SIZE and check queue is now underfull and channel unblocked
- _queueMBean.setCapacity(MESSAGE_SIZE);//must increase capacity too
- _queueMBean.setFlowResumeCapacity(MESSAGE_SIZE);
-
- assertFalse(_queueMBean.isFlowOverfull());
- assertFalse(channel.getBlocking());
- }
-
- public void testMaximumDeliveryCount() throws IOException
- {
- assertEquals("Unexpected default maximum delivery count", Integer.valueOf(0), _queueMBean.getMaximumDeliveryCount());
- }
-
- public void testViewAllMessages() throws Exception
- {
- final int messageCount = 5;
- sendPersistentMessages(messageCount);
-
-
- final TabularData messageTable = _queueMBean.viewMessages(1L, 5L);
- assertNotNull("Message table should not be null", messageTable);
- assertEquals("Unexpected number of rows", messageCount, messageTable.size());
-
-
- final Iterator rowIterator = messageTable.values().iterator();
- // Get its message ID
- final CompositeDataSupport row1 = (CompositeDataSupport) rowIterator.next();
- final Long msgId = (Long) row1.get("AMQ MessageId");
- final Long queuePosition = (Long) row1.get("Queue Position");
- final Integer deliveryCount = (Integer) row1.get("Delivery Count");
-
- assertNotNull("Row should have value for queue position", queuePosition);
- assertNotNull("Row should have value for msgid", msgId);
- assertNotNull("Row should have value for deliveryCount", deliveryCount);
- }
-
-
- @Override
- public void setUp() throws Exception
- {
- super.setUp();
-
- _queueMBean = new AMQQueueMBean(getQueue());
- }
-
- public void tearDown()
- {
- ApplicationRegistry.remove();
- }
-
- private void sendPersistentMessages(int messageCount) throws AMQException
- {
- sendMessages(messageCount, true);
- assertEquals("Expected " + messageCount + " messages in the queue", messageCount, _queueMBean
- .getMessageCount().intValue());
- }
-
- private List<AMQMessage> sendMessages(int messageCount, boolean persistent) throws AMQException
- {
- return sendMessages(messageCount, persistent, 0l, 0l);
- }
-
- private List<AMQMessage> sendMessages(int messageCount, boolean persistent, long timestamp, long expiration) throws AMQException
- {
- final List<AMQMessage> sentMessages = new ArrayList<AMQMessage>();
-
- for (int i = 0; i < messageCount; i++)
- {
- IncomingMessage currentMessage = createIncomingMessage(false, persistent, timestamp, expiration);
- ArrayList<AMQQueue> qs = new ArrayList<AMQQueue>();
- qs.add(getQueue());
- currentMessage.enqueue(qs);
-
- // route header
- MessageMetaData mmd = currentMessage.headersReceived(System.currentTimeMillis());
-
- // Add the message to the store so we have something to test later
- currentMessage.setStoredMessage(getMessageStore().addMessage(mmd));
- ContentChunk chunk = getSession().getMethodRegistry()
- .getProtocolVersionMethodConverter()
- .convertToContentChunk(
- new ContentBody(new byte[(int) MESSAGE_SIZE]));
- currentMessage.addContentBodyFrame(chunk);
- currentMessage.getStoredMessage().addContent(0, ByteBuffer.wrap(chunk.getData()));
-
- AMQMessage m = new AMQMessage(currentMessage.getStoredMessage());
- for(BaseQueue q : currentMessage.getDestinationQueues())
- {
- q.enqueue(m);
- }
-
- sentMessages.add(m);
- }
-
- return sentMessages;
- }
-
- private IncomingMessage createIncomingMessage(final boolean immediate, boolean persistent, long timestamp, long expiration) throws AMQException
- {
- MessagePublishInfo publish = new MessagePublishInfo()
- {
-
- public AMQShortString getExchange()
- {
- return null;
- }
-
- public void setExchange(AMQShortString exchange)
- {
- }
-
- public boolean isImmediate()
- {
- return immediate;
- }
-
- public boolean isMandatory()
- {
- return false;
- }
-
- public AMQShortString getRoutingKey()
- {
- return null;
- }
- };
-
- ContentHeaderBody contentHeaderBody = new ContentHeaderBody();
- contentHeaderBody.setBodySize(MESSAGE_SIZE); // in bytes
- final BasicContentHeaderProperties props = new BasicContentHeaderProperties();
- contentHeaderBody.setProperties(props);
- props.setDeliveryMode((byte) (persistent ? 2 : 1));
- if (timestamp > 0)
- {
- props.setTimestamp(timestamp);
- }
- if (expiration > 0)
- {
- props.setExpiration(expiration);
- }
- IncomingMessage msg = new IncomingMessage(publish);
- msg.setContentHeaderBody(contentHeaderBody);
- return msg;
- }
-
- /**
- *
- * Utility method to convert array of Strings in the form x = y into a
- * map with key/value x =&gt; y.
- *
- */
- private Map<String,String> headerArrayToMap(final String[] headerArray)
- {
- final Map<String, String> headerMap = new HashMap<String, String>();
- final List<String> headerList = Arrays.asList(headerArray);
- for (Iterator<String> iterator = headerList.iterator(); iterator.hasNext();)
- {
- final String nameValuePair = iterator.next();
- final String[] nameValue = nameValuePair.split(" *= *", 2);
- headerMap.put(nameValue[0], nameValue[1]);
- }
- return headerMap;
- }
-
-
-}
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 409b9fd92e..190d5c777b 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
@@ -32,6 +32,7 @@ import org.apache.qpid.server.flow.LimitlessCreditManager;
import org.apache.qpid.server.flow.Pre0_10CreditManager;
import org.apache.qpid.server.message.AMQMessage;
import org.apache.qpid.server.message.MessageMetaData;
+import org.apache.qpid.server.model.UUIDGenerator;
import org.apache.qpid.server.protocol.AMQProtocolSession;
import org.apache.qpid.server.protocol.InternalTestProtocolSession;
import org.apache.qpid.server.registry.ApplicationRegistry;
@@ -76,7 +77,7 @@ public class AckTest extends InternalBrokerBaseCase
_protocolSession.addChannel(_channel);
- _queue = AMQQueueFactory.createAMQQueueImpl(new AMQShortString("myQ"), false, new AMQShortString("guest"), true, false,
+ _queue = AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), "myQ", false, "guest", true, false,
_virtualHost, null);
}
diff --git a/java/broker/src/test/java/org/apache/qpid/server/queue/ConflationQueueListTest.java b/java/broker/src/test/java/org/apache/qpid/server/queue/ConflationQueueListTest.java
new file mode 100644
index 0000000000..a94548f1c3
--- /dev/null
+++ b/java/broker/src/test/java/org/apache/qpid/server/queue/ConflationQueueListTest.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.server.queue;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+import junit.framework.TestCase;
+
+import org.apache.qpid.server.message.AMQMessage;
+import org.apache.qpid.server.message.AMQMessageHeader;
+import org.apache.qpid.server.message.AMQMessageReference;
+import org.apache.qpid.server.message.MessageMetaData;
+import org.apache.qpid.server.message.ServerMessage;
+import org.apache.qpid.server.virtualhost.VirtualHost;
+
+public class ConflationQueueListTest extends TestCase
+{
+ private static final String CONFLATION_KEY = "CONFLATION_KEY";
+
+ private static final String TEST_KEY_VALUE = "testKeyValue";
+ private static final String TEST_KEY_VALUE1 = "testKeyValue1";
+ private static final String TEST_KEY_VALUE2 = "testKeyValue2";
+
+ private ConflationQueueList _list;
+ private AMQQueue _queue = createTestQueue();
+
+ @Override
+ protected void setUp() throws Exception
+ {
+ super.setUp();
+ _list = new ConflationQueueList(_queue, CONFLATION_KEY);
+ }
+
+ public void testListHasNoEntries()
+ {
+ int numberOfEntries = countEntries(_list);
+ assertEquals(0, numberOfEntries);
+ }
+
+ public void testAddMessageWithoutConflationKeyValue()
+ {
+ ServerMessage<MessageMetaData> message = createTestServerMessage(null);
+
+ _list.add(message);
+ int numberOfEntries = countEntries(_list);
+ assertEquals(1, numberOfEntries);
+ }
+
+ public void testAddAndDiscardMessageWithoutConflationKeyValue()
+ {
+ ServerMessage<MessageMetaData> message = createTestServerMessage(null);
+
+ QueueEntry addedEntry = _list.add(message);
+ addedEntry.discard();
+
+ int numberOfEntries = countEntries(_list);
+ assertEquals(0, numberOfEntries);
+ }
+
+ public void testAddMessageWithConflationKeyValue()
+ {
+ ServerMessage<MessageMetaData> message = createTestServerMessage(TEST_KEY_VALUE);
+
+ _list.add(message);
+ int numberOfEntries = countEntries(_list);
+ assertEquals(1, numberOfEntries);
+ }
+
+ public void testAddAndRemoveMessageWithConflationKeyValue()
+ {
+ ServerMessage<MessageMetaData> message = createTestServerMessage(TEST_KEY_VALUE);
+
+ QueueEntry addedEntry = _list.add(message);
+ addedEntry.discard();
+
+ int numberOfEntries = countEntries(_list);
+ assertEquals(0, numberOfEntries);
+ }
+
+ public void testAddTwoMessagesWithDifferentConflationKeyValue()
+ {
+ ServerMessage<MessageMetaData> message1 = createTestServerMessage(TEST_KEY_VALUE1);
+ ServerMessage<MessageMetaData> message2 = createTestServerMessage(TEST_KEY_VALUE2);
+
+ _list.add(message1);
+ _list.add(message2);
+
+ int numberOfEntries = countEntries(_list);
+ assertEquals(2, numberOfEntries);
+ }
+
+ public void testAddTwoMessagesWithSameConflationKeyValue()
+ {
+ ServerMessage<MessageMetaData> message1 = createTestServerMessage(TEST_KEY_VALUE);
+ ServerMessage<MessageMetaData> message2 = createTestServerMessage(TEST_KEY_VALUE);
+
+ _list.add(message1);
+ _list.add(message2);
+
+ int numberOfEntries = countEntries(_list);
+ assertEquals(1, numberOfEntries);
+ }
+
+ public void testSupersededEntryIsDiscardedOnRelease()
+ {
+ ServerMessage<MessageMetaData> message1 = createTestServerMessage(TEST_KEY_VALUE);
+ ServerMessage<MessageMetaData> message2 = createTestServerMessage(TEST_KEY_VALUE);
+
+ QueueEntry entry1 = _list.add(message1);
+ entry1.acquire(); // simulate an in-progress delivery to consumer
+
+ _list.add(message2);
+ assertFalse(entry1.isDeleted());
+
+ assertEquals(2, countEntries(_list));
+
+ entry1.release(); // simulate consumer rollback/recover
+
+ assertEquals(1, countEntries(_list));
+ assertTrue(entry1.isDeleted());
+ }
+
+ public void testConflationMapMaintained()
+ {
+ assertEquals(0, _list.getLatestValuesMap().size());
+
+ ServerMessage<MessageMetaData> message = createTestServerMessage(TEST_KEY_VALUE);
+
+ QueueEntry addedEntry = _list.add(message);
+
+ assertEquals(1, countEntries(_list));
+ assertEquals(1, _list.getLatestValuesMap().size());
+
+ addedEntry.discard();
+
+ assertEquals(0, countEntries(_list));
+ assertEquals(0, _list.getLatestValuesMap().size());
+ }
+
+ public void testConflationMapMaintainedWithDifferentConflationKeyValue()
+ {
+
+ assertEquals(0, _list.getLatestValuesMap().size());
+
+ ServerMessage<MessageMetaData> message1 = createTestServerMessage(TEST_KEY_VALUE1);
+ ServerMessage<MessageMetaData> message2 = createTestServerMessage(TEST_KEY_VALUE2);
+
+ QueueEntry addedEntry1 = _list.add(message1);
+ QueueEntry addedEntry2 = _list.add(message2);
+
+ assertEquals(2, countEntries(_list));
+ assertEquals(2, _list.getLatestValuesMap().size());
+
+ addedEntry1.discard();
+ addedEntry2.discard();
+
+ assertEquals(0, countEntries(_list));
+ assertEquals(0, _list.getLatestValuesMap().size());
+ }
+
+ private int countEntries(ConflationQueueList list)
+ {
+ QueueEntryIterator<SimpleQueueEntryImpl> iterator = list.iterator();
+ int count = 0;
+ while(iterator.advance())
+ {
+ count++;
+ }
+ return count;
+ }
+
+ private ServerMessage<MessageMetaData> createTestServerMessage(String conflationKeyValue)
+ {
+ AMQMessage mockMessage = mock(AMQMessage.class);
+
+ AMQMessageHeader messageHeader = mock(AMQMessageHeader.class);
+ when(messageHeader.getHeader(CONFLATION_KEY)).thenReturn(conflationKeyValue);
+ when(mockMessage.getMessageHeader()).thenReturn(messageHeader);
+
+ AMQMessageReference messageReference = new AMQMessageReference(mockMessage);
+ when(mockMessage.newReference()).thenReturn(messageReference);
+
+ return mockMessage;
+ }
+
+ private AMQQueue createTestQueue()
+ {
+ AMQQueue queue = mock(AMQQueue.class);
+ VirtualHost virtualHost = mock(VirtualHost.class);
+ when(queue.getVirtualHost()).thenReturn(virtualHost);
+
+ return queue;
+ }
+}
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 afaa417415..bcb8d54636 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,13 +29,14 @@ import org.apache.qpid.server.configuration.QueueConfigType;
import org.apache.qpid.server.configuration.plugins.ConfigurationPlugin;
import org.apache.qpid.server.exchange.Exchange;
import org.apache.qpid.server.logging.LogSubject;
-import org.apache.qpid.server.management.ManagedObject;
import org.apache.qpid.server.message.ServerMessage;
import org.apache.qpid.server.protocol.AMQSessionModel;
import org.apache.qpid.server.security.AuthorizationHolder;
import org.apache.qpid.server.subscription.Subscription;
import org.apache.qpid.server.virtualhost.VirtualHost;
+import java.util.Collection;
+import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -51,7 +52,6 @@ public class MockAMQQueue implements AMQQueue
private AuthorizationHolder _authorizationHolder;
private AMQSessionModel _exclusiveOwner;
- private AMQShortString _owner;
private List<Binding> _bindings = new CopyOnWriteArrayList<Binding>();
private boolean _autoDelete;
@@ -98,7 +98,12 @@ public class MockAMQQueue implements AMQQueue
return "[MockAMQQueue]";
}
- };
+ };
+ }
+
+ public long getUnackedMessageBytes()
+ {
+ return 0;
}
public ConfigStore getConfigStore()
@@ -121,6 +126,16 @@ public class MockAMQQueue implements AMQQueue
return 0;
}
+ public long getTotalDequeueCount()
+ {
+ return 0;
+ }
+
+ public long getTotalEnqueueCount()
+ {
+ return 0;
+ }
+
public int getBindingCountHigh()
{
return 0;
@@ -171,6 +186,12 @@ public class MockAMQQueue implements AMQQueue
return null;
}
+ @Override
+ public UUID getQMFId()
+ {
+ return null;
+ }
+
public QueueConfigType getConfigType()
{
return null;
@@ -219,12 +240,27 @@ public class MockAMQQueue implements AMQQueue
public void registerSubscription(Subscription subscription, boolean exclusive) throws AMQException
{
-
+
}
public void unregisterSubscription(Subscription subscription) throws AMQException
{
-
+
+ }
+
+ public Collection<Subscription> getConsumers()
+ {
+ return Collections.emptyList();
+ }
+
+ public void addSubscriptionRegistrationListener(final SubscriptionRegistrationListener listener)
+ {
+
+ }
+
+ public void removeSubscriptionRegistrationListener(final SubscriptionRegistrationListener listener)
+ {
+
}
public int getConsumerCount()
@@ -283,7 +319,7 @@ public class MockAMQQueue implements AMQQueue
}
public int delete() throws AMQException
- {
+ {
_deleted = true;
return getMessageCount();
}
@@ -356,21 +392,6 @@ public class MockAMQQueue implements AMQQueue
return null;
}
- public void moveMessagesToAnotherQueue(long fromMessageId, long toMessageId, String queueName)
- {
-
- }
-
- public void copyMessagesToAnotherQueue(long fromMessageId, long toMessageId, String queueName)
- {
-
- }
-
- public void removeMessagesFromQueue(long fromMessageId, long toMessageId)
- {
-
- }
-
public long getMaximumMessageSize()
{
return 0;
@@ -378,7 +399,7 @@ public class MockAMQQueue implements AMQQueue
public void setMaximumMessageSize(long value)
{
-
+
}
public long getMaximumMessageCount()
@@ -388,7 +409,7 @@ public class MockAMQQueue implements AMQQueue
public void setMaximumMessageCount(long value)
{
-
+
}
public long getMaximumQueueDepth()
@@ -398,7 +419,7 @@ public class MockAMQQueue implements AMQQueue
public void setMaximumQueueDepth(long value)
{
-
+
}
public long getMaximumMessageAge()
@@ -408,7 +429,7 @@ public class MockAMQQueue implements AMQQueue
public void setMaximumMessageAge(long maximumMessageAge)
{
-
+
}
public long getMinimumAlertRepeatGap()
@@ -418,7 +439,7 @@ public class MockAMQQueue implements AMQQueue
public void deleteMessageFromTop()
{
-
+
}
public long clearQueue()
@@ -429,7 +450,7 @@ public class MockAMQQueue implements AMQQueue
public void checkMessageStatus() throws AMQException
{
-
+
}
public Set<NotificationCheck> getNotificationChecks()
@@ -439,22 +460,22 @@ public class MockAMQQueue implements AMQQueue
public void flushSubscription(Subscription sub) throws AMQException
{
-
+
}
public void deliverAsync(Subscription sub)
{
-
+
}
public void deliverAsync()
{
-
+
}
public void stop()
{
-
+
}
public boolean isExclusive()
@@ -469,7 +490,7 @@ public class MockAMQQueue implements AMQQueue
public void setAlternateExchange(Exchange exchange)
{
-
+
}
public Map<String, Object> getArguments()
@@ -481,11 +502,6 @@ public class MockAMQQueue implements AMQQueue
{
}
- public ManagedObject getManagedObject()
- {
- return null;
- }
-
public int compareTo(AMQQueue o)
{
return 0;
@@ -503,7 +519,7 @@ public class MockAMQQueue implements AMQQueue
public void setCapacity(long capacity)
{
-
+
}
public long getFlowResumeCapacity()
@@ -513,7 +529,7 @@ public class MockAMQQueue implements AMQQueue
public void setFlowResumeCapacity(long flowResumeCapacity)
{
-
+
}
public void configure(ConfigurationPlugin config)
@@ -546,12 +562,6 @@ public class MockAMQQueue implements AMQQueue
_exclusiveOwner = exclusiveOwner;
}
-
- public String getResourceName()
- {
- return _name.toString();
- }
-
public boolean isOverfull()
{
return false;
@@ -582,7 +592,7 @@ public class MockAMQQueue implements AMQQueue
return 0;
}
- public void decrementUnackedMsgCount()
+ public void decrementUnackedMsgCount(QueueEntry queueEntry)
{
}
@@ -599,7 +609,6 @@ public class MockAMQQueue implements AMQQueue
public void setExclusive(boolean exclusive)
{
-
}
public int getMaximumDeliveryCount()
@@ -611,11 +620,23 @@ public class MockAMQQueue implements AMQQueue
{
}
- public void setAlternateExchange(String exchangeName)
+ public void visit(final QueueEntryVisitor visitor)
+ {
+ }
+
+ @Override
+ public void setNotificationListener(NotificationListener listener)
{
}
- public void visit(final Visitor visitor)
+ @Override
+ public void setDescription(String description)
{
}
+
+ @Override
+ public String getDescription()
+ {
+ return null;
+ }
}
diff --git a/java/broker/src/test/java/org/apache/qpid/server/queue/NotificationCheckTest.java b/java/broker/src/test/java/org/apache/qpid/server/queue/NotificationCheckTest.java
new file mode 100644
index 0000000000..df2de7f0e0
--- /dev/null
+++ b/java/broker/src/test/java/org/apache/qpid/server/queue/NotificationCheckTest.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.server.queue;
+
+import static org.mockito.Matchers.contains;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
+import static org.mockito.Mockito.when;
+
+import static org.apache.qpid.server.queue.NotificationCheck.MESSAGE_AGE_ALERT;
+import static org.apache.qpid.server.queue.NotificationCheck.MESSAGE_COUNT_ALERT;
+import static org.apache.qpid.server.queue.NotificationCheck.MESSAGE_SIZE_ALERT;
+import static org.apache.qpid.server.queue.NotificationCheck.QUEUE_DEPTH_ALERT;
+
+
+import junit.framework.TestCase;
+
+import org.apache.qpid.server.message.ServerMessage;
+import org.apache.qpid.server.queue.AMQQueue.NotificationListener;
+
+public class NotificationCheckTest extends TestCase
+{
+
+ private ServerMessage<?> _message = mock(ServerMessage.class);
+ private AMQQueue _queue = mock(AMQQueue.class);
+ private NotificationListener _listener = mock(NotificationListener.class);
+
+ public void testMessageCountAlertFires() throws Exception
+ {
+ when(_queue.getMaximumMessageCount()).thenReturn(1000l);
+ when(_queue.getMessageCount()).thenReturn(999, 1000, 1001);
+
+ MESSAGE_COUNT_ALERT.notifyIfNecessary(_message, _queue, _listener);
+ verifyZeroInteractions(_listener);
+
+ MESSAGE_COUNT_ALERT.notifyIfNecessary(_message, _queue, _listener);
+ verify(_listener).notifyClients(eq(MESSAGE_COUNT_ALERT), eq(_queue), eq("1000: Maximum count on queue threshold (1000) breached."));
+
+ MESSAGE_COUNT_ALERT.notifyIfNecessary(_message, _queue, _listener);
+ verify(_listener).notifyClients(eq(MESSAGE_COUNT_ALERT), eq(_queue), eq("1001: Maximum count on queue threshold (1000) breached."));
+ }
+
+ public void testMessageSizeAlertFires() throws Exception
+ {
+ when(_queue.getMaximumMessageSize()).thenReturn(1024l);
+ when(_message.getSize()).thenReturn(1023l, 1024l, 1025l);
+
+ MESSAGE_SIZE_ALERT.notifyIfNecessary(_message, _queue, _listener);
+ verifyZeroInteractions(_listener);
+
+ MESSAGE_SIZE_ALERT.notifyIfNecessary(_message, _queue, _listener);
+ verify(_listener).notifyClients(eq(MESSAGE_SIZE_ALERT), eq(_queue), contains("1024b : Maximum message size threshold (1024) breached."));
+
+ MESSAGE_SIZE_ALERT.notifyIfNecessary(_message, _queue, _listener);
+ verify(_listener).notifyClients(eq(MESSAGE_SIZE_ALERT), eq(_queue), contains("1025b : Maximum message size threshold (1024) breached."));
+ }
+
+ public void testMessageAgeAlertFires() throws Exception
+ {
+ long now = System.currentTimeMillis();
+ when(_queue.getMaximumMessageAge()).thenReturn(1000l);
+ when(_queue.getOldestMessageArrivalTime()).thenReturn(now, now - 15000);
+
+ MESSAGE_AGE_ALERT.notifyIfNecessary(_message, _queue, _listener);
+ verifyZeroInteractions(_listener);
+
+ MESSAGE_AGE_ALERT.notifyIfNecessary(_message, _queue, _listener);
+ // Uses contains as first part of message is nondeterministic
+ verify(_listener).notifyClients(eq(MESSAGE_AGE_ALERT), eq(_queue), contains("s : Maximum age on queue threshold (1s) breached."));
+ }
+
+ public void testQueueDepthAlertFires() throws Exception
+ {
+ when(_queue.getMaximumQueueDepth()).thenReturn(1024l);
+ when(_queue.getQueueDepth()).thenReturn(1023l, 1024l, 2048l);
+
+ QUEUE_DEPTH_ALERT.notifyIfNecessary(_message, _queue, _listener);
+ verifyZeroInteractions(_listener);
+
+ QUEUE_DEPTH_ALERT.notifyIfNecessary(_message, _queue, _listener);
+ verify(_listener).notifyClients(eq(QUEUE_DEPTH_ALERT), eq(_queue), eq("1Kb : Maximum queue depth threshold (1Kb) breached."));
+
+ QUEUE_DEPTH_ALERT.notifyIfNecessary(_message, _queue, _listener);
+ verify(_listener).notifyClients(eq(QUEUE_DEPTH_ALERT), eq(_queue), eq("2Kb : Maximum queue depth threshold (1Kb) breached."));
+ }
+}
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 52ad4a7c5b..2cd423d4c9 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
@@ -21,6 +21,13 @@
package org.apache.qpid.server.queue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
+import static org.mockito.Mockito.atLeastOnce;
+import static org.mockito.Matchers.contains;
+import static org.mockito.Matchers.eq;
+
import org.apache.commons.configuration.PropertiesConfiguration;
import org.apache.qpid.AMQException;
@@ -43,7 +50,6 @@ 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.store.TestableMemoryMessageStoreFactory;
import org.apache.qpid.server.subscription.MockSubscription;
import org.apache.qpid.server.subscription.Subscription;
import org.apache.qpid.server.txn.AutoCommitTransaction;
@@ -80,7 +86,6 @@ public class SimpleAMQQueueTest extends InternalBrokerBaseCase
public void setExchange(AMQShortString exchange)
{
- //To change body of implemented methods use File | Settings | File Templates.
}
public boolean isImmediate()
@@ -108,11 +113,11 @@ public class SimpleAMQQueueTest extends InternalBrokerBaseCase
PropertiesConfiguration env = new PropertiesConfiguration();
final VirtualHostConfiguration vhostConfig = new VirtualHostConfiguration(getClass().getName(), env);
- vhostConfig.setMessageStoreFactoryClass(TestableMemoryMessageStoreFactory.class.getName());
+ vhostConfig.setMessageStoreClass(TestableMemoryMessageStore.class.getName());
_virtualHost = new VirtualHostImpl(ApplicationRegistry.getInstance(), vhostConfig);
applicationRegistry.getVirtualHostRegistry().registerVirtualHost(_virtualHost);
- _queue = (SimpleAMQQueue) AMQQueueFactory.createAMQQueueImpl(_qname, false, _owner, false, false, _virtualHost, _arguments);
+ _queue = (SimpleAMQQueue) AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), _qname.asString(), false, _owner.asString(), false, false, _virtualHost, FieldTable.convertToMap(_arguments));
_exchange = (DirectExchange)_virtualHost.getExchangeRegistry().getExchange(ExchangeDefaults.DIRECT_EXCHANGE_NAME);
}
@@ -128,7 +133,7 @@ public class SimpleAMQQueueTest extends InternalBrokerBaseCase
{
_queue.stop();
try {
- _queue = (SimpleAMQQueue) AMQQueueFactory.createAMQQueueImpl(null, false, _owner, false, false, _virtualHost, _arguments );
+ _queue = (SimpleAMQQueue) AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), null, false, _owner.asString(), false, false, _virtualHost, FieldTable.convertToMap(_arguments));
assertNull("Queue was created", _queue);
}
catch (IllegalArgumentException e)
@@ -138,7 +143,7 @@ public class SimpleAMQQueueTest extends InternalBrokerBaseCase
}
try {
- _queue = new SimpleAMQQueue(UUIDGenerator.generateUUID(), _qname, false, _owner, false,false, null, Collections.EMPTY_MAP);
+ _queue = new SimpleAMQQueue(UUIDGenerator.generateRandomUUID(), _qname, false, _owner, false,false, null, Collections.EMPTY_MAP);
assertNull("Queue was created", _queue);
}
catch (IllegalArgumentException e)
@@ -147,8 +152,8 @@ public class SimpleAMQQueueTest extends InternalBrokerBaseCase
e.getMessage().contains("Host"));
}
- _queue = (SimpleAMQQueue) AMQQueueFactory.createAMQQueueImpl(_qname, false, _owner, false,
- false, _virtualHost, _arguments);
+ _queue = (SimpleAMQQueue) AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), _qname.asString(), false, _owner.asString(), false,
+ false, _virtualHost, FieldTable.convertToMap(_arguments));
assertNotNull("Queue was not created", _queue);
}
@@ -480,7 +485,7 @@ public class SimpleAMQQueueTest extends InternalBrokerBaseCase
public void testAutoDeleteQueue() throws Exception
{
_queue.stop();
- _queue = new SimpleAMQQueue(UUIDGenerator.generateUUID(), _qname, false, null, true, false, _virtualHost, Collections.EMPTY_MAP);
+ _queue = new SimpleAMQQueue(UUIDGenerator.generateRandomUUID(), _qname, false, null, true, false, _virtualHost, Collections.EMPTY_MAP);
_queue.setDeleteOnNoConsumers(true);
_queue.registerSubscription(_subscription, false);
AMQMessage message = createMessage(new Long(25));
@@ -692,7 +697,7 @@ public class SimpleAMQQueueTest extends InternalBrokerBaseCase
public void testProcessQueueWithUniqueSelectors() throws Exception
{
TestSimpleQueueEntryListFactory factory = new TestSimpleQueueEntryListFactory();
- SimpleAMQQueue testQueue = new SimpleAMQQueue(UUIDGenerator.generateUUID(), "testQueue", false,"testOwner",
+ SimpleAMQQueue testQueue = new SimpleAMQQueue(UUIDGenerator.generateRandomUUID(), "testQueue", false,"testOwner",
false, false, _virtualHost, factory, null)
{
@Override
@@ -840,120 +845,7 @@ public class SimpleAMQQueueTest extends InternalBrokerBaseCase
}
}
- /**
- * Tests that dequeued message is not copied as part of invocation of
- * {@link SimpleAMQQueue#copyMessagesToAnotherQueue(long, long, String)}
- */
- 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);
-
- // copy messages into another queue
- _queue.copyMessagesToAnotherQueue(0, messageNumber, anotherQueueName);
- // 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)}
- */
- 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);
-
- // move messages into another queue
- _queue.moveMessagesToAnotherQueue(0, messageNumber, anotherQueueName);
-
- // 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)}
- */
- 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
@@ -1029,7 +921,7 @@ public class SimpleAMQQueueTest extends InternalBrokerBaseCase
int dequeueMessageIndex = 1;
// create queue with overridden method deliverAsync
- SimpleAMQQueue testQueue = new SimpleAMQQueue(UUIDGenerator.generateUUID(), new AMQShortString("test"),
+ SimpleAMQQueue testQueue = new SimpleAMQQueue(UUIDGenerator.generateRandomUUID(), new AMQShortString("test"),
false, new AMQShortString("testOwner"), false, false, _virtualHost, null)
{
@Override
@@ -1097,10 +989,10 @@ public class SimpleAMQQueueTest extends InternalBrokerBaseCase
/**
* Tests that entry in dequeued state are not enqueued and not delivered to subscription
*/
- public void testEqueueDequeuedEntry()
+ public void testEnqueueDequeuedEntry()
{
// create a queue where each even entry is considered a dequeued
- SimpleAMQQueue queue = new SimpleAMQQueue(UUIDGenerator.generateUUID(), new AMQShortString("test"), false,
+ SimpleAMQQueue queue = new SimpleAMQQueue(UUIDGenerator.generateRandomUUID(), new AMQShortString("test"), false,
new AMQShortString("testOwner"), false, false, _virtualHost, new QueueEntryListFactory()
{
public QueueEntryList createQueueEntryList(AMQQueue queue)
@@ -1178,7 +1070,7 @@ public class SimpleAMQQueueTest extends InternalBrokerBaseCase
public void testActiveConsumerCount() throws Exception
{
- final SimpleAMQQueue queue = new SimpleAMQQueue(UUIDGenerator.generateUUID(), new AMQShortString("testActiveConsumerCount"), false,
+ final SimpleAMQQueue queue = new SimpleAMQQueue(UUIDGenerator.generateRandomUUID(), new AMQShortString("testActiveConsumerCount"), false,
new AMQShortString("testOwner"), false, false, _virtualHost, new SimpleQueueEntryList.Factory(), null);
//verify adding an active subscription increases the count
@@ -1232,29 +1124,37 @@ public class SimpleAMQQueueTest extends InternalBrokerBaseCase
assertEquals("Unexpected active consumer count", 1, queue.getActiveConsumerCount());
}
- /**
- * A helper method to create a queue with given name
- *
- * @param name
- * queue name
- * @return queue
- */
- private SimpleAMQQueue createQueue(String name)
+ public void testNotificationFiredOnEnqueue() throws Exception
{
- 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;
+ AMQQueue.NotificationListener listener = mock(AMQQueue.NotificationListener.class);
+
+ _queue.setNotificationListener(listener);
+ _queue.setMaximumMessageCount(2);
+
+ _queue.enqueue(createMessage(new Long(24)));
+ verifyZeroInteractions(listener);
+
+ _queue.enqueue(createMessage(new Long(25)));
+
+ verify(listener, atLeastOnce()).notifyClients(eq(NotificationCheck.MESSAGE_COUNT_ALERT), eq(_queue), contains("Maximum count on queue threshold"));
+ }
+
+ public void testNotificationFiredAsync() throws Exception
+ {
+ AMQQueue.NotificationListener listener = mock(AMQQueue.NotificationListener.class);
+
+ _queue.enqueue(createMessage(new Long(24)));
+ _queue.enqueue(createMessage(new Long(25)));
+ _queue.enqueue(createMessage(new Long(26)));
+
+ _queue.setNotificationListener(listener);
+ _queue.setMaximumMessageCount(2);
+
+ verifyZeroInteractions(listener);
+
+ _queue.checkMessageStatus();
+
+ verify(listener, atLeastOnce()).notifyClients(eq(NotificationCheck.MESSAGE_COUNT_ALERT), eq(_queue), contains("Maximum count on queue threshold"));
}
/**
diff --git a/java/broker/src/test/java/org/apache/qpid/server/queue/SimpleAMQQueueThreadPoolTest.java b/java/broker/src/test/java/org/apache/qpid/server/queue/SimpleAMQQueueThreadPoolTest.java
index 39ddd1d500..6b82cd361a 100644
--- a/java/broker/src/test/java/org/apache/qpid/server/queue/SimpleAMQQueueThreadPoolTest.java
+++ b/java/broker/src/test/java/org/apache/qpid/server/queue/SimpleAMQQueueThreadPoolTest.java
@@ -21,8 +21,8 @@
package org.apache.qpid.server.queue;
import org.apache.qpid.AMQException;
-import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.pool.ReferenceCountingExecutorService;
+import org.apache.qpid.server.model.UUIDGenerator;
import org.apache.qpid.server.registry.ApplicationRegistry;
import org.apache.qpid.server.util.InternalBrokerBaseCase;
import org.apache.qpid.server.virtualhost.VirtualHost;
@@ -37,9 +37,8 @@ public class SimpleAMQQueueThreadPoolTest extends InternalBrokerBaseCase
try
{
- SimpleAMQQueue queue = (SimpleAMQQueue) AMQQueueFactory.createAMQQueueImpl(new AMQShortString("test"), false,
- new AMQShortString("owner"),
- false, false, test, null);
+ SimpleAMQQueue queue = (SimpleAMQQueue) AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), "test", false,
+ "owner", false, false, test, null);
assertFalse("Creation did not start Pool.", ReferenceCountingExecutorService.getInstance().getPool().isShutdown());
diff --git a/java/broker/src/test/java/org/apache/qpid/server/registry/ApplicationRegistryShutdownTest.java b/java/broker/src/test/java/org/apache/qpid/server/registry/ApplicationRegistryShutdownTest.java
index 9ff8f0a531..9af950d385 100644
--- a/java/broker/src/test/java/org/apache/qpid/server/registry/ApplicationRegistryShutdownTest.java
+++ b/java/broker/src/test/java/org/apache/qpid/server/registry/ApplicationRegistryShutdownTest.java
@@ -49,7 +49,7 @@ public class ApplicationRegistryShutdownTest extends InternalBrokerBaseCase
/**
- * QPID-1399 : Ensure that the Authentiction manager unregisters any SASL providers created during
+ * QPID-1399 : Ensure that the Authentication manager unregisters any SASL providers created during
* ApplicationRegistry initialisation.
*
*/
diff --git a/java/broker/src/test/java/org/apache/qpid/server/security/auth/manager/AnonymousAuthenticationManagerTest.java b/java/broker/src/test/java/org/apache/qpid/server/security/auth/manager/AnonymousAuthenticationManagerTest.java
new file mode 100644
index 0000000000..9dcd22c088
--- /dev/null
+++ b/java/broker/src/test/java/org/apache/qpid/server/security/auth/manager/AnonymousAuthenticationManagerTest.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.server.security.auth.manager;
+
+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.database.PlainPasswordFilePrincipalDatabase;
+import org.apache.qpid.server.util.InternalBrokerBaseCase;
+
+public class AnonymousAuthenticationManagerTest extends InternalBrokerBaseCase
+{
+
+ private AuthenticationManager _manager = null;
+
+ public void setUp() throws Exception
+ {
+ _manager = AnonymousAuthenticationManager.INSTANCE;
+ }
+
+
+ public void tearDown() throws Exception
+ {
+ if(_manager != null)
+ {
+ _manager = null;
+ }
+ }
+
+ private ConfigurationPlugin getPlainDatabaseConfig() throws ConfigurationException
+ {
+ final ConfigurationPlugin config = new PrincipalDatabaseAuthenticationManager.PrincipalDatabaseAuthenticationManagerConfiguration();
+
+ XMLConfiguration xmlconfig = new XMLConfiguration();
+ xmlconfig.addProperty("pd-auth-manager.principal-database.class", PlainPasswordFilePrincipalDatabase.class.getName());
+
+ // Create a CompositeConfiguration as this is what the broker uses
+ CompositeConfiguration composite = new CompositeConfiguration();
+ composite.addConfiguration(xmlconfig);
+ config.setConfiguration("security", xmlconfig);
+ return config;
+ }
+
+
+ public void testConfiguration() throws Exception
+ {
+ AuthenticationManager authenticationManager =
+ AnonymousAuthenticationManager.FACTORY.newInstance(getPlainDatabaseConfig());
+
+ assertNull("AnonymousAuthenticationManager unexpectedly created when not in config", authenticationManager);
+ }
+
+ public void testGetMechanisms() throws Exception
+ {
+ assertEquals("ANONYMOUS", _manager.getMechanisms());
+ }
+
+ public void testCreateSaslServer() throws Exception
+ {
+ SaslServer server = _manager.createSaslServer("ANONYMOUS", "example.example.com", null);
+
+ assertEquals("Sasl Server mechanism name is not as expected", "ANONYMOUS", server.getMechanismName());
+
+ try
+ {
+ server = _manager.createSaslServer("PLAIN", "example.example.com", null);
+ fail("Expected creating SaslServer with incorrect mechanism to throw an exception");
+ }
+ catch (SaslException e)
+ {
+ // pass
+ }
+ }
+
+ public void testAuthenticate() throws Exception
+ {
+ SaslServer saslServer = _manager.createSaslServer("ANONYMOUS", "example.example.com", null);
+ AuthenticationResult result = _manager.authenticate(saslServer, new byte[0]);
+ assertNotNull(result);
+ assertEquals("Expected authentication to be successful",
+ AuthenticationResult.AuthenticationStatus.SUCCESS,
+ result.getStatus());
+ assertNotNull("Subject should not be null", result.getSubject());
+ }
+
+
+}
diff --git a/java/broker/src/test/java/org/apache/qpid/server/security/auth/manager/AuthenticationManagerRegistryTest.java b/java/broker/src/test/java/org/apache/qpid/server/security/auth/manager/AuthenticationManagerRegistryTest.java
new file mode 100644
index 0000000000..efb8df3a38
--- /dev/null
+++ b/java/broker/src/test/java/org/apache/qpid/server/security/auth/manager/AuthenticationManagerRegistryTest.java
@@ -0,0 +1,304 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.security.auth.manager;
+
+import static org.mockito.Mockito.*;
+
+import java.net.InetSocketAddress;
+import java.net.SocketAddress;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.configuration.ConfigurationException;
+import org.apache.qpid.server.configuration.ServerConfiguration;
+import org.apache.qpid.server.plugins.Plugin;
+import org.apache.qpid.server.plugins.PluginManager;
+import org.apache.qpid.server.security.SecurityManager.SecurityConfiguration;
+import org.mockito.Mockito;
+
+import junit.framework.TestCase;
+
+public class AuthenticationManagerRegistryTest extends TestCase
+{
+ private static final Map<String, AuthenticationManagerPluginFactory<? extends Plugin>> EMPTY_PLUGINMAP = Collections.emptyMap();
+
+ private PluginManager _pluginManager = Mockito.mock(PluginManager.class);
+ private ServerConfiguration _serverConfiguration = Mockito.mock(ServerConfiguration.class);
+ private SecurityConfiguration _securityConfiguration = Mockito.mock(SecurityConfiguration.class);
+
+ private List<AuthenticationManager> _allCreatedAuthManagers = new ArrayList<AuthenticationManager>();
+
+ @Override
+ protected void setUp() throws Exception
+ {
+ super.setUp();
+
+ // Setup server configuration to return mock security config.
+ when(_serverConfiguration.getConfiguration(SecurityConfiguration.class.getName())).thenReturn(_securityConfiguration);
+ }
+
+ @Override
+ protected void tearDown() throws Exception
+ {
+ try
+ {
+ verifyAllCreatedAuthManagersClosed();
+ }
+ finally
+ {
+ super.tearDown();
+ }
+ }
+
+ public void testNoAuthenticationManagerFactoryPluginsFound() throws Exception
+ {
+ when(_pluginManager.getAuthenticationManagerPlugins()).thenReturn(EMPTY_PLUGINMAP);
+ try
+ {
+ new AuthenticationManagerRegistry(_serverConfiguration, _pluginManager);
+ fail("Exception not thrown");
+ }
+ catch (ConfigurationException ce)
+ {
+ // PASS
+ assertEquals("No authentication manager factory plugins found. Check the desired authentication manager plugin has been placed in the plugins directory.",
+ ce.getMessage());
+ }
+ }
+
+ public void testSameAuthenticationManagerSpecifiedTwice() throws Exception
+ {
+ AuthenticationManagerPluginFactory<? extends Plugin> myAuthManagerFactory = newMockFactoryProducingMockAuthManagerImplementing(TestAuthenticationManager1.class);
+
+ Map<String, AuthenticationManagerPluginFactory<? extends Plugin>> pluginMap = createPluginMap(myAuthManagerFactory, myAuthManagerFactory);
+
+ when(_pluginManager.getAuthenticationManagerPlugins()).thenReturn(pluginMap);
+
+ try
+ {
+ new AuthenticationManagerRegistry(_serverConfiguration, _pluginManager);
+ fail("Exception not thrown");
+ }
+ catch (ConfigurationException ce)
+ {
+ // PASS
+ assertEquals("Cannot configure more than one authentication manager of type " + myAuthManagerFactory.getPluginClass().getSimpleName() + ". Remove configuration for one of the authentication managers.",
+ ce.getMessage());
+ }
+ }
+
+ public void testMultipleAuthenticationManagersSpecifiedButNoDefaultSpecified() throws Exception
+ {
+ AuthenticationManagerPluginFactory<? extends Plugin> myAuthManagerFactory1 = newMockFactoryProducingMockAuthManagerImplementing(TestAuthenticationManager1.class);
+ AuthenticationManagerPluginFactory<? extends Plugin> myAuthManagerFactory2 = newMockFactoryProducingMockAuthManagerImplementing(TestAuthenticationManager2.class);
+
+ Map<String, AuthenticationManagerPluginFactory<? extends Plugin>> pluginMap = createPluginMap(myAuthManagerFactory1, myAuthManagerFactory2);
+
+ when(_pluginManager.getAuthenticationManagerPlugins()).thenReturn(pluginMap);
+ when(_serverConfiguration.getDefaultAuthenticationManager()).thenReturn(null);
+
+ try
+ {
+ new AuthenticationManagerRegistry(_serverConfiguration, _pluginManager);
+ fail("Exception not thrown");
+ }
+ catch (ConfigurationException ce)
+ {
+ // PASS
+ assertEquals("If more than one authentication manager is configured a default MUST be specified.",
+ ce.getMessage());
+ }
+ }
+
+ public void testDefaultAuthenticationManagerNotKnown() throws Exception
+ {
+ String myDefaultAuthManagerSimpleClassName = "UnknownAuthenticationManager";
+
+ AuthenticationManagerPluginFactory<? extends Plugin> myAuthManagerFactory1 = newMockFactoryProducingMockAuthManagerImplementing(TestAuthenticationManager1.class);
+ AuthenticationManagerPluginFactory<? extends Plugin> myAuthManagerFactory2 = newMockFactoryProducingMockAuthManagerImplementing(TestAuthenticationManager2.class);
+
+ Map<String, AuthenticationManagerPluginFactory<? extends Plugin>> pluginMap = createPluginMap(myAuthManagerFactory1, myAuthManagerFactory2);
+
+ when(_pluginManager.getAuthenticationManagerPlugins()).thenReturn(pluginMap);
+ when(_serverConfiguration.getDefaultAuthenticationManager()).thenReturn(myDefaultAuthManagerSimpleClassName);
+
+ try
+ {
+ new AuthenticationManagerRegistry(_serverConfiguration, _pluginManager);
+ fail("Exception not thrown");
+ }
+ catch (ConfigurationException ce)
+ {
+ // PASS
+ assertTrue("Unexpected message " + ce.getMessage(),
+ ce.getMessage().startsWith("No authentication managers configured of type " + myDefaultAuthManagerSimpleClassName + " which is specified as the default"));
+ }
+ }
+
+ public void testPortMappedToUnknownAuthenticationManager() throws Exception
+ {
+ String myDefaultAuthManagerSimpleClassName = "UnknownAuthenticationManager";
+ int portNumber = 1234;
+
+ AuthenticationManagerPluginFactory<? extends Plugin> myAuthManagerFactory1 = newMockFactoryProducingMockAuthManagerImplementing(TestAuthenticationManager1.class);
+
+ Map<String, AuthenticationManagerPluginFactory<? extends Plugin>> pluginMap = createPluginMap(myAuthManagerFactory1);
+
+ when(_pluginManager.getAuthenticationManagerPlugins()).thenReturn(pluginMap);
+ when(_serverConfiguration.getPortAuthenticationMappings()).thenReturn(Collections.singletonMap(portNumber, myDefaultAuthManagerSimpleClassName));
+
+ try
+ {
+ new AuthenticationManagerRegistry(_serverConfiguration, _pluginManager);
+ fail("Exception not thrown");
+ }
+ catch (ConfigurationException ce)
+ {
+ // PASS
+ assertEquals("Unknown authentication manager class " + myDefaultAuthManagerSimpleClassName + " configured for port " + portNumber, ce.getMessage());
+ }
+ }
+
+ public void testGetAuthenticationManagerForInetSocketAddress() throws Exception
+ {
+ AuthenticationManagerPluginFactory<? extends Plugin> myAuthManagerFactory1 = newMockFactoryProducingMockAuthManagerImplementing(TestAuthenticationManager1.class);
+ Map<String, AuthenticationManagerPluginFactory<? extends Plugin>> pluginMap = createPluginMap(myAuthManagerFactory1);
+
+ when(_pluginManager.getAuthenticationManagerPlugins()).thenReturn(pluginMap);
+
+ AuthenticationManagerRegistry registry = new AuthenticationManagerRegistry(_serverConfiguration, _pluginManager);
+
+ AuthenticationManager authenticationManager = registry.getAuthenticationManager(new InetSocketAddress(1234));
+ assertEquals("TestAuthenticationManager1", authenticationManager.getMechanisms());
+
+ registry.close();
+ }
+
+ public void testGetAuthenticationManagerForNonInetSocketAddress() throws Exception
+ {
+ AuthenticationManagerPluginFactory<? extends Plugin> myAuthManagerFactory1 = newMockFactoryProducingMockAuthManagerImplementing(TestAuthenticationManager1.class);
+ Map<String, AuthenticationManagerPluginFactory<? extends Plugin>> pluginMap = createPluginMap(myAuthManagerFactory1);
+
+ when(_pluginManager.getAuthenticationManagerPlugins()).thenReturn(pluginMap);
+
+ AuthenticationManagerRegistry registry = new AuthenticationManagerRegistry(_serverConfiguration, _pluginManager);
+
+ AuthenticationManager authenticationManager = registry.getAuthenticationManager(mock(SocketAddress.class));
+ assertEquals("TestAuthenticationManager1", authenticationManager.getMechanisms());
+
+ registry.close();
+ }
+
+ public void testGetAuthenticationManagerWithMultipleAuthenticationManager() throws Exception
+ {
+ AuthenticationManagerPluginFactory<? extends Plugin> myAuthManagerFactory1 = newMockFactoryProducingMockAuthManagerImplementing(TestAuthenticationManager1.class);
+ AuthenticationManagerPluginFactory<? extends Plugin> myAuthManagerFactory2 = newMockFactoryProducingMockAuthManagerImplementing(TestAuthenticationManager2.class);
+ Map<String, AuthenticationManagerPluginFactory<? extends Plugin>> pluginMap = createPluginMap(myAuthManagerFactory1, myAuthManagerFactory2);
+
+ String defaultAuthManger = myAuthManagerFactory1.getPluginName();
+ int unmappedPortNumber = 1234;
+ int mappedPortNumber = 1235;
+ String mappedAuthManager = myAuthManagerFactory2.getPluginName();
+
+ when(_pluginManager.getAuthenticationManagerPlugins()).thenReturn(pluginMap);
+ when(_serverConfiguration.getDefaultAuthenticationManager()).thenReturn(defaultAuthManger);
+ when(_serverConfiguration.getPortAuthenticationMappings()).thenReturn(Collections.singletonMap(mappedPortNumber, mappedAuthManager));
+
+ AuthenticationManagerRegistry registry = new AuthenticationManagerRegistry(_serverConfiguration, _pluginManager);
+
+ AuthenticationManager authenticationManager1 = registry.getAuthenticationManager(new InetSocketAddress(unmappedPortNumber));
+ assertEquals("TestAuthenticationManager1", authenticationManager1.getMechanisms());
+
+ AuthenticationManager authenticationManager2 = registry.getAuthenticationManager(new InetSocketAddress(mappedPortNumber));
+ assertEquals("TestAuthenticationManager2", authenticationManager2.getMechanisms());
+
+ registry.close();
+ }
+
+ public void testAuthenticationManagersAreClosed() throws Exception
+ {
+ AuthenticationManagerPluginFactory<? extends Plugin> myAuthManagerFactory1 = newMockFactoryProducingMockAuthManagerImplementing(TestAuthenticationManager1.class);
+ AuthenticationManagerPluginFactory<? extends Plugin> myAuthManagerFactory2 = newMockFactoryProducingMockAuthManagerImplementing(TestAuthenticationManager2.class);
+ Map<String, AuthenticationManagerPluginFactory<? extends Plugin>> pluginMap = createPluginMap(myAuthManagerFactory1, myAuthManagerFactory2);
+
+ String defaultAuthManger = myAuthManagerFactory1.getPluginName();
+ when(_pluginManager.getAuthenticationManagerPlugins()).thenReturn(pluginMap);
+ when(_serverConfiguration.getDefaultAuthenticationManager()).thenReturn(defaultAuthManger);
+
+ AuthenticationManagerRegistry registry = new AuthenticationManagerRegistry(_serverConfiguration, _pluginManager);
+
+ registry.close();
+ }
+
+ private AuthenticationManagerPluginFactory<? extends Plugin> newMockFactoryProducingMockAuthManagerImplementing(Class<? extends AuthenticationManager> authManagerClazz)
+ throws ConfigurationException
+ {
+ AuthenticationManager myAuthManager = mock(authManagerClazz);
+ when(myAuthManager.getMechanisms()).thenReturn(authManagerClazz.getSimpleName()); // used to verify the getAuthenticationManagerFor returns expected impl.
+
+ AuthenticationManagerPluginFactory myAuthManagerFactory = mock(AuthenticationManagerPluginFactory.class);
+ when(myAuthManagerFactory.getPluginClass()).thenReturn(myAuthManager.getClass());
+ when(myAuthManagerFactory.getPluginName()).thenReturn(myAuthManager.getClass().getSimpleName());
+ when(myAuthManagerFactory.newInstance(_securityConfiguration)).thenReturn(myAuthManager);
+
+ _allCreatedAuthManagers.add(myAuthManager);
+ return myAuthManagerFactory;
+ }
+
+ private Map<String, AuthenticationManagerPluginFactory<? extends Plugin>> createPluginMap(
+ AuthenticationManagerPluginFactory<? extends Plugin> myAuthManagerFactory)
+ {
+ return createPluginMap(myAuthManagerFactory, null);
+ }
+
+ private Map<String, AuthenticationManagerPluginFactory<? extends Plugin>> createPluginMap(
+ AuthenticationManagerPluginFactory<? extends Plugin> authManagerFactory1,
+ AuthenticationManagerPluginFactory<? extends Plugin> authManagerFactory2)
+ {
+ Map<String, AuthenticationManagerPluginFactory<? extends Plugin>> pluginMap = new HashMap<String, AuthenticationManagerPluginFactory<? extends Plugin>>();
+ pluginMap.put("config.path.unused1", authManagerFactory1);
+ if (authManagerFactory2 != null)
+ {
+ pluginMap.put("config.path.unused2", authManagerFactory2);
+ }
+ return pluginMap;
+ }
+
+ private void verifyAllCreatedAuthManagersClosed()
+ {
+ for (Iterator<AuthenticationManager> iterator = _allCreatedAuthManagers.iterator(); iterator.hasNext();)
+ {
+ AuthenticationManager authenticationManager = (AuthenticationManager) iterator.next();
+ verify(authenticationManager).close();
+ }
+ }
+
+ private interface TestAuthenticationManager1 extends AuthenticationManager
+ {
+ }
+
+ private interface TestAuthenticationManager2 extends AuthenticationManager
+ {
+ }
+}
diff --git a/java/broker/src/test/java/org/apache/qpid/server/security/auth/manager/ExternalAuthenticationManagerTest.java b/java/broker/src/test/java/org/apache/qpid/server/security/auth/manager/ExternalAuthenticationManagerTest.java
new file mode 100644
index 0000000000..c1a55ef2ad
--- /dev/null
+++ b/java/broker/src/test/java/org/apache/qpid/server/security/auth/manager/ExternalAuthenticationManagerTest.java
@@ -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.
+ */
+package org.apache.qpid.server.security.auth.manager;
+
+import javax.security.auth.x500.X500Principal;
+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.database.PlainPasswordFilePrincipalDatabase;
+import org.apache.qpid.server.util.InternalBrokerBaseCase;
+
+public class ExternalAuthenticationManagerTest extends InternalBrokerBaseCase
+{
+
+ private AuthenticationManager _manager = null;
+
+ public void setUp() throws Exception
+ {
+ _manager = ExternalAuthenticationManager.INSTANCE;
+ }
+
+
+ public void tearDown() throws Exception
+ {
+ if(_manager != null)
+ {
+ _manager = null;
+ }
+ }
+
+ private ConfigurationPlugin getPlainDatabaseConfig() throws ConfigurationException
+ {
+ final ConfigurationPlugin config = new PrincipalDatabaseAuthenticationManager.PrincipalDatabaseAuthenticationManagerConfiguration();
+
+ XMLConfiguration xmlconfig = new XMLConfiguration();
+ xmlconfig.addProperty("pd-auth-manager.principal-database.class", PlainPasswordFilePrincipalDatabase.class.getName());
+
+ // Create a CompositeConfiguration as this is what the broker uses
+ CompositeConfiguration composite = new CompositeConfiguration();
+ composite.addConfiguration(xmlconfig);
+ config.setConfiguration("security", xmlconfig);
+ return config;
+ }
+
+
+ public void testConfiguration() throws Exception
+ {
+ AuthenticationManager authenticationManager =
+ ExternalAuthenticationManager.FACTORY.newInstance(getPlainDatabaseConfig());
+
+ assertNull("ExternalAuthenticationManager unexpectedly created when not in config", authenticationManager);
+ }
+
+ public void testGetMechanisms() throws Exception
+ {
+ assertEquals("EXTERNAL", _manager.getMechanisms());
+ }
+
+ public void testCreateSaslServer() throws Exception
+ {
+ SaslServer server = _manager.createSaslServer("EXTERNAL", "example.example.com", null);
+
+ assertEquals("Sasl Server mechanism name is not as expected", "EXTERNAL", server.getMechanismName());
+
+ try
+ {
+ server = _manager.createSaslServer("PLAIN", "example.example.com", null);
+ fail("Expected creating SaslServer with incorrect mechanism to throw an exception");
+ }
+ catch (SaslException e)
+ {
+ // pass
+ }
+ }
+
+ public void testAuthenticate() throws Exception
+ {
+ X500Principal principal = new X500Principal("CN=person, DC=example, DC=com");
+ SaslServer saslServer = _manager.createSaslServer("EXTERNAL", "example.example.com", principal);
+
+ AuthenticationResult result = _manager.authenticate(saslServer, new byte[0]);
+ assertNotNull(result);
+ assertEquals("Expected authentication to be successful",
+ AuthenticationResult.AuthenticationStatus.SUCCESS,
+ result.getStatus());
+ assertEquals("Expected principal to be unchanged",
+ principal,
+ result.getSubject().getPrincipals().iterator().next());
+
+ saslServer = _manager.createSaslServer("EXTERNAL", "example.example.com", null);
+ result = _manager.authenticate(saslServer, new byte[0]);
+ assertNotNull(result);
+ assertEquals("Expected authentication to be unsuccessful",
+ AuthenticationResult.AuthenticationStatus.ERROR,
+ result.getStatus());
+
+ }
+
+
+}
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
index 1a42fe3886..47c189e4fa 100644
--- 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
@@ -167,7 +167,7 @@ public class PrincipalDatabaseAuthenticationManagerTest extends InternalBrokerBa
*/
public void testSaslMechanismCreation() throws Exception
{
- SaslServer server = _manager.createSaslServer("CRAM-MD5", "localhost");
+ SaslServer server = _manager.createSaslServer("CRAM-MD5", "localhost", null);
assertNotNull(server);
// Merely tests the creation of the mechanism. Mechanisms themselves are tested
// by their own tests.
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 bef03057ec..c0c55de92a 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,23 +20,19 @@
*/
package org.apache.qpid.server.security.auth.rmi;
+import java.security.Principal;
import junit.framework.TestCase;
-import org.apache.commons.configuration.ConfigurationException;
-import org.apache.commons.configuration.XMLConfiguration;
-import org.apache.qpid.server.configuration.ServerConfiguration;
import org.apache.qpid.server.configuration.plugins.ConfigurationPlugin;
-import org.apache.qpid.server.registry.ApplicationRegistry;
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.util.TestApplicationRegistry;
import javax.management.remote.JMXPrincipal;
import javax.security.auth.Subject;
-import javax.security.auth.callback.CallbackHandler;
import javax.security.sasl.SaslException;
import javax.security.sasl.SaslServer;
+import java.net.InetSocketAddress;
import java.util.Collections;
/**
@@ -52,7 +48,7 @@ public class RMIPasswordAuthenticatorTest extends TestCase
protected void setUp() throws Exception
{
- _rmipa = new RMIPasswordAuthenticator();
+ _rmipa = new RMIPasswordAuthenticator(new InetSocketAddress(5672));
_credentials = new String[] {USERNAME, PASSWORD};
}
@@ -76,14 +72,14 @@ public class RMIPasswordAuthenticatorTest extends TestCase
newSubject.equals(expectedSubject));
}
-
+
/**
* Tests a unsuccessful authentication.
*/
public void testUsernameOrPasswordInvalid()
{
_rmipa.setAuthenticationManager(createTestAuthenticationManager(false, null));
-
+
try
{
_rmipa.authenticate(_credentials);
@@ -122,17 +118,7 @@ public class RMIPasswordAuthenticatorTest extends TestCase
*/
public void testNullAuthenticationManager() throws Exception
{
- ServerConfiguration serverConfig = new ServerConfiguration(new XMLConfiguration());
- TestApplicationRegistry reg = new TestApplicationRegistry(serverConfig)
- {
- @Override
- protected AuthenticationManager createAuthenticationManager() throws ConfigurationException
- {
- return null;
- }
- };
- ApplicationRegistry.initialise(reg);
-
+ _rmipa.setAuthenticationManager(null);
try
{
_rmipa.authenticate(_credentials);
@@ -143,10 +129,6 @@ public class RMIPasswordAuthenticatorTest extends TestCase
assertEquals("Unexpected exception message",
RMIPasswordAuthenticator.UNABLE_TO_LOOKUP, se.getMessage());
}
- finally
- {
- ApplicationRegistry.remove();
- }
}
/**
@@ -185,7 +167,7 @@ public class RMIPasswordAuthenticatorTest extends TestCase
assertEquals("Unexpected exception message",
RMIPasswordAuthenticator.SHOULD_HAVE_2_ELEMENTS, se.getMessage());
}
-
+
// Test handling of null credentials
try
{
@@ -199,7 +181,7 @@ public class RMIPasswordAuthenticatorTest extends TestCase
assertEquals("Unexpected exception message",
RMIPasswordAuthenticator.CREDENTIALS_REQUIRED, se.getMessage());
}
-
+
try
{
//send a null password
@@ -212,7 +194,7 @@ public class RMIPasswordAuthenticatorTest extends TestCase
assertEquals("Unexpected exception message",
RMIPasswordAuthenticator.SHOULD_BE_NON_NULL, se.getMessage());
}
-
+
try
{
//send a null username
@@ -251,7 +233,7 @@ public class RMIPasswordAuthenticatorTest extends TestCase
throw new UnsupportedOperationException();
}
- public SaslServer createSaslServer(String mechanism, String localFQDN) throws SaslException
+ public SaslServer createSaslServer(String mechanism, String localFQDN, Principal externalPrincipal) throws SaslException
{
throw new UnsupportedOperationException();
}
@@ -276,10 +258,6 @@ public class RMIPasswordAuthenticatorTest extends TestCase
}
}
- public CallbackHandler getHandler(String mechanism)
- {
- return null;
- }
};
}
}
diff --git a/java/broker/src/test/java/org/apache/qpid/server/store/DurableConfigurationStoreTest.java b/java/broker/src/test/java/org/apache/qpid/server/store/DurableConfigurationStoreTest.java
index a1cbb2cbc8..cd8d91d835 100644
--- a/java/broker/src/test/java/org/apache/qpid/server/store/DurableConfigurationStoreTest.java
+++ b/java/broker/src/test/java/org/apache/qpid/server/store/DurableConfigurationStoreTest.java
@@ -1,3 +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.
+ *
+ */
package org.apache.qpid.server.store;
import static org.mockito.Matchers.any;
@@ -27,7 +47,6 @@ import org.apache.qpid.server.exchange.Exchange;
import org.apache.qpid.server.logging.SystemOutMessageLogger;
import org.apache.qpid.server.logging.actors.CurrentActor;
import org.apache.qpid.server.logging.actors.TestLogActor;
-import org.apache.qpid.server.logging.subjects.TestBlankSubject;
import org.apache.qpid.server.message.EnqueableMessage;
import org.apache.qpid.server.model.UUIDGenerator;
import org.apache.qpid.server.queue.AMQQueue;
@@ -41,7 +60,7 @@ import org.apache.qpid.server.store.ConfigurationRecoveryHandler.ExchangeRecover
import org.apache.qpid.server.store.ConfigurationRecoveryHandler.QueueRecoveryHandler;
import org.apache.qpid.server.store.MessageStoreRecoveryHandler.StoredMessageRecoveryHandler;
import org.apache.qpid.server.store.Transaction.Record;
-import org.apache.qpid.server.store.derby.DerbyMessageStoreFactory;
+import org.apache.qpid.server.store.derby.DerbyMessageStore;
import org.apache.qpid.test.utils.QpidTestCase;
import org.apache.qpid.util.FileUtils;
@@ -75,11 +94,11 @@ public class DurableConfigurationStoreTest extends QpidTestCase
{
super.setUp();
- _queueId = UUIDGenerator.generateUUID();
- _exchangeId = UUIDGenerator.generateUUID();
+ _queueId = UUIDGenerator.generateRandomUUID();
+ _exchangeId = UUIDGenerator.generateRandomUUID();
_storeName = getName();
- _storePath = TMP_FOLDER + "/" + _storeName;
+ _storePath = TMP_FOLDER + File.separator + _storeName;
FileUtils.delete(new File(_storePath), true);
setTestSystemProperty("QPID_WORK", TMP_FOLDER);
_configuration = mock(Configuration.class);
@@ -94,9 +113,9 @@ public class DurableConfigurationStoreTest extends QpidTestCase
_dtxRecordRecoveryHandler = mock(TransactionLogRecoveryHandler.DtxRecordRecoveryHandler.class);
when(_messageStoreRecoveryHandler.begin()).thenReturn(_storedMessageRecoveryHandler);
- when(_recoveryHandler.begin(isA(MessageStore.class))).thenReturn(_queueRecoveryHandler);
- when(_queueRecoveryHandler.completeQueueRecovery()).thenReturn(_exchangeRecoveryHandler);
- when(_exchangeRecoveryHandler.completeExchangeRecovery()).thenReturn(_bindingRecoveryHandler);
+ when(_recoveryHandler.begin(isA(MessageStore.class))).thenReturn(_exchangeRecoveryHandler);
+ when(_exchangeRecoveryHandler.completeExchangeRecovery()).thenReturn(_queueRecoveryHandler);
+ when(_queueRecoveryHandler.completeQueueRecovery()).thenReturn(_bindingRecoveryHandler);
when(_bindingRecoveryHandler.completeBindingRecovery()).thenReturn(_linkRecoveryHandler);
when(_logRecoveryHandler.begin(any(MessageStore.class))).thenReturn(_queueEntryRecoveryHandler);
when(_queueEntryRecoveryHandler.completeQueueEntryRecovery()).thenReturn(_dtxRecordRecoveryHandler);
@@ -142,8 +161,8 @@ public class DurableConfigurationStoreTest extends QpidTestCase
public void testBindQueue() throws Exception
{
AMQQueue queue = createTestQueue(QUEUE_NAME, "queueOwner", false);
- Binding binding = new Binding(UUIDGenerator.generateUUID(), ROUTING_KEY, queue, _exchange,
- FieldTable.convertToMap(_bindingArgs));
+ Binding binding = new Binding(UUIDGenerator.generateRandomUUID(), null, ROUTING_KEY, queue,
+ _exchange, FieldTable.convertToMap(_bindingArgs));
_store.bindQueue(binding);
reopenStore();
@@ -156,8 +175,8 @@ public class DurableConfigurationStoreTest extends QpidTestCase
public void testUnbindQueue() throws Exception
{
AMQQueue queue = createTestQueue(QUEUE_NAME, "queueOwner", false);
- Binding binding = new Binding(UUIDGenerator.generateUUID(), ROUTING_KEY, queue, _exchange,
- FieldTable.convertToMap(_bindingArgs));
+ Binding binding = new Binding(UUIDGenerator.generateRandomUUID(), null, ROUTING_KEY, queue,
+ _exchange, FieldTable.convertToMap(_bindingArgs));
_store.bindQueue(binding);
_store.unbindQueue(binding);
@@ -173,7 +192,7 @@ public class DurableConfigurationStoreTest extends QpidTestCase
_store.createQueue(queue);
reopenStore();
- verify(_queueRecoveryHandler).queue(_queueId, getName(), getName() + "Owner", true, null);
+ verify(_queueRecoveryHandler).queue(_queueId, getName(), getName() + "Owner", true, null, null);
}
public void testCreateQueueAMQQueueFieldTable() throws Exception
@@ -187,10 +206,29 @@ public class DurableConfigurationStoreTest extends QpidTestCase
_store.createQueue(queue, arguments);
reopenStore();
- verify(_queueRecoveryHandler).queue(_queueId, getName(), getName() + "Owner", true, arguments);
+ verify(_queueRecoveryHandler).queue(_queueId, getName(), getName() + "Owner", true, arguments, null);
}
- public void testUpdateQueue() throws Exception
+ public void testCreateQueueAMQQueueWithAlternateExchange() throws Exception
+ {
+ Exchange alternateExchange = createTestAlternateExchange();
+
+ AMQQueue queue = createTestQueue(getName(), getName() + "Owner", true, alternateExchange);
+ _store.createQueue(queue);
+
+ reopenStore();
+ verify(_queueRecoveryHandler).queue(_queueId, getName(), getName() + "Owner", true, null, alternateExchange.getId());
+ }
+
+ private Exchange createTestAlternateExchange()
+ {
+ UUID exchUuid = UUID.randomUUID();
+ Exchange alternateExchange = mock(Exchange.class);
+ when(alternateExchange.getId()).thenReturn(exchUuid);
+ return alternateExchange;
+ }
+
+ public void testUpdateQueueExclusivity() throws Exception
{
// create queue
AMQQueue queue = createTestQueue(getName(), getName() + "Owner", true);
@@ -205,7 +243,26 @@ public class DurableConfigurationStoreTest extends QpidTestCase
_store.updateQueue(queue);
reopenStore();
- verify(_queueRecoveryHandler).queue(_queueId, getName(), getName() + "Owner", false, arguments);
+ verify(_queueRecoveryHandler).queue(_queueId, getName(), getName() + "Owner", false, arguments, null);
+ }
+
+ public void testUpdateQueueAlternateExchange() throws Exception
+ {
+ // create queue
+ AMQQueue queue = createTestQueue(getName(), getName() + "Owner", true);
+ Map<String, Object> attributes = new HashMap<String, Object>();
+ attributes.put("x-qpid-dlq-enabled", Boolean.TRUE);
+ attributes.put("x-qpid-maximum-delivery-count", new Integer(10));
+ FieldTable arguments = FieldTable.convertToFieldTable(attributes);
+ _store.createQueue(queue, arguments);
+
+ // update the queue to have exclusive=false
+ Exchange alternateExchange = createTestAlternateExchange();
+ queue = createTestQueue(getName(), getName() + "Owner", false, alternateExchange);
+ _store.updateQueue(queue);
+
+ reopenStore();
+ verify(_queueRecoveryHandler).queue(_queueId, getName(), getName() + "Owner", false, arguments, alternateExchange.getId());
}
public void testRemoveQueue() throws Exception
@@ -222,17 +279,23 @@ public class DurableConfigurationStoreTest extends QpidTestCase
_store.removeQueue(queue);
reopenStore();
verify(_queueRecoveryHandler, never()).queue(any(UUID.class), anyString(), anyString(), anyBoolean(),
- any(FieldTable.class));
+ any(FieldTable.class), any(UUID.class));
}
private AMQQueue createTestQueue(String queueName, String queueOwner, boolean exclusive) throws AMQStoreException
{
+ return createTestQueue(queueName, queueOwner, exclusive, null);
+ }
+
+ private AMQQueue createTestQueue(String queueName, String queueOwner, boolean exclusive, Exchange alternateExchange) throws AMQStoreException
+ {
AMQQueue queue = mock(AMQQueue.class);
when(queue.getName()).thenReturn(queueName);
when(queue.getNameShortString()).thenReturn(AMQShortString.valueOf(queueName));
when(queue.getOwner()).thenReturn(AMQShortString.valueOf(queueOwner));
when(queue.isExclusive()).thenReturn(exclusive);
when(queue.getId()).thenReturn(_queueId);
+ when(queue.getAlternateExchange()).thenReturn(alternateExchange);
return queue;
}
@@ -262,14 +325,14 @@ public class DurableConfigurationStoreTest extends QpidTestCase
protected MessageStore createStore() throws Exception
{
- String storeFactoryClass = System.getProperty(MS_FACTORY_CLASS_NAME_KEY);
- if (storeFactoryClass == null)
+ String storeClass = System.getProperty(MESSAGE_STORE_CLASS_NAME_KEY);
+ if (storeClass == null)
{
- storeFactoryClass = DerbyMessageStoreFactory.class.getName();
+ storeClass = DerbyMessageStore.class.getName();
}
CurrentActor.set(new TestLogActor(new SystemOutMessageLogger()));
- MessageStoreFactory factory = (MessageStoreFactory) Class.forName(storeFactoryClass).newInstance();
- return factory.createMessageStore();
+ MessageStore messageStore = (MessageStore) Class.forName(storeClass).newInstance();
+ return messageStore;
}
public void testRecordXid() throws Exception
@@ -297,7 +360,7 @@ public class DurableConfigurationStoreTest extends QpidTestCase
private Record getTestRecord(long messageNumber)
{
- UUID queueId1 = UUIDGenerator.generateUUID();
+ UUID queueId1 = UUIDGenerator.generateRandomUUID();
TransactionLogResource queue1 = mock(TransactionLogResource.class);
when(queue1.getId()).thenReturn(queueId1);
EnqueableMessage message1 = mock(EnqueableMessage.class);
diff --git a/java/broker/src/test/java/org/apache/qpid/server/store/MessageStoreQuotaEventsTestBase.java b/java/broker/src/test/java/org/apache/qpid/server/store/MessageStoreQuotaEventsTestBase.java
new file mode 100644
index 0000000000..f1976ecee3
--- /dev/null
+++ b/java/broker/src/test/java/org/apache/qpid/server/store/MessageStoreQuotaEventsTestBase.java
@@ -0,0 +1,178 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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;
+
+import java.io.File;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+
+import org.apache.commons.configuration.XMLConfiguration;
+import org.apache.log4j.Logger;
+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.server.message.EnqueableMessage;
+import org.apache.qpid.server.message.MessageMetaData;
+import org.apache.qpid.test.utils.QpidTestCase;
+import org.apache.qpid.util.FileUtils;
+
+public abstract class MessageStoreQuotaEventsTestBase extends QpidTestCase implements EventListener, TransactionLogResource
+{
+ private static final Logger _logger = Logger.getLogger(MessageStoreQuotaEventsTestBase.class);
+
+ protected static final byte[] MESSAGE_DATA = new byte[32 * 1024];
+
+ private MessageStore _store;
+ private File _storeLocation;
+
+ private List<Event> _events;
+ private UUID _transactionResource;
+
+ protected abstract MessageStore createStore() throws Exception;
+
+ protected abstract void applyStoreSpecificConfiguration(XMLConfiguration config);
+
+ protected abstract int getNumberOfMessagesToFillStore();
+
+ @Override
+ public void setUp() throws Exception
+ {
+ super.setUp();
+
+ _storeLocation = new File(new File(TMP_FOLDER), getTestName());
+ FileUtils.delete(_storeLocation, true);
+
+ XMLConfiguration config = new XMLConfiguration();
+ config.addProperty("environment-path", _storeLocation.getAbsolutePath());
+ applyStoreSpecificConfiguration(config);
+
+ _store = createStore();
+ _store.configureConfigStore("test", null, config);
+
+ _transactionResource = UUID.randomUUID();
+ _events = new ArrayList<Event>();
+ _store.addEventListener(this, Event.PERSISTENT_MESSAGE_SIZE_OVERFULL, Event.PERSISTENT_MESSAGE_SIZE_UNDERFULL);
+ }
+
+ @Override
+ public void tearDown() throws Exception
+ {
+ super.tearDown();
+ FileUtils.delete(_storeLocation, true);
+ }
+
+ public void testOverflow() throws Exception
+ {
+ Transaction transaction = _store.newTransaction();
+
+ List<EnqueableMessage> messages = new ArrayList<EnqueableMessage>();
+ for (int i = 0; i < getNumberOfMessagesToFillStore(); i++)
+ {
+ EnqueableMessage m = addMessage(i);
+ messages.add(m);
+ transaction.enqueueMessage(this, m);
+ }
+ transaction.commitTran();
+
+ assertEvent(1, Event.PERSISTENT_MESSAGE_SIZE_OVERFULL);
+
+ for (EnqueableMessage m : messages)
+ {
+ m.getStoredMessage().remove();
+ }
+
+ assertEvent(2, Event.PERSISTENT_MESSAGE_SIZE_UNDERFULL);
+ }
+
+ protected EnqueableMessage addMessage(long id)
+ {
+ MessagePublishInfo pubInfoBody = new MessagePublishInfoImpl(new AMQShortString(getName()), false, false,
+ new AMQShortString(getName()));
+ BasicContentHeaderProperties props = new BasicContentHeaderProperties();
+ props.setDeliveryMode(Integer.valueOf(BasicContentHeaderProperties.PERSISTENT).byteValue());
+ props.setContentType(getTestName());
+
+ MethodRegistry methodRegistry = MethodRegistry.getMethodRegistry(ProtocolVersion.v0_9);
+ int classForBasic = methodRegistry.createBasicQosOkBody().getClazz();
+ ContentHeaderBody contentHeaderBody = new ContentHeaderBody(classForBasic, 1, props, MESSAGE_DATA.length);
+
+ MessageMetaData metaData = new MessageMetaData(pubInfoBody, contentHeaderBody, 1);
+ StoredMessage<MessageMetaData> handle = _store.addMessage(metaData);
+ handle.addContent(0, ByteBuffer.wrap(MESSAGE_DATA));
+ TestMessage message = new TestMessage(id, handle);
+ return message;
+ }
+
+ @Override
+ public void event(Event event)
+ {
+ _logger.debug("Test event listener received event " + event);
+ _events.add(event);
+ }
+
+ private void assertEvent(int expectedNumberOfEvents, Event... expectedEvents)
+ {
+ assertEquals("Unexpected number of events received ", expectedNumberOfEvents, _events.size());
+ for (Event event : expectedEvents)
+ {
+ assertTrue("Expected event is not found:" + event, _events.contains(event));
+ }
+ }
+
+ @Override
+ public UUID getId()
+ {
+ return _transactionResource;
+ }
+
+ private static class TestMessage implements EnqueableMessage
+ {
+ private final StoredMessage<?> _handle;
+ private final long _messageId;
+
+ public TestMessage(long messageId, StoredMessage<?> handle)
+ {
+ _messageId = messageId;
+ _handle = handle;
+ }
+
+ public long getMessageNumber()
+ {
+ return _messageId;
+ }
+
+ public boolean isPersistent()
+ {
+ return true;
+ }
+
+ public StoredMessage<?> getStoredMessage()
+ {
+ return _handle;
+ }
+ }
+}
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 3fb0776083..a1536565ad 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
@@ -59,7 +59,6 @@ import java.io.File;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import java.util.UUID;
/**
* This tests the MessageStores by using the available interfaces.
@@ -100,10 +99,10 @@ public class MessageStoreTest extends InternalBrokerBaseCase
{
super.setUp();
- String storePath = System.getProperty("QPID_WORK") + "/" + getName();
+ String storePath = System.getProperty("QPID_WORK") + File.separator + getName();
_config = new PropertiesConfiguration();
- _config.addProperty("store.factoryclass", getTestProfileMessageStoreFactoryClassName());
+ _config.addProperty("store.class", getTestProfileMessageStoreClassName());
_config.addProperty("store.environment-path", storePath);
cleanup(new File(storePath));
@@ -268,15 +267,9 @@ public class MessageStoreTest extends InternalBrokerBaseCase
//Validate normally expected properties of Queues/Topics
validateDurableQueueProperties();
- //Update the durable exclusive queue's exclusivity and verify it is persisted and recovered correctly
+ //Update the durable exclusive queue's exclusivity
setQueueExclusivity(false);
validateQueueExclusivityProperty(false);
-
- //Reload the Virtualhost to recover the queues again
- reloadVirtualHost();
-
- //verify the change was persisted and recovered correctly
- validateQueueExclusivityProperty(false);
}
/**
@@ -702,8 +695,8 @@ public class MessageStoreTest extends InternalBrokerBaseCase
//Ideally we would be able to use the QueueDeclareHandler here.
try
{
- queue = AMQQueueFactory.createAMQQueueImpl(queueName, durable, queueOwner, false, exclusive,
- getVirtualHost(), queueArguments);
+ queue = AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), queueName.asString(), durable, queueOwner.asString(), false, exclusive,
+ getVirtualHost(), FieldTable.convertToMap(queueArguments));
validateQueueProperties(queue, usePriority, durable, exclusive, lastValueQueue);
@@ -741,7 +734,7 @@ public class MessageStoreTest extends InternalBrokerBaseCase
try
{
- exchange = type.newInstance(UUIDGenerator.generateUUID(), getVirtualHost(), name, durable, 0, false);
+ exchange = type.newInstance(UUIDGenerator.generateRandomUUID(), getVirtualHost(), name, durable, 0, false);
}
catch (AMQException e)
{
diff --git a/java/broker/src/test/java/org/apache/qpid/server/store/OperationalLoggingListenerTest.java b/java/broker/src/test/java/org/apache/qpid/server/store/OperationalLoggingListenerTest.java
index 42746f9119..c309dad5eb 100644
--- a/java/broker/src/test/java/org/apache/qpid/server/store/OperationalLoggingListenerTest.java
+++ b/java/broker/src/test/java/org/apache/qpid/server/store/OperationalLoggingListenerTest.java
@@ -1,3 +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.
+ */
package org.apache.qpid.server.store;
import java.util.ArrayList;
@@ -12,22 +28,6 @@ import org.apache.qpid.server.logging.messages.ConfigStoreMessages;
import org.apache.qpid.server.logging.messages.MessageStoreMessages;
import org.apache.qpid.server.logging.messages.TransactionLogMessages;
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * <p/>
- * http://www.apache.org/licenses/LICENSE-2.0
- * <p/>
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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 OperationalLoggingListenerTest extends TestCase
{
@@ -73,11 +73,11 @@ public class OperationalLoggingListenerTest extends TestCase
}
- messageStore.attainState(State.CONFIGURING);
+ messageStore.attainState(State.INITIALISING);
assertEquals("Unexpected number of operational log messages on configuring", 1, messages.size());
assertEquals(messages.remove(0).toString(), ConfigStoreMessages.CREATED().toString());
- messageStore.attainState(State.CONFIGURED);
+ messageStore.attainState(State.INITIALISED);
assertEquals("Unexpected number of operational log messages on CONFIGURED", setStoreLocation ? 3 : 2, messages.size());
assertEquals(messages.remove(0).toString(), MessageStoreMessages.CREATED().toString());
assertEquals(messages.remove(0).toString(), TransactionLogMessages.CREATED().toString());
@@ -86,7 +86,7 @@ public class OperationalLoggingListenerTest extends TestCase
assertEquals(messages.remove(0).toString(), MessageStoreMessages.STORE_LOCATION(STORE_LOCATION).toString());
}
- messageStore.attainState(State.RECOVERING);
+ messageStore.attainState(State.ACTIVATING);
assertEquals("Unexpected number of operational log messages on RECOVERING", 1, messages.size());
assertEquals(messages.remove(0).toString(), MessageStoreMessages.RECOVERY_START().toString());
@@ -147,6 +147,12 @@ public class OperationalLoggingListenerTest extends TestCase
{
_eventManager.addEventListener(eventListener, events);
}
+
+ @Override
+ public String getStoreType()
+ {
+ return "TEST";
+ }
}
private static class TestActor implements LogActor
diff --git a/java/broker/src/test/java/org/apache/qpid/server/store/StateManagerTest.java b/java/broker/src/test/java/org/apache/qpid/server/store/StateManagerTest.java
index 97c88ca1d3..18efb976eb 100644
--- a/java/broker/src/test/java/org/apache/qpid/server/store/StateManagerTest.java
+++ b/java/broker/src/test/java/org/apache/qpid/server/store/StateManagerTest.java
@@ -45,8 +45,8 @@ public class StateManagerTest extends TestCase implements EventListener
{
assertEquals(State.INITIAL, _manager.getState());
- _manager.stateTransition(State.INITIAL, State.CONFIGURING);
- assertEquals(State.CONFIGURING, _manager.getState());
+ _manager.attainState(State.INITIALISING);
+ assertEquals(State.INITIALISING, _manager.getState());
}
public void testStateTransitionDisallowed()
@@ -55,7 +55,7 @@ public class StateManagerTest extends TestCase implements EventListener
try
{
- _manager.stateTransition(State.ACTIVE, State.CLOSING);
+ _manager.attainState(State.CLOSING);
fail("Exception not thrown");
}
catch (IllegalStateException e)
@@ -98,22 +98,29 @@ public class StateManagerTest extends TestCase implements EventListener
public void testValidStateTransitions()
{
assertEquals(State.INITIAL, _manager.getState());
- performValidTransition(StateManager.CONFIGURE);
- performValidTransition(StateManager.CONFIGURE_COMPLETE);
- performValidTransition(StateManager.RECOVER);
+ performValidTransition(StateManager.INITIALISE);
+ performValidTransition(StateManager.INITALISE_COMPLETE);
performValidTransition(StateManager.ACTIVATE);
+ performValidTransition(StateManager.ACTIVATE_COMPLETE);
performValidTransition(StateManager.QUIESCE);
performValidTransition(StateManager.QUIESCE_COMPLETE);
performValidTransition(StateManager.RESTART);
- performValidTransition(StateManager.ACTIVATE);
+ performValidTransition(StateManager.ACTIVATE_COMPLETE);
performValidTransition(StateManager.CLOSE_ACTIVE);
performValidTransition(StateManager.CLOSE_COMPLETE);
+
+ _manager = new StateManager(this);
+ assertEquals(State.INITIAL, _manager.getState());
+ performValidTransition(StateManager.INITIALISE);
+ performValidTransition(StateManager.INITALISE_COMPLETE);
+ performValidTransition(StateManager.CLOSE_INITIALISED);
+ performValidTransition(StateManager.CLOSE_COMPLETE);
_manager = new StateManager(this);
- performValidTransition(StateManager.CONFIGURE);
- performValidTransition(StateManager.CONFIGURE_COMPLETE);
- performValidTransition(StateManager.RECOVER);
+ performValidTransition(StateManager.INITIALISE);
+ performValidTransition(StateManager.INITALISE_COMPLETE);
performValidTransition(StateManager.ACTIVATE);
+ performValidTransition(StateManager.ACTIVATE_COMPLETE);
performValidTransition(StateManager.QUIESCE);
performValidTransition(StateManager.QUIESCE_COMPLETE);
performValidTransition(StateManager.CLOSE_QUIESCED);
@@ -132,54 +139,50 @@ public class StateManagerTest extends TestCase implements EventListener
{
assertEquals(State.INITIAL, _manager.getState());
-
- performInvalidTransitions(StateManager.CONFIGURE, State.CONFIGURED);
- performInvalidTransitions(StateManager.CONFIGURE_COMPLETE, State.RECOVERING);
- performInvalidTransitions(StateManager.RECOVER, State.ACTIVE);
- performInvalidTransitions(StateManager.ACTIVATE, State.QUIESCING, State.CLOSING);
+ performInvalidTransitions(StateManager.INITIALISE, State.INITIALISED);
+ performInvalidTransitions(StateManager.INITALISE_COMPLETE, State.ACTIVATING, State.CLOSING);
+ performInvalidTransitions(StateManager.ACTIVATE, State.ACTIVE);
+ performInvalidTransitions(StateManager.ACTIVATE_COMPLETE, State.QUIESCING, State.CLOSING, State.INITIALISED);
performInvalidTransitions(StateManager.QUIESCE, State.QUIESCED);
- performInvalidTransitions(StateManager.QUIESCE_COMPLETE, State.RECOVERING, State.CLOSING);
+ performInvalidTransitions(StateManager.QUIESCE_COMPLETE, State.ACTIVATING, State.CLOSING);
performInvalidTransitions(StateManager.CLOSE_QUIESCED, State.CLOSED);
performInvalidTransitions(StateManager.CLOSE_COMPLETE);
-
-
-
}
- private void performInvalidTransitions(StateManager.Transition preTransition, State... validTransitions)
+ private void performInvalidTransitions(StateManager.Transition preTransition, State... validEndStates)
{
if(preTransition != null)
{
performValidTransition(preTransition);
}
- EnumSet<State> nextStates = EnumSet.allOf(State.class);
+ EnumSet<State> endStates = EnumSet.allOf(State.class);
- if(validTransitions != null)
+ if(validEndStates != null)
{
- for(State state: validTransitions)
+ for(State state: validEndStates)
{
- nextStates.remove(state);
+ endStates.remove(state);
}
}
- for(State nextState : nextStates)
+ for(State invalidEndState : endStates)
{
- performInvalidStateTransition(nextState);
+ performInvalidStateTransition(invalidEndState);
}
}
- private void performInvalidStateTransition(State state)
+ private void performInvalidStateTransition(State invalidEndState)
{
try
{
_event = null;
State startState = _manager.getState();
- _manager.attainState(state);
- fail("Invalid state transition performed: " + startState + " to " + state);
+ _manager.attainState(invalidEndState);
+ fail("Invalid state transition performed: " + startState + " to " + invalidEndState);
}
catch(IllegalStateException e)
{
@@ -188,6 +191,7 @@ public class StateManagerTest extends TestCase implements EventListener
assertNull("No event should have be fired", _event);
}
+ @Override
public void event(Event event)
{
_event = event;
diff --git a/java/broker/src/test/java/org/apache/qpid/server/store/derby/DerbyMessageStoreQuotaEventsTest.java b/java/broker/src/test/java/org/apache/qpid/server/store/derby/DerbyMessageStoreQuotaEventsTest.java
new file mode 100644
index 0000000000..5d316fca43
--- /dev/null
+++ b/java/broker/src/test/java/org/apache/qpid/server/store/derby/DerbyMessageStoreQuotaEventsTest.java
@@ -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.
+ *
+ */
+package org.apache.qpid.server.store.derby;
+
+import org.apache.commons.configuration.XMLConfiguration;
+import org.apache.log4j.Logger;
+import org.apache.qpid.server.store.MessageStore;
+import org.apache.qpid.server.store.MessageStoreQuotaEventsTestBase;
+
+public class DerbyMessageStoreQuotaEventsTest extends MessageStoreQuotaEventsTestBase
+{
+ private static final Logger _logger = Logger.getLogger(DerbyMessageStoreQuotaEventsTest.class);
+
+ private static final int NUMBER_OF_MESSAGES_TO_OVERFILL_STORE = 10;
+
+ /**
+ * Estimated using an assumption that a physical disk space occupied by a
+ * message is 3 times bigger then a message size
+ */
+ private static final int OVERFULL_SIZE = (int) (MESSAGE_DATA.length * 3 * NUMBER_OF_MESSAGES_TO_OVERFILL_STORE * 0.8);
+
+ private static final int UNDERFULL_SIZE = (int) (OVERFULL_SIZE * 0.8);
+
+ @Override
+ protected int getNumberOfMessagesToFillStore()
+ {
+ return NUMBER_OF_MESSAGES_TO_OVERFILL_STORE;
+ }
+
+ @Override
+ protected void applyStoreSpecificConfiguration(XMLConfiguration config)
+ {
+ _logger.debug("Applying store specific config. overfull-sze=" + OVERFULL_SIZE + ", underfull-size=" + UNDERFULL_SIZE);
+
+ config.addProperty("overfull-size", OVERFULL_SIZE);
+ config.addProperty("underfull-size", UNDERFULL_SIZE);
+ }
+
+ @Override
+ protected MessageStore createStore() throws Exception
+ {
+ return new DerbyMessageStore();
+ }
+}
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 5ba9c0c015..8c5d2684ff 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
@@ -1,5 +1,3 @@
-package org.apache.qpid.server.subscription;
-
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
@@ -21,16 +19,24 @@ package org.apache.qpid.server.subscription;
*
*/
+package org.apache.qpid.server.subscription;
+
import org.apache.qpid.AMQException;
import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpid.server.AMQChannel;
+import org.apache.qpid.protocol.AMQConstant;
import org.apache.qpid.server.logging.LogActor;
+import org.apache.qpid.server.logging.LogSubject;
+import org.apache.qpid.server.message.InboundMessage;
+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.QueueEntry;
import org.apache.qpid.server.queue.QueueEntry.SubscriptionAcquiredState;
+import org.apache.qpid.server.stats.StatisticsCounter;
import java.util.ArrayList;
import java.util.List;
+import java.util.UUID;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
@@ -42,7 +48,7 @@ public class MockSubscription implements Subscription
private AMQShortString tag = new AMQShortString("mocktag");
private AMQQueue queue = null;
private StateListener _listener = null;
- private AMQQueue.Context _queueContext = null;
+ private volatile AMQQueue.Context _queueContext = null;
private State _state = State.ACTIVE;
private ArrayList<QueueEntry> messages = new ArrayList<QueueEntry>();
private final Lock _stateChangeLock = new ReentrantLock();
@@ -76,19 +82,9 @@ public class MockSubscription implements Subscription
_state = State.CLOSED;
}
- public boolean filtersMessages()
- {
- return false;
- }
-
- public AMQChannel getChannel()
- {
- return null;
- }
-
- public AMQShortString getConsumerTag()
+ public String getConsumerName()
{
- return tag;
+ return tag == null ? null : tag.asString();
}
public long getSubscriptionID()
@@ -121,11 +117,36 @@ public class MockSubscription implements Subscription
return false;
}
+ public long getBytesOut()
+ {
+ return 0; // TODO - Implement
+ }
+
+ public long getMessagesOut()
+ {
+ return 0; // TODO - Implement
+ }
+
+ public long getUnacknowledgedBytes()
+ {
+ return 0; // TODO - Implement
+ }
+
+ public long getUnacknowledgedMessages()
+ {
+ return 0; // TODO - Implement
+ }
+
public AMQQueue getQueue()
{
return queue;
}
+ public AMQSessionModel getSessionModel()
+ {
+ return new MockSessionModel();
+ }
+
public boolean trySendLock()
{
return _stateChangeLock.tryLock();
@@ -154,11 +175,6 @@ public class MockSubscription implements Subscription
return _isActive ;
}
- public void confirmAutoClose()
- {
-
- }
-
public void set(String key, Object value)
{
}
@@ -173,11 +189,6 @@ public class MockSubscription implements Subscription
return false;
}
- public boolean isBrowser()
- {
- return false;
- }
-
public boolean isClosed()
{
return _closed;
@@ -207,10 +218,6 @@ public class MockSubscription implements Subscription
_stateChangeLock.unlock();
}
- public void resend(QueueEntry entry) throws AMQException
- {
- }
-
public void onDequeue(QueueEntry queueEntry)
{
}
@@ -232,7 +239,6 @@ public class MockSubscription implements Subscription
messages.add(entry);
}
- @Override
public void flushBatched()
{
@@ -249,7 +255,7 @@ public class MockSubscription implements Subscription
}
public void setNoLocal(boolean noLocal)
- {
+ {
}
public void setStateListener(StateListener listener)
@@ -285,4 +291,259 @@ public class MockSubscription implements Subscription
{
_isActive = isActive;
}
+
+ private static class MockSessionModel implements AMQSessionModel
+ {
+
+ @Override
+ public int compareTo(AMQSessionModel o)
+ {
+ return 0;
+ }
+
+ @Override
+ public UUID getQMFId()
+ {
+ return null;
+ }
+
+ @Override
+ public AMQConnectionModel getConnectionModel()
+ {
+ return new MockConnectionModel();
+ }
+
+ @Override
+ public String getClientID()
+ {
+ return null;
+ }
+
+ @Override
+ public void close() throws AMQException
+ {
+ }
+
+ @Override
+ public LogSubject getLogSubject()
+ {
+ return null;
+ }
+
+ @Override
+ public void checkTransactionStatus(long openWarn, long openClose,
+ long idleWarn, long idleClose) throws AMQException
+ {
+ }
+
+ @Override
+ public void block(AMQQueue queue)
+ {
+ }
+
+ @Override
+ public void unblock(AMQQueue queue)
+ {
+ }
+
+ @Override
+ public void block()
+ {
+ }
+
+ @Override
+ public void unblock()
+ {
+ }
+
+ @Override
+ public boolean getBlocking()
+ {
+ return false;
+ }
+
+ @Override
+ public boolean onSameConnection(InboundMessage inbound)
+ {
+ return false;
+ }
+
+ @Override
+ public int getUnacknowledgedMessageCount()
+ {
+ return 0;
+ }
+
+ @Override
+ public Long getTxnCount()
+ {
+ return null;
+ }
+
+ @Override
+ public Long getTxnStart()
+ {
+ return null;
+ }
+
+ @Override
+ public Long getTxnCommits()
+ {
+ return null;
+ }
+
+ @Override
+ public Long getTxnRejects()
+ {
+ return null;
+ }
+
+ @Override
+ public int getChannelId()
+ {
+ return 0;
+ }
+
+ @Override
+ public int getConsumerCount()
+ {
+ return 0;
+ }
+ }
+
+ private static class MockConnectionModel implements AMQConnectionModel
+ {
+ @Override
+ public void initialiseStatistics()
+ {
+ }
+
+ @Override
+ public void registerMessageReceived(long messageSize, long timestamp)
+ {
+ }
+
+ @Override
+ public void registerMessageDelivered(long messageSize)
+ {
+ }
+
+ @Override
+ public StatisticsCounter getMessageDeliveryStatistics()
+ {
+ return null;
+ }
+
+ @Override
+ public StatisticsCounter getMessageReceiptStatistics()
+ {
+ return null;
+ }
+
+ @Override
+ public StatisticsCounter getDataDeliveryStatistics()
+ {
+ return null;
+ }
+
+ @Override
+ public StatisticsCounter getDataReceiptStatistics()
+ {
+ return null;
+ }
+
+ @Override
+ public void resetStatistics()
+ {
+
+ }
+
+ @Override
+ public void close(AMQConstant cause, String message)
+ throws AMQException
+ {
+ }
+
+ @Override
+ public void closeSession(AMQSessionModel session, AMQConstant cause,
+ String message) throws AMQException
+ {
+ }
+
+ @Override
+ public long getConnectionId()
+ {
+ return 0;
+ }
+
+ @Override
+ public List<AMQSessionModel> getSessionModels()
+ {
+ return null;
+ }
+
+ @Override
+ public void block()
+ {
+ }
+
+ @Override
+ public void unblock()
+ {
+ }
+
+ @Override
+ public LogSubject getLogSubject()
+ {
+ return null;
+ }
+
+ @Override
+ public String getUserName()
+ {
+ return null;
+ }
+
+ @Override
+ public boolean isSessionNameUnique(byte[] name)
+ {
+ return false;
+ }
+
+ @Override
+ public String getRemoteAddressString()
+ {
+ return "remoteAddress:1234";
+ }
+
+ @Override
+ public String getClientId()
+ {
+ return null;
+ }
+
+ @Override
+ public String getClientVersion()
+ {
+ return null;
+ }
+
+ @Override
+ public String getPrincipalAsString()
+ {
+ return null;
+ }
+
+ @Override
+ public long getSessionCountLimit()
+ {
+ return 0;
+ }
+
+ @Override
+ public long getLastIoTime()
+ {
+ return 0;
+ }
+ }
}
diff --git a/java/broker/src/test/java/org/apache/qpid/server/transport/ServerConnectionMBeanTest.java b/java/broker/src/test/java/org/apache/qpid/server/transport/ServerConnectionMBeanTest.java
deleted file mode 100644
index dcb3692cf5..0000000000
--- a/java/broker/src/test/java/org/apache/qpid/server/transport/ServerConnectionMBeanTest.java
+++ /dev/null
@@ -1,230 +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.transport;
-
-import org.apache.qpid.management.common.mbeans.ManagedConnection;
-import org.apache.qpid.server.configuration.MockConnectionConfig;
-import org.apache.qpid.server.registry.ApplicationRegistry;
-import org.apache.qpid.server.util.InternalBrokerBaseCase;
-import org.apache.qpid.server.virtualhost.VirtualHost;
-import org.apache.qpid.transport.Binary;
-import org.apache.qpid.transport.Connection;
-import org.apache.qpid.transport.Session;
-
-import javax.management.JMException;
-import javax.management.openmbean.CompositeData;
-import javax.management.openmbean.TabularData;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Date;
-import java.util.List;
-import java.util.UUID;
-import java.util.concurrent.atomic.AtomicLong;
-
-public class ServerConnectionMBeanTest extends InternalBrokerBaseCase
-{
- private ServerConnection _serverConnection;
- private ServerSessionMock _serverSession;
- private ServerConnectionMBean _mbean;
- private List<Session> _sessions = new ArrayList<Session>();
-
- @Override
- public void setUp() throws Exception
- {
- super.setUp();
-
- final VirtualHost vhost = ApplicationRegistry.getInstance().getVirtualHostRegistry().getVirtualHost("test");
- _serverConnection = new ServerConnection(1)
- {
- protected Collection<Session> getChannels()
- {
- return _sessions;
- }
- public Session getSession(int channelId)
- {
- for(Session session : _sessions)
- {
- if (session.getChannel() == channelId)
- {
- return session;
- }
- }
- return null;
- }
- @Override
- public AtomicLong getLastIoTime()
- {
- return new AtomicLong(1);
- }
- };
- final MockConnectionConfig config = new MockConnectionConfig(UUID.randomUUID(), null, null,
- false, 1, vhost, "address", Boolean.TRUE, Boolean.TRUE, Boolean.TRUE,
- "authid", "remoteProcessName", new Integer(1967), new Integer(1970), vhost.getConfigStore(), Boolean.FALSE);
- _serverConnection.setConnectionConfig(config);
- _serverConnection.setVirtualHost(vhost);
- _serverConnection.setConnectionDelegate(new ServerConnectionDelegate(getRegistry(), ""));
- _serverSession = new ServerSessionMock(_serverConnection, 1);
- _mbean = (ServerConnectionMBean) _serverConnection.getManagedObject();
- }
-
- public void testChannels() throws Exception
- {
- // check the channel count is correct
- TabularData tabularData = _mbean.channels();
-
- int channelCount = tabularData.size();
- assertEquals("Unexpected number of channels",1,channelCount);
- _sessions.add(new ServerSession(_serverConnection, new ServerSessionDelegate(),
- new Binary(getName().getBytes()), 2 , _serverConnection.getConfig()));
-
- channelCount = _mbean.channels().size();
- assertEquals("Unexpected number of channels",2,channelCount);
-
- final CompositeData chanresult = tabularData.get(new Integer[]{1});
- assertNotNull(chanresult);
- assertEquals("Unexpected channel id", new Integer(1),(Integer)chanresult.get(ManagedConnection.CHAN_ID));
- assertNull("Unexpected default queue", chanresult.get(ManagedConnection.DEFAULT_QUEUE));
- assertFalse("Unexpected transactional flag", (Boolean)chanresult.get(ManagedConnection.TRANSACTIONAL));
- assertFalse("Flow should have been blocked", (Boolean)chanresult.get(ManagedConnection.FLOW_BLOCKED));
- assertEquals("Unexpected unack'd count", new Integer(1967), (Integer)chanresult.get(ManagedConnection.UNACKED_COUNT));
- }
-
- public void testMaxChannels() throws Exception
- {
- _serverConnection.getConnectionDelegate().setChannelMax(10001);
- assertEquals("Max channels not got correctly", new Long(10001), _mbean.getMaximumNumberOfChannels());
- }
-
- public void testRollback() throws Exception
- {
- _mbean.rollbackTransactions(1);
- assertFalse("Rollback performed despite not being transacted", _serverSession.isRolledback());
-
- _serverSession.setTransactional(true);
- _mbean.rollbackTransactions(1);
- assertTrue("Rollback not performed", _serverSession.isRolledback());
-
- try
- {
- _mbean.rollbackTransactions(2);
- fail("Exception expected");
- }
- catch (JMException jme)
- {
- //pass
- }
- }
-
- public void testCommit() throws Exception
- {
- _mbean.commitTransactions(1);
- assertFalse("Commit performed despite not being transacted", _serverSession.isCommitted());
-
- _serverSession.setTransactional(true);
- _mbean.commitTransactions(1);
- assertTrue("Commit not performed", _serverSession.isCommitted());
-
- try
- {
- _mbean.commitTransactions(2);
- fail("Exception expected");
- }
- catch (JMException jme)
- {
- //pass
- }
- }
-
- public void testGetName()
- {
- assertEquals("Unexpected Object Instance Name", "\"address\"", _mbean.getObjectInstanceName());
- }
-
- public void testEnableStatistics()
- {
- assertFalse("Unexpected statistics enable flag", _mbean.isStatisticsEnabled());
- _mbean.setStatisticsEnabled(true);
- assertTrue("Unexpected statistics enable flag", _mbean.isStatisticsEnabled());
- }
-
- public void testLastIOTime()
- {
- assertEquals("Unexpected last IO time", new Date(1), _mbean.getLastIoTime());
- }
-
- private class ServerSessionMock extends ServerSession
- {
- private int _channelId = 0;
- private boolean _committed = false;
- private boolean _rolledback = false;
- private boolean _transacted = false;
-
- ServerSessionMock(Connection connection, int channelId)
- {
- super(connection, new ServerSessionDelegate(), new Binary(String.valueOf(channelId).getBytes()), 1 , _serverConnection.getConfig());
- _channelId = channelId;
- _sessions.add(this);
- }
-
- public int getChannel()
- {
- return _channelId;
- }
-
- @Override
- public void commit()
- {
- _committed = true;
- }
-
- @Override
- public void rollback()
- {
- _rolledback = true;
- }
-
- public boolean isCommitted()
- {
- return _committed;
- }
-
- public boolean isRolledback()
- {
- return _rolledback;
- }
-
- @Override
- public int getUnacknowledgedMessageCount()
- {
- return 1967;
- }
-
- public boolean isTransactional()
- {
- return _transacted;
- }
-
- public void setTransactional(boolean transacted)
- {
- _transacted = transacted;
- }
- }
-}
diff --git a/java/broker/src/test/java/org/apache/qpid/server/txn/AsyncAutoCommitTransactionTest.java b/java/broker/src/test/java/org/apache/qpid/server/txn/AsyncAutoCommitTransactionTest.java
new file mode 100644
index 0000000000..1aa91fa98a
--- /dev/null
+++ b/java/broker/src/test/java/org/apache/qpid/server/txn/AsyncAutoCommitTransactionTest.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.server.txn;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.*;
+
+import java.util.Collections;
+
+import org.apache.qpid.server.message.EnqueableMessage;
+import org.apache.qpid.server.queue.BaseQueue;
+import org.apache.qpid.server.store.MessageStore;
+import org.apache.qpid.server.store.StoreFuture;
+import org.apache.qpid.server.store.Transaction;
+import org.apache.qpid.server.txn.AsyncAutoCommitTransaction.FutureRecorder;
+import org.apache.qpid.server.txn.ServerTransaction.Action;
+import org.apache.qpid.test.utils.QpidTestCase;
+
+public class AsyncAutoCommitTransactionTest extends QpidTestCase
+{
+ private static final String STRICT_ORDER_SYSTEM_PROPERTY = AsyncAutoCommitTransaction.QPID_STRICT_ORDER_WITH_MIXED_DELIVERY_MODE;
+
+ private FutureRecorder _futureRecorder = mock(FutureRecorder.class);
+ private EnqueableMessage _message = mock(EnqueableMessage.class);
+ private BaseQueue _queue = mock(BaseQueue.class);
+ private MessageStore _messageStore = mock(MessageStore.class);
+ private Transaction _storeTransaction = mock(Transaction.class);
+ private Action _postTransactionAction = mock(Action.class);
+ private StoreFuture _future = mock(StoreFuture.class);
+
+
+ @Override
+ protected void setUp() throws Exception
+ {
+ super.setUp();
+
+ when(_messageStore.newTransaction()).thenReturn(_storeTransaction);
+ when(_storeTransaction.commitTranAsync()).thenReturn(_future);
+ when(_queue.isDurable()).thenReturn(true);
+ }
+
+ public void testEnqueuePersistentMessagePostCommitNotCalledWhenFutureAlreadyComplete() throws Exception
+ {
+ setTestSystemProperty(STRICT_ORDER_SYSTEM_PROPERTY, "false");
+
+ when(_message.isPersistent()).thenReturn(true);
+ when(_future.isComplete()).thenReturn(true);
+
+ AsyncAutoCommitTransaction asyncAutoCommitTransaction =
+ new AsyncAutoCommitTransaction(_messageStore, _futureRecorder);
+
+ asyncAutoCommitTransaction.enqueue(_queue, _message, _postTransactionAction);
+
+ verify(_storeTransaction).enqueueMessage(_queue, _message);
+ verify(_futureRecorder).recordFuture(_future, _postTransactionAction);
+ verifyZeroInteractions(_postTransactionAction);
+ }
+
+ public void testEnqueuePersistentMessageOnMultiplQueuesPostCommitNotCalled() throws Exception
+ {
+ setTestSystemProperty(STRICT_ORDER_SYSTEM_PROPERTY, "false");
+
+ when(_message.isPersistent()).thenReturn(true);
+ when(_future.isComplete()).thenReturn(true);
+
+ AsyncAutoCommitTransaction asyncAutoCommitTransaction =
+ new AsyncAutoCommitTransaction(_messageStore, _futureRecorder);
+
+ asyncAutoCommitTransaction.enqueue(Collections.singletonList(_queue), _message, _postTransactionAction, System.currentTimeMillis());
+
+ verify(_storeTransaction).enqueueMessage(_queue, _message);
+ verify(_futureRecorder).recordFuture(_future, _postTransactionAction);
+ verifyZeroInteractions(_postTransactionAction);
+ }
+
+ public void testEnqueuePersistentMessagePostCommitNotCalledWhenFutureNotYetComplete() throws Exception
+ {
+ setTestSystemProperty(STRICT_ORDER_SYSTEM_PROPERTY, "false");
+
+ when(_message.isPersistent()).thenReturn(true);
+ when(_future.isComplete()).thenReturn(false);
+
+ AsyncAutoCommitTransaction asyncAutoCommitTransaction =
+ new AsyncAutoCommitTransaction(_messageStore, _futureRecorder);
+
+ asyncAutoCommitTransaction.enqueue(_queue, _message, _postTransactionAction);
+
+ verify(_storeTransaction).enqueueMessage(_queue, _message);
+ verify(_futureRecorder).recordFuture(_future, _postTransactionAction);
+ verifyZeroInteractions(_postTransactionAction);
+ }
+
+ public void testEnqueueTransientMessagePostCommitIsCalledWhenNotBehavingStrictly() throws Exception
+ {
+ setTestSystemProperty(STRICT_ORDER_SYSTEM_PROPERTY, "false");
+
+ when(_message.isPersistent()).thenReturn(false);
+
+ AsyncAutoCommitTransaction asyncAutoCommitTransaction =
+ new AsyncAutoCommitTransaction(_messageStore, _futureRecorder);
+
+ asyncAutoCommitTransaction.enqueue(_queue, _message, _postTransactionAction);
+
+ verifyZeroInteractions(_storeTransaction);
+ verify(_postTransactionAction).postCommit();
+ verifyZeroInteractions(_futureRecorder);
+ }
+
+ public void testEnqueueTransientMessagePostCommitIsCalledWhenBehavingStrictly() throws Exception
+ {
+ setTestSystemProperty(STRICT_ORDER_SYSTEM_PROPERTY, "true");
+
+ when(_message.isPersistent()).thenReturn(false);
+
+ AsyncAutoCommitTransaction asyncAutoCommitTransaction =
+ new AsyncAutoCommitTransaction(_messageStore, _futureRecorder);
+
+ asyncAutoCommitTransaction.enqueue(_queue, _message, _postTransactionAction);
+
+ verifyZeroInteractions(_storeTransaction);
+ verify(_futureRecorder).recordFuture(StoreFuture.IMMEDIATE_FUTURE, _postTransactionAction);
+ verifyZeroInteractions(_postTransactionAction);
+ }
+}
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 af49238998..0221f3d509 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
@@ -124,6 +124,12 @@ class MockStoreTransaction implements Transaction
storeTransaction.setState(TransactionState.STARTED);
return storeTransaction;
}
+
+ @Override
+ public String getStoreType()
+ {
+ return "TEST";
+ }
};
}
} \ No newline at end of file
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 8a34e92985..d7a9078412 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
@@ -20,8 +20,7 @@
*/
package org.apache.qpid.server.util;
-import java.util.UUID;
-
+import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.configuration.XMLConfiguration;
import org.apache.qpid.AMQException;
@@ -38,6 +37,7 @@ import org.apache.qpid.server.exchange.Exchange;
import org.apache.qpid.server.logging.SystemOutMessageLogger;
import org.apache.qpid.server.logging.actors.CurrentActor;
import org.apache.qpid.server.logging.actors.TestLogActor;
+import org.apache.qpid.server.model.UUIDGenerator;
import org.apache.qpid.server.protocol.InternalTestProtocolSession;
import org.apache.qpid.server.queue.AMQQueue;
import org.apache.qpid.server.queue.AMQQueueFactory;
@@ -45,7 +45,6 @@ import org.apache.qpid.server.registry.ApplicationRegistry;
import org.apache.qpid.server.registry.IApplicationRegistry;
import org.apache.qpid.server.store.MessageStore;
import org.apache.qpid.server.store.TestableMemoryMessageStore;
-import org.apache.qpid.server.store.TestableMemoryMessageStoreFactory;
import org.apache.qpid.server.virtualhost.VirtualHost;
import org.apache.qpid.test.utils.QpidTestCase;
@@ -68,10 +67,10 @@ public class InternalBrokerBaseCase extends QpidTestCase
super.setUp();
_configXml.addProperty("virtualhosts.virtualhost.name", "test");
- _configXml.addProperty("virtualhosts.virtualhost.test.store.factoryclass", TestableMemoryMessageStoreFactory.class.getName());
+ _configXml.addProperty("virtualhosts.virtualhost.test.store.class", TestableMemoryMessageStore.class.getName());
_configXml.addProperty("virtualhosts.virtualhost(-1).name", getName());
- _configXml.addProperty("virtualhosts.virtualhost(-1)."+getName()+".store.factoryclass", TestableMemoryMessageStoreFactory.class.getName());
+ _configXml.addProperty("virtualhosts.virtualhost(-1)."+getName()+".store.class", TestableMemoryMessageStore.class.getName());
createBroker();
}
@@ -85,7 +84,7 @@ public class InternalBrokerBaseCase extends QpidTestCase
configure();
- _registry = new TestApplicationRegistry(_configuration);
+ _registry = createApplicationRegistry();
ApplicationRegistry.initialise(_registry);
_registry.getVirtualHostRegistry().setDefaultVirtualHostName(getName());
_virtualHost = _registry.getVirtualHostRegistry().getVirtualHost(getName());
@@ -93,7 +92,7 @@ public class InternalBrokerBaseCase extends QpidTestCase
QUEUE_NAME = new AMQShortString("test");
// Create a queue on the test Vhost.. this will aid in diagnosing duff tests
// as the ExpiredMessage Task will log with the test Name.
- _queue = AMQQueueFactory.createAMQQueueImpl(QUEUE_NAME, false, new AMQShortString("testowner"),
+ _queue = AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), QUEUE_NAME.asString(), false, "testowner",
false, false, _virtualHost, null);
Exchange defaultExchange = _virtualHost.getExchangeRegistry().getDefaultExchange();
@@ -102,7 +101,7 @@ public class InternalBrokerBaseCase extends QpidTestCase
_virtualHost = _registry.getVirtualHostRegistry().getVirtualHost("test");
_messageStore = _virtualHost.getMessageStore();
- _queue = AMQQueueFactory.createAMQQueueImpl(new AMQShortString(getName()), false, new AMQShortString("testowner"),
+ _queue = AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), getName(), false, "testowner",
false, false, _virtualHost, null);
_virtualHost.getQueueRegistry().registerQueue(_queue);
@@ -119,6 +118,11 @@ public class InternalBrokerBaseCase extends QpidTestCase
_session.addChannel(_channel);
}
+ protected IApplicationRegistry createApplicationRegistry() throws ConfigurationException
+ {
+ return new TestApplicationRegistry(_configuration);
+ }
+
protected void configure()
{
// Allow other tests to override configuration
@@ -250,7 +254,7 @@ public class InternalBrokerBaseCase extends QpidTestCase
channel.publishContentHeader(_headerBody);
}
-
+ channel.sync();
}
public void acknowledge(AMQChannel channel, long deliveryTag)
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 7aa5ed23fe..a64ab620ab 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,6 +20,9 @@
*/
package org.apache.qpid.server.util;
+import java.net.SocketAddress;
+import java.util.Collections;
+import java.util.Map;
import org.apache.commons.configuration.ConfigurationException;
import org.apache.qpid.server.configuration.ServerConfiguration;
@@ -28,9 +31,11 @@ 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.plugins.PluginManager;
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.IAuthenticationManagerRegistry;
import org.apache.qpid.server.security.auth.manager.PrincipalDatabaseAuthenticationManager;
import java.util.Properties;
@@ -51,11 +56,10 @@ public class TestApplicationRegistry extends ApplicationRegistry
super.initialise();
}
- /**
- * @see org.apache.qpid.server.registry.ApplicationRegistry#createAuthenticationManager()
- */
@Override
- protected AuthenticationManager createAuthenticationManager() throws ConfigurationException
+ protected IAuthenticationManagerRegistry createAuthenticationManagerRegistry(
+ ServerConfiguration _configuration, PluginManager _pluginManager)
+ throws ConfigurationException
{
final Properties users = new Properties();
users.put("guest","guest");
@@ -63,7 +67,7 @@ public class TestApplicationRegistry extends ApplicationRegistry
final PropertiesPrincipalDatabase ppd = new PropertiesPrincipalDatabase(users);
- AuthenticationManager pdam = new PrincipalDatabaseAuthenticationManager()
+ final AuthenticationManager pdam = new PrincipalDatabaseAuthenticationManager()
{
/**
@@ -83,12 +87,35 @@ public class TestApplicationRegistry extends ApplicationRegistry
super.initialise();
}
};
-
pdam.initialise();
- return pdam;
- }
+ return new IAuthenticationManagerRegistry()
+ {
+ @Override
+ public void close()
+ {
+ pdam.close();
+ }
+
+ @Override
+ public AuthenticationManager getAuthenticationManager(
+ SocketAddress address)
+ {
+ return pdam;
+ }
+ @Override
+ public Map<String, AuthenticationManager> getAvailableAuthenticationManagers()
+ {
+ return Collections.singletonMap(pdam.getClass().getName(), pdam);
+ }
+
+ @Override
+ public void addRegistryChangeListener(RegistryChangeListener listener)
+ {
+ }
+ };
+ }
}
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
index 0794154e47..8b4a52bb79 100644
--- 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
@@ -64,4 +64,50 @@ public class HouseKeepingTaskTest extends QpidTestCase
//clean up the test actor
CurrentActor.remove();
}
+
+ public void testThreadNameIsSetForDurationOfTask() throws Exception
+ {
+ //create and set a test actor
+ LogActor testActor = new TestLogActor(new NullRootMessageLogger());
+ CurrentActor.set(testActor);
+
+ String originalThreadName = Thread.currentThread().getName();
+
+ String vhostName = "HouseKeepingTaskTestVhost";
+
+ String expectedThreadNameDuringExecution = vhostName + ":" + "ThreadNameRememberingTask";
+
+ ThreadNameRememberingTask testTask = new ThreadNameRememberingTask(new MockVirtualHost(vhostName));
+
+ testTask.run();
+
+ assertEquals("Thread name should have been set during execution", expectedThreadNameDuringExecution, testTask.getThreadNameDuringExecution());
+ assertEquals("Thread name should have been reverted after task has run", originalThreadName, Thread.currentThread().getName());
+
+ //clean up the test actor
+ CurrentActor.remove();
+ }
+
+
+ private static final class ThreadNameRememberingTask extends HouseKeepingTask
+ {
+ private String _threadNameDuringExecution;
+
+ private ThreadNameRememberingTask(VirtualHost vhost)
+ {
+ super(vhost);
+ }
+
+ @Override
+ public void execute()
+ {
+ _threadNameDuringExecution = Thread.currentThread().getName(); // store current thread name so we can assert it later
+ throw new RuntimeException("deliberate exception to check that thread name still gets reverted");
+ }
+
+ public String getThreadNameDuringExecution()
+ {
+ return _threadNameDuringExecution;
+ }
+ }
}
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
index 91174c5d10..290c465785 100644
--- 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
@@ -32,7 +32,6 @@ 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.protocol.v1_0.LinkRegistry;
import org.apache.qpid.server.queue.QueueRegistry;
import org.apache.qpid.server.registry.IApplicationRegistry;
@@ -141,11 +140,6 @@ public class MockVirtualHost implements VirtualHost
return 0;
}
- public ManagedObject getManagedObject()
- {
- return null;
- }
-
public MessageStore getMessageStore()
{
return null;
@@ -222,6 +216,12 @@ public class MockVirtualHost implements VirtualHost
return null;
}
+ @Override
+ public UUID getQMFId()
+ {
+ return null;
+ }
+
public ConfiguredObject<VirtualHostConfigType, VirtualHostConfig> getParent()
{
return null;
@@ -257,11 +257,6 @@ public class MockVirtualHost implements VirtualHost
}
- public boolean isStatisticsEnabled()
- {
- return false;
- }
-
public void registerMessageDelivered(long messageSize)
{
@@ -277,14 +272,16 @@ public class MockVirtualHost implements VirtualHost
}
- public void setStatisticsEnabled(boolean enabled)
+ public State getState()
{
+ return State.ACTIVE;
+ }
+ public void block()
+ {
}
- @Override
- public State getState()
+ public void unblock()
{
- return State.ACTIVE;
}
} \ 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
index 87eb0f9d16..b8ba76e43d 100644
--- 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
@@ -27,7 +27,7 @@ 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.MemoryMessageStoreFactory;
+import org.apache.qpid.server.store.MemoryMessageStore;
import org.apache.qpid.server.util.TestApplicationRegistry;
import org.apache.qpid.test.utils.QpidTestCase;
@@ -192,7 +192,7 @@ public class VirtualHostImplTest extends QpidTestCase
writer.write(" <name>" + vhostName + "</name>");
writer.write(" <" + vhostName + ">");
writer.write(" <store>");
- writer.write(" <factoryclass>" + MemoryMessageStoreFactory.class.getName() + "</factoryclass>");
+ writer.write(" <class>" + MemoryMessageStore.class.getName() + "</class>");
writer.write(" </store>");
if(exchangeName != null && !dontDeclare)
{
diff --git a/java/broker/src/test/java/org/apache/qpid/server/virtualhost/plugins/policies/TopicDeletePolicyTest.java b/java/broker/src/test/java/org/apache/qpid/server/virtualhost/plugins/policies/TopicDeletePolicyTest.java
index fdd163b323..aa8448b99d 100644
--- a/java/broker/src/test/java/org/apache/qpid/server/virtualhost/plugins/policies/TopicDeletePolicyTest.java
+++ b/java/broker/src/test/java/org/apache/qpid/server/virtualhost/plugins/policies/TopicDeletePolicyTest.java
@@ -146,7 +146,7 @@ public class TopicDeletePolicyTest extends InternalBrokerBaseCase
MockAMQQueue queue = createOwnedQueue();
- queue.addBinding(new Binding(null, "bindingKey", queue, new DirectExchange(), null));
+ queue.addBinding(new Binding(null, null, "bindingKey", queue, new DirectExchange(), null));
policy.performPolicy(queue);
@@ -165,7 +165,7 @@ public class TopicDeletePolicyTest extends InternalBrokerBaseCase
MockAMQQueue queue = createOwnedQueue();
- queue.addBinding(new Binding(null, "bindingKey", queue, new TopicExchange(), null));
+ queue.addBinding(new Binding(null, null, "bindingKey", queue, new TopicExchange(), null));
queue.setAutoDelete(false);
@@ -186,7 +186,7 @@ public class TopicDeletePolicyTest extends InternalBrokerBaseCase
final MockAMQQueue queue = createOwnedQueue();
- queue.addBinding(new Binding(null, "bindingKey", queue, new TopicExchange(), null));
+ queue.addBinding(new Binding(null, null, "bindingKey", queue, new TopicExchange(), null));
setQueueToAutoDelete(queue);
@@ -207,7 +207,7 @@ public class TopicDeletePolicyTest extends InternalBrokerBaseCase
MockAMQQueue queue = createOwnedQueue();
- queue.addBinding(new Binding(null, "bindingKey", queue, new TopicExchange(), null));
+ queue.addBinding(new Binding(null, null, "bindingKey", queue, new TopicExchange(), null));
policy.performPolicy(queue);
@@ -233,7 +233,7 @@ public class TopicDeletePolicyTest extends InternalBrokerBaseCase
MockAMQQueue queue = createOwnedQueue();
- queue.addBinding(new Binding(null, "bindingKey", queue, new TopicExchange(), null));
+ queue.addBinding(new Binding(null, null, "bindingKey", queue, new TopicExchange(), null));
policy.performPolicy(queue);
@@ -253,7 +253,7 @@ public class TopicDeletePolicyTest extends InternalBrokerBaseCase
MockAMQQueue queue = createOwnedQueue();
- queue.addBinding(new Binding(null, "bindingKey", queue, new TopicExchange(), null));
+ queue.addBinding(new Binding(null, null, "bindingKey", queue, new TopicExchange(), null));
policy.performPolicy(queue);
diff --git a/java/build.deps b/java/build.deps
index 76b1461fe2..52ae277ce4 100644
--- a/java/build.deps
+++ b/java/build.deps
@@ -17,41 +17,54 @@
# under the License.
#
-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
-commons-collections=lib/commons-collections-3.2.jar
-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-beanutils-core=lib/required/commons-beanutils-core-1.8.3.jar
+commons-cli=lib/required/commons-cli-1.2.jar
+commons-codec=lib/required/commons-codec-1.6.jar
+commons-collections=lib/required/commons-collections-3.2.1.jar
+commons-configuration=lib/required/commons-configuration-1.8.jar
+commons-digester=lib/required/commons-digester-1.8.1.jar
+commons-lang=lib/required/commons-lang-2.6.jar
+commons-logging=lib/required/commons-logging-1.1.1.jar
-derby-db=lib/derby-10.6.1.0.jar
+derby-db=lib/required/derby-10.8.2.2.jar
-geronimo-jms=lib/geronimo-jms_1.1_spec-1.0.jar
-geronimo-j2ee=lib/geronimo-j2ee-connector_1.5_spec-2.0.0.jar
-geronimo-jta=lib/geronimo-jta_1.1_spec-1.1.1.jar
-geronimo-kernel=lib/geronimo-kernel-2.2.1.jar
-geronimo-openejb=lib/geronimo-ejb_3.0_spec-1.0.1.jar
+geronimo-jms=lib/required/geronimo-jms_1.1_spec-1.0.jar
+geronimo-j2ee=lib/required/geronimo-j2ee-connector_1.5_spec-2.0.0.jar
+geronimo-jta=lib/required/geronimo-jta_1.1_spec-1.1.1.jar
+geronimo-kernel=lib/required/geronimo-kernel-2.2.1.jar
+geronimo-openejb=lib/required/geronimo-ejb_3.0_spec-1.0.1.jar
+geronimo-servlet=lib/required/geronimo-servlet_2.5_spec-1.2.jar
-junit=lib/junit-3.8.1.jar
-mockito-all=lib/mockito-all-1.9.0.jar
+junit=lib/required/junit-3.8.1.jar
+mockito-all=lib/required/mockito-all-1.9.0.jar
-gson-all=lib/gson-2.0.jar
+gson-all=lib/required/gson-2.0.jar
-log4j=lib/log4j-1.2.12.jar
+log4j=lib/required/log4j-1.2.16.jar
-slf4j-api=lib/slf4j-api-1.6.1.jar
-slf4j-log4j=lib/slf4j-log4j12-1.6.1.jar
+slf4j-api=lib/required/slf4j-api-1.6.4.jar
+slf4j-log4j=lib/required/slf4j-log4j12-1.6.4.jar
-xalan=lib/xalan-2.7.0.jar
+xalan=lib/required/xalan-2.7.0.jar
-felix-main=lib/org.apache.felix.main-2.0.5.jar
+jetty=lib/required/jetty-server-7.6.3.v20120416.jar
+jetty-continuation=lib/required/jetty-continuation-7.6.3.v20120416.jar
+jetty-security=lib/required/jetty-security-7.6.3.v20120416.jar
+jetty-util=lib/required/jetty-util-7.6.3.v20120416.jar
+jetty-io=lib/required/jetty-io-7.6.3.v20120416.jar
+jetty-http=lib/required/jetty-http-7.6.3.v20120416.jar
+jetty-servlet=lib/required/jetty-servlet-7.6.3.v20120416.jar
+jetty-websocket=lib/required/jetty-websocket-7.6.3.v20120416.jar
+servlet-api=${geronimo-servlet}
+
+dojo=lib/required/dojo-war-1.7.2.war
+
+felix-main=lib/required/org.apache.felix.main-2.0.5.jar
felix.libs=${felix-main}
-jackson-core=lib/jackson-core-asl-1.9.0.jar
-jackson-mapper=lib/jackson-mapper-asl-1.9.0.jar
+jackson-core=lib/required/jackson-core-asl-1.9.0.jar
+jackson-mapper=lib/required/jackson-mapper-asl-1.9.0.jar
commons-configuration.libs = ${commons-beanutils-core} ${commons-digester} \
${commons-codec} ${commons-lang} ${commons-collections} ${commons-configuration}
@@ -64,72 +77,17 @@ amqp-1-0-client-jms.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} \
- ${jackson-core} ${jackson-mapper}
+ ${jackson-core} ${jackson-mapper} ${jetty} ${jetty-continuation} ${jetty-security} ${jetty-http} ${jetty-io} ${jetty-servlet} ${jetty-util} ${servlet-api} ${jetty-websocket}
+broker-plugins-management-http.libs=${jetty} ${jetty-continuation} ${jetty-security} ${jetty-http} ${jetty-io} ${jetty-servlet} ${jetty-util} ${servlet-api} ${jackson-core} ${jackson-mapper}
broker-plugins.libs=${felix.libs} ${log4j} ${commons-configuration.libs}
test.libs=${slf4j-log4j} ${log4j} ${junit} ${slf4j-api} ${mockito-all}
-perftests.libs=${geronimo-jms} ${slf4j-api} ${commons-collections} ${commons-beanutils-core} ${commons-lang} ${gson-all}
-
-ibm-icu=lib/com.ibm.icu_3.8.1.v20080530.jar
-ecl-core-jface=lib/org.eclipse.jface_3.4.1.M20080827-2000.jar
-ecl-core-jface-databinding=lib/org.eclipse.jface.databinding_1.2.1.M20080827-0800a.jar
-ecl-core-commands=lib/org.eclipse.core.commands_3.4.0.I20080509-2000.jar
-ecl-core-contenttype=lib/org.eclipse.core.contenttype_3.3.0.v20080604-1400.jar
-ecl-core-databinding=lib/org.eclipse.core.databinding_1.1.1.M20080827-0800b.jar
-ecl-core-expressions=lib/org.eclipse.core.expressions_3.4.0.v20080603-2000.jar
-ecl-core-jobs=lib/org.eclipse.core.jobs_3.4.0.v20080512.jar
-ecl-core-runtime=lib/org.eclipse.core.runtime_3.4.0.v20080512.jar
-ecl-core-runtime-compat-registry=lib/org.eclipse.core.runtime.compatibility.registry_3.2.200.v20080610/**
-ecl-equinox-app=lib/org.eclipse.equinox.app_1.1.0.v20080421-2006.jar
-ecl-equinox-common=lib/org.eclipse.equinox.common_3.4.0.v20080421-2006.jar
-ecl-equinox-launcher=lib/org.eclipse.equinox.launcher_1.0.101.R34x_v20080819.jar
-ecl-equinox-prefs=lib/org.eclipse.equinox.preferences_3.2.201.R34x_v20080709.jar
-ecl-equinox-registry=lib/org.eclipse.equinox.registry_3.4.0.v20080516-0950.jar
-ecl-help=lib/org.eclipse.help_3.3.101.v20080702_34x.jar
-ecl-osgi=lib/org.eclipse.osgi_3.4.2.R34x_v20080826-1230.jar
-ecl-swt=lib/org.eclipse.swt_3.4.1.v3449c.jar
-ecl-ui=lib/org.eclipse.ui_3.4.1.M20080910-0800.jar
-ecl-ui-forms=lib/org.eclipse.ui.forms_3.3.101.v20080708_34x.jar
-ecl-ui-workbench=lib/org.eclipse.ui.workbench_3.4.1.M20080827-0800a.jar
-apache-commons-codec=lib/org.apache.commons.codec_1.3.0.v20080530-1600.jar
-
-ecl-swt-win32-win32-x86=lib/org.eclipse.swt.win32.win32.x86_3.4.1.v3449c.jar
-ecl-equinox-launcher-win32-win32-x86=lib/org.eclipse.equinox.launcher.win32.win32.x86_1.0.101.R34x_v20080731/**
-ecl-swt-linux-gtk-x86=lib/org.eclipse.swt.gtk.linux.x86_3.4.1.v3449c.jar
-ecl-equinox-launcher-linux-gtk-x86=lib/org.eclipse.equinox.launcher.gtk.linux.x86_1.0.101.R34x_v20080805/**
-ecl-swt-linux-gtk-x86_64=lib/org.eclipse.swt.gtk.linux.x86_64_3.4.1.v3449c.jar
-ecl-equinox-launcher-linux-gtk-x86_64=lib/org.eclipse.equinox.launcher.gtk.linux.x86_64_1.0.101.R34x_v20080731/**
-ecl-swt-macosx-carbon=lib/org.eclipse.swt.carbon.macosx_3.4.1.v3449c.jar
-ecl-equinox-launcher-macosx-carbon=lib/org.eclipse.equinox.launcher.carbon.macosx_1.0.101.R34x_v20080731/**
-ecl-swt-solaris-gtk-sparc=lib/org.eclipse.swt.gtk.solaris.sparc_3.4.1.v3449c.jar
-ecl-equinox-launcher-solaris-gtk-sparc=lib/org.eclipse.equinox.launcher.gtk.solaris.sparc_1.0.101.R34x_v20080731/**
+perftests.libs=${geronimo-jms} ${slf4j-api} ${log4j} ${slf4j-log4j} ${commons-logging} ${commons-collections} ${commons-beanutils-core} ${commons-lang} ${gson-all}
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}
-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}
-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}
-management-eclipse-plugin-macosx.libs=${management-eclipse-plugin.core-libs} \
- ${ecl-swt-macosx-carbon} ${ecl-equinox-launcher-macosx-carbon} ${ecl-core-runtime-compat-registry}
-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}
-
common.test.libs=${test.libs}
broker.test.libs=${test.libs}
client.test.libs=${test.libs}
@@ -139,27 +97,30 @@ testkit.test.libs=${test.libs}
systests.libs=${test.libs}
perftests.test.libs=${test.libs}
-broker-plugins.test.libs=${test.libs}
+broker-plugins.test.libs=${test.libs}
-management-eclipse-plugin.test.libs=${test.libs}
management-common.test.libs=${test.libs}
# JCA Resource adapter
-ra.libs=${geronimo-j2ee} ${geronimo-jta} ${geronimo-jms} ${test.libs} ${geronimo-kernel} ${geronimo-openejb}
-ra.test.libs=${test.libs}
-
-#note this is a hack because systests is looking for 'jca' versus 'ra' we need to do this twice
-jca.libs=${geronimo-j2ee} ${geronimo-jta} ${geronimo-jms} ${test.libs} ${geronimo-kernel} ${geronimo-openejb}
+jca.libs=${geronimo-j2ee} ${geronimo-jta} ${geronimo-jms} ${test.libs} ${geronimo-kernel} ${geronimo-openejb} ${geronimo-servlet}
jca.test.libs=${test.libs}
# optional bdbstore module deps
-bdb-je=lib/bdbstore/je-5.0.34.jar
+bdb-je=lib/bdbstore/je-5.0.55.jar
bdbstore.libs=${bdb-je}
bdbstore.test.libs=${test.libs}
+bdbstore-jmx.libs=${bdb-je}
+bdbstore-jmx.test.libs=${test.libs}
+
# optional perftests-visualisation-jfc module deps
jfreechart.jar=lib/jfree/jfreechart-1.0.13.jar
-jfreecommon.jar=lib/jfree/jfreecommon-1.0.16.jar
+jcommon.jar=lib/jfree/jcommon-1.0.16.jar
csvjdbc.jar=lib/csvjdbc/csvjdbc-1.0.8.jar
-perftests-visualisation-jfc.libs=${jfreechart.jar} ${jfreecommon.jar} ${csvjdbc.jar}
+perftests-visualisation-jfc.libs=${jfreechart.jar} ${jcommon.jar} ${csvjdbc.jar}
perftests-visualisation-jfc.test.libs=${test.libs}
+
+# Libraries used only within the build
+bnd=lib/required/bnd-0.0.384.jar
+jython=lib/required/jython-standalone-2.5.2.jar
+maven-ant-tasks=lib/required/maven-ant-tasks-2.1.1.jar
diff --git a/java/build.xml b/java/build.xml
index 1de6c8f49c..7f51cb64c0 100644
--- a/java/build.xml
+++ b/java/build.xml
@@ -18,29 +18,35 @@
- under the License.
-
-->
-<project name="AMQ Java" default="build">
+<project name="AMQ Java" xmlns:ivy="antlib:org.apache.ivy.ant" default="build">
<import file="common.xml"/>
<findSubProjects name="broker-plugins" dir="broker-plugins"/>
<findSubProjects name="client-plugins" dir="client-plugins"/>
- <findSubProjects name="management" dir="management" excludes="common,example"/>
+
+ <property name="optional" value="false"/>
+ <property name="modules.opt.default" value="bdbstore bdbstore/jmx perftests/visualisation-jfc"/>
+ <condition property="modules.opt" value="" else="${modules.opt.default}">
+ <isfalse value="${optional}"/>
+ </condition>
<property name="modules.core" value="common management/common amqp-1-0-common broker client amqp-1-0-client amqp-1-0-client-jms tools"/>
<property name="modules.examples" value="client/example management/example"/>
<property name="modules.tests" value="systests perftests"/>
- <property name="modules.management" value="${management}"/>
<property name="modules.plugin" value="${broker-plugins} ${client-plugins}"/>
- <property name="modules.opt" value=""/>
<property name="modules.jca" value="jca"/>
<property name="modules" value="${modules.core} ${modules.examples}
- ${modules.management} ${modules.jca} ${modules.tests} ${modules.plugin} ${modules.opt}"/>
+ ${modules.jca} ${modules.tests} ${modules.plugin} ${modules.opt}"/>
<property name="qpid.jar" location="${build.lib}/qpid-all.jar"/>
<basename property="qpid.jar.name" file="${qpid.jar}"/>
<property name="resources" value="${project.root}/resources"/>
+ <!-- Modules for which coverage will be created by the cover-test target -->
+ <property name="coverage.modules" value="${modules}"/>
+
<map property="release.excludes" value="${modules}">
<globmapper from="*" to="*/\*\*"/>
</map>
@@ -156,7 +162,7 @@
<touch file="${qpid.jar}"/>
</target>
- <target name="build" description="build the project">
+ <target name="build" depends="retrieve-dependencies" description="build the project">
<iterate target="build"/>
<antcall target="manifest"/>
</target>
@@ -212,33 +218,39 @@
</target>
<target name="coverage-report" description="generate coverage report" depends="cobertura-init">
- <cobertura-merge datafile="${build.coveragereport}/cobertura.ser">
+ <mkdir dir="${build.coverage.report}" />
+ <mkdir dir="${build.coverage.src}" />
+
+ <cobertura-merge datafile="${build.coverage.report}/cobertura.ser">
<!-- merge all module coverage reports -->
<fileset dir="${build}">
<include name="**/*.ser"/>
</fileset>
</cobertura-merge>
+
+ <!-- Copy all covered sources to single directory for cobertura report -->
+
+ <foreach property="module" list="${coverage.modules}">
+
+ <copy todir="${build.coverage.src}">
+ <fileset dir="${module}/src/main/java" includes="**/*.java"/>
+ </copy>
+
+ <copy todir="${build.coverage.src}">
+ <fileset dir="build/scratch/${module}/src" includes="**/*.java"/>
+ </copy>
+ </foreach>
+
<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" />
+ destdir="${build.coverage.report}"
+ datafile="${build.coverage.report}/cobertura.ser">
+ <fileset dir="${build.coverage.src}" includes="**/*.java" />
</cobertura-report>
- <cobertura-report format="html"
- 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 format="html"
+ destdir="${build.coverage.report}"
+ datafile="${build.coverage.report}/cobertura.ser">
+ <fileset dir="${build.coverage.src}" includes="**/*.java" />
</cobertura-report>
</target>
@@ -247,7 +259,7 @@
</target>
<target name="cover-test" description="run tests and generate coverage information" depends="build">
- <iterate target="cover-test" modules="broker client common"/>
+ <iterate target="cover-test" modules="${coverage.modules}"/>
</target>
<target name="test-interop" depends="build,compile-tests"
@@ -270,7 +282,7 @@
</jython>
</target>
- <target name="findbugs" depends="findbugs-init,build">
+ <target name="findbugs" depends="build,findbugs-init">
<mkdir dir="${build.findbugs}"/>
@@ -280,13 +292,15 @@
stylesheet="fancy-hist.xsl"
jvmargs="-Xmx512m"
projectName="Qpid">
- <auxAnalyzePath>
- <fileset dir="${build.lib}" includes="qpid*.jar" excludes="*test*.jar *junit*.jar *example*.jar qpid-all.jar"/>
- </auxAnalyzePath>
+ <!-- The classes for analysis -->
+ <fileset dir="${build.lib}" includes="qpid*.jar" excludes="*test*.jar *-sources*.jar *example*.jar qpid-all.jar"/>
+
+ <!--Additional classes, not for analysis -->
<auxClassPath>
- <fileset dir="${build.lib}" includes="**/*.jar" />
- <fileset dir="${basedir}/lib" includes="org.eclipse*.jar com.ibm.*.jar"/>
+ <fileset dir="${basedir}/lib" includes="**/*.jar"/>
</auxClassPath>
+
+ <!-- Source, used for improved reporting -->
<sourcePath>
<fileset dir="${basedir}" includes="**/src/**/org/.." />
</sourcePath>
@@ -296,4 +310,22 @@
<target name="eclipse" description="build eclipse project and classpath files">
<iterate target="eclipse"/>
</target>
+
+ <!-- check the following properties which must be specified by the user-->
+ <target name="check-upload-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">
+ <ivy:configure file="ivysettings.nexus.xml"/>
+ <ivy:resolve file="ivy.nexus.xml"/>
+ <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-upload-props-exist, perform-nexus-upload"/>
+
</project>
diff --git a/java/client/build.xml b/java/client/build.xml
index 5a72d67b68..a02500d8e4 100644
--- a/java/client/build.xml
+++ b/java/client/build.xml
@@ -61,4 +61,5 @@
<target name="release-bin" depends="release-bin-tasks"/>
<target name="bundle" depends="bundle-tasks"/>
+
</project>
diff --git a/java/client/src/main/java/client.bnd b/java/client/src/main/java/client.bnd
index 495ea6793f..4b9b191520 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.17.0
+ver: 0.19.0
Bundle-SymbolicName: qpid-client
Bundle-Version: ${ver}
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 23b47c8d67..d80858a7a1 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
@@ -69,6 +69,7 @@ import javax.naming.StringRefAddr;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.net.ConnectException;
+import java.net.SocketAddress;
import java.net.UnknownHostException;
import java.nio.channels.UnresolvedAddressException;
import java.util.ArrayList;
@@ -78,11 +79,14 @@ import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicLong;
public class AMQConnection extends Closeable implements Connection, QueueConnection, TopicConnection, Referenceable
{
private static final Logger _logger = LoggerFactory.getLogger(AMQConnection.class);
+ private static final AtomicLong CONN_NUMBER_GENERATOR = new AtomicLong();
+ private final long _connectionNumber;
/**
* This is the "root" mutex that must be held when doing anything that could be impacted by failover. This must be
@@ -222,6 +226,13 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
throw new IllegalArgumentException("Connection must be specified");
}
+ _connectionNumber = CONN_NUMBER_GENERATOR.incrementAndGet();
+
+ if (_logger.isDebugEnabled())
+ {
+ _logger.debug("Connection(" + _connectionNumber + "):" + connectionURL);
+ }
+
// set this connection maxPrefetch
if (connectionURL.getOption(ConnectionURL.OPTIONS_MAXPREFETCH) != null)
{
@@ -308,11 +319,6 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
_delegate = new AMQConnectionDelegate_0_10(this);
}
- if (_logger.isDebugEnabled())
- {
- _logger.debug("Connection:" + connectionURL);
- }
-
_connectionURL = connectionURL;
_clientName = connectionURL.getClientName();
@@ -1519,4 +1525,18 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
{
return _delegate;
}
+
+ public Long getConnectionNumber()
+ {
+ return _connectionNumber;
+ }
+
+ protected void logConnected(SocketAddress localAddress, SocketAddress remoteAddress)
+ {
+ if(_logger.isInfoEnabled())
+ {
+ _logger.info("Connection " + _connectionNumber + " now connected from "
+ + localAddress + " to " + remoteAddress);
+ }
+ }
}
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 a1a06c5547..51e7e4153d 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
@@ -222,6 +222,7 @@ public class AMQConnectionDelegate_0_10 implements AMQConnectionDelegate, Connec
_conn.setUsername(_qpidConnection.getUserID());
_conn.setMaximumChannelCount(_qpidConnection.getChannelMax());
_conn.getFailoverPolicy().attainedConnection();
+ _conn.logConnected(_qpidConnection.getLocalAddress(), _qpidConnection.getRemoteAddress());
}
catch (ProtocolVersionException pe)
{
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 08ee7c3705..e1bf007e83 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
@@ -24,13 +24,11 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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.common.ServerPropertyNames;
import org.apache.qpid.framing.BasicQosBody;
@@ -68,7 +66,6 @@ public class AMQConnectionDelegate_8_0 implements AMQConnectionDelegate
private static final Logger _logger = LoggerFactory.getLogger(AMQConnectionDelegate_8_0.class);
private final AMQConnection _conn;
-
public void closeConnection(long timeout) throws JMSException, AMQException
{
_conn.getProtocolHandler().closeConnection(timeout);
@@ -110,9 +107,11 @@ public class AMQConnectionDelegate_8_0 implements AMQConnectionDelegate
sslContext = SSLContextFactory.buildClientContext(
settings.getTrustStorePath(),
settings.getTrustStorePassword(),
+ settings.getTrustStoreType(),
settings.getTrustManagerFactoryAlgorithm(),
settings.getKeyStorePath(),
settings.getKeyStorePassword(),
+ settings.getKeyStoreType(),
settings.getKeyManagerFactoryAlgorithm(),
settings.getCertAlias());
}
@@ -137,6 +136,7 @@ public class AMQConnectionDelegate_8_0 implements AMQConnectionDelegate
{
_conn.getFailoverPolicy().attainedConnection();
_conn.setConnected(true);
+ _conn.logConnected(network.getLocalAddress(), network.getRemoteAddress());
return null;
}
else
@@ -283,7 +283,14 @@ public class AMQConnectionDelegate_8_0 implements AMQConnectionDelegate
for (Iterator it = sessions.iterator(); it.hasNext();)
{
AMQSession s = (AMQSession) it.next();
+
+ // reset the flow control flag
+ // on opening channel, broker sends flow blocked if virtual host is blocked
+ // if virtual host is not blocked, then broker does not send flow command
+ // that's why we need to reset the flow control flag
+ s.setFlowControl(true);
reopenChannel(s.getChannelId(), s.getDefaultPrefetchHigh(), s.getDefaultPrefetchLow(), s.isTransacted());
+
s.resubscribe();
}
}
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 cc91746d98..8bc815d98e 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
@@ -55,12 +55,13 @@ public class AMQConnectionFactory implements ConnectionFactory, QueueConnectionF
ObjectFactory, Referenceable, XATopicConnectionFactory,
XAQueueConnectionFactory, XAConnectionFactory
{
- private final ConnectionURL _connectionDetails;
+ protected static final String NO_URL_CONFIGURED = "The connection factory wasn't created with a proper URL, the connection details are empty";
+
+ private ConnectionURL _connectionDetails;
// The default constructor is necessary to allow AMQConnectionFactory to be deserialised from JNDI
public AMQConnectionFactory()
{
- _connectionDetails = null;
}
public AMQConnectionFactory(final String url) throws URLSyntaxException
@@ -106,6 +107,11 @@ public class AMQConnectionFactory implements ConnectionFactory, QueueConnectionF
public Connection createConnection() throws JMSException
{
+ if(_connectionDetails == null)
+ {
+ throw new JMSException(NO_URL_CONFIGURED);
+ }
+
try
{
if (_connectionDetails.getClientName() == null || _connectionDetails.getClientName().equals(""))
@@ -158,7 +164,7 @@ public class AMQConnectionFactory implements ConnectionFactory, QueueConnectionF
}
else
{
- throw new JMSException("The connection factory wasn't created with a proper URL, the connection details are empty");
+ throw new JMSException(NO_URL_CONFIGURED);
}
}
@@ -193,6 +199,12 @@ public class AMQConnectionFactory implements ConnectionFactory, QueueConnectionF
return _connectionDetails.toString();
}
+ //setter necessary to use instances created with the default constructor (which we can't remove)
+ public final void setConnectionURLString(String url) throws URLSyntaxException
+ {
+ _connectionDetails = new AMQConnectionURL(url);
+ }
+
/**
* JNDI interface to create objects from References.
*
@@ -332,7 +344,7 @@ public class AMQConnectionFactory implements ConnectionFactory, QueueConnectionF
}
else
{
- throw new JMSException("The connection factory wasn't created with a proper URL, the connection details are empty");
+ throw new JMSException(NO_URL_CONFIGURED);
}
}
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 55d3ccb6e7..1468e90c4e 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
@@ -20,6 +20,11 @@
*/
package org.apache.qpid.client;
+import static org.apache.qpid.configuration.ClientProperties.DEFAULT_FLOW_CONTROL_WAIT_FAILURE;
+import static org.apache.qpid.configuration.ClientProperties.DEFAULT_FLOW_CONTROL_WAIT_NOTIFY_PERIOD;
+import static org.apache.qpid.configuration.ClientProperties.QPID_FLOW_CONTROL_WAIT_FAILURE;
+import static org.apache.qpid.configuration.ClientProperties.QPID_FLOW_CONTROL_WAIT_NOTIFY_PERIOD;
+
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -117,18 +122,17 @@ public abstract class AMQSession<C extends BasicMessageConsumer, P extends Basic
/** Immediate message prefetch default. */
public static final String IMMEDIATE_PREFETCH_DEFAULT = "false";
- public static final long DEFAULT_FLOW_CONTROL_WAIT_FAILURE = 120000L;
-
/**
* The period to wait while flow controlled before sending a log message confirming that the session is still
* waiting on flow control being revoked
*/
- private final long _flowControlWaitPeriod = Long.getLong("qpid.flow_control_wait_notify_period",5000L);
+ private final long _flowControlWaitPeriod = Long.getLong(QPID_FLOW_CONTROL_WAIT_NOTIFY_PERIOD,
+ DEFAULT_FLOW_CONTROL_WAIT_NOTIFY_PERIOD);
/**
* The period to wait while flow controlled before declaring a failure
*/
- private final long _flowControlWaitFailure = Long.getLong("qpid.flow_control_wait_failure",
+ private final long _flowControlWaitFailure = Long.getLong(QPID_FLOW_CONTROL_WAIT_FAILURE,
DEFAULT_FLOW_CONTROL_WAIT_FAILURE);
private final boolean _delareQueues =
@@ -797,11 +801,8 @@ public abstract class AMQSession<C extends BasicMessageConsumer, P extends Basic
if (e instanceof AMQDisconnectedException)
{
- if (_dispatcherThread != null)
- {
- // Failover failed and ain't coming back. Knife the dispatcher.
- _dispatcherThread.interrupt();
- }
+ // Failover failed and ain't coming back. Knife the dispatcher.
+ stopDispatcherThread();
}
@@ -830,6 +831,13 @@ public abstract class AMQSession<C extends BasicMessageConsumer, P extends Basic
}
}
+ protected void stopDispatcherThread()
+ {
+ if (_dispatcherThread != null)
+ {
+ _dispatcherThread.interrupt();
+ }
+ }
/**
* Commits all messages done in this transaction and releases any locks currently held.
*
@@ -2366,7 +2374,10 @@ public abstract class AMQSession<C extends BasicMessageConsumer, P extends Basic
{
throw new Error("Error creating Dispatcher thread",e);
}
- _dispatcherThread.setName("Dispatcher-Channel-" + _channelId);
+
+ String dispatcherThreadName = "Dispatcher-" + _channelId + "-Conn-" + _connection.getConnectionNumber();
+
+ _dispatcherThread.setName(dispatcherThreadName);
_dispatcherThread.setDaemon(DEAMON_DISPATCHER_THREAD);
_dispatcher.setConnectionStopped(initiallyStopped);
_dispatcherThread.start();
@@ -3130,6 +3141,14 @@ public abstract class AMQSession<C extends BasicMessageConsumer, P extends Basic
_ticket = ticket;
}
+ public boolean isFlowBlocked()
+ {
+ synchronized (_flowControl)
+ {
+ return !_flowControl.getFlowControl();
+ }
+ }
+
public void setFlowControl(final boolean active)
{
_flowControl.setFlowControl(active);
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 3902c726f3..8a7c6b1a01 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
@@ -128,7 +128,8 @@ public class AMQSession_0_10 extends AMQSession<BasicMessageConsumer_0_10, Basic
* Used to store the range of in tx messages
*/
private final RangeSet _txRangeSet = RangeSetFactory.createRangeSet();
- private int _txSize = 0;
+ private int _txSize = 0;
+ private boolean _isHardError = Boolean.getBoolean("qpid.session.legacy_exception_behaviour");
//--- constructors
/**
@@ -390,11 +391,7 @@ public class AMQSession_0_10 extends AMQSession<BasicMessageConsumer_0_10, Basic
*/
public void sendClose(long timeout) throws AMQException, FailoverException
{
- if (flushTask != null)
- {
- flushTask.cancel();
- flushTask = null;
- }
+ cancelTimerTask();
flushAcknowledgments();
try
{
@@ -1051,9 +1048,22 @@ 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());
+ AMQException amqe = new AMQException(AMQConstant.getConstant(code), _isHardError, se.getMessage(), se.getCause());
_currentException = amqe;
}
+ if (!_isHardError)
+ {
+ cancelTimerTask();
+ stopDispatcherThread();
+ try
+ {
+ closed(_currentException);
+ }
+ catch(Exception e)
+ {
+ _logger.warn("Error closing session", e);
+ }
+ }
getAMQConnection().exceptionReceived(_currentException);
}
@@ -1408,5 +1418,19 @@ public class AMQSession_0_10 extends AMQSession<BasicMessageConsumer_0_10, Basic
sync();
}
+ @Override
+ public boolean isFlowBlocked()
+ {
+ return _qpidSession.isFlowBlocked();
+ }
+
+ private void cancelTimerTask()
+ {
+ if (flushTask != null)
+ {
+ flushTask.cancel();
+ flushTask = null;
+ }
+ }
}
diff --git a/java/client/src/main/java/org/apache/qpid/client/AMQXAResource.java b/java/client/src/main/java/org/apache/qpid/client/AMQXAResource.java
new file mode 100644
index 0000000000..cce6b91781
--- /dev/null
+++ b/java/client/src/main/java/org/apache/qpid/client/AMQXAResource.java
@@ -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.
+ *
+ */
+package org.apache.qpid.client;
+
+import java.util.List;
+
+import javax.transaction.xa.XAResource;
+
+public interface AMQXAResource extends XAResource
+{
+ public String getBrokerUUID();
+
+ public List<XAResource> getSiblings();
+}
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 af9048f1f5..6341510c2f 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
@@ -17,8 +17,13 @@
*/
package org.apache.qpid.client;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import javax.transaction.xa.XAException;
+import javax.transaction.xa.XAResource;
+import javax.transaction.xa.Xid;
import org.apache.qpid.dtx.XidImpl;
import org.apache.qpid.transport.DtxXaStatus;
@@ -28,15 +33,13 @@ 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 javax.transaction.xa.XAException;
-import javax.transaction.xa.XAResource;
-import javax.transaction.xa.Xid;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
* This is an implementation of javax.njms.XAResource.
*/
-public class XAResourceImpl implements XAResource
+public class XAResourceImpl implements AMQXAResource
{
/**
* this XAResourceImpl's logger
@@ -57,9 +60,11 @@ public class XAResourceImpl implements XAResource
* The time for this resource
*/
private int _timeout;
-
+
//--- constructor
-
+
+ private List<XAResource> _siblings = new ArrayList<XAResource>();
+
/**
* Create an XAResource associated with a XASession
*
@@ -157,7 +162,21 @@ public class XAResourceImpl implements XAResource
_xaSession.createSession();
convertExecutionErrorToXAErr(e.getException().getErrorCode());
}
+
checkStatus(result.getStatus());
+
+ if(_logger.isDebugEnabled())
+ {
+ _logger.debug("Calling end for " + _siblings.size() + " XAResource siblings");
+ }
+
+ for(XAResource sibling: _siblings)
+ {
+
+ sibling.end(xid, flag);
+ }
+
+ _siblings.clear();
}
@@ -216,28 +235,38 @@ 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 true;
+ }
+
+ if(!(xaResource instanceof AMQXAResource))
{
- return false;
+ return false;
}
-
- XAResourceImpl other = (XAResourceImpl)xaResource;
- String myUUID = ((AMQSession_0_10)_xaSession).getAMQConnection().getBrokerUUID();
- String otherUUID = ((AMQSession_0_10)other._xaSession).getAMQConnection().getBrokerUUID();
-
+ String myUUID = getBrokerUUID();
+ String otherUUID = ((AMQXAResource)xaResource).getBrokerUUID();
+
if(_logger.isDebugEnabled())
{
_logger.debug("Comparing my UUID " + myUUID + " with other UUID " + otherUUID);
}
-
- return (myUUID != null && otherUUID != null && myUUID.equals(otherUUID));
-
+
+ boolean isSameRm = (myUUID != null && otherUUID != null && myUUID.equals(otherUUID));
+
+ if(isSameRm)
+ {
+ if(_logger.isDebugEnabled())
+ {
+ _logger.debug("XAResource " + xaResource + " is from the ResourceManager. Adding XAResource as sibling for AMQP protocol support. ");
+ }
+ _siblings.add(xaResource);
+ }
+
+ return isSameRm;
+
}
/**
@@ -369,12 +398,12 @@ public class XAResourceImpl implements XAResource
{
_timeout = timeout;
if (timeout != _timeout && _xid != null)
- {
+ {
setDtxTimeout(_timeout);
}
return true;
}
-
+
private void setDtxTimeout(int timeout) throws XAException
{
_xaSession.getQpidSession()
@@ -437,18 +466,23 @@ public class XAResourceImpl implements XAResource
{
setDtxTimeout(_timeout);
}
+
+ for(XAResource sibling: _siblings)
+ {
+ sibling.start(xid, flag);
+ }
}
/**
* Is this resource currently enlisted in a transaction?
- *
+ *
* @return true if the resource is associated with a transaction, false otherwise.
*/
public boolean isEnlisted()
{
return (_xid != null) ;
}
-
+
//------------------------------------------------------------------------
// Private methods
//------------------------------------------------------------------------
@@ -517,7 +551,7 @@ public class XAResourceImpl implements XAResource
}
catch (XAException e)
{
- e.printStackTrace();
+ _logger.error(e.getMessage(), e);
throw e;
}
case ILLEGAL_STATE:
@@ -544,7 +578,7 @@ public class XAResourceImpl implements XAResource
* convert a generic xid into qpid format
* @param xid xid to be converted
* @return the qpid formated xid
- * @throws XAException when xid is null
+ * @throws XAException when xid is null
*/
private org.apache.qpid.transport.Xid convertXid(Xid xid) throws XAException
{
@@ -556,4 +590,13 @@ public class XAResourceImpl implements XAResource
return XidImpl.convert(xid);
}
+ public String getBrokerUUID()
+ {
+ return ((AMQSession_0_10)_xaSession).getAMQConnection().getBrokerUUID();
+ }
+
+ public List<XAResource> getSiblings()
+ {
+ return Collections.unmodifiableList(_siblings);
+ }
}
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 f2efb6e8a5..05bd121bbd 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
@@ -17,6 +17,7 @@
*/
package org.apache.qpid.client;
+import org.apache.qpid.AMQException;
import org.apache.qpid.client.message.MessageFactoryRegistry;
import org.apache.qpid.transport.RangeSet;
@@ -31,7 +32,7 @@ import javax.jms.XATopicSession;
import javax.transaction.xa.XAResource;
/**
- * This is an implementation of the javax.njms.XASEssion interface.
+ * This is an implementation of the javax.jms.XASession interface.
*/
public class XASessionImpl extends AMQSession_0_10 implements XASession, XATopicSession, XAQueueSession
{
@@ -67,7 +68,7 @@ public class XASessionImpl extends AMQSession_0_10 implements XASession, XATopic
{
this(qpidConnection, con, channelId, false, ackMode, MessageFactoryRegistry.newDefaultRegistry(),
defaultPrefetchHigh, defaultPrefetchLow, null);
-
+
}
public XASessionImpl(org.apache.qpid.transport.Connection qpidConnection, AMQConnection con, int channelId,
@@ -92,9 +93,6 @@ public class XASessionImpl extends AMQSession_0_10 implements XASession, XATopic
_qpidDtxSession.dtxSelect();
}
-
- // javax.njms.XASEssion API
-
/**
* Gets the session associated with this XASession.
*
@@ -192,4 +190,11 @@ public class XASessionImpl extends AMQSession_0_10 implements XASession, XATopic
super.acknowledgeImpl() ;
}
}
+
+ @Override
+ void resubscribe() throws AMQException
+ {
+ super.resubscribe();
+ createSession();
+ }
}
diff --git a/java/client/src/main/java/org/apache/qpid/client/handler/AccessRequestOkMethodHandler.java b/java/client/src/main/java/org/apache/qpid/client/handler/AccessRequestOkMethodHandler.java
index 3a3ddae52f..fa544f2d2e 100644
--- a/java/client/src/main/java/org/apache/qpid/client/handler/AccessRequestOkMethodHandler.java
+++ b/java/client/src/main/java/org/apache/qpid/client/handler/AccessRequestOkMethodHandler.java
@@ -1,4 +1,3 @@
-package org.apache.qpid.client.handler;
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
@@ -19,6 +18,7 @@ package org.apache.qpid.client.handler;
* under the License.
*
*/
+package org.apache.qpid.client.handler;
import org.slf4j.Logger;
diff --git a/java/client/src/main/java/org/apache/qpid/client/handler/ChannelFlowMethodHandler.java b/java/client/src/main/java/org/apache/qpid/client/handler/ChannelFlowMethodHandler.java
index 919c5f6d67..46b1f08db3 100644
--- a/java/client/src/main/java/org/apache/qpid/client/handler/ChannelFlowMethodHandler.java
+++ b/java/client/src/main/java/org/apache/qpid/client/handler/ChannelFlowMethodHandler.java
@@ -1,3 +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.
+ *
+ */
package org.apache.qpid.client.handler;
import org.slf4j.Logger;
@@ -8,26 +28,6 @@ import org.apache.qpid.client.protocol.AMQProtocolSession;
import org.apache.qpid.client.state.StateAwareMethodListener;
import org.apache.qpid.framing.ChannelFlowBody;
-/*
-*
-* Licensed to the Apache Software Foundation (ASF) under one
-* or more contributor license agreements. See the NOTICE file
-* distributed with this work for additional information
-* regarding copyright ownership. The ASF licenses this file
-* to you under the Apache License, Version 2.0 (the
-* "License"); you may not use this file except in compliance
-* with the License. You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing,
-* software distributed under the License is distributed on an
-* "AS IS" BASIS, WITHOUT 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 ChannelFlowMethodHandler implements StateAwareMethodListener<ChannelFlowBody>
{
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 11d99f5446..69ecd7bfba 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
@@ -1,4 +1,3 @@
-package org.apache.qpid.client.message;
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
@@ -19,6 +18,7 @@ package org.apache.qpid.client.message;
* under the License.
*
*/
+package org.apache.qpid.client.message;
import org.apache.qpid.AMQException;
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 f997862bb0..183ec4cb40 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,4 +1,3 @@
-package org.apache.qpid.client.message;
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
@@ -19,6 +18,7 @@ package org.apache.qpid.client.message;
* under the License.
*
*/
+package org.apache.qpid.client.message;
import org.apache.qpid.AMQException;
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 d1e43447cc..9e15b08f12 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
@@ -321,7 +321,40 @@ public abstract class AbstractJMSMessage implements org.apache.qpid.jms.Message
protected abstract String getMimeType();
+ public String toHeaderString() throws JMSException
+ {
+ StringBuffer buf = new StringBuffer();
+ buf.append("\nJMS Correlation ID: ").append(getJMSCorrelationID());
+ buf.append("\nJMS timestamp: ").append(getJMSTimestamp());
+ buf.append("\nJMS expiration: ").append(getJMSExpiration());
+ buf.append("\nJMS priority: ").append(getJMSPriority());
+ buf.append("\nJMS delivery mode: ").append(getJMSDeliveryMode());
+ buf.append("\nJMS reply to: ").append(getReplyToString());
+ buf.append("\nJMS Redelivered: ").append(_redelivered);
+ buf.append("\nJMS Destination: ").append(getJMSDestination());
+ buf.append("\nJMS Type: ").append(getJMSType());
+ buf.append("\nJMS MessageID: ").append(getJMSMessageID());
+ buf.append("\nJMS Content-Type: ").append(getContentType());
+ buf.append("\nAMQ message number: ").append(getDeliveryTag());
+
+ buf.append("\nProperties:");
+ final Enumeration propertyNames = getPropertyNames();
+ if (!propertyNames.hasMoreElements())
+ {
+ buf.append("<NONE>");
+ }
+ else
+ {
+ buf.append('\n');
+ while(propertyNames.hasMoreElements())
+ {
+ String propertyName = (String) propertyNames.nextElement();
+ buf.append("\t").append(propertyName).append(" = ").append(getObjectProperty(propertyName)).append("\n");
+ }
+ }
+ return buf.toString();
+ }
public String toString()
{
@@ -330,35 +363,7 @@ public abstract class AbstractJMSMessage implements org.apache.qpid.jms.Message
StringBuffer buf = new StringBuffer("Body:\n");
buf.append(toBodyString());
- buf.append("\nJMS Correlation ID: ").append(getJMSCorrelationID());
- buf.append("\nJMS timestamp: ").append(getJMSTimestamp());
- buf.append("\nJMS expiration: ").append(getJMSExpiration());
- buf.append("\nJMS priority: ").append(getJMSPriority());
- buf.append("\nJMS delivery mode: ").append(getJMSDeliveryMode());
- buf.append("\nJMS reply to: ").append(getReplyToString());
- buf.append("\nJMS Redelivered: ").append(_redelivered);
- buf.append("\nJMS Destination: ").append(getJMSDestination());
- buf.append("\nJMS Type: ").append(getJMSType());
- buf.append("\nJMS MessageID: ").append(getJMSMessageID());
- buf.append("\nJMS Content-Type: ").append(getContentType());
- buf.append("\nAMQ message number: ").append(getDeliveryTag());
-
- buf.append("\nProperties:");
- final Enumeration propertyNames = getPropertyNames();
- if (!propertyNames.hasMoreElements())
- {
- buf.append("<NONE>");
- }
- else
- {
- buf.append('\n');
- while(propertyNames.hasMoreElements())
- {
- String propertyName = (String) propertyNames.nextElement();
- buf.append("\t").append(propertyName).append(" = ").append(getObjectProperty(propertyName)).append("\n");
- }
-
- }
+ buf.append(toHeaderString());
return buf.toString();
}
diff --git a/java/client/src/main/java/org/apache/qpid/client/message/FieldTableSupport.java b/java/client/src/main/java/org/apache/qpid/client/message/FieldTableSupport.java
index bd63cdb5c5..c3f36a545a 100644
--- a/java/client/src/main/java/org/apache/qpid/client/message/FieldTableSupport.java
+++ b/java/client/src/main/java/org/apache/qpid/client/message/FieldTableSupport.java
@@ -1,4 +1,3 @@
-package org.apache.qpid.client.message;
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
@@ -19,6 +18,7 @@ package org.apache.qpid.client.message;
* under the License.
*
*/
+package org.apache.qpid.client.message;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.framing.FieldTable;
diff --git a/java/client/src/main/java/org/apache/qpid/client/message/ReturnMessage.java b/java/client/src/main/java/org/apache/qpid/client/message/ReturnMessage.java
index 6e5f33a65c..e253e43a86 100644
--- a/java/client/src/main/java/org/apache/qpid/client/message/ReturnMessage.java
+++ b/java/client/src/main/java/org/apache/qpid/client/message/ReturnMessage.java
@@ -1,4 +1,3 @@
-package org.apache.qpid.client.message;
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
@@ -19,6 +18,7 @@ package org.apache.qpid.client.message;
* under the License.
*
*/
+package org.apache.qpid.client.message;
import org.apache.qpid.framing.AMQShortString;
diff --git a/java/client/src/main/java/org/apache/qpid/client/security/crammd5hashed/CRAMMD5HashedSaslClient.java b/java/client/src/main/java/org/apache/qpid/client/security/crammd5hashed/CRAMMD5HashedSaslClient.java
new file mode 100644
index 0000000000..9965176772
--- /dev/null
+++ b/java/client/src/main/java/org/apache/qpid/client/security/crammd5hashed/CRAMMD5HashedSaslClient.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.client.security.crammd5hashed;
+
+import java.util.Map;
+
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.sasl.Sasl;
+import javax.security.sasl.SaslClient;
+import javax.security.sasl.SaslException;
+
+import org.apache.qpid.client.security.UsernameHashedPasswordCallbackHandler;
+
+/**
+ * A {@link CRAMMD5HashedSaslClient} merely wraps an instance of a CRAM-MD5 SASL client delegating
+ * all method calls to it, except {@link #getMechanismName()} which returns "CRAM-MD5-HASHED".
+ *
+ * This mechanism must be used with {@link UsernameHashedPasswordCallbackHandler} which is responsible
+ * for the additional hash of the password.
+ */
+public class CRAMMD5HashedSaslClient implements SaslClient
+{
+ private final SaslClient _cramMd5SaslClient;
+
+ public CRAMMD5HashedSaslClient(String authorizationId, String protocol, String serverName, Map<String, ?> props, CallbackHandler cbh) throws SaslException
+ {
+ super();
+ String[] mechanisms = {"CRAM-MD5"};
+ _cramMd5SaslClient = Sasl.createSaslClient(mechanisms, authorizationId, protocol, serverName, props, cbh);
+ }
+
+ public void dispose() throws SaslException
+ {
+ _cramMd5SaslClient.dispose();
+ }
+
+ public String getMechanismName()
+ {
+ return CRAMMD5HashedSaslClientFactory.MECHANISM;
+ }
+
+ public byte[] evaluateChallenge(byte[] challenge) throws SaslException
+ {
+ return _cramMd5SaslClient.evaluateChallenge(challenge);
+ }
+
+
+ public Object getNegotiatedProperty(String propName)
+ {
+ return _cramMd5SaslClient.getNegotiatedProperty(propName);
+ }
+
+ public boolean hasInitialResponse()
+ {
+ return _cramMd5SaslClient.hasInitialResponse();
+ }
+
+ public boolean isComplete()
+ {
+ return _cramMd5SaslClient.isComplete();
+ }
+
+ public byte[] unwrap(byte[] incoming, int offset, int len)
+ throws SaslException
+ {
+ return _cramMd5SaslClient.unwrap(incoming, offset, len);
+ }
+
+ public byte[] wrap(byte[] outgoing, int offset, int len)
+ throws SaslException
+ {
+ return _cramMd5SaslClient.wrap(outgoing, offset, len);
+ }
+}
diff --git a/java/client/src/main/java/org/apache/qpid/client/security/crammd5hashed/CRAMMD5HashedSaslClientFactory.java b/java/client/src/main/java/org/apache/qpid/client/security/crammd5hashed/CRAMMD5HashedSaslClientFactory.java
index cb989f7919..b3ce1a0d23 100644
--- a/java/client/src/main/java/org/apache/qpid/client/security/crammd5hashed/CRAMMD5HashedSaslClientFactory.java
+++ b/java/client/src/main/java/org/apache/qpid/client/security/crammd5hashed/CRAMMD5HashedSaslClientFactory.java
@@ -44,14 +44,13 @@ public class CRAMMD5HashedSaslClientFactory implements SaslClientFactory
throw new SaslException("CallbackHandler must not be null");
}
- String[] mechs = {"CRAM-MD5"};
- return Sasl.createSaslClient(mechs, authorizationId, protocol, serverName, props, cbh);
+ return new CRAMMD5HashedSaslClient(authorizationId, protocol, serverName, props, cbh);
}
}
return null;
}
- public String[] getMechanismNames(Map props)
+ public String[] getMechanismNames(Map<String,?> props)
{
if (props != null)
{
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 7d028e022a..0b6217ffce 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
@@ -125,9 +125,9 @@ public class AMQStateManager implements AMQMethodListener
*/
public void setProtocolSession(AMQProtocolSession session)
{
- if (_logger.isInfoEnabled())
+ if (_logger.isDebugEnabled())
{
- _logger.info("Setting ProtocolSession:" + session);
+ _logger.debug("Setting ProtocolSession:" + session);
}
_protocolSession = session;
}
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 c8903d252f..fd2f003a56 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
@@ -61,7 +61,10 @@ public class StateWaiter extends BlockingWaiter<AMQState>
*/
public StateWaiter(AMQStateManager stateManager, AMQState currentState, Set<AMQState> awaitStates)
{
- _logger.info("New StateWaiter :" + currentState + ":" + awaitStates);
+ if(_logger.isDebugEnabled())
+ {
+ _logger.debug("New StateWaiter :" + currentState + ":" + awaitStates);
+ }
_stateManager = stateManager;
_awaitStates = awaitStates;
_startState = currentState;
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 f303d155c6..516ee8cf37 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
@@ -1,4 +1,3 @@
-package org.apache.qpid.client.url;
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
@@ -19,6 +18,7 @@ package org.apache.qpid.client.url;
* under the License.
*
*/
+package org.apache.qpid.client.url;
import org.apache.qpid.client.AMQBrokerDetails;
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 f4d2ecc36d..0b4f0800d2 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
@@ -33,9 +33,7 @@ public class FailoverPolicy
{
private static final Logger _logger = LoggerFactory.getLogger(FailoverPolicy.class);
- private static final long MINUTE = 60000L;
-
- private static final long DEFAULT_METHOD_TIMEOUT = 1 * MINUTE;
+ private final long DEFAULT_METHOD_TIMEOUT = Long.getLong("qpid.failover_method_timeout", 120000);
private FailoverMethod[] _methods = new FailoverMethod[1];
diff --git a/java/client/src/main/java/org/apache/qpid/jms/TopicSubscriber.java b/java/client/src/main/java/org/apache/qpid/jms/TopicSubscriber.java
index 1dbe464230..fe43ae8cd0 100644
--- a/java/client/src/main/java/org/apache/qpid/jms/TopicSubscriber.java
+++ b/java/client/src/main/java/org/apache/qpid/jms/TopicSubscriber.java
@@ -1,4 +1,3 @@
-package org.apache.qpid.jms;
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
@@ -19,6 +18,7 @@ package org.apache.qpid.jms;
* under the License.
*
*/
+package org.apache.qpid.jms;
import org.apache.qpid.AMQException;
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 9b202a13ee..f17fb9b5f5 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
@@ -69,46 +69,21 @@ public class PropertiesFileInitialContextFactory implements InitialContextFactor
public Context getInitialContext(Hashtable environment) throws NamingException
{
Map data = new ConcurrentHashMap();
-
+ BufferedInputStream inputStream = null;
try
{
- String file = null;
-
- if (environment.containsKey(Context.PROVIDER_URL))
- {
- file = (String) environment.get(Context.PROVIDER_URL);
- }
- else
- {
- file = System.getProperty(Context.PROVIDER_URL);
- }
+ String fileName = (environment.containsKey(Context.PROVIDER_URL))
+ ? (String)environment.get(Context.PROVIDER_URL) : System.getProperty(Context.PROVIDER_URL);
- // Load the properties specified
- if (file != null)
+ if (fileName != null)
{
- _logger.info("Loading Properties from:" + file);
- BufferedInputStream inputStream = null;
+ _logger.info("Attempting to load " + fileName);
- if(file.contains("file:"))
- {
- inputStream = new BufferedInputStream(new FileInputStream(new File(new URI(file))));
- }
- else
- {
- inputStream = new BufferedInputStream(new FileInputStream(file));
- }
-
+ inputStream = new BufferedInputStream(new FileInputStream((fileName.contains("file:"))
+ ? new File(new URI(fileName)) : new File(fileName)));
Properties p = new Properties();
-
- try
- {
- p.load(inputStream);
- }
- finally
- {
- inputStream.close();
- }
+ p.load(inputStream);
Strings.Resolver resolver = new Strings.ChainedResolver
(Strings.SYSTEM_RESOLVER, new Strings.PropertiesResolver(p));
@@ -134,12 +109,23 @@ public class PropertiesFileInitialContextFactory implements InitialContextFactor
catch (IOException ioe)
{
_logger.warn("Unable to load property file specified in Provider_URL:" + environment.get(Context.PROVIDER_URL) +"\n" +
- "Due to:"+ioe.getMessage());
+ "Due to:" + ioe.getMessage());
}
catch(URISyntaxException uoe)
{
_logger.warn("Unable to load property file specified in Provider_URL:" + environment.get(Context.PROVIDER_URL) +"\n" +
- "Due to:"+uoe.getMessage());
+ "Due to:" + uoe.getMessage());
+ }
+ finally
+ {
+ try
+ {
+ if(inputStream != null)
+ {
+ inputStream.close();
+ }
+ }
+ catch(Exception ignore){}
}
createConnectionFactories(data, environment);
diff --git a/java/client/src/main/java/org/apache/qpid/nclient/util/ByteBufferMessage.java b/java/client/src/main/java/org/apache/qpid/nclient/util/ByteBufferMessage.java
index 7134f0a960..e8455f6dfa 100644
--- a/java/client/src/main/java/org/apache/qpid/nclient/util/ByteBufferMessage.java
+++ b/java/client/src/main/java/org/apache/qpid/nclient/util/ByteBufferMessage.java
@@ -1,4 +1,3 @@
-package org.apache.qpid.nclient.util;
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
@@ -19,6 +18,7 @@ package org.apache.qpid.nclient.util;
* under the License.
*
*/
+package org.apache.qpid.nclient.util;
import org.apache.qpid.api.Message;
diff --git a/java/client/src/main/java/org/apache/qpid/nclient/util/MessagePartListenerAdapter.java b/java/client/src/main/java/org/apache/qpid/nclient/util/MessagePartListenerAdapter.java
index 9a2e9de3d9..a3fce7611f 100644
--- a/java/client/src/main/java/org/apache/qpid/nclient/util/MessagePartListenerAdapter.java
+++ b/java/client/src/main/java/org/apache/qpid/nclient/util/MessagePartListenerAdapter.java
@@ -1,4 +1,3 @@
-package org.apache.qpid.nclient.util;
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
@@ -19,6 +18,7 @@ package org.apache.qpid.nclient.util;
* under the License.
*
*/
+package org.apache.qpid.nclient.util;
import org.apache.qpid.nclient.MessagePartListener;
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/client/AMQConnectionFactoryTest.java
index 20496026ce..bb92fa4ecd 100644
--- a/java/client/src/test/java/org/apache/qpid/test/unit/jndi/ConnectionFactoryTest.java
+++ b/java/client/src/test/java/org/apache/qpid/client/AMQConnectionFactoryTest.java
@@ -18,7 +18,9 @@
* under the License.
*
*/
-package org.apache.qpid.test.unit.jndi;
+package org.apache.qpid.client;
+
+import javax.jms.JMSException;
import junit.framework.TestCase;
@@ -26,7 +28,7 @@ import org.apache.qpid.client.AMQConnectionFactory;
import org.apache.qpid.jms.BrokerDetails;
import org.apache.qpid.jms.ConnectionURL;
-public class ConnectionFactoryTest extends TestCase
+public class AMQConnectionFactoryTest extends TestCase
{
//URL will be returned with the password field swapped for '********'
@@ -58,6 +60,20 @@ public class ConnectionFactoryTest extends TestCase
assertEquals("tcp", service.getTransport());
assertEquals("localhost", service.getHost());
assertEquals(5672, service.getPort());
+ }
+
+ public void testInstanceCreatedWithDefaultConstructorThrowsExceptionOnCallingConnectWithoutSettingURL() throws Exception
+ {
+ AMQConnectionFactory factory = new AMQConnectionFactory();
+ try
+ {
+ factory.createConnection();
+ fail("Expected exception not thrown");
+ }
+ catch(JMSException e)
+ {
+ assertEquals("Unexpected exception", AMQConnectionFactory.NO_URL_CONFIGURED, e.getMessage());
+ }
}
}
diff --git a/java/client/src/test/java/org/apache/qpid/client/message/AbstractJMSMessageTest.java b/java/client/src/test/java/org/apache/qpid/client/message/AbstractJMSMessageTest.java
index 1fbd7cf212..c535fdd705 100644
--- a/java/client/src/test/java/org/apache/qpid/client/message/AbstractJMSMessageTest.java
+++ b/java/client/src/test/java/org/apache/qpid/client/message/AbstractJMSMessageTest.java
@@ -1,4 +1,3 @@
-package org.apache.qpid.client.message;
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
@@ -19,6 +18,7 @@ package org.apache.qpid.client.message;
* under the License.
*
*/
+package org.apache.qpid.client.message;
import junit.framework.TestCase;
diff --git a/java/client/src/test/java/org/apache/qpid/jndi/PropertiesFileInitialContextFactoryTest.java b/java/client/src/test/java/org/apache/qpid/jndi/PropertiesFileInitialContextFactoryTest.java
index 2989970dcd..ce9e681eaf 100644
--- a/java/client/src/test/java/org/apache/qpid/jndi/PropertiesFileInitialContextFactoryTest.java
+++ b/java/client/src/test/java/org/apache/qpid/jndi/PropertiesFileInitialContextFactoryTest.java
@@ -21,51 +21,47 @@
package org.apache.qpid.jndi;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
import java.util.Properties;
+import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.Queue;
import javax.jms.Topic;
import javax.naming.ConfigurationException;
import javax.naming.Context;
import javax.naming.InitialContext;
+import javax.naming.NamingException;
-import junit.framework.TestCase;
-
+import org.apache.qpid.client.AMQConnectionFactory;
import org.apache.qpid.client.AMQDestination;
+import org.apache.qpid.configuration.ClientProperties;
import org.apache.qpid.framing.AMQShortString;
+import org.apache.qpid.test.utils.QpidTestCase;
-public class PropertiesFileInitialContextFactoryTest extends TestCase
+public class PropertiesFileInitialContextFactoryTest extends QpidTestCase
{
- private static final String FILE_URL_PATH = System.getProperty("user.dir") + "/client/src/test/java/org/apache/qpid/jndi/";
- private static final String FILE_NAME = "hello.properties";
-
- private Context ctx;
-
- protected void setUp() throws Exception
- {
- Properties properties = new Properties();
- properties.load(this.getClass().getResourceAsStream("JNDITest.properties"));
-
- //Create the initial context
- ctx = new InitialContext(properties);
- }
-
+ private static final String CONNECTION_URL = "amqp://username:password@clientid/test?brokerlist='tcp://testContextFromProviderURL:5672'";
public void testQueueNamesWithTrailingSpaces() throws Exception
{
+ Context ctx = prepareContext();
Queue queue = (Queue)ctx.lookup("QueueNameWithSpace");
assertEquals("QueueNameWithSpace",queue.getQueueName());
}
public void testTopicNamesWithTrailingSpaces() throws Exception
{
+ Context ctx = prepareContext();
Topic topic = (Topic)ctx.lookup("TopicNameWithSpace");
assertEquals("TopicNameWithSpace",topic.getTopicName());
}
public void testMultipleTopicNamesWithTrailingSpaces() throws Exception
{
+ Context ctx = prepareContext();
Topic topic = (Topic)ctx.lookup("MultipleTopicNamesWithSpace");
int i = 0;
for (AMQShortString bindingKey: ((AMQDestination)topic).getBindingKeys())
@@ -83,13 +79,59 @@ public class PropertiesFileInitialContextFactoryTest extends TestCase
try
{
- ctx = new InitialContext(properties);
+ 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}"));
}
+ }
+
+ private InitialContext prepareContext() throws IOException, NamingException
+ {
+ Properties properties = new Properties();
+ properties.load(this.getClass().getResourceAsStream("JNDITest.properties"));
+ return new InitialContext(properties);
+ }
+
+ /**
+ * Test loading of a JNDI properties file through use of a file:// URL
+ * supplied via the InitialContext.PROVIDER_URL system property.
+ */
+ public void testContextFromProviderURL() throws Exception
+ {
+ Properties properties = new Properties();
+ properties.put("connectionfactory.qpidConnectionfactory", CONNECTION_URL);
+ properties.put("destination.topicExchange", "destName");
+
+ File f = File.createTempFile(getTestName(), ".properties");
+ try
+ {
+ FileOutputStream fos = new FileOutputStream(f);
+ properties.store(fos, null);
+ fos.close();
+
+ setTestSystemProperty(ClientProperties.DEST_SYNTAX, "ADDR");
+ setTestSystemProperty(InitialContext.INITIAL_CONTEXT_FACTORY, "org.apache.qpid.jndi.PropertiesFileInitialContextFactory");
+ setTestSystemProperty(InitialContext.PROVIDER_URL, "file://" + f.getCanonicalPath());
+
+ InitialContext context = new InitialContext();
+ Destination dest = (Destination) context.lookup("topicExchange");
+ assertNotNull("Lookup from URI based context should not be null", dest);
+ assertTrue("Unexpected value from lookup", dest.toString().contains("destName"));
+
+ ConnectionFactory factory = (ConnectionFactory) context.lookup("qpidConnectionfactory");
+ assertTrue("ConnectionFactory was not an instance of AMQConnectionFactory", factory instanceof AMQConnectionFactory);
+ assertEquals("Unexpected ConnectionURL value", CONNECTION_URL.replaceAll("password", "********"),
+ ((AMQConnectionFactory)factory).getConnectionURLString());
+
+ context.close();
+ }
+ finally
+ {
+ f.delete();
+ }
}
}
diff --git a/java/client/src/test/java/org/apache/qpid/jndi/hello.properties b/java/client/src/test/java/org/apache/qpid/jndi/hello.properties
deleted file mode 100644
index d017d137fe..0000000000
--- a/java/client/src/test/java/org/apache/qpid/jndi/hello.properties
+++ /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.
-#
-java.naming.factory.initial = org.apache.qpid.jndi.PropertiesFileInitialContextFactory
-
-# register some connection factories
-# connectionfactory.[jndiname] = [ConnectionURL]
-connectionfactory.qpidConnectionfactory = amqp://guest:guest@clientid/test?brokerlist='tcp://10.0.1.46:5672'
-
-# Register an AMQP destination in JNDI
-# destination.[jniName] = [Address Format]
-destination.topicExchange = amq.topic
diff --git a/java/common.xml b/java/common.xml
index 2059e0aeb9..7e7b9c0c07 100644
--- a/java/common.xml
+++ b/java/common.xml
@@ -18,12 +18,12 @@
- under the License.
-
-->
-<project name="common">
+<project xmlns:ivy="antlib:org.apache.ivy.ant" name="common">
<dirname property="project.root" file="${ant.file.common}"/>
<property name="project.name" value="qpid"/>
- <property name="project.version" value="0.17"/>
+ <property name="project.version" value="0.19"/>
<property name="project.url" value="http://qpid.apache.org"/>
<property name="project.groupid" value="org.apache.qpid"/>
<property name="project.namever" value="${project.name}-${project.version}"/>
@@ -43,7 +43,8 @@
<property name="build.release" location="${build}/release"/>
<property name="build.release.prepare" location="${build.release}/prepare"/>
<property name="build.plugins" location="${build}/lib/plugins"/>
- <property name="build.coveragereport" location="${build}/coverage"/>
+ <property name="build.coverage.report" location="${build}/coverage/report"/>
+ <property name="build.coverage.src" location="${build}/coverage/src"/>
<property name="build.findbugs" location="${build}/findbugs"/>
<property name="java.target" value="1.5"/>
@@ -62,10 +63,12 @@
<property name="cobertura.dir" value="${project.root}/lib/cobertura" />
<property name="cobertura.version" value="1.9.4.1" />
- <property name="cobertura.download.url"
- value="http://downloads.sourceforge.net/project/cobertura/cobertura/${cobertura.version}/cobertura-${cobertura.version}-bin.zip" />
- <property name="cobertura.zip.filename" value="cobertura-${cobertura.version}-bin.zip" />
- <property name="cobertura.temp.dir" value="${cobertura.dir}"/>
+
+ <path id="cobertura.classpath">
+ <fileset dir="${cobertura.dir}">
+ <include name="**/*.jar" />
+ </fileset>
+ </path>
<property name="mllib.dir" value="${project.root}/../python" />
<property name="findbugs.dir" value="${project.root}/lib/findbugs" />
@@ -75,13 +78,7 @@
<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-${cobertura.version}/*.jar" />
- <include name="cobertura-${cobertura.version}/**/lib/*.jar" />
- </fileset>
- </path>
-
+ <!-- properties for generating the maven artifacts -->
<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"/>
@@ -90,6 +87,52 @@
<isfalse value="${maven.snapshot}"/>
</condition>
+ <!-- properties for uploading our Maven artifacts to Nexus using Ivy -->
+ <property name="ivy.organisation" value="org/apache"/>
+ <property name="nexus.organisation" value="org.apache"/>
+ <property name="nexus.host" value="repository.apache.org"/>
+ <property name="nexus.upload.url" value="https://${nexus.host}/service/local/staging/deploy/maven2"/>
+
+ <!-- properties for downloading ivy, and then our dependencies -->
+ <property name="ivy.jar.dir" value="${project.root}/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"/>
+ <property name="ivy.jar.url" value="${ivy.repo.url}/${ivy.install.version}/ivy-${ivy.install.version}.jar"/>
+
+ <available property="ivy.jar.file.exists" file="${ivy.jar.file}"/>
+ <property name="retrieve.dependencies" value="true" />
+ <property name="optional.dependencies" value="false" />
+
+ <condition property="dont.download.ivy">
+ <!-- Set prop to stop Ivy download if asked not to retrieve
+ the dependencies, or the ivy jar is already present -->
+ <or>
+ <isfalse value="${retrieve.dependencies}"/>
+ <and>
+ <isset property="ivy.jar.file.exists"/>
+ <istrue value="${ivy.jar.file.exists}"/>
+ </and>
+ </or>
+ </condition>
+
+ <condition property="ivy.dont.retrieve">
+ <isfalse value="${retrieve.dependencies}"/>
+ </condition>
+ <condition property="ivy.configured">
+ <isfalse value="${retrieve.dependencies}"/>
+ </condition>
+ <condition property="ivy.retrieve.optional">
+ <and>
+ <istrue value="${retrieve.dependencies}"/>
+ <or>
+ <istrue value="${optional.dependencies}"/>
+ <istrue value="${optional}"/>
+ </or>
+ </and>
+ </condition>
+
+
<macrodef name="indirect">
<attribute name="name"/>
<attribute name="variable"/>
@@ -141,7 +184,7 @@
<attribute name="path"/>
<element name="args"/>
<sequential>
- <java jar="${project.root}/lib/jython-2.5.0.jar" fork="true" failonerror="true">
+ <java jar="${project.root}/${jython}" fork="true" failonerror="true">
<arg value="-Dpython.path=@{path}"/>
<args/>
</java>
@@ -175,6 +218,21 @@
</sequential>
</macrodef>
+ <macrodef name="copytofile">
+ <attribute name="tofile"/>
+ <attribute name="dir"/>
+ <attribute name="include"/>
+ <attribute name="failOnError" default="false"/>
+ <sequential>
+ <copy tofile="@{tofile}" failOnError="@{failOnError}">
+ <fileset dir="@{dir}">
+ <include name="@{include}"/>
+ </fileset>
+ </copy>
+ </sequential>
+ </macrodef>
+
+
<target name="clean-tasks">
<delete dir="${tasks.classes}"/>
</target>
@@ -198,29 +256,69 @@
<taskdef classpathref="cobertura.classpath" resource="tasks.properties" />
</target>
- <!--download Cobertura jar and expand-->
- <target name="download-cobertura" description="download Cobertura if not already present" depends="cobertura-check" unless="cobertura.already.exists">
- <mkdir dir="${cobertura.dir}"/>
- <echo>Downloading Cobertura ${cobertura.version}</echo>
- <get src="${cobertura.download.url}" dest="${cobertura.temp.dir}/${cobertura.zip.filename}" usetimestamp="false" />
- <echo>Extracting Cobertura JAR and dependencies</echo>
- <unzip src="${cobertura.temp.dir}/${cobertura.zip.filename}" dest="${cobertura.dir}"/>
- <echo>Cleanup Cobertura Download</echo>
- <delete file="${cobertura.temp.dir}/${cobertura.zip.filename}"/>
- <echo>Done</echo>
- </target>
+ <target name="findbugs-init">
- <target name="cobertura-check">
- <available property="cobertura.already.exists" file="${cobertura.dir}/cobertura-${cobertura.version}" type="dir"/>
- </target>
+ <mkdir dir="${findbugs.dir}"/>
+ <!-- Hack to make the FindBugs jars retrieved using Ivy work with the Ant Task,
+ because it expects certain jar names without versions like in the .zip release -->
+ <copytofile tofile="${findbugs.dir}/findbugs.jar" dir="${findbugs.dir}" include="findbugs-?.*.*.jar"/>
+ <copytofile tofile="${findbugs.dir}/findbugs-ant.jar" dir="${findbugs.dir}" include="findbugs-ant-?.*.*.jar"/>
+ <copytofile tofile="${findbugs.dir}/bcel.jar" dir="${findbugs.dir}" include="bcel-*.jar"/>
+ <copytofile tofile="${findbugs.dir}/annotations.jar" dir="${findbugs.dir}" include="annotations-?.*.*.jar"/>
+ <copytofile tofile="${findbugs.dir}/jsr305.jar" dir="${findbugs.dir}" include="jsr305-*.jar"/>
+ <copytofile tofile="${findbugs.dir}/jFormatString.jar" dir="${findbugs.dir}" include="jFormatString-*.jar"/>
- <target name="findbugs-init">
<available file="${findbugs.dir}/findbugs-ant.jar" property="findbugs-ant.jar.present"/>
- <fail unless="findbugs-ant.jar.present" message="Please follow the instructions at ${findbugs.dir}/README.txt to configure FindBugs"/>
+ <fail unless="findbugs-ant.jar.present" message="FindBugs was not found. Please add -Doptional.dependencies=true to your build command to retrieve FindBugs"/>
<taskdef name="findbugs" classname="edu.umd.cs.findbugs.anttask.FindBugsTask" classpath="${findbugs.dir}/findbugs-ant.jar"/>
</target>
+
+ <!-- targets for downloading ivy and retrieving dependencies -->
+ <target name="retrieve-dependencies" depends="load-ivy, configure-ivy, retrieve-optional-dependencies" unless="${ivy.dont.retrieve}">
+ <echo message="Resolving and retrieving dependencies..."/>
+ <ivy:resolve type="jar,bundle,war" file="${project.root}/ivy.retrieve.xml" conf="required"/>
+ <ivy:retrieve type="jar,bundle,war" conf="required" sync="true"
+ pattern="${project.root}/lib/required/[artifact]-[revision].[ext]" />
+ </target>
+
+ <target name="retrieve-optional-dependencies" if="${ivy.retrieve.optional}">
+ <echo message="Resolving and retrieving optional dependencies..."/>
+ <ivy:resolve type="jar" file="${project.root}/ivy.retrieve.xml" conf="findbugs"/>
+ <ivy:retrieve type="jar" conf="findbugs" sync="true"
+ pattern="${findbugs.dir}/[artifact]-[revision].[ext]" />
+
+ <ivy:resolve type="jar" file="${project.root}/ivy.retrieve.xml" conf="cobertura"/>
+ <ivy:retrieve type="jar" conf="cobertura" sync="true"
+ pattern="${cobertura.dir}/[artifact]-[revision].[ext]" />
+ </target>
+
+
+ <target name="configure-ivy" unless="${ivy.configured}">
+ <ivy:configure file="${project.root}/ivysettings.retrieve.xml" override="true"/>
+ <property name="ivy.configured" value="true" />
+ </target>
+
+ <target name="load-ivy" depends="download-ivy" unless="${ivy.dont.retrieve}">
+ <!-- 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>
+
+ <target name="download-ivy" unless="${dont.download.ivy}">
+ <mkdir dir="${ivy.jar.dir}"/>
+ <echo message="Downloading ivy..."/>
+ <get src="${ivy.jar.url}" dest="${ivy.jar.file}" usetimestamp="true"/>
+ </target>
+
+
<target name="help" description="display detailed build documentation">
<echo>
ant build
diff --git a/java/common/build.xml b/java/common/build.xml
index fe96f384d5..9caf93c026 100644
--- a/java/common/build.xml
+++ b/java/common/build.xml
@@ -98,13 +98,19 @@ public class QpidBuildVersion
</target>
<target name="jms-selector">
+ <copy tofile="${module.build}/javacc.jar" failonerror="true">
+ <fileset dir="${project.root}/lib/required">
+ <include name="javacc-*.jar"/>
+ </fileset>
+ </copy>
<mkdir dir="${selector.output.dir}"/>
<javacc target="src/main/grammar/SelectorParser.jj"
outputdirectory="${selector.output.dir}"
- javacchome="${project.root}/lib"/>
+ javacchome="${module.build}"/>
</target>
<target name="precompile" depends="gentools,jython,create-version,build-version,jms-selector"/>
<target name="bundle" depends="bundle-tasks"/>
+
</project>
diff --git a/java/common/src/main/java/common.bnd b/java/common/src/main/java/common.bnd
index 9149986aa3..b34f8deacc 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.17.0
+ver: 0.19.0
Bundle-SymbolicName: qpid-common
Bundle-Version: ${ver}
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..2d54e35191 100644
--- a/java/common/src/main/java/org/apache/qpid/AMQException.java
+++ b/java/common/src/main/java/org/apache/qpid/AMQException.java
@@ -40,6 +40,8 @@ public class AMQException extends Exception
/** Holds the AMQ error code constant associated with this exception. */
private AMQConstant _errorCode;
+ private boolean _isHardError;
+
/**
* Creates an exception with an optional error code, optional message and optional underlying cause.
*
@@ -49,8 +51,24 @@ public class AMQException extends Exception
*/
public AMQException(AMQConstant errorCode, String msg, Throwable cause)
{
+ // isHardError is defaulted to true to avoid unnessacery modification to
+ // existing code.
+ this(errorCode,true,msg,cause);
+ }
+
+ /**
+ * Creates an exception with an optional error code, optional message and optional underlying cause.
+ *
+ * @param errorCode The error code. May be null if not to be set.
+ * @param isHardError Denotes if the underlying error is considered a hard error.
+ * @param msg The exception message. May be null if not to be set.
+ * @param cause The underlying cause of the exception. May be null if not to be set.
+ */
+ public AMQException(AMQConstant errorCode, boolean isHardError, String msg, Throwable cause)
+ {
super(((msg == null) ? "" : msg), cause);
_errorCode = errorCode;
+ _isHardError = isHardError;
}
/*
@@ -92,7 +110,7 @@ public class AMQException extends Exception
public boolean isHardError()
{
- return true;
+ return _isHardError;
}
/**
diff --git a/java/common/src/main/java/org/apache/qpid/AMQProtocolException.java b/java/common/src/main/java/org/apache/qpid/AMQProtocolException.java
index bbc569839a..7744b128ce 100644
--- a/java/common/src/main/java/org/apache/qpid/AMQProtocolException.java
+++ b/java/common/src/main/java/org/apache/qpid/AMQProtocolException.java
@@ -1,8 +1,5 @@
-package org.apache.qpid;
-
-import org.apache.qpid.protocol.AMQConstant;
-
-/* Licensed to the Apache Software Foundation (ASF) under one
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
@@ -19,6 +16,10 @@ import org.apache.qpid.protocol.AMQConstant;
* specific language governing permissions and limitations
* under the License.
*/
+package org.apache.qpid;
+
+import org.apache.qpid.protocol.AMQConstant;
+
public class AMQProtocolException extends AMQException
{
diff --git a/java/common/src/main/java/org/apache/qpid/api/Message.java b/java/common/src/main/java/org/apache/qpid/api/Message.java
index 49c7be162c..c0427c2f37 100644
--- a/java/common/src/main/java/org/apache/qpid/api/Message.java
+++ b/java/common/src/main/java/org/apache/qpid/api/Message.java
@@ -1,12 +1,3 @@
-package org.apache.qpid.api;
-
-import org.apache.qpid.transport.DeliveryProperties;
-import org.apache.qpid.transport.Header;
-import org.apache.qpid.transport.MessageProperties;
-
-import java.io.IOException;
-import java.nio.ByteBuffer;
-
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
@@ -25,6 +16,14 @@ import java.nio.ByteBuffer;
* specific language governing permissions and limitations
* under the License.
*/
+package org.apache.qpid.api;
+
+import org.apache.qpid.transport.DeliveryProperties;
+import org.apache.qpid.transport.Header;
+import org.apache.qpid.transport.MessageProperties;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
public interface Message
{
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 3227bb6fc2..97fbd43ea0 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
@@ -168,4 +168,28 @@ public class ClientProperties
public static final String SEND_BUFFER_SIZE_PROP_NAME = "qpid.send_buffer_size";
@Deprecated
public static final String LEGACY_SEND_BUFFER_SIZE_PROP_NAME = "amqj.sendBufferSize";
+
+ /**
+ * System property to set the time (in millis) to wait before failing when sending and
+ * the client has been flow controlled by the broker.
+ */
+ public static final String QPID_FLOW_CONTROL_WAIT_FAILURE = "qpid.flow_control_wait_failure";
+
+ /**
+ * Default time (in millis) to wait before failing when sending and the client has been
+ * flow controlled by the broker.
+ */
+ public static final long DEFAULT_FLOW_CONTROL_WAIT_FAILURE = 60000L;
+
+ /**
+ * System property to set the time (in millis) between log notifications that a
+ * send is waiting because the client was flow controlled by the broker.
+ */
+ public static final String QPID_FLOW_CONTROL_WAIT_NOTIFY_PERIOD = "qpid.flow_control_wait_notify_period";
+
+ /**
+ * Default time (in millis) between log notifications that a send is
+ * waiting because the client was flow controlled by the broker.
+ */
+ public static final long DEFAULT_FLOW_CONTROL_WAIT_NOTIFY_PERIOD = 5000L;
}
diff --git a/java/common/src/main/java/org/apache/qpid/configuration/Validator.java b/java/common/src/main/java/org/apache/qpid/configuration/Validator.java
index 13f7954bbc..e65bddf10b 100644
--- a/java/common/src/main/java/org/apache/qpid/configuration/Validator.java
+++ b/java/common/src/main/java/org/apache/qpid/configuration/Validator.java
@@ -1,4 +1,3 @@
-package org.apache.qpid.configuration;
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
@@ -19,6 +18,7 @@ package org.apache.qpid.configuration;
* under the License.
*
*/
+package org.apache.qpid.configuration;
public interface Validator
diff --git a/java/common/src/main/java/org/apache/qpid/filter/FilterableMessage.java b/java/common/src/main/java/org/apache/qpid/filter/FilterableMessage.java
index b5b00ae70f..98c34bafd2 100644
--- a/java/common/src/main/java/org/apache/qpid/filter/FilterableMessage.java
+++ b/java/common/src/main/java/org/apache/qpid/filter/FilterableMessage.java
@@ -1,21 +1,21 @@
-package org.apache.qpid.filter;
-
-/**
+/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
- * <p/>
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- * <p/>
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+package org.apache.qpid.filter;
+
public interface FilterableMessage
{
diff --git a/java/common/src/main/java/org/apache/qpid/filter/SelectorParsingException.java b/java/common/src/main/java/org/apache/qpid/filter/SelectorParsingException.java
index f08b3df155..53909a0009 100644
--- a/java/common/src/main/java/org/apache/qpid/filter/SelectorParsingException.java
+++ b/java/common/src/main/java/org/apache/qpid/filter/SelectorParsingException.java
@@ -1,5 +1,3 @@
-package org.apache.qpid.filter;
-
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
@@ -7,15 +5,17 @@ package org.apache.qpid.filter;
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
- * <p/>
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- * <p/>
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+package org.apache.qpid.filter;
+
public class SelectorParsingException extends RuntimeException
{
public SelectorParsingException(String s)
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 d6f518b123..571570d7b4 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
@@ -1,5 +1,3 @@
-package org.apache.qpid.framing;
-
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
@@ -20,6 +18,8 @@ package org.apache.qpid.framing;
* under the License.
*
*/
+package org.apache.qpid.framing;
+
import org.apache.qpid.AMQChannelException;
import org.apache.qpid.AMQConnectionException;
diff --git a/java/common/src/main/java/org/apache/qpid/framing/AMQShortStringTokenizer.java b/java/common/src/main/java/org/apache/qpid/framing/AMQShortStringTokenizer.java
index e2db8906a1..25ab60327a 100644
--- a/java/common/src/main/java/org/apache/qpid/framing/AMQShortStringTokenizer.java
+++ b/java/common/src/main/java/org/apache/qpid/framing/AMQShortStringTokenizer.java
@@ -1,5 +1,3 @@
-package org.apache.qpid.framing;
-
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
@@ -20,6 +18,9 @@ package org.apache.qpid.framing;
* under the License.
*
*/
+package org.apache.qpid.framing;
+
+
public interface AMQShortStringTokenizer
{
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 c9ff180c54..b2967bb0bb 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
@@ -39,7 +39,6 @@ import java.security.KeyStore;
*/
public class SSLContextFactory
{
- public static final String JAVA_KEY_STORE_CODE = "JKS";
public static final String TRANSPORT_LAYER_SECURITY_CODE = "TLS";
private SSLContextFactory()
@@ -48,28 +47,32 @@ public class SSLContextFactory
}
public static SSLContext buildServerContext(final String keyStorePath,
- final String keyStorePassword, final String keyManagerFactoryAlgorithm)
+ final String keyStorePassword, final String keyStoreType,
+ final String keyManagerFactoryAlgorithm)
throws GeneralSecurityException, IOException
{
- return buildContext(null, null, null, keyStorePath, keyStorePassword,
+ return buildContext(null, null, null, null, keyStorePath, keyStorePassword, keyStoreType,
keyManagerFactoryAlgorithm, null);
}
public static SSLContext buildClientContext(final String trustStorePath,
- final String trustStorePassword, final String trustManagerFactoryAlgorithm,
- final String keyStorePath, final String keyStorePassword,
+ final String trustStorePassword, final String trustStoreType,
+ final String trustManagerFactoryAlgorithm, final String keyStorePath,
+ final String keyStorePassword, final String keyStoreType,
final String keyManagerFactoryAlgorithm, final String certAlias)
throws GeneralSecurityException, IOException
{
- return buildContext(trustStorePath, trustStorePassword,
- trustManagerFactoryAlgorithm, keyStorePath, keyStorePassword,
+ return buildContext(trustStorePath, trustStorePassword, trustStoreType,
+ trustManagerFactoryAlgorithm, keyStorePath, keyStorePassword, keyStoreType,
keyManagerFactoryAlgorithm, certAlias);
}
private static SSLContext buildContext(final String trustStorePath,
- final String trustStorePassword, final String trustManagerFactoryAlgorithm,
- final String keyStorePath, final String keyStorePassword,
- final String keyManagerFactoryAlgorithm, final String certAlias)
+ final String trustStorePassword, final String trustStoreType,
+ final String trustManagerFactoryAlgorithm,
+ final String keyStorePath, final String keyStorePassword,
+ final String keyStoreType, final String keyManagerFactoryAlgorithm,
+ final String certAlias)
throws GeneralSecurityException, IOException
{
// Initialize the SSLContext to work with our key managers.
@@ -82,7 +85,7 @@ public class SSLContextFactory
if (trustStorePath != null)
{
final KeyStore ts = SSLUtil.getInitializedKeyStore(trustStorePath,
- trustStorePassword);
+ trustStorePassword, trustStoreType);
final TrustManagerFactory tmf = TrustManagerFactory
.getInstance(trustManagerFactoryAlgorithm);
tmf.init(ts);
@@ -99,13 +102,13 @@ public class SSLContextFactory
if (certAlias != null)
{
keyManagers = new KeyManager[] { new QpidClientX509KeyManager(
- certAlias, keyStorePath, keyStorePassword,
+ certAlias, keyStorePath, keyStoreType, keyStorePassword,
keyManagerFactoryAlgorithm) };
}
else
{
final KeyStore ks = SSLUtil.getInitializedKeyStore(
- keyStorePath, keyStorePassword);
+ keyStorePath, keyStorePassword, keyStoreType);
char[] keyStoreCharPassword = keyStorePassword == null ? null : keyStorePassword.toCharArray();
// Set up key manager factory to use our key store
diff --git a/java/common/src/main/java/org/apache/qpid/thread/RealtimeThreadFactory.java b/java/common/src/main/java/org/apache/qpid/thread/RealtimeThreadFactory.java
index 95a8d192c5..631ee98b94 100644
--- a/java/common/src/main/java/org/apache/qpid/thread/RealtimeThreadFactory.java
+++ b/java/common/src/main/java/org/apache/qpid/thread/RealtimeThreadFactory.java
@@ -1,4 +1,3 @@
-package org.apache.qpid.thread;
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
@@ -19,6 +18,7 @@ package org.apache.qpid.thread;
* under the License.
*
*/
+package org.apache.qpid.thread;
import java.lang.reflect.Constructor;
diff --git a/java/common/src/main/java/org/apache/qpid/thread/ThreadFactory.java b/java/common/src/main/java/org/apache/qpid/thread/ThreadFactory.java
index 4b8937acbd..c8f1cbfcba 100644
--- a/java/common/src/main/java/org/apache/qpid/thread/ThreadFactory.java
+++ b/java/common/src/main/java/org/apache/qpid/thread/ThreadFactory.java
@@ -1,4 +1,3 @@
-package org.apache.qpid.thread;
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
@@ -19,6 +18,7 @@ package org.apache.qpid.thread;
* under the License.
*
*/
+package org.apache.qpid.thread;
public interface ThreadFactory
diff --git a/java/common/src/main/java/org/apache/qpid/thread/Threading.java b/java/common/src/main/java/org/apache/qpid/thread/Threading.java
index 265b336157..d3ccc138dd 100644
--- a/java/common/src/main/java/org/apache/qpid/thread/Threading.java
+++ b/java/common/src/main/java/org/apache/qpid/thread/Threading.java
@@ -1,4 +1,3 @@
-package org.apache.qpid.thread;
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
@@ -19,6 +18,7 @@ package org.apache.qpid.thread;
* under the License.
*
*/
+package org.apache.qpid.thread;
public final class Threading
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 2cd6a6e465..388e3442bf 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
@@ -41,6 +41,8 @@ import static org.apache.qpid.transport.Connection.State.OPENING;
import javax.security.sasl.SaslClient;
import javax.security.sasl.SaslServer;
+
+import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Collection;
@@ -127,6 +129,9 @@ public class Connection extends ConnectionInvoker
private final AtomicBoolean connectionLost = new AtomicBoolean(false);
+ private SocketAddress _remoteAddress;
+ private SocketAddress _localAddress;
+
public Connection() {}
public void setConnectionDelegate(ConnectionDelegate delegate)
@@ -228,6 +233,9 @@ public class Connection extends ConnectionInvoker
}
NetworkConnection network = transport.connect(settings, secureReceiver, null);
+ _remoteAddress = network.getRemoteAddress();
+ _localAddress = network.getLocalAddress();
+
final Sender<ByteBuffer> secureSender = securityLayer.sender(network.getSender());
if(secureSender instanceof ConnectionListener)
{
@@ -701,4 +709,14 @@ public class Connection extends ConnectionInvoker
ssn.notifyFailoverRequired();
}
}
+
+ public SocketAddress getRemoteAddress()
+ {
+ return _remoteAddress;
+ }
+
+ public SocketAddress getLocalAddress()
+ {
+ return _localAddress;
+ }
}
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 084428d182..c90a11594c 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
@@ -31,6 +31,7 @@ import static org.apache.qpid.configuration.ClientProperties.SEND_BUFFER_SIZE_PR
import static org.apache.qpid.configuration.ClientProperties.LEGACY_RECEIVE_BUFFER_SIZE_PROP_NAME;
import static org.apache.qpid.configuration.ClientProperties.LEGACY_SEND_BUFFER_SIZE_PROP_NAME;
+import java.security.KeyStore;
import java.util.Map;
import javax.net.ssl.KeyManagerFactory;
@@ -67,10 +68,12 @@ public class ConnectionSettings
private boolean useSSL;
private String keyStorePath = System.getProperty("javax.net.ssl.keyStore");
private String keyStorePassword = System.getProperty("javax.net.ssl.keyStorePassword");
+ private String keyStoreType = System.getProperty("javax.net.ssl.keyStoreType",KeyStore.getDefaultType());
private String keyManagerFactoryAlgorithm = QpidProperty.stringProperty(KeyManagerFactory.getDefaultAlgorithm(), QPID_SSL_KEY_MANAGER_FACTORY_ALGORITHM_PROP_NAME, QPID_SSL_KEY_STORE_CERT_TYPE_PROP_NAME).get();
private String trustManagerFactoryAlgorithm = QpidProperty.stringProperty(TrustManagerFactory.getDefaultAlgorithm(), QPID_SSL_TRUST_MANAGER_FACTORY_ALGORITHM_PROP_NAME, QPID_SSL_TRUST_STORE_CERT_TYPE_PROP_NAME).get();
- private String trustStorePath = System.getProperty("javax.net.ssl.trustStore");;
- private String trustStorePassword = System.getProperty("javax.net.ssl.trustStorePassword");;
+ private String trustStorePath = System.getProperty("javax.net.ssl.trustStore");
+ private String trustStorePassword = System.getProperty("javax.net.ssl.trustStorePassword");
+ private String trustStoreType = System.getProperty("javax.net.ssl.trustStoreType",KeyStore.getDefaultType());
private String certAlias;
private boolean verifyHostname;
@@ -262,6 +265,16 @@ public class ConnectionSettings
this.keyStorePassword = keyStorePassword;
}
+ public void setKeyStoreType(String keyStoreType)
+ {
+ this.keyStoreType = keyStoreType;
+ }
+
+ public String getKeyStoreType()
+ {
+ return keyStoreType;
+ }
+
public String getTrustStorePath()
{
return trustStorePath;
@@ -322,6 +335,16 @@ public class ConnectionSettings
this.trustManagerFactoryAlgorithm = trustManagerFactoryAlgorithm;
}
+ public String getTrustStoreType()
+ {
+ return trustStoreType;
+ }
+
+ public void setTrustStoreType(String trustStoreType)
+ {
+ this.trustStoreType = trustStoreType;
+ }
+
public int getReadBufferSize()
{
return readBufferSize;
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
index 472beb6bb1..20d6f98fa6 100644
--- a/java/common/src/main/java/org/apache/qpid/transport/NetworkTransportConfiguration.java
+++ b/java/common/src/main/java/org/apache/qpid/transport/NetworkTransportConfiguration.java
@@ -25,17 +25,17 @@ import java.net.InetSocketAddress;
/**
* 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();
+ * 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 incoming buffer
+ Integer getReceiveBufferSize();
- // The amount of memory in bytes to allocate to the outgoing buffer
+ // The amount of memory in bytes to allocate to the outgoing buffer
Integer getSendBufferSize();
Integer getPort();
@@ -47,4 +47,8 @@ public interface NetworkTransportConfiguration
Integer getConnectorProcessors();
InetSocketAddress getAddress();
+
+ boolean needClientAuth();
+
+ boolean wantClientAuth();
}
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 ec409d1c72..e9a7d51456 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
@@ -78,7 +78,7 @@ public class ServerDelegate extends ConnectionDelegate
try
{
- SaslServer ss = createSaslServer(mechanism);
+ SaslServer ss = createSaslServer(conn, mechanism);
if (ss == null)
{
conn.connectionClose(ConnectionCloseCode.CONNECTION_FORCED,
@@ -94,7 +94,7 @@ public class ServerDelegate extends ConnectionDelegate
}
}
- protected SaslServer createSaslServer(String mechanism)
+ protected SaslServer createSaslServer(Connection conn, String mechanism)
throws SaslException
{
SaslServer ss = Sasl.createSaslServer(mechanism, "AMQP", "localhost", null, null);
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 110c73f718..95c3e4669f 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
@@ -94,8 +94,10 @@ public class Session extends SessionInvoker
private final long timeout = Long.getLong(ClientProperties.QPID_SYNC_OP_TIMEOUT,
Long.getLong(ClientProperties.AMQJ_DEFAULT_SYNCWRITE_TIMEOUT,
ClientProperties.DEFAULT_SYNC_OPERATION_TIMEOUT));
- private final long blockedSendTimeout = Long.getLong("qpid.flow_control_wait_failure", timeout);
- private long blockedSendReportingPeriod = Long.getLong("qpid.flow_control_wait_notify_period",5000L);
+ private final long blockedSendTimeout = Long.getLong(ClientProperties.QPID_FLOW_CONTROL_WAIT_FAILURE,
+ ClientProperties.DEFAULT_FLOW_CONTROL_WAIT_FAILURE);
+ private long blockedSendReportingPeriod = Long.getLong(ClientProperties.QPID_FLOW_CONTROL_WAIT_NOTIFY_PERIOD,
+ ClientProperties.DEFAULT_FLOW_CONTROL_WAIT_NOTIFY_PERIOD);
private boolean autoSync = false;
@@ -210,6 +212,11 @@ public class Session extends SessionInvoker
}
}
+ protected State getState()
+ {
+ return this.state;
+ }
+
void setFlowControl(boolean value)
{
flowControl = value;
@@ -307,7 +314,7 @@ public class Session extends SessionInvoker
xfr.setHeader(new Header(deliveryProps, header.getMessageProperties(),
header.getNonStandardProperties()));
}
-
+
}
else
{
@@ -616,7 +623,7 @@ public class Session extends SessionInvoker
{
acquireCredit();
}
-
+
synchronized (commandsLock)
{
if (state == DETACHED && m.isUnreliable())
@@ -732,11 +739,11 @@ public class Session extends SessionInvoker
{
sessionCommandPoint(0, 0);
}
-
+
boolean replayTransfer = !closing && !transacted &&
m instanceof MessageTransfer &&
! m.isUnreliable();
-
+
if ((replayTransfer) || m.hasCompletionListener())
{
setCommand(next, m);
@@ -833,7 +840,7 @@ public class Session extends SessionInvoker
Waiter w = new Waiter(commandsLock, timeout);
while (w.hasTime() && state != CLOSED && lt(maxComplete, point))
{
- checkFailoverRequired("Session sync was interrupted by failover.");
+ checkFailoverRequired("Session sync was interrupted by failover.");
if(log.isDebugEnabled())
{
log.debug("%s waiting for[%d]: %d, %s", this, point, maxComplete, commands);
@@ -871,7 +878,7 @@ public class Session extends SessionInvoker
{
future = results.remove(command);
}
-
+
if (future != null)
{
future.set(result);
@@ -1039,7 +1046,7 @@ public class Session extends SessionInvoker
}
}
- protected void awaitClose()
+ protected void awaitClose()
{
Waiter w = new Waiter(commandsLock, timeout);
while (w.hasTime() && state != CLOSED)
@@ -1096,7 +1103,7 @@ public class Session extends SessionInvoker
if(state == CLOSED)
{
- connection.removeSession(this);
+ connection.removeSession(this);
listener.closed(this);
}
}
@@ -1184,4 +1191,12 @@ public class Session extends SessionInvoker
}
}
}
+
+ /**
+ * An auxiliary method for test purposes only
+ */
+ public boolean isFlowBlocked()
+ {
+ return flowControl && credit.availablePermits() == 0;
+ }
}
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
index 2cc7c14f00..12c42d6643 100644
--- 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
@@ -20,10 +20,10 @@
*/
package org.apache.qpid.transport.network;
-import org.apache.qpid.transport.Sender;
-
import java.net.SocketAddress;
import java.nio.ByteBuffer;
+import java.security.Principal;
+import org.apache.qpid.transport.Sender;
public interface NetworkConnection
{
@@ -46,4 +46,8 @@ public interface NetworkConnection
void setMaxWriteIdle(int sec);
void setMaxReadIdle(int sec);
-} \ No newline at end of file
+
+ void setPeerPrincipal(Principal principal);
+
+ Principal getPeerPrincipal();
+}
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
index 4046691779..2658296c5f 100644
--- 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
@@ -20,16 +20,15 @@
*/
package org.apache.qpid.transport.network.io;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import org.apache.qpid.transport.Receiver;
-import org.apache.qpid.transport.Sender;
-import org.apache.qpid.transport.network.NetworkConnection;
-
import java.net.Socket;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
+import java.security.Principal;
+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
{
@@ -38,6 +37,7 @@ public class IoNetworkConnection implements NetworkConnection
private final long _timeout;
private final IoSender _ioSender;
private final IoReceiver _ioReceiver;
+ private Principal _principal;
public IoNetworkConnection(Socket socket, Receiver<ByteBuffer> delegate,
int sendBufferSize, int receiveBufferSize, long timeout)
@@ -97,4 +97,16 @@ public class IoNetworkConnection implements NetworkConnection
// TODO implement support for setting heartbeating config in this way
// Currently a socket timeout is used in IoSender
}
+
+ @Override
+ public void setPeerPrincipal(Principal principal)
+ {
+ _principal = principal;
+ }
+
+ @Override
+ public Principal getPeerPrincipal()
+ {
+ return _principal;
+ }
}
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 42c8334a5d..dfb318b80c 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
@@ -27,10 +27,12 @@ import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.nio.ByteBuffer;
-
+import java.security.Principal;
import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLPeerUnverifiedException;
+import javax.net.ssl.SSLServerSocket;
import javax.net.ssl.SSLServerSocketFactory;
-
+import javax.net.ssl.SSLSocket;
import org.apache.qpid.protocol.ProtocolEngine;
import org.apache.qpid.protocol.ProtocolEngineFactory;
import org.apache.qpid.transport.ConnectionSettings;
@@ -45,10 +47,10 @@ import org.slf4j.LoggerFactory;
public class IoNetworkTransport implements OutgoingNetworkTransport, IncomingNetworkTransport
{
private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(IoNetworkTransport.class);
+ private static final int TIMEOUT = 60000;
private Socket _socket;
private IoNetworkConnection _connection;
- private long _timeout = 60000;
private AcceptingThread _acceptor;
public NetworkConnection connect(ConnectionSettings settings, Receiver<ByteBuffer> delegate, SSLContext sslContext)
@@ -73,7 +75,7 @@ public class IoNetworkTransport implements OutgoingNetworkTransport, IncomingNet
InetAddress address = InetAddress.getByName(settings.getHost());
- _socket.connect(new InetSocketAddress(address, settings.getPort()));
+ _socket.connect(new InetSocketAddress(address, settings.getPort()), TIMEOUT);
}
catch (SocketException e)
{
@@ -86,7 +88,7 @@ public class IoNetworkTransport implements OutgoingNetworkTransport, IncomingNet
try
{
- _connection = new IoNetworkConnection(_socket, delegate, sendBufferSize, receiveBufferSize, _timeout);
+ _connection = new IoNetworkConnection(_socket, delegate, sendBufferSize, receiveBufferSize, TIMEOUT);
_connection.start();
}
catch(Exception e)
@@ -167,6 +169,9 @@ public class IoNetworkTransport implements OutgoingNetworkTransport, IncomingNet
{
SSLServerSocketFactory socketFactory = _sslContext.getServerSocketFactory();
_serverSocket = socketFactory.createServerSocket();
+ ((SSLServerSocket)_serverSocket).setNeedClientAuth(config.needClientAuth());
+ ((SSLServerSocket)_serverSocket).setWantClientAuth(config.wantClientAuth());
+
}
_serverSocket.setReuseAddress(true);
@@ -216,9 +221,23 @@ public class IoNetworkTransport implements OutgoingNetworkTransport, IncomingNet
socket.setSendBufferSize(sendBufferSize);
socket.setReceiveBufferSize(receiveBufferSize);
+
ProtocolEngine engine = _factory.newProtocolEngine();
- NetworkConnection connection = new IoNetworkConnection(socket, engine, sendBufferSize, receiveBufferSize, _timeout);
+ NetworkConnection connection = new IoNetworkConnection(socket, engine, sendBufferSize, receiveBufferSize, TIMEOUT);
+
+ if(_sslContext != null)
+ {
+ try
+ {
+ Principal peerPrincipal = ((SSLSocket) socket).getSession().getPeerPrincipal();
+ connection.setPeerPrincipal(peerPrincipal);
+ }
+ catch(SSLPeerUnverifiedException e)
+ {
+ // ignore
+ }
+ }
engine.setNetworkConnection(connection, connection.getSender());
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
index 442800c529..478355edc1 100644
--- 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
@@ -78,9 +78,11 @@ public class SecurityLayerFactory
sslCtx = SSLContextFactory
.buildClientContext(settings.getTrustStorePath(),
settings.getTrustStorePassword(),
+ settings.getTrustStoreType(),
settings.getTrustManagerFactoryAlgorithm(),
settings.getKeyStorePath(),
settings.getKeyStorePassword(),
+ settings.getKeyStoreType(),
settings.getKeyManagerFactoryAlgorithm(),
settings.getCertAlias());
}
diff --git a/java/common/src/main/java/org/apache/qpid/transport/network/security/sasl/SASLEncryptor.java b/java/common/src/main/java/org/apache/qpid/transport/network/security/sasl/SASLEncryptor.java
index 625e1a77c2..a90ea52202 100644
--- a/java/common/src/main/java/org/apache/qpid/transport/network/security/sasl/SASLEncryptor.java
+++ b/java/common/src/main/java/org/apache/qpid/transport/network/security/sasl/SASLEncryptor.java
@@ -1,4 +1,3 @@
-package org.apache.qpid.transport.network.security.sasl;
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
@@ -19,6 +18,7 @@ package org.apache.qpid.transport.network.security.sasl;
* under the License.
*
*/
+package org.apache.qpid.transport.network.security.sasl;
import org.apache.qpid.transport.Connection;
diff --git a/java/common/src/main/java/org/apache/qpid/transport/network/security/sasl/SASLReceiver.java b/java/common/src/main/java/org/apache/qpid/transport/network/security/sasl/SASLReceiver.java
index a100b96412..59e9453454 100644
--- a/java/common/src/main/java/org/apache/qpid/transport/network/security/sasl/SASLReceiver.java
+++ b/java/common/src/main/java/org/apache/qpid/transport/network/security/sasl/SASLReceiver.java
@@ -1,4 +1,3 @@
-package org.apache.qpid.transport.network.security.sasl;
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
@@ -19,6 +18,7 @@ package org.apache.qpid.transport.network.security.sasl;
* under the License.
*
*/
+package org.apache.qpid.transport.network.security.sasl;
import org.apache.qpid.transport.Receiver;
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 61d54a8386..098f2fb20c 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
@@ -1,4 +1,3 @@
-package org.apache.qpid.transport.network.security.sasl;
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
@@ -19,6 +18,7 @@ package org.apache.qpid.transport.network.security.sasl;
* under the License.
*
*/
+package org.apache.qpid.transport.network.security.sasl;
import org.apache.qpid.transport.Sender;
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 3ab028c8a8..0dccf37979 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
@@ -40,11 +40,11 @@ public class QpidClientX509KeyManager extends X509ExtendedKeyManager
private X509ExtendedKeyManager delegate;
private String alias;
- public QpidClientX509KeyManager(String alias, String keyStorePath,
+ public QpidClientX509KeyManager(String alias, String keyStorePath, String keyStoreType,
String keyStorePassword, String keyManagerFactoryAlgorithmName) throws GeneralSecurityException, IOException
{
this.alias = alias;
- KeyStore ks = SSLUtil.getInitializedKeyStore(keyStorePath,keyStorePassword);
+ KeyStore ks = SSLUtil.getInitializedKeyStore(keyStorePath,keyStorePassword,keyStoreType);
KeyManagerFactory kmf = KeyManagerFactory.getInstance(keyManagerFactoryAlgorithmName);
kmf.init(ks, keyStorePassword.toCharArray());
this.delegate = (X509ExtendedKeyManager)kmf.getKeyManagers()[0];
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 71a73db71f..ce7cc105a1 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,9 +125,9 @@ public class SSLUtil
return id.toString();
}
- public static KeyStore getInitializedKeyStore(String storePath, String storePassword) throws GeneralSecurityException, IOException
+ public static KeyStore getInitializedKeyStore(String storePath, String storePassword, String keyStoreType) throws GeneralSecurityException, IOException
{
- KeyStore ks = KeyStore.getInstance("JKS");
+ KeyStore ks = KeyStore.getInstance(keyStoreType);
InputStream in = null;
try
{
@@ -140,7 +140,7 @@ public class SSLUtil
{
in = Thread.currentThread().getContextClassLoader().getResourceAsStream(storePath);
}
- if (in == null)
+ if (in == null && !"PKCS11".equalsIgnoreCase(keyStoreType)) // PKCS11 will not require an explicit path
{
throw new IOException("Unable to load keystore resource: " + storePath);
}
diff --git a/java/common/src/main/java/org/apache/qpid/url/BindingURLParser.java b/java/common/src/main/java/org/apache/qpid/url/BindingURLParser.java
index fe7b01761b..939080e252 100644
--- a/java/common/src/main/java/org/apache/qpid/url/BindingURLParser.java
+++ b/java/common/src/main/java/org/apache/qpid/url/BindingURLParser.java
@@ -1,4 +1,3 @@
-package org.apache.qpid.url;
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
@@ -19,6 +18,7 @@ package org.apache.qpid.url;
* under the License.
*
*/
+package org.apache.qpid.url;
import org.slf4j.Logger;
diff --git a/java/common/src/main/java/org/apache/qpid/util/Serial.java b/java/common/src/main/java/org/apache/qpid/util/Serial.java
index 451d5d60eb..287c094b88 100644
--- a/java/common/src/main/java/org/apache/qpid/util/Serial.java
+++ b/java/common/src/main/java/org/apache/qpid/util/Serial.java
@@ -1,4 +1,3 @@
-package org.apache.qpid.util;
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
@@ -19,6 +18,7 @@ package org.apache.qpid.util;
* under the License.
*
*/
+package org.apache.qpid.util;
import java.util.Comparator;
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 6540e053b1..cb820b333b 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
@@ -1,4 +1,3 @@
-package org.apache.qpid.codec;
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
@@ -19,6 +18,7 @@ package org.apache.qpid.codec;
* under the License.
*
*/
+package org.apache.qpid.codec;
import junit.framework.TestCase;
diff --git a/java/common/src/test/java/org/apache/qpid/codec/MockAMQVersionAwareProtocolSession.java b/java/common/src/test/java/org/apache/qpid/codec/MockAMQVersionAwareProtocolSession.java
index 3a95ca330f..e0244e0581 100644
--- a/java/common/src/test/java/org/apache/qpid/codec/MockAMQVersionAwareProtocolSession.java
+++ b/java/common/src/test/java/org/apache/qpid/codec/MockAMQVersionAwareProtocolSession.java
@@ -1,4 +1,3 @@
-package org.apache.qpid.codec;
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
@@ -19,6 +18,7 @@ package org.apache.qpid.codec;
* under the License.
*
*/
+package org.apache.qpid.codec;
import org.apache.qpid.AMQException;
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
index 69b04c9979..21b8871d9a 100644
--- a/java/common/src/test/java/org/apache/qpid/ssl/SSLContextFactoryTest.java
+++ b/java/common/src/test/java/org/apache/qpid/ssl/SSLContextFactoryTest.java
@@ -31,13 +31,14 @@ public class SSLContextFactoryTest extends QpidTestCase
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 STORE_TYPE = "JKS";
private static final String DEFAULT_KEY_MANAGER_ALGORITHM = KeyManagerFactory.getDefaultAlgorithm();
private static final String DEFAULT_TRUST_MANAGER_ALGORITHM = TrustManagerFactory.getDefaultAlgorithm();
private static final String CERT_ALIAS_APP1 = "app1";
public void testBuildServerContext() throws Exception
{
- SSLContext context = SSLContextFactory.buildServerContext(BROKER_KEYSTORE_PATH, STORE_PASSWORD, DEFAULT_KEY_MANAGER_ALGORITHM);
+ SSLContext context = SSLContextFactory.buildServerContext(BROKER_KEYSTORE_PATH, STORE_PASSWORD, STORE_TYPE, DEFAULT_KEY_MANAGER_ALGORITHM);
assertNotNull("SSLContext should not be null", context);
}
@@ -45,7 +46,7 @@ public class SSLContextFactoryTest extends QpidTestCase
{
try
{
- SSLContextFactory.buildServerContext(BROKER_KEYSTORE_PATH, "sajdklsad", DEFAULT_KEY_MANAGER_ALGORITHM);
+ SSLContextFactory.buildServerContext(BROKER_KEYSTORE_PATH, "sajdklsad", STORE_TYPE, DEFAULT_KEY_MANAGER_ALGORITHM);
fail("Exception was not thrown due to incorrect password");
}
catch (IOException e)
@@ -58,7 +59,7 @@ public class SSLContextFactoryTest extends QpidTestCase
{
try
{
- SSLContextFactory.buildClientContext("/path/to/nothing", STORE_PASSWORD, DEFAULT_TRUST_MANAGER_ALGORITHM, CLIENT_KEYSTORE_PATH, STORE_PASSWORD, DEFAULT_KEY_MANAGER_ALGORITHM, null);
+ SSLContextFactory.buildClientContext("/path/to/nothing", STORE_PASSWORD, STORE_TYPE, DEFAULT_TRUST_MANAGER_ALGORITHM, CLIENT_KEYSTORE_PATH, STORE_PASSWORD, STORE_TYPE, DEFAULT_KEY_MANAGER_ALGORITHM, null);
fail("Exception was not thrown due to incorrect path");
}
catch (IOException e)
@@ -69,19 +70,19 @@ public class SSLContextFactoryTest extends QpidTestCase
public void testBuildClientContextForSSLEncryptionOnly() throws Exception
{
- SSLContext context = SSLContextFactory.buildClientContext(CLIENT_TRUSTSTORE_PATH, STORE_PASSWORD, DEFAULT_TRUST_MANAGER_ALGORITHM, null, null, null, null);
+ SSLContext context = SSLContextFactory.buildClientContext(CLIENT_TRUSTSTORE_PATH, STORE_PASSWORD, STORE_TYPE, DEFAULT_TRUST_MANAGER_ALGORITHM, null, 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, DEFAULT_TRUST_MANAGER_ALGORITHM, CLIENT_KEYSTORE_PATH, STORE_PASSWORD, DEFAULT_KEY_MANAGER_ALGORITHM, null);
+ SSLContext context = SSLContextFactory.buildClientContext(CLIENT_TRUSTSTORE_PATH, STORE_PASSWORD, STORE_TYPE, DEFAULT_TRUST_MANAGER_ALGORITHM, CLIENT_KEYSTORE_PATH, STORE_PASSWORD, STORE_TYPE, DEFAULT_KEY_MANAGER_ALGORITHM, null);
assertNotNull("SSLContext should not be null", context);
}
public void testBuildClientContextWithForClientAuthWithCertAlias() throws Exception
{
- SSLContext context = SSLContextFactory.buildClientContext(CLIENT_TRUSTSTORE_PATH, STORE_PASSWORD, DEFAULT_TRUST_MANAGER_ALGORITHM, CLIENT_KEYSTORE_PATH, STORE_PASSWORD, DEFAULT_KEY_MANAGER_ALGORITHM, CERT_ALIAS_APP1);
+ SSLContext context = SSLContextFactory.buildClientContext(CLIENT_TRUSTSTORE_PATH, STORE_PASSWORD, STORE_TYPE, DEFAULT_TRUST_MANAGER_ALGORITHM, CLIENT_KEYSTORE_PATH, STORE_PASSWORD, STORE_TYPE, DEFAULT_KEY_MANAGER_ALGORITHM, CERT_ALIAS_APP1);
assertNotNull("SSLContext should not be null", context);
}
}
diff --git a/java/common/src/test/java/org/apache/qpid/test/utils/PortHelper.java b/java/common/src/test/java/org/apache/qpid/test/utils/PortHelper.java
new file mode 100644
index 0000000000..d3586c364f
--- /dev/null
+++ b/java/common/src/test/java/org/apache/qpid/test/utils/PortHelper.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.test.utils;
+
+import java.io.IOException;
+import java.net.DatagramSocket;
+import java.net.ServerSocket;
+import java.util.Set;
+
+import org.apache.log4j.Logger;
+
+public class PortHelper
+{
+ private static final Logger _logger = Logger.getLogger(PortHelper.class);
+
+ private static final int DEFAULT_TIMEOUT_MILLIS = 5000;
+
+ private int timeout = DEFAULT_TIMEOUT_MILLIS;
+
+ public void waitUntilPortsAreFree(Set<Integer> ports)
+ {
+ _logger.debug("Checking if ports " + ports + " are free...");
+
+ for (Integer port : ports)
+ {
+ waitUntilPortIsFree(port);
+ }
+
+ _logger.debug("ports " + ports + " are free");
+ }
+
+ private void waitUntilPortIsFree(int port)
+ {
+ long startTime = System.currentTimeMillis();
+ long deadline = startTime + timeout;
+ boolean alreadyFailed = false;
+
+ while (true)
+ {
+ if (System.currentTimeMillis() > deadline)
+ {
+ throw new RuntimeException("Timed out after " + timeout + " ms waiting for port " + port + " to become available");
+ }
+
+ if (isPortAvailable(port))
+ {
+ if(alreadyFailed)
+ {
+ _logger.debug("port " + port + " is now available");
+ }
+ return;
+ }
+ else
+ {
+ alreadyFailed = true;
+ }
+
+ try
+ {
+ Thread.sleep(500);
+ }
+ catch (InterruptedException e)
+ {
+ Thread.currentThread().interrupt();
+ }
+ }
+ }
+
+ public boolean isPortAvailable(int port)
+ {
+ ServerSocket serverSocket = null;
+ DatagramSocket datagramSocket = null;
+
+ try
+ {
+ serverSocket = new ServerSocket(port);
+ serverSocket.setReuseAddress(true); // ensures that the port is subsequently usable
+ datagramSocket = new DatagramSocket(port);
+ datagramSocket.setReuseAddress(true);
+ return true;
+ }
+ catch (IOException e)
+ {
+ _logger.debug("port " + port + " is not free");
+ return false;
+ }
+ finally
+ {
+ if (serverSocket != null)
+ {
+ try
+ {
+ serverSocket.close();
+ }
+ catch (IOException e)
+ {
+ throw new RuntimeException("Couldn't close port " + port + " that we created to check its availability", e);
+ }
+ }
+ if(datagramSocket != null)
+ {
+ datagramSocket.close();
+ }
+ }
+ }
+
+ public void setTimeout(int timeout)
+ {
+ this.timeout = timeout;
+ }
+}
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 cbf6caf141..ec06400b7d 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
@@ -29,8 +29,6 @@ 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.ArrayList;
import java.util.HashMap;
import java.util.List;
@@ -110,8 +108,8 @@ public class QpidTestCase extends TestCase
}
}
- protected static final String MS_FACTORY_CLASS_NAME_KEY = "messagestorefactory.class.name";
- protected static final String MEMORY_STORE_FACTORY_CLASS_NAME = "org.apache.qpid.server.store.MemoryMessageStoreFactory";
+ protected static final String MESSAGE_STORE_CLASS_NAME_KEY = "messagestore.class.name";
+ protected static final String MEMORY_STORE_CLASS_NAME = "org.apache.qpid.server.store.MemoryMessageStore";
private static List<String> _exclusionList;
@@ -140,12 +138,12 @@ public class QpidTestCase extends TestCase
}
}
- public String getTestProfileMessageStoreFactoryClassName()
+ public String getTestProfileMessageStoreClassName()
{
- final String storeFactoryClass = System.getProperty(MS_FACTORY_CLASS_NAME_KEY);
- _logger.debug("MS_FACTORY_CLASS_NAME_KEY " + storeFactoryClass);
+ final String storeClass = System.getProperty(MESSAGE_STORE_CLASS_NAME_KEY);
+ _logger.debug("MESSAGE_STORE_CLASS_NAME_KEY " + storeClass);
- return storeFactoryClass != null ? storeFactoryClass : MEMORY_STORE_FACTORY_CLASS_NAME ;
+ return storeClass != null ? storeClass : MEMORY_STORE_CLASS_NAME ;
}
@@ -166,9 +164,10 @@ public class QpidTestCase extends TestCase
throw new IllegalArgumentException("Invalid start port: " + fromPort);
}
+ PortHelper portHelper = new PortHelper();
for (int i = fromPort; i <= MAX_PORT_NUMBER; i++)
{
- if (available(i)) {
+ if (portHelper.isPortAvailable(i)) {
return i;
}
}
@@ -176,54 +175,6 @@ public class QpidTestCase extends TestCase
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);
diff --git a/java/common/src/test/java/org/apache/qpid/test/utils/TestFileUtils.java b/java/common/src/test/java/org/apache/qpid/test/utils/TestFileUtils.java
new file mode 100644
index 0000000000..056d11faaa
--- /dev/null
+++ b/java/common/src/test/java/org/apache/qpid/test/utils/TestFileUtils.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.test.utils;
+
+import java.io.File;
+
+import org.apache.qpid.util.FileUtils;
+
+/**
+ * Utility methods intended to be used in unit tests that manipulate files
+ */
+public class TestFileUtils
+{
+ private static final String SYSTEM_TMP_DIR = System.getProperty("java.io.tmpdir");
+
+ /**
+ * Create and return a temporary directory that will be deleted on exit.
+ */
+ public static File createTestDirectory()
+ {
+ String dirNameStem = TestFileUtils.class.getSimpleName() + "-testDir";
+ return createTestDirectory(dirNameStem, true);
+ }
+
+ /**
+ * Creates an empty directory with a name like /tmp/dirNameStem-12345678
+ */
+ public static File createTestDirectory(String dirNameStem, boolean deleteOnExit)
+ {
+ File testDir = new File(SYSTEM_TMP_DIR, dirNameStem + "-" + System.currentTimeMillis());
+ if (testDir.exists())
+ {
+ FileUtils.delete(testDir, true);
+ }
+
+ testDir.mkdirs();
+
+ if (deleteOnExit)
+ {
+ testDir.deleteOnExit();
+ }
+
+ return testDir;
+ }
+}
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
index 548e8dab12..893f66c5ff 100644
--- a/java/common/src/test/java/org/apache/qpid/transport/TestNetworkConnection.java
+++ b/java/common/src/test/java/org/apache/qpid/transport/TestNetworkConnection.java
@@ -20,6 +20,7 @@
*/
package org.apache.qpid.transport;
+import java.security.Principal;
import org.apache.qpid.protocol.ProtocolEngineFactory;
import org.apache.qpid.ssl.SSLContextFactory;
import org.apache.qpid.transport.network.NetworkConnection;
@@ -71,6 +72,17 @@ public class TestNetworkConnection implements NetworkConnection
}
+ @Override
+ public void setPeerPrincipal(Principal principal)
+ {
+ }
+
+ @Override
+ public Principal getPeerPrincipal()
+ {
+ return null;
+ }
+
public void setMaxWriteIdle(int idleTime)
{
diff --git a/java/common/src/test/java/org/apache/qpid/util/SerialTest.java b/java/common/src/test/java/org/apache/qpid/util/SerialTest.java
index ef8e7de61c..c3fcf73b38 100644
--- a/java/common/src/test/java/org/apache/qpid/util/SerialTest.java
+++ b/java/common/src/test/java/org/apache/qpid/util/SerialTest.java
@@ -1,4 +1,3 @@
-package org.apache.qpid.util;
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
@@ -19,6 +18,7 @@ package org.apache.qpid.util;
* under the License.
*
*/
+package org.apache.qpid.util;
import junit.framework.TestCase;
diff --git a/java/genpom b/java/genpom
index 07a5b82a1f..6ac0e970cc 100755
--- a/java/genpom
+++ b/java/genpom
@@ -111,8 +111,10 @@ for module in module_depends:
<groupId>%s</groupId>
<artifactId>%s</artifactId>
<version>%s</version>
+ <scope>%s</scope>
</dependency>
-""" % (opts.group, artifactId, opts.version))
+""" % (opts.group, artifactId, opts.version,
+ scopes.get(artifactId, "compile")))
for jar in jars:
base, ext = os.path.splitext(os.path.basename(jar))
diff --git a/java/ivy.xml b/java/ivy.nexus.xml
index cc891094a3..61ae9f315b 100644
--- a/java/ivy.xml
+++ b/java/ivy.nexus.xml
@@ -18,7 +18,7 @@
<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.17"/>
+ <info organisation="${ivy.organisation}" module="${project.name}" revision="${project.version}"/>
<publications xmlns:e="urn:ant.apache.org:ivy-extras">
<artifact name="qpid-client" type="pom" ext="pom"/>
diff --git a/java/ivy.retrieve.xml b/java/ivy.retrieve.xml
new file mode 100644
index 0000000000..98d3d3785d
--- /dev/null
+++ b/java/ivy.retrieve.xml
@@ -0,0 +1,86 @@
+<?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="${ivy.organisation}" module="${project.name}" revision="${project.version}"/>
+
+ <configurations defaultconf="required" defaultconfmapping="*->default">
+ <conf name="required"/>
+ <conf name="bdbje"/>
+ <conf name="jfree"/>
+ <conf name="csvjdbc"/>
+ <conf name="findbugs"/>
+ <conf name="cobertura"/>
+ </configurations>
+
+ <publications xmlns:e="urn:ant.apache.org:ivy-extras"/>
+
+ <dependencies>
+ <dependency org="biz.aQute" name="bnd" rev="0.0.384" transitive="false"/>
+ <dependency org="commons-beanutils" name="commons-beanutils-core" rev="1.8.3" transitive="false"/>
+ <dependency org="commons-cli" name="commons-cli" rev="1.2" transitive="false"/>
+ <dependency org="commons-codec" name="commons-codec" rev="1.6" transitive="false"/>
+ <dependency org="commons-collections" name="commons-collections" rev="3.2.1" transitive="false"/>
+ <dependency org="commons-configuration" name="commons-configuration" rev="1.8" transitive="false"/>
+ <dependency org="commons-digester" name="commons-digester" rev="1.8.1" transitive="false"/>
+ <dependency org="commons-lang" name="commons-lang" rev="2.6" transitive="false"/>
+ <dependency org="commons-logging" name="commons-logging" rev="1.1.1" transitive="false"/>
+ <dependency org="org.apache.derby" name="derby" rev="10.8.2.2" transitive="false"/>
+ <dependency org="org.apache.geronimo.framework" name="geronimo-kernel" rev="2.2.1" transitive="false"/>
+ <dependency org="org.apache.geronimo.specs" name="geronimo-ejb_3.0_spec" rev="1.0.1" transitive="false"/>
+ <dependency org="org.apache.geronimo.specs" name="geronimo-j2ee-connector_1.5_spec" rev="2.0.0" transitive="false"/>
+ <dependency org="org.apache.geronimo.specs" name="geronimo-jms_1.1_spec" rev="1.0" transitive="false"/>
+ <dependency org="org.apache.geronimo.specs" name="geronimo-jta_1.1_spec" rev="1.1.1" transitive="false"/>
+ <dependency org="org.apache.geronimo.specs" name="geronimo-servlet_2.5_spec" rev="1.2" transitive="false"/>
+ <dependency org="com.google.code.gson" name="gson" rev="2.0" transitive="false"/>
+ <dependency org="org.codehaus.jackson" name="jackson-core-asl" rev="1.9.0" transitive="false"/>
+ <dependency org="org.codehaus.jackson" name="jackson-mapper-asl" rev="1.9.0" transitive="false"/>
+ <dependency org="net.java.dev.javacc" name="javacc" rev="5.0" transitive="false"/>
+ <dependency org="junit" name="junit" rev="3.8.1" transitive="false"/>
+ <dependency org="org.python" name="jython-standalone" rev="2.5.2" transitive="false"/>
+ <dependency org="log4j" name="log4j" rev="1.2.16" transitive="false"/>
+ <dependency org="org.apache.maven" name="maven-ant-tasks" rev="2.1.1" transitive="false"/>
+ <dependency org="org.mockito" name="mockito-all" rev="1.9.0" transitive="false"/>
+ <dependency org="org.apache.felix" name="org.apache.felix.main" rev="2.0.5" transitive="false"/>
+ <dependency org="org.slf4j" name="slf4j-api" rev="1.6.4" transitive="false"/>
+ <dependency org="org.slf4j" name="slf4j-log4j12" rev="1.6.4" transitive="false"/>
+ <dependency org="org.eclipse.jetty" name="jetty-server" rev="7.6.3.v20120416" transitive="false"/>
+ <dependency org="org.eclipse.jetty" name="jetty-websocket" rev="7.6.3.v20120416" transitive="false"/>
+ <dependency org="org.eclipse.jetty" name="jetty-continuation" rev="7.6.3.v20120416" transitive="false"/>
+ <dependency org="org.eclipse.jetty" name="jetty-io" rev="7.6.3.v20120416" transitive="false"/>
+ <dependency org="org.eclipse.jetty" name="jetty-http" rev="7.6.3.v20120416" transitive="false"/>
+ <dependency org="org.eclipse.jetty" name="jetty-security" rev="7.6.3.v20120416" transitive="false"/>
+ <dependency org="org.eclipse.jetty" name="jetty-servlet" rev="7.6.3.v20120416" transitive="false"/>
+ <dependency org="org.eclipse.jetty" name="jetty-util" rev="7.6.3.v20120416" transitive="false"/>
+ <dependency org="org.dojotoolkit" name="dojo-war" rev="1.7.2" transitive="false"/>
+ <dependency org="xalan" name="xalan" rev="2.7.0" transitive="false"/>
+
+ <!-- The following are optional dependencies, for modules providing optional functionlity or
+ for use in optional build/test steps. Their optional status is usually indicative of licences
+ which are not compatible with the Apache Licence -->
+ <dependency org="com.sleepycat" name="je" rev="5.0.55" transitive="false" conf="bdbje"/>
+ <dependency org="jfree" name="jfreechart" rev="1.0.13" transitive="false" conf="jfree"/>
+ <dependency org="jfree" name="jcommon" rev="1.0.16" transitive="false" conf="jfree"/>
+ <dependency org="net.sourceforge.csvjdbc" name="csvjdbc" rev="1.0.8" transitive="false" conf="csvjdbc"/>
+ <dependency org="com.google.code.findbugs" name="findbugs-ant" rev="2.0.0" conf="findbugs"/>
+ <dependency org="net.sourceforge.cobertura" name="cobertura" rev="1.9.4.1" conf="cobertura">
+ <exclude org="org.apache.ant"/>
+ </dependency>
+ </dependencies>
+</ivy-module>
diff --git a/java/ivysettings-nexus.xml b/java/ivysettings.nexus.xml
index 1d9c393e23..03f84f9f7c 100644
--- a/java/ivysettings-nexus.xml
+++ b/java/ivysettings.nexus.xml
@@ -18,7 +18,6 @@
<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>
@@ -26,5 +25,5 @@
<modules>
<module organisation="${nexus.organisation}" name="qpid" resolver="nexus"/>
</modules>
- <settings defaultResolver="public"/>
+ <settings defaultResolver="nexus"/>
</ivysettings>
diff --git a/java/ivysettings.retrieve.xml b/java/ivysettings.retrieve.xml
new file mode 100644
index 0000000000..8faf23c2d1
--- /dev/null
+++ b/java/ivysettings.retrieve.xml
@@ -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.
+-->
+<ivysettings>
+ <property name="ivy.default.resolver" value="chain" override="false"/>
+ <property name="ivy.localfs.root" value="${project.root}/localfs_repo" override="false"/>
+ <property name="ivy.localfs.pattern" value="[artifact]-[revision](-[classifier]).[ext]" override="false"/>
+ <property name="ivy.m2repo.url" value="http://repo1.maven.org/maven2" override="false"/>
+
+ <settings defaultResolver="${ivy.default.resolver}"/>
+ <resolvers>
+ <filesystem name="localfs">
+ <artifact pattern="${ivy.localfs.root}/${ivy.localfs.pattern}" />
+ </filesystem>
+
+ <ibiblio name="m2repo" m2compatible="true" root="${ivy.m2repo.url}"/>
+
+ <url name="csvjdbc" m2compatible="true">
+ <artifact pattern="http://csvjdbc.sourceforge.net/maven2/[organisation]/[module]/[revision]/[artifact]-[revision].[ext]"/>
+ </url>
+
+ <url name="oracle" m2compatible="true">
+ <artifact pattern="http://download.oracle.com/maven/[organisation]/[module]/[revision]/[artifact]-[revision].[ext]"/>
+ </url>
+
+ <ibiblio name="public" m2compatible="true"/>
+
+ <chain name="chain" returnFirst="true">
+ <resolver ref="m2repo"/>
+ <resolver ref="csvjdbc"/>
+ <resolver ref="oracle"/>
+ <resolver ref="public"/>
+ </chain>
+ </resolvers>
+</ivysettings>
diff --git a/java/jca/build.xml b/java/jca/build.xml
index 3430232003..934514aa52 100644
--- a/java/jca/build.xml
+++ b/java/jca/build.xml
@@ -18,18 +18,20 @@
- under the License.
-
-->
-<project name="Qpid JCA RA" default="build">
+<project name="Qpid JCA" default="build">
<property name="module.depends" value="common client"/>
- <property name="module.name" value="ra"/>
+ <property name="module.name" value="jca"/>
<import file="../module.xml"/>
- <property name="module.rar" value="${build.lib}/${project.name}-${module.name}-${project.version}.rar"/>
- <property name="module.resources" value="src/main/resources"/>
+ <property name="module.rar" value="${build.lib}/${project.name}-ra-${project.version}.rar"/>
+ <property name="module.resources" value="src/main/resources"/>
<target name="rar" depends="jar">
+ <!--Note we need to do this as we need to keep the ra in the name of the artificats but we can't override the module.jar property which is based on the directory name-->
+ <move file="${build.lib}/${project.name}-${module.name}-${project.version}.jar" tofile="${build.lib}/${project.name}-ra-${project.version}.jar"/>
<jar destfile="${module.rar}">
<fileset dir="${module.resources}">
<include name="**/*.xml"/>
@@ -66,4 +68,5 @@
<target name="examples" depends="example-properties-file, example-jars"/>
<target name="build" depends="rar, examples"/>
+
</project>
diff --git a/java/jca/example/README-EXAMPLE.txt b/java/jca/example/README-EXAMPLE.txt
index 3a2ee0c38e..fd0af585ef 100644
--- a/java/jca/example/README-EXAMPLE.txt
+++ b/java/jca/example/README-EXAMPLE.txt
@@ -232,4 +232,9 @@ While this documentation highlights the major components and steps needed to tak
the possiblities for modifcation are numerous. You are encouraged to experiment with the example as you work
to develop your own messaging applications.
+***Note***
+Due to the way Ant handle XML escape characters in the Copy task, if you are attempting to deploy the
+examples to a clustered broker configuration, you will need to modify the resultant XML configuration
+file to remove the '&' character and replace it with the &amp; character. This file varies by app
+server. Please see the app server specific documentation for your platform for further details.
diff --git a/java/jca/example/build-jboss7-properties.xml b/java/jca/example/build-jboss7-properties.xml
index 68ecd8a4f4..157802cc73 100644
--- a/java/jca/example/build-jboss7-properties.xml
+++ b/java/jca/example/build-jboss7-properties.xml
@@ -53,19 +53,19 @@
<path id="compile.classpath">
<fileset dir="${jboss.modules}/javax/jms/api/main">
- <include name="jboss-jms-api_1.1_spec-1.0.1.Final.jar"/>
+ <include name="jboss-jms-api_1.1_spec-*.Final.jar"/>
</fileset>
<fileset dir="${jboss.modules}/javax/ejb/api/main">
- <include name="jboss-ejb-api_3.1_spec-1.0.2.Final.jar"/>
+ <include name="jboss-ejb-api_3.1_spec-*.Final.jar"/>
</fileset>
<fileset dir="${jboss.modules}/javax/servlet/api/main">
- <include name="jboss-servlet-api_3.0_spec-1.0.1.Final.jar"/>
+ <include name="jboss-servlet-api_3.0_spec-*.Final.jar"/>
</fileset>
<fileset dir="${jboss.modules}/javax/transaction/api/main">
- <include name="jboss-transaction-api_1.1_spec-1.0.1.Final.jar"/>
+ <include name="jboss-transaction-api_1.1_spec-*.Final.jar"/>
</fileset>
<fileset dir="${jboss.modules}/org/slf4j/main">
- <include name="slf4j-api-1.6.1.jar"/>
+ <include name="slf4j-api-*.jar"/>
</fileset>
</path>
@@ -121,13 +121,10 @@
<target name="deploy-config" depends="generate" description="Deploys the standalone file to the JBoss environment.">
<copy todir="${jboss.config.dir}" overwrite="true">
<fileset dir="${gen.dir}">
- <include name="${jboss.server.config}.xml"/>
+ <include name="qpid-${jboss.server.config}.xml"/>
</fileset>
</copy>
</target>
- <target name="undeploy-ds" description="Undeploys the ds.xml file from the JBoss environment.">
- <delete file="${jboss.deploy}/qpid-jca-ds.xml"/>
- </target>
</project>
diff --git a/java/jca/example/conf/qpid-standalone.xml b/java/jca/example/conf/qpid-standalone.xml
index 8d6137aea7..2e22bd3f99 100644
--- a/java/jca/example/conf/qpid-standalone.xml
+++ b/java/jca/example/conf/qpid-standalone.xml
@@ -1,3 +1,4 @@
+<?xml version='1.0' encoding='UTF-8'?>
<!--
-
- Licensed to the Apache Software Foundation (ASF) under one
@@ -18,7 +19,6 @@
- under the License.
-
-->
-<?xml version='1.0' encoding='UTF-8'?>
<server xmlns="urn:jboss:domain:1.1" xmlns:xsd="http://www.w3.org/2001/XMLSchema-instance">
diff --git a/java/jca/src/main/java/org/apache/qpid/ra/QpidRAXAResource.java b/java/jca/src/main/java/org/apache/qpid/ra/QpidRAXAResource.java
index 22b39792b1..37ae7f5514 100644
--- a/java/jca/src/main/java/org/apache/qpid/ra/QpidRAXAResource.java
+++ b/java/jca/src/main/java/org/apache/qpid/ra/QpidRAXAResource.java
@@ -21,10 +21,13 @@
package org.apache.qpid.ra;
+import java.util.List;
+
import javax.transaction.xa.XAException;
import javax.transaction.xa.XAResource;
import javax.transaction.xa.Xid;
+import org.apache.qpid.client.AMQXAResource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -32,7 +35,7 @@ import org.slf4j.LoggerFactory;
* QpidRAXAResource.
*
*/
-public class QpidRAXAResource implements XAResource
+public class QpidRAXAResource implements AMQXAResource
{
/** The logger */
private static final Logger _log = LoggerFactory.getLogger(QpidRAXAResource.class);
@@ -192,7 +195,7 @@ public class QpidRAXAResource implements XAResource
{
_log.trace("isSameRM(" + xaRes + ")");
}
-
+
return _xaResource.isSameRM(xaRes);
}
@@ -242,4 +245,14 @@ public class QpidRAXAResource implements XAResource
return _xaResource.setTransactionTimeout(seconds);
}
+
+ public String getBrokerUUID()
+ {
+ return ((AMQXAResource)_xaResource).getBrokerUUID();
+ }
+
+ public List<XAResource> getSiblings()
+ {
+ return ((AMQXAResource)_xaResource).getSiblings();
+ }
}
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/bnd-0.0.384.jar b/java/lib/bnd-0.0.384.jar
deleted file mode 100644
index fa5e5263f7..0000000000
--- a/java/lib/bnd-0.0.384.jar
+++ /dev/null
Binary files differ
diff --git a/java/lib/cobertura/README.txt b/java/lib/cobertura/README.txt
deleted file mode 100644
index 080bb5f2f3..0000000000
--- a/java/lib/cobertura/README.txt
+++ /dev/null
@@ -1,9 +0,0 @@
-Download the cobertura binary from the following location and expand it into
-this directory.
-
-http://cobertura.sourceforge.net/download.html
-
-Alternatively run "ant download-cobertura" to do this automatically.
-(to set a http proxy for ant use ANT_OPTS="-Dhttp.proxyHost=<host> -Dhttp.proxyPort=<port>")
-
-Run "ant cover-test coverage-report" to generate coverage report.
diff --git a/java/lib/com.ibm.icu_3.8.1.v20080530.jar b/java/lib/com.ibm.icu_3.8.1.v20080530.jar
deleted file mode 100644
index 1d8a0a0997..0000000000
--- a/java/lib/com.ibm.icu_3.8.1.v20080530.jar
+++ /dev/null
Binary files differ
diff --git a/java/lib/commons-beanutils-core-1.8.0.jar b/java/lib/commons-beanutils-core-1.8.0.jar
deleted file mode 100644
index 87c15f4565..0000000000
--- a/java/lib/commons-beanutils-core-1.8.0.jar
+++ /dev/null
Binary files differ
diff --git a/java/lib/commons-cli-1.0.jar b/java/lib/commons-cli-1.0.jar
deleted file mode 100644
index 22a004e14e..0000000000
--- a/java/lib/commons-cli-1.0.jar
+++ /dev/null
Binary files differ
diff --git a/java/lib/commons-codec-1.3.jar b/java/lib/commons-codec-1.3.jar
deleted file mode 100644
index 957b6752af..0000000000
--- a/java/lib/commons-codec-1.3.jar
+++ /dev/null
Binary files differ
diff --git a/java/lib/commons-collections-3.2.jar b/java/lib/commons-collections-3.2.jar
deleted file mode 100644
index 75580be255..0000000000
--- a/java/lib/commons-collections-3.2.jar
+++ /dev/null
Binary files differ
diff --git a/java/lib/commons-configuration-1.6.jar b/java/lib/commons-configuration-1.6.jar
deleted file mode 100644
index 2d4689a1b8..0000000000
--- a/java/lib/commons-configuration-1.6.jar
+++ /dev/null
Binary files differ
diff --git a/java/lib/commons-digester-1.8.1.jar b/java/lib/commons-digester-1.8.1.jar
deleted file mode 100644
index 7abda9696a..0000000000
--- a/java/lib/commons-digester-1.8.1.jar
+++ /dev/null
Binary files differ
diff --git a/java/lib/commons-lang-2.2.jar b/java/lib/commons-lang-2.2.jar
deleted file mode 100644
index b9105611f3..0000000000
--- a/java/lib/commons-lang-2.2.jar
+++ /dev/null
Binary files differ
diff --git a/java/lib/commons-logging-1.0.4.jar b/java/lib/commons-logging-1.0.4.jar
deleted file mode 100644
index b73a80fab6..0000000000
--- a/java/lib/commons-logging-1.0.4.jar
+++ /dev/null
Binary files differ
diff --git a/java/lib/derby-10.6.1.0.jar b/java/lib/derby-10.6.1.0.jar
deleted file mode 100644
index 33a84e9dc5..0000000000
--- a/java/lib/derby-10.6.1.0.jar
+++ /dev/null
Binary files differ
diff --git a/java/lib/findbugs/README.txt b/java/lib/findbugs/README.txt
deleted file mode 100644
index 56343d7e63..0000000000
--- a/java/lib/findbugs/README.txt
+++ /dev/null
@@ -1,30 +0,0 @@
-Download the FindBugs archive from the following location:
-http://findbugs.sourceforge.net/downloads.html
-
-Unpack the contents of the 'findbugs-<version>/lib' folder within the archive
-to the 'qpid/java/lib/findbugs' (i.e. this) directory. This should leave you
-with contents of 'qpid/java/lib/findbugs' similar to:
-
-annotations.jar
-ant.jar
-asm-3.1.jar
-asm-analysis-3.1.jar
-asm-commons-3.1.jar
-asm-tree-3.1.jar
-asm-util-3.1.jar
-asm-xml-3.1.jar
-bcel.jar
-buggy.icns
-commons-lang-2.4.jar
-dom4j-1.6.1.jar
-findbugs-ant.jar
-findbugs.jar
-jFormatString.jar
-jaxen-1.1.1.jar
-jdepend-2.9.jar
-jsr305.jar
-mysql-connector-java-5.1.7-bin.jar
-
-
-Now simply run "ant findbugs" in qpid/java to generate the report.
-
diff --git a/java/lib/geronimo-ejb_3.0_spec-1.0.1.jar b/java/lib/geronimo-ejb_3.0_spec-1.0.1.jar
deleted file mode 100644
index 29087f2f46..0000000000
--- a/java/lib/geronimo-ejb_3.0_spec-1.0.1.jar
+++ /dev/null
Binary files differ
diff --git a/java/lib/geronimo-j2ee-connector_1.5_spec-2.0.0.jar b/java/lib/geronimo-j2ee-connector_1.5_spec-2.0.0.jar
deleted file mode 100644
index 70e7ed4a93..0000000000
--- a/java/lib/geronimo-j2ee-connector_1.5_spec-2.0.0.jar
+++ /dev/null
Binary files differ
diff --git a/java/lib/geronimo-jms_1.1_spec-1.0.jar b/java/lib/geronimo-jms_1.1_spec-1.0.jar
deleted file mode 100644
index 42bf403e28..0000000000
--- a/java/lib/geronimo-jms_1.1_spec-1.0.jar
+++ /dev/null
Binary files differ
diff --git a/java/lib/geronimo-jta_1.1_spec-1.1.1.jar b/java/lib/geronimo-jta_1.1_spec-1.1.1.jar
deleted file mode 100644
index ee9963dfc8..0000000000
--- a/java/lib/geronimo-jta_1.1_spec-1.1.1.jar
+++ /dev/null
Binary files differ
diff --git a/java/lib/geronimo-kernel-2.2.1.jar b/java/lib/geronimo-kernel-2.2.1.jar
deleted file mode 100644
index 34c46c3183..0000000000
--- a/java/lib/geronimo-kernel-2.2.1.jar
+++ /dev/null
Binary files differ
diff --git a/java/lib/gson-2.0.jar b/java/lib/gson-2.0.jar
deleted file mode 100644
index 7b413f9570..0000000000
--- a/java/lib/gson-2.0.jar
+++ /dev/null
Binary files differ
diff --git a/java/lib/jackson-core-asl-1.9.0.jar b/java/lib/jackson-core-asl-1.9.0.jar
deleted file mode 100644
index e9456ad887..0000000000
--- a/java/lib/jackson-core-asl-1.9.0.jar
+++ /dev/null
Binary files differ
diff --git a/java/lib/jackson-mapper-asl-1.9.0.jar b/java/lib/jackson-mapper-asl-1.9.0.jar
deleted file mode 100644
index f8beebcfea..0000000000
--- a/java/lib/jackson-mapper-asl-1.9.0.jar
+++ /dev/null
Binary files differ
diff --git a/java/lib/javacc.jar b/java/lib/javacc.jar
deleted file mode 100644
index 2550727eef..0000000000
--- a/java/lib/javacc.jar
+++ /dev/null
Binary files differ
diff --git a/java/lib/junit-3.8.1.jar b/java/lib/junit-3.8.1.jar
deleted file mode 100644
index 674d71e89e..0000000000
--- a/java/lib/junit-3.8.1.jar
+++ /dev/null
Binary files differ
diff --git a/java/lib/jython-2.5.0.jar b/java/lib/jython-2.5.0.jar
deleted file mode 100644
index f8fc553ae7..0000000000
--- a/java/lib/jython-2.5.0.jar
+++ /dev/null
Binary files differ
diff --git a/java/lib/log4j-1.2.12.jar b/java/lib/log4j-1.2.12.jar
deleted file mode 100644
index 9b5a720088..0000000000
--- a/java/lib/log4j-1.2.12.jar
+++ /dev/null
Binary files differ
diff --git a/java/lib/maven-ant-tasks-2.1.1.jar b/java/lib/maven-ant-tasks-2.1.1.jar
deleted file mode 100644
index 7810a541b8..0000000000
--- a/java/lib/maven-ant-tasks-2.1.1.jar
+++ /dev/null
Binary files differ
diff --git a/java/lib/mockito-all-1.9.0.jar b/java/lib/mockito-all-1.9.0.jar
deleted file mode 100644
index 273fd50feb..0000000000
--- a/java/lib/mockito-all-1.9.0.jar
+++ /dev/null
Binary files differ
diff --git a/java/lib/org.apache.commons.codec_1.3.0.v20080530-1600.jar b/java/lib/org.apache.commons.codec_1.3.0.v20080530-1600.jar
deleted file mode 100644
index d9b4c8ea1f..0000000000
--- a/java/lib/org.apache.commons.codec_1.3.0.v20080530-1600.jar
+++ /dev/null
Binary files differ
diff --git a/java/lib/org.apache.felix.main-2.0.5.jar b/java/lib/org.apache.felix.main-2.0.5.jar
deleted file mode 100644
index 71e5a84231..0000000000
--- a/java/lib/org.apache.felix.main-2.0.5.jar
+++ /dev/null
Binary files differ
diff --git a/java/lib/org.eclipse.core.commands_3.4.0.I20080509-2000.jar b/java/lib/org.eclipse.core.commands_3.4.0.I20080509-2000.jar
deleted file mode 100644
index 6467d78d66..0000000000
--- a/java/lib/org.eclipse.core.commands_3.4.0.I20080509-2000.jar
+++ /dev/null
Binary files differ
diff --git a/java/lib/org.eclipse.core.contenttype_3.3.0.v20080604-1400.jar b/java/lib/org.eclipse.core.contenttype_3.3.0.v20080604-1400.jar
deleted file mode 100644
index 0b6163cf1b..0000000000
--- a/java/lib/org.eclipse.core.contenttype_3.3.0.v20080604-1400.jar
+++ /dev/null
Binary files differ
diff --git a/java/lib/org.eclipse.core.databinding_1.1.1.M20080827-0800b.jar b/java/lib/org.eclipse.core.databinding_1.1.1.M20080827-0800b.jar
deleted file mode 100644
index 7f9d1b637e..0000000000
--- a/java/lib/org.eclipse.core.databinding_1.1.1.M20080827-0800b.jar
+++ /dev/null
Binary files differ
diff --git a/java/lib/org.eclipse.core.expressions_3.4.0.v20080603-2000.jar b/java/lib/org.eclipse.core.expressions_3.4.0.v20080603-2000.jar
deleted file mode 100644
index 671e92aa4b..0000000000
--- a/java/lib/org.eclipse.core.expressions_3.4.0.v20080603-2000.jar
+++ /dev/null
Binary files differ
diff --git a/java/lib/org.eclipse.core.jobs_3.4.0.v20080512.jar b/java/lib/org.eclipse.core.jobs_3.4.0.v20080512.jar
deleted file mode 100644
index 7bdbc00313..0000000000
--- a/java/lib/org.eclipse.core.jobs_3.4.0.v20080512.jar
+++ /dev/null
Binary files differ
diff --git a/java/lib/org.eclipse.core.runtime.compatibility.registry_3.2.200.v20080610/META-INF/ECLIPSE.RSA b/java/lib/org.eclipse.core.runtime.compatibility.registry_3.2.200.v20080610/META-INF/ECLIPSE.RSA
deleted file mode 100644
index d694a14d7f..0000000000
--- a/java/lib/org.eclipse.core.runtime.compatibility.registry_3.2.200.v20080610/META-INF/ECLIPSE.RSA
+++ /dev/null
Binary files differ
diff --git a/java/lib/org.eclipse.core.runtime.compatibility.registry_3.2.200.v20080610/META-INF/ECLIPSE.SF b/java/lib/org.eclipse.core.runtime.compatibility.registry_3.2.200.v20080610/META-INF/ECLIPSE.SF
deleted file mode 100644
index 6bf4f8d81a..0000000000
--- a/java/lib/org.eclipse.core.runtime.compatibility.registry_3.2.200.v20080610/META-INF/ECLIPSE.SF
+++ /dev/null
@@ -1,17 +0,0 @@
-Signature-Version: 1.0
-SHA1-Digest-Manifest: lM34M2cYUookZFTsw+CIRRJzG/o=
-Created-By: 1.5.0 (IBM Corporation)
-SHA1-Digest-Manifest-Main-Attributes: XjH6FbEjs0cznPMbHs9K2V7KmP4=
-
-Name: runtime_registry_compatibility.jar
-SHA1-Digest: 3ZA+TQU6TxgVia+krDcqMAAYdpU=
-
-Name: about.html
-SHA1-Digest: M+fykt9heyWoEv1LNiIEeBhi/2Q=
-
-Name: META-INF/eclipse.inf
-SHA1-Digest: SAqY+5ITAL0mkdYeijlSRhyIaZk=
-
-Name: fragment.properties
-SHA1-Digest: Gi/SEQV8Vl9A/8928AtuhnVkrKQ=
-
diff --git a/java/lib/org.eclipse.core.runtime.compatibility.registry_3.2.200.v20080610/META-INF/MANIFEST.MF b/java/lib/org.eclipse.core.runtime.compatibility.registry_3.2.200.v20080610/META-INF/MANIFEST.MF
deleted file mode 100644
index d9a497e8f4..0000000000
--- a/java/lib/org.eclipse.core.runtime.compatibility.registry_3.2.200.v20080610/META-INF/MANIFEST.MF
+++ /dev/null
@@ -1,25 +0,0 @@
-Manifest-Version: 1.0
-Bundle-RequiredExecutionEnvironment: CDC-1.0/Foundation-1.0,J2SE-1.3
-Bundle-SymbolicName: org.eclipse.core.runtime.compatibility.registry
-Bundle-ManifestVersion: 2
-Bundle-Localization: fragment
-Bundle-Name: %fragmentName
-Bundle-Version: 3.2.200.v20080610
-Bundle-ClassPath: runtime_registry_compatibility.jar
-Fragment-Host: org.eclipse.equinox.registry;bundle-version="[3.3.0,3.5
- .0)"
-Eclipse-PatchFragment: true
-Bundle-Vendor: %providerName
-
-Name: runtime_registry_compatibility.jar
-SHA1-Digest: Oxij1RUWY4Q3SjHVBqQuVSFgLxs=
-
-Name: about.html
-SHA1-Digest: ejOZra0kypGLQQ2bJtGTX+LI8tU=
-
-Name: META-INF/eclipse.inf
-SHA1-Digest: KyT9FF7C7t86NoBoa2kZT3ZJBfw=
-
-Name: fragment.properties
-SHA1-Digest: 4yjHkU5Z/6ej6ZFYT+PE9sMOJPY=
-
diff --git a/java/lib/org.eclipse.core.runtime.compatibility.registry_3.2.200.v20080610/META-INF/eclipse.inf b/java/lib/org.eclipse.core.runtime.compatibility.registry_3.2.200.v20080610/META-INF/eclipse.inf
deleted file mode 100644
index 7864d3c4c3..0000000000
--- a/java/lib/org.eclipse.core.runtime.compatibility.registry_3.2.200.v20080610/META-INF/eclipse.inf
+++ /dev/null
@@ -1,3 +0,0 @@
-#Processed using Jarprocessor
-pack200.args = -E4
-pack200.conditioned = true
diff --git a/java/lib/org.eclipse.core.runtime.compatibility.registry_3.2.200.v20080610/about.html b/java/lib/org.eclipse.core.runtime.compatibility.registry_3.2.200.v20080610/about.html
deleted file mode 100644
index 460233046e..0000000000
--- a/java/lib/org.eclipse.core.runtime.compatibility.registry_3.2.200.v20080610/about.html
+++ /dev/null
@@ -1,28 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"/>
-<title>About</title>
-</head>
-<body lang="EN-US">
-<h2>About This Content</h2>
-
-<p>June 2, 2006</p>
-<h3>License</h3>
-
-<p>The Eclipse Foundation makes available all content in this plug-in (&quot;Content&quot;). Unless otherwise
-indicated below, the Content is provided to you under the terms and conditions of the
-Eclipse Public License Version 1.0 (&quot;EPL&quot;). A copy of the EPL is available
-at <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>.
-For purposes of the EPL, &quot;Program&quot; will mean the Content.</p>
-
-<p>If you did not receive this Content directly from the Eclipse Foundation, the Content is
-being redistributed by another party (&quot;Redistributor&quot;) and different terms and conditions may
-apply to your use of any object code in the Content. Check the Redistributor's license that was
-provided with the Content. If no such license exists, contact the Redistributor. Unless otherwise
-indicated below, the terms and conditions of the EPL still apply to any source code in the Content
-and such source code may be obtained at <a href="http://www.eclipse.org">http://www.eclipse.org</a>.</p>
-
-</body>
-</html> \ No newline at end of file
diff --git a/java/lib/org.eclipse.core.runtime.compatibility.registry_3.2.200.v20080610/fragment.properties b/java/lib/org.eclipse.core.runtime.compatibility.registry_3.2.200.v20080610/fragment.properties
deleted file mode 100644
index e60dbf5c67..0000000000
--- a/java/lib/org.eclipse.core.runtime.compatibility.registry_3.2.200.v20080610/fragment.properties
+++ /dev/null
@@ -1,12 +0,0 @@
-###############################################################################
-# Copyright (c) 2006 IBM Corporation and others.
-# All rights reserved. This program and the accompanying materials
-# are made available under the terms of the Eclipse Public License v1.0
-# which accompanies this distribution, and is available at
-# http://www.eclipse.org/legal/epl-v10.html
-#
-# Contributors:
-# IBM Corporation - initial API and implementation
-###############################################################################
-providerName=Eclipse.org
-fragmentName=Eclipse Registry Compatibility Fragment
diff --git a/java/lib/org.eclipse.core.runtime.compatibility.registry_3.2.200.v20080610/runtime_registry_compatibility.jar b/java/lib/org.eclipse.core.runtime.compatibility.registry_3.2.200.v20080610/runtime_registry_compatibility.jar
deleted file mode 100644
index 3103fb0ce7..0000000000
--- a/java/lib/org.eclipse.core.runtime.compatibility.registry_3.2.200.v20080610/runtime_registry_compatibility.jar
+++ /dev/null
Binary files differ
diff --git a/java/lib/org.eclipse.core.runtime_3.4.0.v20080512.jar b/java/lib/org.eclipse.core.runtime_3.4.0.v20080512.jar
deleted file mode 100644
index 366be26fe3..0000000000
--- a/java/lib/org.eclipse.core.runtime_3.4.0.v20080512.jar
+++ /dev/null
Binary files differ
diff --git a/java/lib/org.eclipse.equinox.app_1.1.0.v20080421-2006.jar b/java/lib/org.eclipse.equinox.app_1.1.0.v20080421-2006.jar
deleted file mode 100644
index e46c099fe4..0000000000
--- a/java/lib/org.eclipse.equinox.app_1.1.0.v20080421-2006.jar
+++ /dev/null
Binary files differ
diff --git a/java/lib/org.eclipse.equinox.common_3.4.0.v20080421-2006.jar b/java/lib/org.eclipse.equinox.common_3.4.0.v20080421-2006.jar
deleted file mode 100644
index c73223995b..0000000000
--- a/java/lib/org.eclipse.equinox.common_3.4.0.v20080421-2006.jar
+++ /dev/null
Binary files differ
diff --git a/java/lib/org.eclipse.equinox.launcher.carbon.macosx_1.0.101.R34x_v20080731/META-INF/ECLIPSE.RSA b/java/lib/org.eclipse.equinox.launcher.carbon.macosx_1.0.101.R34x_v20080731/META-INF/ECLIPSE.RSA
deleted file mode 100644
index 29e6f3e7a0..0000000000
--- a/java/lib/org.eclipse.equinox.launcher.carbon.macosx_1.0.101.R34x_v20080731/META-INF/ECLIPSE.RSA
+++ /dev/null
Binary files differ
diff --git a/java/lib/org.eclipse.equinox.launcher.carbon.macosx_1.0.101.R34x_v20080731/META-INF/ECLIPSE.SF b/java/lib/org.eclipse.equinox.launcher.carbon.macosx_1.0.101.R34x_v20080731/META-INF/ECLIPSE.SF
deleted file mode 100644
index 1d2eece149..0000000000
--- a/java/lib/org.eclipse.equinox.launcher.carbon.macosx_1.0.101.R34x_v20080731/META-INF/ECLIPSE.SF
+++ /dev/null
@@ -1,17 +0,0 @@
-Signature-Version: 1.0
-SHA1-Digest-Manifest: FheFhPCFIe9e17dtN19PvFpfHzs=
-Created-By: 1.5.0 (IBM Corporation)
-SHA1-Digest-Manifest-Main-Attributes: X4gDjCpbD8vwxPcCNeLjJjIHBoU=
-
-Name: about.html
-SHA1-Digest: xGcp/Hbq/ywyvVWkPzD/2vkIzdY=
-
-Name: eclipse_1115.so
-SHA1-Digest: ItFKEUKn9bCxLiWwFj8ubKbopDg=
-
-Name: META-INF/eclipse.inf
-SHA1-Digest: SAqY+5ITAL0mkdYeijlSRhyIaZk=
-
-Name: launcher.carbon.macosx.properties
-SHA1-Digest: iJiwtqN46CqxjQPiFqskiJDS2hk=
-
diff --git a/java/lib/org.eclipse.equinox.launcher.carbon.macosx_1.0.101.R34x_v20080731/META-INF/MANIFEST.MF b/java/lib/org.eclipse.equinox.launcher.carbon.macosx_1.0.101.R34x_v20080731/META-INF/MANIFEST.MF
deleted file mode 100644
index f9ef43c43a..0000000000
--- a/java/lib/org.eclipse.equinox.launcher.carbon.macosx_1.0.101.R34x_v20080731/META-INF/MANIFEST.MF
+++ /dev/null
@@ -1,25 +0,0 @@
-Manifest-Version: 1.0
-Bundle-SymbolicName: org.eclipse.equinox.launcher.carbon.macosx;single
- ton:=true
-Bundle-ManifestVersion: 2
-Bundle-Localization: launcher.carbon.macosx
-Bundle-Name: %pluginName
-Eclipse-PlatformFilter: (& (osgi.ws=carbon) (osgi.os=macosx) (|(osgi.a
- rch=x86)(osgi.arch=ppc)) )
-Bundle-Version: 1.0.101.R34x_v20080731
-Fragment-Host: org.eclipse.equinox.launcher;bundle-version="[1.0.0,1.1
- .0)"
-Bundle-Vendor: %providerName
-
-Name: eclipse_1115.so
-SHA1-Digest: RRLhb5Prci79GCZFsylKadyPBvM=
-
-Name: about.html
-SHA1-Digest: a9lDHrGuLPkvHBUhsqWU+V2mhPw=
-
-Name: META-INF/eclipse.inf
-SHA1-Digest: KyT9FF7C7t86NoBoa2kZT3ZJBfw=
-
-Name: launcher.carbon.macosx.properties
-SHA1-Digest: L4VSSU2M0KAWyhCp8QBLMsnC6Jk=
-
diff --git a/java/lib/org.eclipse.equinox.launcher.carbon.macosx_1.0.101.R34x_v20080731/META-INF/eclipse.inf b/java/lib/org.eclipse.equinox.launcher.carbon.macosx_1.0.101.R34x_v20080731/META-INF/eclipse.inf
deleted file mode 100644
index 7864d3c4c3..0000000000
--- a/java/lib/org.eclipse.equinox.launcher.carbon.macosx_1.0.101.R34x_v20080731/META-INF/eclipse.inf
+++ /dev/null
@@ -1,3 +0,0 @@
-#Processed using Jarprocessor
-pack200.args = -E4
-pack200.conditioned = true
diff --git a/java/lib/org.eclipse.equinox.launcher.carbon.macosx_1.0.101.R34x_v20080731/about.html b/java/lib/org.eclipse.equinox.launcher.carbon.macosx_1.0.101.R34x_v20080731/about.html
deleted file mode 100644
index 395df3ba90..0000000000
--- a/java/lib/org.eclipse.equinox.launcher.carbon.macosx_1.0.101.R34x_v20080731/about.html
+++ /dev/null
@@ -1,28 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"/>
-<title>About</title>
-</head>
-<body lang="EN-US">
-<h2>About This Content</h2>
-
-<p>June 5, 2006</p>
-<h3>License</h3>
-
-<p>The Eclipse Foundation makes available all content in this plug-in (&quot;Content&quot;).
-Unless otherwise indicated below, the Content is provided to you under the terms and conditions of the
-Eclipse Public License Version 1.0 (&quot;EPL&quot;). A copy of the EPL is available
-at <a href="http://www.eclipse.org/org/documents/epl-v10.php">http://www.eclipse.org/legal/epl-v10.html</a>.
-For purposes of the EPL, &quot;Program&quot; will mean the Content.</p>
-
-<p>If you did not receive this Content directly from the Eclipse Foundation, the Content is
-being redistributed by another party (&quot;Redistributor&quot;) and different terms and conditions may
-apply to your use of any object code in the Content. Check the Redistributor&rsquo;s license
-that was provided with the Content. If no such license exists, contact the Redistributor. Unless otherwise
-indicated below, the terms and conditions of the EPL still apply to any source code in the Content
-and such source code may be obtained at <a href="http://www.eclipse.org/">http://www.eclipse.org</a>.</p>
-
-</body>
-</html> \ No newline at end of file
diff --git a/java/lib/org.eclipse.equinox.launcher.carbon.macosx_1.0.101.R34x_v20080731/eclipse_1115.so b/java/lib/org.eclipse.equinox.launcher.carbon.macosx_1.0.101.R34x_v20080731/eclipse_1115.so
deleted file mode 100644
index 17e8230b19..0000000000
--- a/java/lib/org.eclipse.equinox.launcher.carbon.macosx_1.0.101.R34x_v20080731/eclipse_1115.so
+++ /dev/null
Binary files differ
diff --git a/java/lib/org.eclipse.equinox.launcher.carbon.macosx_1.0.101.R34x_v20080731/launcher.carbon.macosx.properties b/java/lib/org.eclipse.equinox.launcher.carbon.macosx_1.0.101.R34x_v20080731/launcher.carbon.macosx.properties
deleted file mode 100644
index 4373d35790..0000000000
--- a/java/lib/org.eclipse.equinox.launcher.carbon.macosx_1.0.101.R34x_v20080731/launcher.carbon.macosx.properties
+++ /dev/null
@@ -1,12 +0,0 @@
-###############################################################################
-# Copyright (c) 2007 IBM Corporation and others.
-# All rights reserved. This program and the accompanying materials
-# are made available under the terms of the Eclipse Public License v1.0
-# which accompanies this distribution, and is available at
-# http://www.eclipse.org/legal/epl-v10.html
-#
-# Contributors:
-# IBM Corporation - initial API and implementation
-###############################################################################
-pluginName = Equinox Launcher MacOSX Fragment
-providerName = Eclipse.org
diff --git a/java/lib/org.eclipse.equinox.launcher.gtk.linux.x86_1.0.101.R34x_v20080805/META-INF/ECLIPSE.RSA b/java/lib/org.eclipse.equinox.launcher.gtk.linux.x86_1.0.101.R34x_v20080805/META-INF/ECLIPSE.RSA
deleted file mode 100644
index 566c0abd11..0000000000
--- a/java/lib/org.eclipse.equinox.launcher.gtk.linux.x86_1.0.101.R34x_v20080805/META-INF/ECLIPSE.RSA
+++ /dev/null
Binary files differ
diff --git a/java/lib/org.eclipse.equinox.launcher.gtk.linux.x86_1.0.101.R34x_v20080805/META-INF/ECLIPSE.SF b/java/lib/org.eclipse.equinox.launcher.gtk.linux.x86_1.0.101.R34x_v20080805/META-INF/ECLIPSE.SF
deleted file mode 100644
index 4122b4ea8f..0000000000
--- a/java/lib/org.eclipse.equinox.launcher.gtk.linux.x86_1.0.101.R34x_v20080805/META-INF/ECLIPSE.SF
+++ /dev/null
@@ -1,17 +0,0 @@
-Signature-Version: 1.0
-SHA1-Digest-Manifest: tswsDz0e+s2SPhfY7LybTLEXoI4=
-Created-By: 1.5.0 (IBM Corporation)
-SHA1-Digest-Manifest-Main-Attributes: Ymnpf9HjgpR8t0MrPx1wLH4tJFQ=
-
-Name: launcher.gtk.linux.x86.properties
-SHA1-Digest: +CJXeQUkWFS+xYpRY6jNNT065mI=
-
-Name: about.html
-SHA1-Digest: xGcp/Hbq/ywyvVWkPzD/2vkIzdY=
-
-Name: eclipse_1115.so
-SHA1-Digest: gvha3rnYpdA1SDXsMMxPKyEB/Xg=
-
-Name: META-INF/eclipse.inf
-SHA1-Digest: SAqY+5ITAL0mkdYeijlSRhyIaZk=
-
diff --git a/java/lib/org.eclipse.equinox.launcher.gtk.linux.x86_1.0.101.R34x_v20080805/META-INF/MANIFEST.MF b/java/lib/org.eclipse.equinox.launcher.gtk.linux.x86_1.0.101.R34x_v20080805/META-INF/MANIFEST.MF
deleted file mode 100644
index d699938858..0000000000
--- a/java/lib/org.eclipse.equinox.launcher.gtk.linux.x86_1.0.101.R34x_v20080805/META-INF/MANIFEST.MF
+++ /dev/null
@@ -1,25 +0,0 @@
-Manifest-Version: 1.0
-Bundle-SymbolicName: org.eclipse.equinox.launcher.gtk.linux.x86;single
- ton:=true
-Bundle-ManifestVersion: 2
-Bundle-Localization: launcher.gtk.linux.x86
-Bundle-Name: %pluginName
-Eclipse-PlatformFilter: (& (osgi.ws=gtk) (osgi.os=linux) (osgi.arch=x8
- 6))
-Bundle-Version: 1.0.101.R34x_v20080805
-Fragment-Host: org.eclipse.equinox.launcher;bundle-version="[1.0.0,1.1
- .0)"
-Bundle-Vendor: %providerName
-
-Name: launcher.gtk.linux.x86.properties
-SHA1-Digest: BSbhScorws9R/DVRUdKNmymMSIU=
-
-Name: eclipse_1115.so
-SHA1-Digest: n3UyHV1KgJ0YuFIDUxPBXj2dxw0=
-
-Name: about.html
-SHA1-Digest: a9lDHrGuLPkvHBUhsqWU+V2mhPw=
-
-Name: META-INF/eclipse.inf
-SHA1-Digest: KyT9FF7C7t86NoBoa2kZT3ZJBfw=
-
diff --git a/java/lib/org.eclipse.equinox.launcher.gtk.linux.x86_1.0.101.R34x_v20080805/META-INF/eclipse.inf b/java/lib/org.eclipse.equinox.launcher.gtk.linux.x86_1.0.101.R34x_v20080805/META-INF/eclipse.inf
deleted file mode 100644
index 7864d3c4c3..0000000000
--- a/java/lib/org.eclipse.equinox.launcher.gtk.linux.x86_1.0.101.R34x_v20080805/META-INF/eclipse.inf
+++ /dev/null
@@ -1,3 +0,0 @@
-#Processed using Jarprocessor
-pack200.args = -E4
-pack200.conditioned = true
diff --git a/java/lib/org.eclipse.equinox.launcher.gtk.linux.x86_1.0.101.R34x_v20080805/about.html b/java/lib/org.eclipse.equinox.launcher.gtk.linux.x86_1.0.101.R34x_v20080805/about.html
deleted file mode 100644
index 395df3ba90..0000000000
--- a/java/lib/org.eclipse.equinox.launcher.gtk.linux.x86_1.0.101.R34x_v20080805/about.html
+++ /dev/null
@@ -1,28 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"/>
-<title>About</title>
-</head>
-<body lang="EN-US">
-<h2>About This Content</h2>
-
-<p>June 5, 2006</p>
-<h3>License</h3>
-
-<p>The Eclipse Foundation makes available all content in this plug-in (&quot;Content&quot;).
-Unless otherwise indicated below, the Content is provided to you under the terms and conditions of the
-Eclipse Public License Version 1.0 (&quot;EPL&quot;). A copy of the EPL is available
-at <a href="http://www.eclipse.org/org/documents/epl-v10.php">http://www.eclipse.org/legal/epl-v10.html</a>.
-For purposes of the EPL, &quot;Program&quot; will mean the Content.</p>
-
-<p>If you did not receive this Content directly from the Eclipse Foundation, the Content is
-being redistributed by another party (&quot;Redistributor&quot;) and different terms and conditions may
-apply to your use of any object code in the Content. Check the Redistributor&rsquo;s license
-that was provided with the Content. If no such license exists, contact the Redistributor. Unless otherwise
-indicated below, the terms and conditions of the EPL still apply to any source code in the Content
-and such source code may be obtained at <a href="http://www.eclipse.org/">http://www.eclipse.org</a>.</p>
-
-</body>
-</html> \ No newline at end of file
diff --git a/java/lib/org.eclipse.equinox.launcher.gtk.linux.x86_1.0.101.R34x_v20080805/eclipse_1115.so b/java/lib/org.eclipse.equinox.launcher.gtk.linux.x86_1.0.101.R34x_v20080805/eclipse_1115.so
deleted file mode 100644
index 3ec14a5e88..0000000000
--- a/java/lib/org.eclipse.equinox.launcher.gtk.linux.x86_1.0.101.R34x_v20080805/eclipse_1115.so
+++ /dev/null
Binary files differ
diff --git a/java/lib/org.eclipse.equinox.launcher.gtk.linux.x86_1.0.101.R34x_v20080805/launcher.gtk.linux.x86.properties b/java/lib/org.eclipse.equinox.launcher.gtk.linux.x86_1.0.101.R34x_v20080805/launcher.gtk.linux.x86.properties
deleted file mode 100644
index 792485112e..0000000000
--- a/java/lib/org.eclipse.equinox.launcher.gtk.linux.x86_1.0.101.R34x_v20080805/launcher.gtk.linux.x86.properties
+++ /dev/null
@@ -1,12 +0,0 @@
-###############################################################################
-# Copyright (c) 2007 IBM Corporation and others.
-# All rights reserved. This program and the accompanying materials
-# are made available under the terms of the Eclipse Public License v1.0
-# which accompanies this distribution, and is available at
-# http://www.eclipse.org/legal/epl-v10.html
-#
-# Contributors:
-# IBM Corporation - initial API and implementation
-###############################################################################
-pluginName = Equinox Launcher Linux X86 Fragment
-providerName = Eclipse.org
diff --git a/java/lib/org.eclipse.equinox.launcher.gtk.linux.x86_64_1.0.101.R34x_v20080731/META-INF/ECLIPSE.RSA b/java/lib/org.eclipse.equinox.launcher.gtk.linux.x86_64_1.0.101.R34x_v20080731/META-INF/ECLIPSE.RSA
deleted file mode 100644
index df6b24ad57..0000000000
--- a/java/lib/org.eclipse.equinox.launcher.gtk.linux.x86_64_1.0.101.R34x_v20080731/META-INF/ECLIPSE.RSA
+++ /dev/null
Binary files differ
diff --git a/java/lib/org.eclipse.equinox.launcher.gtk.linux.x86_64_1.0.101.R34x_v20080731/META-INF/ECLIPSE.SF b/java/lib/org.eclipse.equinox.launcher.gtk.linux.x86_64_1.0.101.R34x_v20080731/META-INF/ECLIPSE.SF
deleted file mode 100644
index 4193e97338..0000000000
--- a/java/lib/org.eclipse.equinox.launcher.gtk.linux.x86_64_1.0.101.R34x_v20080731/META-INF/ECLIPSE.SF
+++ /dev/null
@@ -1,17 +0,0 @@
-Signature-Version: 1.0
-SHA1-Digest-Manifest: gnfArgp6eM77c1JxQF9X3q9/Hd8=
-Created-By: 1.5.0 (IBM Corporation)
-SHA1-Digest-Manifest-Main-Attributes: hR6QNnvCGlzBxiyTmh4DMZ03Yyg=
-
-Name: about.html
-SHA1-Digest: xGcp/Hbq/ywyvVWkPzD/2vkIzdY=
-
-Name: eclipse_1115.so
-SHA1-Digest: 33jSy/p2jY6bvgg4W0xBlxjxMWA=
-
-Name: META-INF/eclipse.inf
-SHA1-Digest: SAqY+5ITAL0mkdYeijlSRhyIaZk=
-
-Name: launcher.gtk.linux.x86_64.properties
-SHA1-Digest: Q2rsj7VmfkLLH24miqu0v+2sZjE=
-
diff --git a/java/lib/org.eclipse.equinox.launcher.gtk.linux.x86_64_1.0.101.R34x_v20080731/META-INF/MANIFEST.MF b/java/lib/org.eclipse.equinox.launcher.gtk.linux.x86_64_1.0.101.R34x_v20080731/META-INF/MANIFEST.MF
deleted file mode 100644
index b790c0af9a..0000000000
--- a/java/lib/org.eclipse.equinox.launcher.gtk.linux.x86_64_1.0.101.R34x_v20080731/META-INF/MANIFEST.MF
+++ /dev/null
@@ -1,25 +0,0 @@
-Manifest-Version: 1.0
-Bundle-SymbolicName: org.eclipse.equinox.launcher.gtk.linux.x86_64;sin
- gleton:=true
-Bundle-ManifestVersion: 2
-Bundle-Localization: launcher.gtk.linux.x86_64
-Bundle-Name: %pluginName
-Eclipse-PlatformFilter: (& (osgi.ws=gtk) (osgi.os=linux) (osgi.arch=x8
- 6_64))
-Bundle-Version: 1.0.101.R34x_v20080731
-Fragment-Host: org.eclipse.equinox.launcher;bundle-version="[1.0.0,1.1
- .0)"
-Bundle-Vendor: %providerName
-
-Name: eclipse_1115.so
-SHA1-Digest: l0VkVxLXANjcUEWTLRqXKUmIfn8=
-
-Name: about.html
-SHA1-Digest: a9lDHrGuLPkvHBUhsqWU+V2mhPw=
-
-Name: META-INF/eclipse.inf
-SHA1-Digest: KyT9FF7C7t86NoBoa2kZT3ZJBfw=
-
-Name: launcher.gtk.linux.x86_64.properties
-SHA1-Digest: thXaNI0tmsHrCOYNbQBW2zzAh+Q=
-
diff --git a/java/lib/org.eclipse.equinox.launcher.gtk.linux.x86_64_1.0.101.R34x_v20080731/META-INF/eclipse.inf b/java/lib/org.eclipse.equinox.launcher.gtk.linux.x86_64_1.0.101.R34x_v20080731/META-INF/eclipse.inf
deleted file mode 100644
index 7864d3c4c3..0000000000
--- a/java/lib/org.eclipse.equinox.launcher.gtk.linux.x86_64_1.0.101.R34x_v20080731/META-INF/eclipse.inf
+++ /dev/null
@@ -1,3 +0,0 @@
-#Processed using Jarprocessor
-pack200.args = -E4
-pack200.conditioned = true
diff --git a/java/lib/org.eclipse.equinox.launcher.gtk.linux.x86_64_1.0.101.R34x_v20080731/about.html b/java/lib/org.eclipse.equinox.launcher.gtk.linux.x86_64_1.0.101.R34x_v20080731/about.html
deleted file mode 100644
index 395df3ba90..0000000000
--- a/java/lib/org.eclipse.equinox.launcher.gtk.linux.x86_64_1.0.101.R34x_v20080731/about.html
+++ /dev/null
@@ -1,28 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"/>
-<title>About</title>
-</head>
-<body lang="EN-US">
-<h2>About This Content</h2>
-
-<p>June 5, 2006</p>
-<h3>License</h3>
-
-<p>The Eclipse Foundation makes available all content in this plug-in (&quot;Content&quot;).
-Unless otherwise indicated below, the Content is provided to you under the terms and conditions of the
-Eclipse Public License Version 1.0 (&quot;EPL&quot;). A copy of the EPL is available
-at <a href="http://www.eclipse.org/org/documents/epl-v10.php">http://www.eclipse.org/legal/epl-v10.html</a>.
-For purposes of the EPL, &quot;Program&quot; will mean the Content.</p>
-
-<p>If you did not receive this Content directly from the Eclipse Foundation, the Content is
-being redistributed by another party (&quot;Redistributor&quot;) and different terms and conditions may
-apply to your use of any object code in the Content. Check the Redistributor&rsquo;s license
-that was provided with the Content. If no such license exists, contact the Redistributor. Unless otherwise
-indicated below, the terms and conditions of the EPL still apply to any source code in the Content
-and such source code may be obtained at <a href="http://www.eclipse.org/">http://www.eclipse.org</a>.</p>
-
-</body>
-</html> \ No newline at end of file
diff --git a/java/lib/org.eclipse.equinox.launcher.gtk.linux.x86_64_1.0.101.R34x_v20080731/eclipse_1115.so b/java/lib/org.eclipse.equinox.launcher.gtk.linux.x86_64_1.0.101.R34x_v20080731/eclipse_1115.so
deleted file mode 100644
index 8bf855533c..0000000000
--- a/java/lib/org.eclipse.equinox.launcher.gtk.linux.x86_64_1.0.101.R34x_v20080731/eclipse_1115.so
+++ /dev/null
Binary files differ
diff --git a/java/lib/org.eclipse.equinox.launcher.gtk.linux.x86_64_1.0.101.R34x_v20080731/launcher.gtk.linux.x86_64.properties b/java/lib/org.eclipse.equinox.launcher.gtk.linux.x86_64_1.0.101.R34x_v20080731/launcher.gtk.linux.x86_64.properties
deleted file mode 100644
index da448aadbb..0000000000
--- a/java/lib/org.eclipse.equinox.launcher.gtk.linux.x86_64_1.0.101.R34x_v20080731/launcher.gtk.linux.x86_64.properties
+++ /dev/null
@@ -1,12 +0,0 @@
-###############################################################################
-# Copyright (c) 2007 IBM Corporation and others.
-# All rights reserved. This program and the accompanying materials
-# are made available under the terms of the Eclipse Public License v1.0
-# which accompanies this distribution, and is available at
-# http://www.eclipse.org/legal/epl-v10.html
-#
-# Contributors:
-# IBM Corporation - initial API and implementation
-###############################################################################
-pluginName = Equinox Launcher Linux X86_64 Fragment
-providerName = Eclipse.org
diff --git a/java/lib/org.eclipse.equinox.launcher.gtk.solaris.sparc_1.0.101.R34x_v20080731/META-INF/ECLIPSE.RSA b/java/lib/org.eclipse.equinox.launcher.gtk.solaris.sparc_1.0.101.R34x_v20080731/META-INF/ECLIPSE.RSA
deleted file mode 100644
index 81599f2e21..0000000000
--- a/java/lib/org.eclipse.equinox.launcher.gtk.solaris.sparc_1.0.101.R34x_v20080731/META-INF/ECLIPSE.RSA
+++ /dev/null
Binary files differ
diff --git a/java/lib/org.eclipse.equinox.launcher.gtk.solaris.sparc_1.0.101.R34x_v20080731/META-INF/ECLIPSE.SF b/java/lib/org.eclipse.equinox.launcher.gtk.solaris.sparc_1.0.101.R34x_v20080731/META-INF/ECLIPSE.SF
deleted file mode 100644
index 20fe507cdf..0000000000
--- a/java/lib/org.eclipse.equinox.launcher.gtk.solaris.sparc_1.0.101.R34x_v20080731/META-INF/ECLIPSE.SF
+++ /dev/null
@@ -1,17 +0,0 @@
-Signature-Version: 1.0
-SHA1-Digest-Manifest: kR1kAxZlcW3W0rm/xjIZED9LrAo=
-Created-By: 1.5.0 (IBM Corporation)
-SHA1-Digest-Manifest-Main-Attributes: pqNWWWTyBz8hsANASpU3hoVl9kc=
-
-Name: about.html
-SHA1-Digest: xGcp/Hbq/ywyvVWkPzD/2vkIzdY=
-
-Name: eclipse_1115.so
-SHA1-Digest: o5PGzpcLRdWF5shzEwmVFCwZrb0=
-
-Name: META-INF/eclipse.inf
-SHA1-Digest: SAqY+5ITAL0mkdYeijlSRhyIaZk=
-
-Name: launcher.gtk.solaris.sparc.properties
-SHA1-Digest: gu+HrnaK+kn508ppLY/iXys12yA=
-
diff --git a/java/lib/org.eclipse.equinox.launcher.gtk.solaris.sparc_1.0.101.R34x_v20080731/META-INF/MANIFEST.MF b/java/lib/org.eclipse.equinox.launcher.gtk.solaris.sparc_1.0.101.R34x_v20080731/META-INF/MANIFEST.MF
deleted file mode 100644
index f81e6141bb..0000000000
--- a/java/lib/org.eclipse.equinox.launcher.gtk.solaris.sparc_1.0.101.R34x_v20080731/META-INF/MANIFEST.MF
+++ /dev/null
@@ -1,25 +0,0 @@
-Manifest-Version: 1.0
-Bundle-SymbolicName: org.eclipse.equinox.launcher.gtk.solaris.sparc;si
- ngleton:=true
-Bundle-ManifestVersion: 2
-Bundle-Localization: launcher.gtk.solaris.sparc
-Bundle-Name: %pluginName
-Eclipse-PlatformFilter: (& (osgi.ws=gtk) (osgi.os=solaris) (osgi.arch=
- sparc))
-Bundle-Version: 1.0.101.R34x_v20080731
-Fragment-Host: org.eclipse.equinox.launcher;bundle-version="[1.0.0,1.1
- .0)"
-Bundle-Vendor: %providerName
-
-Name: eclipse_1115.so
-SHA1-Digest: 5km5rPngvbWH3aWIYrl+xMejhCE=
-
-Name: about.html
-SHA1-Digest: a9lDHrGuLPkvHBUhsqWU+V2mhPw=
-
-Name: META-INF/eclipse.inf
-SHA1-Digest: KyT9FF7C7t86NoBoa2kZT3ZJBfw=
-
-Name: launcher.gtk.solaris.sparc.properties
-SHA1-Digest: B/N7qN8v4Os5flFl4mE2UaqnMZs=
-
diff --git a/java/lib/org.eclipse.equinox.launcher.gtk.solaris.sparc_1.0.101.R34x_v20080731/META-INF/eclipse.inf b/java/lib/org.eclipse.equinox.launcher.gtk.solaris.sparc_1.0.101.R34x_v20080731/META-INF/eclipse.inf
deleted file mode 100644
index 7864d3c4c3..0000000000
--- a/java/lib/org.eclipse.equinox.launcher.gtk.solaris.sparc_1.0.101.R34x_v20080731/META-INF/eclipse.inf
+++ /dev/null
@@ -1,3 +0,0 @@
-#Processed using Jarprocessor
-pack200.args = -E4
-pack200.conditioned = true
diff --git a/java/lib/org.eclipse.equinox.launcher.gtk.solaris.sparc_1.0.101.R34x_v20080731/about.html b/java/lib/org.eclipse.equinox.launcher.gtk.solaris.sparc_1.0.101.R34x_v20080731/about.html
deleted file mode 100644
index 395df3ba90..0000000000
--- a/java/lib/org.eclipse.equinox.launcher.gtk.solaris.sparc_1.0.101.R34x_v20080731/about.html
+++ /dev/null
@@ -1,28 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"/>
-<title>About</title>
-</head>
-<body lang="EN-US">
-<h2>About This Content</h2>
-
-<p>June 5, 2006</p>
-<h3>License</h3>
-
-<p>The Eclipse Foundation makes available all content in this plug-in (&quot;Content&quot;).
-Unless otherwise indicated below, the Content is provided to you under the terms and conditions of the
-Eclipse Public License Version 1.0 (&quot;EPL&quot;). A copy of the EPL is available
-at <a href="http://www.eclipse.org/org/documents/epl-v10.php">http://www.eclipse.org/legal/epl-v10.html</a>.
-For purposes of the EPL, &quot;Program&quot; will mean the Content.</p>
-
-<p>If you did not receive this Content directly from the Eclipse Foundation, the Content is
-being redistributed by another party (&quot;Redistributor&quot;) and different terms and conditions may
-apply to your use of any object code in the Content. Check the Redistributor&rsquo;s license
-that was provided with the Content. If no such license exists, contact the Redistributor. Unless otherwise
-indicated below, the terms and conditions of the EPL still apply to any source code in the Content
-and such source code may be obtained at <a href="http://www.eclipse.org/">http://www.eclipse.org</a>.</p>
-
-</body>
-</html> \ No newline at end of file
diff --git a/java/lib/org.eclipse.equinox.launcher.gtk.solaris.sparc_1.0.101.R34x_v20080731/eclipse_1115.so b/java/lib/org.eclipse.equinox.launcher.gtk.solaris.sparc_1.0.101.R34x_v20080731/eclipse_1115.so
deleted file mode 100644
index 3d8beb88dd..0000000000
--- a/java/lib/org.eclipse.equinox.launcher.gtk.solaris.sparc_1.0.101.R34x_v20080731/eclipse_1115.so
+++ /dev/null
Binary files differ
diff --git a/java/lib/org.eclipse.equinox.launcher.gtk.solaris.sparc_1.0.101.R34x_v20080731/launcher.gtk.solaris.sparc.properties b/java/lib/org.eclipse.equinox.launcher.gtk.solaris.sparc_1.0.101.R34x_v20080731/launcher.gtk.solaris.sparc.properties
deleted file mode 100644
index c3f2ae186e..0000000000
--- a/java/lib/org.eclipse.equinox.launcher.gtk.solaris.sparc_1.0.101.R34x_v20080731/launcher.gtk.solaris.sparc.properties
+++ /dev/null
@@ -1,12 +0,0 @@
-###############################################################################
-# Copyright (c) 2007 IBM Corporation and others.
-# All rights reserved. This program and the accompanying materials
-# are made available under the terms of the Eclipse Public License v1.0
-# which accompanies this distribution, and is available at
-# http://www.eclipse.org/legal/epl-v10.html
-#
-# Contributors:
-# IBM Corporation - initial API and implementation
-###############################################################################
-pluginName = Equinox Launcher Sparc Fragment
-providerName = Eclipse.org
diff --git a/java/lib/org.eclipse.equinox.launcher.win32.win32.x86_1.0.101.R34x_v20080731/META-INF/ECLIPSE.RSA b/java/lib/org.eclipse.equinox.launcher.win32.win32.x86_1.0.101.R34x_v20080731/META-INF/ECLIPSE.RSA
deleted file mode 100644
index e2350f7b3d..0000000000
--- a/java/lib/org.eclipse.equinox.launcher.win32.win32.x86_1.0.101.R34x_v20080731/META-INF/ECLIPSE.RSA
+++ /dev/null
Binary files differ
diff --git a/java/lib/org.eclipse.equinox.launcher.win32.win32.x86_1.0.101.R34x_v20080731/META-INF/ECLIPSE.SF b/java/lib/org.eclipse.equinox.launcher.win32.win32.x86_1.0.101.R34x_v20080731/META-INF/ECLIPSE.SF
deleted file mode 100644
index a4cc0ac995..0000000000
--- a/java/lib/org.eclipse.equinox.launcher.win32.win32.x86_1.0.101.R34x_v20080731/META-INF/ECLIPSE.SF
+++ /dev/null
@@ -1,17 +0,0 @@
-Signature-Version: 1.0
-SHA1-Digest-Manifest: oXE8Y8m0B4hXXkniJ3e42s+zWZA=
-Created-By: 1.5.0 (IBM Corporation)
-SHA1-Digest-Manifest-Main-Attributes: D+OZA9EIs+7l5qfZkdxKrzNalvU=
-
-Name: about.html
-SHA1-Digest: xGcp/Hbq/ywyvVWkPzD/2vkIzdY=
-
-Name: launcher.win32.win32.x86.properties
-SHA1-Digest: TMYbn4sXlC4uxONCDt2S0kP1hTY=
-
-Name: META-INF/eclipse.inf
-SHA1-Digest: SAqY+5ITAL0mkdYeijlSRhyIaZk=
-
-Name: eclipse_1115.dll
-SHA1-Digest: ishZ405IXeNkJcKK6X6ZCmhtZOk=
-
diff --git a/java/lib/org.eclipse.equinox.launcher.win32.win32.x86_1.0.101.R34x_v20080731/META-INF/MANIFEST.MF b/java/lib/org.eclipse.equinox.launcher.win32.win32.x86_1.0.101.R34x_v20080731/META-INF/MANIFEST.MF
deleted file mode 100644
index 6acfe13c74..0000000000
--- a/java/lib/org.eclipse.equinox.launcher.win32.win32.x86_1.0.101.R34x_v20080731/META-INF/MANIFEST.MF
+++ /dev/null
@@ -1,25 +0,0 @@
-Manifest-Version: 1.0
-Bundle-SymbolicName: org.eclipse.equinox.launcher.win32.win32.x86; sin
- gleton:=true
-Bundle-ManifestVersion: 2
-Bundle-Localization: launcher.win32.win32.x86
-Bundle-Name: %pluginName
-Eclipse-PlatformFilter: (& (osgi.ws=win32) (osgi.os=win32) (osgi.arch=
- x86))
-Bundle-Version: 1.0.101.R34x_v20080731
-Fragment-Host: org.eclipse.equinox.launcher;bundle-version="[1.0.0,1.1
- .0)"
-Bundle-Vendor: %providerName
-
-Name: about.html
-SHA1-Digest: a9lDHrGuLPkvHBUhsqWU+V2mhPw=
-
-Name: META-INF/eclipse.inf
-SHA1-Digest: KyT9FF7C7t86NoBoa2kZT3ZJBfw=
-
-Name: launcher.win32.win32.x86.properties
-SHA1-Digest: rhstucCaFV5tj2GARC/9A5zdmB4=
-
-Name: eclipse_1115.dll
-SHA1-Digest: 6f1Zg9WvwnS5OsA5EB8tWKy1480=
-
diff --git a/java/lib/org.eclipse.equinox.launcher.win32.win32.x86_1.0.101.R34x_v20080731/META-INF/eclipse.inf b/java/lib/org.eclipse.equinox.launcher.win32.win32.x86_1.0.101.R34x_v20080731/META-INF/eclipse.inf
deleted file mode 100644
index 7864d3c4c3..0000000000
--- a/java/lib/org.eclipse.equinox.launcher.win32.win32.x86_1.0.101.R34x_v20080731/META-INF/eclipse.inf
+++ /dev/null
@@ -1,3 +0,0 @@
-#Processed using Jarprocessor
-pack200.args = -E4
-pack200.conditioned = true
diff --git a/java/lib/org.eclipse.equinox.launcher.win32.win32.x86_1.0.101.R34x_v20080731/about.html b/java/lib/org.eclipse.equinox.launcher.win32.win32.x86_1.0.101.R34x_v20080731/about.html
deleted file mode 100644
index 395df3ba90..0000000000
--- a/java/lib/org.eclipse.equinox.launcher.win32.win32.x86_1.0.101.R34x_v20080731/about.html
+++ /dev/null
@@ -1,28 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"/>
-<title>About</title>
-</head>
-<body lang="EN-US">
-<h2>About This Content</h2>
-
-<p>June 5, 2006</p>
-<h3>License</h3>
-
-<p>The Eclipse Foundation makes available all content in this plug-in (&quot;Content&quot;).
-Unless otherwise indicated below, the Content is provided to you under the terms and conditions of the
-Eclipse Public License Version 1.0 (&quot;EPL&quot;). A copy of the EPL is available
-at <a href="http://www.eclipse.org/org/documents/epl-v10.php">http://www.eclipse.org/legal/epl-v10.html</a>.
-For purposes of the EPL, &quot;Program&quot; will mean the Content.</p>
-
-<p>If you did not receive this Content directly from the Eclipse Foundation, the Content is
-being redistributed by another party (&quot;Redistributor&quot;) and different terms and conditions may
-apply to your use of any object code in the Content. Check the Redistributor&rsquo;s license
-that was provided with the Content. If no such license exists, contact the Redistributor. Unless otherwise
-indicated below, the terms and conditions of the EPL still apply to any source code in the Content
-and such source code may be obtained at <a href="http://www.eclipse.org/">http://www.eclipse.org</a>.</p>
-
-</body>
-</html> \ No newline at end of file
diff --git a/java/lib/org.eclipse.equinox.launcher.win32.win32.x86_1.0.101.R34x_v20080731/eclipse_1115.dll b/java/lib/org.eclipse.equinox.launcher.win32.win32.x86_1.0.101.R34x_v20080731/eclipse_1115.dll
deleted file mode 100644
index 5e438cf505..0000000000
--- a/java/lib/org.eclipse.equinox.launcher.win32.win32.x86_1.0.101.R34x_v20080731/eclipse_1115.dll
+++ /dev/null
Binary files differ
diff --git a/java/lib/org.eclipse.equinox.launcher.win32.win32.x86_1.0.101.R34x_v20080731/launcher.win32.win32.x86.properties b/java/lib/org.eclipse.equinox.launcher.win32.win32.x86_1.0.101.R34x_v20080731/launcher.win32.win32.x86.properties
deleted file mode 100644
index e8f40bca50..0000000000
--- a/java/lib/org.eclipse.equinox.launcher.win32.win32.x86_1.0.101.R34x_v20080731/launcher.win32.win32.x86.properties
+++ /dev/null
@@ -1,12 +0,0 @@
-###############################################################################
-# Copyright (c) 2007 IBM Corporation and others.
-# All rights reserved. This program and the accompanying materials
-# are made available under the terms of the Eclipse Public License v1.0
-# which accompanies this distribution, and is available at
-# http://www.eclipse.org/legal/epl-v10.html
-#
-# Contributors:
-# IBM Corporation - initial API and implementation
-###############################################################################
-pluginName = Equinox Launcher Win32 X86 Fragment
-providerName = Eclipse.org
diff --git a/java/lib/org.eclipse.equinox.launcher_1.0.101.R34x_v20080819.jar b/java/lib/org.eclipse.equinox.launcher_1.0.101.R34x_v20080819.jar
deleted file mode 100644
index 21cc2a6a07..0000000000
--- a/java/lib/org.eclipse.equinox.launcher_1.0.101.R34x_v20080819.jar
+++ /dev/null
Binary files differ
diff --git a/java/lib/org.eclipse.equinox.preferences_3.2.201.R34x_v20080709.jar b/java/lib/org.eclipse.equinox.preferences_3.2.201.R34x_v20080709.jar
deleted file mode 100644
index 0efcea4022..0000000000
--- a/java/lib/org.eclipse.equinox.preferences_3.2.201.R34x_v20080709.jar
+++ /dev/null
Binary files differ
diff --git a/java/lib/org.eclipse.equinox.registry_3.4.0.v20080516-0950.jar b/java/lib/org.eclipse.equinox.registry_3.4.0.v20080516-0950.jar
deleted file mode 100644
index ddc97ffe7c..0000000000
--- a/java/lib/org.eclipse.equinox.registry_3.4.0.v20080516-0950.jar
+++ /dev/null
Binary files differ
diff --git a/java/lib/org.eclipse.help_3.3.101.v20080702_34x.jar b/java/lib/org.eclipse.help_3.3.101.v20080702_34x.jar
deleted file mode 100644
index 8bb2b74a73..0000000000
--- a/java/lib/org.eclipse.help_3.3.101.v20080702_34x.jar
+++ /dev/null
Binary files differ
diff --git a/java/lib/org.eclipse.jface.databinding_1.2.1.M20080827-0800a.jar b/java/lib/org.eclipse.jface.databinding_1.2.1.M20080827-0800a.jar
deleted file mode 100644
index b61037ef9f..0000000000
--- a/java/lib/org.eclipse.jface.databinding_1.2.1.M20080827-0800a.jar
+++ /dev/null
Binary files differ
diff --git a/java/lib/org.eclipse.jface_3.4.1.M20080827-2000.jar b/java/lib/org.eclipse.jface_3.4.1.M20080827-2000.jar
deleted file mode 100644
index ad1c58f0d0..0000000000
--- a/java/lib/org.eclipse.jface_3.4.1.M20080827-2000.jar
+++ /dev/null
Binary files differ
diff --git a/java/lib/org.eclipse.osgi_3.4.2.R34x_v20080826-1230.jar b/java/lib/org.eclipse.osgi_3.4.2.R34x_v20080826-1230.jar
deleted file mode 100644
index 673f3f5932..0000000000
--- a/java/lib/org.eclipse.osgi_3.4.2.R34x_v20080826-1230.jar
+++ /dev/null
Binary files differ
diff --git a/java/lib/org.eclipse.swt.carbon.macosx_3.4.1.v3449c.jar b/java/lib/org.eclipse.swt.carbon.macosx_3.4.1.v3449c.jar
deleted file mode 100644
index d64249df6a..0000000000
--- a/java/lib/org.eclipse.swt.carbon.macosx_3.4.1.v3449c.jar
+++ /dev/null
Binary files differ
diff --git a/java/lib/org.eclipse.swt.gtk.linux.x86_3.4.1.v3449c.jar b/java/lib/org.eclipse.swt.gtk.linux.x86_3.4.1.v3449c.jar
deleted file mode 100644
index cda22da341..0000000000
--- a/java/lib/org.eclipse.swt.gtk.linux.x86_3.4.1.v3449c.jar
+++ /dev/null
Binary files differ
diff --git a/java/lib/org.eclipse.swt.gtk.linux.x86_64_3.4.1.v3449c.jar b/java/lib/org.eclipse.swt.gtk.linux.x86_64_3.4.1.v3449c.jar
deleted file mode 100644
index 95909028d4..0000000000
--- a/java/lib/org.eclipse.swt.gtk.linux.x86_64_3.4.1.v3449c.jar
+++ /dev/null
Binary files differ
diff --git a/java/lib/org.eclipse.swt.gtk.solaris.sparc_3.4.1.v3449c.jar b/java/lib/org.eclipse.swt.gtk.solaris.sparc_3.4.1.v3449c.jar
deleted file mode 100644
index d7143505a4..0000000000
--- a/java/lib/org.eclipse.swt.gtk.solaris.sparc_3.4.1.v3449c.jar
+++ /dev/null
Binary files differ
diff --git a/java/lib/org.eclipse.swt.win32.win32.x86_3.4.1.v3449c.jar b/java/lib/org.eclipse.swt.win32.win32.x86_3.4.1.v3449c.jar
deleted file mode 100644
index 5c261c8411..0000000000
--- a/java/lib/org.eclipse.swt.win32.win32.x86_3.4.1.v3449c.jar
+++ /dev/null
Binary files differ
diff --git a/java/lib/org.eclipse.swt_3.4.1.v3449c.jar b/java/lib/org.eclipse.swt_3.4.1.v3449c.jar
deleted file mode 100644
index 606abc5a3b..0000000000
--- a/java/lib/org.eclipse.swt_3.4.1.v3449c.jar
+++ /dev/null
Binary files differ
diff --git a/java/lib/org.eclipse.ui.forms_3.3.101.v20080708_34x.jar b/java/lib/org.eclipse.ui.forms_3.3.101.v20080708_34x.jar
deleted file mode 100644
index a458fcb058..0000000000
--- a/java/lib/org.eclipse.ui.forms_3.3.101.v20080708_34x.jar
+++ /dev/null
Binary files differ
diff --git a/java/lib/org.eclipse.ui.workbench_3.4.1.M20080827-0800a.jar b/java/lib/org.eclipse.ui.workbench_3.4.1.M20080827-0800a.jar
deleted file mode 100644
index 3e151c8122..0000000000
--- a/java/lib/org.eclipse.ui.workbench_3.4.1.M20080827-0800a.jar
+++ /dev/null
Binary files differ
diff --git a/java/lib/org.eclipse.ui_3.4.1.M20080910-0800.jar b/java/lib/org.eclipse.ui_3.4.1.M20080910-0800.jar
deleted file mode 100644
index c7a8cf4256..0000000000
--- a/java/lib/org.eclipse.ui_3.4.1.M20080910-0800.jar
+++ /dev/null
Binary files differ
diff --git a/java/lib/poms/commons-beanutils-core-1.8.0.xml b/java/lib/poms/commons-beanutils-core-1.8.3.xml
index 612b45e1a6..10d664fca8 100644
--- a/java/lib/poms/commons-beanutils-core-1.8.0.xml
+++ b/java/lib/poms/commons-beanutils-core-1.8.3.xml
@@ -18,5 +18,5 @@
<dep>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils-core</artifactId>
- <version>1.8.0</version>
+ <version>1.8.3</version>
</dep>
diff --git a/java/lib/poms/commons-cli-1.0.xml b/java/lib/poms/commons-cli-1.2.xml
index 77b47f63f1..5b4f0e35d7 100644
--- a/java/lib/poms/commons-cli-1.0.xml
+++ b/java/lib/poms/commons-cli-1.2.xml
@@ -18,5 +18,5 @@
<dep>
<groupId>commons-cli</groupId>
<artifactId>commons-cli</artifactId>
- <version>1.0</version>
+ <version>1.2</version>
</dep>
diff --git a/java/lib/poms/commons-codec-1.3.xml b/java/lib/poms/commons-codec-1.6.xml
index 772ff6ab71..95f6f24aa2 100644
--- a/java/lib/poms/commons-codec-1.3.xml
+++ b/java/lib/poms/commons-codec-1.6.xml
@@ -18,5 +18,5 @@
<dep>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
- <version>1.3</version>
+ <version>1.6</version>
</dep>
diff --git a/java/lib/poms/commons-collections-3.2.xml b/java/lib/poms/commons-collections-3.2.1.xml
index 3a07dc4a9d..85be0c2e6a 100644
--- a/java/lib/poms/commons-collections-3.2.xml
+++ b/java/lib/poms/commons-collections-3.2.1.xml
@@ -18,5 +18,5 @@
<dep>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
- <version>3.2</version>
+ <version>3.2.1</version>
</dep>
diff --git a/java/lib/poms/commons-configuration-1.6.xml b/java/lib/poms/commons-configuration-1.8.xml
index 523310f10a..337b9d0993 100644
--- a/java/lib/poms/commons-configuration-1.6.xml
+++ b/java/lib/poms/commons-configuration-1.8.xml
@@ -18,5 +18,5 @@
<dep>
<groupId>commons-configuration</groupId>
<artifactId>commons-configuration</artifactId>
- <version>1.6</version>
+ <version>1.8</version>
</dep>
diff --git a/java/lib/poms/commons-lang-2.2.xml b/java/lib/poms/commons-lang-2.6.xml
index b0bef7ca04..be092371ce 100644
--- a/java/lib/poms/commons-lang-2.2.xml
+++ b/java/lib/poms/commons-lang-2.6.xml
@@ -18,5 +18,5 @@
<dep>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
- <version>2.2</version>
+ <version>2.6</version>
</dep>
diff --git a/java/lib/poms/commons-logging-1.0.4.xml b/java/lib/poms/commons-logging-1.1.1.xml
index c85d0f7b29..bf14523b24 100644
--- a/java/lib/poms/commons-logging-1.0.4.xml
+++ b/java/lib/poms/commons-logging-1.1.1.xml
@@ -18,5 +18,5 @@
<dep>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
- <version>1.0.4</version>
+ <version>1.1.1</version>
</dep>
diff --git a/java/lib/poms/derby-10.6.1.0.xml b/java/lib/poms/derby-10.8.2.2.xml
index de6a4d79f3..897dddd607 100644
--- a/java/lib/poms/derby-10.6.1.0.xml
+++ b/java/lib/poms/derby-10.8.2.2.xml
@@ -18,5 +18,5 @@
<dep>
<groupId>org.apache.derby</groupId>
<artifactId>derby</artifactId>
- <version>10.6.1.0</version>
+ <version>10.8.2.2</version>
</dep>
diff --git a/java/lib/poms/geronimo-servlet_2.5_spec-1.2.xml b/java/lib/poms/geronimo-servlet_2.5_spec-1.2.xml
new file mode 100644
index 0000000000..11228afcfa
--- /dev/null
+++ b/java/lib/poms/geronimo-servlet_2.5_spec-1.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>org.apache.geronimo.specs</groupId>
+ <artifactId>geronimo-servlet_2.5_spec</artifactId>
+ <version>1.2</version>
+</dep>
diff --git a/java/lib/poms/je-5.0.34.xml b/java/lib/poms/je-5.0.55.xml
index 1e4688019b..0c40ea541a 100644
--- a/java/lib/poms/je-5.0.34.xml
+++ b/java/lib/poms/je-5.0.55.xml
@@ -18,5 +18,5 @@
<dep>
<groupId>com.sleepycat</groupId>
<artifactId>je</artifactId>
- <version>5.0.34</version>
+ <version>5.0.55</version>
</dep>
diff --git a/java/lib/poms/jetty-continuation-7.6.3.v20120416.xml b/java/lib/poms/jetty-continuation-7.6.3.v20120416.xml
new file mode 100644
index 0000000000..6ace17c18a
--- /dev/null
+++ b/java/lib/poms/jetty-continuation-7.6.3.v20120416.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.eclipse.jetty</groupId>
+ <artifactId>jetty-continuation</artifactId>
+ <version>7.6.3.v20120416</version>
+</dep>
diff --git a/java/lib/poms/jetty-http-7.6.3.v20120416.xml b/java/lib/poms/jetty-http-7.6.3.v20120416.xml
new file mode 100644
index 0000000000..02af020cfe
--- /dev/null
+++ b/java/lib/poms/jetty-http-7.6.3.v20120416.xml
@@ -0,0 +1,28 @@
+<?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.eclipse.jetty</groupId>
+ <artifactId>jetty-http</artifactId>
+ <version>7.6.3.v20120416</version>
+ <exclusions>
+ <exclusion>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-io</artifactId>
+ </exclusion>
+ </exclusions>
+</dep>
diff --git a/java/lib/poms/jetty-io-7.6.3.v20120416.xml b/java/lib/poms/jetty-io-7.6.3.v20120416.xml
new file mode 100644
index 0000000000..b6c865f0fb
--- /dev/null
+++ b/java/lib/poms/jetty-io-7.6.3.v20120416.xml
@@ -0,0 +1,28 @@
+<?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.eclipse.jetty</groupId>
+ <artifactId>jetty-io</artifactId>
+ <version>7.6.3.v20120416</version>
+ <exclusions>
+ <exclusion>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-util</artifactId>
+ </exclusion>
+ </exclusions>
+</dep>
diff --git a/java/lib/poms/jetty-security-7.6.3.v20120416.xml b/java/lib/poms/jetty-security-7.6.3.v20120416.xml
new file mode 100644
index 0000000000..ba643ccb97
--- /dev/null
+++ b/java/lib/poms/jetty-security-7.6.3.v20120416.xml
@@ -0,0 +1,28 @@
+<?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.eclipse.jetty</groupId>
+ <artifactId>jetty-security</artifactId>
+ <version>7.6.3.v20120416</version>
+ <exclusions>
+ <exclusion>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-server</artifactId>
+ </exclusion>
+ </exclusions>
+</dep>
diff --git a/java/lib/poms/jetty-server-7.6.3.v20120416.xml b/java/lib/poms/jetty-server-7.6.3.v20120416.xml
new file mode 100644
index 0000000000..1e7ce42623
--- /dev/null
+++ b/java/lib/poms/jetty-server-7.6.3.v20120416.xml
@@ -0,0 +1,36 @@
+<?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.eclipse.jetty</groupId>
+ <artifactId>jetty-server</artifactId>
+ <version>7.6.3.v20120416</version>
+ <exclusions>
+ <exclusion>
+ <groupId>org.eclipse.jetty.orbit</groupId>
+ <artifactId>javax.servlet</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-continuation</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-http</artifactId>
+ </exclusion>
+ </exclusions>
+</dep>
diff --git a/java/lib/poms/jetty-servlet-7.6.3.v20120416.xml b/java/lib/poms/jetty-servlet-7.6.3.v20120416.xml
new file mode 100644
index 0000000000..001bcce824
--- /dev/null
+++ b/java/lib/poms/jetty-servlet-7.6.3.v20120416.xml
@@ -0,0 +1,28 @@
+<?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.eclipse.jetty</groupId>
+ <artifactId>jetty-servlet</artifactId>
+ <version>7.6.3.v20120416</version>
+ <exclusions>
+ <exclusion>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-security</artifactId>
+ </exclusion>
+ </exclusions>
+</dep>
diff --git a/java/lib/poms/jetty-util-7.6.3.v20120416.xml b/java/lib/poms/jetty-util-7.6.3.v20120416.xml
new file mode 100644
index 0000000000..c40d7e5f60
--- /dev/null
+++ b/java/lib/poms/jetty-util-7.6.3.v20120416.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.eclipse.jetty</groupId>
+ <artifactId>jetty-util</artifactId>
+ <version>7.6.3.v20120416</version>
+</dep>
diff --git a/java/lib/poms/jetty-websocket-7.6.3.v20120416.xml b/java/lib/poms/jetty-websocket-7.6.3.v20120416.xml
new file mode 100644
index 0000000000..bba80d9236
--- /dev/null
+++ b/java/lib/poms/jetty-websocket-7.6.3.v20120416.xml
@@ -0,0 +1,36 @@
+<?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.eclipse.jetty</groupId>
+ <artifactId>jetty-websocket</artifactId>
+ <version>7.6.3.v20120416</version>
+ <exclusions>
+ <exclusion>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-util</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-io</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-http</artifactId>
+ </exclusion>
+ </exclusions>
+</dep>
diff --git a/java/lib/poms/log4j-1.2.12.xml b/java/lib/poms/log4j-1.2.16.xml
index 87331f4acc..b60a30d993 100644
--- a/java/lib/poms/log4j-1.2.12.xml
+++ b/java/lib/poms/log4j-1.2.16.xml
@@ -18,5 +18,5 @@
<dep>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
- <version>1.2.12</version>
+ <version>1.2.16</version>
</dep>
diff --git a/java/lib/poms/slf4j-api-1.6.1.xml b/java/lib/poms/slf4j-api-1.6.4.xml
index e3f989bd4e..4eb7c2fe96 100644
--- a/java/lib/poms/slf4j-api-1.6.1.xml
+++ b/java/lib/poms/slf4j-api-1.6.4.xml
@@ -18,5 +18,5 @@
<dep>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
- <version>1.6.1</version>
+ <version>1.6.4</version>
</dep>
diff --git a/java/lib/poms/slf4j-log4j12-1.6.1.xml b/java/lib/poms/slf4j-log4j12-1.6.4.xml
index 482bbec894..516dda9eeb 100644
--- a/java/lib/poms/slf4j-log4j12-1.6.1.xml
+++ b/java/lib/poms/slf4j-log4j12-1.6.4.xml
@@ -18,5 +18,5 @@
<dep>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
- <version>1.6.1</version>
+ <version>1.6.4</version>
</dep>
diff --git a/java/lib/slf4j-api-1.6.1.jar b/java/lib/slf4j-api-1.6.1.jar
deleted file mode 100644
index 42e0ad0de7..0000000000
--- a/java/lib/slf4j-api-1.6.1.jar
+++ /dev/null
Binary files differ
diff --git a/java/lib/slf4j-log4j12-1.6.1.jar b/java/lib/slf4j-log4j12-1.6.1.jar
deleted file mode 100644
index 873d11983e..0000000000
--- a/java/lib/slf4j-log4j12-1.6.1.jar
+++ /dev/null
Binary files differ
diff --git a/java/lib/xalan-2.7.0.jar b/java/lib/xalan-2.7.0.jar
deleted file mode 100644
index 007be3960a..0000000000
--- a/java/lib/xalan-2.7.0.jar
+++ /dev/null
Binary files differ
diff --git a/java/management/common/build.xml b/java/management/common/build.xml
index 1a0520b1e3..2315027b14 100644
--- a/java/management/common/build.xml
+++ b/java/management/common/build.xml
@@ -24,4 +24,5 @@
<property name="module.genpom" value="true"/>
<target name="bundle" depends="bundle-tasks"/>
+
</project>
diff --git a/java/management/common/src/main/java/management-common.bnd b/java/management/common/src/main/java/management-common.bnd
index f42652d1d4..5a6be6bb15 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.17.0
+ver: 0.19.0
Bundle-SymbolicName: qpid-management-common
Bundle-Version: ${ver}
diff --git a/java/management/common/src/main/java/org/apache/qpid/management/common/mbeans/ManagedQueue.java b/java/management/common/src/main/java/org/apache/qpid/management/common/mbeans/ManagedQueue.java
index 254ec01519..b00b28b2a9 100644
--- a/java/management/common/src/main/java/org/apache/qpid/management/common/mbeans/ManagedQueue.java
+++ b/java/management/common/src/main/java/org/apache/qpid/management/common/mbeans/ManagedQueue.java
@@ -63,9 +63,14 @@ public interface ManagedQueue
String ENCODING = "Encoding";
String CONTENT = "Content";
List<String> VIEW_MSG_CONTENT_COMPOSITE_ITEM_NAMES_DESC = Collections.unmodifiableList(Arrays.asList(MSG_AMQ_ID, MIME, ENCODING, CONTENT));
-
+
+ /** Date/time format used for message expiration and message timestamp formatting */
+ String JMSTIMESTAMP_DATETIME_FORMAT = "MM-dd-yy HH:mm:ss.SSS z";
+
//Individual attribute name constants
static final String ATTR_NAME = "Name";
+ static final String ATTR_DESCRIPTION = "Description";
+ static final String ATTR_QUEUE_TYPE = "QueueType";
static final String ATTR_OWNER = "Owner";
static final String ATTR_MAX_MSG_AGE = "MaximumMessageAge";
static final String ATTR_MAX_MSG_COUNT = "MaximumMessageCount";
@@ -92,6 +97,8 @@ public interface ManagedQueue
new HashSet<String>(
Arrays.asList(
ATTR_NAME,
+ ATTR_QUEUE_TYPE,
+ ATTR_DESCRIPTION,
ATTR_OWNER,
ATTR_MAX_MSG_AGE,
ATTR_MAX_MSG_COUNT,
@@ -235,7 +242,7 @@ public interface ManagedQueue
* Tells the maximum number of messages that can be stored in the queue.
* This is useful in setting the notifications or taking required
* action is the number of message increase this limit.
- * @return maximum muber of message allowed to be stored in the queue.
+ * @return maximum nuumber of message allowed to be stored in the queue.
* @throws IOException
*/
Long getMaximumMessageCount() throws IOException;
@@ -287,13 +294,33 @@ public interface ManagedQueue
*/
@MBeanAttribute(name="Capacity", description="The flow control Capacity (Bytes) of the queue")
void setCapacity(Long value) throws IOException, IllegalArgumentException;
+
+ /**
+ * Gets the free text queue description.
+ * @since Qpid JMX API 2.5
+ */
+ String getDescription();
+
+ /**
+ * Sets the free text queue description.
+ * @since Qpid JMX API 2.5
+ */
+ @MBeanAttribute(name="Description", description="Free text description of the queue")
+ void setDescription(String string);
+
+ /**
+ * Gets the queue type
+ * @since Qpid JMX API 2.5
+ */
+ @MBeanAttribute(name="QueueType", description="Type of the queue e.g. standard, priority, etc")
+ String getQueueType();
/**
* Returns the current flow control FlowResumeCapacity of the queue in bytes.
*
* @since Qpid JMX API 1.6
* @return Capacity below which flow resumes in bytes
- * @throws IOException
+ * @throws IOExceptionm
*/
Long getFlowResumeCapacity() throws IOException;
@@ -332,7 +359,7 @@ public interface ManagedQueue
* @since Qpid JMX API 2.0
* @param exclusive the capacity in bytes
* @throws IOException
- * @throws JMException
+ * @throws JMException
*/
@MBeanAttribute(name="Exclusive", description="Whether the queue is Exclusive or not")
void setExclusive(boolean exclusive) throws IOException, JMException;
@@ -341,10 +368,13 @@ public interface ManagedQueue
* Sets the Alternate Exchange for the queue, for use in dead letter queue functionality.
*
* @since Qpid JMX API 2.4
- * @param the name of the exchange to use. Specifying null or the empty string will clear the alternate exchange.
+ * @param exchangeName the name of the exchange to use. Specifying null or the empty string will clear the
+ * alternate exchange.
* @throws IOException
+ * @throws JMException
*/
- void setAlternateExchange(String exchangeName) throws IOException;
+ @MBeanAttribute(name="AlternateExchange", description="Alternate exchange for the queue")
+ void setAlternateExchange(String exchangeName) throws IOException, JMException;
/**
* Returns the name of the Alternate Exchange for the queue, or null if there isn't one.
@@ -353,7 +383,6 @@ public interface ManagedQueue
* @return the name of the Alternate Exchange for the queue, or null if there isn't one
* @throws IOException
*/
- @MBeanAttribute(name="AlternateExchange", description="Alternate exchange for the queue")
String getAlternateExchange() throws IOException;
//********** Operations *****************//
@@ -473,4 +502,5 @@ public interface ManagedQueue
@MBeanOperationParameter(name="to MessageId", description="to MessageId")long toMessageId,
@MBeanOperationParameter(name= ManagedQueue.TYPE, description="to Queue Name")String toQueue)
throws IOException, JMException;
+
}
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 38b89b58c5..1a4715224f 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
@@ -46,7 +46,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 = 4;
+ int QPID_JMX_API_MINOR_VERSION = 5;
/**
diff --git a/java/management/eclipse-plugin/META-INF/MANIFEST.MF b/java/management/eclipse-plugin/META-INF/MANIFEST.MF
deleted file mode 100644
index 097b6ba0a9..0000000000
--- a/java/management/eclipse-plugin/META-INF/MANIFEST.MF
+++ /dev/null
@@ -1,22 +0,0 @@
-Manifest-Version: 1.0
-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.17.0
-Bundle-Activator: org.apache.qpid.management.ui.Activator
-Bundle-Vendor: Apache Software Foundation
-Bundle-Localization: plugin
-Require-Bundle: org.eclipse.ui,
- org.eclipse.core.runtime,
- org.eclipse.ui.forms,
- qpid-management-common,
- org.apache.commons.codec;bundle-version="1.3.0"
-Eclipse-LazyStart: true
-Export-Package: org.apache.qpid.management.ui,
- org.apache.qpid.management.ui.actions,
- org.apache.qpid.management.ui.exceptions,
- org.apache.qpid.management.ui.jmx,
- org.apache.qpid.management.ui.model,
- org.apache.qpid.management.ui.sasl,
- org.apache.qpid.management.ui.views
diff --git a/java/management/eclipse-plugin/build-release-linux-gtk-x86.properties b/java/management/eclipse-plugin/build-release-linux-gtk-x86.properties
deleted file mode 100644
index 51c4bfa8d0..0000000000
--- a/java/management/eclipse-plugin/build-release-linux-gtk-x86.properties
+++ /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.
-#
-#
-
-release.name=${project.name}-${app.namever}-linux-gtk-x86
-
-release.subdir=${module.release.base}/${release.name}
-
-release.tar.gz=${module.release.base}/${release.name}.tar.gz
-
-qpidmc.ini=src/main/resources/linux-gtk-x86/qpidmc.ini
-
-qpidmc.executable=src/main/resources/linux-gtk-x86/qpidmc
-
-qpidmc.companion.library=src/main/resources/linux-gtk-x86/libcairo-swt.so
-
-rcp.libs=${management-eclipse-plugin-linux-gtk-x86.libs}
-
-rcp.configuration.dir=src/main/resources/linux-gtk-x86/Configuration
diff --git a/java/management/eclipse-plugin/build-release-linux-gtk-x86_64.properties b/java/management/eclipse-plugin/build-release-linux-gtk-x86_64.properties
deleted file mode 100644
index bf58d9c08e..0000000000
--- a/java/management/eclipse-plugin/build-release-linux-gtk-x86_64.properties
+++ /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.
-#
-#
-
-release.name=${project.name}-${app.namever}-linux-gtk-x86_64
-
-release.subdir=${module.release.base}/${release.name}
-
-release.tar.gz=${module.release.base}/${release.name}.tar.gz
-
-qpidmc.ini=src/main/resources/linux-gtk-x86_64/qpidmc.ini
-
-qpidmc.executable=src/main/resources/linux-gtk-x86_64/qpidmc
-
-qpidmc.companion.library=src/main/resources/linux-gtk-x86_64/libcairo-swt.so
-
-rcp.libs=${management-eclipse-plugin-linux-gtk-x86_64.libs}
-
-rcp.configuration.dir=src/main/resources/linux-gtk-x86_64/Configuration
diff --git a/java/management/eclipse-plugin/build-release-macosx.properties b/java/management/eclipse-plugin/build-release-macosx.properties
deleted file mode 100644
index bdb2f0d7da..0000000000
--- a/java/management/eclipse-plugin/build-release-macosx.properties
+++ /dev/null
@@ -1,40 +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.
-#
-#
-
-application.name=Qpid JMX Management Console
-
-application.dir=${application.name}.app
-
-release.name=${project.name}-${app.namever}-macosx
-
-release.subdir=${module.release.base}/${release.name}
-
-release.zip=${module.release.base}/${release.name}.zip
-
-rcp.libs=${management-eclipse-plugin-macosx.libs}
-
-rcp.configuration.dir=src/main/resources/macosx/Configuration
-
-qpidmc.ini=src/main/resources/macosx/Contents/MacOS/qpidmc.ini
-qpidmc.executable=src/main/resources/macosx/Contents/MacOS/qpidmc
-
-eclipse.icns=src/main/resources/macosx/Contents/Resources/Console.icns
-macosx.plist=src/main/resources/macosx/Contents/Info.plist
diff --git a/java/management/eclipse-plugin/build-release-macosx.xml b/java/management/eclipse-plugin/build-release-macosx.xml
deleted file mode 100644
index 2aa63d7f2f..0000000000
--- a/java/management/eclipse-plugin/build-release-macosx.xml
+++ /dev/null
@@ -1,101 +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="JMX Management Console MacOSX Binary Release" default="release-bin">
-
- <import file="build-release.xml"/>
-
- <property name="release.app" value="${release.subdir}/${application.dir}"/>
-
- <target name="release-bin-qpid-mc-plugin">
- <available file="${build.lib}/qpid-management-eclipse-plugin-${project.version}.jar" property="management-eclipse-plugin.jar.present"/>
- <fail unless="management-eclipse-plugin.jar.present" message="Please run ant build for the management-eclipse-plugin module"/>
-
- <!-- Copy the qpid management-eclipse-plugin module jar -->
- <copy tofile="${release.app}/plugins/${mcplugin.filename}.jar" flatten="true" failonerror="true">
- <fileset file="${build.lib}/qpid-management-eclipse-plugin-${project.version}.jar"/>
- </copy>
- </target>
-
- <target name="release-bin-jmxremote-plugin">
- <!-- Copy the jmxremote.sasl plugin's manifest, creating its plugin directory -->
- <copy todir="${release.app}/plugins/jmxremote.sasl_1.0.1/META-INF" flatten="true" failonerror="true">
- <fileset file="${jmxremote.sasl.manifest}"/>
- </copy>
- </target>
-
- <target name="release-bin-qpid-management-common-plugin">
- <available file="${build.lib}/qpid-management-common_${project.version}.0.osgi.jar" property="management-common.jar.present"/>
- <fail unless="management-common.jar.present" message="Please run ant bundle for the management-common module"/>
-
- <!-- Copy the qpid-management-common module osgi jar -->
- <copy todir="${release.app}/plugins" flatten="true" failonerror="true">
- <fileset file="${build.lib}/qpid-management-common_${project.version}.0.osgi.jar"/>
- </copy>
- </target>
-
-
- <target name="release-bin-rcp-deps" description="copy eclipse-rcp dependencies into module release">
-
- <!-- Copy Eclipse binary and start-up files -->
- <copy todir="${release.app}/Contents/MacOS" flatten="true" failonerror="true">
- <fileset file="${qpidmc.ini}"/>
- <fileset file="${qpidmc.executable}"/>
- </copy>
-
- <chmod dir="${release.app}/Contents/MacOS" perm="u+rx" includes="**/*"/>
-
- <!-- Copy MacOS plist file -->
- <copy todir="${release.app}/Contents" flatten="true" failonerror="true">
- <fileset file="${macosx.plist}"/>
- </copy>
-
- <!-- Copy Icns icon file -->
- <copy todir="${release.app}/Contents/Resources" flatten="true" failonerror="true">
- <fileset file="${eclipse.icns}"/>
- </copy>
-
- <!-- Copy the eclipse rcp module libs -->
- <copy todir="${release.app}/plugins" failonerror="true">
- <fileset dir="${project.root}" includes="${rcp.libs}"/>
- <globmapper from="lib${file.separator}*" to="*"/>
- </copy>
-
- <!-- Copy the relevant configuration dir -->
- <copy todir="${release.app}/Configuration" failonerror="true">
- <fileset dir="${rcp.configuration.dir}"/>
- </copy>
- <chmod dir="${release.app}/Configuration" perm="ugo+r" includes="**/*"/>
- </target>
-
- <target name="release-bin-zip" if="release.zip" description="build mc zip archive">
-
- <zip destfile="${release.zip}">
- <zipfileset dir="${release.subdir}" filemode="755">
- <include name="${application.dir}/Contents/MacOS/**"/>
- </zipfileset>
-
- <zipfileset dir="${release.subdir}" filemode="644" dirmode="755">
- <exclude name="${application.dir}/Contents/MacOS/**"/>
- </zipfileset>
- </zip>
- </target>
-
-</project>
diff --git a/java/management/eclipse-plugin/build-release-solaris-gtk-sparc.properties b/java/management/eclipse-plugin/build-release-solaris-gtk-sparc.properties
deleted file mode 100644
index d58d0c9ac0..0000000000
--- a/java/management/eclipse-plugin/build-release-solaris-gtk-sparc.properties
+++ /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.
-#
-#
-
-release.name=${project.name}-${app.namever}-solaris-gtk-sparc
-
-release.subdir=${module.release.base}/${release.name}
-
-release.tar.gz=${module.release.base}/${release.name}.tar.gz
-
-qpidmc.ini=src/main/resources/solaris-gtk-sparc/qpidmc.ini
-
-qpidmc.solaris.xpm.files=src/main/resources/solaris-gtk-sparc/Qpidmc.l.pm \
- src/main/resources/solaris-gtk-sparc/Qpidmc.m.pm \
- src/main/resources/solaris-gtk-sparc/Qpidmc.s.pm \
- src/main/resources/solaris-gtk-sparc/Qpidmc.t.pm
-
-qpidmc.executable=src/main/resources/solaris-gtk-sparc/qpidmc
-
-rcp.libs=${management-eclipse-plugin-solaris-gtk-sparc.libs}
-
-rcp.configuration.dir=src/main/resources/solaris-gtk-sparc/Configuration
diff --git a/java/management/eclipse-plugin/build-release-win32-win32-x86.properties b/java/management/eclipse-plugin/build-release-win32-win32-x86.properties
deleted file mode 100644
index ee678a92c9..0000000000
--- a/java/management/eclipse-plugin/build-release-win32-win32-x86.properties
+++ /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.
-#
-#
-
-release.name=${project.name}-${app.namever}-win32-win32-x86
-
-release.subdir=${module.release.base}/${release.name}
-
-release.zip=${module.release.base}/${release.name}.zip
-
-qpidmc.executable=src/main/resources/win32-win32-x86/qpidmc.exe
-
-qpidmc.ini=src/main/resources/win32-win32-x86/qpidmc.ini
-
-rcp.libs=${management-eclipse-plugin-win32-win32-x86.libs}
-
-rcp.configuration.dir=src/main/resources/win32-win32-x86/Configuration
diff --git a/java/management/eclipse-plugin/build-release.xml b/java/management/eclipse-plugin/build-release.xml
deleted file mode 100644
index dec4cd5f32..0000000000
--- a/java/management/eclipse-plugin/build-release.xml
+++ /dev/null
@@ -1,172 +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="JMX Management Console Binary Release" default="release-bin">
-
- <!-- check properties that must be set by caller -->
- <target name="check" description="ensure all required properties are set">
- <condition property="properties.set">
- <and>
- <!-- common properties -->
- <isset property ="mcplugin.filename"/>
- <isset property ="jmxremote.sasl.manifest"/>
- <!-- platform specific properties -->
- <isset property ="qpidmc.ini"/>
- <isset property ="qpidmc.executable"/>
- <isset property ="release.name"/>
- <isset property ="release.subdir"/>
- <isset property ="rcp.libs"/>
- <isset property ="rcp.configuration.dir"/>
- <or>
- <isset property ="release.zip"/>
- <isset property ="release.tar.gz"/>
- </or>
- </and>
- <!-- Optional Properties:
-
- For linux libcairo-swt.so file:
- qpidmc.companion.library
-
- For solaris .xpm files:
- qpidmc.solaris.xpm.files
-
- -->
- </condition>
-
- <fail unless="properties.set" message="some required properties were not set"/>
- </target>
-
- <target name="release-bin-prepare">
- <mkdir dir="${release.subdir}"/>
- </target>
-
- <target name="release-bin-qpid-mc-plugin">
- <available file="${build.lib}/qpid-management-eclipse-plugin-${project.version}.jar" property="management-eclipse-plugin.jar.present"/>
- <fail unless="management-eclipse-plugin.jar.present" message="Please run ant build for the management-eclipse-plugin module"/>
-
- <!-- Copy the qpid management-eclipse-plugin module jar -->
- <copy tofile="${release.subdir}/plugins/${mcplugin.filename}.jar" flatten="true" failonerror="true">
- <fileset file="${build.lib}/qpid-management-eclipse-plugin-${project.version}.jar"/>
- </copy>
- </target>
-
- <target name="release-bin-jmxremote-plugin">
- <!-- Copy the jmxremote.sasl plugin's manifest, creating its plugin directory -->
- <copy todir="${release.subdir}/plugins/jmxremote.sasl_1.0.1/META-INF" flatten="true" failonerror="true">
- <fileset file="${jmxremote.sasl.manifest}"/>
- </copy>
- </target>
-
- <target name="release-bin-qpid-management-common-plugin">
- <available file="${build.lib}/qpid-management-common_${project.version}.0.osgi.jar" property="management-common.jar.present"/>
- <fail unless="management-common.jar.present" message="Please run ant bundle for the management-common module"/>
-
- <!-- Copy the qpid-management-common module osgi jar -->
- <copy todir="${release.subdir}/plugins" failonerror="true">
- <fileset file="${build.lib}/qpid-management-common_${project.version}.0.osgi.jar"/>
- </copy>
- </target>
-
- <target name="release-bin-executable-companion-library" if="qpidmc.companion.library">
- <!-- Copy the rcp executable companion library file -->
- <copy todir="${release.subdir}" flatten="true" failonerror="true">
- <fileset file="${qpidmc.companion.library}"/>
- </copy>
- </target>
-
- <target name="release-bin-executable-solaris-xpm-files" if="qpidmc.solaris.xpm.files">
- <!-- Copy the solaris xpm files -->
- <copy todir="${release.subdir}" flatten="true" failonerror="true">
- <fileset dir="${basedir}" includes="${qpidmc.solaris.xpm.files}"/>
- </copy>
- </target>
-
- <target name="release-bin-rcp-deps" description="copy eclipse-rcp dependencies into module release"
- depends="release-bin-executable-companion-library, release-bin-executable-solaris-xpm-files">
-
- <!-- Copy the rcp executable file -->
- <copy todir="${release.subdir}" flatten="true" failonerror="true">
- <fileset file="${qpidmc.executable}"/>
- </copy>
- <chmod dir="${release.subdir}" perm="u+rx" includes="qpidmc*"/>
-
- <!-- Copy remaining startup & license files -->
- <copy todir="${release.subdir}" flatten="true" failonerror="true">
- <fileset file="${qpidmc.ini}"/>
- </copy>
-
- <!-- Copy the rcp module libs -->
- <copy todir="${release.subdir}/plugins" failonerror="true">
- <fileset dir="${project.root}" includes="${rcp.libs}"/>
- <globmapper from="lib${file.separator}*" to="*"/>
- </copy>
-
- <!-- Copy the relevant configuration dir -->
- <copy todir="${release.subdir}/configuration" failonerror="true">
- <fileset dir="${rcp.configuration.dir}"/>
- </copy>
- <chmod dir="${release.subdir}/configuration" perm="ugo+r" includes="**/*"/>
- </target>
-
- <target name="release-bin-zip" if="release.zip" description="build mc zip archive">
- <zip destfile="${release.zip}">
- <zipfileset dir="${release.subdir}" prefix="${release.name}" filemode="755">
- <include name="qpidmc*"/>
- <exclude name="qpidmc.ini"/>
- </zipfileset>
-
- <zipfileset dir="${release.subdir}" prefix="${release.name}" filemode="644">
- <include name="qpidmc.ini"/>
- </zipfileset>
-
- <zipfileset dir="${release.subdir}" prefix="${release.name}" filemode="644" dirmode="755">
- <exclude name="qpidmc*"/>
- </zipfileset>
- </zip>
- </target>
-
- <target name="release-bin-gzip" if="release.tar.gz" description="build mc tar.gz archive">
- <tar destfile="${release.tar.gz}" longfile="gnu" compression="gzip">
- <tarfileset dir="${release.subdir}" prefix="${release.name}" filemode="755">
- <include name="qpidmc*"/>
- <exclude name="qpidmc.ini"/>
- </tarfileset>
-
- <tarfileset dir="${release.subdir}" prefix="${release.name}" filemode="644">
- <include name="qpidmc.ini"/>
- </tarfileset>
-
- <tarfileset dir="${release.subdir}" prefix="${release.name}" filemode="644" dirmode="755">
- <exclude name="qpidmc*"/>
- </tarfileset>
- </tar>
- </target>
-
- <target name="release-bin-resources" description="copy project resources into module release">
- <copy todir="${release.subdir}" failonerror="false" flatten="true">
- <fileset dir="${resources}" excludes="META-INF"/>
- </copy>
- </target>
-
- <!-- override imported module.xml release-bin target -->
- <target name="release-bin" depends="check,release-bin-prepare,release-bin-rcp-deps,release-bin-resources,
- release-bin-qpid-mc-plugin,release-bin-qpid-management-common-plugin,release-bin-jmxremote-plugin,release-bin-zip,release-bin-gzip"/>
-
-</project>
diff --git a/java/management/eclipse-plugin/build.xml b/java/management/eclipse-plugin/build.xml
deleted file mode 100644
index 527fc1cd09..0000000000
--- a/java/management/eclipse-plugin/build.xml
+++ /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.
- -
- -->
-<project name="Eclipse Plugin" default="build">
-
- <property name="module.depends" value="broker common management/common"/>
- <property name="module.test.depends" value="broker/test common/test" />
-
- <import file="../../module.xml"/>
-
- <!-- module.manifest property to invoke use of 'jar.manifest' jar target when building -->
- <property name="module.manifest" value="${module.classes}/META-INF/MANIFEST.MF"/>
-
- <!-- override module.xml 'libs' target, avoids cluttering the 'build/lib' dir as the
- MC build/packaging process does not use the libs from there -->
- <target name="libs"/>
-
- <target name="copy-plugin-files" description="copy eclipse management plugin files into build tree">
- <copy todir="${module.classes}/icons" failonerror="true">
- <fileset dir="icons/"/>
- </copy>
- <copy todir="${module.classes}/META-INF/" failonerror="true">
- <fileset dir="META-INF/"/>
- </copy>
- <copy todir="${module.classes}" failonerror="true">
- <fileset file="icons/splash.bmp"/>
- </copy>
- <copy todir="${module.classes}" failonerror="true">
- <fileset file="plugin.properties"/>
- </copy>
- <copy todir="${module.classes}" failonerror="true">
- <fileset file="plugin.xml"/>
- </copy>
- </target>
-
- <target name="precompile" depends="copy-plugin-files, create-version" />
-
- <!-- Override imported module.xml release-bin target -->
- <target name="release-bin" depends="build">
- <!-- linux gtk x86 -->
- <ant antfile="build-release.xml">
- <property file="build-release-common.properties"/>
- <property file="build-release-linux-gtk-x86.properties"/>
- </ant>
-
- <!-- linux gtk x86_64 -->
- <ant antfile="build-release.xml">
- <property file="build-release-common.properties"/>
- <property file="build-release-linux-gtk-x86_64.properties"/>
- </ant>
-
- <!-- solaris gtk sparc -->
- <ant antfile="build-release.xml">
- <property file="build-release-common.properties"/>
- <property file="build-release-solaris-gtk-sparc.properties"/>
- </ant>
-
- <!-- mac os x -->
- <ant antfile="build-release-macosx.xml">
- <property file="build-release-common.properties"/>
- <property file="build-release-macosx.properties"/>
- </ant>
-
- <!-- win32 win32 x86 -->
- <ant antfile="build-release.xml">
- <property file="build-release-common.properties"/>
- <property file="build-release-win32-win32-x86.properties"/>
- </ant>
- </target>
-
-</project>
diff --git a/java/management/eclipse-plugin/icons/add.gif b/java/management/eclipse-plugin/icons/add.gif
deleted file mode 100644
index 252d7ebcb8..0000000000
--- a/java/management/eclipse-plugin/icons/add.gif
+++ /dev/null
Binary files differ
diff --git a/java/management/eclipse-plugin/icons/back.gif b/java/management/eclipse-plugin/icons/back.gif
deleted file mode 100644
index d3a10077a5..0000000000
--- a/java/management/eclipse-plugin/icons/back.gif
+++ /dev/null
Binary files differ
diff --git a/java/management/eclipse-plugin/icons/configuration_management.gif b/java/management/eclipse-plugin/icons/configuration_management.gif
deleted file mode 100644
index d11c996e57..0000000000
--- a/java/management/eclipse-plugin/icons/configuration_management.gif
+++ /dev/null
Binary files differ
diff --git a/java/management/eclipse-plugin/icons/delete.gif b/java/management/eclipse-plugin/icons/delete.gif
deleted file mode 100644
index 6f647666d3..0000000000
--- a/java/management/eclipse-plugin/icons/delete.gif
+++ /dev/null
Binary files differ
diff --git a/java/management/eclipse-plugin/icons/failure.gif b/java/management/eclipse-plugin/icons/failure.gif
deleted file mode 100644
index 9b048d6053..0000000000
--- a/java/management/eclipse-plugin/icons/failure.gif
+++ /dev/null
Binary files differ
diff --git a/java/management/eclipse-plugin/icons/icon_ClosedFolder.gif b/java/management/eclipse-plugin/icons/icon_ClosedFolder.gif
deleted file mode 100644
index beb6ed134c..0000000000
--- a/java/management/eclipse-plugin/icons/icon_ClosedFolder.gif
+++ /dev/null
Binary files differ
diff --git a/java/management/eclipse-plugin/icons/icon_OpenFolder.gif b/java/management/eclipse-plugin/icons/icon_OpenFolder.gif
deleted file mode 100644
index a9c777343c..0000000000
--- a/java/management/eclipse-plugin/icons/icon_OpenFolder.gif
+++ /dev/null
Binary files differ
diff --git a/java/management/eclipse-plugin/icons/logging_management.gif b/java/management/eclipse-plugin/icons/logging_management.gif
deleted file mode 100644
index 7f5fe98a73..0000000000
--- a/java/management/eclipse-plugin/icons/logging_management.gif
+++ /dev/null
Binary files differ
diff --git a/java/management/eclipse-plugin/icons/mbean_view.png b/java/management/eclipse-plugin/icons/mbean_view.png
deleted file mode 100644
index 9871b72bb8..0000000000
--- a/java/management/eclipse-plugin/icons/mbean_view.png
+++ /dev/null
Binary files differ
diff --git a/java/management/eclipse-plugin/icons/notifications.gif b/java/management/eclipse-plugin/icons/notifications.gif
deleted file mode 100644
index f1e585bdf7..0000000000
--- a/java/management/eclipse-plugin/icons/notifications.gif
+++ /dev/null
Binary files differ
diff --git a/java/management/eclipse-plugin/icons/qpidConnections.gif b/java/management/eclipse-plugin/icons/qpidConnections.gif
deleted file mode 100644
index 17f927e9a4..0000000000
--- a/java/management/eclipse-plugin/icons/qpidConnections.gif
+++ /dev/null
Binary files differ
diff --git a/java/management/eclipse-plugin/icons/qpidmc.gif b/java/management/eclipse-plugin/icons/qpidmc.gif
deleted file mode 100644
index baf929fbc5..0000000000
--- a/java/management/eclipse-plugin/icons/qpidmc.gif
+++ /dev/null
Binary files differ
diff --git a/java/management/eclipse-plugin/icons/qpidmc16.gif b/java/management/eclipse-plugin/icons/qpidmc16.gif
deleted file mode 100644
index 4df535bb9a..0000000000
--- a/java/management/eclipse-plugin/icons/qpidmc16.gif
+++ /dev/null
Binary files differ
diff --git a/java/management/eclipse-plugin/icons/qpidmc32.bmp b/java/management/eclipse-plugin/icons/qpidmc32.bmp
deleted file mode 100644
index e42ce01dff..0000000000
--- a/java/management/eclipse-plugin/icons/qpidmc32.bmp
+++ /dev/null
Binary files differ
diff --git a/java/management/eclipse-plugin/icons/qpidmc32.gif b/java/management/eclipse-plugin/icons/qpidmc32.gif
deleted file mode 100644
index e42ce01dff..0000000000
--- a/java/management/eclipse-plugin/icons/qpidmc32.gif
+++ /dev/null
Binary files differ
diff --git a/java/management/eclipse-plugin/icons/reconnect.gif b/java/management/eclipse-plugin/icons/reconnect.gif
deleted file mode 100644
index e2f8c3e1fe..0000000000
--- a/java/management/eclipse-plugin/icons/reconnect.gif
+++ /dev/null
Binary files differ
diff --git a/java/management/eclipse-plugin/icons/refresh.gif b/java/management/eclipse-plugin/icons/refresh.gif
deleted file mode 100644
index 1b724a6784..0000000000
--- a/java/management/eclipse-plugin/icons/refresh.gif
+++ /dev/null
Binary files differ
diff --git a/java/management/eclipse-plugin/icons/server_information.gif b/java/management/eclipse-plugin/icons/server_information.gif
deleted file mode 100644
index 716df436f9..0000000000
--- a/java/management/eclipse-plugin/icons/server_information.gif
+++ /dev/null
Binary files differ
diff --git a/java/management/eclipse-plugin/icons/splash.bmp b/java/management/eclipse-plugin/icons/splash.bmp
deleted file mode 100644
index cf3b93d523..0000000000
--- a/java/management/eclipse-plugin/icons/splash.bmp
+++ /dev/null
Binary files differ
diff --git a/java/management/eclipse-plugin/icons/stop.gif b/java/management/eclipse-plugin/icons/stop.gif
deleted file mode 100644
index dc47edf069..0000000000
--- a/java/management/eclipse-plugin/icons/stop.gif
+++ /dev/null
Binary files differ
diff --git a/java/management/eclipse-plugin/icons/success.gif b/java/management/eclipse-plugin/icons/success.gif
deleted file mode 100644
index 9cacb96dca..0000000000
--- a/java/management/eclipse-plugin/icons/success.gif
+++ /dev/null
Binary files differ
diff --git a/java/management/eclipse-plugin/icons/user_management.gif b/java/management/eclipse-plugin/icons/user_management.gif
deleted file mode 100644
index d28c326dea..0000000000
--- a/java/management/eclipse-plugin/icons/user_management.gif
+++ /dev/null
Binary files differ
diff --git a/java/management/eclipse-plugin/icons/virtualhost_manager.gif b/java/management/eclipse-plugin/icons/virtualhost_manager.gif
deleted file mode 100644
index e7ec2a1544..0000000000
--- a/java/management/eclipse-plugin/icons/virtualhost_manager.gif
+++ /dev/null
Binary files differ
diff --git a/java/management/eclipse-plugin/plugin.properties b/java/management/eclipse-plugin/plugin.properties
deleted file mode 100644
index 8507441886..0000000000
--- a/java/management/eclipse-plugin/plugin.properties
+++ /dev/null
@@ -1,20 +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.
-###############################################################################
-pluginName = Qpid Management Console Plug-in
-providerName = Apache Software Foundation \ No newline at end of file
diff --git a/java/management/eclipse-plugin/plugin.xml b/java/management/eclipse-plugin/plugin.xml
deleted file mode 100644
index e151456fa1..0000000000
--- a/java/management/eclipse-plugin/plugin.xml
+++ /dev/null
@@ -1,225 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<?eclipse version="3.2"?>
-<!--
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
--->
-<plugin>
-
- <extension
- id="application"
- point="org.eclipse.core.runtime.applications">
- <application>
- <run
- class="org.apache.qpid.management.ui.Application">
- </run>
- </application>
- </extension>
- <extension
- point="org.eclipse.ui.perspectives">
- <perspective
- name="Qpid Management"
- icon="icons/mbean_view.png"
- class="org.apache.qpid.management.ui.Perspective"
- id="org.apache.qpid.management.ui.perspective">
- </perspective>
- </extension>
- <extension
- point="org.eclipse.ui.views">
- <category
- id="org.apache.qpid.management.ui.viewcategory"
- name="Qpid Management Console"/>
- <view
- allowMultiple="false"
- category="org.apache.qpid.management.ui.viewcategory"
- class="org.apache.qpid.management.ui.views.NavigationView"
- icon="icons/qpidConnections.gif"
- id="org.apache.qpid.management.ui.navigationView"
- name="Qpid Connections">
- </view>
- <view
- allowMultiple="false"
- category="org.apache.qpid.management.ui.viewcategory"
- class="org.apache.qpid.management.ui.views.MBeanView"
- icon="icons/mbean_view.png"
- id="org.apache.qpid.management.ui.mbeanView"
- name="Qpid Management">
- </view>
- </extension>
- <extension
- point="org.eclipse.ui.commands">
- <category
- name="qpid.manager.commands"
- id="org.apache.qpid.management.ui.category">
- </category>
- <command
- name="New Connection"
- description="Created a new Qpid server connection"
- categoryId="org.apache.qpid.management.ui.category"
- id="org.apache.qpid.management.ui.actions.cmd_add">
- </command>
- <command
- categoryId="org.apache.qpid.management.ui.category"
- description="Reconnect the Qpid server connection"
- id="org.apache.qpid.management.ui.actions.cmd_reconnect"
- name="Reconnect"/>
- <command
- categoryId="org.apache.qpid.management.ui.category"
- description="Disconnects the Qpid server connection"
- id="org.apache.qpid.management.ui.actions.cmd_disconnect"
- name="Disconnect"/>
- <command
- categoryId="org.apache.qpid.management.ui.category"
- description="Removes the server from management console"
- id="org.apache.qpid.management.ui.actions.cmd_remove"
- name="Remove Connection"/>
- <command
- categoryId="org.apache.qpid.management.ui.category"
- description="refreshes the views"
- id="org.apache.qpid.management.ui.actions.cmd_refresh"
- name="Refresh"/>
- <command
- categoryId="org.apache.qpid.management.ui.category"
- description="About Qpid Management Console"
- id="qpidmc.about"
- name="About"/>
- </extension>
- <extension
- point="org.eclipse.ui.bindings">
- <key
- commandId="org.apache.qpid.management.ui.actions.cmd_add"
- schemeId="org.eclipse.ui.defaultAcceleratorConfiguration"
- sequence="CTRL+Alt+N">
- </key>
- <key
- commandId="org.apache.qpid.management.ui.actions.cmd_reconnect"
- schemeId="org.eclipse.ui.defaultAcceleratorConfiguration"
- sequence="CTRL+Alt+C"/>
- <key
- commandId="org.apache.qpid.management.ui.actions.cmd_disconnect"
- schemeId="org.eclipse.ui.defaultAcceleratorConfiguration"
- sequence="CTRL+Alt+D">
- </key>
- <key
- commandId="org.apache.qpid.management.ui.actions.cmd_remove"
- schemeId="org.eclipse.ui.defaultAcceleratorConfiguration"
- sequence="CTRL+Alt+R"/>
- <key
- commandId="org.apache.qpid.management.ui.actions.cmd_refresh"
- schemeId="org.eclipse.ui.defaultAcceleratorConfiguration"
- sequence="CTRL+Alt+F5"/>
- <key
- commandId="org.eclipse.ui.file.exit"
- schemeId="org.eclipse.ui.defaultAcceleratorConfiguration"
- sequence="CTRL+Alt+X">
- </key>
- </extension>
-
- <extension
- id="product"
- point="org.eclipse.core.runtime.products">
- <product
- application="org.apache.qpid.management.ui.application"
- name="Qpid Management Console">
- <property
- name="windowImages"
- value="icons/qpidmc16.gif,icons/qpidmc32.gif">
- </property>
- <property
- name="aboutText"
- value="Qpid Management Console"/>
- </product>
- </extension>
-
- <extension point="org.eclipse.ui.menus">
- <menuContribution locationURI="toolbar:org.eclipse.ui.main.toolbar?after=additions">
- <toolbar id="qpidMC">
- <separator name="qpidActionsGroup" visible="false"/>
- <separator name="refresh" visible="true"/>
- <separator name="refresh2" visible="false"/>
- <separator name="additions" visible="false"/>
- </toolbar>
- </menuContribution>
- <menuContribution locationURI="toolbar:qpidMC?after=refresh">
- <control
- class="org.apache.qpid.management.ui.RefreshIntervalComboPanel">
- </control>
- </menuContribution>
- </extension>
-
- <extension
- point="org.eclipse.ui.actionSets">
- <actionSet
- id="org.apache.qpid.management.ui.actionSet"
- label="Qpid Action Set"
- visible="true">
- <menu
- id="qpidmanager"
- label="&amp;Qpid Manager">
- <separator name="qpidActionsGroup"/>
- </menu>
- <action
- class="org.apache.qpid.management.ui.actions.Refresh"
- definitionId="org.apache.qpid.management.ui.actions.cmd_refresh"
- icon="icons/refresh.gif"
- id="org.apache.qpid.management.ui.actions.refresh"
- label="Refresh"
- menubarPath="qpidmanager/additions"
- style="push"
- toolbarPath="qpidMC/refresh2"
- tooltip="Refresh Now"/>
- <action
- class="org.apache.qpid.management.ui.actions.RemoveServer"
- definitionId="org.apache.qpid.management.ui.actions.cmd_remove"
- icon="icons/delete.gif"
- id="org.apache.qpid.management.ui.actions.remove"
- label="Remove Connection"
- menubarPath="qpidmanager/additions"
- style="push"
- toolbarPath="qpidMC/qpidActionsGroup"
- tooltip="Remove Server"/>
- <action
- class="org.apache.qpid.management.ui.actions.CloseConnection"
- definitionId="org.apache.qpid.management.ui.actions.cmd_disconnect"
- icon="icons/stop.gif"
- id="org.apache.qpid.management.ui.disconnect"
- label="Disconnect"
- menubarPath="qpidmanager/additions"
- toolbarPath="qpidMC/qpidActionsGroup"
- tooltip="Disconnect"/>
- <action
- class="org.apache.qpid.management.ui.actions.ReconnectServer"
- definitionId="org.apache.qpid.management.ui.actions.cmd_reconnect"
- icon="icons/reconnect.gif"
- id="org.apache.qpid.management.ui.reconnect"
- label="Reconnect"
- menubarPath="qpidmanager/additions"
- toolbarPath="qpidMC/qpidActionsGroup"
- tooltip="Reconnect"/>
- <action
- class="org.apache.qpid.management.ui.actions.AddServer"
- definitionId="org.apache.qpid.management.ui.actions.cmd_add"
- icon="icons/add.gif"
- id="org.apache.qpid.management.ui.add"
- label="New Connection"
- menubarPath="qpidmanager/additions"
- toolbarPath="qpidMC/qpidActionsGroup"
- tooltip="New Connection"/>
- </actionSet>
- </extension>
-
-</plugin>
diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/Activator.java b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/Activator.java
deleted file mode 100644
index d6a9c0b0c6..0000000000
--- a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/Activator.java
+++ /dev/null
@@ -1,83 +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;
-
-import org.eclipse.jface.resource.ImageDescriptor;
-import org.eclipse.ui.plugin.AbstractUIPlugin;
-import org.osgi.framework.BundleContext;
-
-/**
- * The activator class controls the plug-in life cycle
- * @author Bhupendra Bhardwaj
- */
-public class Activator extends AbstractUIPlugin
-{
- // The plug-in ID
- public static final String PLUGIN_ID = "org.apache.qpid.management.ui";
-
- // The shared instance
- private static final Activator PLUGIN = new Activator();
-
- /**
- * The constructor
- */
- public Activator()
- {
-
- }
-
- /*
- * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext)
- */
- public void start(BundleContext context) throws Exception
- {
- super.start(context);
- }
-
- /*
- * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext)
- */
- public void stop(BundleContext context) throws Exception
- {
- super.stop(context);
- }
-
- /**
- * Returns the shared instance
- *
- * @return the shared instance
- */
- public static Activator getDefault()
- {
- return PLUGIN;
- }
-
- /**
- * Returns an image descriptor for the image file at the given plug-in relative path
- *
- * @param path the path
- * @return the image descriptor
- */
- public static ImageDescriptor getImageDescriptor(String path)
- {
- return imageDescriptorFromPlugin(PLUGIN_ID, path);
- }
-}
diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ApiVersion.java b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ApiVersion.java
deleted file mode 100644
index 2bdcd77f08..0000000000
--- a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ApiVersion.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.ui;
-
-public class ApiVersion
-{
- private int major;
- private int minor;
-
- public ApiVersion(int major, int minor)
- {
- this.major = major;
- this.minor = minor;
- }
-
- public int getMajor()
- {
- return major;
- }
-
- public int getMinor()
- {
- return minor;
- }
-
- public boolean greaterThanOrEqualTo(int major, int minor)
- {
- if((this.major == major) && (this.minor >= minor))
- {
- return true;
- }
- else if (this.major > major)
- {
- return true;
- }
-
- return false;
- }
-
- public boolean lessThanOrEqualTo(int major, int minor)
- {
- if((this.major == major) && (this.minor <= minor))
- {
- return true;
- }
- else if (this.major < major)
- {
- return true;
- }
-
- return false;
- }
-
- public boolean greaterThan(int major, int minor)
- {
- if(this.major > major)
- {
- return true;
- }
- else if ((this.major == major) && (this.minor > minor))
- {
- return true;
- }
-
- return false;
- }
-
- public boolean lessThan(int major, int minor)
- {
- if(this.major < major)
- {
- return true;
- }
- else if ((this.major == major) && (this.minor < minor))
- {
- return true;
- }
-
- return false;
- }
-
- public boolean equals(int major, int minor)
- {
- return (this.major == major) && (this.minor == minor);
- }
-
- public String toString()
- {
- return "major=" + major + ",minor=" + minor;
- }
-
-}
diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/Application.java b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/Application.java
deleted file mode 100644
index 5855b9ae55..0000000000
--- a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/Application.java
+++ /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.
- *
- */
-package org.apache.qpid.management.ui;
-
-import org.eclipse.core.runtime.IPlatformRunnable;
-import org.eclipse.swt.widgets.Display;
-import org.eclipse.swt.widgets.Shell;
-import org.eclipse.ui.PlatformUI;
-
-/**
- * This class controls all aspects of the application's execution
- * @author Bhupendra Bhardwaj
- */
-public class Application implements IPlatformRunnable
-{
- private static Shell shell = null;
-
- /*
- * The call to createAndRunWorkbench will not return until the workbench is closed.
- * The SWT event loop and other low-level logistics are handled inside this method.
- * @see org.eclipse.core.runtime.IPlatformRunnable#run(java.lang.Object)
- */
- public Object run(Object args) throws Exception
- {
- Display display = PlatformUI.createDisplay();
- try
- {
- int returnCode = PlatformUI.createAndRunWorkbench(display,
- new ApplicationWorkbenchAdvisor());
- if (returnCode == PlatformUI.RETURN_RESTART)
- {
- return IPlatformRunnable.EXIT_RESTART;
- }
- return IPlatformRunnable.EXIT_OK;
- } finally
- {
- display.dispose();
- }
- }
-
- static Shell getActiveShell()
- {
- return shell;
- }
-}
diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ApplicationActionBarAdvisor.java b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ApplicationActionBarAdvisor.java
deleted file mode 100644
index e4c3bbb894..0000000000
--- a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ApplicationActionBarAdvisor.java
+++ /dev/null
@@ -1,97 +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;
-
-import org.eclipse.jface.action.Action;
-import org.eclipse.jface.action.GroupMarker;
-import org.eclipse.jface.action.ICoolBarManager;
-import org.eclipse.jface.action.IMenuManager;
-import org.eclipse.jface.action.MenuManager;
-import org.eclipse.jface.action.Separator;
-import org.eclipse.ui.IWorkbenchActionConstants;
-import org.eclipse.ui.IWorkbenchWindow;
-import org.eclipse.ui.actions.ActionFactory;
-import org.eclipse.ui.actions.ActionFactory.IWorkbenchAction;
-import org.eclipse.ui.application.ActionBarAdvisor;
-import org.eclipse.ui.application.IActionBarConfigurer;
-
-import org.apache.qpid.management.ui.actions.VersionAction;
-
-/**
- * An action bar advisor is responsible for creating, adding, and disposing of the
- * actions added to a workbench window. Each window will be populated with
- * new actions.
- */
-public class ApplicationActionBarAdvisor extends ActionBarAdvisor
-{
-
- // Actions - important to allocate these only in makeActions, and then use them
- // in the fill methods. This ensures that the actions aren't recreated
- // when fillActionBars is called with FILL_PROXY.
- private IWorkbenchAction exitAction;
- private Action _aboutAction;
-
- public ApplicationActionBarAdvisor(IActionBarConfigurer configurer)
- {
- super(configurer);
- }
-
- protected void makeActions(final IWorkbenchWindow window)
- {
- // Creates the actions and registers them.
- // Registering is needed to ensure that key bindings work.
- // The corresponding commands keybindings are defined in the plugin.xml file.
- // Registering also provides automatic disposal of the actions when
- // the window is closed.
-
- exitAction = ActionFactory.QUIT.create(window);
- register(exitAction);
-
- _aboutAction = new VersionAction(window);
- register(_aboutAction);
- }
-
-
- protected void fillMenuBar(IMenuManager menuBar)
- {
- MenuManager fileMenu = new MenuManager("&Qpid Manager", "qpidmanager");
- MenuManager helpMenu = new MenuManager("&Help", IWorkbenchActionConstants.M_HELP);
-
- menuBar.add(fileMenu);
- // Add a group marker indicating where action set menus will appear.
- menuBar.add(new GroupMarker(IWorkbenchActionConstants.MB_ADDITIONS));
- menuBar.add(helpMenu);
-
- fileMenu.add(new GroupMarker(IWorkbenchActionConstants.MB_ADDITIONS));
- fileMenu.add(new Separator());
- fileMenu.add(new GroupMarker("mbeanactions"));
- fileMenu.add(new Separator());
- fileMenu.add(exitAction);
-
- // Help
- helpMenu.add(_aboutAction);
- }
-
- protected void fillCoolBar(ICoolBarManager coolBar)
- {
-
- }
-}
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
deleted file mode 100644
index 963a821864..0000000000
--- a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ApplicationRegistry.java
+++ /dev/null
@@ -1,191 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.management.ui;
-
-import org.eclipse.jface.resource.FontRegistry;
-import org.eclipse.jface.resource.ImageRegistry;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.graphics.Font;
-import org.eclipse.swt.graphics.FontData;
-import org.eclipse.swt.graphics.Image;
-import org.eclipse.ui.ISharedImages;
-import org.eclipse.ui.PlatformUI;
-
-import java.io.File;
-import java.util.List;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.CopyOnWriteArrayList;
-
-/**
- * Main Application Registry, which contains shared resources and map to all connected servers.
- * @author Bhupendra Bhardwaj
- */
-public abstract class ApplicationRegistry
-{
- private static ImageRegistry imageRegistry = new ImageRegistry();
- private static FontRegistry fontRegistry = new FontRegistry();
- public static final boolean debug = Boolean.getBoolean("eclipse.consoleLog");
- public static final long timeout = Long.parseLong(System.getProperty("timeout", "15000"));
-
- //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 = 4;
-
- public static final String DATA_DIR = System.getProperty("user.home") + File.separator + ".qpidmc";
-
- static
- {
- imageRegistry.put(Constants.SUCCESS_IMAGE,
- org.apache.qpid.management.ui.Activator.getImageDescriptor("/icons/success.gif"));
- imageRegistry.put(Constants.FAILURE_IMAGE,
- org.apache.qpid.management.ui.Activator.getImageDescriptor("/icons/failure.gif"));
- imageRegistry.put(Constants.CONSOLE_IMAGE,
- org.apache.qpid.management.ui.Activator.getImageDescriptor("/icons/qpidmc.gif"));
- imageRegistry.put(Constants.CLOSED_FOLDER_IMAGE,
- org.apache.qpid.management.ui.Activator.getImageDescriptor("/icons/icon_ClosedFolder.gif"));
- imageRegistry.put(Constants.OPEN_FOLDER_IMAGE,
- PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_OBJ_FOLDER));
- imageRegistry.put(Constants.MBEAN_IMAGE,
- PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_OBJ_ELEMENT));
- imageRegistry.put(Constants.NOTIFICATION_IMAGE,
- org.apache.qpid.management.ui.Activator.getImageDescriptor("/icons/notifications.gif"));
- imageRegistry.put(Constants.LOGGING_MANAGEMENT_IMAGE,
- org.apache.qpid.management.ui.Activator.getImageDescriptor("/icons/logging_management.gif"));
- imageRegistry.put(Constants.USER_MANAGEMENT_IMAGE,
- org.apache.qpid.management.ui.Activator.getImageDescriptor("/icons/user_management.gif"));
- imageRegistry.put(Constants.CONFIGURATION_MANAGEMENT_IMAGE,
- org.apache.qpid.management.ui.Activator.getImageDescriptor("/icons/configuration_management.gif"));
- imageRegistry.put(Constants.SERVER_INFO_IMAGE,
- org.apache.qpid.management.ui.Activator.getImageDescriptor("/icons/server_information.gif"));
- imageRegistry.put(Constants.VHOST_MANAGER_IMAGE,
- org.apache.qpid.management.ui.Activator.getImageDescriptor("/icons/virtualhost_manager.gif"));
- }
-
- static
- {
- fontRegistry.put(Constants.FONT_BUTTON, new FontData[]{new FontData("Arial", 8, SWT.BOLD)} );
- fontRegistry.put(Constants.FONT_BOLD, new FontData[]{new FontData("Bold", 9, SWT.BOLD)} );
- fontRegistry.put(Constants.FONT_ITALIC, new FontData[]{new FontData("Italic", 9, SWT.ITALIC)} );
- fontRegistry.put(Constants.FONT_TABLE_CELL, new FontData[]{new FontData("Tablecell", 8, SWT.NORMAL)} );
- fontRegistry.put(Constants.FONT_NORMAL, new FontData[]{new FontData("Normal", 9, SWT.NORMAL)} );
- }
-
- /*
- * This maps all the managed servers to the respective server registry.
- */
- private static ConcurrentHashMap<ManagedServer, ServerRegistry> _serverRegistryMap = new ConcurrentHashMap<ManagedServer, ServerRegistry>();
-
- // This map gets updated when a server connection closes.
- private static List<ManagedServer> _closedServerList = new CopyOnWriteArrayList<ManagedServer>();
-
- public static Image getImage(String key)
- {
- return imageRegistry.get(key);
- }
-
- public static Font getFont(String key)
- {
- return fontRegistry.get(key);
- }
-
- public static void addServer(ManagedServer server, ServerRegistry registry)
- {
- _serverRegistryMap.put(server, registry);
- }
-
- public static void removeServer(ManagedServer server)
- {
- _serverRegistryMap.remove(server);
- }
-
- public static ServerRegistry getServerRegistry(ManagedServer server)
- {
- return _serverRegistryMap.get(server);
- }
-
- public static ServerRegistry getServerRegistry(ManagedBean mbean)
- {
- ManagedServer server = mbean.getServer();
- return getServerRegistry(server);
- }
-
- public static boolean isServerConnected(ManagedServer server)
- {
- if(server == null)
- {
- //checking for null is not permitted in a CHM
- return false;
- }
-
- ServerRegistry reg = _serverRegistryMap.get(server);
- if(reg !=null)
- {
- return !reg.isServerConnectionClosed();
- }
-
- return false;
- }
-
- // remove the server from the registry
- public static void serverConnectionClosed(ManagedServer server)
- {
- _closedServerList.add(server);
- removeServer(server);
- }
-
- // remove the server from the registry
- public static void serverConnectionClosedRemotely(ManagedServer server)
- {
- ServerRegistry reg = _serverRegistryMap.get(server);
- if(reg !=null)
- {
- synchronized(server)
- {
- if(reg.isServerConnectionClosed())
- {
- //the connection closure was already processed
- return;
- }
-
- reg.serverConnectionClosed();
- }
- }
-
- serverConnectionClosed(server);
- }
-
- /*
- * Returns the lis of closed servers. The Thread in GUI, which keeps checking for closed connection
- * will check this and will remove the server links from the GUI.
- */
- public static List<ManagedServer> getClosedServers()
- {
- if (_closedServerList.isEmpty())
- {
- return null;
- }
-
- List<ManagedServer> list = new CopyOnWriteArrayList<ManagedServer>(_closedServerList);
- _closedServerList.clear();
- return list;
- }
-
-}
diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ApplicationWorkbenchAdvisor.java b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ApplicationWorkbenchAdvisor.java
deleted file mode 100644
index a46fa870e4..0000000000
--- a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ApplicationWorkbenchAdvisor.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.management.ui;
-
-import org.eclipse.ui.application.IWorkbenchWindowConfigurer;
-import org.eclipse.ui.application.WorkbenchAdvisor;
-import org.eclipse.ui.application.WorkbenchWindowAdvisor;
-
-/**
- * This workbench advisor creates the window advisor, and specifies
- * the perspective id for the initial window.
- */
-public class ApplicationWorkbenchAdvisor extends WorkbenchAdvisor
-{
- public static final String PERSPECTIVE_ID = "org.apache.qpid.management.ui.perspective";
-
- public WorkbenchWindowAdvisor createWorkbenchWindowAdvisor(IWorkbenchWindowConfigurer configurer)
- {
- return new ApplicationWorkbenchWindowAdvisor(configurer);
- }
-
-
- public String getInitialWindowPerspectiveId()
- {
- return PERSPECTIVE_ID;
- }
-
-}
diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ApplicationWorkbenchWindowAdvisor.java b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ApplicationWorkbenchWindowAdvisor.java
deleted file mode 100644
index 00574440c5..0000000000
--- a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ApplicationWorkbenchWindowAdvisor.java
+++ /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.
- *
- */
-package org.apache.qpid.management.ui;
-
-import org.eclipse.swt.graphics.Point;
-import org.eclipse.swt.widgets.Display;
-import org.eclipse.swt.widgets.Shell;
-import org.eclipse.ui.application.ActionBarAdvisor;
-import org.eclipse.ui.application.IActionBarConfigurer;
-import org.eclipse.ui.application.IWorkbenchWindowConfigurer;
-import org.eclipse.ui.application.WorkbenchWindowAdvisor;
-
-/**
- *
- * @author Bhupendra Bhardwaj
- */
-public class ApplicationWorkbenchWindowAdvisor extends WorkbenchWindowAdvisor
-{
- public ApplicationWorkbenchWindowAdvisor(IWorkbenchWindowConfigurer configurer)
- {
- super(configurer);
- }
-
- public ActionBarAdvisor createActionBarAdvisor(IActionBarConfigurer configurer)
- {
- return new ApplicationActionBarAdvisor(configurer);
- }
-
- public void preWindowOpen()
- {
- IWorkbenchWindowConfigurer configurer = getWindowConfigurer();
- int x = Display.getDefault().getBounds().width;
- int y = Display.getDefault().getBounds().height;
- configurer.setInitialSize(new Point(9*x/10, 8*y/10));
- configurer.setShowCoolBar(true);
- configurer.setShowStatusLine(true);
-
- configurer.setTitle(Constants.APPLICATION_NAME);
- }
-
- public void postWindowCreate()
- {
- IWorkbenchWindowConfigurer configurer = getWindowConfigurer();
- Shell shell = configurer.getWindow().getShell();
- shell.setImage(ApplicationRegistry.getImage(Constants.CONSOLE_IMAGE));
- }
-} \ No newline at end of file
diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/Constants.java b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/Constants.java
deleted file mode 100644
index c8f95dd8cb..0000000000
--- a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/Constants.java
+++ /dev/null
@@ -1,153 +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;
-
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-
-/**
- * Contains constants for the application
- * @author Bhupendra Bhardwaj
- *
- */
-public class Constants
-{
- public final static String APPLICATION_NAME = "Qpid JMX Management Console";
- public static final String DEFAULT_DOMAIN = "org.apache.qpid";
-
- public final static String ACTION_REMOVE_MBEANNODE = "Remove from list";
- public final static String VALUE = "value";
- public final static String TYPE = "type";
- public final static String VERSION = "version";
- public final static String NODE_TYPE_SERVER = "server";
- public final static String NODE_TYPE_MBEANTYPE = "mbeantype";
- // currently used only for virtual host instances, but will work as general also
- public final static String NODE_TYPE_TYPEINSTANCE = "mbeantype_instance";
- public final static String MBEAN = "mbean";
- public final static String ATTRIBUTE = "Attribute";
- public final static String ATTRIBUTES = "Attributes";
- public final static String NOTIFICATIONS = "Notifications";
- public final static String RESULT = "Result";
- public final static String VIRTUAL_HOST = "VirtualHost";
- public final static String DEFAULT_VH = "Default";
- public final static String DEFAULT_USERNAME = "guest";
- public final static String DEFAULT_PASSWORD = "guest";
-
- public final static String USERNAME = "Username";
- public final static String PASSWORD = "Password";
-
- // Attributes and operations are used to customize the GUI for Qpid. If these are changes in the
- // Qpid server, then these should be updated accordingly
- public final static String ATTRIBUTE_QUEUE_OWNER = "owner";
- public final static String ATTRIBUTE_QUEUE_DEPTH = "QueueDepth";
- public final static String ATTRIBUTE_QUEUE_CONSUMERCOUNT = "ActiveConsumerCount";
- public final static String OPERATION_CREATE_QUEUE = "createNewQueue";
- public final static String OPERATION_CREATE_BINDING = "createNewBinding";
- public final static String OPERATION_MOVE_MESSAGES = "moveMessages";
-
- public final static String OPERATION_CREATEUSER = "createUser";
- public final static String OPERATION_DELETEUSER = "deleteUser";
- public final static String OPERATION_VIEWUSERS = "viewUsers";
- public final static String OPERATION_PARAM_USERNAME = "username";
-
- public final static String OPERATION_SUCCESSFUL = "Operation successful";
- public final static String OPERATION_UNSUCCESSFUL = "Operation unsuccessful";
-
- public final static String ALL = "All";
-
- public final static String NAVIGATION_ROOT = "Qpid Connections";
- public final static String DESCRIPTION = " Description";
-
- public final static String ADMIN_MBEAN_TYPE = "UserManagement";
- public final static String QUEUE = "Queue";
- public final static String CONNECTION ="Connection";
- public final static String EXCHANGE = "Exchange";
- public final static String EXCHANGE_TYPE = "ExchangeType";
-
- public final static String DIRECT_EXCHANGE = "direct";
- public final static String FANOUT_EXCHANGE = "fanout";
- public final static String HEADERS_EXCHANGE = "headers";
- public final static String TOPIC_EXCHANGE = "topic";
- public final static List<String> DEFAULT_EXCHANGE_TYPE_VALUES = Collections.unmodifiableList(
- Arrays.asList(DIRECT_EXCHANGE, FANOUT_EXCHANGE, HEADERS_EXCHANGE, TOPIC_EXCHANGE));
- public final static List<String> ATTRIBUTE_TABLE_TITLES = Collections.unmodifiableList(
- Arrays.asList("Attribute Name", "Value"));
-
- public final static String ACTION_ADDSERVER = "New Connection";
- public final static String ACTION_RECONNECT = "Reconnect";
- public final static String ACTION_CLOSE = "Close Connection";
- public final static String ACTION_EDITATTRIBUTE = "Edit Attribute";
- public final static String ACTION_LOGIN = "Login";
-
- public final static String QUEUE_SORT_BY_NAME = "Queue Name";
- public final static String QUEUE_SORT_BY_DEPTH = "Queue Depth";
- public final static String QUEUE_SORT_BY_CONSUMERCOUNT = "Consumer Count";
- public final static String QUEUE_SHOW_TEMP_QUEUES= "show temporary queues";
-
- public final static String SUBSCRIBE_BUTTON = "Subscribe";
- public final static String UNSUBSCRIBE_BUTTON = "Unsubscribe";
-
-
- public final static String SUCCESS_IMAGE = "SuccessImage";
- public final static String FAILURE_IMAGE = "FailureImage";
- public final static String CONSOLE_IMAGE = "ConsoleImage";
- public final static String CLOSED_FOLDER_IMAGE = "ClosedFolderImage";
- public final static String OPEN_FOLDER_IMAGE = "OpenFolderImage";
- public final static String MBEAN_IMAGE = "MBeanImage";
- public final static String NOTIFICATION_IMAGE = "NotificationImage";
- public final static String LOGGING_MANAGEMENT_IMAGE = "LoggingManagementImage";
- public final static String USER_MANAGEMENT_IMAGE = "UserManagementImage";
- public final static String CONFIGURATION_MANAGEMENT_IMAGE = "ConfigurationManagementImage";
- public final static String SERVER_INFO_IMAGE = "ServerInfoImage";
- public final static String VHOST_MANAGER_IMAGE = "VhostManagerImage";
-
- public final static String FONT_BUTTON = "ButtonFont";
- public final static String FONT_BOLD = "BoldFont";
- public final static String FONT_ITALIC = "ItalicFont";
- public final static String FONT_TABLE_CELL = "TableCellFont";
- public final static String FONT_NORMAL = "Normal";
-
- public final static String BUTTON_DETAILS = "Details";
- public final static String BUTTON_EDIT_ATTRIBUTE = "Edit";
- public final static String BUTTON_REFRESH = "Refresh";
- public final static String BUTTON_GRAPH = "Graph";
- public final static int TIMER_INTERVAL = 5000;
- public final static String BUTTON_EXECUTE = "Execute";
- public final static String BUTTON_CLEAR = "Clear";
- public final static String BUTTON_CONNECT = "Connect";
- public final static String BUTTON_CANCEL = "Cancel";
- public final static String BUTTON_UPDATE = "Update";
-
-
- public final static int OPERATION_IMPACT_INFO = 0;
- public final static int OPERATION_IMPACT_ACTION = 1;
- public final static int OPERATION_IMPACT_ACTIONINFO = 2;
- public final static int OPERATION_IMPACT_UNKNOWN = 3;
-
- public final static String ERROR_SERVER_CONNECTION = "Server Connection Failed";
- public final static String INFO_PROTOCOL = "Please select the protocol";
- public final static String INFO_HOST_ADDRESS = "Please enter the host address";
- public final static String INFO_HOST_PORT = "Please enter the port number";
- public final static String INFO_USERNAME = "Please enter the " + USERNAME;
- public final static String INFO_PASSWORD = "Please enter the " + PASSWORD;
-
-}
diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ManagedBean.java b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ManagedBean.java
deleted file mode 100644
index f8db1b1f9b..0000000000
--- a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ManagedBean.java
+++ /dev/null
@@ -1,176 +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;
-
-import org.apache.qpid.management.common.mbeans.ManagedBroker;
-
-import static org.apache.qpid.management.ui.Constants.ADMIN_MBEAN_TYPE;
-import static org.apache.qpid.management.ui.Constants.CONNECTION;
-import static org.apache.qpid.management.ui.Constants.DEFAULT_VH;
-import static org.apache.qpid.management.ui.Constants.EXCHANGE;
-import static org.apache.qpid.management.ui.Constants.QUEUE;
-import static org.apache.qpid.management.ui.Constants.VIRTUAL_HOST;
-
-import java.util.HashMap;
-
-/**
- * Class representing a managed bean on the managed server
- */
-public abstract class ManagedBean extends ManagedObject
-{
- private String _uniqueName = "";
- private String _domain = "";
- private String _type = "";
- private String _virtualHostName = null;
- private ManagedServer _server = null;
- private HashMap _properties = null;
- private int _version;
-
- public String getProperty(String key)
- {
- return (String) _properties.get(key);
- }
-
- public HashMap getProperties()
- {
- return _properties;
- }
-
- public void setProperties(HashMap properties)
- {
- this._properties = properties;
- setName(getProperty("name"));
- setType(getProperty("type"));
- setVersion(getProperty("version"));
- _virtualHostName = getProperty(VIRTUAL_HOST);
- }
-
- public void setVersion(String version)
- {
- try
- {
- _version = Integer.parseInt(version);
- }
- catch (NumberFormatException nfe)
- {
- _version = 1;
- }
-
- }
-
- public int getVersion()
- {
- return _version;
- }
-
- public String getDomain()
- {
- return _domain;
- }
-
- public void setDomain(String domain)
- {
- this._domain = domain;
- }
-
- public ManagedServer getServer()
- {
- return _server;
- }
-
- public void setServer(ManagedServer server)
- {
- this._server = server;
- }
-
- public String getType()
- {
- return _type;
- }
-
- public void setType(String type)
- {
- this._type = type;
- }
-
- public String getUniqueName()
- {
- return _uniqueName;
- }
-
- public void setUniqueName(String uniqueName)
- {
- this._uniqueName = uniqueName;
- }
-
- public String getVirtualHostName()
- {
- // To make it work with the broker with no virtual host implementation
- return _virtualHostName == null ? DEFAULT_VH : _virtualHostName;
- }
-
- /**
- * Returns mbean instance name. MBeans which have only one instance, the type attribute will be returned
- *
- * @return
- */
- public String getInstanceName()
- {
- if (getName() != null)
- {
- return getName();
- }
- else
- {
- return getType();
- }
- }
-
- public boolean isQueue()
- {
- return _type.endsWith(QUEUE);
- }
-
- public boolean isConnection()
- {
- return _type.endsWith(CONNECTION);
- }
-
- public boolean isExchange()
- {
- return _type.endsWith(EXCHANGE);
- }
-
- public boolean isVirtualHostManager()
- {
- return _type.endsWith(ManagedBroker.TYPE);
- }
-
- public boolean isTempQueue()
- {
- return (isQueue() && getName().startsWith("tmp_"));
- }
-
- public boolean isAdmin()
- {
- return _type.endsWith(ADMIN_MBEAN_TYPE);
- }
-}
diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ManagedServer.java b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ManagedServer.java
deleted file mode 100644
index 9ca8787bb5..0000000000
--- a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ManagedServer.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.management.ui;
-
-/**
- * Class representing a server being managed eg. MBeanServer
- */
-public class ManagedServer extends ManagedObject
-{
- private String _host;
- private int _port;
- private String _domain;
- private String _user;
- private String _password;
-
- public ManagedServer(String host, int port, String domain)
- {
- this(host, port, domain, null, null);
- }
-
- public ManagedServer(String host, int port, String domain, String user, String password)
- {
- setName(host + ":" + port);
- _host = host;
- _port = port;
- _domain = domain;
- _user = user;
- _password = password;
- }
-
- public String getDomain()
- {
- return _domain;
- }
-
- public String getHost()
- {
- return _host;
- }
-
- public int getPort()
- {
- return _port;
- }
-
- public String getPassword()
- {
- return _password;
- }
-
- public void setPassword(String password)
- {
- _password = password;
- }
-
- public String getUser()
- {
- return _user;
- }
-
- public void setUser(String user)
- {
- _user = user;
- }
-
-}
diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/Perspective.java b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/Perspective.java
deleted file mode 100644
index abe166f798..0000000000
--- a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/Perspective.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.management.ui;
-
-import org.eclipse.ui.IPageLayout;
-import org.eclipse.ui.IPerspectiveFactory;
-
-import org.apache.qpid.management.ui.views.MBeanView;
-import org.apache.qpid.management.ui.views.NavigationView;
-
-/**
- *
- * @author Bhupendra Bhardwaj
- */
-public class Perspective implements IPerspectiveFactory
-{
- public void createInitialLayout(IPageLayout layout)
- {
- String editorArea = layout.getEditorArea();
- layout.setEditorAreaVisible(false);
-
- // standalone view meaning it can't be docked or stacked with other views, and it doesn't have a title bar.
- layout.addStandaloneView(NavigationView.ID, true, IPageLayout.LEFT, 0.30f, editorArea);
- layout.addStandaloneView(MBeanView.ID, true, IPageLayout.RIGHT, 0.70f, editorArea);
-
- layout.getViewLayout(NavigationView.ID).setCloseable(false);
- layout.getViewLayout(MBeanView.ID).setCloseable(false);
- }
-}
diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/RefreshIntervalComboPanel.java b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/RefreshIntervalComboPanel.java
deleted file mode 100644
index b8a81f67a7..0000000000
--- a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/RefreshIntervalComboPanel.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;
-
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.events.ModifyEvent;
-import org.eclipse.swt.events.ModifyListener;
-import org.eclipse.swt.layout.GridData;
-import org.eclipse.swt.layout.GridLayout;
-import org.eclipse.swt.widgets.Combo;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Control;
-import org.eclipse.swt.widgets.Display;
-import org.eclipse.swt.widgets.Label;
-import org.eclipse.ui.IWorkbenchWindow;
-import org.eclipse.ui.PlatformUI;
-import org.eclipse.ui.menus.WorkbenchWindowControlContribution;
-
-import org.apache.qpid.management.ui.jmx.MBeanUtility;
-import org.apache.qpid.management.ui.views.MBeanView;
-import org.apache.qpid.management.ui.views.NavigationView;
-
-public class RefreshIntervalComboPanel extends WorkbenchWindowControlContribution
-{
- private Display _display = null;
- private RefreshTask _refreshTask = null;
-
- private static int DEFAULT_INDEX = 2; //15seconds
- private static final int[] INTERVALS = new int[]{5,10,15,30,60,120,300,600};
-
- public RefreshIntervalComboPanel()
- {
- super();
- }
-
- public RefreshIntervalComboPanel(String id)
- {
- super(id);
- }
-
- @Override
- public Control createControl(Composite parent)
- {
- _display = parent.getDisplay();
-
- Composite holder = new Composite(parent,SWT.NONE);
- holder.setLayout(new GridLayout(2,false));
- holder.setLayoutData(new GridData(SWT.LEFT,SWT.TOP,false,false));
-
- Label refreshLabel = new Label(holder,SWT.NONE);
- refreshLabel.setLayoutData(new GridData(SWT.LEFT,SWT.TOP,false,true));
- refreshLabel.setText("Refresh Interval: ");
-
- final Combo combo = new Combo(holder, SWT.NONE | SWT.DROP_DOWN | SWT.READ_ONLY);
- combo.setLayoutData(new GridData(SWT.LEFT,SWT.TOP,false,false));
- for(int i=0; i< INTERVALS.length ; i++)
- {
- combo.add(String.valueOf(INTERVALS[i]) + " seconds");
- }
- combo.select(DEFAULT_INDEX);
-
- _refreshTask = new RefreshTask(INTERVALS[DEFAULT_INDEX]);
- _display.timerExec(1000 * INTERVALS[DEFAULT_INDEX], _refreshTask);
-
- combo.addModifyListener(
- new ModifyListener()
- {
- public void modifyText(final ModifyEvent e)
- {
- _display.timerExec(-1, _refreshTask); //cancels existing refresh runnable
- _refreshTask = new RefreshTask(INTERVALS[combo.getSelectionIndex()]);
- _display.timerExec(0, _refreshTask); //immediately refresh and begin new schedule
- }
- });
-
- return holder;
- }
-
-
- private class RefreshTask implements Runnable
- {
- private int seconds;
-
- public RefreshTask(int secs)
- {
- this.seconds = secs;
- }
-
- @Override
- public void run()
- {
- IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
- if(window != null)
- {
- final MBeanView mbView = (MBeanView)window.getActivePage().findView(MBeanView.ID);
-
- final NavigationView navView = (NavigationView)window.getActivePage().findView(NavigationView.ID);
- try
- {
- mbView.refresh();
- navView.refresh();
- }
- catch (Exception ex)
- {
- MBeanUtility.handleException(ex);
- }
-
- _display.timerExec(1000 * seconds, this);
- }
- }
-
- }
-
-}
diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ServerRegistry.java b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ServerRegistry.java
deleted file mode 100644
index bc60b6f76c..0000000000
--- a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ServerRegistry.java
+++ /dev/null
@@ -1,263 +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;
-
-
-import org.apache.qpid.management.ui.jmx.ClientListener;
-import org.apache.qpid.management.ui.model.ManagedAttributeModel;
-import org.apache.qpid.management.ui.model.NotificationObject;
-import org.apache.qpid.management.ui.model.OperationDataModel;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
-import java.util.concurrent.atomic.AtomicBoolean;
-
-public abstract class ServerRegistry
-{
- private ManagedServer _managedServer = null;
-
- // API version for the management interface on the broker
- private ApiVersion _managementApiVersion = new ApiVersion(0,0);
-
- // list of virtual hosts for this server
- private List<String> _virtualHosts = new ArrayList<String>();
- // map of all Connection mbeans
- private ConcurrentMap<String,List<ManagedBean>> _connections = new ConcurrentHashMap<String,List<ManagedBean>>();
- // map of all exchange mbeans
- private ConcurrentMap<String,List<ManagedBean>> _exchanges = new ConcurrentHashMap<String,List<ManagedBean>>();
- // map of all queue mbenas
- private ConcurrentMap<String,List<ManagedBean>> _queues = new ConcurrentHashMap<String,List<ManagedBean>>();
- // map of all virtual host manager mbeans
- private ConcurrentMap<String,ManagedBean> _vhostManagers = new ConcurrentHashMap<String,ManagedBean>();
-
- private AtomicBoolean _serverConnectionClosed = new AtomicBoolean(false);
-
- public ServerRegistry()
- {
-
- }
-
- public ServerRegistry(ManagedServer server)
- {
- _managedServer = server;
- }
-
- public void serverConnectionClosed()
- {
- _serverConnectionClosed.set(true);
- }
-
- public boolean isServerConnectionClosed()
- {
- return _serverConnectionClosed.get();
- }
-
- public void setManagementApiVersion(ApiVersion mgmtApiVersion)
- {
- _managementApiVersion = mgmtApiVersion;
- }
-
- public ApiVersion getManagementApiVersion()
- {
- return _managementApiVersion;
- }
-
- public ManagedServer getManagedServer()
- {
- return _managedServer;
- }
-
- public void setManagedServer(ManagedServer server)
- {
- _managedServer = server;
- }
-
- protected void addConnectionMBean(ManagedBean mbean)
- {
- String vHost = mbean.getVirtualHostName();
- List<ManagedBean> vhostConnections = getVhostSubList(vHost, _connections);
- vhostConnections.add(mbean);
- }
-
- protected void addExchangeMBean(ManagedBean mbean)
- {
- String vHost = mbean.getVirtualHostName();
- List<ManagedBean> vhostExchanges = getVhostSubList(vHost, _exchanges);
- vhostExchanges.add(mbean);
- }
-
- protected void addQueueMBean(ManagedBean mbean)
- {
- String vHost = mbean.getVirtualHostName();
- List<ManagedBean> vhostQueues = getVhostSubList(vHost, _queues);
- vhostQueues.add(mbean);
- }
-
- private List<ManagedBean> getVhostSubList(String vHost, ConcurrentMap<String,List<ManagedBean>> parentList)
- {
- //add an empty sublist for the vhost if required
- if (!parentList.containsKey(vHost))
- {
- List<ManagedBean> subList = Collections.synchronizedList(new ArrayList<ManagedBean>());
- parentList.putIfAbsent(vHost, subList);
- }
-
- return parentList.get(vHost);
- }
-
- protected void addVirtualHostManagerMBean(ManagedBean mbean)
- {
- String vHost = mbean.getVirtualHostName();
- _vhostManagers.put(vHost, mbean);
- }
-
- protected void removeVirtualHostManagerMBean(ManagedBean mbean)
- {
- _vhostManagers.remove(mbean.getVirtualHostName());
- }
-
- public ManagedBean getVirtualHostManagerMBean(String virtualHost)
- {
- return _vhostManagers.get(virtualHost);
- }
-
- protected void removeConnectionMBean(ManagedBean mbean)
- {
- _connections.get(mbean.getVirtualHostName()).remove(mbean);
- }
-
- protected void removeExchangeMBean(ManagedBean mbean)
- {
- _exchanges.get(mbean.getVirtualHostName()).remove(mbean);
- }
-
- protected void removeQueueMBean(ManagedBean mbean)
- {
- _queues.get(mbean.getVirtualHostName()).remove(mbean);
- }
-
- public List<ManagedBean> getConnections(String virtualHost)
- {
- return getVhostObjects(virtualHost, _connections);
- }
-
- public List<ManagedBean> getExchanges(String virtualHost)
- {
- return getVhostObjects(virtualHost, _exchanges);
- }
-
- public List<ManagedBean> getQueues(String virtualHost)
- {
- return getVhostObjects(virtualHost, _queues);
- }
-
- public List<ManagedBean> getVhostObjects(String virtualHost, ConcurrentMap<String,List<ManagedBean>> parentList)
- {
- List<ManagedBean> objects = parentList.get(virtualHost);
-
- if(objects == null)
- {
- return new ArrayList<ManagedBean>();
- }
-
- synchronized (objects)
- {
- return new ArrayList<ManagedBean>(objects);
- }
- }
-
- //returns the requested ManagedBean, or null if it cant be found
- public ManagedBean getQueue(String queueName, String virtualHost)
- {
- ManagedBean requestedQueue = null;
-
- for(ManagedBean queue : _queues.get(virtualHost))
- {
- if(queueName.equals(queue.getName()))
- {
- requestedQueue = queue;
- break;
- }
- }
-
- return requestedQueue;
- }
-
- public void addVirtualHost(String name)
- {
- if (!_virtualHosts.contains(name))
- {
- _virtualHosts.add(name);
- }
- }
-
- public List<String> getVirtualHosts()
- {
- return _virtualHosts;
- }
-
- public abstract void setUserList(List<String> list);
-
- public abstract List<String> getUsernames();
-
- public abstract void addManagedObject(ManagedBean key);
-
- public abstract List<ManagedBean> getMBeans();
-
- public abstract void removeManagedObject(ManagedBean mbean);
-
- public abstract List<ManagedBean> getObjectsToBeRemoved();
-
- public abstract ManagedAttributeModel getAttributeModel(ManagedBean mbean);
-
- public abstract Object getServerConnection();
-
- public abstract void closeServerConnection() throws Exception;
-
- public abstract OperationDataModel getOperationModel(ManagedBean mbean);
-
- public abstract List<String> getQueueNames(String vistualHostName);
-
- public abstract String[] getExchangeNames(String vistualHostName);
-
- public abstract String[] getConnectionNames(String vistualHostName);
-
- public abstract List<NotificationObject> getNotifications(ManagedBean mbean);
-
- public abstract List<NotificationObject> getNotifications(String virtualhost);
-
- public abstract boolean hasSubscribedForNotifications(ManagedBean mbean, String name, String type);
-
- public abstract void clearNotifications(ManagedBean mbean, List<NotificationObject> list);
-
- public ClientListener getNotificationListener()
- {
- return null;
- }
-
- public ClientListener getClientListener()
- {
- return null;
- }
-}
diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/actions/AbstractAction.java b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/actions/AbstractAction.java
deleted file mode 100644
index 5ba300ea32..0000000000
--- a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/actions/AbstractAction.java
+++ /dev/null
@@ -1,220 +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.actions;
-
-import org.eclipse.core.runtime.IStatus;
-import org.eclipse.core.runtime.Status;
-import org.eclipse.jface.action.IAction;
-import org.eclipse.jface.dialogs.ErrorDialog;
-import org.eclipse.jface.viewers.ISelection;
-import org.eclipse.ui.IWorkbenchWindow;
-import org.eclipse.ui.IWorkbenchWindowActionDelegate;
-
-import org.apache.qpid.management.ui.ApplicationRegistry;
-import org.apache.qpid.management.ui.ApplicationWorkbenchAdvisor;
-import org.apache.qpid.management.ui.Constants;
-import org.apache.qpid.management.ui.exceptions.ManagementConsoleException;
-import org.apache.qpid.management.ui.jmx.MBeanUtility;
-import org.apache.qpid.management.ui.views.NavigationView;
-
-import static org.apache.qpid.management.ui.Constants.ERROR_SERVER_CONNECTION;
-
-import javax.net.ssl.SSLException;
-import javax.net.ssl.SSLHandshakeException;
-import javax.net.ssl.SSLKeyException;
-import javax.net.ssl.SSLPeerUnverifiedException;
-import java.io.IOException;
-
-public class AbstractAction
-{
- private NavigationView _navigationView;
-
- protected IWorkbenchWindow _window;
-
- public static final String INVALID_PERSPECTIVE = "Invalid Perspective";
- public static final String CHANGE_PERSPECTIVE = "Please use the Qpid Management Perspective";
-
- private static final String SSL_EMPTY_TRUSTANCHORS = "the trustAnchors parameter must be non-empty";
- private static final String SSL_UNABLE_TO_FIND_CERTPATH = "sun.security.provider.certpath.SunCertPathBuilderException: " +
- "unable to find valid certification path to requested target";
-
- /**
- * We will cache window object in order to
- * be able to provide parent shell for the message dialog.
- * @see IWorkbenchWindowActionDelegate#init
- */
- public void init(IWorkbenchWindow window)
- {
- this._window = window;
- if (_window.getShell() != null)
- {
- _window.getShell().setImage(ApplicationRegistry.getImage(Constants.CONSOLE_IMAGE));
- }
- }
-
- protected NavigationView getNavigationView()
- {
- if (_navigationView == null)
- {
- _navigationView = (NavigationView)_window.getActivePage().findView(NavigationView.ID);
- }
-
- return _navigationView;
- }
-
- protected void handleException(Throwable ex, String title, String msg)
- {
- //ensure first that the exception is not due to running in the wrong eclipse perspective
- NavigationView view = (NavigationView)_window.getActivePage().findView(NavigationView.ID);
- if (view == null)
- {
- IStatus status = new Status(IStatus.WARNING, ApplicationWorkbenchAdvisor.PERSPECTIVE_ID,
- IStatus.OK, CHANGE_PERSPECTIVE, null);
- ErrorDialog.openError(_window.getShell(), "Warning", INVALID_PERSPECTIVE, status);
- return;
- }
-
- //default title if none given
- if (title == null)
- {
- title = ERROR_SERVER_CONNECTION;
- }
-
- //determine the error message to display
- if (msg == null)
- {
- if (ex instanceof SSLException)
- {
- if (ex instanceof SSLKeyException)
- {
- msg = "SSL key was invalid, please check the certificate configuration.";
- //Display error dialogue and return
- displayErrorDialogue(msg, title);
- return;
- }
- else if (ex instanceof SSLPeerUnverifiedException)
- {
- msg = "SSL peer identity could not be verified, please ensure valid certificate configuration.";
- //Display error dialogue and return
- displayErrorDialogue(msg, title);
- return;
- }
- else if (ex instanceof SSLHandshakeException)
- {
- if (ex.getMessage().contains(SSL_UNABLE_TO_FIND_CERTPATH))
- {
- msg = "Unable to certify the provided SSL certificate using the current SSL trust store.";
- }
- else
- {
- //cause unknown, provide a trace too
- MBeanUtility.printStackTrace(ex);
- msg = "SSL handhshake error.";
- }
- //Display error dialogue and return
- displayErrorDialogue(msg, title);
- return;
- }
- else
- {
- //general SSL Exception.
- if (ex.getMessage().contains(SSL_EMPTY_TRUSTANCHORS))
- {
- msg = "Unable to locate the specified SSL certificate trust store, please check the configuration.";
- }
- else
- {
- //cause unknown, print stack trace
- MBeanUtility.printStackTrace(ex);
- msg = "SSL connection error.";
- }
- //Display error dialogue and return
- displayErrorDialogue(msg, title);
- return;
- }
- }
- else if (ex instanceof IOException || ex instanceof SecurityException )
- {
- msg = ex.getMessage();
-
- //if msg is still null, try reporting the cause.
- if ((msg == null) && (ex.getCause() != null))
- {
- msg = ex.getCause().getMessage();
- }
-
- //Display error dialogue and return
- displayErrorDialogue(msg, title);
- return;
- }
- else if (ex instanceof ManagementConsoleException)
- {
- msg = ex.getMessage();
- displayErrorDialogue(msg, title);
- return;
- }
- else
- {
- //Unknown exception type/reason.
- msg = ex.getMessage();
- }
-
- //if msg is still null, try reporting the cause.
- if ((msg == null) && (ex.getCause() != null))
- {
- msg = ex.getCause().getMessage();
- }
-
- //failing all else, default non-descript error message.
- if (msg == null)
- {
- msg = "An unknown error has occured.";
- }
- }
-
- //Display error dialogue and print the exception stack trace
- MBeanUtility.printStackTrace(ex);
- displayErrorDialogue(msg, title);
- }
-
- private void displayErrorDialogue(String msg, String title)
- {
- IStatus status = new Status(IStatus.ERROR, ApplicationWorkbenchAdvisor.PERSPECTIVE_ID,
- IStatus.OK, msg, null);
- ErrorDialog.openError(_window.getShell(), "Error", title, status);
- }
-
- /**
- * Selection in the workbench has been changed. We can change the state of the 'real' action here
- * if we want, but this can only happen after the delegate has been created.
- * @see IWorkbenchWindowActionDelegate#selectionChanged
- */
- public void selectionChanged(IAction action, ISelection selection) {
- }
-
- /**
- * We can use this method to dispose of any system resources we previously allocated.
- * @see IWorkbenchWindowActionDelegate#dispose
- */
- public void dispose() {
-
- }
-}
diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/actions/AddServer.java b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/actions/AddServer.java
deleted file mode 100644
index f80790ce0c..0000000000
--- a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/actions/AddServer.java
+++ /dev/null
@@ -1,316 +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.actions;
-
-import org.eclipse.jface.action.IAction;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.events.KeyAdapter;
-import org.eclipse.swt.events.KeyEvent;
-import org.eclipse.swt.events.SelectionAdapter;
-import org.eclipse.swt.events.SelectionEvent;
-import org.eclipse.swt.layout.GridData;
-import org.eclipse.swt.layout.GridLayout;
-import org.eclipse.swt.widgets.Button;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Control;
-import org.eclipse.swt.widgets.Display;
-import org.eclipse.swt.widgets.Label;
-import org.eclipse.swt.widgets.Shell;
-import org.eclipse.swt.widgets.Text;
-import org.eclipse.ui.IWorkbenchWindowActionDelegate;
-
-import org.apache.qpid.management.ui.ApplicationRegistry;
-import org.apache.qpid.management.ui.exceptions.InfoRequiredException;
-import org.apache.qpid.management.ui.views.NumberVerifyListener;
-import org.apache.qpid.management.ui.views.ViewUtility;
-
-import static org.apache.qpid.management.ui.Constants.*;
-
-public class AddServer extends AbstractAction implements IWorkbenchWindowActionDelegate
-{
- private String _host;
- private String _port;
- private String _domain = DEFAULT_DOMAIN;
- private String _user;
- private String _password;
-
- private boolean _addServer;
-
- public AddServer()
- {
-
- }
-
- public void run(IAction action)
- {
- if(_window == null)
- {
- return;
- }
-
- reset();
- createAddServerPopup();
- try
- {
- if (_addServer)
- {
- getNavigationView().addNewServer(_host, Integer.parseInt(_port), _domain, _user, _password);
- }
- }
- catch(InfoRequiredException ex)
- {
- ViewUtility.popupInfoMessage(ACTION_ADDSERVER, ex.getMessage());
- }
- catch (Exception ex)
- {
- handleException(ex, null, null);
- }
- }
-
- private void reset()
- {
- _addServer = false;
- _host = null;
- _port = null;
- _user = null;
- _password = null;
- }
-
- /**
- * Creates the shell and then opens the popup where user can enter new connection details.
- * Connects to the new server and adds the server in the navigation page.
- * Pops up any error occured in connecting to the new server
- */
- private void createAddServerPopup()
- {
- final Shell appShell = _window.getShell();
-
- Display display = Display.getCurrent();
- final Shell shell = new Shell(display, SWT.BORDER | SWT.CLOSE);
- shell.setText(ACTION_ADDSERVER);
- shell.setImage(ApplicationRegistry.getImage(CONSOLE_IMAGE));
- shell.setLayout(new GridLayout());
-
- createWidgets(shell);
- shell.pack();
-
- //get current size dialog, and application window size and location
- int appWidth = appShell.getBounds().width;
- int appHeight = appShell.getBounds().height;
- int appLocX = appShell.getBounds().x;
- int appLocY = appShell.getBounds().y;
- int currentShellWidth = shell.getSize().x;
- int currentShellHeight = shell.getSize().y;
-
- //default sizes for the dialog
- int minShellWidth = 425;
- int minShellHeight= 265;
- //ensure this is large enough, increase it if its not
- int newShellWidth = currentShellWidth > minShellWidth ? currentShellWidth : minShellWidth;
- int newShellHeight = currentShellHeight > minShellHeight ? currentShellHeight : minShellHeight;
-
- //set the final size and centre the dialog within the app window
- shell.setBounds((appWidth - newShellWidth)/2 + appLocX, (appHeight - newShellHeight)/2 + appLocY, newShellWidth, newShellHeight);
-
- shell.open();
- _window.getShell().setEnabled(false);
-
- while (!shell.isDisposed())
- {
- if (!display.readAndDispatch())
- {
- display.sleep();
- }
- }
-
- // enable the main shell
- _window.getShell().setEnabled(true);
- _window.getShell().open();
- }
-
- // Creates SWT widgets for the user to add server connection details.
- // Adds listeners to the widgets to take appropriate action
- private void createWidgets(final Shell shell)
- {
- Composite composite = new Composite(shell, SWT.NONE);
- composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
- GridLayout layout = new GridLayout(2, false);
- layout.horizontalSpacing = 10;
- layout.verticalSpacing = 10;
- layout.marginHeight = 20;
- layout.marginWidth = 20;
- composite.setLayout(layout);
-
- /* Commenting this, as there is only one protocol at the moment.
- * This can be uncommented and enhanced, if more protocols are added in future
- Label name = new Label(composite, SWT.NONE);
- name.setText("Connection Type");
- GridData layoutData = new GridData(SWT.TRAIL, SWT.TOP, false, false);
- name.setLayoutData(layoutData);
-
- final Combo comboTransport = new Combo(composite, SWT.READ_ONLY);
- comboTransport.setItems(CONNECTION_PROTOCOLS);
- comboTransport.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
- comboTransport.select(0);
- */
-
- Label host = new Label(composite, SWT.NONE);
- host.setText("Host");
- host.setLayoutData(new GridData(SWT.TRAIL, SWT.TOP, false, false));
-
- final Text textHost = new Text(composite, SWT.BORDER);
- textHost.setText("");
- textHost.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
- textHost.setFocus();
-
- Label port = new Label(composite, SWT.NONE);
- port.setText("Port");
- port.setLayoutData(new GridData(SWT.TRAIL, SWT.TOP, false, false));
-
- final Text textPort = new Text(composite, SWT.BORDER);
- textPort.setText("");
- textPort.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
- // Verify if the value entered is numeric
- textPort.addVerifyListener(new NumberVerifyListener());
-
- Label user = new Label(composite, SWT.NONE);
- user.setText(USERNAME);
- user.setLayoutData(new GridData(SWT.TRAIL, SWT.TOP, false, false));
-
- final Text textUser = new Text(composite, SWT.BORDER);
- textUser.setText("");
- textUser.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
-
- Label password = new Label(composite, SWT.NONE);
- password.setText(PASSWORD);
- password.setLayoutData(new GridData(SWT.TRAIL, SWT.TOP, false, false));
-
- final Text textPwd = new Text(composite, SWT.BORDER | SWT.SINGLE | SWT.PASSWORD);
- textPwd.setText("");
- //textPwd.setEchoChar('*');
- textPwd.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
-
- //Get the text widgets
- Control[] widgets = composite.getChildren();
- for (int i=0; i < widgets.length; i++)
- {
- widgets[i].addKeyListener(new KeyAdapter()
- {
- public void keyPressed(KeyEvent event)
- {
- if (event.character == SWT.ESC)
- {
- //Escape key acts as cancel on all widgets
- shell.dispose();
- }
- }
- });
- }
-
- Composite buttonsComposite = new Composite(composite, SWT.NONE);
- buttonsComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 2, 1));
- buttonsComposite.setLayout(new GridLayout(2, true));
-
- final Button connectButton = new Button(buttonsComposite, SWT.PUSH | SWT.CENTER);
- connectButton.setText(BUTTON_CONNECT);
- GridData gridData = new GridData (SWT.TRAIL, SWT.BOTTOM, true, true);
- gridData.widthHint = 100;
- connectButton.setLayoutData(gridData);
- connectButton.setFont(ApplicationRegistry.getFont(FONT_BUTTON));
- connectButton.addSelectionListener(new SelectionAdapter(){
- public void widgetSelected(SelectionEvent event)
- {
- _host = textHost.getText();
- if ((_host == null) || (_host.trim().length() == 0))
- {
- ViewUtility.popupInfoMessage(ACTION_ADDSERVER, INFO_HOST_ADDRESS);
- textHost.setText("");
- textHost.setFocus();
- return;
- }
-
- _port = textPort.getText();
- if ((_port == null) || (_port.trim().length() == 0))
- {
- ViewUtility.popupInfoMessage(ACTION_ADDSERVER, INFO_HOST_PORT);
- textPort.setText("");
- textPort.setFocus();
- return;
- }
-
- _user = textUser.getText();
- if ((_user == null) || (_user.trim().length() == 0))
- {
- ViewUtility.popupInfoMessage(ACTION_ADDSERVER, INFO_USERNAME);
- textUser.setText("");
- textUser.setFocus();
- return;
- }
-
- _password = textPwd.getText();
- if (_password == null)
- {
- ViewUtility.popupInfoMessage(ACTION_ADDSERVER, INFO_PASSWORD);
- textPwd.setText("");
- textPwd.setFocus();
- return;
- }
-
- _addServer = true;
- shell.dispose();
- }
- });
-
- final Button cancelButton = new Button(buttonsComposite, SWT.PUSH);
- cancelButton.setText(BUTTON_CANCEL);
- gridData = new GridData (SWT.LEAD, SWT.BOTTOM, true, true);
- gridData.widthHint = 100;
- cancelButton.setLayoutData(gridData);
- cancelButton.setFont(ApplicationRegistry.getFont(FONT_BUTTON));
- cancelButton.addSelectionListener(new SelectionAdapter()
- {
- public void widgetSelected(SelectionEvent event)
- {
- shell.dispose();
- }
- });
-
- //Get the ok/cancel button widgets and add a new key listener
- widgets = buttonsComposite.getChildren();
- for (int i=0; i < widgets.length; i++)
- {
- widgets[i].addKeyListener(new KeyAdapter()
- {
- public void keyPressed(KeyEvent event)
- {
- if (event.character == SWT.ESC)
- {
- //Escape key acts as cancel on all widgets
- shell.dispose();
- }
- }
- });
- }
-
- shell.setDefaultButton(connectButton);
- }
-
-}
diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/actions/BackAction.java b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/actions/BackAction.java
deleted file mode 100644
index ade4cecef5..0000000000
--- a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/actions/BackAction.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.management.ui.actions;
-
-import org.eclipse.jface.action.Action;
-import org.eclipse.ui.PlatformUI;
-import org.eclipse.ui.actions.ActionFactory.IWorkbenchAction;
-
-import org.apache.qpid.management.ui.jmx.MBeanUtility;
-import org.apache.qpid.management.ui.views.MBeanView;
-
-
-public class BackAction extends Action implements IWorkbenchAction
-{
- private static final String ID = "org.apache.qpid.management.ui.actions.back";
-
- public BackAction()
- {
- setText("Back");
- setImageDescriptor(org.apache.qpid.management.ui.Activator.getImageDescriptor("/icons/back.gif"));
- setId(ID);
- }
-
- public void run()
- {
- MBeanView mbeanview = (MBeanView)PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().findView(MBeanView.ID);
- try
- {
- mbeanview.back();
- }
- catch (Exception ex)
- {
- MBeanUtility.handleException(ex);
- }
-
- }
-
- public void dispose()
- {
-
- }
-}
diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/actions/CloseConnection.java b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/actions/CloseConnection.java
deleted file mode 100644
index 2dbbcc3b5b..0000000000
--- a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/actions/CloseConnection.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.management.ui.actions;
-
-import org.eclipse.jface.action.IAction;
-import org.eclipse.ui.IWorkbenchWindowActionDelegate;
-
-import org.apache.qpid.management.ui.exceptions.InfoRequiredException;
-import org.apache.qpid.management.ui.views.NavigationView;
-import org.apache.qpid.management.ui.views.ViewUtility;
-
-import static org.apache.qpid.management.ui.Constants.ACTION_CLOSE;
-
-public class CloseConnection extends AbstractAction implements IWorkbenchWindowActionDelegate
-{
- public CloseConnection()
- {
-
- }
-
- public void run(IAction action)
- {
- if(_window != null)
- {
- NavigationView view = (NavigationView)_window.getActivePage().findView(NavigationView.ID);
- try
- {
- view.disconnect();
- }
- catch(InfoRequiredException ex)
- {
- ViewUtility.popupInfoMessage(ACTION_CLOSE, ex.getMessage());
- }
- catch(Exception ex)
- {
- handleException(ex, null, null);
- }
- }
- }
-}
diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/actions/ReconnectServer.java b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/actions/ReconnectServer.java
deleted file mode 100644
index c1634ef8f8..0000000000
--- a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/actions/ReconnectServer.java
+++ /dev/null
@@ -1,267 +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.actions;
-
-import org.eclipse.jface.action.IAction;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.events.KeyAdapter;
-import org.eclipse.swt.events.KeyEvent;
-import org.eclipse.swt.events.SelectionAdapter;
-import org.eclipse.swt.events.SelectionEvent;
-import org.eclipse.swt.layout.GridData;
-import org.eclipse.swt.layout.GridLayout;
-import org.eclipse.swt.widgets.Button;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Control;
-import org.eclipse.swt.widgets.Display;
-import org.eclipse.swt.widgets.Label;
-import org.eclipse.swt.widgets.Shell;
-import org.eclipse.swt.widgets.Text;
-import org.eclipse.ui.IWorkbenchWindowActionDelegate;
-
-import org.apache.qpid.management.ui.ApplicationRegistry;
-import org.apache.qpid.management.ui.Constants;
-import org.apache.qpid.management.ui.exceptions.InfoRequiredException;
-import org.apache.qpid.management.ui.views.TreeObject;
-import org.apache.qpid.management.ui.views.ViewUtility;
-
-import static org.apache.qpid.management.ui.Constants.ACTION_LOGIN;
-import static org.apache.qpid.management.ui.Constants.CONSOLE_IMAGE;
-import static org.apache.qpid.management.ui.Constants.INFO_PASSWORD;
-import static org.apache.qpid.management.ui.Constants.INFO_USERNAME;
-import static org.apache.qpid.management.ui.Constants.PASSWORD;
-import static org.apache.qpid.management.ui.Constants.USERNAME;
-
-public class ReconnectServer extends AbstractAction implements IWorkbenchWindowActionDelegate
-{
- private String _title;
- private String _serverName;
- private String _user;
- private String _password;
- private boolean _connect;
-
- public void run(IAction action)
- {
- if(_window == null)
- {
- return;
- }
-
- try
- {
- reset();
- // Check if a server node is selected to be reconnected.
- TreeObject serverNode = getNavigationView().getSelectedServerNode();
- _serverName = serverNode.getName();
- _title = ACTION_LOGIN + " (" + _serverName + ")";
-
- // Get the login details(username/password)
- createLoginPopup();
-
- if (_connect)
- {
- // Connect the server
- getNavigationView().reconnect(_user, _password);
- }
- }
- catch(InfoRequiredException ex)
- {
- ViewUtility.popupInfoMessage("Reconnect Qpid server", ex.getMessage());
- }
- catch (Exception ex)
- {
- handleException(ex, null, null);
- }
- }
-
- private void reset()
- {
- _connect = false;
- _user = null;
- _password = null;
- }
-
- // Create the login popup fot th user to enter usernaem and password
- private void createLoginPopup()
- {
- final Shell appShell = _window.getShell();
-
- Display display = Display.getCurrent();
- final Shell shell = new Shell(display, SWT.BORDER | SWT.CLOSE);
- shell.setText(_title);
- shell.setImage(ApplicationRegistry.getImage(CONSOLE_IMAGE));
- shell.setLayout(new GridLayout());
-
- createWidgets(shell);
- shell.pack();
-
- //get current size dialog, and application window size and location
- int appWidth = appShell.getBounds().width;
- int appHeight = appShell.getBounds().height;
- int appLocX = appShell.getBounds().x;
- int appLocY = appShell.getBounds().y;
- int currentShellWidth = shell.getSize().x;
- int currentShellHeight = shell.getSize().y;
-
- //default sizes for the dialog
- int minShellWidth = 350;
- int minShellHeight= 200;
- //ensure this is large enough, increase it if its not
- int newShellWidth = currentShellWidth > minShellWidth ? currentShellWidth : minShellWidth;
- int newShellHeight = currentShellHeight > minShellHeight ? currentShellHeight : minShellHeight;
-
- //set the final size and centre the dialog within the app window
- shell.setBounds((appWidth - newShellWidth)/2 + appLocX, (appHeight - newShellHeight)/2 + appLocY, newShellWidth, newShellHeight);
-
- shell.open();
- _window.getShell().setEnabled(false);
-
- while (!shell.isDisposed())
- {
- if (!display.readAndDispatch())
- {
- display.sleep();
- }
- }
-
- // enable the main shell
- _window.getShell().setEnabled(true);
- _window.getShell().open();
- }
-
- // Creates the SWT widgets in the popup shell, to enter username and password.
- // Adds listeners to the widgets to take appropriate action
- private void createWidgets(final Shell shell)
- {
- Composite composite = new Composite(shell, SWT.NONE);
- composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
- GridLayout layout = new GridLayout(2, false);
- layout.horizontalSpacing = 10;
- layout.verticalSpacing = 10;
- layout.marginHeight = 20;
- layout.marginWidth = 20;
- composite.setLayout(layout);
-
- Label user = new Label(composite, SWT.NONE);
- user.setText(USERNAME);
- user.setLayoutData(new GridData(SWT.TRAIL, SWT.TOP, false, false));
-
- final Text textUser = new Text(composite, SWT.BORDER);
- textUser.setText("");
- textUser.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
- // Put cursor on this field
- textUser.setFocus();
-
- Label password = new Label(composite, SWT.NONE);
- password.setText(PASSWORD);
- password.setLayoutData(new GridData(SWT.TRAIL, SWT.TOP, false, false));
-
- final Text textPwd = new Text(composite, SWT.BORDER | SWT.SINGLE | SWT.PASSWORD);
- textPwd.setText("");
- textPwd.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
-
- //Get the text widgets
- Control[] widgets = composite.getChildren();
- for (int i=0; i < widgets.length; i++)
- {
- widgets[i].addKeyListener(new KeyAdapter()
- {
- public void keyPressed(KeyEvent event)
- {
- if (event.character == SWT.ESC)
- {
- //Escape key acts as cancel on all widgets
- shell.dispose();
- }
- }
- });
- }
-
- Composite buttonsComposite = new Composite(composite, SWT.NONE);
- buttonsComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 2, 1));
- buttonsComposite.setLayout(new GridLayout(2, true));
-
- final Button connectButton = new Button(buttonsComposite, SWT.PUSH | SWT.CENTER);
- connectButton.setText(Constants.BUTTON_CONNECT);
- GridData gridData = new GridData (SWT.TRAIL, SWT.BOTTOM, true, true);
- gridData.widthHint = 100;
- connectButton.setLayoutData(gridData);
- connectButton.setFont(ApplicationRegistry.getFont(Constants.FONT_BUTTON));
- connectButton.addSelectionListener(new SelectionAdapter(){
- public void widgetSelected(SelectionEvent event)
- {
- _user = textUser.getText();
- if ((_user == null) || (_user.trim().length() == 0))
- {
- ViewUtility.popupInfoMessage(_title, INFO_USERNAME);
- textUser.setText("");
- textUser.setFocus();
- return;
- }
-
- _password = textPwd.getText();
- if (_password == null)
- {
- ViewUtility.popupInfoMessage(_title, INFO_PASSWORD);
- textPwd.setText("");
- textPwd.setFocus();
- return;
- }
-
- _connect = true;
- shell.dispose();
- }
- });
-
- final Button cancelButton = new Button(buttonsComposite, SWT.PUSH);
- cancelButton.setText(Constants.BUTTON_CANCEL);
- gridData = new GridData (SWT.LEAD, SWT.BOTTOM, true, true);
- gridData.widthHint = 100;
- cancelButton.setLayoutData(gridData);
- cancelButton.setFont(ApplicationRegistry.getFont(Constants.FONT_BUTTON));
- cancelButton.addSelectionListener(new SelectionAdapter(){
- public void widgetSelected(SelectionEvent event)
- {
- shell.dispose();
- }
- });
-
- //Get the ok/cancel button widgets and add a new key listener
- widgets = buttonsComposite.getChildren();
- for (int i=0; i < widgets.length; i++)
- {
- widgets[i].addKeyListener(new KeyAdapter()
- {
- public void keyPressed(KeyEvent event)
- {
- if (event.character == SWT.ESC)
- {
- //Escape key acts as cancel on all widgets
- shell.dispose();
- }
- }
- });
- }
-
- shell.setDefaultButton(connectButton);
- }
-
-}
diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/actions/Refresh.java b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/actions/Refresh.java
deleted file mode 100644
index f9ea900c3a..0000000000
--- a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/actions/Refresh.java
+++ /dev/null
@@ -1,54 +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.actions;
-
-import org.eclipse.jface.action.IAction;
-import org.eclipse.ui.IWorkbenchWindowActionDelegate;
-
-import org.apache.qpid.management.ui.jmx.MBeanUtility;
-import org.apache.qpid.management.ui.views.MBeanView;
-import org.apache.qpid.management.ui.views.NavigationView;
-
-/**
- * This action refreshes both the views -Navigation and MBeanView
- * @author Bhupendra Bhardwaj
- */
-public class Refresh extends AbstractAction implements IWorkbenchWindowActionDelegate
-{
- public void run(IAction action)
- {
- if(_window != null)
- {
- NavigationView view = (NavigationView)_window.getActivePage().findView(NavigationView.ID);
- view.refresh();
-
- MBeanView mbeanview = (MBeanView)_window.getActivePage().findView(MBeanView.ID);
- try
- {
- mbeanview.refresh();
- }
- catch (Exception ex)
- {
- MBeanUtility.handleException(ex);
- }
- }
- }
-}
diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/actions/RemoveServer.java b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/actions/RemoveServer.java
deleted file mode 100644
index 82766f063b..0000000000
--- a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/actions/RemoveServer.java
+++ /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.
- *
- */
-package org.apache.qpid.management.ui.actions;
-
-import org.eclipse.jface.action.IAction;
-import org.eclipse.ui.IWorkbenchWindowActionDelegate;
-
-import org.apache.qpid.management.ui.exceptions.InfoRequiredException;
-import org.apache.qpid.management.ui.views.NavigationView;
-import org.apache.qpid.management.ui.views.ViewUtility;
-
-public class RemoveServer extends AbstractAction implements IWorkbenchWindowActionDelegate
-{
- public void run(IAction action)
- {
- if(_window != null)
- {
- NavigationView view = (NavigationView)_window.getActivePage().findView(NavigationView.ID);
- try
- {
- view.removeServer();
- }
- catch(InfoRequiredException ex)
- {
- ViewUtility.popupInfoMessage("Remove Qpid server", ex.getMessage());
- }
- catch(Exception ex)
- {
- handleException(ex, "Server could not be removed", null);
- }
- }
- }
-}
diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/actions/VersionAction.java b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/actions/VersionAction.java
deleted file mode 100644
index 98d89478d1..0000000000
--- a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/actions/VersionAction.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.management.ui.actions;
-
-import org.eclipse.jface.action.Action;
-import org.eclipse.jface.dialogs.MessageDialog;
-import org.eclipse.ui.IWorkbenchWindow;
-
-import org.apache.qpid.management.ui.Constants;
-import org.apache.qpid.management.ui.jmx.MBeanUtility;
-
-import java.io.InputStream;
-import java.util.Properties;
-
-public class VersionAction extends Action
-{
- private IWorkbenchWindow _window;
- public static final String VERSION_RESOURCE = "qpidversion.properties";
-
- public static final String PRODUCT_NAME_PROPERTY = "qpid.name";
- public static final String RELEASE_VERSION_PROPERTY = "qpid.version";
- public static final String BUILD_VERSION_PROPERTY = "qpid.svnversion";
-
- private static final String DEFAULT = "unknown";
- private static String _releaseVersion;
- private static String _buildVersion;
- private static String _text;
-
- static
- {
- Properties props = new Properties();
- try
- {
- InputStream propertyStream = VersionAction.class.getClassLoader().getResourceAsStream(VERSION_RESOURCE);
- if (propertyStream != null)
- {
- props.load(propertyStream);
- _releaseVersion = readPropertyValue(props, RELEASE_VERSION_PROPERTY);
- _buildVersion = readPropertyValue(props, BUILD_VERSION_PROPERTY);
- _text = "Build Version : " + _buildVersion + "\n" +
- "Release Version : " + _releaseVersion;
- }
- else
- {
- _text = "Build Version : \n" +
- "Release Version : ";
- }
- }
- catch (Exception ex)
- {
- MBeanUtility.printStackTrace(ex);
- }
- }
-
- public VersionAction(IWorkbenchWindow window)
- {
- _window = window;
- setText("About " + Constants.APPLICATION_NAME);
- setId("qpidmc.about");
- setActionDefinitionId("qpidmc.about");
- }
-
- private static String readPropertyValue(Properties props, String propertyName)
- {
- String retVal = (String) props.get(propertyName);
- if (retVal == null)
- {
- retVal = DEFAULT;
- }
- return retVal;
- }
-
- public void run()
- {
- MessageDialog.openInformation(_window.getShell(), Constants.APPLICATION_NAME, _text);
- }
-}
diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/jmx/ClientListener.java b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/jmx/ClientListener.java
deleted file mode 100644
index c6cf3e82eb..0000000000
--- a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/jmx/ClientListener.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.management.ui.jmx;
-
-import org.apache.qpid.management.ui.ApplicationRegistry;
-import org.apache.qpid.management.ui.ManagedServer;
-
-import javax.management.MBeanServerNotification;
-import javax.management.Notification;
-import javax.management.NotificationListener;
-import javax.management.ObjectName;
-import javax.management.remote.JMXConnectionNotification;
-
-
-public class ClientListener implements NotificationListener
-{
- protected ManagedServer server = null;
- protected JMXServerRegistry serverRegistry = null;
-
- public ClientListener(ManagedServer server)
- {
- this.server = server;
- serverRegistry = (JMXServerRegistry)ApplicationRegistry.getServerRegistry(server);
- }
-
- public void handleNotification(Notification notification, Object handback)
- {
- String type = notification.getType();
-
- if(notification instanceof MBeanServerNotification)
- {
- ObjectName objName = ((MBeanServerNotification)notification).getMBeanName();
-
- if (MBeanServerNotification.REGISTRATION_NOTIFICATION.equals(type))
- {
- getServerRegistry().registerManagedObject(objName);
- }
- else if (MBeanServerNotification.UNREGISTRATION_NOTIFICATION.equals(type))
- {
- getServerRegistry().unregisterManagedObject(objName);
- }
- }
- else if (JMXConnectionNotification.FAILED.equals(type))
- {
- ApplicationRegistry.serverConnectionClosedRemotely(server);
- MBeanUtility.printOutput("JMX Connection to " + server.getName() + " failed.");
- }
- else if (JMXConnectionNotification.CLOSED.equals(type))
- {
- ApplicationRegistry.serverConnectionClosedRemotely(server);
- MBeanUtility.printOutput("JMX Connection to " + server.getName() + " was closed.");
- }
- }
-
- protected JMXServerRegistry getServerRegistry()
- {
- if (serverRegistry == null)
- {
- serverRegistry = (JMXServerRegistry)ApplicationRegistry.getServerRegistry(server);
- }
-
- return serverRegistry;
- }
- public ManagedServer getServer()
- {
- return server;
- }
-}
diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/jmx/ClientNotificationListener.java b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/jmx/ClientNotificationListener.java
deleted file mode 100644
index d5c8709b56..0000000000
--- a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/jmx/ClientNotificationListener.java
+++ /dev/null
@@ -1,40 +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.jmx;
-
-import org.apache.qpid.management.ui.ManagedServer;
-
-import javax.management.Notification;
-import javax.management.ObjectName;
-
-public class ClientNotificationListener extends ClientListener
-{
- public ClientNotificationListener(ManagedServer server)
- {
- super(server);
- }
-
- public void handleNotification(Notification notification, Object handback)
- {
- ObjectName objName = (ObjectName)notification.getSource();
- getServerRegistry().addNotification(objName, notification);
- }
-}
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
deleted file mode 100644
index f83b201011..0000000000
--- a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/jmx/JMXManagedObject.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.management.ui.jmx;
-
-import org.apache.qpid.management.ui.ManagedBean;
-
-import javax.management.ObjectName;
-import java.util.HashMap;
-import java.util.Map;
-
-
-public class JMXManagedObject extends ManagedBean
-{
- private ObjectName _objName;
-
- 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);
- }
-
- public ObjectName getObjectName()
- {
- return _objName;
- }
-}
diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/jmx/JMXServerRegistry.java b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/jmx/JMXServerRegistry.java
deleted file mode 100644
index 5df161823e..0000000000
--- a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/jmx/JMXServerRegistry.java
+++ /dev/null
@@ -1,619 +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.jmx;
-
-import org.apache.qpid.management.common.JMXConnnectionFactory;
-import org.apache.qpid.management.ui.ApplicationRegistry;
-import org.apache.qpid.management.ui.ManagedBean;
-import org.apache.qpid.management.ui.ManagedServer;
-import org.apache.qpid.management.ui.ServerRegistry;
-import org.apache.qpid.management.ui.model.ManagedAttributeModel;
-import org.apache.qpid.management.ui.model.NotificationInfoModel;
-import org.apache.qpid.management.ui.model.NotificationObject;
-import org.apache.qpid.management.ui.model.OperationDataModel;
-
-import static org.apache.qpid.management.ui.Constants.ALL;
-
-import javax.management.MBeanInfo;
-import javax.management.MBeanServerConnection;
-import javax.management.Notification;
-import javax.management.ObjectName;
-import javax.management.remote.JMXConnector;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.List;
-import java.util.concurrent.CopyOnWriteArrayList;
-
-
-public class JMXServerRegistry extends ServerRegistry
-{
- private ObjectName _serverObjectName = null;
- private JMXConnector _jmxc = null;
- private MBeanServerConnection _mbsc = null;
- private String _securityMechanism = null;
-
- private List<String> _usersList;
- // When an mbean gets removed from mbean server, then the notification listener
- // will add that mbean in this list.
- private List<ManagedBean> _mbeansToBeRemoved = new ArrayList<ManagedBean>();
-
- // Map containing all managed beans and mapped with unique mbean name
- private HashMap<String, ManagedBean> _mbeansMap = new HashMap<String, ManagedBean>();
- // Map containing MBeanInfo for all mbeans and mapped with unique mbean name
- private HashMap<String, MBeanInfo> _mbeanInfoMap = new HashMap<String, MBeanInfo>();
- // Map containing attribute model for all mbeans and mapped with unique mbean name
- private HashMap<String, ManagedAttributeModel> _attributeModelMap = new HashMap<String, ManagedAttributeModel>();
- // Map containing operation model for all mbeans and mapped with unique mbean name
- private HashMap<String, OperationDataModel> _operationModelMap = new HashMap<String, OperationDataModel>();
- // Map containing NotificationInfo for all mbeans and mapped with unique mbean name
- private HashMap<String, List<NotificationInfoModel>> _notificationInfoMap = new HashMap<String, List<NotificationInfoModel>>();
- // Map containing all notifications sent for all mbeans, which are registered for notification
- private HashMap<String, List<NotificationObject>> _notificationsMap = new HashMap<String, List<NotificationObject>>();
- // For mbeans which have subscribed for a notification type
- // mbean unique name mapped with notification map. Notification map contains list of notification type
- // mapped with notification name. Notification type list contains those notification types,
- // which are subscribed for notification.
- private HashMap<String, HashMap<String, List<String>>> _subscribedNotificationMap = new HashMap<String, HashMap<String, List<String>>>();
-
- // listener for registration or unregistratioj of mbeans on mbean server
- private ClientNotificationListener _notificationListener = null;
- // listener for server connection. Receives notification if server connection goes down
- private ClientListener _clientListener = null;
-
- public JMXServerRegistry(ManagedServer server) throws Exception
- {
- super(server);
-
- _jmxc = JMXConnnectionFactory.getJMXConnection(
- ApplicationRegistry.timeout, server.getHost(),
- server.getPort(), server.getUser(), server.getPassword());
-
- _mbsc = _jmxc.getMBeanServerConnection();
-
- _clientListener = new ClientListener(server);
- _notificationListener = new ClientNotificationListener(server);
-
- _jmxc.addConnectionNotificationListener(_clientListener, null, null);
- _serverObjectName = new ObjectName("JMImplementation:type=MBeanServerDelegate");
- _mbsc.addNotificationListener(_serverObjectName, _clientListener, null, null);
-
- }
-
- public MBeanServerConnection getServerConnection()
- {
- return _mbsc;
- }
-
-
- public String getSecurityMechanism()
- {
- return _securityMechanism;
- }
-
- /**
- * removes all listeners from the mbean server. This is required when user
- * disconnects the Qpid server connection
- */
- public void closeServerConnection() throws IOException
- {
- if(isServerConnectionClosed())
- {
- //connection was already closed
- return;
- }
-
- try
- {
- //remove the listener from the JMXConnector
- if (_jmxc != null && _clientListener != null)
- {
- _jmxc.removeConnectionNotificationListener(_clientListener);
- }
- }
- catch (Exception e)
- {
- //ignore
- }
-
- try
- {
- //remove the listener from the MBeanServerDelegate MBean
- if (_mbsc != null && _clientListener != null)
- {
- _mbsc.removeNotificationListener(_serverObjectName, _clientListener);
- }
- }
- catch (Exception e)
- {
- //ignore
- }
-
- if (_mbsc != null && _clientListener != null)
- {
- //remove any listeners from the Qpid MBeans
- for (String mbeanName : _subscribedNotificationMap.keySet())
- {
- try
- {
- _mbsc.removeNotificationListener(new ObjectName(mbeanName), _notificationListener);
- }
- catch (Exception e)
- {
- //ignore
- }
- }
- }
-
- //close the JMXConnector
- if (_jmxc != null)
- {
- _jmxc.close();
- }
-
- serverConnectionClosed();
- }
-
- public ManagedBean getManagedObject(String uniqueName)
- {
- return _mbeansMap.get(uniqueName);
- }
-
- public void addManagedObject(ManagedBean mbean)
- {
- if (mbean.isQueue())
- {
- addQueueMBean(mbean);
- }
- else if (mbean.isExchange())
- {
- addExchangeMBean(mbean);
- }
- else if (mbean.isConnection())
- {
- addConnectionMBean(mbean);
- }
- else if (mbean.isVirtualHostManager())
- {
- addVirtualHostManagerMBean(mbean);
- }
-
- addVirtualHost(mbean.getVirtualHostName());
- _mbeansMap.put(mbean.getUniqueName(), mbean);
- }
-
- public void removeManagedObject(ManagedBean mbean)
- {
- if (mbean == null)
- {
- return;
- }
-
- _mbeansMap.remove(mbean.getUniqueName());
-
- if (mbean.isQueue())
- {
- removeQueueMBean(mbean);
- }
- else if (mbean.isExchange())
- {
- removeExchangeMBean(mbean);
- }
- else if (mbean.isConnection())
- {
- removeConnectionMBean(mbean);
- }
- else if (mbean.isVirtualHostManager())
- {
- removeVirtualHostManagerMBean(mbean);
- }
- }
-
- public void putMBeanInfo(ManagedBean mbean, MBeanInfo mbeanInfo)
- {
- _mbeanInfoMap.put(mbean.getUniqueName(), mbeanInfo);
- }
- public MBeanInfo getMBeanInfo(ManagedBean mbean)
- {
- return _mbeanInfoMap.get(mbean.getUniqueName());
- }
-
- public List<ManagedBean> getMBeans()
- {
- return new ArrayList<ManagedBean>(_mbeansMap.values());
- }
-
- public void setNotificationInfo(ManagedBean mbean, List<NotificationInfoModel>value)
- {
- _notificationInfoMap.put(mbean.getUniqueName(), value);
- }
-
- public List<NotificationInfoModel> getNotificationInfo(ManagedBean mbean)
- {
- return _notificationInfoMap.get(mbean.getUniqueName());
- }
-
- public void addNotification(ObjectName objName, Notification notification)
- {
- List<NotificationObject> list = _notificationsMap.get(objName.toString());
- NotificationObject obj = new NotificationObject(notification.getSequenceNumber(),
- new Date(notification.getTimeStamp()),
- notification.getMessage(),
- notification.getSource(),
- notification.getType());
-
- if (list == null)
- {
- list = new ArrayList<NotificationObject>();
- _notificationsMap.put(objName.toString(), list);
- }
-
- list.add(obj);
- }
-
- /**
- * Returns all the notification objects for a given mbean. If mbean is null, it returns
- * notification objects for all the mbeans.
- */
- public List<NotificationObject> getNotifications(ManagedBean mbean)
- {
- if (mbean == null)
- {
- List<NotificationObject> totalList = new ArrayList<NotificationObject>();
- for (List<NotificationObject> list : _notificationsMap.values())
- {
- totalList.addAll(list);
- }
- return totalList;
- }
- else
- {
- return _notificationsMap.get(mbean.getUniqueName());
- }
- }
-
- public List<NotificationObject> getNotifications(String virtualhost)
- {
- List<NotificationObject> vhostNotificationsList = new ArrayList<NotificationObject>();
-
- //iterate over all the notification lists for mbeans with subscribed notifications
- for (List<NotificationObject> list : _notificationsMap.values())
- {
- if(list == null || list.isEmpty())
- {
- continue;
- }
-
- //Check the source vhost of the first notification
- NotificationObject notification = list.get(0);
-
- if (notification != null)
- {
- String sourceVhost = notification.getSourceVirtualHost();
- if(sourceVhost != null)
- {
- if(sourceVhost.equalsIgnoreCase(virtualhost))
- {
- //If it matches, add the entire list as they are from the same vhost (same source mbean)
- vhostNotificationsList.addAll(list);
- }
- }
- }
- }
-
- return vhostNotificationsList;
- }
-
- public void clearNotifications(ManagedBean mbean, List<NotificationObject> list)
- {
- if (mbean == null)
- {
- if (list == null || list.isEmpty())
- {
- // All notifications of all mbeans to be cleared
- _notificationsMap.clear();
- }
- else
- {
- // Clear the selected notifications
- for (NotificationObject obj : list)
- {
- mbean = _mbeansMap.get(obj.getSource().toString());
- List<NotificationObject> nList = _notificationsMap.get(mbean.getUniqueName());
- if (nList != null && !nList.isEmpty())
- {
- nList.remove(obj);
- }
- }
- }
- }
- else
- {
- if (list == null || list.isEmpty())
- {
- // All notifications of this mbean to be cleared
- List<NotificationObject> nList = _notificationsMap.get(mbean.getUniqueName());
- if (nList != null && !nList.isEmpty())
- {
- nList.clear();
- }
- }
- else
- {
- // Clear the selected notifications
- for (NotificationObject obj : list)
- {
- List<NotificationObject> nList = _notificationsMap.get(mbean.getUniqueName());
- if (nList != null && !nList.isEmpty())
- {
- nList.remove(obj);
- }
- }
- }
- }
- }
-
-
-
- /**
- * Adds notification name and type to the map. The map contains all the notification names,
- * subscribed for an mbean.
- * @param mbean
- * @param name
- * @param type
- */
- public void addNotificationListener(ManagedBean mbean, String name, String type)
- {
- // Get the subscribed notifications map for given mbean. If map is null then create a new one.
- HashMap<String, List<String>> map = _subscribedNotificationMap.get(mbean.getUniqueName());
- if (map == null)
- {
- map = new HashMap<String, List<String>>();
- _subscribedNotificationMap.put(mbean.getUniqueName(),map);
- }
-
- // Get the list of notification types for given notification name. If null, then create a new list.
- List<String> list = map.get(name);
- if (list == null)
- {
- list = new ArrayList<String>();
- map.put(name, list);
- }
- // Now add the notification type to the list
- if (ALL.equals(type))
- {
- List<NotificationInfoModel> infoList = _notificationInfoMap.get(mbean.getUniqueName());
- for (NotificationInfoModel model : infoList)
- {
- if (model.getName().equals(name))
- {
- String[] types = model.getTypes();
- for (int i = 0; i < types.length; i++)
- {
- list.add(types[i]);
- }
- }
- }
- }
- else
- {
- list.add(type);
- }
-
- //System.out.println("Subscribed for notification :" + mbean.getUniqueName());
- }
-
- /**
- * Checks if the given notification name and type are subscribed for the mbean.
- */
- public boolean hasSubscribedForNotifications(ManagedBean mbean, String name, String type)
- {
- if (_subscribedNotificationMap.containsKey(mbean.getUniqueName()))
- {
- HashMap<String, List<String>> map = _subscribedNotificationMap.get(mbean.getUniqueName());
- if (map.containsKey(name))
- {
- if (map.get(name).contains(type))
- {
- return true;
- }
- }
- }
- return false;
- }
-
- /**
- * Clears the notification name and type information from the subscribed notifications map
- * and removes the listener from mbeanserver connection
- * @param mbean
- * @param name
- * @param type
- * @throws Exception
- */
- public void removeNotificationListener(ManagedBean mbean, String name, String type) throws Exception
- {
- //System.out.println("Removed notification listener :" + mbean.getUniqueName() + name +type);
- if (_subscribedNotificationMap.containsKey(mbean.getUniqueName()))
- {
- // get the notifications map. This map contains the notification name mapped with the notification types
- HashMap<String, List<String>> map = _subscribedNotificationMap.get(mbean.getUniqueName());
- if (map.containsKey(name))
- {
- if (ALL.equals(type))
- {
- map.remove(name);
- }
- else if (type != null)
- {
- map.get(name).remove(type);
- if (map.get(name).isEmpty())
- {
- map.remove(name);
- }
- }
- }
- if (map.size() == 0)
- {
- _subscribedNotificationMap.remove(mbean.getUniqueName());
- }
-
- JMXManagedObject jmxbean = (JMXManagedObject)mbean;
- _mbsc.removeNotificationListener(jmxbean.getObjectName(), _notificationListener);
- }
- }
-
- /**
- * When the mbean registration request is received from the mbean server, then the client listener
- * can use this method. It will add the mbean to a list, which will be used to add the mbean to
- * the registry and gui
- * @param objName
- */
- public void registerManagedObject(ObjectName objName)
- {
- JMXManagedObject managedObject = new JMXManagedObject(objName);
- managedObject.setServer(getManagedServer());
- addManagedObject(managedObject);
- }
-
- /**
- * When mbean unregistration notification is received from the mbean server, then client listener
- * can invoke this method. It will add the mbean to the list of mbeans to be removed from registry
- * @param objName
- */
- public void unregisterManagedObject(ObjectName objName)
- {
- ManagedBean mbean = _mbeansMap.get(objName.toString());
- // Check if mbean was not available in the map. It can happen if mbean unregistration
- // notification is received and the mbean is not added in the map.
- if (mbean != null)
- {
- removeManagedObject(mbean);
- _mbeansToBeRemoved.add(mbean);
- }
- }
-
- public List<ManagedBean> getObjectsToBeRemoved()
- {
- if (_mbeansToBeRemoved.isEmpty())
- {
- return null;
- }
- else
- {
- List<ManagedBean> list = new CopyOnWriteArrayList<ManagedBean>(_mbeansToBeRemoved);
- _mbeansToBeRemoved.clear();
- return list;
- }
- }
-
- public void setAttributeModel(ManagedBean mbean, ManagedAttributeModel value)
- {
- _attributeModelMap.put(mbean.getUniqueName(), value);
- }
-
- public ManagedAttributeModel getAttributeModel(ManagedBean mbean)
- {
- return _attributeModelMap.get(mbean.getUniqueName());
- }
-
- public void setOperationModel(ManagedBean mbean, OperationDataModel value)
- {
- _operationModelMap.put(mbean.getUniqueName(), value);
- }
-
- public OperationDataModel getOperationModel(ManagedBean mbean)
- {
- return _operationModelMap.get(mbean.getUniqueName());
- }
-
- public List<String> getQueueNames(String virtualHostName)
- {
- List<ManagedBean> list = getQueues(virtualHostName);
- if (list == null)
- {
- return null;
- }
-
- List<String> queueNames = new ArrayList<String>();
- for (ManagedBean mbean : list)
- {
- queueNames.add(mbean.getName());
- }
- return queueNames;
- }
-
- public String[] getExchangeNames(String virtualHostName)
- {
- List<ManagedBean> list = getExchanges(virtualHostName);
- if (list == null)
- {
- return null;
- }
-
- String[] exchanges = new String[list.size()];
- int i = 0;
- for (ManagedBean mbean : list)
- {
- exchanges[i++] = mbean.getName();
- }
- return exchanges;
- }
-
- public String[] getConnectionNames(String virtualHostName)
- {
- List<ManagedBean> list = getExchanges(virtualHostName);
- if (list == null)
- {
- return null;
- }
-
- String[] connections = new String[list.size()];
- int i = 0;
- for (ManagedBean mbean : list)
- {
- connections[i++] = mbean.getName();
- }
- return connections;
- }
-
- public void setUserList(List<String> list)
- {
- _usersList = list;
- Collections.sort(_usersList);
- }
-
- public List<String> getUsernames()
- {
- return _usersList;
- }
-
- public ClientNotificationListener getNotificationListener()
- {
- return _notificationListener;
- }
-
- public ClientListener getClientListener()
- {
- return _clientListener;
- }
-}
diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/jmx/MBeanUtility.java b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/jmx/MBeanUtility.java
deleted file mode 100644
index be7d488a15..0000000000
--- a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/jmx/MBeanUtility.java
+++ /dev/null
@@ -1,612 +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.jmx;
-
-import org.apache.qpid.management.common.mbeans.ServerInformation;
-import org.apache.qpid.management.ui.ApiVersion;
-import org.apache.qpid.management.ui.ApplicationRegistry;
-import org.apache.qpid.management.ui.Constants;
-import org.apache.qpid.management.ui.ManagedBean;
-import org.apache.qpid.management.ui.ManagedServer;
-import org.apache.qpid.management.ui.exceptions.ManagementConsoleException;
-import org.apache.qpid.management.ui.model.AttributeData;
-import org.apache.qpid.management.ui.model.ManagedAttributeModel;
-import org.apache.qpid.management.ui.model.NotificationInfoModel;
-import org.apache.qpid.management.ui.model.OperationData;
-import org.apache.qpid.management.ui.model.OperationDataModel;
-import org.apache.qpid.management.ui.model.ParameterData;
-import org.apache.qpid.management.ui.views.ViewUtility;
-
-import javax.management.*;
-import java.io.IOException;
-import java.math.BigInteger;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Set;
-
-/**
- * Utility class for all mbeanserver related operations. Keeps all JMX code out from view and model classes
- * @author Bhupendra Bhardwaj
- */
-public class MBeanUtility
-{
- public static final BigInteger MAX_LONG = BigInteger.valueOf(Long.MAX_VALUE);
- public static final BigInteger MAX_INT = BigInteger.valueOf(Integer.MAX_VALUE);
- /**
- * Retrieves the MBeanInfo from MBeanServer and stores in the application registry
- * @param mbean managed bean
- * @return MBeanInfo
- * @throws Exception, if server connection is null or if server throws Exception
- */
- public static MBeanInfo getMBeanInfo(ManagedBean mbean) throws Exception
- {
- ManagedServer server = mbean.getServer();
- JMXServerRegistry serverRegistry = (JMXServerRegistry)ApplicationRegistry.getServerRegistry(server);
-
- MBeanServerConnection mbsc = serverRegistry.getServerConnection();
- if (mbsc == null)
- {
- throw new ManagementConsoleException("Server connection is broken");
- }
-
- JMXManagedObject jmxbean = (JMXManagedObject)mbean;
- MBeanInfo mbeanInfo = mbsc.getMBeanInfo(jmxbean.getObjectName());
- serverRegistry.putMBeanInfo(mbean, mbeanInfo);
-
- // populate the server registry with attribute and operation info
- getAttributes(mbean);
- getOperations(mbean);
-
- return mbeanInfo;
- }
-
- /**
- * executes the MBean operation
- * @param mbean
- * @param opData
- * @return MBean operation return value
- * @throws Exception if server connection is broken or if operation execution fails on the mbean server
- */
- public static Object execute(ManagedBean mbean, OperationData opData) throws Exception
- {
- String opName = opData.getName();
- Object[] values = null;
- String[] signature = null;
-
- List<ParameterData> params = opData.getParameters();
- if (params != null && !params.isEmpty())
- {
- signature = new String[params.size()];;
- values = new Object[params.size()];
- for (int i = 0; i < params.size(); i++)
- {
- signature[i] = params.get(i).getType();
- values[i] = params.get(i).getValue();
- }
- }
-
- ManagedServer server = mbean.getServer();
- JMXServerRegistry serverRegistry = (JMXServerRegistry)ApplicationRegistry.getServerRegistry(server);
-
- MBeanServerConnection mbsc = serverRegistry.getServerConnection();
- if (mbsc == null)
- {
- throw new ManagementConsoleException("Server connection is broken");
- // TODO
- // try and get the connection again if it was disconnected
- }
- JMXManagedObject jmxbean = (JMXManagedObject)mbean;
- return mbsc.invoke(jmxbean.getObjectName(), opName, values, signature);
- }
-
- /**
- * @see MBeanUtility#handleException(ManagedBean, Exception)
- */
- public static void handleException(Exception ex)
- {
- handleException(null, ex);
- }
-
- /**
- * handels the exception received. Shows the exception to the user in best suitable way
- * @param mbean managed bean
- * @param ex Exception
- */
- public static void handleException(ManagedBean mbean, Throwable ex)
- {
- if (mbean == null)
- {
- ViewUtility.popupErrorMessage("Error", "Managed Object is null \n" + ex.toString());
- printStackTrace(ex);
- }
- else if (ex instanceof ReflectionException)
- {
- ViewUtility.popupErrorMessage(mbean.getInstanceName(), "Server has thrown error \n" + ex.toString());
- printStackTrace(ex);
- }
- else if (ex instanceof InstanceNotFoundException)
- {
- ViewUtility.popupErrorMessage(mbean.getInstanceName(), "Managed Object Not Found \n" + ex.toString());
- printStackTrace(ex);
- }
- else if (ex instanceof MBeanException)
- {
- String cause = ((MBeanException)ex).getTargetException().getMessage();
- if (cause == null)
- {
- cause = ex.toString();
- }
- ViewUtility.popupInfoMessage(mbean.getInstanceName(), cause);
- }
- else if (ex instanceof JMException)
- {
- ViewUtility.popupErrorMessage(mbean.getInstanceName(), "Management Exception occured \n" + ex.toString());
- }
- else if (ex instanceof ManagementConsoleException)
- {
- ViewUtility.popupErrorMessage(mbean.getInstanceName(), ex.getMessage());
- }
- else if (ex instanceof SecurityException)
- {
- ViewUtility.popupErrorMessage(mbean.getInstanceName(), ex.getMessage());
- }
- else
- {
- if (ex.getCause() != null)
- {
- handleException(mbean, ex.getCause());
- }
- else
- {
- String msg = ex.getMessage();
- if (msg == null)
- {
- msg = ex.toString();
- }
- ViewUtility.popupErrorMessage(mbean.getInstanceName(), msg);
- printStackTrace(ex);
- }
- }
-
- }
-
- /**
- * Registers the notification listener with the MBeanServer
- * @param mbean managed bean
- * @param name notification name
- * @param type notification type
- * @throws Exception if server connection is broken or if listener could not be created
- */
- public static void createNotificationlistener(ManagedBean mbean, String name, String type)
- throws Exception
- {
- JMXManagedObject jmxbean = (JMXManagedObject)mbean;
- JMXServerRegistry serverRegistry = (JMXServerRegistry)ApplicationRegistry.getServerRegistry(mbean);
- serverRegistry.addNotificationListener(mbean, name, type);
- MBeanServerConnection mbsc = serverRegistry.getServerConnection();
-
- if (mbsc == null)
- {
- throw new ManagementConsoleException("Server connection is broken");
- }
- mbsc.addNotificationListener(jmxbean.getObjectName(), serverRegistry.getNotificationListener(), null, null);
- }
-
- public static void removeNotificationListener(ManagedBean mbean, String name, String type) throws Exception
- {
- JMXServerRegistry serverRegistry = (JMXServerRegistry)ApplicationRegistry.getServerRegistry(mbean);
- serverRegistry.removeNotificationListener(mbean, name, type);
- }
-
- /**
- * Checks if the server registry contains attribute information for this mbean. If not then it queries the
- * mbean server for complete mbean information, else it gets the latest value of the given attribute
- * from mbean server.
- * @return attribute data for the given mbean attribute
- */
- public static AttributeData getAttributeData(ManagedBean mbean, String attribute) throws Exception
- {
- JMXServerRegistry serverRegistry = (JMXServerRegistry)ApplicationRegistry.getServerRegistry(mbean);
- ManagedAttributeModel attributeModel = serverRegistry.getAttributeModel(mbean);
- if (attributeModel == null)
- {
- // If process is here, it means the mbeanInfo is not retrieved from mbean server even once for this mbean
- getMBeanInfo(mbean);
- }
- else
- {
- // refresh attribute value from mbean server
- refreshAttribute(mbean, attribute);
- }
- attributeModel = serverRegistry.getAttributeModel(mbean);
- return attributeModel.getAttribute(attribute);
- }
-
- /**
- * Retrieves the latest attribute value from mbean server for the given mbean attribute
- * and also sets that value in the attribute model in the server registry
- * @return latest attribute value for the given mbean attribute
- */
- public static Object refreshAttribute(ManagedBean mbean, String attribute) throws Exception
- {
- JMXServerRegistry serverRegistry = (JMXServerRegistry)ApplicationRegistry.getServerRegistry(mbean);
- MBeanServerConnection mbsc = serverRegistry.getServerConnection();
-
- if (mbsc == null)
- {
- throw new ManagementConsoleException("Server connection is broken");
- }
-
- Object value = mbsc.getAttribute(((JMXManagedObject)mbean).getObjectName(), attribute);
- // update the attribute data in server registry for this attribute
- ManagedAttributeModel attributeModel = serverRegistry.getAttributeModel(mbean);
- attributeModel.setAttributeValue(attribute, value);
- return value;
- }
-
-
- /**
- * Returns a List of Object arrays containing the requested attribute values (in the same sequence requested) for each queue in the virtualhost.
- * If a particular attribute cant be found or raises an mbean/reflection exception whilst being gathered its value is substituted with the String "-".
- */
- public static List<List<Object>> getQueueAttributes(List<ManagedBean> mbeans, String[] attributes)
- {
- List<List<Object>> results = new ArrayList<List<Object>>();
-
- MBeanServerConnection mbsc = null;
- if(mbeans.isEmpty())
- {
- return results;
- }
- else
- {
- ManagedBean mbean = mbeans.get(0);
- JMXServerRegistry serverRegistry = (JMXServerRegistry)ApplicationRegistry.getServerRegistry(mbean);
- mbsc = serverRegistry.getServerConnection();
- }
-
- if(mbsc == null)
- {
- return results;
- }
-
- for(ManagedBean mbean : mbeans)
- {
- HashMap<String,Object> tempResults = new HashMap<String,Object>();
-
- ObjectName objName = ((JMXManagedObject)mbean).getObjectName();
- try
- {
- AttributeList list = mbsc.getAttributes(objName, attributes);
-
- for (Attribute attr : list.toArray(new Attribute[0]))
- {
- tempResults.put(attr.getName(), attr.getValue());
- }
-
- List<Object> attributeValues = new ArrayList<Object>(attributes.length);
-
- for(int i = 0; i <attributes.length; i++)
- {
- if(tempResults.containsKey(attributes[i]))
- {
- attributeValues.add(tempResults.get(attributes[i]));
- }
- else
- {
- attributeValues.add("-");
- }
- }
-
- results.add(attributeValues);
- }
- catch (Exception ignore)
- {
- continue;
- }
- }
-
- return results;
- }
-
-
- /**
- * Retrieves the attribute values from MBeanSever and stores in the server registry.
- * @param mbean
- * @return the attribute model
- * @throws Exception if attributes can not be retrieved from MBeanServer
- */
- public static ManagedAttributeModel getAttributes(ManagedBean mbean) throws Exception
- {
- ObjectName objName = ((JMXManagedObject)mbean).getObjectName();
- String[] attributes = null;
- AttributeList list = null;
-
- JMXServerRegistry serverRegistry = (JMXServerRegistry)ApplicationRegistry.getServerRegistry(mbean);
- MBeanServerConnection mbsc = serverRegistry.getServerConnection();
- MBeanAttributeInfo[] attributesInfo = null;
- ManagedAttributeModel attributeModel = serverRegistry.getAttributeModel(mbean);
-
- if (attributeModel == null)
- {
- // If the process is here, then it means the attribute values are not retrieved from mbean server
- // even once for this mbean. Create attribute model, retrieve values from mbean server and
- // set the attribute model in server registry for this mbean
- attributeModel = new ManagedAttributeModel();
- attributesInfo = serverRegistry.getMBeanInfo(mbean).getAttributes();
- attributes = new String[attributesInfo.length];
- for (int i = 0; i< attributesInfo.length ; i++)
- {
- attributes[i] = attributesInfo[i].getName();
- attributeModel.setAttributeDescription(attributes[i], attributesInfo[i].getDescription());
- attributeModel.setAttributeWritable(attributes[i], attributesInfo[i].isWritable());
- attributeModel.setAttributeReadable(attributes[i], attributesInfo[i].isReadable());
- }
- }
- else
- {
- attributes = attributeModel.getAttributeNames().toArray(new String[0]);
- }
-
- if (attributes.length != 0)
- {
- list = mbsc.getAttributes(objName, attributes);
- for (Iterator itr = list.iterator(); itr.hasNext();)
- {
- Attribute attrib = (Attribute)itr.next();
- attributeModel.setAttributeValue(attrib.getName(), attrib.getValue());
- }
- }
-
- serverRegistry.setAttributeModel(mbean, attributeModel);
- return attributeModel;
- }
-
- /**
- * Updates the attribute value of an MBean
- * @param mbean
- * @param attribute
- * @param value
- * @throws Exception if MBeanServer throws exception in updating the attribute value
- */
- public static void updateAttribute(ManagedBean mbean, AttributeData attribute, String value) throws Exception
- {
- JMXManagedObject jmxbean = (JMXManagedObject)mbean;
- JMXServerRegistry serverRegistry = (JMXServerRegistry)ApplicationRegistry.getServerRegistry(mbean);
-
- MBeanServerConnection mbsc = serverRegistry.getServerConnection();
-
- Object newValue = value;
- if (attribute.getDataType().equals(Long.class.getName()))
- {
- if (MAX_LONG.compareTo(new BigInteger(value)) == -1)
- {
- throw new ManagementConsoleException("Entered value is too big for \"" +
- ViewUtility.getDisplayText(attribute.getName()) + "\"");
- }
- newValue = Long.parseLong(value);
- }
- else if (attribute.getDataType().equals(Integer.class.getName()))
- {
- if (MAX_INT.compareTo(new BigInteger(value)) == -1)
- {
- throw new ManagementConsoleException("Entered value is too big for " + attribute.getName());
- }
- newValue = Integer.parseInt(value);
- }
- else if (attribute.getDataType().equals(Boolean.class.getName()))
- {
- if (!value.equalsIgnoreCase("true") && !value.equalsIgnoreCase("false"))
- {
- throw new ManagementConsoleException("Entered value was not true or false");
- }
-
- newValue = Boolean.valueOf(value);
- }
-
- mbsc.setAttribute(jmxbean.getObjectName(), new Attribute(attribute.getName(), newValue));
- // Update the value in the registry, to avoid refreshing from mbsc
- ManagedAttributeModel attributeModel = serverRegistry.getAttributeModel(mbean);
- attributeModel.setAttributeValue(attribute.getName(), newValue);
- }
-
- /**
- * populates the operation data model in server registry for given mbean
- * @param mbean
- * @return operation data model
- */
- public static OperationDataModel getOperations(ManagedBean mbean)
- {
- JMXServerRegistry serverRegistry = (JMXServerRegistry)ApplicationRegistry.getServerRegistry(mbean);
- OperationDataModel dataModel = serverRegistry.getOperationModel(mbean);
- if (dataModel == null)
- {
- // Create operation model and set it in server registry for this mbean
- MBeanOperationInfo[] operationsInfo = serverRegistry.getMBeanInfo(mbean).getOperations();
- dataModel = new OperationDataModel();
-
- for (int i = 0; i < operationsInfo.length; i++)
- {
- dataModel.addOperation(operationsInfo[i]);
- }
-
- serverRegistry.setOperationModel(mbean, dataModel);
- }
- return dataModel;
- }
-
- /**
- * populates the notification in the server registry for given mbean
- * @param mbean
- * @return notification info model
- */
- public static NotificationInfoModel[] getNotificationInfo(ManagedBean mbean)
- {
- JMXServerRegistry serverRegistry = (JMXServerRegistry)ApplicationRegistry.getServerRegistry(mbean);
- MBeanNotificationInfo[] info = serverRegistry.getMBeanInfo(mbean).getNotifications();
-
- // Check if this mbean sends any notification
- if (info == null || info.length == 0)
- {
- return null;
- }
-
- // Create notification model if not already set in the server registry for this mbean
- List<NotificationInfoModel> list = serverRegistry.getNotificationInfo(mbean);
- if (list != null)
- {
- return list.toArray(new NotificationInfoModel[0]);
- }
- else
- {
- list = new ArrayList<NotificationInfoModel>();
- }
-
- for (int i = 0; i < info.length; i++)
- {
- list.add(new NotificationInfoModel(info[i].getName(), info[i].getDescription(), info[i].getNotifTypes()));
- }
-
- // Set the notification model in the server registry for this mbean
- serverRegistry.setNotificationInfo(mbean, list);
- return list.toArray(new NotificationInfoModel[0]);
- }
-
- /**
- * Retrieves all the MBeans from mbean server for a given domain
- * @return list of ManagedBeans
- */
- public static List<ManagedBean> getManagedObjectsForDomain(ManagedServer server, String domain) throws MalformedObjectNameException, NullPointerException, IOException
- {
- JMXServerRegistry serverRegistry = (JMXServerRegistry)ApplicationRegistry.getServerRegistry(server);
- return getManagedObjectsForDomain(server,serverRegistry, domain);
- }
-
- /**
- * Retrieves all the MBeans from mbean server for a given domain
- * @return list of ManagedBeans
- */
- public static List<ManagedBean> getManagedObjectsForDomain(ManagedServer server, JMXServerRegistry serverRegistry, String domain) throws MalformedObjectNameException, NullPointerException, IOException
- {
- List<ManagedBean> mbeans = new ArrayList<ManagedBean>();
-
- MBeanServerConnection mbsc = serverRegistry.getServerConnection();
- ObjectName objName = new ObjectName(domain + ":*");
- Set objectInstances = mbsc.queryMBeans(objName, null);
-
- for (Iterator itr = objectInstances.iterator(); itr.hasNext();)
- {
- ObjectInstance instance = (ObjectInstance)itr.next();
- ManagedBean obj = new JMXManagedObject(instance.getObjectName());
- mbeans.add(obj);
- }
-
- return mbeans;
- }
-
- /**
- * Classifies the management API version of the given server
- * @return list of ManagedBeans
- * @throws NullPointerException
- * @throws ManagementConsoleException
- * @throws MalformedObjectNameException
- * @throws IOException
- */
- public static void classifyManagementApiVersion(ManagedServer server, JMXServerRegistry serverRegistry)
- throws MalformedObjectNameException, NullPointerException, IOException
- {
- MBeanServerConnection mbsc = serverRegistry.getServerConnection();
-
- //Detect if the ServerInformation MBean is present, and use it to retrieve the API version.
- ObjectName objName = new ObjectName(server.getDomain() + ":type="+ ServerInformation.TYPE + ",*");
- Set<ObjectName> objectInstances = mbsc.queryNames(objName, null);
-
- if(objectInstances.size() != 0)
- {
- for (Iterator<ObjectName> itr = objectInstances.iterator(); itr.hasNext();)
- {
- ObjectName instance = (ObjectName)itr.next();
- ServerInformation simb = (ServerInformation)
- MBeanServerInvocationHandler.newProxyInstance(mbsc,
- instance, ServerInformation.class, false);
-
- int major = simb.getManagementApiMajorVersion();
- int minor = simb.getManagementApiMinorVersion();
-
- serverRegistry.setManagementApiVersion(new ApiVersion(major, minor));
- }
-
- return;
- }
-
- //ServerInformation mbean was not present, so this is a older pre-v1.3 API server.
-
- //Detect the value of the 'version' key property on the UserManagement MBean ObjectName.
- //If present, we have a v1.2 API server. If null, we have a v1.1 API server.
- ObjectName umMBeanObjectName = null;
- List<ManagedBean> mbeans = getManagedObjectsForDomain(server, serverRegistry, Constants.DEFAULT_DOMAIN);
- for(ManagedBean mbean: mbeans)
- {
- if("UserManagement".equalsIgnoreCase(mbean.getType()))
- {
- umMBeanObjectName = ((JMXManagedObject) mbean).getObjectName();
- break;
- }
- }
-
- if(umMBeanObjectName != null)
- {
- //UserManagement MBean was present, determine if it has a version key
- if(umMBeanObjectName.getKeyProperty("version") != null)
- {
- serverRegistry.setManagementApiVersion(new ApiVersion(1, 2));
- }
- else
- {
- //no version key,
- serverRegistry.setManagementApiVersion(new ApiVersion(1, 1));
- }
-
- return;
- }
-
- //UserManagement MBean was not present, connected to an old server: classify as v1.0 API
- serverRegistry.setManagementApiVersion(new ApiVersion(1, 0));
- }
-
- public static void printOutput(String statement)
- {
- if (ApplicationRegistry.debug)
- {
- System.out.println(statement);
- }
- }
-
- public static void printStackTrace(Throwable ex)
- {
- if (ApplicationRegistry.debug)
- {
- ex.printStackTrace();
- }
- }
-}
diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/model/AttributeData.java b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/model/AttributeData.java
deleted file mode 100644
index 36c67a6ae1..0000000000
--- a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/model/AttributeData.java
+++ /dev/null
@@ -1,100 +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.model;
-
-public class AttributeData
-{
- private String name = "";
- private String description = "";
- private String dataType = "";
- private Object value = "";
- private boolean readable = true;
- private boolean writable = false;
-
-
- public String getDataType()
- {
- return dataType;
- }
- public void setDataType(String dataType)
- {
- this.dataType = dataType;
- }
-
- public String getDescription()
- {
- return description;
- }
- public void setDescription(String description)
- {
- this.description = description;
- }
-
- public String getName()
- {
- return name;
- }
- public void setName(String name)
- {
- this.name = name;
- }
-
- public Object getValue()
- {
- return value;
- }
- public void setValue(Object value)
- {
- if (value != null)
- {
- this.value = value;
- }
- }
- public boolean isReadable()
- {
- return readable;
- }
- public void setReadable(boolean readable)
- {
- this.readable = readable;
- }
- public boolean isWritable()
- {
- return writable;
- }
- public void setWritable(boolean writable)
- {
- this.writable = writable;
- }
-
- public boolean isNumber()
- {
- if ("int".equals(dataType) || "java.lang.Integer".equals(dataType) ||
- "long".equals(dataType) || "java.lang.Long".equals(dataType) )
- {
- return true;
- }
- else
- {
- return false;
- }
- }
-}
diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/model/ManagedAttributeModel.java b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/model/ManagedAttributeModel.java
deleted file mode 100644
index 41a37bf428..0000000000
--- a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/model/ManagedAttributeModel.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.management.ui.model;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-
-public class ManagedAttributeModel
-{
- private HashMap<String, AttributeData> _attributeMap = new HashMap<String, AttributeData>();
-
- public void setAttributeValue(String name, Object value)
- {
- if (value == null)
- {
- return;
- }
-
- AttributeData data = null;
- String dataType = value.getClass().getName();
- if (_attributeMap.containsKey(name))
- {
- data = _attributeMap.get(name);
- data.setValue(value);
- }
- else
- {
- data = new AttributeData();
- data.setName(name);
- data.setValue(value);
- _attributeMap.put(name, data);
- }
- data.setDataType(dataType);
- }
-
-
- public void setAttributeDescription(String name, String value)
- {
- if (_attributeMap.containsKey(name))
- {
- _attributeMap.get(name).setDescription(value);
- }
- else
- {
- AttributeData data = new AttributeData();
- data.setName(name);
- data.setDescription(value);
- _attributeMap.put(name, data);
- }
- }
-
- public void setAttributeReadable(String name, boolean readable)
- {
- if (_attributeMap.containsKey(name))
- {
- _attributeMap.get(name).setReadable(readable);
- }
- else
- {
- AttributeData data = new AttributeData();
- data.setName(name);
- data.setReadable(readable);
- _attributeMap.put(name, data);
- }
- }
-
- public void setAttributeWritable(String name, boolean writable)
- {
- if (_attributeMap.containsKey(name))
- {
- _attributeMap.get(name).setWritable(writable);
- }
- else
- {
- AttributeData data = new AttributeData();
- data.setName(name);
- data.setWritable(writable);
- _attributeMap.put(name, data);
- }
- }
-
- public List<String> getAttributeNames()
- {
- return new ArrayList<String>(_attributeMap.keySet());
- }
-
- public AttributeData[] getAttributes()
- {
- return _attributeMap.values().toArray(new AttributeData[0]);
- }
-
- public AttributeData getAttribute(String name)
- {
- return _attributeMap.get(name);
- }
-
- public int getCount()
- {
- return _attributeMap.size();
- }
-}
diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/model/NotificationInfoModel.java b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/model/NotificationInfoModel.java
deleted file mode 100644
index 7cfc9e41c2..0000000000
--- a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/model/NotificationInfoModel.java
+++ /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.
- *
- */
-package org.apache.qpid.management.ui.model;
-
-public class NotificationInfoModel
-{
- private String name;
- private String description;
- private String[] types;
-
- public NotificationInfoModel(String name, String desc, String[] types)
- {
- this.name = name;
- this.description = desc;
- this.types = types;
- }
-
- public String getDescription()
- {
- return description;
- }
-
- public String getName()
- {
- return name;
- }
-
- public String[] getTypes()
- {
- return types;
- }
-
-}
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
deleted file mode 100644
index c5fd526f27..0000000000
--- a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/model/NotificationObject.java
+++ /dev/null
@@ -1,131 +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.model;
-
-import static org.apache.qpid.management.ui.Constants.VIRTUAL_HOST;
-
-import javax.management.ObjectName;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-import java.util.TimeZone;
-
-public class NotificationObject
-{
-
- private long _sequenceNo;
- private Date _timeStamp;
- private String _message;
- private Object _source;
- private String _type; // INFO, WARN, etc
- private static final SimpleDateFormat dateFormat = new SimpleDateFormat("hh:mm:ss dd/MM/yy z");
-
- public NotificationObject(long seqNo, Date timeStamp, String message, Object source, String type)
- {
- this._sequenceNo = seqNo;
- this._message = message;
- this._source = source;
- this._type = type;
- this._timeStamp = timeStamp;
- dateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
- }
-
- public Object getSource()
- {
- return _source;
- }
- public void setSource(Object _source)
- {
- this._source = _source;
- }
-
- public String getSourceName()
- {
- if (_source instanceof ObjectName)
- {
- return unquote(((ObjectName)_source).getKeyProperty("name"));
- }
-
- return null;
- }
-
- public String getSourceVirtualHost()
- {
- if (_source instanceof ObjectName)
- {
- return unquote(((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;
- }
- public void setMessage(String _message)
- {
- this._message = _message;
- }
- public long getSequenceNo()
- {
- return _sequenceNo;
- }
- public void setSequenceNo(long no)
- {
- _sequenceNo = no;
- }
- public String getTimeStamp()
- {
- return dateFormat.format(_timeStamp);
- }
- public void setTimeStamp(Date stamp)
- {
- _timeStamp = stamp;
- }
- public String getType()
- {
- return _type;
- }
- public void setType(String _type)
- {
- this._type = _type;
- }
-
-}
diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/model/OperationData.java b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/model/OperationData.java
deleted file mode 100644
index bf3b730b3e..0000000000
--- a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/model/OperationData.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.ui.model;
-
-import java.util.List;
-
-public class OperationData
-{
- private String _name;
- private String _description;
- private String _returnType;
- private int _impact;
- private List<ParameterData> _parameters;
-
- public OperationData(String value)
- {
- this._name = value;
- }
-
- public String getName()
- {
- return _name;
- }
-
- public String getDescription()
- {
- return _description;
- }
-
- public void setDescription(String description)
- {
- this._description = description;
- }
-
- public List<ParameterData> getParameters()
- {
- return _parameters;
- }
-
- public void setParameters(List<ParameterData> parameters)
- {
- this._parameters = parameters;
- }
-
- public int getImpact()
- {
- return _impact;
- }
-
- public void setImpact(int impact)
- {
- this._impact = impact;
- }
-
- public String getReturnType()
- {
- return _returnType;
- }
-
- public void setReturnType(String returnType)
- {
- this._returnType = returnType;
- }
-
- public boolean isReturnTypeBoolean()
- {
- return (_returnType.equals("boolean") || _returnType.equals("java.lang.Boolean"));
- }
-
- public boolean isReturnTypeVoid()
- {
- return (_returnType.equals("void") || _returnType.equals("java.lang.Void"));
- }
-
- public Object getParameterValue(String paramName)
- {
- if (_parameters == null)
- {
- return null;
- }
-
- for (int i = 0; i < _parameters.size(); i++)
- {
- if (paramName.equalsIgnoreCase(_parameters.get(i).getName()))
- {
- return _parameters.get(i).getValue();
- }
- }
-
- return null;
- }
-} \ No newline at end of file
diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/model/OperationDataModel.java b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/model/OperationDataModel.java
deleted file mode 100644
index 95f6d0c9b8..0000000000
--- a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/model/OperationDataModel.java
+++ /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.
- *
- */
-package org.apache.qpid.management.ui.model;
-
-import javax.management.MBeanOperationInfo;
-import javax.management.MBeanParameterInfo;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-
-public class OperationDataModel
-{
- private HashMap<String, OperationData> _operationMap = new HashMap<String, OperationData>();
-
- public void addOperation(MBeanOperationInfo opInfo)
- {
- OperationData opData = new OperationData(opInfo.getName());
- opData.setDescription(opInfo.getDescription());
- opData.setImpact(opInfo.getImpact());
- opData.setReturnType(opInfo.getReturnType());
-
- int parametersCount = opInfo.getSignature().length;
- if (parametersCount != 0)
- {
- List<ParameterData> paramList = new ArrayList<ParameterData>();
- for (int i = 0; i < parametersCount; i++)
- {
- MBeanParameterInfo paramInfo = opInfo.getSignature()[i];
- ParameterData param = new ParameterData(paramInfo.getName(), paramInfo.getDescription(),
- paramInfo.getType());
- paramList.add(param);
- }
- opData.setParameters(paramList);
- }
-
- _operationMap.put(opInfo.getName(), opData);
- }
-
- public OperationData getOperation(String name)
- {
- return _operationMap.get(name);
- }
-
- public List<OperationData> getOperations()
- {
- return new ArrayList<OperationData>(_operationMap.values());
- }
-
- public int getCount()
- {
- return _operationMap.size();
- }
-}
diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/model/ParameterData.java b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/model/ParameterData.java
deleted file mode 100644
index bf5301bf93..0000000000
--- a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/model/ParameterData.java
+++ /dev/null
@@ -1,103 +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.model;
-
-/**
- * Class representing an mbean operation parameter
- * @author Bhupendra Bhardwaj
- */
-public class ParameterData
-{
- private String _name;
- private String _description;
- private String _type;
- private Object _value;
-
- ParameterData(String name, String desc, String type)
- {
- this._name = name;
- this._description = desc;
- this._type = type;
- setDefaultValue();
- }
-
- public String getDescription()
- {
- return _description;
- }
-
- public String getName()
- {
- return _name;
- }
-
- public String getType()
- {
- return _type;
- }
-
- public Object getValue()
- {
- return _value;
- }
-
- public void setValueFromString(String strValue)
- {
- if ("int".equals(_type))
- {
- _value = Integer.parseInt(strValue);
- }
- else if (isBoolean())
- {
- _value = Boolean.valueOf(strValue);
- }
- else if ("long".equals(_type))
- {
- _value = Long.parseLong(strValue);
- }
- else
- {
- _value = strValue;
- }
- }
-
- public void setValue(Object value)
- {
- this._value = value;
- }
-
- public boolean isBoolean()
- {
- return (_type.equals("boolean") || _type.equals("java.lang.Boolean"));
- }
-
- public void setDefaultValue()
- {
- if (isBoolean())
- {
- _value = Boolean.valueOf("false");
- }
- else
- {
- _value = null;
- }
- }
-}
diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/AttributesTabControl.java b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/AttributesTabControl.java
deleted file mode 100644
index de356ddb13..0000000000
--- a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/AttributesTabControl.java
+++ /dev/null
@@ -1,937 +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;
-
-import org.eclipse.jface.viewers.IColorProvider;
-import org.eclipse.jface.viewers.IFontProvider;
-import org.eclipse.jface.viewers.ISelectionChangedListener;
-import org.eclipse.jface.viewers.IStructuredContentProvider;
-import org.eclipse.jface.viewers.IStructuredSelection;
-import org.eclipse.jface.viewers.ITableLabelProvider;
-import org.eclipse.jface.viewers.LabelProvider;
-import org.eclipse.jface.viewers.SelectionChangedEvent;
-import org.eclipse.jface.viewers.TableViewer;
-import org.eclipse.jface.viewers.Viewer;
-import org.eclipse.jface.viewers.ViewerSorter;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.events.DisposeEvent;
-import org.eclipse.swt.events.DisposeListener;
-import org.eclipse.swt.events.KeyEvent;
-import org.eclipse.swt.events.KeyListener;
-import org.eclipse.swt.events.MouseEvent;
-import org.eclipse.swt.events.MouseListener;
-import org.eclipse.swt.events.MouseMoveListener;
-import org.eclipse.swt.events.MouseTrackListener;
-import org.eclipse.swt.events.PaintEvent;
-import org.eclipse.swt.events.PaintListener;
-import org.eclipse.swt.events.SelectionAdapter;
-import org.eclipse.swt.events.SelectionEvent;
-import org.eclipse.swt.graphics.Color;
-import org.eclipse.swt.graphics.Font;
-import org.eclipse.swt.graphics.Image;
-import org.eclipse.swt.graphics.Point;
-import org.eclipse.swt.graphics.Rectangle;
-import org.eclipse.swt.layout.FillLayout;
-import org.eclipse.swt.layout.GridData;
-import org.eclipse.swt.layout.GridLayout;
-import org.eclipse.swt.widgets.Button;
-import org.eclipse.swt.widgets.Canvas;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Control;
-import org.eclipse.swt.widgets.Display;
-import org.eclipse.swt.widgets.Event;
-import org.eclipse.swt.widgets.Label;
-import org.eclipse.swt.widgets.Listener;
-import org.eclipse.swt.widgets.Shell;
-import org.eclipse.swt.widgets.TabFolder;
-import org.eclipse.swt.widgets.Table;
-import org.eclipse.swt.widgets.TableColumn;
-import org.eclipse.swt.widgets.TableItem;
-import org.eclipse.swt.widgets.Text;
-import org.eclipse.ui.forms.widgets.FormToolkit;
-import org.eclipse.ui.forms.widgets.ScrolledForm;
-
-import org.apache.qpid.management.ui.ApplicationRegistry;
-import org.apache.qpid.management.ui.ManagedBean;
-import org.apache.qpid.management.ui.jmx.MBeanUtility;
-import org.apache.qpid.management.ui.model.AttributeData;
-import org.apache.qpid.management.ui.model.ManagedAttributeModel;
-
-import static org.apache.qpid.management.ui.Constants.*;
-
-
-/**
- * Creates controller composite for the attribute's tab.
- * @author Bhupendra Bhardwaj
- */
-public class AttributesTabControl extends TabControl
-{
- private FormToolkit _toolkit;
- private ScrolledForm _form;
- private Table _table = null;
- private TableViewer _tableViewer = null;
- private int[] tableWidths = new int[] {275, 275};
-
- private Composite _tableComposite = null;
- private Composite _buttonsComposite = null;
-
- private DisposeListener tableDisposeListener = new DisposeListenerImpl();
- private final Image image;
- private Button _detailsButton = null;
- private Button _editButton = null;
- private Button _graphButton = null;
- private boolean disableEditing = false;
-
- private static final String MAX_VALUE = "MaxValue";
- private static final String GRAPH_VALUES = "GraphValues";
- private int GRAPH_WIDTH = 700;
- private int GRAPH_HEIGHT = 450;
- private int GRAPH_ITEM_GAP = 100;
- private int startX = 80;
- private int startY = 60;
-
- public AttributesTabControl(TabFolder tabFolder)
- {
- super(tabFolder);
- _toolkit = new FormToolkit(_tabFolder.getDisplay());
- _form = _toolkit.createScrolledForm(_tabFolder);
- GridLayout gridLayout = new GridLayout(2, false);
- gridLayout.marginWidth = 0;
- gridLayout.marginHeight = 0;
- _form.getBody().setLayout(gridLayout);
- _tableComposite = _toolkit.createComposite(_form.getBody());
- _tableComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
- _tableComposite.setLayout(new GridLayout());
- _buttonsComposite = _toolkit.createComposite(_form.getBody());
- _buttonsComposite.setLayoutData(new GridData(SWT.LEFT, SWT.TOP, false, true));
- _buttonsComposite.setLayout(new GridLayout());
-
- image = Display.getCurrent().getSystemImage(SWT.ICON_INFORMATION);
- createWidgets();
- }
-
- /**
- * @see TabControl#getControl()
- */
- public Control getControl()
- {
- return _form;
- }
-
- /**
- * Creates required widgets for Attribute's tab
- */
- protected void createWidgets()
- {
- createTable();
- createTableViewer();
- createButtons();
- addTableListeners();
- }
-
- /**
- * Creates table for listing the MBean attributes
- */
- private void createTable()
- {
- _table = _toolkit.createTable(_tableComposite, SWT.FULL_SELECTION);
- GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
- _table.setLayoutData(gridData);
-
- for (int i = 0; i < ATTRIBUTE_TABLE_TITLES.size(); ++i)
- {
- final TableColumn column = new TableColumn(_table, SWT.NONE);
- column.setText(ATTRIBUTE_TABLE_TITLES.get(i));
- column.setWidth(tableWidths[i]);
- column.setResizable(true);
- }
-
- _table.setLinesVisible (true);
- _table.setHeaderVisible (true);
- }
-
- /**
- * Creates tableviewer for the attribute's table
- */
- private void createTableViewer()
- {
- _tableViewer = new TableViewer(_table);
- _tableViewer.setUseHashlookup(true);
- _tableViewer.setColumnProperties(
- ATTRIBUTE_TABLE_TITLES.toArray(new String[ATTRIBUTE_TABLE_TITLES.size()]));
- _tableViewer.setContentProvider(new ContentProviderImpl());
- _tableViewer.setLabelProvider(new LabelProviderImpl());
- _tableViewer.setSorter(new ViewerSorterImpl());
- }
-
- private void createButtons()
- {
- addDetailsButton();
- addEditButton();
- addGraphButton();
- }
-
- private void addDetailsButton()
- {
- // Create and configure the button for attribute details
- _detailsButton = _toolkit.createButton(_buttonsComposite, BUTTON_DETAILS, SWT.PUSH | SWT.CENTER);
- _detailsButton.setFont(ApplicationRegistry.getFont(FONT_BUTTON));
- GridData gridData = new GridData(SWT.FILL, SWT.TOP, false, false);
- gridData.widthHint = 80;
- _detailsButton.setLayoutData(gridData);
- _detailsButton.addSelectionListener(new SelectionAdapter()
- {
- public void widgetSelected(SelectionEvent e)
- {
- disableEditing = true;
- int index = _table.getSelectionIndex();
- TableItem item = _table.getItem(index);
- createDetailsPopup((AttributeData)item.getData());
- disableEditing = false;
- setFocus();
- }
- });
- }
-
- /**
- * Creates the button for editing attributes.
- */
- private void addEditButton()
- {
- // Create and configure the button for editing attribute
- _editButton = _toolkit.createButton(_buttonsComposite, BUTTON_EDIT_ATTRIBUTE, SWT.PUSH | SWT.CENTER);
- _editButton.setFont(ApplicationRegistry.getFont(FONT_BUTTON));
- GridData gridData = new GridData(SWT.FILL, SWT.TOP, false, false);
- gridData.widthHint = 80;
- _editButton.setLayoutData(gridData);
- _editButton.addSelectionListener(new SelectionAdapter()
- {
- public void widgetSelected(SelectionEvent e)
- {
- int index = _table.getSelectionIndex();
- TableItem item = _table.getItem(index);
- createDetailsPopup((AttributeData)item.getData());
- setFocus();
- }
- });
- }
-
- /**
- * Creates the button for viewing Graphs
- */
- private void addGraphButton()
- {
- _graphButton = _toolkit.createButton(_buttonsComposite, BUTTON_GRAPH, SWT.PUSH | SWT.CENTER);
- _graphButton.setFont(ApplicationRegistry.getFont(FONT_BUTTON));
- GridData gridData = new GridData(SWT.FILL, SWT.TOP, false, false);
- gridData.widthHint = 80;
- _graphButton.setLayoutData(gridData);
- _graphButton.addSelectionListener(new SelectionAdapter()
- {
- public void widgetSelected(SelectionEvent event)
- {
- int selectionIndex = _table.getSelectionIndex();
- AttributeData data = (AttributeData)_table.getItem(selectionIndex).getData();
- createGraph(data);
- setFocus();
- }
- });
- }
-
- private void addTableListeners()
- {
- _tableViewer.addSelectionChangedListener(new ISelectionChangedListener(){
- public void selectionChanged(SelectionChangedEvent evt)
- {
- IStructuredSelection ss = (IStructuredSelection)evt.getSelection();
- checkForEnablingButtons((AttributeData)ss.getFirstElement());
- }
- });
-
- MouseListenerImpl listener = new MouseListenerImpl();
- _tableViewer.getTable().addMouseTrackListener(listener);
- _tableViewer.getTable().addMouseMoveListener(listener);
- _tableViewer.getTable().addMouseListener(listener);
-
- _table.addDisposeListener(tableDisposeListener);
-
- // _table is equal to _tableViewer.getControl()
- _table.addListener(SWT.MeasureItem, new Listener() {
- public void handleEvent(Event event)
- {
- event.height = event.gc.getFontMetrics().getHeight() * 3/2;
- }
- });
- }
-
- /**
- * Listeners implementation class for showing table tooltip
- * @author Bhupendra Bhardwaj
- */
- private class MouseListenerImpl implements MouseTrackListener, MouseMoveListener, KeyListener, MouseListener
- {
- private Shell tooltipShell = null;
- private Label tooltipLabel = null;
- public void mouseHover(MouseEvent event)
- {
- TableItem item = _table.getItem (new Point (event.x, event.y));
-
- if (item != null)
- {
- AttributeData data = (AttributeData)item.getData();
- if (tooltipShell != null && !tooltipShell.isDisposed ())
- {
- tooltipShell.dispose ();
- }
- tooltipShell = new Shell(_table.getShell(), SWT.ON_TOP | SWT.NO_FOCUS | SWT.TOOL);
- tooltipShell.setBackground(event.display.getSystemColor(SWT.COLOR_INFO_BACKGROUND));
- FillLayout layout = new FillLayout();
- layout.marginWidth = 2;
- tooltipShell.setLayout(layout);
- tooltipLabel = new Label(tooltipShell, SWT.NONE);
- tooltipLabel.setForeground(event.display.getSystemColor(SWT.COLOR_INFO_FOREGROUND));
- tooltipLabel.setBackground(event.display.getSystemColor(SWT.COLOR_INFO_BACKGROUND));
- tooltipLabel.setText(data.getDescription());
- tooltipLabel.setData("_TABLEITEM", item);
- tooltipLabel.addListener(SWT.MouseExit, tooltipLabelListener);
- tooltipLabel.addListener(SWT.MouseDown, tooltipLabelListener);
- Point size = tooltipShell.computeSize(SWT.DEFAULT, SWT.DEFAULT);
- Rectangle rect = item.getBounds(0);
- Point pt = _table.toDisplay(rect.x, rect.y);
- tooltipShell.setBounds(pt.x, pt.y, size.x, size.y);
- tooltipShell.setVisible(true);
- }
- }
- public void mouseEnter(MouseEvent e)
- {
- }
- public void mouseExit(MouseEvent e)
- {
- }
-
- // MouseMoveListener implementation
- public void mouseMove(MouseEvent event)
- {
- if (tooltipShell == null)
- {
- return;
- }
-
- tooltipShell.dispose();
- tooltipShell = null;
- tooltipLabel = null;
- }
-
- // KeyListener implementation
- public void keyPressed(KeyEvent e)
- {
- if (tooltipShell == null)
- {
- return;
- }
-
- tooltipShell.dispose();
- tooltipShell = null;
- tooltipLabel = null;
- }
- public void keyReleased(KeyEvent e)
- {
-
- }
-
- // MouseListener implementation
- public void mouseDoubleClick(MouseEvent event)
- {
- if (tooltipShell != null)
- {
- tooltipShell.dispose();
- tooltipShell = null;
- tooltipLabel = null;
- }
- Table table = (Table)event.getSource();
- int selectionIndex = table.getSelectionIndex();
- AttributeData data = (AttributeData)table.getItem(selectionIndex).getData();
- createDetailsPopup(data);
- }
- public void mouseDown(MouseEvent e)
- {
- if (tooltipShell != null)
- {
- tooltipShell.dispose();
- tooltipShell = null;
- tooltipLabel = null;
- }
- }
- public void mouseUp(MouseEvent e)
- {
-
- }
- } // end of MouseListenerImpl
-
- /**
- * Creates pop-up window for showing attribute details
- * @param data - Selectes attribute
- */
- public void createDetailsPopup(AttributeData data)
- {
- int width = 500;
- int height = 250;
- if (!isSimpleType(data.getValue()))
- {
- width = 650;
- height = 450;
- }
-
- Display display = Display.getCurrent();
- Shell shell = ViewUtility.createPopupShell(ATTRIBUTE, width, height);
- createDetailsPopupContents(shell, data);
-
- shell.open();
- while (!shell.isDisposed())
- {
- if (!display.readAndDispatch())
- {
- display.sleep();
- }
- }
- shell.dispose();
- }
-
- /**
- * Listener class for table tooltip label
- */
- private final Listener tooltipLabelListener = new Listener ()
- {
- public void handleEvent (Event event)
- {
- Label label = (Label)event.widget;
- Shell shell = label.getShell();
- switch (event.type)
- {
- case SWT.MouseDown:
- Event e = new Event();
- e.item = (TableItem)label.getData ("_TABLEITEM");
- _table.setSelection(new TableItem[] {(TableItem)e.item});
- shell.dispose();
- _table.setFocus();
- break;
- case SWT.MouseExit:
- shell.dispose();
- break;
- }
- }
- };
-
-
- /**
- * Create the contents for the attribute details window pop-up
- * @param shell - The shell that will be filled with details.
- * @param attribute - Selected attribute
- */
- private void createDetailsPopupContents(Composite shell, AttributeData attribute)
- {
- GridLayout layout = new GridLayout(2, false);
- layout.horizontalSpacing = 10;
- layout.verticalSpacing = 10;
- layout.marginHeight = 20;
- layout.marginWidth = 20;
-
- Composite parent = _toolkit.createComposite(shell, SWT.NONE);
- parent.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
- parent.setLayout(layout);
-
- // Name
- Label label = _toolkit.createLabel(parent, ATTRIBUTE_TABLE_TITLES.get(0), SWT.NONE);
- GridData layoutData = new GridData(SWT.TRAIL, SWT.TOP, false, false);
- label.setLayoutData(layoutData);
- int textStyle = SWT.BEGINNING | SWT.BORDER |SWT.READ_ONLY;
- Text value = _toolkit.createText(parent, ViewUtility.getDisplayText(attribute.getName()), textStyle);
- value.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
-
-
- // Description
- label = _toolkit.createLabel(parent, DESCRIPTION, SWT.NONE);
- label.setLayoutData(new GridData(SWT.TRAIL, SWT.TOP, false, false));
- value = _toolkit.createText(parent, attribute.getDescription(), textStyle);
- value.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
-
- // value
- label = _toolkit.createLabel(parent, ATTRIBUTE_TABLE_TITLES.get(1), SWT.NONE);
- label.setLayoutData(new GridData(SWT.TRAIL, SWT.TOP, false, false));
-
- if (!attribute.isReadable())
- {
- value = _toolkit.createText(parent, "", textStyle);
- value.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
- }
- else
- {
- if (!isSimpleType(attribute.getValue()))
- {
- if (attribute.getValue() instanceof String[])
- {
- String result = "";
- for(String val : (String[]) attribute.getValue()){
- result = result.concat(val+ "; ");
- }
- value = _toolkit.createText(parent, "", textStyle);
-
- value.setText(result);
- value.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
- }
- else
- {
- Composite composite = new Composite(parent, SWT.BORDER);
- composite.setLayout(new GridLayout());
- composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
- ViewUtility.populateCompositeWithData(_toolkit, composite, attribute.getValue());
- }
- }
- else
- {
- if (attribute.isWritable())
- {
- value = _toolkit.createText(parent, "", SWT.BEGINNING | SWT.BORDER);
- if(attribute.isNumber())
- {
- value.addVerifyListener(new NumberVerifyListener());
- }
-
- // set data to access in the listener
- parent.setData(attribute);
- }
- else
- {
- value = _toolkit.createText(parent, "", textStyle);
- }
-
- value.setText(attribute.getValue().toString());
- value.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
- }
- }
-
-
- // Update button
- Button updateButton = addUpdateButton(parent);
- updateButton.setData(value);
- if (!attribute.isWritable())
- {
- updateButton.setVisible(false);
- }
-
- if (disableEditing)
- {
- value.setEditable(false);
- updateButton.setVisible(false);
- }
- }
-
- /**
- * Create the button for updating attributes. This should be enabled for writable attribute
- */
- private Button addUpdateButton(Composite parent)
- {
- final Button updateButton = new Button(parent, SWT.PUSH | SWT.CENTER);
- // set the data to access in the listener
- parent.setData(BUTTON_UPDATE, updateButton);
-
- updateButton.setText(BUTTON_UPDATE);
- GridData gridData = new GridData (SWT.CENTER, SWT.BOTTOM, true, true, 2, 1);
- gridData.widthHint = 100;
- updateButton.setLayoutData(gridData);
- updateButton.addSelectionListener(new SelectionAdapter()
- {
- public void widgetSelected(SelectionEvent event)
- {
- try
- {
- Button button = (Button)event.widget;
- Text text = (Text)button.getData();
- AttributeData data = (AttributeData)button.getParent().getData();
- MBeanUtility.updateAttribute(_mbean, data, text.getText());
- button.getShell().close();
- refresh(_mbean);
- }
- catch (Exception ex)
- {
- MBeanUtility.handleException(_mbean, ex);
- }
- }
- });
-
- return updateButton;
- }
-
- /**
- * Refreshes the attribute tab by querying the mbean server for latest values
- */
- @Override
- public void refresh(ManagedBean mbean)
- {
- _mbean = mbean;
- if (_mbean == null)
- {
- _tableViewer.setInput(null);
- return;
- }
- ManagedAttributeModel attributesList = null;
- try
- {
- attributesList = MBeanUtility.getAttributes(mbean);
- }
- catch(Exception ex)
- {
- MBeanUtility.handleException(_mbean, ex);
- }
- _tableViewer.setInput(attributesList);
- checkForEnablingButtons(getSelectionAttribute());
-
- _form.layout(true);
- _form.getBody().layout(true, true);
- }
-
- /**
- * @see TabControl#setFocus()
- */
- public void setFocus()
- {
- _table.setFocus();
- }
-
- /**
- * Checks which buttons are to be enabled or disabled. The graph button will be enabled only
- * for readable number attributes. Editing is enabled for writeable attribtues.
- * @param attribute
- */
- private void checkForEnablingButtons(AttributeData attribute)
- {
- if (attribute == null)
- {
- _detailsButton.setEnabled(false);
- _editButton.setEnabled(false);
- _graphButton.setEnabled(false);
- return;
- }
-
- _detailsButton.setEnabled(true);
- if (attribute.isWritable())
- {
- _editButton.setEnabled(true);
- _graphButton.setEnabled(false);
- }
- else
- {
- _editButton.setEnabled(false);
- // Currently only Queues are having attributes, which are suitable for a graph
- if (attribute.isNumber() && _mbean.isQueue())
- {
- _graphButton.setEnabled(true);
- }
- else
- {
- _graphButton.setEnabled(false);
- }
- }
- }
-
- /**
- * Creates graph in a pop-up window for given attribute.
- * @param data
- */
- private void createGraph(final AttributeData data)
- {
- Display display = Display.getCurrent();
- Shell shell = new Shell(display, SWT.BORDER | SWT.CLOSE | SWT.MIN | SWT.MAX);
- shell.setText(_mbean.getName());
- int x = display.getBounds().width;
- int y = display.getBounds().height;
- shell.setBounds(x/4, y/4, GRAPH_WIDTH, GRAPH_HEIGHT);
- shell.setLayout(new FillLayout());
-
- final Canvas canvas = new Canvas(shell, SWT.NONE);
- long currentValue = Long.parseLong(data.getValue().toString());
- long mValue = getGraphMaxValue(currentValue);
- canvas.setData(MAX_VALUE, mValue);
- canvas.setData(GRAPH_VALUES, new long[] {0,0,0,0,0,currentValue});
-
- canvas.setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_WHITE));
- canvas.addPaintListener(new PaintListener()
- {
- public void paintControl(PaintEvent event)
- {
- Canvas canvas = (Canvas)event.widget;
- int maxX = canvas.getSize().x;
- int maxY = canvas.getSize().y;
- event.gc.fillRectangle(canvas.getBounds());
- event.gc.setForeground(Display.getCurrent().getSystemColor(SWT.COLOR_BLACK));
- event.gc.setLineWidth(4);
-
- Object canvasData = canvas.getData(MAX_VALUE);
- String str = canvasData.toString();
- long maxValue = Long.parseLong(str);
- // Set the graph dimensions
- event.gc.drawText("0", startX - 40, maxY - startY - 10);
- event.gc.drawText("" + maxValue/2, startX - 40, maxY/2);
- event.gc.drawText("" + maxValue, startX - 40, startY);
-
- // horizontal line
- event.gc.drawLine(startX, maxY - startY, maxX - 60, maxY - startY);
- // vertical line
- event.gc.drawLine(startX, maxY - startY, startX, startY);
- // set graph text
- event.gc.drawText(data.getName(), startX - 40, startY - 40);
- event.gc.drawText("25 sec", startX, maxY - startY + 10);
- event.gc.drawText("20 sec", startX + GRAPH_ITEM_GAP, maxY - startY + 10);
- event.gc.drawText("15 sec", startX + GRAPH_ITEM_GAP * 2, maxY - startY + 10);
- event.gc.drawText("10 sec", startX + GRAPH_ITEM_GAP * 3, maxY - startY + 10);
- event.gc.drawText(" 5 sec", startX + GRAPH_ITEM_GAP * 4, maxY - startY + 10);
- event.gc.drawText(" 0 sec", startX + GRAPH_ITEM_GAP * 5, maxY - startY + 10);
-
- // plot the graph now for values
- event.gc.setForeground(Display.getCurrent().getSystemColor(SWT.COLOR_BLUE));
- canvasData = canvas.getData(GRAPH_VALUES);
- long[] graphValues = (long[]) canvasData;
- for (int i = 0; i < graphValues.length; i++)
- {
- int x = startX + i * GRAPH_ITEM_GAP;
- int yTotalLength = (maxY - 2 * startY);
- float ratio = ((float)graphValues[i]/(float)maxValue);
- int itemlength = (int)(yTotalLength * ratio);
- int y = maxY - startY - itemlength;
- event.gc.drawLine(x, maxY- startY, x, y);
- event.gc.drawText(String.valueOf(graphValues[i]), x, y - 20);
- }
- }
- });
-
- shell.open();
-
- // Set up the timer for the animation
- Runnable runnable = new Runnable()
- {
- public void run()
- {
- try
- {
- animate(canvas, data);
- Display.getCurrent().timerExec(TIMER_INTERVAL, this);
- }
- catch(Exception ex)
- {
- MBeanUtility.handleException(ex);
- }
- }
- };
-
- // Launch the timer
- display.timerExec(TIMER_INTERVAL, runnable);
-
- while (!shell.isDisposed())
- {
- if (!display.readAndDispatch())
- {
- display.sleep();
- }
- }
-
- // Kill the timer
- display.timerExec(-1, runnable);
- shell.dispose();
- }
-
- /**
- * @return selected attribute in the table
- */
- public AttributeData getSelectionAttribute()
- {
- int index = _table.getSelectionIndex();
- if (index == -1)
- {
- return null;
- }
-
- return (AttributeData)_table.getItem(index).getData();
- }
-
- /**
- * checks for newer values of selected attribute to update the graph
- * @param canvas
- * @param data
- * @throws Exception
- */
- private void animate(Canvas canvas, AttributeData data) throws Exception
- {
- String attribute = data.getName();
- Object valueObj = MBeanUtility.refreshAttribute(_mbean, attribute);
- int value = Integer.parseInt(String.valueOf(valueObj));
- Object canvasData = canvas.getData(GRAPH_VALUES);
- long[] graphValues = (long[]) canvasData;
-
- for (int i = 0; i < graphValues.length -1; i++)
- {
- graphValues[i] = graphValues[i + 1];
- }
- graphValues[graphValues.length - 1] = value;
-
- canvasData = canvas.getData(MAX_VALUE);
- long maxValue = Long.parseLong(String.valueOf(canvasData));
- if (maxValue < value)
- {
- maxValue = getGraphMaxValue(value);
- canvas.setData(MAX_VALUE, maxValue);
- }
-
- canvas.redraw();
- }
-
- /**
- * @param maxAttributeValue
- * @return dynamically calculated value for y-axis on the graph
- */
- private long getGraphMaxValue(long maxAttributeValue)
- {
- long maxGraphValue = 100;
- long temp = maxAttributeValue * 3/2;
- if (temp > maxGraphValue)
- {
- long modulus = temp % 100;
- maxGraphValue = temp + ( 100 - modulus);
- }
-
- return maxGraphValue;
- }
-
- /**
- * Content Provider class for the table viewer
- * @author Bhupendra Bhardwaj
- */
- private static class ContentProviderImpl implements IStructuredContentProvider
- {
-
- public void inputChanged(Viewer v, Object oldInput, Object newInput)
- {
-
- }
-
- public void dispose()
- {
-
- }
-
- public Object[] getElements(Object parent)
- {
- return ((ManagedAttributeModel)parent).getAttributes();
- }
- }
-
- /**
- * Label Provider class for the table viewer
- * @author Bhupendra Bhardwaj
- */
- private class LabelProviderImpl extends LabelProvider implements ITableLabelProvider,
- IFontProvider,
- IColorProvider
- {
- private AttributeData attribute = null;
- public String getColumnText(Object element, int columnIndex)
- {
- String result = "";
- attribute = (AttributeData) element;
-
- switch (columnIndex)
- {
- case 0 : // attribute name column
- result = ViewUtility.getDisplayText(attribute.getName());
- break;
- case 1 : // attribute value column
- if (attribute.getValue() != null)
- {
- if (attribute.getValue() instanceof String[])
- {
- for(String val : (String[]) attribute.getValue()){
- result = result.concat(val+ "; ");
- }
- }
- else
- {
- result = String.valueOf(attribute.getValue());
- }
- }
- break;
- default :
- result = "";
- }
-
- return result;
- }
-
- public Image getColumnImage(Object element, int columnIndex)
- {
- return null;
- }
-
- public Font getFont(Object element)
- {
- return ApplicationRegistry.getFont(FONT_TABLE_CELL);
- }
-
- public Color getForeground(Object element)
- {
- attribute = (AttributeData) element;
- if (attribute.isWritable())
- {
- return Display.getCurrent().getSystemColor(SWT.COLOR_BLUE);
- }
- else
- {
- return Display.getCurrent().getSystemColor(SWT.COLOR_BLACK);
- }
- }
- public Color getBackground(Object element)
- {
- return _form.getBackground();
- }
- }
-
- private static class DisposeListenerImpl implements DisposeListener
- {
- public void widgetDisposed(DisposeEvent e)
- {
-
- }
- }
-
- /**
- * Sorter class for the table viewer. It sorts the table for according to attribute name.
- * @author Bhupendra Bhardwaj
- *
- */
- private static class ViewerSorterImpl extends ViewerSorter
- {
- public int compare(Viewer viewer, Object o1, Object o2)
- {
- AttributeData attribtue1 = (AttributeData)o1;
- AttributeData attribtue2 = (AttributeData)o2;
-
- return collator.compare(attribtue1.getName(), attribtue2.getName());
- }
- }
-}
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
deleted file mode 100644
index 245d989a04..0000000000
--- a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/MBeanTabFolderFactory.java
+++ /dev/null
@@ -1,466 +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;
-
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.layout.FormAttachment;
-import org.eclipse.swt.layout.FormData;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Event;
-import org.eclipse.swt.widgets.Listener;
-import org.eclipse.swt.widgets.TabFolder;
-import org.eclipse.swt.widgets.TabItem;
-
-import org.apache.qpid.management.ui.ApplicationRegistry;
-import org.apache.qpid.management.ui.ManagedServer;
-import org.apache.qpid.management.ui.ServerRegistry;
-import org.apache.qpid.management.ui.jmx.JMXManagedObject;
-import org.apache.qpid.management.ui.jmx.MBeanUtility;
-import org.apache.qpid.management.ui.model.NotificationInfoModel;
-import org.apache.qpid.management.ui.model.OperationData;
-import org.apache.qpid.management.ui.model.OperationDataModel;
-import org.apache.qpid.management.ui.views.connection.ConnectionOperationsTabControl;
-import org.apache.qpid.management.ui.views.exchange.ExchangeOperationsTabControl;
-import org.apache.qpid.management.ui.views.exchange.HeadersExchangeOperationsTabControl;
-import org.apache.qpid.management.ui.views.logging.ConfigurationFileTabControl;
-import org.apache.qpid.management.ui.views.logging.RuntimeTabControl;
-import org.apache.qpid.management.ui.views.queue.QueueOperationsTabControl;
-import org.apache.qpid.management.ui.views.type.ConnectionTypeTabControl;
-import org.apache.qpid.management.ui.views.type.ExchangeTypeTabControl;
-import org.apache.qpid.management.ui.views.type.QueueTypeTabControl;
-import org.apache.qpid.management.ui.views.users.UserManagementTabControl;
-import org.apache.qpid.management.ui.views.vhost.VHostTabControl;
-
-import static org.apache.qpid.management.ui.Constants.ATTRIBUTES;
-import static org.apache.qpid.management.ui.Constants.CONNECTION;
-import static org.apache.qpid.management.ui.Constants.EXCHANGE;
-import static org.apache.qpid.management.ui.Constants.EXCHANGE_TYPE;
-import static org.apache.qpid.management.ui.Constants.NOTIFICATIONS;
-import static org.apache.qpid.management.ui.Constants.QUEUE;
-
-import javax.management.MBeanServerConnection;
-import java.util.EnumSet;
-import java.util.HashMap;
-import java.util.Map;
-
-public class MBeanTabFolderFactory
-{
- private static final String MBEANTYPE_QUEUE = "VirtualHost.Queue";
- private static final String MBEANTYPE_CONNECTION = "VirtualHost.Connection";
- private static final String MBEANTYPE_EXCHANGE = "VirtualHost.Exchange";
- private static final String MBEANTYPE_VHOST_MANAGER = "VirtualHost.VirtualHostManager";
- private static final String MBEANTYPE_LOGGING_MANAGEMENT = "LoggingManagement";
- private static final String MBEANTYPE_USER_MANAGEMENT = "UserManagement";
- private static final String MBEANTYPE_CONFIGURATION_MANAGEMENT = "ConfigurationManagement";
-
- private MBeanTabFolderFactory()
- {
- //no instances
- }
-
- public static TabFolder generateMBeanTabFolder(final Composite parent, final JMXManagedObject mbean, final MBeanServerConnection mbsc)
- {
- TabFolder tabFolder = new TabFolder(parent, SWT.NONE);
- FormData layoutData = new FormData();
- layoutData.left = new FormAttachment(0);
- layoutData.top = new FormAttachment(0);
- layoutData.right = new FormAttachment(100);
- layoutData.bottom = new FormAttachment(100);
- tabFolder.setLayoutData(layoutData);
-
- TabItem tab;
- TabControl controller;
- QpidMBeanType mbeanType = QpidMBeanType.get(mbean.getType());
-
- switch(mbeanType)
- {
- case QUEUE:
- createAttributesTab(tabFolder, mbean);
-
- tab = new TabItem(tabFolder, SWT.NONE);
- tab.setText("Operations");
- controller = new QueueOperationsTabControl(tabFolder, mbean, mbsc);
- tab.setControl(controller.getControl());
- tab.setData(TabControl.CONTROLLER, controller);
- break;
- case CONNECTION:
- createAttributesTab(tabFolder, mbean);
-
- tab = new TabItem(tabFolder, SWT.NONE);
- tab.setText("Operations");
- controller = new ConnectionOperationsTabControl(tabFolder, mbean, mbsc);
- tab.setControl(controller.getControl());
- tab.setData(TabControl.CONTROLLER, controller);
- break;
- case EXCHANGE:
- createAttributesTab(tabFolder, mbean);
-
- if (mbean.getProperty(EXCHANGE_TYPE).equalsIgnoreCase("headers"))
- {
- tab = new TabItem(tabFolder, SWT.NONE);
- tab.setText("Operations");
- controller = new HeadersExchangeOperationsTabControl(tabFolder, mbean, mbsc);
- tab.setControl(controller.getControl());
- tab.setData(TabControl.CONTROLLER, controller);
- }
- else
- {
- tab = new TabItem(tabFolder, SWT.NONE);
- tab.setText("Operations");
- controller = new ExchangeOperationsTabControl(tabFolder, mbean, mbsc);
- tab.setControl(controller.getControl());
- tab.setData(TabControl.CONTROLLER, controller);
- }
- break;
- case VHOST_MANAGER:
- createAttributesTab(tabFolder, mbean);
-
- tab = new TabItem(tabFolder, SWT.NONE);
- tab.setText("Operations");
- controller = new VHostTabControl(tabFolder, mbean, mbsc);
- tab.setControl(controller.getControl());
- tab.setData(TabControl.CONTROLLER, controller);
- break;
- case LOGGING_MANAGEMENT:
- tab = new TabItem(tabFolder, SWT.NONE);
- tab.setText("Runtime Options");
- controller = new RuntimeTabControl(tabFolder, mbean, mbsc);
- tab.setControl(controller.getControl());
- tab.setData(TabControl.CONTROLLER, controller);
-
- tab = new TabItem(tabFolder, SWT.NONE);
- tab.setText("ConfigurationFile Options");
- controller = new ConfigurationFileTabControl(tabFolder, mbean, mbsc);
- tab.setControl(controller.getControl());
- tab.setData(TabControl.CONTROLLER, controller);
- break;
- case USER_MANAGEMENT:
- tab = new TabItem(tabFolder, SWT.NONE);
- tab.setText("Operations");
- controller = new UserManagementTabControl(tabFolder, mbean, mbsc);
- tab.setControl(controller.getControl());
- tab.setData(TabControl.CONTROLLER, controller);
- break;
- case CONFIGURATION_MANAGEMENT:
- createGenericTabFolder(tabFolder, mbean);
- break;
- case UNKNOWN:
- createGenericTabFolder(tabFolder, mbean);
- break;
- }
-
- createNotificationsTabIfNecessary(tabFolder, mbean);
-
- tabFolder.addListener(SWT.Selection, new Listener()
- {
- public void handleEvent(Event evt)
- {
- TabItem tab = (TabItem)evt.item;
- TabControl controller = (TabControl)tab.getData(TabControl.CONTROLLER);
- if(controller != null)
- {
- controller.refresh(mbean);
- }
- }
- });
-
- return tabFolder;
- }
-
- private static void createGenericTabFolder(TabFolder tabFolder, JMXManagedObject mbean)
- {
- createAttributesTab(tabFolder, mbean);
- createOperationTabs(tabFolder, mbean);
- }
-
- private static void createAttributesTab(TabFolder tabFolder, JMXManagedObject mbean)
- {
- ServerRegistry serverRegistry = ApplicationRegistry.getServerRegistry(mbean);
- if(serverRegistry.getAttributeModel(mbean).getCount() == 0)
- {
- return;
- }
-
- TabItem tab = new TabItem(tabFolder, SWT.NONE);
- tab.setText(ATTRIBUTES);
- AttributesTabControl controller = new AttributesTabControl(tabFolder);
- tab.setControl(controller.getControl());
- tab.setData(TabControl.CONTROLLER, controller);
- }
-
- private static void createOperationTabs(TabFolder tabFolder, JMXManagedObject mbean)
- {
- ServerRegistry serverRegistry = ApplicationRegistry.getServerRegistry(mbean);
- int operationsCount = serverRegistry.getOperationModel(mbean).getCount();
- if(operationsCount == 0)
- {
- return;
- }
-
- OperationDataModel operationModel = serverRegistry.getOperationModel(mbean);
- for(OperationData operationData : operationModel.getOperations())
- {
- TabItem operationTab = new TabItem(tabFolder, SWT.NONE);
- operationTab.setText(ViewUtility.getDisplayText(operationData.getName()));
- operationTab.setData(operationData);
- OperationTabControl control = new OperationTabControl(tabFolder, operationData);
- operationTab.setData(TabControl.CONTROLLER, control);
- operationTab.setControl(control.getControl());
- }
- }
-
- private static void createNotificationsTabIfNecessary(TabFolder tabFolder, JMXManagedObject mbean)
- {
- NotificationInfoModel[] items = MBeanUtility.getNotificationInfo(mbean);
- if(items == null || items.length == 0)
- {
- //the mbean has no notifications to subscribe for, do not create the tab.
- return;
- }
-
- NotificationsTabControl controller = new NotificationsTabControl(tabFolder, mbean);
-
- TabItem tab = new TabItem(tabFolder, SWT.NONE);
- tab.setText(NOTIFICATIONS);
- tab.setData(TabControl.CONTROLLER, controller);
- tab.setControl(controller.getControl());
- }
-
- /**
- * Creates TabFolder and tabs for all mbeantype (Connection, Queue, and Exchange)
- */
- public static TabFolder generateMBeanTypeTabFolder(final Composite parent, ManagedServer server, String virtualHost)
- {
- TabFolder tabFolder = new TabFolder(parent, SWT.NONE);
- FormData layoutData = new FormData();
- layoutData.left = new FormAttachment(0);
- layoutData.top = new FormAttachment(0);
- layoutData.right = new FormAttachment(100);
- layoutData.bottom = new FormAttachment(100);
- tabFolder.setLayoutData(layoutData);
-
-
- TabItem tab;
- TabControl controller;
-
- tab = new TabItem(tabFolder, SWT.NONE);
- tab.setText(CONNECTION);
- controller = new ConnectionTypeTabControl(tabFolder,server,virtualHost);
- tab.setData(TabControl.CONTROLLER, controller);
- tab.setControl(controller.getControl());
-
- tab = new TabItem(tabFolder, SWT.NONE);
- tab.setText(EXCHANGE);
- controller = new ExchangeTypeTabControl(tabFolder,server,virtualHost);
- tab.setData(TabControl.CONTROLLER, controller);
- tab.setControl(controller.getControl());
-
- tab = new TabItem(tabFolder, SWT.NONE);
- tab.setText(QUEUE);
- controller = new QueueTypeTabControl(tabFolder,server,virtualHost);
- tab.setData(TabControl.CONTROLLER, controller);
- tab.setControl(controller.getControl());
-
- tabFolder.addListener(SWT.Selection, new Listener()
- {
- public void handleEvent(Event evt)
- {
- TabItem tab = (TabItem)evt.item;
- TabControl controller = (TabControl)tab.getData(TabControl.CONTROLLER);
- if(controller != null)
- {
- controller.refresh(null);
- }
- }
- });
-
- return tabFolder;
- }
-
- /**
- * Creates TabFolder and tab for the Connection selection view
- */
- public static TabFolder generateConnectionTypeTabFolder(final Composite parent, ManagedServer server, String virtualHost)
- {
- TabFolder tabFolder = new TabFolder(parent, SWT.NONE);
- FormData layoutData = new FormData();
- layoutData.left = new FormAttachment(0);
- layoutData.top = new FormAttachment(0);
- layoutData.right = new FormAttachment(100);
- layoutData.bottom = new FormAttachment(100);
- tabFolder.setLayoutData(layoutData);
-
- TabItem tab;
- TabControl controller;
-
- tab = new TabItem(tabFolder, SWT.NONE);
- tab.setText(CONNECTION);
- controller = new ConnectionTypeTabControl(tabFolder,server,virtualHost);
- tab.setData(TabControl.CONTROLLER, controller);
- tab.setControl(controller.getControl());
-
- tabFolder.addListener(SWT.Selection, new Listener()
- {
- public void handleEvent(Event evt)
- {
- TabItem tab = (TabItem)evt.item;
- TabControl controller = (TabControl)tab.getData(TabControl.CONTROLLER);
- if(controller != null)
- {
- controller.refresh(null);
- }
- }
- });
-
- return tabFolder;
- }
-
- /**
- * Creates TabFolder and tab for the Exchange selection view
- */
- public static TabFolder generateExchangeTypeTabFolder(final Composite parent, ManagedServer server, String virtualHost)
- {
- TabFolder tabFolder = new TabFolder(parent, SWT.NONE);
- FormData layoutData = new FormData();
- layoutData.left = new FormAttachment(0);
- layoutData.top = new FormAttachment(0);
- layoutData.right = new FormAttachment(100);
- layoutData.bottom = new FormAttachment(100);
- tabFolder.setLayoutData(layoutData);
-
- TabItem tab;
- TabControl controller;
-
- tab = new TabItem(tabFolder, SWT.NONE);
- tab.setText(EXCHANGE);
- controller = new ExchangeTypeTabControl(tabFolder,server,virtualHost);
- tab.setData(TabControl.CONTROLLER, controller);
- tab.setControl(controller.getControl());
-
- tabFolder.addListener(SWT.Selection, new Listener()
- {
- public void handleEvent(Event evt)
- {
- TabItem tab = (TabItem)evt.item;
- TabControl controller = (TabControl)tab.getData(TabControl.CONTROLLER);
- if(controller != null)
- {
- controller.refresh(null);
- }
- }
- });
-
- return tabFolder;
- }
-
- /**
- * Creates TabFolder and tab for the Queue selection view
- */
- public static TabFolder generateQueueTypeTabFolder(final Composite parent, ManagedServer server, String virtualHost)
- {
- TabFolder tabFolder = new TabFolder(parent, SWT.NONE);
- FormData layoutData = new FormData();
- layoutData.left = new FormAttachment(0);
- layoutData.top = new FormAttachment(0);
- layoutData.right = new FormAttachment(100);
- layoutData.bottom = new FormAttachment(100);
- tabFolder.setLayoutData(layoutData);
-
- TabItem tab;
- TabControl controller;
-
- tab = new TabItem(tabFolder, SWT.NONE);
- tab.setText(QUEUE);
- controller = new QueueTypeTabControl(tabFolder,server,virtualHost);
- tab.setData(TabControl.CONTROLLER, controller);
- tab.setControl(controller.getControl());
-
- tabFolder.addListener(SWT.Selection, new Listener()
- {
- public void handleEvent(Event evt)
- {
- TabItem tab = (TabItem)evt.item;
- TabControl controller = (TabControl)tab.getData(TabControl.CONTROLLER);
- if(controller != null)
- {
- controller.refresh(null);
- }
- }
- });
-
- return tabFolder;
- }
-
- private enum QpidMBeanType
- {
- QUEUE (MBEANTYPE_QUEUE),
- CONNECTION (MBEANTYPE_CONNECTION),
- EXCHANGE (MBEANTYPE_EXCHANGE),
- VHOST_MANAGER (MBEANTYPE_VHOST_MANAGER),
- LOGGING_MANAGEMENT (MBEANTYPE_LOGGING_MANAGEMENT),
- USER_MANAGEMENT (MBEANTYPE_USER_MANAGEMENT),
- CONFIGURATION_MANAGEMENT (MBEANTYPE_CONFIGURATION_MANAGEMENT),
- UNKNOWN (null);
-
- private static final Map<String,QpidMBeanType> lookup = new HashMap<String,QpidMBeanType>();
-
- static
- {
- for(QpidMBeanType m : EnumSet.allOf(QpidMBeanType.class))
- {
- lookup.put(m.getType(), m);
- }
- }
-
- private String type;
-
- private QpidMBeanType()
- {
-
- }
-
- private QpidMBeanType(String type)
- {
- this.type = type;
- }
-
- public String getType()
- {
- return type;
- }
-
- public static QpidMBeanType get(String type)
- {
- QpidMBeanType t= lookup.get(type);
- if (t != null)
- {
- return t;
- }
- else
- {
- return UNKNOWN;
- }
-
- }
- }
-
-
-}
diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/MBeanView.java b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/MBeanView.java
deleted file mode 100644
index 1ce31ae3d1..0000000000
--- a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/MBeanView.java
+++ /dev/null
@@ -1,609 +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;
-
-import org.eclipse.jface.viewers.ISelection;
-import org.eclipse.jface.viewers.IStructuredSelection;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.graphics.Image;
-import org.eclipse.swt.layout.FormAttachment;
-import org.eclipse.swt.layout.FormData;
-import org.eclipse.swt.layout.FormLayout;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.TabFolder;
-import org.eclipse.swt.widgets.TabItem;
-import org.eclipse.ui.IActionBars;
-import org.eclipse.ui.ISelectionListener;
-import org.eclipse.ui.IWorkbenchPart;
-import org.eclipse.ui.forms.widgets.Form;
-import org.eclipse.ui.forms.widgets.FormToolkit;
-import org.eclipse.ui.part.ViewPart;
-
-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.ui.ManagedServer;
-import org.apache.qpid.management.ui.ServerRegistry;
-import org.apache.qpid.management.ui.actions.BackAction;
-import org.apache.qpid.management.ui.jmx.JMXManagedObject;
-import org.apache.qpid.management.ui.jmx.JMXServerRegistry;
-import org.apache.qpid.management.ui.jmx.MBeanUtility;
-
-import static org.apache.qpid.management.ui.Constants.*;
-
-import javax.management.MBeanServerConnection;
-import java.util.LinkedList;
-
-/**
- * MBean View create appropriate view based on the user selection on the Navigation View.
- */
-public class MBeanView extends ViewPart
-{
- public static final String ID = "org.apache.qpid.management.ui.mbeanView";
-
- private FormToolkit _toolkit = null;
- private Form _form = null;
- private String _formText = APPLICATION_NAME;
- private static ManagedServer _server = null;
- private TreeObject _selectedNode = null;
- private ManagedBean _mbean = null;
- private static String _virtualHostName = null;
- private static MBeanServerConnection _mbsc = null;
- private TabFolder _tabFolder = null;
- private ISelectionListener _selectionListener = new SelectionListenerImpl();
-
- // TabFolder to list all the mbeans for a given mbeantype(eg Connection, Queue, Exchange)
- private TabFolder _typeTabFolder = null;
-
- private TabFolder _notificationTabFolder = null;
-
- private LinkedList<Object> _backHistory;
- private BackAction _backAction;
-
- /*
- * Listener for the selection events in the navigation view
- */
- private class SelectionListenerImpl implements ISelectionListener
- {
- public void selectionChanged(IWorkbenchPart part, ISelection sel)
- {
- if (!(sel instanceof IStructuredSelection))
- {
- return;
- }
-
- IStructuredSelection ss = (IStructuredSelection) sel;
- _selectedNode = (TreeObject)ss.getFirstElement();
-
-
- // mbean should be set to null. A selection done on the navigation view can be either an mbean or
- // an mbeantype. For mbeantype selection(eg Connection, Queue, Exchange) _mbean will remain null.
- _mbean = null;
- clearView();
-
- //clear the back history, it is only for use when opening subsequent mbeans not in the nav tree
- _backHistory.clear();
- _backAction.setEnabled(false);
-
- // If a selected node(mbean) gets unregistered from mbean server, mbeanview should
- // make the tabfolber for that mbean invisible
- if (_selectedNode == null)
- {
- return;
- }
-
- setServer();
-
- if(!ApplicationRegistry.isServerConnected(_server))
- {
- return;
- }
-
- if (MBEAN.equals(_selectedNode.getType()))
- {
- _mbean = (ManagedBean)_selectedNode.getManagedObject();
- }
-
- setFormTitle();
- showRelevantTabView();
- }
- }
-
- public void openMBean(ManagedBean mbean)
- {
- openMBean(mbean, false);
- }
-
- private void openMBean(ManagedBean mbean, boolean undoing)
- {
- if(mbean == null)
- {
- return;
- }
-
- //if an mbean is about to be opened (but not returning to using back) from the mbean view,
- //then record the current viewed area/object as a means of back history
- if(!undoing)
- {
- if(_backHistory.isEmpty())
- {
- //ensure the button is enabled if this is to be the first history item
- _backAction.setEnabled(true);
- }
-
- if(_mbean == null)
- {
- //queue etc selection area is open, record the tree object
- _backHistory.addLast(_selectedNode);
- }
- else
- {
- _backHistory.addLast(_mbean);
- }
- }
-
- _mbean = mbean;
-
- try
- {
- clearView();
-
- setFormTitle();
- showMBean(mbean);
-
- _form.layout(true);
- _form.getBody().layout(true, true);
- }
- catch(Exception ex)
- {
- MBeanUtility.handleException(mbean, ex);
- }
- }
-
- private void setFormTitle()
- {
- if (_mbean != null)
- {
- _formText = _mbean.getType();
- if ((_mbean.getVirtualHostName() != null) && (!DEFAULT_VH.equals(_mbean.getVirtualHostName())) )
- {
- _formText = _formText.replaceFirst(VIRTUAL_HOST, _mbean.getVirtualHostName());
- if (_mbean.getName() != null && _mbean.getName().length() != 0)
- {
- _formText = _formText + ": " + _mbean.getName();
- }
- }
- }
- else if ((_selectedNode.getVirtualHost() != null) && (!DEFAULT_VH.equals(_selectedNode.getVirtualHost())))
- {
- _formText = _selectedNode.getVirtualHost();
- }
- else
- {
- _formText = APPLICATION_NAME;
- }
- _form.setText(_formText);
- }
-
- public void showRelevantTabView()
- {
- try
- {
- if (_selectedNode == null)
- {
- return;
- }
-
- String mbeanType = _selectedNode.getType();
-
- if (NODE_TYPE_TYPEINSTANCE.equals(mbeanType))
- {
- // An virtual host instance is selected
- generateTypeTabFolder();
- }
- else if (NODE_TYPE_MBEANTYPE.equals(mbeanType))
- {
- showTypeTabFolder(_selectedNode.getName());
- }
- else if (NOTIFICATIONS.equals(mbeanType))
- {
- refreshNotificationPage();
- }
- else if (MBEAN.equals(mbeanType))
- {
- showMBean(_mbean);
- }
- else if(NODE_TYPE_SERVER.equals(mbeanType))
- {
- ServerRegistry serverReg = ApplicationRegistry.getServerRegistry(_server);
-
- //check the server is connected
- if(serverReg != null)
- {
- //post a message if the server supports a newer API version.
- ApiVersion serverAPI = serverReg.getManagementApiVersion();
- int supportedMajor = ApplicationRegistry.SUPPORTED_QPID_JMX_API_MAJOR_VERSION;
- int supportedMinor = ApplicationRegistry.SUPPORTED_QPID_JMX_API_MINOR_VERSION;
-
- if(serverAPI.greaterThan(supportedMajor, supportedMinor))
- {
- _form.setText("The server supports an updated management API and may offer " +
- "functionality not available with this console. " +
- "Please check for an updated console release.");
- }
-
- }
- }
- else
- {
- return;
- }
-
- _form.layout(true);
- _form.getBody().layout(true, true);
- }
- catch(Exception ex)
- {
- MBeanUtility.handleException(_mbean, ex);
- }
- }
-
- /**
- * Sets the managedServer based on the selection in the navigation view
- * At any given time MBeanView will be displaying information for an mbean of mbeantype
- * for a specifiv managed server. This server information will be used by the tab controllers
- * to get server registry.
- */
- private void setServer()
- {
- if (NODE_TYPE_SERVER.equals(_selectedNode.getType()))
- {
- _server = (ManagedServer)_selectedNode.getManagedObject();
- _virtualHostName = null;
- }
- else
- {
- TreeObject parent = _selectedNode.getParent();
- while (parent != null && !parent.getType().equals(NODE_TYPE_SERVER))
- {
- parent = parent.getParent();
- }
-
- if (parent != null && parent.getType().equals(NODE_TYPE_SERVER))
- {
- _server = (ManagedServer)parent.getManagedObject();
- }
-
- _virtualHostName = _selectedNode.getVirtualHost();
- }
-
- JMXServerRegistry serverRegistry = (JMXServerRegistry)ApplicationRegistry.getServerRegistry(_server);
- if(serverRegistry != null){
- _mbsc = serverRegistry.getServerConnection();
- }
- }
-
- public static ManagedServer getServer()
- {
- return _server;
- }
-
- public static String getVirtualHost()
- {
- return _virtualHostName;
- }
-
- private void showMBean(ManagedBean mbean) throws Exception
- {
- try
- {
- MBeanUtility.getMBeanInfo(mbean);
- }
- catch(Exception ex)
- {
- MBeanUtility.handleException(mbean, ex);
- return;
- }
-
- if (_tabFolder != null && !_tabFolder.isDisposed())
- {
- _tabFolder.dispose();
- }
-
- _tabFolder = MBeanTabFolderFactory.generateMBeanTabFolder(_form.getBody(),(JMXManagedObject)mbean,_mbsc);
-
- int tabIndex = 0;
- if (NOTIFICATIONS.equals(_selectedNode.getType()))
- {
- tabIndex = _tabFolder.getItemCount() -1;
- }
-
- TabItem tab = _tabFolder.getItem(tabIndex);
- // If folder is being set as visible after tab refresh, then the tab
- // doesn't have the focus.
- _tabFolder.setSelection(tabIndex);
- refreshTab(tab);
- }
-
- public void createPartControl(Composite parent)
- {
- // Create the Form
- _toolkit = new FormToolkit(parent.getDisplay());
- _form = _toolkit.createForm(parent);
- _form.getBody().setLayout(new FormLayout());
- _form.setText(APPLICATION_NAME);
-
- // Add selection listener for selection events in the Navigation view
- getSite().getPage().addSelectionListener(NavigationView.ID, _selectionListener);
-
- createNotificationsTabFolder();
-
- ViewUtility.setMBeanView(this);
-
- _backAction = new BackAction();
- getViewSite().getActionBars().getToolBarManager().add(_backAction);
- _backAction.setEnabled(false);
- _backHistory = new LinkedList<Object>();
- }
-
- private void refreshTab(TabItem tab)
- {
- if (tab == null)
- {
- return;
- }
-
- TabControl controller = (TabControl)tab.getData(TabControl.CONTROLLER);
- if(controller != null)
- {
- controller.refresh(_mbean);
- }
- }
-
- public void setFocus()
- {
- //_form.setFocus();
- }
-
- public void dispose()
- {
- _toolkit.dispose();
- super.dispose();
- }
-
-
- private void createNotificationsTabFolder()
- {
- _notificationTabFolder = new TabFolder(_form.getBody(), SWT.NONE);
- FormData layoutData = new FormData();
- layoutData.left = new FormAttachment(0);
- layoutData.top = new FormAttachment(0);
- layoutData.right = new FormAttachment(100);
- layoutData.bottom = new FormAttachment(100);
- _notificationTabFolder.setLayoutData(layoutData);
- _notificationTabFolder.setVisible(false);
-
- VHNotificationsTabControl controller = new VHNotificationsTabControl(_notificationTabFolder);
- TabItem tab = new TabItem(_notificationTabFolder, SWT.NONE);
- tab.setText(NOTIFICATIONS);
- tab.setData(TabControl.CONTROLLER, controller);
- tab.setControl(controller.getControl());
- }
-
- private void refreshNotificationPage()
- {
- TabItem tab = _notificationTabFolder.getItem(0);
- VHNotificationsTabControl controller = (VHNotificationsTabControl)tab.getData(TabControl.CONTROLLER);
- controller.refresh();
- _notificationTabFolder.setVisible(true);
- }
-
-
-
- private void generateTypeTabFolder() throws Exception
- {
- if (_typeTabFolder != null && !_typeTabFolder.isDisposed())
- {
- _typeTabFolder.dispose();
- }
-
- //Generates the full Queue/Connection/Exchange selection tab set
- _typeTabFolder = MBeanTabFolderFactory.generateMBeanTypeTabFolder(
- _form.getBody(), getServer(), getVirtualHost());
- refreshTab(_typeTabFolder.getItem(0));
- }
-
- private void showTypeTabFolder(String type) throws Exception
- {
- if (_typeTabFolder != null && !_typeTabFolder.isDisposed())
- {
- _typeTabFolder.dispose();
- }
-
- if (CONNECTION.equals(type))
- {
- //Generates the Connection selection tab
- _typeTabFolder = MBeanTabFolderFactory.generateConnectionTypeTabFolder(
- _form.getBody(), getServer(), getVirtualHost());
- refreshTab(_typeTabFolder.getItem(0));
- }
- else if (EXCHANGE.equals(type))
- {
- //Generates the Exchange selection tab
- _typeTabFolder = MBeanTabFolderFactory.generateExchangeTypeTabFolder(
- _form.getBody(), getServer(), getVirtualHost());
- refreshTab(_typeTabFolder.getItem(0));
- }
- else if (QUEUE.equals(type))
- {
- //Generates the Queue selection tab
- _typeTabFolder = MBeanTabFolderFactory.generateQueueTypeTabFolder(
- _form.getBody(), getServer(), getVirtualHost());
- refreshTab(_typeTabFolder.getItem(0));
- }
- }
-
- private void clearView()
- {
- if (_tabFolder != null && !_tabFolder.isDisposed())
- {
- _tabFolder.setVisible(false);
- }
-
- if (_typeTabFolder != null && !_typeTabFolder.isDisposed())
- {
- _typeTabFolder.setVisible(false);
- }
-
- if (_notificationTabFolder != null && !_notificationTabFolder.isDisposed())
- {
- _notificationTabFolder.setVisible(false);
- }
-
- _form.setText(APPLICATION_NAME);
- clearStatusBar();
- }
-
- public void mbeanUnregistered(ManagedBean mbean)
- {
- //if the mbean is actually open, clear the view and empty the Back history
- if(mbean == _mbean)
- {
- clearView();
- _backHistory.clear();
- _backAction.setEnabled(false);
- ViewUtility.popupInfoMessage("MBean Unregistered",
- "The open MBean was unregistered from the server.");
- }
- }
-
- public void refresh()
- {
- if(!ApplicationRegistry.isServerConnected(_server))
- {
- return;
- }
-
- if (_tabFolder != null && !_tabFolder.isDisposed())
- {
- if(_tabFolder.getVisible())
- {
- int selectedTab = _tabFolder.getSelectionIndex();
- TabItem tab = _tabFolder.getItem(selectedTab);
- TabControl controller = (TabControl) tab.getData(TabControl.CONTROLLER);
- if(controller != null)
- {
- controller.refresh(_mbean);
- }
- return;
- }
- }
-
- if (_typeTabFolder != null && !_typeTabFolder.isDisposed())
- {
-
- if(_typeTabFolder.getVisible())
- {
- int selectedTab = _typeTabFolder.getSelectionIndex();
- TabItem tab = _typeTabFolder.getItem(selectedTab);
- TabControl controller = (TabControl) tab.getData(TabControl.CONTROLLER);
- if(controller != null)
- {
- controller.refresh(_mbean);
- }
- return;
- }
- }
-
- if (_notificationTabFolder != null && !_notificationTabFolder.isDisposed())
- {
- if(_notificationTabFolder.getVisible())
- {
- int selectedTab = _notificationTabFolder.getSelectionIndex();
- TabItem tab = _notificationTabFolder.getItem(selectedTab);
- TabControl controller = (TabControl) tab.getData(TabControl.CONTROLLER);
- if(controller != null)
- {
- controller.refresh(_mbean);
- }
- return;
- }
- }
- }
-
- public void populateStatusBar(Image icon, String message)
- {
- IActionBars bars = getViewSite().getActionBars();
- bars.getStatusLineManager().setMessage(icon, message);
- }
-
- public void populateStatusBar(String message)
- {
- IActionBars bars = getViewSite().getActionBars();
- bars.getStatusLineManager().setMessage(message);
- }
-
- public void clearStatusBar()
- {
- populateStatusBar("");
- }
-
- public void back() throws Exception
- {
- if(_backHistory.isEmpty())
- {
- return;
- }
-
- Object previous = _backHistory.removeLast();
- if(_backHistory.isEmpty())
- {
- //if this is the last history item, disable the action button
- _backAction.setEnabled(false);
- }
-
- if(previous instanceof ManagedBean)
- {
- openMBean((ManagedBean)previous, true);
- }
- else if (previous instanceof TreeObject)
- {
- _mbean = null;
- clearView();
- setFormTitle();
-
- TreeObject node = (TreeObject) previous;
- String mbeanType = node.getType();
-
- if (NODE_TYPE_TYPEINSTANCE.equals(mbeanType))
- {
- generateTypeTabFolder();
- }
- else if (NODE_TYPE_MBEANTYPE.equals(mbeanType))
- {
- showTypeTabFolder(node.getName());
- }
- }
-
- _form.layout(true);
- _form.getBody().layout(true, true);
- }
-}
diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/NavigationView.java b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/NavigationView.java
deleted file mode 100644
index 4a956aaeab..0000000000
--- a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/NavigationView.java
+++ /dev/null
@@ -1,1358 +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;
-
-import org.eclipse.jface.preference.PreferenceStore;
-import org.eclipse.jface.viewers.DoubleClickEvent;
-import org.eclipse.jface.viewers.IDoubleClickListener;
-import org.eclipse.jface.viewers.IFontProvider;
-import org.eclipse.jface.viewers.IStructuredSelection;
-import org.eclipse.jface.viewers.ITreeContentProvider;
-import org.eclipse.jface.viewers.ITreeViewerListener;
-import org.eclipse.jface.viewers.LabelProvider;
-import org.eclipse.jface.viewers.StructuredSelection;
-import org.eclipse.jface.viewers.TreeExpansionEvent;
-import org.eclipse.jface.viewers.TreeViewer;
-import org.eclipse.jface.viewers.Viewer;
-import org.eclipse.jface.viewers.ViewerSorter;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.graphics.Font;
-import org.eclipse.swt.graphics.Image;
-import org.eclipse.swt.layout.GridData;
-import org.eclipse.swt.layout.GridLayout;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Display;
-import org.eclipse.swt.widgets.Event;
-import org.eclipse.swt.widgets.Listener;
-import org.eclipse.swt.widgets.Menu;
-import org.eclipse.swt.widgets.MenuItem;
-import org.eclipse.swt.widgets.Shell;
-import org.eclipse.swt.widgets.Tree;
-import org.eclipse.swt.widgets.TreeItem;
-import org.eclipse.ui.IWorkbenchWindow;
-import org.eclipse.ui.PlatformUI;
-import org.eclipse.ui.part.ViewPart;
-
-import org.apache.qpid.management.common.mbeans.ConfigurationManagement;
-import org.apache.qpid.management.common.mbeans.LoggingManagement;
-import org.apache.qpid.management.common.mbeans.ServerInformation;
-import org.apache.qpid.management.common.mbeans.UserManagement;
-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.ui.ManagedObject;
-import org.apache.qpid.management.ui.ManagedServer;
-import org.apache.qpid.management.ui.ServerRegistry;
-import org.apache.qpid.management.ui.exceptions.InfoRequiredException;
-import org.apache.qpid.management.ui.exceptions.ManagementConsoleException;
-import org.apache.qpid.management.ui.jmx.JMXServerRegistry;
-import org.apache.qpid.management.ui.jmx.MBeanUtility;
-
-import static org.apache.qpid.management.ui.ApplicationRegistry.DATA_DIR;
-import static org.apache.qpid.management.ui.Constants.*;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.concurrent.ConcurrentHashMap;
-
-/**
- * Navigation View for navigating the managed servers and managed beans on
- * those servers
- * @author Bhupendra Bhardwaj
- */
-public class NavigationView extends ViewPart
-{
- public static final String ID = "org.apache.qpid.management.ui.navigationView";
- public static final String INI_FILENAME = DATA_DIR + File.separator + "qpidmc_navigation.ini";
-
- private static final String INI_SERVERS = "Servers";
- private static final String INI_QUEUES = QUEUE + "s";
- private static final String INI_CONNECTIONS = CONNECTION + "s";
- private static final String INI_EXCHANGES = EXCHANGE + "s";
-
- private TreeViewer _treeViewer = null;
- private TreeObject _serversRootNode = null;
-
- private PreferenceStore _preferences;
- // Map of connected servers
- private ConcurrentHashMap<ManagedServer, TreeObject> _managedServerMap = new ConcurrentHashMap<ManagedServer, TreeObject>();
-
- private static HashSet<String> _serverTopLevelMBeans = new HashSet<String>();
- {
- _serverTopLevelMBeans.add(UserManagement.TYPE);
- _serverTopLevelMBeans.add(LoggingManagement.TYPE);
- _serverTopLevelMBeans.add(ConfigurationManagement.TYPE);
- _serverTopLevelMBeans.add(ServerInformation.TYPE);
- }
-
- private void createTreeViewer(Composite parent)
- {
- _treeViewer = new TreeViewer(parent);
- _treeViewer.setContentProvider(new ContentProviderImpl());
- _treeViewer.setLabelProvider(new LabelProviderImpl());
- _treeViewer.setSorter(new ViewerSorterImpl());
-
- // layout the tree viewer below the label field, to cover the area
- GridData layoutData = new GridData();
- layoutData.grabExcessHorizontalSpace = true;
- layoutData.grabExcessVerticalSpace = true;
- layoutData.horizontalAlignment = GridData.FILL;
- layoutData.verticalAlignment = GridData.FILL;
- _treeViewer.getControl().setLayoutData(layoutData);
- _treeViewer.setUseHashlookup(true);
-
- createListeners();
- }
-
- /**
- * Creates listeners for the JFace treeviewer
- */
- private void createListeners()
- {
- _treeViewer.addDoubleClickListener(new IDoubleClickListener()
- {
- public void doubleClick(DoubleClickEvent event)
- {
- IStructuredSelection ss = (IStructuredSelection) event.getSelection();
- if ((ss == null) || (ss.getFirstElement() == null))
- {
- return;
- }
-
- boolean state = _treeViewer.getExpandedState(ss.getFirstElement());
- _treeViewer.setExpandedState(ss.getFirstElement(), !state);
- }
- });
-
- _treeViewer.addTreeListener(new ITreeViewerListener()
- {
- public void treeExpanded(TreeExpansionEvent event)
- {
- getSite().getShell().getDisplay().asyncExec(
- new Runnable()
- {
- public void run()
- {
- _treeViewer.refresh();
- }
- });
- }
-
- public void treeCollapsed(TreeExpansionEvent event)
- {
- getSite().getShell().getDisplay().asyncExec(
- new Runnable()
- {
- public void run()
- {
- _treeViewer.refresh();
- }
- });
- }
- });
-
- // This listener is for popup menu, which pops up if a queue,exchange or connection is selected
- // with right click.
- _treeViewer.getTree().addListener(SWT.MenuDetect, new Listener()
- {
- private Display display = getSite().getShell().getDisplay();
- private final Shell shell = new Shell(display);
-
- public void handleEvent(Event event)
- {
- Tree widget = (Tree) event.widget;
- TreeItem[] items = widget.getSelection();
- if (items == null)
- {
- return;
- }
-
- // Get the selected node
- final TreeObject selectedNode = (TreeObject) items[0].getData();
- final TreeObject parentNode = selectedNode.getParent();
-
- // This popup is only for mbeans and only connection,exchange and queue types
- if ((parentNode == null) || !MBEAN.equals(selectedNode.getType())
- || !(CONNECTION.equals(parentNode.getName()) || QUEUE.equals(parentNode.getName())
- || EXCHANGE.equals(parentNode.getName())))
- {
- return;
- }
-
- Menu menu = new Menu(shell, SWT.POP_UP);
- MenuItem item = new MenuItem(menu, SWT.PUSH);
- // Add the action item, which will remove the node from the tree if selected
- item.setText(ACTION_REMOVE_MBEANNODE);
- item.addListener(SWT.Selection, new Listener()
- {
- public void handleEvent(Event e)
- {
- removeManagedObject(parentNode, (ManagedBean) selectedNode.getManagedObject(), true);
- _treeViewer.refresh();
- // set the selection to the parent node
- _treeViewer.setSelection(new StructuredSelection(parentNode));
- }
- });
- menu.setLocation(event.x, event.y);
- menu.setVisible(true);
- while (!menu.isDisposed() && menu.isVisible())
- {
- if (!display.readAndDispatch())
- {
- display.sleep();
- }
- }
-
- menu.dispose();
- }
- });
- }
-
- /**
- * Creates Qpid Server connection
- * @param server
- * @throws Exception
- */
- private void createJMXServerConnection(ManagedServer server) throws Exception
- {
- // Currently Qpid Management Console only supports JMX MBeanServer
- JMXServerRegistry serverRegistry = new JMXServerRegistry(server);
-
- try
- {
- //determine the management API version of the server just connected to
- MBeanUtility.classifyManagementApiVersion(server, serverRegistry);
- }
- catch (Exception e)
- {
- //Exception classifying the server API, clean up the connection and rethrow
- serverRegistry.closeServerConnection();
- throw e;
- }
-
- //check that the console supports the API major version encountered, otherwise abort.
- ApiVersion serverAPI = serverRegistry.getManagementApiVersion();
-
- int serverMajor = serverAPI.getMajor();
- int supportedMajor = ApplicationRegistry.SUPPORTED_QPID_JMX_API_MAJOR_VERSION;
-
- if(serverMajor > supportedMajor)
- {
- serverRegistry.closeServerConnection();
- throw new ManagementConsoleException("The server management API version encountered is not supported"
- + " by this console release. Please check for an updated console release.");
- }
-
- //connection succeeded, add the ServerRegistry to the ApplicationRegistry
- ApplicationRegistry.addServer(server, serverRegistry);
- }
-
- /**
- * Adds a new server node in the navigation view if server connection is successful.
- * @param transportProtocol
- * @param host
- * @param port
- * @param domain
- * @throws Exception
- */
- public void addNewServer(String host, int port, String domain, String user, String pwd)
- throws Exception
- {
- ManagedServer managedServer = new ManagedServer(host, port, domain, user, pwd);
-
- String server = managedServer.getName();
- List<TreeObject> list = _serversRootNode.getChildren();
- for (TreeObject node : list)
- {
- ManagedServer nodeServer = (ManagedServer)node.getManagedObject();
- if (server.equals(nodeServer.getName()))
- {
- // Server is already in the list of added servers, so now connect it.
- // Set the server node as selected and then connect it.
- _treeViewer.setSelection(new StructuredSelection(node));
- reconnect(user, pwd);
-
- return;
- }
- }
-
- // The server is not in the list of already added servers, so now connect and add it.
- createJMXServerConnection(managedServer);
-
- // Server connection is successful. Now add the server in the tree
- TreeObject serverNode = new TreeObject(server, NODE_TYPE_SERVER);
- serverNode.setManagedObject(managedServer);
- _serversRootNode.addChild(serverNode);
-
- // Add server in the connected server map
- _managedServerMap.put(managedServer, serverNode);
-
- // populate the server tree
- try
- {
- populateServer(serverNode);
- }
- catch (SecurityException ex)
- {
- disconnect(managedServer);
- throw ex;
- }
-
- // Add the Queue/Exchanges/Connections from config file into the navigation tree
- addConfiguredItems(managedServer);
-
- _treeViewer.refresh();
-
- expandInitialMBeanView(serverNode);
-
- //(re)select the server node now that it is connected to force a selectionEvent
- _treeViewer.setSelection(new StructuredSelection(serverNode));
- _treeViewer.refresh();
-
- // save server address in file
- addServerInConfigFile(server);
- }
-
- /**
- * Create the config file, if it doesn't already exist.
- * Exits the application if the file could not be created.
- */
- private void createConfigFile()
- {
- File dir = new File(DATA_DIR);
- if (!dir.exists())
- {
- if(!dir.mkdir())
- {
- System.out.println("Could not create application data directory " + DATA_DIR);
- System.exit(1);
- }
- }
-
- File file = new File(INI_FILENAME);
- try
- {
- if (!file.exists())
- {
- file.createNewFile();
- }
- }
- catch (IOException ex)
- {
- System.out.println("Could not write to the file " + INI_FILENAME);
- System.out.println(ex);
- System.exit(1);
- }
- }
-
- /**
- * Server addresses are stored in a file. When user launches the application again, the
- * server addresses are picked up from the file and shown in the navigfation view. This method
- * adds the server address in a file, when a new server is added in the navigation view.
- * @param serverAddress
- */
- private void addServerInConfigFile(String serverAddress)
- {
- // Check if the address already exists
- List<String> list = getServerListFromFile();
- if ((list != null) && list.contains(serverAddress))
- {
- return;
- }
-
- // Get the existing server list and add to that
- String servers = _preferences.getString(INI_SERVERS);
- String value = (servers.length() != 0) ? (servers + "," + serverAddress) : serverAddress;
- _preferences.putValue(INI_SERVERS, value);
- try
- {
- _preferences.save();
- }
- catch (IOException ex)
- {
- System.err.println("Could not add " + serverAddress + " in " + INI_SERVERS + " (" + INI_FILENAME + ")");
- System.out.println(ex);
- }
- }
-
- /**
- * Adds the item (Queue/Exchange/Connection) to the config file
- * @param server
- * @param virtualhost
- * @param type - (Queue or Exchange or Connection)
- * @param name - item name
- */
- private void addItemInConfigFile(TreeObject node)
- {
- ManagedBean mbean = (ManagedBean) node.getManagedObject();
- String server = mbean.getServer().getName();
- String virtualhost = mbean.getVirtualHostName();
- String type = node.getParent().getName() + "s";
- String name = node.getName();
- String itemKey = server + "." + virtualhost + "." + type;
-
- // Check if the item already exists in the config file
- List<String> list = getConfiguredItemsFromFile(itemKey);
- if ((list != null) && list.contains(name))
- {
- return;
- }
-
- // Add this item to the existing list of items
- String items = _preferences.getString(itemKey);
- String value = (items.length() != 0) ? (items + "," + name) : name;
- _preferences.putValue(itemKey, value);
- try
- {
- _preferences.save();
- }
- catch (IOException ex)
- {
- System.err.println("Could not add " + name + " in " + itemKey + " (" + INI_FILENAME + ")");
- System.out.println(ex);
- }
- }
-
- private void removeItemFromConfigFile(TreeObject node)
- {
- ManagedBean mbean = (ManagedBean) node.getManagedObject();
- String server = mbean.getServer().getName();
- String vHost = mbean.getVirtualHostName();
- String type = node.getParent().getName() + "s";
- String itemKey = server + "." + vHost + "." + type;
-
- List<String> list = getConfiguredItemsFromFile(itemKey);
- if (list.contains(node.getName()))
- {
- list.remove(node.getName());
- String value = "";
- for (String item : list)
- {
- value += item + ",";
- }
-
- value = (value.lastIndexOf(",") != -1) ? value.substring(0, value.lastIndexOf(",")) : value;
-
- _preferences.putValue(itemKey, value);
- try
- {
- _preferences.save();
- }
- catch (IOException ex)
- {
- System.err.println("Error in updating the config file " + INI_FILENAME);
- System.out.println(ex);
- }
- }
- }
-
- //check if the MBeanInfo can be retrieved.
- private boolean haveAccessPermission(ManagedBean mbean)
- {
- try
- {
- MBeanUtility.getMBeanInfo(mbean);
- }
- catch(Exception ex)
- {
- return false;
- }
-
- return true;
- }
-
- /**
- * Queries the qpid server for MBeans and populates the navigation view with all MBeans for
- * the given server node.
- * @param serverNode
- * @throws Exception
- */
- private void populateServer(TreeObject serverNode) throws Exception
- {
- ManagedServer server = (ManagedServer) serverNode.getManagedObject();
- String domain = server.getDomain();
-
- List<ManagedBean> mbeans = MBeanUtility.getManagedObjectsForDomain(server, domain);
- for (ManagedBean mbean : mbeans)
- {
- mbean.setServer(server);
- ServerRegistry serverRegistry = ApplicationRegistry.getServerRegistry(server);
- serverRegistry.addManagedObject(mbean);
-
- // Add all mbeans other than Connections, Exchanges and Queues. Because these will be added
- // manually by selecting from MBeanView
- if (!(mbean.isConnection() || mbean.isExchange() || mbean.isQueue()))
- {
- //if we cant get the MBeanInfo then we cant display the mbean, so dont add it to the tree
- if (haveAccessPermission(mbean))
- {
- addManagedBean(serverNode, mbean);
- }
- }
- }
-
- }
-
- /**
- * Add these three types - Connection, Exchange, Queue
- * By adding these, these will always be available, even if there are no mbeans under thse types
- * This is required because, the mbeans will be added from mbeanview, by selecting from the list
- * @param parent Node
- */
- private void addDefaultNodes(TreeObject parent)
- {
- TreeObject typeChild = new TreeObject(CONNECTION, NODE_TYPE_MBEANTYPE);
- typeChild.setParent(parent);
- typeChild.setVirtualHost(parent.getVirtualHost());
- typeChild = new TreeObject(EXCHANGE, NODE_TYPE_MBEANTYPE);
- typeChild.setParent(parent);
- typeChild.setVirtualHost(parent.getVirtualHost());
- typeChild = new TreeObject(QUEUE, NODE_TYPE_MBEANTYPE);
- typeChild.setParent(parent);
- typeChild.setVirtualHost(parent.getVirtualHost());
-
- // Add common notification node for virtual host
- TreeObject notificationNode = new TreeObject(NOTIFICATIONS, NOTIFICATIONS);
- notificationNode.setParent(parent);
- notificationNode.setVirtualHost(parent.getVirtualHost());
- }
-
- /**
- * Checks if a particular mbeantype is already there in the navigation view for a domain.
- * This is used while populating domain with mbeans.
- * @param parent
- * @param typeName
- * @return Node if given mbeantype already exists, otherwise null
- */
- private TreeObject getMBeanTypeNode(TreeObject parent, String typeName)
- {
- List<TreeObject> childNodes = parent.getChildren();
- for (TreeObject child : childNodes)
- {
- if ((NODE_TYPE_MBEANTYPE.equals(child.getType()) || NODE_TYPE_TYPEINSTANCE.equals(child.getType()))
- && typeName.equals(child.getName()))
- {
- return child;
- }
- }
-
- return null;
- }
-
- private boolean doesMBeanNodeAlreadyExist(TreeObject typeNode, String mbeanName)
- {
- List<TreeObject> childNodes = typeNode.getChildren();
- for (TreeObject child : childNodes)
- {
- if (MBEAN.equals(child.getType()) && mbeanName != null && mbeanName.equals(child.getName()))
- {
- return true;
- }
- }
-
- return false;
- }
-
- /**
- * Adds the given MBean to the given domain node.
- * sample ObjectNames -
- * org.apache.qpid:type=VirtualHost.VirtualHostManager,VirtualHost=localhost
- * org.apache.qpid:type=VirtualHost.Queue,VirtualHost=test,name=ping_1
- * @param parent parent tree node to add the mbean to
- * @param mbean mbean to add
- */
- private void addManagedBean(TreeObject parent, ManagedBean mbean)
- {
- String name = mbean.getName();
- // Split the mbean type into array of Strings, to create hierarchy
- // eg. type=VirtualHost.VirtualHostManager,VirtualHost=localhost will be:
- // localhost->VirtualHostManager
- // eg. type=org.apache.qpid:type=VirtualHost.Queue,VirtualHost=test,name=ping will be:
- // test->Queue->ping
- String[] types = mbean.getType().split("\\.");
- TreeObject typeNode = null;
- TreeObject parentNode = parent;
-
- // Run this loop till all nodes(hierarchy) for this mbean are created. This loop only creates
- // all the required parent nodes for the mbean
- for (int i = 0; i < types.length; i++)
- {
- String type = types[i];
-
- if(types.length == 1 && _serverTopLevelMBeans.contains(type))
- {
- //This mbean is not to be contained in a type hierarchy
- //Just add it as a child of the server node.
- break;
- }
-
- String valueOftype = mbean.getProperty(type);
- // If value is not null, then there will be a parent node for this mbean
- // eg. for type=VirtualHost the value is "test"
- typeNode = getMBeanTypeNode(parentNode, type);
-
- // create the type node if not already created
- if (typeNode == null)
- {
- // If the ObjectName doesn't have name property, that means there will be only one instance
- // of this mbean for given "type". So there will be no type node created for this mbean.
- if ((name == null) && (i == (types.length - 1)))
- {
- break;
- }
-
- // create a node for "type"
- typeNode = createTypeNode(parentNode, type);
- if (!type.equals(VIRTUAL_HOST))
- {
- typeNode.setVirtualHost(mbean.getVirtualHostName());
- }
- }
-
- // now type node create becomes the parent node for next node in hierarchy
- parentNode = typeNode;
-
- /*
- * Now create instances node for this type if value exists.
- */
- if (valueOftype == null)
- {
- // No instance node will be created when value is null (eg type=Queue)
- break;
- }
-
- // For different virtual hosts, the nodes with given value will be created.
- // eg type=VirtualHost, value=test
- typeNode = getMBeanTypeNode(parentNode, valueOftype);
- if (typeNode == null)
- {
- typeNode = createTypeInstanceNode(parentNode, valueOftype);
- typeNode.setVirtualHost(mbean.getVirtualHostName());
-
- // Create default nodes for VHost instances
- if (type.equals(VIRTUAL_HOST))
- {
- addDefaultNodes(typeNode);
- }
- }
-
- parentNode = typeNode;
- }
-
- if (typeNode == null)
- {
- typeNode = parentNode;
- }
-
- // Check if an MBean is already added
- if (doesMBeanNodeAlreadyExist(typeNode, name))
- {
- return;
- }
-
- // Add the mbean node now
- TreeObject mbeanNode = new TreeObject(mbean);
- mbeanNode.setVirtualHost(mbean.getVirtualHostName());
- mbeanNode.setParent(typeNode);
-
- // Add the mbean to the config file
- if (mbean.isQueue() || mbean.isExchange() || mbean.isConnection())
- {
- addItemInConfigFile(mbeanNode);
- }
- }
-
- private TreeObject createTypeNode(TreeObject parent, String name)
- {
- TreeObject typeNode = new TreeObject(name, NODE_TYPE_MBEANTYPE);
- typeNode.setParent(parent);
-
- return typeNode;
- }
-
- private TreeObject createTypeInstanceNode(TreeObject parent, String name)
- {
- TreeObject typeNode = new TreeObject(name, NODE_TYPE_TYPEINSTANCE);
- typeNode.setParent(parent);
-
- return typeNode;
- }
-
- /**
- * Removes all the child nodes of the given parent node. Used when closing a server.
- * @param parent
- */
- private void removeManagedObject(TreeObject parent)
- {
- if(parent == null)
- {
- return;
- }
-
- List<TreeObject> list = parent.getChildren();
- for (TreeObject child : list)
- {
- removeManagedObject(child);
- }
-
- list.clear();
- }
-
- /**
- * Removes the mbean from the tree
- * @param parent
- * @param mbean
- */
- private void removeManagedObject(TreeObject parent, ManagedBean mbean, boolean removeFromConfigFile)
- {
- List<TreeObject> list = parent.getChildren();
- TreeObject objectToRemove = null;
- for (TreeObject child : list)
- {
- if (MBEAN.equals(child.getType()))
- {
- String name = (mbean.getName() != null) ? mbean.getName() : mbean.getType();
- if (child.getName().equals(name))
- {
- objectToRemove = child;
-
- break;
- }
- }
- else
- {
- removeManagedObject(child, mbean, removeFromConfigFile);
- }
- }
-
- if (objectToRemove != null)
- {
- list.remove(objectToRemove);
- if(removeFromConfigFile)
- {
- removeItemFromConfigFile(objectToRemove);
- }
- }
-
- }
-
- /**
- * Closes the Qpid server connection
- */
- public void disconnect() throws Exception
- {
- TreeObject selectedNode = getSelectedServerNode();
- ManagedServer managedServer = (ManagedServer) selectedNode.getManagedObject();
- disconnect(managedServer);
- }
-
- private void disconnect(ManagedServer managedServer) throws Exception
- {
- if (!_managedServerMap.containsKey(managedServer))
- {
- return;
- }
-
- // Close server connection
- ServerRegistry serverRegistry = ApplicationRegistry.getServerRegistry(managedServer);
- if (serverRegistry == null) // server connection is already closed
- {
- return;
- }
-
- // Add server to the closed server list and the worker thread will remove the server from required places.
- ApplicationRegistry.serverConnectionClosed(managedServer);
-
- //close the connection
- serverRegistry.closeServerConnection();
- }
-
- /**
- * Connects the selected server node
- * @throws Exception
- */
- public void reconnect(String user, String password) throws Exception
- {
- TreeObject selectedNode = getSelectedServerNode();
- ManagedServer managedServer = (ManagedServer) selectedNode.getManagedObject();
- if (_managedServerMap.containsKey(managedServer))
- {
- throw new InfoRequiredException("Server " + managedServer.getName() + " is already connected");
- }
-
- managedServer.setUser(user);
- managedServer.setPassword(password);
- createJMXServerConnection(managedServer);
-
- // put the server in the managed server map
- _managedServerMap.put(managedServer, selectedNode);
-
- try
- {
- // populate the server tree now
- populateServer(selectedNode);
- }
- catch (SecurityException ex)
- {
- disconnect(managedServer);
- throw ex;
- }
-
-
- // Add the Queue/Exchanges/Connections from config file into the navigation tree
- addConfiguredItems(managedServer);
-
- expandInitialMBeanView(selectedNode);
-
- //(re)select the server node now that it is connected to force a selectionEvent
- _treeViewer.setSelection(new StructuredSelection(selectedNode));
- _treeViewer.refresh();
- }
-
- private void expandInitialMBeanView(TreeObject serverNode)
- {
- if (serverNode.getChildren().size() == 0 )
- {
- return;
- }
- else
- {
- _treeViewer.setExpandedState(serverNode , true);
- }
-
- List<TreeObject> children = serverNode.getChildren();
- for (TreeObject child : children)
- {
- if (child.getChildren().size() > 0)
- {
- _treeViewer.setExpandedState(child, true);
- }
- }
- }
-
- /**
- * Adds the items(queues/exchanges/connectins) from config file to the server tree
- * @param server
- */
- private void addConfiguredItems(ManagedServer server)
- {
- ServerRegistry serverRegistry = ApplicationRegistry.getServerRegistry(server);
- List<String> list = serverRegistry.getVirtualHosts();
- for (String virtualHost : list)
- {
- // Add Queues
- String itemKey = server.getName() + "." + virtualHost + "." + INI_QUEUES;
- List<String> items = getConfiguredItemsFromFile(itemKey);
- List<ManagedBean> mbeans = serverRegistry.getQueues(virtualHost);
- addConfiguredItems(items, mbeans);
-
- // Add Exchanges
- itemKey = server.getName() + "." + virtualHost + "." + INI_EXCHANGES;
- items = getConfiguredItemsFromFile(itemKey);
- mbeans = serverRegistry.getExchanges(virtualHost);
- addConfiguredItems(items, mbeans);
-
- // Add Connections
- itemKey = server.getName() + "." + virtualHost + "." + INI_CONNECTIONS;
- items = getConfiguredItemsFromFile(itemKey);
- mbeans = serverRegistry.getConnections(virtualHost);
- addConfiguredItems(items, mbeans);
- }
- }
-
- /**
- * Gets the mbeans corresponding to the items and adds those to the navigation tree
- * @param items
- * @param mbeans
- */
- private void addConfiguredItems(List<String> items, List<ManagedBean> mbeans)
- {
- if ((items == null) || (items.isEmpty() || (mbeans == null)) || mbeans.isEmpty())
- {
- return;
- }
-
- for (String item : items)
- {
- for (ManagedBean mbean : mbeans)
- {
- if (item.equals(mbean.getName()))
- {
- addManagedBean(mbean);
-
- break;
- }
- }
- }
- }
-
- /**
- * Closes the Qpid server connection if not already closed and removes the server node from the navigation view and
- * also from the ini file stored in the system.
- * @throws Exception
- */
- public void removeServer() throws Exception
- {
- disconnect();
-
- // Remove from the Tree
- String serverNodeName = getSelectedServerNode().getName();
- List<TreeObject> list = _serversRootNode.getChildren();
- TreeObject objectToRemove = null;
- for (TreeObject child : list)
- {
- if (child.getName().equals(serverNodeName))
- {
- objectToRemove = child;
-
- break;
- }
- }
-
- if (objectToRemove != null)
- {
- list.remove(objectToRemove);
- }
-
- _treeViewer.refresh();
-
- // Remove from the ini file
- removeServerFromConfigFile(serverNodeName);
- }
-
- private void removeServerFromConfigFile(String serverNodeName)
- {
- List<String> serversList = getServerListFromFile();
- serversList.remove(serverNodeName);
-
- String value = "";
- for (String item : serversList)
- {
- value += item + ",";
- }
-
- value = (value.lastIndexOf(",") != -1) ? value.substring(0, value.lastIndexOf(",")) : value;
-
- _preferences.putValue(INI_SERVERS, value);
-
- try
- {
- _preferences.save();
- }
- catch (IOException ex)
- {
- System.err.println("Error in updating the config file " + INI_FILENAME);
- System.out.println(ex);
- }
- }
-
- /**
- * @return the server addresses from the ini file
- * @throws Exception
- */
- private List<String> getServerListFromFile()
- {
- return getConfiguredItemsFromFile(INI_SERVERS);
- }
-
- /**
- * Returns the list of items from the config file.
- * sample ini file:
- * Servers=localhost:8999,127.0.0.1:8999
- * localhost.virtualhost1.Queues=queue1,queue2
- * localhost.virtualhost1.Exchanges=exchange1,exchange2
- * localhost.virtualhost2.Connections=conn1
- * @param key
- * @return
- */
- private List<String> getConfiguredItemsFromFile(String key)
- {
- List<String> list = new ArrayList<String>();
- String items = _preferences.getString(key);
- if (items.length() != 0)
- {
- String[] array = items.split(",");
- for (String item : array)
- {
- list.add(item);
- }
- }
-
- return list;
- }
-
- public TreeObject getSelectedServerNode() throws Exception
- {
- IStructuredSelection ss = (IStructuredSelection) _treeViewer.getSelection();
- TreeObject selectedNode = (TreeObject) ss.getFirstElement();
- if (ss.isEmpty() || (selectedNode == null) || (!selectedNode.getType().equals(NODE_TYPE_SERVER)))
- {
- throw new InfoRequiredException("Please select the server");
- }
-
- return selectedNode;
- }
-
- /**
- * This is a callback that will allow us to create the viewer and initialize
- * it.
- */
- public void createPartControl(Composite parent)
- {
- Composite composite = new Composite(parent, SWT.NONE);
- GridLayout gridLayout = new GridLayout();
- gridLayout.marginHeight = 2;
- gridLayout.marginWidth = 2;
- gridLayout.horizontalSpacing = 0;
- gridLayout.verticalSpacing = 2;
- composite.setLayout(gridLayout);
-
- createTreeViewer(composite);
- _serversRootNode = new TreeObject(NAVIGATION_ROOT, "ROOT");
-
- _treeViewer.setInput(_serversRootNode);
- // set viewer as selection event provider for MBeanView
- getSite().setSelectionProvider(_treeViewer);
-
- // Start worker thread to refresh tree for added or removed objects
- (new Thread(new Worker())).start();
-
- createConfigFile();
- _preferences = new PreferenceStore(INI_FILENAME);
-
- try
- {
- _preferences.load();
- }
- catch (IOException ex)
- {
- System.out.println(ex);
- }
-
- // load the list of servers already added from file
- List<String> serversList = getServerListFromFile();
- if (serversList != null)
- {
- for (String serverAddress : serversList)
- {
- String[] server = serverAddress.split(":");
- ManagedServer managedServer = new ManagedServer(server[0], Integer.parseInt(server[1]), "org.apache.qpid");
- TreeObject serverNode = new TreeObject(serverAddress, NODE_TYPE_SERVER);
- serverNode.setManagedObject(managedServer);
- _serversRootNode.addChild(serverNode);
- }
- }
-
- _treeViewer.refresh();
-
- }
-
- /**
- * Passing the focus request to the viewer's control.
- */
- public void setFocus()
- { }
-
- public void refresh()
- {
- _treeViewer.refresh();
- }
-
- /**
- * Content provider class for the tree viewer
- */
- private static class ContentProviderImpl implements ITreeContentProvider
- {
- public Object[] getElements(Object parent)
- {
- return getChildren(parent);
- }
-
- public Object[] getChildren(final Object parentElement)
- {
- final TreeObject node = (TreeObject) parentElement;
-
- return node.getChildren().toArray(new TreeObject[0]);
- }
-
- public Object getParent(final Object element)
- {
- final TreeObject node = (TreeObject) element;
-
- return node.getParent();
- }
-
- public boolean hasChildren(final Object element)
- {
- final TreeObject node = (TreeObject) element;
-
- return !node.getChildren().isEmpty();
- }
-
- public void inputChanged(final Viewer viewer, final Object oldInput, final Object newInput)
- {
- // Do nothing
- }
-
- public void dispose()
- {
- // Do nothing
- }
- }
-
- /**
- * Label provider class for the tree viewer
- */
- private class LabelProviderImpl extends LabelProvider implements IFontProvider
- {
- public Image getImage(Object element)
- {
- TreeObject node = (TreeObject) element;
- if (node.getType().equals(NOTIFICATIONS))
- {
- return ApplicationRegistry.getImage(NOTIFICATION_IMAGE);
- }
- else if (!node.getType().equals(MBEAN))
- {
- if (_treeViewer.getExpandedState(node))
- {
- return ApplicationRegistry.getImage(OPEN_FOLDER_IMAGE);
- }
- else
- {
- return ApplicationRegistry.getImage(CLOSED_FOLDER_IMAGE);
- }
-
- }
- else
- {
- ManagedObject obj = node.getManagedObject();
- if(obj instanceof ManagedBean)
- {
- ManagedBean mbean = (ManagedBean) obj;
- String mbeanType = mbean.getType();
-
- if(mbeanType.equals(LoggingManagement.TYPE))
- {
- return ApplicationRegistry.getImage(LOGGING_MANAGEMENT_IMAGE);
- }
- else if(mbeanType.equals(UserManagement.TYPE))
- {
- return ApplicationRegistry.getImage(USER_MANAGEMENT_IMAGE);
- }
- else if(mbeanType.equals(ConfigurationManagement.TYPE))
- {
- return ApplicationRegistry.getImage(CONFIGURATION_MANAGEMENT_IMAGE);
- }
- else if(mbeanType.equals(ServerInformation.TYPE))
- {
- return ApplicationRegistry.getImage(SERVER_INFO_IMAGE);
- }
- else if(mbeanType.equals("VirtualHost.VirtualHostManager"))
- {
- return ApplicationRegistry.getImage(VHOST_MANAGER_IMAGE);
- }
- else
- {
- return ApplicationRegistry.getImage(MBEAN_IMAGE);
- }
-
- }
- else
- {
- return ApplicationRegistry.getImage(MBEAN_IMAGE);
- }
- }
- }
-
- public String getText(Object element)
- {
- TreeObject node = (TreeObject) element;
- if (node.getType().equals(NODE_TYPE_MBEANTYPE))
- {
- return node.getName() + "s";
- }
- else
- {
- return node.getName();
- }
- }
-
- public Font getFont(Object element)
- {
- TreeObject node = (TreeObject) element;
- if (node.getType().equals(NODE_TYPE_SERVER))
- {
- if (node.getChildren().isEmpty())
- {
- return ApplicationRegistry.getFont(FONT_NORMAL);
- }
- else
- {
- return ApplicationRegistry.getFont(FONT_BOLD);
- }
- }
-
- return ApplicationRegistry.getFont(FONT_NORMAL);
- }
- } // End of LabelProviderImpl
-
- private static class ViewerSorterImpl extends ViewerSorter
- {
- public int category(Object element)
- {
- TreeObject node = (TreeObject) element;
- if (node.getType().equals(MBEAN))
- {
- return 1;
- }
- if (node.getType().equals(NOTIFICATIONS))
- {
- return 2;
- }
- return 3;
- }
- }
-
- /**
- * Worker thread, which keeps looking for new ManagedObjects to be added and
- * unregistered objects to be removed from the tree.
- * @author Bhupendra Bhardwaj
- */
- private class Worker implements Runnable
- {
- public void run()
- {
- while (true)
- {
- if (!_managedServerMap.isEmpty())
- {
- refreshRemovedObjects();
- refreshClosedServerConnections();
- }
-
- try
- {
- Thread.sleep(2000);
- }
- catch (InterruptedException ex)
- {
- //ignore
- }
-
- } // end of while loop
- } // end of run method.
- } // end of Worker class
-
- /**
- * Adds the mbean to the navigation tree
- * @param mbean mbean to add to the tree
- */
- public void addManagedBean(ManagedBean mbean)
- {
- TreeObject treeServerObject = _managedServerMap.get(mbean.getServer());
- addManagedBean(treeServerObject, mbean);
- _treeViewer.refresh();
- }
-
- private void refreshRemovedObjects()
- {
- for (ManagedServer server : _managedServerMap.keySet())
- {
- final ServerRegistry serverRegistry = ApplicationRegistry.getServerRegistry(server);
- if (serverRegistry == null) // server connection is closed
- {
- continue;
- }
-
- final List<ManagedBean> removalList = serverRegistry.getObjectsToBeRemoved();
- if (removalList != null)
- {
- Display display = getSite().getShell().getDisplay();
- display.syncExec(new Runnable()
- {
- public void run()
- {
- IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
- final MBeanView view = (MBeanView)window.getActivePage().findView(MBeanView.ID);
-
- for (ManagedBean mbean : removalList)
- {
- TreeObject treeServerObject = _managedServerMap.get(mbean.getServer());
-
- if(view != null)
- {
- //notify the MBeanView in case the unregistered mbean is being viewed
- view.mbeanUnregistered(mbean);
- }
-
- removeManagedObject(treeServerObject, mbean, false);
- }
-
- _treeViewer.refresh();
- }
- });
- }
- }
- }
-
- /**
- * Gets the list of closed server connection from the ApplicationRegistry and then removes
- * the closed server nodes from the navigation view
- */
- private void refreshClosedServerConnections()
- {
- final List<ManagedServer> closedServers = ApplicationRegistry.getClosedServers();
- if (closedServers != null)
- {
- Display display = getSite().getShell().getDisplay();
- display.syncExec(new Runnable()
- {
- public void run()
- {
- for (ManagedServer server : closedServers)
- {
- if(server == null)
- {
- continue;
- }
-
- TreeObject node = _managedServerMap.get(server);
- if(node ==null)
- {
- continue;
- }
-
- removeManagedObject(node);
- _managedServerMap.remove(server);
- ApplicationRegistry.removeServer(server);
- }
-
- _treeViewer.refresh();
- }
- });
- }
- }
-
-}
diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/NotificationsTabControl.java b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/NotificationsTabControl.java
deleted file mode 100644
index f4bad79afa..0000000000
--- a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/NotificationsTabControl.java
+++ /dev/null
@@ -1,393 +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;
-
-import org.eclipse.jface.viewers.IStructuredSelection;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.events.SelectionAdapter;
-import org.eclipse.swt.events.SelectionEvent;
-import org.eclipse.swt.events.SelectionListener;
-import org.eclipse.swt.layout.FormAttachment;
-import org.eclipse.swt.layout.FormData;
-import org.eclipse.swt.layout.FormLayout;
-import org.eclipse.swt.layout.GridData;
-import org.eclipse.swt.layout.GridLayout;
-import org.eclipse.swt.widgets.Button;
-import org.eclipse.swt.widgets.Combo;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Label;
-import org.eclipse.swt.widgets.TabFolder;
-
-import org.apache.qpid.management.ui.ApplicationRegistry;
-import org.apache.qpid.management.ui.ManagedBean;
-import org.apache.qpid.management.ui.ServerRegistry;
-import org.apache.qpid.management.ui.jmx.MBeanUtility;
-import org.apache.qpid.management.ui.model.NotificationInfoModel;
-import org.apache.qpid.management.ui.model.NotificationObject;
-
-import static org.apache.qpid.management.ui.Constants.BUTTON_CLEAR;
-import static org.apache.qpid.management.ui.Constants.DESCRIPTION;
-import static org.apache.qpid.management.ui.Constants.FONT_BOLD;
-import static org.apache.qpid.management.ui.Constants.FONT_BUTTON;
-import static org.apache.qpid.management.ui.Constants.FONT_ITALIC;
-import static org.apache.qpid.management.ui.Constants.SUBSCRIBE_BUTTON;
-import static org.apache.qpid.management.ui.Constants.UNSUBSCRIBE_BUTTON;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Creates control composite for Notifications tab
- * @author Bhupendra Bhardwaj
- */
-public class NotificationsTabControl extends VHNotificationsTabControl
-{
- private static final String SELECT_NOTIFICATIONNAME = "Select Notification";
- private static final String SELECT_NOTIFICATIONTYPE = "Select Type";
- private SelectionListener selectionListener;
- private SelectionListener comboListener;
-
- private Combo _notificationNameCombo;
- private Combo _typesCombo;
- private Label _descriptionLabel;
- private Button _subscribeButton;
- private Button _unsubscribeButton;
-
- public NotificationsTabControl(TabFolder tabFolder, ManagedBean mbean)
- {
- super(tabFolder);
- _mbean = mbean;
-
- populateNotificationInfo();
- }
-
- protected void createWidgets()
- {
- selectionListener = new SelectionListenerImpl();
- comboListener = new ComboSelectionListener();
- createNotificationInfoComposite();
- addButtons();
- createTableViewer();
- }
-
- /**
- * Creates composite and populates for displaying Notification Information (name, type, description)
- * and creates buttons for subscribing or unsubscribing for notifications
- */
- private void createNotificationInfoComposite()
- {
- Composite composite = _toolkit.createComposite(_form.getBody(), SWT.NONE);
- composite.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
- composite.setLayout(new FormLayout());
-
- Label label = _toolkit.createLabel(composite, "Select the notification to subscribe or unsubscribe");
- label.setFont(ApplicationRegistry.getFont(FONT_BOLD));
- FormData formData = new FormData();
- formData.top = new FormAttachment(0, 10);
- formData.left = new FormAttachment(0, 10);
- label.setLayoutData(formData);
-
- _notificationNameCombo = new Combo(composite, SWT.READ_ONLY | SWT.DROP_DOWN);
- formData = new FormData();
- formData.top = new FormAttachment(label, 10);
- formData.left = new FormAttachment(0, 10);
- formData.right = new FormAttachment(40);
- _notificationNameCombo.setLayoutData(formData);
- _notificationNameCombo.addSelectionListener(comboListener);
-
- _typesCombo = new Combo(composite, SWT.READ_ONLY | SWT.DROP_DOWN);
- formData = new FormData();
- formData.top = new FormAttachment(label, 10);
- formData.left = new FormAttachment(_notificationNameCombo, 5);
- formData.right = new FormAttachment(65);
- _typesCombo.setLayoutData(formData);
- _typesCombo.addSelectionListener(comboListener);
-
- _subscribeButton = new Button(composite, SWT.PUSH | SWT.CENTER);
- _subscribeButton.setFont(ApplicationRegistry.getFont(FONT_BUTTON));
- _subscribeButton.setText(SUBSCRIBE_BUTTON);
- formData = new FormData();
- formData.top = new FormAttachment(label, 10);
- formData.left = new FormAttachment(65, 10);
- formData.width = 80;
- _subscribeButton.setLayoutData(formData);
- _subscribeButton.addSelectionListener(selectionListener);
-
- _unsubscribeButton = new Button(composite, SWT.PUSH | SWT.CENTER);
- _unsubscribeButton.setFont(ApplicationRegistry.getFont(FONT_BUTTON));
- _unsubscribeButton.setText(UNSUBSCRIBE_BUTTON);
- formData = new FormData();
- formData.top = new FormAttachment(label, 10);
- formData.left = new FormAttachment(_subscribeButton, 10);
- formData.width = 80;
- _unsubscribeButton.setLayoutData(formData);
- _unsubscribeButton.addSelectionListener(selectionListener);
-
- Label fixedLabel = _toolkit.createLabel(composite, "");
- formData = new FormData();
- formData.top = new FormAttachment(_notificationNameCombo, 5);
- formData.left = new FormAttachment(0, 10);
- fixedLabel.setLayoutData(formData);
- fixedLabel.setText(DESCRIPTION + " : ");
- fixedLabel.setFont(ApplicationRegistry.getFont(FONT_BOLD));
-
- _descriptionLabel = _toolkit.createLabel(composite, "");
- formData = new FormData();
- formData.top = new FormAttachment(_notificationNameCombo, 5);
- formData.left = new FormAttachment(fixedLabel, 10);
- formData.right = new FormAttachment(100);
- _descriptionLabel.setLayoutData(formData);
- _descriptionLabel.setText(" ");
- _descriptionLabel.setFont(ApplicationRegistry.getFont(FONT_ITALIC));
- }
-
- /**
- * Creates clear button
- */
- protected void addButtons()
- {
- Composite composite = _toolkit.createComposite(_form.getBody(), SWT.NONE);
- composite.setLayoutData(new GridData(SWT.LEFT, SWT.TOP, false, false));
- composite.setLayout(new GridLayout(2,false));
-
- // Add Clear Button
- _clearButton = _toolkit.createButton(composite, BUTTON_CLEAR, SWT.PUSH | SWT.CENTER);
- _clearButton.setFont(ApplicationRegistry.getFont(FONT_BUTTON));
- GridData gridData = new GridData(SWT.LEAD, SWT.TOP, true, false);
- gridData.widthHint = 80;
- _clearButton.setLayoutData(gridData);
- _clearButton.addSelectionListener(new SelectionAdapter()
- {
- public void widgetSelected(SelectionEvent e)
- {
- if (_mbean == null)
- {
- return;
- }
-
- ServerRegistry serverRegistry = ApplicationRegistry.getServerRegistry(MBeanView.getServer());
- IStructuredSelection ss = (IStructuredSelection)_tableViewer.getSelection();
- if(!ss.isEmpty())
- {
- //clear selected Notifications
- serverRegistry.clearNotifications(_mbean, ss.toList());
- }
- else if(_notifications != null)
- {
- //clear all the notifications, if there are any
-
- //check the user is certain of this clear-all operation
- int response = ViewUtility.popupOkCancelConfirmationMessage(
- "Clear Notifications", "Clear all Notifications for this MBean?");
- if(response != SWT.OK)
- {
- return;
- }
-
- synchronized(this)
- {
- List<NotificationObject> newList = new ArrayList<NotificationObject>();
- newList.addAll(_notifications);
- serverRegistry.clearNotifications(_mbean, newList);
- }
- }
-
- refresh();
- }
- });
- //add description
- Label desc = _toolkit.createLabel(composite,"Clears the selected Notifications, or all if none are selected");
- desc.setLayoutData(new GridData(SWT.LEFT,SWT.CENTER, false, false));
- }
-
- @Override
- public void refresh(ManagedBean mbean)
- {
- refresh();
- }
-
- /**
- * Fills the notification information widgets for selected mbean
- */
- private void populateNotificationInfo()
- {
- _notificationNameCombo.removeAll();
- NotificationInfoModel[] items = MBeanUtility.getNotificationInfo(_mbean);
- if (items.length > 1)
- {
- _notificationNameCombo.add(SELECT_NOTIFICATIONNAME);
- }
-
- for (int i = 0; i < items.length; i++)
- {
- _notificationNameCombo.add(items[i].getName());
- _notificationNameCombo.setData(items[i].getName(), items[i]);
- }
- _notificationNameCombo.select(0);
-
- _typesCombo.removeAll();
- _typesCombo.add("Select Type", 0);
- _typesCombo.select(0);
- _typesCombo.setEnabled(false);
-
- populateNotificationType(_notificationNameCombo.getItem(0));
- checkForEnablingButtons();
- }
-
- /**
- * Checks and the enabing/disabling of buttons
- */
- private void checkForEnablingButtons()
- {
- int nameIndex = _notificationNameCombo.getSelectionIndex();
- int itemCount = _notificationNameCombo.getItems().length;
- if ((itemCount > 1) && (nameIndex == 0))
- {
- _subscribeButton.setEnabled(false);
- _unsubscribeButton.setEnabled(false);
- _descriptionLabel.setText("");
- return;
- }
-
- int typeIndex = _typesCombo.getSelectionIndex();
- itemCount = _typesCombo.getItems().length;
- if ((itemCount > 1) && (typeIndex == 0))
- {
- _subscribeButton.setEnabled(false);
- _unsubscribeButton.setEnabled(false);
- return;
- }
-
- String type = _typesCombo.getItem(typeIndex);
- String name = _notificationNameCombo.getItem(nameIndex);
- ServerRegistry serverRegistry = ApplicationRegistry.getServerRegistry(_mbean);
-
- if (serverRegistry.hasSubscribedForNotifications(_mbean, name, type))
- {
- _subscribeButton.setEnabled(false);
- _unsubscribeButton.setEnabled(true);
- }
- else
- {
- _subscribeButton.setEnabled(true);
- _unsubscribeButton.setEnabled(false);
- }
- }
-
- /**
- * Selection listener for subscribing or unsubscribing the notifications
- */
- private class SelectionListenerImpl extends SelectionAdapter
- {
- public void widgetSelected(SelectionEvent e)
- {
- if (_mbean == null)
- {
- return;
- }
-
- Button source = (Button)e.getSource();
- String type = _typesCombo.getItem(_typesCombo.getSelectionIndex());
- String name = _notificationNameCombo.getItem(_notificationNameCombo.getSelectionIndex());
- if (source == _unsubscribeButton)
- {
- try
- {
- MBeanUtility.removeNotificationListener(_mbean, name, type);
- }
- catch(Exception ex)
- {
- MBeanUtility.handleException(ex);
- }
- }
- else if (source == _subscribeButton)
- {
- try
- {
- MBeanUtility.createNotificationlistener(_mbean, name, type);
- }
- catch(Exception ex)
- {
- MBeanUtility.handleException(ex);
- }
- }
- checkForEnablingButtons();
- }
- }
-
- /**
- * Selection listener class for the Notification Name. The notification type and description will be
- * displayed accordingly
- */
- private class ComboSelectionListener extends SelectionAdapter
- {
- public void widgetSelected(SelectionEvent e)
- {
- if (_mbean == null)
- {
- return;
- }
-
- Combo combo = (Combo)e.getSource();
- if (combo == _notificationNameCombo)
- {
- String selectedItem = combo.getItem(combo.getSelectionIndex());
- populateNotificationType(selectedItem);
- }
- checkForEnablingButtons();
- }
- }
-
- private void populateNotificationType(String notificationName)
- {
- NotificationInfoModel data = (NotificationInfoModel)_notificationNameCombo.getData(notificationName);
- if (data == null)
- {
- _descriptionLabel.setText("");
- _typesCombo.select(0);
- _typesCombo.setEnabled(false);
- return;
- }
- _descriptionLabel.setText(data.getDescription());
- _typesCombo.removeAll();
- _typesCombo.setItems(data.getTypes());
- if (_typesCombo.getItemCount() > 1)
- {
- _typesCombo.add(SELECT_NOTIFICATIONTYPE, 0);
- }
- _typesCombo.select(0);
- _typesCombo.setEnabled(true);
- }
-
- /**
- * Updates the table with new notifications received from mbean server for the selected mbean
- */
- protected void updateTableViewer()
- {
- ServerRegistry serverRegistry = ApplicationRegistry.getServerRegistry(_mbean);
- List<NotificationObject> newList = serverRegistry.getNotifications(_mbean);
- synchronized(this)
- {
- _notifications = newList;
- _tableViewer.setInput(_notifications);
- }
- }
-}
diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/OperationTabControl.java b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/OperationTabControl.java
deleted file mode 100644
index 676389bd96..0000000000
--- a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/OperationTabControl.java
+++ /dev/null
@@ -1,938 +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;
-
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.custom.ScrolledComposite;
-import org.eclipse.swt.events.KeyAdapter;
-import org.eclipse.swt.events.KeyEvent;
-import org.eclipse.swt.events.KeyListener;
-import org.eclipse.swt.events.SelectionAdapter;
-import org.eclipse.swt.events.SelectionEvent;
-import org.eclipse.swt.events.SelectionListener;
-import org.eclipse.swt.events.VerifyEvent;
-import org.eclipse.swt.events.VerifyListener;
-import org.eclipse.swt.layout.FormAttachment;
-import org.eclipse.swt.layout.FormData;
-import org.eclipse.swt.layout.FormLayout;
-import org.eclipse.swt.layout.GridData;
-import org.eclipse.swt.layout.GridLayout;
-import org.eclipse.swt.widgets.Button;
-import org.eclipse.swt.widgets.Combo;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Control;
-import org.eclipse.swt.widgets.Display;
-import org.eclipse.swt.widgets.Label;
-import org.eclipse.swt.widgets.Shell;
-import org.eclipse.swt.widgets.TabFolder;
-import org.eclipse.swt.widgets.Text;
-import org.eclipse.ui.forms.widgets.Form;
-import org.eclipse.ui.forms.widgets.FormToolkit;
-
-import org.apache.qpid.management.ui.ApplicationRegistry;
-import org.apache.qpid.management.ui.ManagedBean;
-import org.apache.qpid.management.ui.jmx.MBeanUtility;
-import org.apache.qpid.management.ui.model.OperationData;
-import org.apache.qpid.management.ui.model.ParameterData;
-
-import static org.apache.qpid.management.ui.Constants.*;
-
-import javax.management.openmbean.CompositeData;
-import javax.management.openmbean.TabularDataSupport;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map.Entry;
-
-
-/**
- * Control class for the MBean operations tab. It creates the required widgets
- * for the selected MBean.
- */
-public class OperationTabControl extends TabControl
-{
- private static final int heightForAParameter = 30;
- private static final int labelWidth = 30;
- private static final int valueWidth = labelWidth + 25;
-
- private FormToolkit _toolkit;
- private Form _form;
- private OperationData _opData;
-
- private SelectionListener operationExecutionListener = new OperationExecutionListener();
- private SelectionListener refreshListener = new RefreshListener();
- private SelectionListener parameterSelectionListener = new ParameterSelectionListener();
- private SelectionListener booleanSelectionListener = new BooleanSelectionListener();
- private VerifyListener verifyListener = new VerifyListenerImpl();
- private KeyListener keyListener = new KeyListenerImpl();
- private KeyListener headerBindingListener = new HeaderBindingKeyListener();
-
- private Composite _headerComposite = null;
- private Composite _paramsComposite = null;
- private Composite _resultsComposite = null;
- private Button _executionButton = null;
-
- // for customized method in header exchange
- private HashMap<Text, Text> headerBindingHashMap = null;
- private String _virtualHostName = null;
-
- public OperationTabControl(TabFolder tabFolder, OperationData opData)
- {
- super(tabFolder);
- _toolkit = new FormToolkit(_tabFolder.getDisplay());
- _form = _toolkit.createForm(_tabFolder);
- _form.getBody().setLayout(new GridLayout());
- _opData = opData;
- createComposites();
- setHeader();
- }
-
- /**
- * Form area is devided in four parts:
- * Header composite - displays operaiton information
- * Patameters composite - displays parameters if there
- * Button - operation execution button
- * Results composite - displays results for operations, which have
- * no parameters but have some return value
- */
- private void createComposites()
- {
- //
- _headerComposite = _toolkit.createComposite(_form.getBody(), SWT.NONE);
- _headerComposite.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
-
- List<ParameterData> params = _opData.getParameters();
- if (params != null && !params.isEmpty())
- {
- _paramsComposite = _toolkit.createComposite(_form.getBody(), SWT.NONE);
- _paramsComposite.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
- }
- _executionButton = _toolkit.createButton(_form.getBody(), BUTTON_EXECUTE, SWT.PUSH | SWT.CENTER);
- _executionButton.setFont(ApplicationRegistry.getFont(FONT_BUTTON));
- GridData layoutData = new GridData(SWT.CENTER, SWT.TOP, true, false);
- layoutData.verticalIndent = 20;
- _executionButton.setLayoutData(layoutData);
-
- _resultsComposite = _toolkit.createComposite(_form.getBody(), SWT.NONE);
- layoutData = new GridData(SWT.FILL, SWT.FILL, true, true);
- layoutData.verticalIndent = 20;
- _resultsComposite.setLayoutData(layoutData);
- _resultsComposite.setLayout(new GridLayout());
- }
-
- /**
- * @see TabControl#getControl()
- */
- public Control getControl()
- {
- return _form;
- }
-
- @Override
- public void refresh(ManagedBean mbean)
- {
- _mbean = mbean;
- _virtualHostName = _mbean.getVirtualHostName();
-
- // Setting the form to be invisible. Just in case the mbean server connection
- // is done and it takes time in getting the response, then the ui should be blank
- // instead of having half the widgets displayed.
- _form.setVisible(false);
-
- ViewUtility.disposeChildren(_paramsComposite);
- createParameterWidgets();
-
- // Set button text and add appropriate listener to button.
- // If there are no parameters and it is info operation, then operation gets executed
- // and result is displayed
- List<ParameterData> params = _opData.getParameters();
- if (params != null && !params.isEmpty())
- {
- setButton(BUTTON_EXECUTE);
- }
- else if (_opData.getImpact() == OPERATION_IMPACT_ACTION)
- {
- setButton(BUTTON_EXECUTE);
- }
- else if (_opData.getImpact() == OPERATION_IMPACT_INFO)
- {
- setButton(BUTTON_REFRESH);
- executeAndShowResults();
- }
-
- _form.setVisible(true);
- layout();
- }
-
- public void layout()
- {
- _form.layout(true);
- _form.getBody().layout(true, true);
- }
-
- /**
- * populates the header composite, containing the operation name and description.
- */
- private void setHeader()
- {
- _form.setText(ViewUtility.getDisplayText(_opData.getName()));
- _headerComposite.setLayout(new GridLayout(2, false));
- //operation description
- Label label = _toolkit.createLabel(_headerComposite, DESCRIPTION + " : ");
- label.setFont(ApplicationRegistry.getFont(FONT_BOLD));
- label.setLayoutData(new GridData(SWT.LEAD, SWT.TOP, false, false));
-
- label = _toolkit.createLabel(_headerComposite, _opData.getDescription());
- label.setFont(ApplicationRegistry.getFont(FONT_NORMAL));
- label.setLayoutData(new GridData(SWT.LEAD, SWT.TOP, true, false));
-
- _headerComposite.layout();
- }
-
- /**
- * Creates the widgets for operation parameters if there are any
- */
- private void createParameterWidgets()
- {
- List<ParameterData> params = _opData.getParameters();
- if (params == null || params.isEmpty())
- {
- return;
- }
-
- // Customised parameter widgets
- if (_mbean.isExchange() &&
- HEADERS_EXCHANGE.equals(_mbean.getProperty(EXCHANGE_TYPE)) &&
- _opData.getName().equalsIgnoreCase(OPERATION_CREATE_BINDING))
- {
- customCreateNewBinding();
- return;
- }
- // end of Customised parameter widgets
-
- _paramsComposite.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
- _paramsComposite.setLayout(new FormLayout());
- int parameterPositionOffset = 0;
- for (ParameterData param : params)
- {
- boolean valueInCombo = false;
- Label label = _toolkit.createLabel(_paramsComposite, ViewUtility.getDisplayText(param.getName()));
- FormData formData = new FormData();
- if (params.indexOf(param) == 0)
- {
- parameterPositionOffset = 0;
- }
- else
- {
- parameterPositionOffset += heightForAParameter;
- }
- formData.top = new FormAttachment(0, parameterPositionOffset + 2);
- formData.right = new FormAttachment(labelWidth);
- label.setLayoutData(formData);
- label.setToolTipText(param.getDescription());
-
- formData = new FormData();
- formData.top = new FormAttachment(0, parameterPositionOffset);
- formData.left = new FormAttachment(label, 5);
- formData.right = new FormAttachment(valueWidth);
- // this will contain the list of items, if the list is to be made available to choose from
- // e.g. the list of exchanges
- String[] items = null;
- if (param.getName().equals(QUEUE))
- {
- List<String> qList = ApplicationRegistry.getServerRegistry(_mbean).getQueueNames(_virtualHostName);
- // Customization for AMQQueueMBean method OPERATION_MOVE_MESSAGES
- if (_opData.getName().equals(OPERATION_MOVE_MESSAGES))
- {
- qList.remove(_mbean.getName());
- }
- // End of Customization
- items = qList.toArray(new String[0]);
- }
- else if (param.getName().equals(EXCHANGE))
- {
- items = ApplicationRegistry.getServerRegistry(_mbean).getExchangeNames(_virtualHostName);
- }
- else if (param.getName().equals(EXCHANGE_TYPE))
- {
- items = DEFAULT_EXCHANGE_TYPE_VALUES.toArray(new String[DEFAULT_EXCHANGE_TYPE_VALUES.size()]);
- }
- else if (isUserListParameter(param))
- {
- List<String> list = ApplicationRegistry.getServerRegistry(_mbean).getUsernames();
- if (list != null && !list.isEmpty())
- {
- items = list.toArray(new String[0]);
- }
- }
-
- if (items != null)
- {
- org.eclipse.swt.widgets.List _list = new org.eclipse.swt.widgets.List(_paramsComposite, SWT.BORDER | SWT.V_SCROLL);
- int listSize = _form.getClientArea().height * 2 / 3;
- int itemsHeight = items.length * (_list.getItemHeight() + 2);
- // Set a min height for the list widget (set it to min 4 items)
- if (items.length < 4)
- {
- itemsHeight = 4 * (_list.getItemHeight() + 2);
- }
-
- listSize = (listSize > itemsHeight) ? itemsHeight : listSize;
- parameterPositionOffset = parameterPositionOffset + listSize;
- formData.bottom = new FormAttachment(0, parameterPositionOffset);
- _list.setLayoutData(formData);
- _list.setData(param);
- _list.setItems(items);
- _list.addSelectionListener(parameterSelectionListener);
- valueInCombo = true;
- }
- else if (param.isBoolean())
- {
- Button booleanButton = _toolkit.createButton(_paramsComposite, "", SWT.CHECK);
- booleanButton.setLayoutData(formData);
- booleanButton.setData(param);
- booleanButton.addSelectionListener(booleanSelectionListener);
- valueInCombo = true;
- }
- else
- {
- int style = SWT.NONE;
- if (PASSWORD.equalsIgnoreCase(param.getName()))
- {
- style = SWT.PASSWORD;
- }
- Text text = _toolkit.createText(_paramsComposite, "", style);
- formData = new FormData();
- formData.top = new FormAttachment(0, parameterPositionOffset);
- formData.left = new FormAttachment(label, 5);
- formData.right = new FormAttachment(valueWidth);
- text.setLayoutData(formData);
- // Listener to assign value to the parameter
- text.addKeyListener(keyListener);
- // Listener to verify if the entered key is valid
- text.addVerifyListener(verifyListener);
- text.setData(param);
- }
-
- // display the parameter data type next to the text field
- if (valueInCombo)
- {
- label = _toolkit.createLabel(_paramsComposite, "");
- }
- else if (PASSWORD.equalsIgnoreCase(param.getName()))
- {
- label = _toolkit.createLabel(_paramsComposite, "(String)");
- }
- else
- {
- String str = param.getType();
-
- if (param.getType().lastIndexOf(".") != -1)
- {
- str = param.getType().substring(1 + param.getType().lastIndexOf("."));
- }
-
- label = _toolkit.createLabel(_paramsComposite, "(" + str + ")");
- }
- formData = new FormData();
- formData.top = new FormAttachment(0, parameterPositionOffset);
- formData.left = new FormAttachment(valueWidth, 5);
- label.setLayoutData(formData);
- }
- }
-
- private boolean isUserListParameter(ParameterData param)
- {
- if (_mbean.isAdmin() && param.getName().equals(OPERATION_PARAM_USERNAME)
- && !_opData.getName().equals(OPERATION_CREATEUSER))
- {
- return true;
- }
-
- return false;
- }
-
- /**
- * Creates customized dispaly for a method "CreateNewBinding" for Headers exchange
- *
- */
- private void customCreateNewBinding()
- {
- headerBindingHashMap = new HashMap<Text, Text>();
-
- _paramsComposite.setLayout(new GridLayout());
- _paramsComposite.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, true));
- final ScrolledComposite scrolledComposite = new ScrolledComposite(_paramsComposite, SWT.BORDER | SWT.V_SCROLL);
- scrolledComposite.setExpandHorizontal(true);
- scrolledComposite.setExpandVertical(true);
- GridData layoutData = new GridData(SWT.FILL, SWT.TOP, true, true);
- scrolledComposite.setLayoutData(layoutData);
- scrolledComposite.setLayout(new GridLayout());
-
- final Composite composite = _toolkit.createComposite(scrolledComposite, SWT.NONE);
- scrolledComposite.setContent(composite);
- layoutData = new GridData(SWT.FILL, SWT.FILL, true, true);
- layoutData.verticalIndent = 20;
- composite.setLayoutData(layoutData);
- composite.setLayout(new FormLayout());
-
- List<ParameterData> params = _opData.getParameters();
- ParameterData param = params.get(0);
- // Queue selection widget
- Label label = _toolkit.createLabel(composite, ViewUtility.getDisplayText(param.getName()));
- FormData formData = new FormData();
- formData.top = new FormAttachment(0, 2);
- formData.right = new FormAttachment(labelWidth);
- label.setLayoutData(formData);
- label.setToolTipText(param.getDescription());
-
- formData = new FormData();
- formData.top = new FormAttachment(0);
- formData.left = new FormAttachment(label, 5);
- formData.right = new FormAttachment(valueWidth);
-
- Combo combo = new Combo(composite, SWT.READ_ONLY | SWT.DROP_DOWN);
- List<String> qList = ApplicationRegistry.getServerRegistry(_mbean).getQueueNames(_virtualHostName);
- combo.setItems(qList.toArray(new String[0]));
- combo.add("Select Queue", 0);
- combo.select(0);
- combo.setLayoutData(formData);
- combo.setData(param);
- combo.addSelectionListener(parameterSelectionListener);
-
- // Binding creation widgets
- createARowForCreatingHeadersBinding(composite, 1);
- createARowForCreatingHeadersBinding(composite, 2);
- createARowForCreatingHeadersBinding(composite, 3);
- createARowForCreatingHeadersBinding(composite, 4);
- createARowForCreatingHeadersBinding(composite, 5);
- createARowForCreatingHeadersBinding(composite, 6);
- createARowForCreatingHeadersBinding(composite, 7);
- createARowForCreatingHeadersBinding(composite, 8);
-
- final Button addMoreButton = _toolkit.createButton(composite, "Add More", SWT.PUSH);
- formData = new FormData();
- formData.top = new FormAttachment(0, heightForAParameter);
- formData.left = new FormAttachment(70, 5);
- addMoreButton.setLayoutData(formData);
- addMoreButton.setData("rowCount", 8);
- addMoreButton.addSelectionListener(new SelectionAdapter()
- {
- public void widgetSelected(SelectionEvent e)
- {
- int count = Integer.parseInt(addMoreButton.getData("rowCount").toString());
- createARowForCreatingHeadersBinding(composite, ++count);
- addMoreButton.setData("rowCount", count);
- scrolledComposite.setMinSize(composite.computeSize(SWT.DEFAULT, SWT.DEFAULT));
- composite.layout();
- _form.layout();
- }
- });
-
- scrolledComposite.setMinSize(composite.computeSize(SWT.DEFAULT, SWT.DEFAULT));
- composite.layout();
- }
-
- /**
- * Adds a row for adding a binding for Headers Exchange. Used by the method, which creates the customized
- * layout and widgest for Header's exchange method createNewBinding.
- * @param parent composite
- * @param rowCount - row number
- */
- private void createARowForCreatingHeadersBinding(Composite parent, int rowCount)
- {
- Label key = _toolkit.createLabel(parent, "Name");
- FormData formData = new FormData();
- formData.top = new FormAttachment(0, rowCount * heightForAParameter + 2);
- formData.right = new FormAttachment(15);
- key.setLayoutData(formData);
-
- Text keyText = _toolkit.createText(parent, "", SWT.NONE);
- formData = new FormData();
- formData.top = new FormAttachment(0, rowCount * heightForAParameter);
- formData.left = new FormAttachment(key, 5);
- formData.right = new FormAttachment(40);
- keyText.setLayoutData(formData);
- keyText.addKeyListener(headerBindingListener);
-
- Label value = _toolkit.createLabel(parent, "Value");
- formData = new FormData();
- formData.top = new FormAttachment(0, rowCount * heightForAParameter + 2);
- formData.right = new FormAttachment(45);
- value.setLayoutData(formData);
-
- Text valueText = _toolkit.createText(parent, "", SWT.NONE);
- formData = new FormData();
- formData.top = new FormAttachment(0, rowCount * heightForAParameter);
- formData.left = new FormAttachment(value, 5);
- formData.right = new FormAttachment(70);
- valueText.setLayoutData(formData);
- valueText.addKeyListener(headerBindingListener);
-
- // Add these to the map, to retrieve the values while setting the parameter value
- headerBindingHashMap.put(keyText, valueText);
- }
-
- /**
- * Sets text and listener for the operation execution button
- * @param text
- */
- private void setButton(String text)
- {
- _executionButton.setText(text);
- _executionButton.removeSelectionListener(refreshListener);
- _executionButton.removeSelectionListener(operationExecutionListener);
-
- if (BUTTON_EXECUTE.equals(text))
- {
- _executionButton.addSelectionListener(operationExecutionListener);
- }
- else
- {
- _executionButton.addSelectionListener(refreshListener);
- }
- }
-
- /**
- * displays the operation result in a pop-up window
- * @param result
- */
- private void populateResults(Object result)
- {
- Display display = Display.getCurrent();
- int width = 610;
- int height = 400;
- Shell shell = ViewUtility.createPopupShell(RESULT, width, height);
- shell.setImage(ApplicationRegistry.getImage(CONSOLE_IMAGE));
- ViewUtility.populateCompositeWithData(_toolkit, shell, result);
-
- shell.open();
- while (!shell.isDisposed()) {
- if (!display.readAndDispatch()) {
- display.sleep();
- }
- }
- shell.dispose();
- }
-
- /**
- * Clears the parameter values of the operation
- */
- private void clearParameters()
- {
- List<ParameterData> params = _opData.getParameters();
- if (params != null && !params.isEmpty())
- {
- for (ParameterData param : params)
- {
- param.setDefaultValue();
- }
- }
- }
-
- /**
- * Clears the values entered by the user from parameter value widgets
- * @param control
- */
- private void clearParameterValues(Composite control)
- {
- if (control == null || (control.isDisposed()))
- {
- return;
- }
-
- Control[] controls = control.getChildren();
- if (controls == null || controls.length == 0)
- {
- return;
- }
-
- for (int i = 0; i < controls.length; i++)
- {
- if (controls[i] instanceof Combo)
- {
- ((Combo)controls[i]).select(0);
- }
- if (controls[i] instanceof org.eclipse.swt.widgets.List)
- {
- ((org.eclipse.swt.widgets.List)controls[i]).deselectAll();
- }
- else if (controls[i] instanceof Text)
- {
- ((Text)controls[i]).setText("");
- }
- else if (controls[i] instanceof Button)
- {
- ((Button)controls[i]).setSelection(false);
- }
- else if (controls[i] instanceof Composite)
- {
- clearParameterValues((Composite)controls[i]);
- }
- }
- }
-
- /**
- * Listener class for operation execution events
- */
- private class OperationExecutionListener extends SelectionAdapter
- {
- public void widgetSelected(SelectionEvent e)
- {
- List<ParameterData> params = _opData.getParameters();
- if (params != null && !params.isEmpty())
- {
- for (ParameterData param : params)
- {
- if (param.getValue() == null || param.getValue().toString().length() == 0)
- {
- // Customized check, because for this parameter null is allowed
- if (param.getName().equals(ATTRIBUTE_QUEUE_OWNER) &&
- _opData.getName().equals(OPERATION_CREATE_QUEUE))
- {
- continue;
- }
- // End of custom code
-
- ViewUtility.popupInfoMessage(_form.getText(), "Please select the " + ViewUtility.getDisplayText(param.getName()));
- return;
- }
-
- //Custom handling for the PASSWORD field
- if (param.getName().equalsIgnoreCase(PASSWORD))
- {
- //Convert the String value to a character array if that is what is required.
- if (param.getType().equals("[C"))
- {
- // Retreive the mBean type and version.
- // If we have a version 1 UserManagement class mbean then it expects the password
- // to be sent as the hashed version.
- if (_mbean.getType().equals("UserManagement") && _mbean.getVersion() == 1)
- {
- try
- {
- param.setValue(ViewUtility.getHash((String) param.getValue()));
- }
- catch (Exception hashException)
- {
- ViewUtility.popupErrorMessage(_form.getText(),
- "Unable to calculate hash for Password:"
- + hashException.getMessage());
- return;
- }
- }
- else
- {
- param.setValue(((String) param.getValue()).toCharArray());
- }
- }
- }
- // end of customization
-
- }
- }
-
- if (_opData.getImpact() == OPERATION_IMPACT_ACTION)
- {
- String bean = _mbean.getName() == null ? _mbean.getType() : _mbean.getName();
- int response = ViewUtility.popupConfirmationMessage(bean, "Do you want to " + _form.getText()+ " ?");
- if (response == SWT.YES)
- {
- executeAndShowResults();
- }
- }
- else
- {
- executeAndShowResults();
- }
-
- if (_mbean.isAdmin() && _opData.getName().equals(OPERATION_DELETEUSER))
- {
- refresh(_mbean);
- }
- else
- {
- clearParameters();
- clearParameterValues(_paramsComposite);
- }
- }
- }
-
- // Listener for the "Refresh" execution button
- private class RefreshListener extends SelectionAdapter
- {
- public void widgetSelected(SelectionEvent e)
- {
- executeAndShowResults();
- }
- }
-
- /**
- * Executres the operation, gets the result from server and displays to the user
- */
- private void executeAndShowResults()
- {
- Object result = null;
- try
- {
- result = MBeanUtility.execute(_mbean, _opData);
- }
- catch(Exception ex)
- {
- MBeanUtility.handleException(_mbean, ex);
- return;
- }
-
- // Custom code for Admin mbean operation
- /* These custome codes here are to make the GUI look more user friendly.
- * Here we are adding the users to a list, which will be used to list username to be selected on
- * pages like "delete user", "set password" instead of typing the username
- */
- if (_mbean.isAdmin())
- {
- if (_opData.getName().equals(OPERATION_VIEWUSERS))
- {
- ApplicationRegistry.getServerRegistry(_mbean).setUserList(extractUserList(result));
- }
- else if (_opData.getName().equals(OPERATION_DELETEUSER))
- {
- List<String> list = ApplicationRegistry.getServerRegistry(_mbean).getUsernames();
- Object userName = _opData.getParameterValue(OPERATION_PARAM_USERNAME);
- if ((list != null) && !list.isEmpty() && (userName != null))
- {
- list.remove(userName);
- ApplicationRegistry.getServerRegistry(_mbean).setUserList(list);
- }
- }
- else if (_opData.getName().equals(OPERATION_CREATEUSER))
- {
- List<String> list = ApplicationRegistry.getServerRegistry(_mbean).getUsernames();
- Object userName = _opData.getParameterValue(OPERATION_PARAM_USERNAME);
- if ((list != null) && !list.isEmpty() && (userName != null))
- {
- list.add(userName.toString());
- ApplicationRegistry.getServerRegistry(_mbean).setUserList(list);
- }
- }
- }
- // end of custom code
-
- // Some mbeans have only "type" and no "name".
- String title = _mbean.getType();
- if (_mbean.getName() != null && _mbean.getName().length() != 0)
- {
- title = _mbean.getName();
- }
-
- if (_opData.isReturnTypeVoid())
- {
- ViewUtility.popupInfoMessage(title, OPERATION_SUCCESSFUL);
- }
- else if (_opData.isReturnTypeBoolean())
- {
- boolean success = Boolean.parseBoolean(result.toString());
- String message = success ? OPERATION_SUCCESSFUL : OPERATION_UNSUCCESSFUL;
- if(success)
- {
- ViewUtility.popupInfoMessage(title, message);
- }
- else
- {
- ViewUtility.popupErrorMessage(title, message);
- }
- }
- else if (_opData.getParameters() != null && !_opData.getParameters().isEmpty())
- {
- populateResults(result);
- }
- else
- {
- ViewUtility.disposeChildren(_resultsComposite);
- ViewUtility.populateCompositeWithData(_toolkit, _resultsComposite, result);
- _resultsComposite.layout();
- _form.layout();
- }
-
- }
-
- private List<String> extractUserList(Object result)
- {
- if (!(result instanceof TabularDataSupport))
- {
- return null;
- }
-
- TabularDataSupport tabularData = (TabularDataSupport)result;
- Collection<Object> records = tabularData.values();
- List<String> list = new ArrayList<String>();
- for (Object o : records)
- {
- CompositeData data = (CompositeData) o;
- if (data.containsKey(USERNAME))
- {
- list.add(data.get(USERNAME).toString());
- }
- }
-
- return list;
- }
-
- /**
- * Listener class for the operation parameters widget
- */
- private static class ParameterSelectionListener extends SelectionAdapter
- {
- public void widgetSelected(SelectionEvent e)
- {
- ParameterData parameter = (ParameterData)e.widget.getData();
- parameter.setValue(null);
- if (e.widget instanceof Combo)
- {
- Combo combo = (Combo)e.widget;
- if (combo.getSelectionIndex() > 0)
- {
- String item = combo.getItem(combo.getSelectionIndex());
- parameter.setValueFromString(item);
- }
- }
- else if (e.widget instanceof org.eclipse.swt.widgets.List)
- {
- org.eclipse.swt.widgets.List list = (org.eclipse.swt.widgets.List)e.widget;
- String[] selectedItems = list.getSelection();
- if (selectedItems.length > 0)
- {
- parameter.setValueFromString(selectedItems[0]);
- }
- }
- }
- }
-
- /**
- * Listener class for boolean parameter widgets
- */
- private static class BooleanSelectionListener extends SelectionAdapter
- {
- public void widgetSelected(SelectionEvent e)
- {
- ParameterData parameter = (ParameterData)(e.widget.getData());
- if (e.widget instanceof Button)
- {
- Button button = (Button)e.widget;
- parameter.setValue(button.getSelection());
- }
- else if (e.widget instanceof Combo)
- {
- Combo combo = (Combo)e.widget;
- String item = combo.getItem(combo.getSelectionIndex());
- parameter.setValueFromString(item);
- }
- }
- }
-
- /**
- * Listener class for the operation parameter value widget (Text field)
- */
- private static class KeyListenerImpl extends KeyAdapter
- {
- public void keyReleased(KeyEvent e)
- {
- if (!(e.widget instanceof Text))
- {
- return;
- }
-
- Text text = (Text)e.widget;
- // Get the parameters widget and assign the text to the parameter
- String strValue = text.getText();
- ParameterData parameter = (ParameterData)text.getData();
- try
- {
- parameter.setValueFromString(strValue);
- }
- catch(Exception ex)
- {
- // Exception occured in setting parameter value.
- // ignore it. The value will not be assigned to the parameter
- }
- }
- }
-
- /**
- * Listener class for HeaderExchange's new binding widgets. Used when the new bindings are
- * being created for Header's Exchange
- */
- private class HeaderBindingKeyListener extends KeyAdapter
- {
- public void keyReleased(KeyEvent e)
- {
- ParameterData param = _opData.getParameters().get(1);
- StringBuffer paramValue = new StringBuffer();
- for (Entry<Text, Text> entry : headerBindingHashMap.entrySet())
- {
-
- Text nameText = entry.getKey();
- String name = nameText.getText();
- Text valueText = entry.getValue();
- String value = valueText.getText();
- if ((name != null) && (name.length() != 0) && (value != null) && (value.length() != 0))
- {
- if (paramValue.length() != 0)
- {
- paramValue.append(",");
- }
- paramValue.append(name + "=" + value);
- }
- }
-
- param.setValue(paramValue.toString());
- }
- }
-
- /**
- * Listener class for verifying the user input with parameter type
- */
- private static class VerifyListenerImpl implements VerifyListener
- {
- public void verifyText(VerifyEvent event)
- {
- ParameterData parameter = (ParameterData)event.widget.getData();
- String text = event.text;
- char [] chars = new char [text.length ()];
- text.getChars(0, chars.length, chars, 0);
- String type = parameter.getType();
- if (type.equals("int") || type.equals("java.lang.Integer") ||
- type.equals("long") || type.equals("java.lang.Long"))
- {
- for (int i=0; i<chars.length; i++)
- {
- if (!('0' <= chars [i] && chars [i] <= '9'))
- {
- event.doit = false;
- return;
- }
- }
-
- }
- }
- }
-
-}
diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/TabControl.java b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/TabControl.java
deleted file mode 100644
index ce615fb8ea..0000000000
--- a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/TabControl.java
+++ /dev/null
@@ -1,104 +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;
-
-import org.eclipse.swt.widgets.Control;
-import org.eclipse.swt.widgets.TabFolder;
-
-import org.apache.qpid.management.ui.ManagedBean;
-import org.apache.qpid.management.ui.model.OperationData;
-
-import java.util.ArrayList;
-
-/**
- * Abstract class for all the control classes of tabs.
- * @author Bhupendra Bhardwaj
- */
-public abstract class TabControl
-{
- public static final String CONTROLLER = "controller";
- protected ManagedBean _mbean = null;
- protected TabFolder _tabFolder = null;
-
- private static java.util.List<String> simpleTypes = new ArrayList<String>();
-
- static
- {
- simpleTypes.add("java.math.BigDecimal");
- simpleTypes.add("java.math.BigInteger");
- simpleTypes.add("java.lang.Boolean");
- simpleTypes.add("java.lang.Byte");
- simpleTypes.add("java.lang.Character");
- simpleTypes.add("java.util.Date");
- simpleTypes.add("java.lang.Double");
- simpleTypes.add("java.lang.Float");
- simpleTypes.add("java.lang.Integer");
- simpleTypes.add("java.lang.Long");
- simpleTypes.add("javax.management.ObjectName");
- simpleTypes.add("java.lang.Short");
- simpleTypes.add("java.lang.String");
- simpleTypes.add("boolean");
- }
-
- public TabControl(TabFolder tabFolder)
- {
- _tabFolder = tabFolder;
- }
-
- /**
- * @return controller composite for the tab
- */
- public Control getControl()
- {
- return null;
- }
-
- public void refresh(ManagedBean mbean)
- {
- if (mbean == null)
- {
- refresh();
- }
- }
-
- public void refresh()
- {
-
- }
-
- public void refresh(ManagedBean mbean, OperationData opData)
- {
-
- }
-
- /**
- * Sets focus on a widget
- */
- public void setFocus()
- {
-
- }
-
- public boolean isSimpleType(Object data)
- {
- return simpleTypes.contains(data.getClass().getName());
- }
-}
diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/TreeObject.java b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/TreeObject.java
deleted file mode 100644
index 7fd0f5a85f..0000000000
--- a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/TreeObject.java
+++ /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.
- *
- */
-package org.apache.qpid.management.ui.views;
-
-import org.apache.qpid.management.ui.Constants;
-import org.apache.qpid.management.ui.ManagedBean;
-import org.apache.qpid.management.ui.ManagedObject;
-
-import java.util.ArrayList;
-import java.util.List;
-
-public class TreeObject
-{
- private String _name;
- private String _type;
- private String _virtualHost;
- private TreeObject _parent;
- private List<TreeObject> _children = new ArrayList<TreeObject>();
- private ManagedObject _object;
-
- public TreeObject(String name, String type)
- {
- this._name = name;
- this._type = type;
- }
-
- public TreeObject(ManagedObject obj)
- {
- _name = obj.getName();
- if (_name == null && (obj instanceof ManagedBean))
- {
- String[] types = ((ManagedBean)obj).getType().split("\\.");
- _name = types[types.length - 1];
- }
- this._type = Constants.MBEAN;
- this._object = obj;
- }
-
- public void addChild(TreeObject child)
- {
- _children.add(child);
- }
-
- public void addChildren(List<TreeObject> subList)
- {
- _children.addAll(subList);
- }
-
- public List<TreeObject> getChildren()
- {
- return _children;
- }
-
- public void setChildren(List<TreeObject> children)
- {
- this._children = children;
- }
-
- public void setName(String value)
- {
- _name = value;
- }
-
- public String getName()
- {
- return _name;
- }
- public String getType()
- {
- return _type;
- }
-
- public String getVirtualHost()
- {
- // To make it work with the broker with no virtual host implementation
- return _virtualHost == null ? Constants.DEFAULT_VH : _virtualHost;
- }
-
- public void setVirtualHost(String vHost)
- {
- _virtualHost = vHost;
- }
-
- public ManagedObject getManagedObject()
- {
- return _object;
- }
-
- public void setManagedObject(ManagedObject obj)
- {
- this._object = obj;
- }
-
- public TreeObject getParent()
- {
- return _parent;
- }
-
- public void setParent(TreeObject parent)
- {
- this._parent = parent;
-
- if (parent != null)
- {
- parent.addChild(this);
- }
- }
-}
diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/VHNotificationsTabControl.java b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/VHNotificationsTabControl.java
deleted file mode 100644
index 4fc4ddc07b..0000000000
--- a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/VHNotificationsTabControl.java
+++ /dev/null
@@ -1,485 +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;
-
-import org.eclipse.jface.viewers.DoubleClickEvent;
-import org.eclipse.jface.viewers.IDoubleClickListener;
-import org.eclipse.jface.viewers.ILabelProviderListener;
-import org.eclipse.jface.viewers.IStructuredContentProvider;
-import org.eclipse.jface.viewers.IStructuredSelection;
-import org.eclipse.jface.viewers.ITableLabelProvider;
-import org.eclipse.jface.viewers.StructuredSelection;
-import org.eclipse.jface.viewers.TableViewer;
-import org.eclipse.jface.viewers.Viewer;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.events.SelectionAdapter;
-import org.eclipse.swt.events.SelectionEvent;
-import org.eclipse.swt.graphics.Image;
-import org.eclipse.swt.layout.GridData;
-import org.eclipse.swt.layout.GridLayout;
-import org.eclipse.swt.widgets.Button;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Control;
-import org.eclipse.swt.widgets.Display;
-import org.eclipse.swt.widgets.Label;
-import org.eclipse.swt.widgets.Shell;
-import org.eclipse.swt.widgets.TabFolder;
-import org.eclipse.swt.widgets.Table;
-import org.eclipse.swt.widgets.TableColumn;
-import org.eclipse.swt.widgets.Text;
-import org.eclipse.ui.forms.widgets.Form;
-import org.eclipse.ui.forms.widgets.FormToolkit;
-
-import org.apache.qpid.management.ui.ApplicationRegistry;
-import org.apache.qpid.management.ui.ServerRegistry;
-import org.apache.qpid.management.ui.model.NotificationObject;
-
-import static org.apache.qpid.management.ui.Constants.BUTTON_CLEAR;
-import static org.apache.qpid.management.ui.Constants.CONSOLE_IMAGE;
-import static org.apache.qpid.management.ui.Constants.FONT_BUTTON;
-
-import java.util.ArrayList;
-import java.util.List;
-
-public class VHNotificationsTabControl extends TabControl
-{
- protected FormToolkit _toolkit;
- protected Form _form;
- protected Table _table = null;
- protected TableViewer _tableViewer = null;
-
- protected Thread _worker = null;
- protected boolean _workerRunning = false;
-
- protected List<NotificationObject> _notifications = null;
-
- private static final String COLUMN_OBJ = "Object Name";
- private static final String COLUMN_SEQ = "Sequence No";
- private static final String COLUMN_TIME = "TimeStamp";
- private static final String COLUMN_TYPE = "Type";
- private static final String COLUMN_MSG = "Notification Message";
- private static final String[] TABLE_TITLES = new String [] {
- COLUMN_OBJ,
- COLUMN_SEQ,
- COLUMN_TIME,
- COLUMN_TYPE,
- COLUMN_MSG
- };
-
- protected Button _clearButton = null;
-
- public VHNotificationsTabControl(TabFolder tabFolder)
- {
- super(tabFolder);
- _toolkit = new FormToolkit(_tabFolder.getDisplay());
- _form = _toolkit.createForm(_tabFolder);
- GridLayout gridLayout = new GridLayout();
- gridLayout.marginWidth = 0;
- gridLayout.marginHeight = 0;
- _form.getBody().setLayout(gridLayout);
-
- createWidgets();
- }
-
- protected void createWidgets()
- {
- addButtons();
- createTableViewer();
- }
-
- /**
- * @see TabControl#getControl()
- */
- public Control getControl()
- {
- return _form;
- }
-
- /**
- * Creates clear buttin and refresh button
- */
- protected void addButtons()
- {
- Composite composite = _toolkit.createComposite(_form.getBody(), SWT.NONE);
- composite.setLayoutData(new GridData(SWT.LEFT, SWT.TOP, false, false));
- composite.setLayout(new GridLayout(2,false));
-
- // Add Clear Button
- _clearButton = _toolkit.createButton(composite, BUTTON_CLEAR, SWT.PUSH | SWT.CENTER);
- _clearButton.setFont(ApplicationRegistry.getFont(FONT_BUTTON));
- GridData gridData = new GridData(SWT.LEAD, SWT.TOP, true, false);
- gridData.widthHint = 80;
- _clearButton.setLayoutData(gridData);
- _clearButton.addSelectionListener(new SelectionAdapter()
- {
- public void widgetSelected(SelectionEvent e)
- {
- ServerRegistry serverRegistry = ApplicationRegistry.getServerRegistry(MBeanView.getServer());
- IStructuredSelection ss = (IStructuredSelection)_tableViewer.getSelection();
- if(!ss.isEmpty())
- {
- //clear selected Notifications
- serverRegistry.clearNotifications(null, ss.toList());
- }
- else if(_notifications != null)
- {
- //clear all the notifications, if there are any
-
- //check the user is certain of this clear-all operation
- int response = ViewUtility.popupOkCancelConfirmationMessage(
- "Clear Notifications", "Clear all Notifications for this VirtualHost?");
- if(response != SWT.OK)
- {
- return;
- }
-
- synchronized(this)
- {
- serverRegistry.clearNotifications(null, _notifications);
- }
- }
-
- refresh();
- }
- });
- //add description
- Label desc = _toolkit.createLabel(composite,"Clears the selected Notifications, or all if none are selected");
- desc.setLayoutData(new GridData(SWT.LEFT,SWT.CENTER, false, false));
- }
-
- /**
- * Creates table to display notifications
- */
- private void createTable()
- {
- _table = _toolkit.createTable(_form.getBody(), SWT.MULTI | SWT.FULL_SELECTION);
- _table.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
-
- TableColumn column = new TableColumn(_table, SWT.NONE);
- column.setText(TABLE_TITLES[0]);
- column.setWidth(100);
-
- column = new TableColumn(_table, SWT.NONE);
- column.setText(TABLE_TITLES[1]);
- column.setWidth(100);
-
- column = new TableColumn(_table, SWT.NONE);
- column.setText(TABLE_TITLES[2]);
- column.setWidth(130);
-
- column = new TableColumn(_table, SWT.NONE);
- column.setText(TABLE_TITLES[3]);
- column.setWidth(100);
-
- column = new TableColumn(_table, SWT.NONE);
- column.setText(TABLE_TITLES[4]);
- column.setWidth(500);
-
- _table.setHeaderVisible(true);
- _table.setLinesVisible(true);
- }
-
- /**
- * Creates JFace viewer for the notifications table
- */
- protected void createTableViewer()
- {
- createTable();
- _tableViewer = new TableViewer(_table);
- _tableViewer.setUseHashlookup(true);
- _tableViewer.setContentProvider(new ContentProviderImpl());
- _tableViewer.setLabelProvider(new LabelProviderImpl());
- _tableViewer.setColumnProperties(TABLE_TITLES);
-
- addTableListeners();
- }
-
- /**
- * Adds listeners to the viewer for displaying notification details
- */
- protected void addTableListeners()
- {
- _tableViewer.addDoubleClickListener(new IDoubleClickListener()
- {
- private Display display = null;
- private Shell shell = null;
- public void doubleClick(DoubleClickEvent event)
- {
- display = Display.getCurrent();
- shell = new Shell(display, SWT.BORDER | SWT.CLOSE | SWT.MIN | SWT.MAX | SWT.RESIZE);
- shell.setText("Notification");
- shell.setImage(ApplicationRegistry.getImage(CONSOLE_IMAGE));
-
- int x = display.getBounds().width;
- int y = display.getBounds().height;
- shell.setBounds(x/4, y/4, x/2, y/3);
- StructuredSelection selection = (StructuredSelection)event.getSelection();
- createPopupContents((NotificationObject)selection.getFirstElement());
- shell.open();
- while (!shell.isDisposed()) {
- if (!display.readAndDispatch()) {
- display.sleep();
- }
- }
-
- //If you create it, you dispose it.
- shell.dispose();
- }
-
- private void createPopupContents(NotificationObject obj)
- {
- shell.setLayout(new GridLayout());
-
- Composite parent = _toolkit.createComposite(shell, SWT.NONE);
- parent.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
- GridLayout layout = new GridLayout(4, true);
- parent.setLayout(layout);
-
- // Object name record
- Label key = _toolkit.createLabel(parent, COLUMN_OBJ, SWT.TRAIL);
- GridData layoutData = new GridData(SWT.TRAIL, SWT.TOP, false, false,1,1);
- key.setLayoutData(layoutData);
- Text value = _toolkit.createText(parent, obj.getSourceName(), SWT.BEGINNING | SWT.BORDER |SWT.READ_ONLY);
- value.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false,3,1));
-
- // Sequence no record
- key = _toolkit.createLabel(parent, COLUMN_SEQ, SWT.TRAIL);
- layoutData = new GridData(SWT.TRAIL, SWT.TOP, false, false,1,1);
- key.setLayoutData(layoutData);
- value = _toolkit.createText(parent, ""+obj.getSequenceNo(), SWT.BEGINNING | SWT.BORDER |SWT.READ_ONLY);
- value.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false,3,1));
-
- // Time row
- key = _toolkit.createLabel(parent, COLUMN_TIME, SWT.TRAIL);
- key.setLayoutData(new GridData(SWT.TRAIL, SWT.TOP, true, false,1,1));
- value = _toolkit.createText(parent, obj.getTimeStamp(), SWT.BEGINNING | SWT.BORDER | SWT.READ_ONLY);
- value.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false,3,1));
-
- key = _toolkit.createLabel(parent, COLUMN_TYPE, SWT.TRAIL);
- key.setLayoutData(new GridData(SWT.TRAIL, SWT.TOP, true, false,1,1));
- value = _toolkit.createText(parent, obj.getType(), SWT.BEGINNING | SWT.BORDER | SWT.READ_ONLY);
- value.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false,3,1));
-
- key = _toolkit.createLabel(parent, COLUMN_MSG, SWT.TRAIL);
- key.setLayoutData(new GridData(SWT.TRAIL, SWT.TOP, true, false,1,1));
- value = _toolkit.createText(parent, obj.getMessage(), SWT.MULTI | SWT.WRAP| SWT.BORDER | SWT.V_SCROLL | SWT.READ_ONLY);
- GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, true, 3, 1);
- gridData.heightHint = 100;
- value.setLayoutData(gridData);
- }
- });
- }
-
- public void refresh()
- {
- if(_workerRunning)
- {
- //perform an single immediate-update
- updateTableViewer();
- }
- else
- {
- //start a worker to do the update and keep going as required
- _workerRunning = true;
- _worker = new Thread(new Worker());
- _worker.start();
- }
-
- _form.layout(true);
- _form.getBody().layout(true, true);
- }
-
- /**
- * Content provider class for the table viewer
- */
- protected class ContentProviderImpl implements IStructuredContentProvider, INotificationViewer
- {
- public void inputChanged(Viewer v, Object oldInput, Object newInput)
- {
-
- }
- public void dispose()
- {
-
- }
- public Object[] getElements(Object parent)
- {
- synchronized(VHNotificationsTabControl.this)
- {
- return _notifications.toArray(new NotificationObject[0]);
- }
- }
- public void addNotification(NotificationObject notification)
- {
- _tableViewer.add(notification);
- }
-
- public void addNotification(List<NotificationObject> notificationList)
- {
- _tableViewer.add(notificationList.toArray(new NotificationObject[0]));
- }
- }
-
- /**
- * Label provider for the table viewer
- */
- protected static class LabelProviderImpl implements ITableLabelProvider
- {
- private List<ILabelProviderListener> listeners = new ArrayList<ILabelProviderListener>();
- public void addListener(ILabelProviderListener listener)
- {
- listeners.add(listener);
- }
-
- public void dispose(){
-
- }
-
- public Image getColumnImage(Object element, int columnIndex)
- {
- return null;
- }
-
- public String getColumnText(Object element, int columnIndex)
- {
- String result = null;
- NotificationObject t = (NotificationObject)element;
- switch(columnIndex)
- {
- case 0 :
- result = t.getSourceName();
- break;
- case 1 :
- result = String.valueOf(t.getSequenceNo());
- break;
- case 2 :
- result = String.valueOf(t.getTimeStamp());
- break;
- case 3 :
- result = t.getType();
- break;
- case 4 :
- result = t.getMessage();
- break;
- default :
- result = "";
- }
-
- return result;
- }
-
- public boolean isLabelProperty(Object element, String property)
- {
- return false;
- }
-
- public void removeListener(ILabelProviderListener listener)
- {
- listeners.remove(listener);
- }
- } // end of LabelProviderImpl
-
-
- protected void setWorkerRunning(boolean running)
- {
- _workerRunning = running;
- }
-
- /**
- * Worker class which keeps looking if there are new notifications coming from server for the selected mbean
- */
- private class Worker implements Runnable
- {
- private boolean keepGoing = true;
-
- public void run()
- {
- final Display display = _tabFolder.getDisplay();
-
- while(keepGoing)
- {
- if (display == null || display.isDisposed())
- {
- setWorkerRunning(false);
- break; //stop the thread
- }
-
- display.syncExec(new Runnable()
- {
- public void run()
- {
- if (_form == null || _form.isDisposed())
- {
- setWorkerRunning(false);
- keepGoing = false; //exit the loop and stop the thread
- }
- else
- {
- keepGoing = _form.isVisible();
- setWorkerRunning(keepGoing);
- }
-
- if (keepGoing)
- {
- updateTableViewer();
- }
- }
- });
-
- if (keepGoing)
- {
- sleep();
- }
- }
- }
-
- private void sleep()
- {
- try
- {
- Thread.sleep(2000);
- }
- catch(Exception ex)
- {
-
- }
- }
- }
-
- /**
- * Updates the table with new notifications received from mbean server for all mbeans in this virtual host
- */
- protected void updateTableViewer()
- {
- String virtualhost = MBeanView.getVirtualHost();
-
- ServerRegistry serverRegistry = ApplicationRegistry.getServerRegistry(MBeanView.getServer());
- List<NotificationObject> newList = serverRegistry.getNotifications(virtualhost);
-
- synchronized(this)
- {
- _notifications = newList;
- _tableViewer.setInput(_notifications);
- }
- }
-
-}
diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/ViewUtility.java b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/ViewUtility.java
deleted file mode 100644
index ba4e091b73..0000000000
--- a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/ViewUtility.java
+++ /dev/null
@@ -1,1036 +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;
-
-import org.apache.commons.codec.binary.Hex;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.events.ControlAdapter;
-import org.eclipse.swt.events.ControlEvent;
-import org.eclipse.swt.events.SelectionAdapter;
-import org.eclipse.swt.events.SelectionEvent;
-import org.eclipse.swt.events.SelectionListener;
-import org.eclipse.swt.graphics.Font;
-import org.eclipse.swt.graphics.Image;
-import org.eclipse.swt.layout.GridData;
-import org.eclipse.swt.layout.GridLayout;
-import org.eclipse.swt.widgets.Button;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Control;
-import org.eclipse.swt.widgets.Display;
-import org.eclipse.swt.widgets.Event;
-import org.eclipse.swt.widgets.Label;
-import org.eclipse.swt.widgets.Listener;
-import org.eclipse.swt.widgets.MessageBox;
-import org.eclipse.swt.widgets.ScrollBar;
-import org.eclipse.swt.widgets.Shell;
-import org.eclipse.swt.widgets.Text;
-import org.eclipse.ui.forms.widgets.FormToolkit;
-
-import org.apache.qpid.management.ui.ApplicationRegistry;
-
-import static org.apache.qpid.management.ui.Constants.FAILURE_IMAGE;
-import static org.apache.qpid.management.ui.Constants.SUCCESS_IMAGE;
-
-import javax.management.openmbean.ArrayType;
-import javax.management.openmbean.CompositeData;
-import javax.management.openmbean.CompositeDataSupport;
-import javax.management.openmbean.CompositeType;
-import javax.management.openmbean.OpenType;
-import javax.management.openmbean.TabularDataSupport;
-import javax.management.openmbean.TabularType;
-import java.io.UnsupportedEncodingException;
-import java.nio.charset.Charset;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * Utility Class for displaying OpenMbean data types by creating required SWT widgets
- */
-public class ViewUtility
-{
- public static final String OP_NAME = "operation_name";
- public static final String OP_PARAMS = "parameters";
- public static final String PARAMS_TEXT = "text";
-
- public static final String FIRST = "First";
- public static final String LAST = "Last";
- public static final String NEXT = "Next";
- public static final String PREV = "Previous";
- public static final String INDEX = "Index";
-
- private static final Comparator tabularDataComparator = new TabularDataComparator();
-
- private static MBeanView _mbeanView = null;
-
- private static List<String> SUPPORTED_ARRAY_DATATYPES = new ArrayList<String>();
- static
- {
- SUPPORTED_ARRAY_DATATYPES.add("java.lang.String");
- SUPPORTED_ARRAY_DATATYPES.add("java.lang.Boolean");
- SUPPORTED_ARRAY_DATATYPES.add("java.lang.Character");
- SUPPORTED_ARRAY_DATATYPES.add("java.lang.Integer");
- SUPPORTED_ARRAY_DATATYPES.add("java.lang.Long");
- SUPPORTED_ARRAY_DATATYPES.add("java.lang.Double");
- SUPPORTED_ARRAY_DATATYPES.add("java.util.Date");
- }
-
- private static final int DEFAULT_CONTENT_SIZE = 198;
- private static Button _firstButton, _nextButton, _previousButton, _lastButton;
- private static Text _hexNumTextToEnd, _hexNumTextToStart;
-
- /**
- * Populates the composite with given openmbean data type (TabularType or CompositeType)
- * @param toolkit
- * @param parent composite
- * @param data open mbean data type(either composite type or tabular data type)
- */
- public static void populateCompositeWithData(FormToolkit toolkit, Composite parent, Object data)
- {
- if (data instanceof TabularDataSupport)
- {
- ViewUtility.createTabularDataHolder(toolkit, parent, (TabularDataSupport)data);
- }
- else if (data instanceof CompositeDataSupport)
- {
- ViewUtility.populateCompositeWithCompositeData(toolkit, parent, (CompositeDataSupport)data);
- }
- }
-
- @SuppressWarnings("unchecked")
- private static void createTabularDataHolder(FormToolkit toolkit, Composite parent, TabularDataSupport tabularData)
- {
- Composite composite = toolkit.createComposite(parent, SWT.BORDER);
- GridLayout layout = new GridLayout(4, true);
- layout.horizontalSpacing = 0;
- layout.marginWidth = 0;
- layout.marginHeight = 10;
- layout.verticalSpacing = 10;
- composite.setLayout(layout);
- composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
-
- Set entrySet = tabularData.entrySet();
- ArrayList<Map.Entry> list = new ArrayList<Map.Entry>(entrySet);
- if (list.size() == 0)
- {
- Text text = toolkit.createText(composite, " No records ", SWT.CENTER | SWT.SINGLE | SWT.READ_ONLY);
- GridData layoutData = new GridData(SWT.FILL, SWT.FILL, true, true, 4, 1);
- text.setLayoutData(layoutData);
- return;
- }
-
- Collections.sort(list, tabularDataComparator);
-
- // Attach the tabular record to be retrieved and shown later when record is traversed
- // using first/next/previous/last buttons
- composite.setData(list);
-
- // Create button and the composite for CompositeData
- Composite compositeDataHolder = createCompositeDataHolder(toolkit, composite,
- tabularData.getTabularType().getRowType());
-
- // display the first record
- CompositeData data = (CompositeData)(list.get(0)).getValue();
- composite.setData(INDEX, 0);
- populateCompositeWithCompositeData(toolkit, compositeDataHolder, data);
- enableOrDisableTraversalButtons(composite);
- }
-
- private static void enableOrDisableTraversalButtons(Composite composite)
- {
- int index = (Integer)composite.getData(INDEX);
- int size = ((List)composite.getData()).size();
-
- ((Button)composite.getData(FIRST)).setEnabled(true);
- ((Button)composite.getData(PREV)).setEnabled(true);
- ((Button)composite.getData(NEXT)).setEnabled(true);
- ((Button)composite.getData(LAST)).setEnabled(true);
-
- if (index == 0)
- {
- ((Button)composite.getData(FIRST)).setEnabled(false);
- ((Button)composite.getData(PREV)).setEnabled(false);
- }
- if (index == size -1)
- {
- ((Button)composite.getData(NEXT)).setEnabled(false);
- ((Button)composite.getData(LAST)).setEnabled(false);
- }
- }
-
- /**
- * Sets up the given composite for holding a CompositeData. Create traversal buttons, label etc and
- * creates a child Composite, which should be populated with the CompositeData
- * @param toolkit
- * @param dataHolder
- * @param compositeType
- * @return
- */
- private static Composite createCompositeDataHolder(final FormToolkit toolkit, final Composite dataHolder, CompositeType compositeType)
- {
- String desc = compositeType.getDescription();
- Label description = toolkit.createLabel(dataHolder, desc, SWT.CENTER);
- description.setLayoutData(new GridData(SWT.CENTER, SWT.TOP, true, false, 4, 1));
- // TODO nameLabel.setFont(font);
- description.setText(desc);
-
- // Add traversal buttons
- final Button firstRecordButton = toolkit.createButton(dataHolder, FIRST, SWT.PUSH);
- GridData layoutData = new GridData (GridData.HORIZONTAL_ALIGN_END);
- layoutData.widthHint = 80;
- firstRecordButton.setLayoutData(layoutData);
-
- final Button previousRecordButton = toolkit.createButton(dataHolder, PREV, SWT.PUSH);
- layoutData = new GridData (GridData.HORIZONTAL_ALIGN_END);
- layoutData.widthHint = 80;
- previousRecordButton.setLayoutData(layoutData);
-
- final Button nextRecordButton = toolkit.createButton(dataHolder, NEXT, SWT.PUSH);
- layoutData = new GridData (GridData.HORIZONTAL_ALIGN_BEGINNING);
- layoutData.widthHint = 80;
- nextRecordButton.setLayoutData(layoutData);
-
- final Button lastRecordButton = toolkit.createButton(dataHolder, LAST, SWT.PUSH);
- layoutData = new GridData (GridData.HORIZONTAL_ALIGN_BEGINNING);
- layoutData.widthHint = 80;
- lastRecordButton.setLayoutData(layoutData);
-
- // Now create the composite, which will hold the CompositeData
- final Composite composite = toolkit.createComposite(dataHolder, SWT.NONE);
- GridLayout layout = new GridLayout();
- layout.horizontalSpacing = layout.verticalSpacing = 0;
- layout.marginHeight = layout.marginWidth = 0;
- composite.setLayout(layout);
- composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 4, 1));
-
- // Add button references. These references will be used when buttons
- // are to enabled or disabled based of record index. e.g. for first record
- // First and Previous buttons will be disabled.
- dataHolder.setData(FIRST, firstRecordButton);
- dataHolder.setData(NEXT, nextRecordButton);
- dataHolder.setData(PREV, previousRecordButton);
- dataHolder.setData(LAST, lastRecordButton);
-
- // Listener for the traversal buttons. When a button is clicked the respective
- // CompositeData will be populated in the composite
- SelectionListener listener = new SelectionAdapter()
- {
- public void widgetSelected(SelectionEvent e)
- {
- if (!(e.widget instanceof Button))
- {
- return;
- }
-
- Button traverseButton =(Button)e.widget;
- // Get the CompositeData respective to the button selected
- CompositeData data = getCompositeData(dataHolder, traverseButton.getText());
- populateCompositeWithCompositeData(toolkit, composite, data);
- enableOrDisableTraversalButtons(dataHolder);
- }
- };
-
- firstRecordButton.addSelectionListener(listener);
- nextRecordButton.addSelectionListener(listener);
- previousRecordButton.addSelectionListener(listener);
- lastRecordButton.addSelectionListener(listener);
-
- return composite;
- }
-
- /**
- * The CompositeData is set as data with the Composite and using the index, this method will
- * return the corresponding CompositeData
- * @param compositeHolder
- * @param dataIndex
- * @return the CompositeData respective to the index
- */
- private static CompositeData getCompositeData(Composite compositeHolder, String dataIndex)
- {
- List objectData = (List)compositeHolder.getData();
- if (objectData == null || objectData.isEmpty())
- {
- // TODO
- }
-
- // Get the index of record to be shown.
- int index = 0;
- if (compositeHolder.getData(INDEX) != null)
- {
- index = (Integer)compositeHolder.getData(INDEX);
- }
-
- if (FIRST.equals(dataIndex))
- {
- index = 0;
- }
- else if (NEXT.equals(dataIndex))
- {
- index = index + 1;
- }
- else if (PREV.equals(dataIndex))
- {
- index = (index != 0) ? (index = index - 1) : index;
- }
- else if (LAST.equals(dataIndex))
- {
- index = objectData.size() -1;
- }
-
- // Set the index being shown.
- compositeHolder.setData(INDEX, index);
-
- return (CompositeData)((Map.Entry)objectData.get(index)).getValue();
- }
-
- /**
- * Populates the given composite with the CompositeData. Creates required widgets to hold the data types
- * @param toolkit
- * @param parent
- * @param data CompositeData
- */
- @SuppressWarnings("unchecked")
- private static void populateCompositeWithCompositeData(FormToolkit toolkit, Composite parent, CompositeData data)
- {
- Control[] oldControls = parent.getChildren();
- for (int i = 0; i < oldControls.length; i++)
- {
- oldControls[i].dispose();
- }
-
- Composite compositeHolder = toolkit.createComposite(parent, SWT.NONE);
- GridLayout layout = new GridLayout(4, false);
- layout.horizontalSpacing = 10;
- compositeHolder.setLayout(layout);
- compositeHolder.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
-
-
- // ItemNames in composite data
- List<String> itemNames = new ArrayList<String>(data.getCompositeType().keySet());
-
- for (String itemName : itemNames)
- {
- OpenType itemType = data.getCompositeType().getType(itemName);
- Label keyLabel = toolkit.createLabel(compositeHolder, itemName, SWT.TRAIL);
- GridData layoutData = new GridData(SWT.FILL, SWT.FILL, false, false, 1, 1);
- layoutData.minimumWidth = 70;
- keyLabel.setLayoutData(layoutData);
-
- if (itemType.isArray())
- {
- OpenType type = ((ArrayType)itemType).getElementOpenType();
- // If Byte array and mimetype is text, convert to text string
- if (type.getClassName().equals(Byte.class.getName()))
- {
- String mimeType = null;
- String encoding = null;
- if (data.containsKey("MimeType"))
- {
- mimeType = (String)data.get("MimeType");
- }
- if (data.containsKey("Encoding"))
- {
- encoding = (String)data.get("Encoding");
- }
-
- if (encoding == null || encoding.length() == 0)
- {
- encoding = Charset.defaultCharset().name();
- }
-
- if ("text/plain".equals(mimeType))
- {
- convertByteArray(toolkit, compositeHolder, data, itemName, encoding);
- }
- else
- {
- handleBinaryMessageContent(toolkit, compositeHolder, data, itemName, encoding);
- }
- }
- // If array of any other supported type, show as a list of String array
- else if (SUPPORTED_ARRAY_DATATYPES.contains(type.getClassName()))
- {
- convertArrayItemForDisplay(compositeHolder, data, itemName);
- }
- else
- {
- setNotSupportedDataType(toolkit, compositeHolder);
- }
- }
- else if (itemType instanceof TabularType)
- {
- Composite composite = toolkit.createComposite(compositeHolder, SWT.NONE);
- composite.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false, 3, 1));
- layout = new GridLayout();
- layout.marginHeight = 0;
- layout.marginWidth = 0;
- composite.setLayout(layout);
- createTabularDataHolder(toolkit, composite, (TabularDataSupport)data.get(itemName));
- }
- else
- {
- Text valueText = toolkit.createText(compositeHolder, String.valueOf(data.get(itemName)), SWT.READ_ONLY | SWT.BORDER);
- valueText.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false, 3, 1));
- }
- }
-
- // layout the composite after creating new widgets.
- parent.layout();
- } //end of method
-
-
- private static void convertByteArray(FormToolkit toolkit, Composite compositeHolder, CompositeData data, String itemName, String encoding)
- {
- Byte[] arrayItems = (Byte[])data.get(itemName);
- byte[] byteArray = new byte[arrayItems.length];
-
- for (int i = 0; i < arrayItems.length; i++)
- {
- byteArray[i] = arrayItems[i];
- }
- try
- {
- String textMessage = new String(byteArray, encoding);
-
- Text valueText = toolkit.createText(compositeHolder, textMessage, SWT.READ_ONLY | SWT.BORDER |
- SWT.MULTI | SWT.WRAP | SWT.V_SCROLL);
- GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, true, 3, 1);
- gridData.heightHint = 300;
- valueText.setLayoutData(gridData);
- }
- catch(Exception ex)
- {
- ex.printStackTrace();
- }
- }
-
- private static Shell getShell()
- {
- Shell shell = Display.getCurrent().getActiveShell();
-
- // Under linux GTK getActiveShell returns null so we need to make a new shell for display.
- // Under windows this is fine.
- if (shell == null)
- {
- // This occurs under linux gtk
- shell = new Shell(Display.getCurrent(), SWT.BORDER | SWT.CLOSE | SWT.MIN | SWT.MAX);
- }
-
- return shell;
- }
-
- private static int showBox(String title, String message, int icon)
- {
- MessageBox messageBox = new MessageBox(getShell(), icon);
- messageBox.setMessage(message);
- messageBox.setText(title);
-
- return messageBox.open();
- }
-
- /**
- * Creates widgets for object messages and populates the content in hexadecimal format.
- * @param toolkit
- * @param compositeHolder
- * @param data
- * @param itemName
- * @param encoding
- */
- private static void handleBinaryMessageContent(FormToolkit toolkit, Composite compositeHolder, CompositeData data, String itemName, String encoding)
- {
- final String thisEncoding = encoding;
- final Byte[] arrayItems = (Byte[]) data.get(itemName);
- final byte[] byteArray = new byte[arrayItems.length];
-
- for (int i = 0; i < arrayItems.length; i++)
- {
- byteArray[i] = arrayItems[i];
- }
-
- try
- {
- //create a new composite to contain the widgets required to display object messages.
- final Composite localComposite = toolkit.createComposite(compositeHolder, SWT.NONE);
- localComposite.setData("currentBytePos", 0);
- localComposite.setData("startingBytePos", 0);
- GridLayout layout = new GridLayout(2, true);
- layout.marginWidth = 0;
- layout.marginHeight = 0;
- localComposite.setLayout(layout);
- localComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 3, 1));
-
- int startContentSize = DEFAULT_CONTENT_SIZE;
-
- if (byteArray.length < DEFAULT_CONTENT_SIZE)
- {
- startContentSize = byteArray.length;
- }
-
- //create a text to display the hexadecimal views of object messages, it takes more space than ascii view as
- //a hex uses 2 chars and 1 space, while ascii only uses 1 char and 1 space.
- final Text hexText = toolkit.createText(localComposite,
- displayByteFormat(localComposite, byteArray, startContentSize * 2, thisEncoding, "<<", true),
- SWT.READ_ONLY | SWT.MULTI | SWT.WRAP | SWT.V_SCROLL | SWT.BORDER);
- GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1);
- gridData.widthHint = 144; //set to 222 if not using any fonts
- gridData.heightHint = 200;
- hexText.setLayoutData(gridData);
-
- final Text asciiText = toolkit.createText(localComposite,
- displayByteFormat(localComposite, byteArray, startContentSize * 2, thisEncoding, "<<", false),
- SWT.READ_ONLY | SWT.MULTI | SWT.WRAP | SWT.V_SCROLL | SWT.BORDER);
-
-
- gridData = new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1);
- gridData.widthHint = 52;//set to 98 if not using any fonts
- gridData.heightHint = 200;
- asciiText.setLayoutData(gridData);
-
- //use a monospaced font for a better layout
- Font font = new Font(compositeHolder.getDisplay(), "Courier", 10, SWT.NORMAL);
- hexText.setFont(font);
- asciiText.setFont(font);
-
- final ScrollBar hexScrollBar = hexText.getVerticalBar();
- final ScrollBar asciiScrollBar = asciiText.getVerticalBar();
-
- //create a sub composite to contain all the buttons
- final Composite buttonComposite = toolkit.createComposite(localComposite, SWT.NONE);
- layout = new GridLayout(7, false);
- layout.marginWidth = 0;
- buttonComposite.setLayout(layout);
- buttonComposite.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false, 2, 1));
-
- _firstButton = toolkit.createButton(buttonComposite, "<<", SWT.PUSH);
- GridData layoutData = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
- layoutData.widthHint = 40;
- _firstButton.setLayoutData(layoutData);
- _firstButton.setToolTipText("See the first n bytes");
-
- _previousButton = toolkit.createButton(buttonComposite, "<", SWT.PUSH);
- layoutData = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
- layoutData.widthHint = 40;
- _previousButton.setLayoutData(layoutData);
- _previousButton.setToolTipText("See the previous n bytes");
- _previousButton.setEnabled(false);
-
- _hexNumTextToStart = toolkit.createText(buttonComposite, "0");
- layoutData = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
- layoutData.widthHint = 40;
- _hexNumTextToStart.setLayoutData(layoutData);
- _hexNumTextToStart.setEditable(false);
-
- final Text hexNumText = toolkit.createText(buttonComposite, "" + startContentSize);
- layoutData = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
- layoutData.widthHint = 40;
- hexNumText.setLayoutData(layoutData);
-
- _hexNumTextToEnd = toolkit.createText(buttonComposite, "" + (byteArray.length - startContentSize));
- layoutData = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
- layoutData.widthHint = 40;
- _hexNumTextToEnd.setLayoutData(layoutData);
- _hexNumTextToEnd.setEditable(false);
-
- _nextButton = toolkit.createButton(buttonComposite, ">", SWT.PUSH);
- layoutData = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
- layoutData.widthHint = 40;
- _nextButton.setLayoutData(layoutData);
- _nextButton.setToolTipText("See the next n bytes");
- _nextButton.setEnabled(true);
-
- _lastButton = toolkit.createButton(buttonComposite, ">>", SWT.PUSH);
- layoutData = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
- layoutData.widthHint = 40;
- _lastButton.setToolTipText("See the last n bytes");
- _lastButton.setLayoutData(layoutData);
-
- SelectionListener listener = new SelectionAdapter()
- {
- public void widgetSelected(SelectionEvent e)
- {
- if (e.widget instanceof Button)
- {
- String numOfBytes = hexNumText.getText();
- try
- {
- int n = Integer.parseInt(numOfBytes);
-
- //Reset range display if user requests a large value
- if (n > byteArray.length)
- {
- n = (byteArray.length > DEFAULT_CONTENT_SIZE) ? DEFAULT_CONTENT_SIZE : byteArray.length;
- hexNumText.setText("" + n);
- }
-
- //rest if the user requests 0
- if (n < 1)
- {
- n = DEFAULT_CONTENT_SIZE;
- hexNumText.setText("" + n);
- }
-
- Button button = (Button) e.widget;
- hexText.setText(displayByteFormat(localComposite, byteArray, n * 2, thisEncoding,
- button.getText(), true));
- asciiText.setText(displayByteFormat(localComposite, byteArray, n * 2, thisEncoding,
- button.getText(), false));
- }
- catch (NumberFormatException exp)
- {
- popupErrorMessage("Error", "Please input the number of bytes you wish to look at");
- }
- }
- if (e.widget instanceof ScrollBar)
- {
- //synchronize the movements of the two scrollbars
- ScrollBar sb = (ScrollBar) e.widget;
- if (sb.getParent().equals(hexText))
- {
- asciiScrollBar.setIncrement(sb.getIncrement());
- asciiScrollBar.setSelection(sb.getSelection());
- }
- else if (sb.getParent().equals(asciiText))
- {
- hexScrollBar.setSelection(sb.getSelection());
- hexScrollBar.setIncrement(sb.getIncrement());
- }
- }
- }
- };
- localComposite.addControlListener(new ControlAdapter()
- {
- public void controlResized(ControlEvent e)
- {
- //if the control is resized, set different parameters to make a single line displays the same contents.
- if (((GridLayout) localComposite.getLayout()).makeColumnsEqualWidth)
- {
- ((GridLayout) localComposite.getLayout()).makeColumnsEqualWidth = false;
- ((GridLayout) localComposite.getLayout()).numColumns = 2;
- ((GridData) hexText.getLayoutData()).horizontalSpan = 1;
- ((GridData) hexText.getLayoutData()).widthHint = 144;
- ((GridData) asciiText.getLayoutData()).horizontalSpan = 1;
- ((GridData) asciiText.getLayoutData()).widthHint = 52;
- ((GridData) buttonComposite.getLayoutData()).horizontalSpan = 2;
- }
- else
- {
- ((GridLayout) localComposite.getLayout()).makeColumnsEqualWidth = true;
- ((GridLayout) localComposite.getLayout()).numColumns = 42; //set to 47 if not using any fonts
- ((GridData) hexText.getLayoutData()).horizontalSpan = 25; // set to 30 if not using any fonts
- ((GridData) asciiText.getLayoutData()).horizontalSpan = 17; // set to 17 if not using any fonts
- ((GridData) buttonComposite.getLayoutData()).horizontalSpan = 42;
- }
- }
- });
-
- _firstButton.addSelectionListener(listener);
- _previousButton.addSelectionListener(listener);
- _nextButton.addSelectionListener(listener);
- _lastButton.addSelectionListener(listener);
- hexScrollBar.addSelectionListener(listener);
- asciiScrollBar.addSelectionListener(listener);
- //f.dispose();
- }
- catch (Exception ex)
- {
- ex.printStackTrace();
- }
- }
-
- /**
- * Format object messages to have a hexadecimal view and a ascii view.
- * @param numOfBytes
- * @param encoding
- * @return
- */
- private static String displayByteFormat(Composite localComposite, byte[] byteArray, int numOfBytes,
- String encoding, String direction, boolean isHex)
- {
- final Hex hexeconder = new Hex();
- final byte[] encoded = hexeconder.encode(byteArray);
-
- int hexLength = byteArray.length * 2;
- StringBuilder sb = new StringBuilder();
- int currentBytePos = (Integer) localComposite.getData("currentBytePos");
- int startingBytePos = (Integer) localComposite.getData("startingBytePos");
-
- int strLength = 0;
- int offset = 0;
- String encStr;
- if (isHex)
- {
- if (direction.equals("<<"))
- {
- strLength = (numOfBytes > hexLength) ? hexLength : numOfBytes;
- offset = 0;
- }
- else if (direction.equals("<"))
- {
- strLength = (startingBytePos - numOfBytes < 0) ? startingBytePos : numOfBytes;
- offset = (startingBytePos - numOfBytes < 0) ? 0 : startingBytePos - numOfBytes;
- }
- else if (direction.equals(">"))
- {
- strLength = (numOfBytes > (hexLength - currentBytePos)) ? hexLength - currentBytePos : numOfBytes;
- offset = currentBytePos;
- }
- else if (direction.equals(">>"))
- {
- strLength = (numOfBytes > hexLength) ? hexLength : numOfBytes;
- offset = (hexLength - numOfBytes > 0) ? hexLength - numOfBytes : 0;
- }
- else
- {
- strLength = hexLength;
- offset = 0;
- }
- localComposite.setData("strLength", strLength);
- localComposite.setData("currentBytePos", offset + strLength);
- localComposite.setData("startingBytePos", offset);
-
- if (_lastButton != null && !_lastButton.isDisposed())
- {
- //Set button state
- _previousButton.setEnabled(offset != 0);
- _nextButton.setEnabled(offset + strLength != hexLength);
-
- //set the text fields
- _hexNumTextToStart.setText("" + offset / 2);
- _hexNumTextToEnd.setText("" + (hexLength - (offset + strLength)) / 2);
- }
- }
-
- try
- {
- if (isHex)
- {
- encStr = new String(encoded, offset, strLength, encoding);
- for (int c = 0; c < strLength; c++)
- {
- sb.append(encStr.charAt(c));
- if (c % 2 == 1)
- {
- sb.append(" ");
- }
- }
- return sb.toString().toUpperCase();
- }
- else
- {
- strLength = (Integer) localComposite.getData("strLength");
- sb = new StringBuilder();
- encStr = new String(byteArray, startingBytePos / 2, strLength / 2, encoding);
- for (int c = 0; c < encStr.length(); c++)
- {
- char ch = encStr.charAt(c);
- if (ch > 31 && ch < 127)
- {
- sb.append(ch);
- }
- else
- {
- sb.append("?");
- }
-
- sb.append(" ");
- }
- }
- }
- catch (UnsupportedEncodingException e)
- {
- e.printStackTrace();
- }
- return sb.toString();
- }
-
- public static int popupInfoMessage(String title, String message)
- {
- return showBox(title, message, SWT.ICON_INFORMATION | SWT.OK);
- }
-
- public static int popupErrorMessage(String title, String message)
- {
- return showBox(title, message, SWT.ICON_ERROR | SWT.OK);
- }
-
- public static int popupConfirmationMessage(String title, String message)
- {
- return showBox(title, message,SWT.ICON_QUESTION | SWT.YES | SWT.NO);
- }
-
- public static int popupOkCancelConfirmationMessage(String title, String message)
- {
- return showBox(title, message,SWT.ICON_QUESTION | SWT.OK | SWT.CANCEL);
- }
-
-
- public static Shell createPopupShell(String title, int width, int height)
- {
- Display display = Display.getCurrent();
- final Shell shell = new Shell(display, SWT.BORDER | SWT.CLOSE | SWT.MIN |SWT.MAX);
- shell.setText(title);
- shell.setLayout(new GridLayout());
- int x = display.getBounds().width;
- int y = display.getBounds().height;
- shell.setBounds(x/4, y/4, width, height);
-
- shell.addListener(SWT.Traverse, new Listener () {
- public void handleEvent (Event event) {
- switch (event.detail) {
- case SWT.TRAVERSE_ESCAPE:
- shell.close ();
- event.detail = SWT.TRAVERSE_NONE;
- event.doit = false;
- break;
- }
- }
- });
-
- return shell;
- }
-
- public static Shell createModalDialogShell(Shell parent, String title)
- {
- final Shell shell = new Shell(parent, SWT.DIALOG_TRIM | SWT.APPLICATION_MODAL);
- shell.setText(title);
- shell.setLayout(new GridLayout());
-
- shell.addListener(SWT.Traverse, new Listener () {
- public void handleEvent (Event event) {
- switch (event.detail) {
- case SWT.TRAVERSE_ESCAPE:
- shell.close ();
- event.detail = SWT.TRAVERSE_NONE;
- event.doit = false;
- break;
- }
- }
- });
-
- return shell;
- }
-
- /**
- * Creates a List widget for displaying array of strings
- * @param compositeHolder
- * @param data - containing the array item value
- * @param itemName - item name
- */
- private static void convertArrayItemForDisplay(Composite compositeHolder, CompositeData data, String itemName)
- {
- Object[] arrayItems = (Object[])data.get(itemName);
- String[] items = new String[arrayItems.length];
- for (int i = 0; i < arrayItems.length; i++)
- {
- items[i] = String.valueOf(arrayItems[i]);
- }
- org.eclipse.swt.widgets.List list = new org.eclipse.swt.widgets.List(compositeHolder,
- SWT.MULTI | SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL | SWT.READ_ONLY);
- list.setItems(items);
- //list.setBackground(compositeHolder.getBackground());
- list.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 3, 1));
- }
-
- private static void setNotSupportedDataType(FormToolkit toolkit, Composite compositeHolder)
- {
- Text valueText = toolkit.createText(compositeHolder, "--- Content can not be displayed ---", SWT.READ_ONLY);
- valueText.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false, 3, 1));
- }
-
- /**
- * Converts the input string to displayable format by converting some character case or inserting space
- * @param input
- * @return formatted string
- */
- public static String getDisplayText(String input)
- {
- StringBuffer result = new StringBuffer(input);
- if (Character.isLowerCase(result.charAt(0)))
- {
- result.setCharAt(0, Character.toUpperCase(result.charAt(0)));
- }
- for (int i = 1; i < input.length(); i++)
- {
- if (Character.isUpperCase(result.charAt(i)) && !Character.isWhitespace(result.charAt(i - 1))
- && Character.isLowerCase(result.charAt(i - 1)))
- {
- result.insert(i, " ");
- i++;
- }
- else if (Character.isLowerCase(result.charAt(i)) && Character.isWhitespace(result.charAt(i - 1)))
- {
- result.setCharAt(i, Character.toUpperCase(result.charAt(i)));
- }
-
- }
-
- return result.toString();
- }
-
- /**
- * Disposes the children of given Composite if not null and not already disposed
- * @param parent composite
- */
- public static void disposeChildren(Composite parent)
- {
- if (parent == null || parent.isDisposed())
- {
- return;
- }
-
- Control[] oldControls = parent.getChildren();
- for (int i = 0; i < oldControls.length; i++)
- {
- oldControls[i].dispose();
- }
- }
-
- public static char[] getHash(String text) throws NoSuchAlgorithmException, UnsupportedEncodingException
- {
- byte[] data = text.getBytes("utf-8");
-
- MessageDigest md = MessageDigest.getInstance("MD5");
-
- for (byte b : data)
- {
- md.update(b);
- }
-
- byte[] digest = md.digest();
-
- char[] hash = new char[digest.length ];
-
- int index = 0;
- for (byte b : digest)
- {
- hash[index++] = (char) b;
- }
-
- return hash;
- }
-
- private static class TabularDataComparator implements java.util.Comparator<Map.Entry>
- {
- public int compare(Map.Entry data1, Map.Entry data2)
- {
- if (data1.getKey() instanceof List)
- {
- Object obj1 = ((List)data1.getKey()).get(0);
- Object obj2 = ((List)data2.getKey()).get(0);
- String str1 = obj1.toString();
- String str2 = obj2.toString();
- if (obj1 instanceof String)
- {
- return str1.compareTo(str2);
- }
-
- try
- {
- return Long.valueOf(str1).compareTo(Long.valueOf(str2));
- }
- catch (Exception ex)
- {
- return -1;
- }
- }
-
- return -1;
- }
- }
-
- public static void setMBeanView(MBeanView mbeanView)
- {
- _mbeanView = mbeanView;
- }
-
- /**
- * Report feedback for the operation
- * @param result true if success, false if unsuccessful, null if invoked but void result type.
- * @param successMessage
- * @param failureMessage
- */
- public static void operationResultFeedback(Boolean result, String successMessage, String failureMessage)
- {
- Image icon;
-
- if(_mbeanView != null)
- {
- if(result == null)
- {
- icon = ApplicationRegistry.getImage(SUCCESS_IMAGE);
- _mbeanView.populateStatusBar(icon, successMessage);
- }
- else if(result)
- {
- icon = ApplicationRegistry.getImage(SUCCESS_IMAGE);
- _mbeanView.populateStatusBar(icon, successMessage);
- }
- else
- {
- icon = ApplicationRegistry.getImage(FAILURE_IMAGE);
- _mbeanView.populateStatusBar(icon, failureMessage);
- popupErrorMessage("Operation Failed", failureMessage);
- }
- }
- }
-
- public static void operationFailedStatusBarMessage(String failureMessage)
- {
- Image icon = ApplicationRegistry.getImage(FAILURE_IMAGE);
-
- if(_mbeanView != null)
- {
- _mbeanView.populateStatusBar(icon, failureMessage);
- }
- }
-
- public static void clearStatusBar()
- {
- if(_mbeanView != null)
- {
- _mbeanView.clearStatusBar();
- }
- }
-
- public static void centerChildInParentShell(Shell parent, Shell child)
- {
- //get current parent shell size and location
- int parentLocX = parent.getBounds().x;
- int parentLocY = parent.getBounds().y;
- int parentWidth = parent.getBounds().width;
- int parentHeight = parent.getBounds().height;
-
- //get current child size
- int childWidth = child.getSize().x;
- int childHeight = child.getSize().y;
-
- //centre the child within/over the parent
- child.setBounds((parentWidth - childWidth)/2 + parentLocX,
- (parentHeight - childHeight)/2 + parentLocY,
- childWidth, childHeight);
- }
-
-}
diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/connection/ConnectionOperationsTabControl.java b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/connection/ConnectionOperationsTabControl.java
deleted file mode 100644
index c053da5108..0000000000
--- a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/connection/ConnectionOperationsTabControl.java
+++ /dev/null
@@ -1,545 +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.connection;
-
-import org.eclipse.jface.viewers.ISelectionChangedListener;
-import org.eclipse.jface.viewers.IStructuredContentProvider;
-import org.eclipse.jface.viewers.ITableLabelProvider;
-import org.eclipse.jface.viewers.LabelProvider;
-import org.eclipse.jface.viewers.SelectionChangedEvent;
-import org.eclipse.jface.viewers.TableViewer;
-import org.eclipse.jface.viewers.Viewer;
-import org.eclipse.jface.viewers.ViewerSorter;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.events.MouseEvent;
-import org.eclipse.swt.events.MouseListener;
-import org.eclipse.swt.events.SelectionAdapter;
-import org.eclipse.swt.events.SelectionEvent;
-import org.eclipse.swt.graphics.Image;
-import org.eclipse.swt.layout.GridData;
-import org.eclipse.swt.layout.GridLayout;
-import org.eclipse.swt.widgets.Button;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Control;
-import org.eclipse.swt.widgets.Group;
-import org.eclipse.swt.widgets.TabFolder;
-import org.eclipse.swt.widgets.Table;
-import org.eclipse.swt.widgets.TableColumn;
-import org.eclipse.ui.IWorkbenchWindow;
-import org.eclipse.ui.PlatformUI;
-import org.eclipse.ui.forms.widgets.Form;
-import org.eclipse.ui.forms.widgets.FormToolkit;
-
-import org.apache.qpid.management.common.mbeans.ManagedConnection;
-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.ui.ServerRegistry;
-import org.apache.qpid.management.ui.jmx.JMXManagedObject;
-import org.apache.qpid.management.ui.jmx.MBeanUtility;
-import org.apache.qpid.management.ui.views.MBeanView;
-import org.apache.qpid.management.ui.views.TabControl;
-import org.apache.qpid.management.ui.views.ViewUtility;
-
-import static org.apache.qpid.management.common.mbeans.ManagedConnection.CHAN_ID;
-import static org.apache.qpid.management.common.mbeans.ManagedConnection.DEFAULT_QUEUE;
-import static org.apache.qpid.management.common.mbeans.ManagedConnection.FLOW_BLOCKED;
-import static org.apache.qpid.management.common.mbeans.ManagedConnection.TRANSACTIONAL;
-import static org.apache.qpid.management.common.mbeans.ManagedConnection.UNACKED_COUNT;
-
-import javax.management.MBeanServerConnection;
-import javax.management.MBeanServerInvocationHandler;
-import javax.management.openmbean.CompositeData;
-import javax.management.openmbean.CompositeDataSupport;
-import javax.management.openmbean.TabularDataSupport;
-import java.util.Collection;
-
-
-/**
- * Control class for the Connection mbean Operations tab.
- */
-public class ConnectionOperationsTabControl extends TabControl
-{
- private FormToolkit _toolkit;
- private Form _form;
- private Table _table = null;
- private TableViewer _tableViewer = null;
- private Composite _paramsComposite = null;
-
- private TabularDataSupport _channels = null;
- private ManagedConnection _cmb;
- private ApiVersion _ApiVersion;
-
- public ConnectionOperationsTabControl(TabFolder tabFolder, JMXManagedObject mbean, MBeanServerConnection mbsc)
- {
- super(tabFolder);
- _mbean = mbean;
- _ApiVersion = ApplicationRegistry.getServerRegistry(mbean).getManagementApiVersion();
- _cmb = (ManagedConnection) MBeanServerInvocationHandler.newProxyInstance(mbsc,
- mbean.getObjectName(), ManagedConnection.class, false);
- _toolkit = new FormToolkit(_tabFolder.getDisplay());
- _form = _toolkit.createForm(_tabFolder);
- _form.getBody().setLayout(new GridLayout());
- createComposites();
- createWidgets();
- }
-
- private void createComposites()
- {
- _paramsComposite = _toolkit.createComposite(_form.getBody(), SWT.NONE);
- _paramsComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
- _paramsComposite.setLayout(new GridLayout());
- }
-
- /**
- * @see TabControl#getControl()
- */
- public Control getControl()
- {
- return _form;
- }
-
- /**
- * @see TabControl#setFocus()
- */
- public void setFocus()
- {
- _table.setFocus();
- }
-
- @Override
- public void refresh(ManagedBean mbean)
- {
- _channels = null;
- try
- {
- //gather a list of all channels on the connection for display and selection
- _channels = (TabularDataSupport) _cmb.channels();
- }
- catch (Exception e)
- {
- MBeanUtility.handleException(mbean,e);
- }
-
- _tableViewer.setInput(_channels);
-
- layout();
- }
-
- public void layout()
- {
- _form.layout(true);
- _form.getBody().layout(true, true);
- }
-
- private void createWidgets()
- {
- Group viewChannelsGroup = new Group(_paramsComposite, SWT.SHADOW_NONE);
- viewChannelsGroup.setBackground(_paramsComposite.getBackground());
- viewChannelsGroup.setText("Channels");
- viewChannelsGroup.setLayout(new GridLayout());
- GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
- gridData.heightHint = 250;
- gridData.minimumHeight = 250;
-
- viewChannelsGroup.setLayoutData(gridData);
-
- _table = new Table (viewChannelsGroup, SWT.SINGLE | SWT.SCROLL_LINE | SWT.BORDER | SWT.FULL_SELECTION);
- _table.setLinesVisible (true);
- _table.setHeaderVisible (true);
- GridData data = new GridData(SWT.FILL, SWT.FILL, true, true);
- _table.setLayoutData(data);
-
- _tableViewer = new TableViewer(_table);
- final TableSorter tableSorter = new TableSorter();
-
- String[] titles;
- if(_ApiVersion.greaterThanOrEqualTo(1, 5))
- {
- titles = new String[]{"Id", "Transactional", "Num Unacked Msg", "Default Queue", "Flow Blocked"};
- }
- else
- {
- titles = new String[]{"Id", "Transactional", "Num Unacked Msg", "Default Queue"};
- }
- int[] bounds = { 50, 110, 145, 200, 110 };
- for (int i = 0; i < titles.length; i++)
- {
- final int index = i;
- final TableColumn column = new TableColumn (_table, SWT.NONE);
-
- column.setText(titles[i]);
- column.setWidth(bounds[i]);
- column.setResizable(true);
-
- //Setting the right sorter
- column.addSelectionListener(new SelectionAdapter()
- {
- @Override
- public void widgetSelected(SelectionEvent e)
- {
- tableSorter.setColumn(index);
- final TableViewer viewer = _tableViewer;
- int dir = viewer .getTable().getSortDirection();
- if (viewer.getTable().getSortColumn() == column)
- {
- dir = dir == SWT.UP ? SWT.DOWN : SWT.UP;
- }
- else
- {
- dir = SWT.UP;
- }
- viewer.getTable().setSortDirection(dir);
- viewer.getTable().setSortColumn(column);
- viewer.refresh();
- }
- });
-
- }
-
- _tableViewer.setContentProvider(new ContentProviderImpl());
- _tableViewer.setLabelProvider(new LabelProviderImpl());
- _tableViewer.setSorter(tableSorter);
- _table.setSortColumn(_table.getColumn(0));
- _table.setSortDirection(SWT.UP);
-
- Composite buttonsComposite = _toolkit.createComposite(viewChannelsGroup);
- gridData = new GridData(SWT.RIGHT, SWT.BOTTOM, false, false);
- buttonsComposite.setLayoutData(gridData);
- buttonsComposite.setLayout(new GridLayout(2,false));
-
- final Button commitButton = _toolkit.createButton(buttonsComposite, "Commit Transactions", SWT.PUSH);
- commitButton.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false));
- commitButton.setEnabled(false);
- commitButton.addSelectionListener(new SelectionAdapter()
- {
- public void widgetSelected(SelectionEvent e)
- {
- int selectionIndex = _table.getSelectionIndex();
-
- if (selectionIndex != -1)
- {
- final CompositeData selectedChannel = (CompositeData)_table.getItem(selectionIndex).getData();
- Integer id = (Integer) selectedChannel.get(CHAN_ID);
-
- int response = ViewUtility.popupOkCancelConfirmationMessage("Commit Transactions",
- "Commit transactions for channel:" + id + " ?");
-
- if (response == SWT.OK)
- {
- try
- {
- _cmb.commitTransactions(id);
- ViewUtility.operationResultFeedback(null, "Commited transactions", null);
- }
- catch (Exception e1)
- {
- ViewUtility.operationFailedStatusBarMessage("Error commiting transactions");
- MBeanUtility.handleException(_mbean, e1);
- }
-
- refresh(_mbean);;
- }
- }
- }
- });
-
- final Button rollbackButton = _toolkit.createButton(buttonsComposite, "Rollback Transactions", SWT.PUSH);
- rollbackButton.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false));
- rollbackButton.setEnabled(false);
- rollbackButton.addSelectionListener(new SelectionAdapter()
- {
- public void widgetSelected(SelectionEvent e)
- {
- int selectionIndex = _table.getSelectionIndex();
-
- if (selectionIndex != -1)
- {
- final CompositeData selectedChannel = (CompositeData)_table.getItem(selectionIndex).getData();
- Integer id = (Integer) selectedChannel.get(CHAN_ID);
-
- int response = ViewUtility.popupOkCancelConfirmationMessage("Rollback Transactions",
- "Rollback transactions for channel:" + id + " ?");
-
- if (response == SWT.OK)
- {
- try
- {
- _cmb.rollbackTransactions(id);
- ViewUtility.operationResultFeedback(null, "Rolled back transactions", null);
- }
- catch (Exception e1)
- {
- ViewUtility.operationFailedStatusBarMessage("Error rolling back transactions");
- MBeanUtility.handleException(_mbean, e1);
- }
-
- refresh(_mbean);;
- }
- }
-
- }
- });
-
- //listener for double clicking to open the selection mbean
- _table.addMouseListener(new MouseListener()
- {
- // MouseListener implementation
- public void mouseDoubleClick(MouseEvent event)
- {
- openMBean(_table);
- }
-
- public void mouseDown(MouseEvent e){}
- public void mouseUp(MouseEvent e){}
- });
-
- _tableViewer.addSelectionChangedListener(new ISelectionChangedListener(){
- public void selectionChanged(SelectionChangedEvent evt)
- {
- int selectionIndex = _table.getSelectionIndex();
-
- if (selectionIndex != -1)
- {
- final CompositeData selectedChannel = (CompositeData)_table.getItem(selectionIndex).getData();
- Boolean transactional = (Boolean) selectedChannel.get(TRANSACTIONAL);
-
- if(transactional)
- {
- rollbackButton.setEnabled(true);
- commitButton.setEnabled(true);
- }
- else
- {
- rollbackButton.setEnabled(false);
- commitButton.setEnabled(false);
- }
- }
- else
- {
- rollbackButton.setEnabled(false);
- commitButton.setEnabled(true);
- }
- }
- });
-
- Composite opsComposite = _toolkit.createComposite(_paramsComposite);
- gridData = new GridData(SWT.LEFT, SWT.FILL, false, true);
- opsComposite.setLayoutData(gridData);
- opsComposite.setLayout(new GridLayout(3,false));
-
- Group closeConnectionGroup = new Group(opsComposite, SWT.SHADOW_NONE);
- closeConnectionGroup.setBackground(opsComposite.getBackground());
- closeConnectionGroup.setText("Close Connection");
- gridData = new GridData(SWT.LEFT, SWT.TOP, true, false);
- closeConnectionGroup.setLayoutData(gridData);
- closeConnectionGroup.setLayout(new GridLayout());
-
- final Button closeConnectionButton = _toolkit.createButton(closeConnectionGroup, "Close Connection", SWT.PUSH);
- closeConnectionButton.addSelectionListener(new SelectionAdapter()
- {
- public void widgetSelected(SelectionEvent e)
- {
- int response = ViewUtility.popupOkCancelConfirmationMessage("Close Connection",
- "Are you sure you wish to close the Connection?");
-
- if (response == SWT.OK)
- {
- try
- {
- _cmb.closeConnection();
- }
- catch (Exception e1)
- {
- MBeanUtility.handleException(_mbean, e1);
- }
- }
- }
- });
- }
-
-
- /**
- * Content Provider class for the table viewer
- */
- private static class ContentProviderImpl implements IStructuredContentProvider
- {
-
- public void inputChanged(Viewer v, Object oldInput, Object newInput)
- {
-
- }
-
- public void dispose()
- {
-
- }
-
- public Object[] getElements(Object parent)
- {
- Collection<Object> rowCollection = ((TabularDataSupport) parent).values();
-
- return rowCollection.toArray();
- }
- }
-
- /**
- * Label Provider class for the table viewer
- */
- private static class LabelProviderImpl extends LabelProvider implements ITableLabelProvider
- {
- public String getColumnText(Object element, int columnIndex)
- {
- switch (columnIndex)
- {
- case 0 : // id column
- return String.valueOf(((CompositeDataSupport) element).get(CHAN_ID));
- case 1 : // transactional column
- return String.valueOf(((CompositeDataSupport) element).get(TRANSACTIONAL));
- case 2 : // num unacked msgs column
- return String.valueOf(((CompositeDataSupport) element).get(UNACKED_COUNT));
- case 3 : // default queue column
- return String.valueOf(((CompositeDataSupport) element).get(DEFAULT_QUEUE));
- case 4 : // flow blocked column
- return String.valueOf(((CompositeDataSupport) element).get(FLOW_BLOCKED));
- default :
- return "-";
- }
- }
-
- public Image getColumnImage(Object element, int columnIndex)
- {
- return null;
- }
-
- }
-
- /**
- * Sorter class for the table viewer.
- *
- */
- public static class TableSorter extends ViewerSorter
- {
- private int column;
- private static final int ASCENDING = 0;
- private static final int DESCENDING = 1;
-
- private int direction = DESCENDING;
-
- public TableSorter()
- {
- this.column = 0;
- direction = ASCENDING;
- }
-
- public void setColumn(int column)
- {
- if (column == this.column)
- {
- // Same column as last sort; toggle the direction
- direction = 1 - direction;
- }
- else
- {
- // New column; do an ascending sort
- this.column = column;
- direction = ASCENDING;
- }
- }
-
- @Override
- public int compare(Viewer viewer, Object e1, Object e2)
- {
- CompositeData chan1 = (CompositeData) e1;
- CompositeData chan2 = (CompositeData) e2;
-
- int comparison = 0;
- switch(column)
- {
- case 0:
- comparison = ((Integer) chan1.get(CHAN_ID)).compareTo((Integer)chan2.get(CHAN_ID));
- break;
- case 1:
- comparison = String.valueOf(chan1.get(TRANSACTIONAL)).compareTo(
- String.valueOf(chan2.get(TRANSACTIONAL)));
- break;
- case 2:
- comparison = ((Long) chan1.get(UNACKED_COUNT)).compareTo((Long)chan2.get(UNACKED_COUNT));
- break;
- case 3:
- comparison = String.valueOf(chan1.get(DEFAULT_QUEUE)).compareTo(
- String.valueOf(chan2.get(DEFAULT_QUEUE)));
- break;
- case 4:
- comparison = String.valueOf(chan1.get(FLOW_BLOCKED)).compareTo(
- String.valueOf(chan2.get(FLOW_BLOCKED)));
- break;
- default:
- comparison = 0;
- }
- // If descending order, flip the direction
- if(direction == DESCENDING)
- {
- comparison = -comparison;
- }
- return comparison;
- }
- }
-
- private void openMBean(Table table)
- {
- int selectionIndex = table.getSelectionIndex();
-
- if (selectionIndex == -1)
- {
- return;
- }
-
- CompositeData channelResult = (CompositeData) table.getItem(selectionIndex).getData();
- String queueName = (String) channelResult.get(DEFAULT_QUEUE);
-
- if(queueName == null)
- {
- return;
- }
-
- ServerRegistry serverRegistry = ApplicationRegistry.getServerRegistry(_mbean);
- ManagedBean selectedMBean = serverRegistry.getQueue(queueName, _mbean.getVirtualHostName());
-
- if(selectedMBean == null)
- {
- ViewUtility.popupErrorMessage("Error", "Unable to retrieve the selected MBean to open it");
- return;
- }
-
- IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
- MBeanView view = (MBeanView) window.getActivePage().findView(MBeanView.ID);
- try
- {
- view.openMBean(selectedMBean);
- }
- catch (Exception ex)
- {
- MBeanUtility.handleException(selectedMBean, ex);
- }
- }
-
-}
diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/exchange/ExchangeOperationsTabControl.java b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/exchange/ExchangeOperationsTabControl.java
deleted file mode 100644
index 43db89baea..0000000000
--- a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/exchange/ExchangeOperationsTabControl.java
+++ /dev/null
@@ -1,722 +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.exchange;
-
-import org.eclipse.jface.viewers.ISelectionChangedListener;
-import org.eclipse.jface.viewers.IStructuredContentProvider;
-import org.eclipse.jface.viewers.ITableLabelProvider;
-import org.eclipse.jface.viewers.LabelProvider;
-import org.eclipse.jface.viewers.SelectionChangedEvent;
-import org.eclipse.jface.viewers.TableViewer;
-import org.eclipse.jface.viewers.Viewer;
-import org.eclipse.jface.viewers.ViewerSorter;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.events.MouseEvent;
-import org.eclipse.swt.events.MouseListener;
-import org.eclipse.swt.events.SelectionAdapter;
-import org.eclipse.swt.events.SelectionEvent;
-import org.eclipse.swt.graphics.Image;
-import org.eclipse.swt.layout.GridData;
-import org.eclipse.swt.layout.GridLayout;
-import org.eclipse.swt.widgets.Button;
-import org.eclipse.swt.widgets.Combo;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Control;
-import org.eclipse.swt.widgets.Group;
-import org.eclipse.swt.widgets.Shell;
-import org.eclipse.swt.widgets.TabFolder;
-import org.eclipse.swt.widgets.Table;
-import org.eclipse.swt.widgets.TableColumn;
-import org.eclipse.swt.widgets.Text;
-import org.eclipse.ui.IWorkbenchWindow;
-import org.eclipse.ui.PlatformUI;
-import org.eclipse.ui.forms.widgets.FormToolkit;
-import org.eclipse.ui.forms.widgets.ScrolledForm;
-
-import org.apache.qpid.management.common.mbeans.ManagedExchange;
-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.ui.ServerRegistry;
-import org.apache.qpid.management.ui.jmx.JMXManagedObject;
-import org.apache.qpid.management.ui.jmx.MBeanUtility;
-import org.apache.qpid.management.ui.views.MBeanView;
-import org.apache.qpid.management.ui.views.TabControl;
-import org.apache.qpid.management.ui.views.ViewUtility;
-
-import static org.apache.qpid.management.common.mbeans.ManagedExchange.BINDING_KEY;
-import static org.apache.qpid.management.common.mbeans.ManagedExchange.QUEUE_NAMES;
-import static org.apache.qpid.management.ui.Constants.DIRECT_EXCHANGE;
-import static org.apache.qpid.management.ui.Constants.EXCHANGE_TYPE;
-import static org.apache.qpid.management.ui.Constants.FANOUT_EXCHANGE;
-import static org.apache.qpid.management.ui.Constants.TOPIC_EXCHANGE;
-
-import javax.management.MBeanServerConnection;
-import javax.management.MBeanServerInvocationHandler;
-import javax.management.openmbean.CompositeData;
-import javax.management.openmbean.CompositeDataSupport;
-import javax.management.openmbean.TabularDataSupport;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-
-
-/**
- * Control class for the Exchange mbean Operations tab.
- */
-public class ExchangeOperationsTabControl extends TabControl
-{
- private FormToolkit _toolkit;
- private ScrolledForm _form;
- private Table _keysTable = null;
- private TableViewer _keysTableViewer = null;
- private Table _queuesTable = null;
- private TableViewer _queuesTableViewer = null;
- private Composite _paramsComposite = null;
-
- private TabularDataSupport _bindings = null;
- private ManagedExchange _emb;
- private ApiVersion _ApiVersion;
-
- public ExchangeOperationsTabControl(TabFolder tabFolder, JMXManagedObject mbean, MBeanServerConnection mbsc)
- {
- super(tabFolder);
- _mbean = mbean;
- _ApiVersion = ApplicationRegistry.getServerRegistry(mbean).getManagementApiVersion();
- _emb = (ManagedExchange) MBeanServerInvocationHandler.newProxyInstance(mbsc,
- mbean.getObjectName(), ManagedExchange.class, false);
- _toolkit = new FormToolkit(_tabFolder.getDisplay());
- _form = _toolkit.createScrolledForm(_tabFolder);
- _form.getBody().setLayout(new GridLayout());
- createComposites();
- createWidgets();
- }
-
- private void createComposites()
- {
- _paramsComposite = _toolkit.createComposite(_form.getBody(), SWT.NONE);
- _paramsComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
- _paramsComposite.setLayout(new GridLayout());
- }
-
- /**
- * @see TabControl#getControl()
- */
- public Control getControl()
- {
- return _form;
- }
-
- /**
- * @see TabControl#setFocus()
- */
- public void setFocus()
- {
- _keysTable.setFocus();
- }
-
- @Override
- public void refresh(ManagedBean mbean)
- {
- _bindings = null;
- try
- {
- //gather a list of all keys and queues for display and selection
- _bindings = (TabularDataSupport) _emb.bindings();
- }
- catch (Exception e)
- {
- MBeanUtility.handleException(_mbean,e);
- }
-
- _keysTableViewer.setInput(_bindings);
-
- //if we have a Qpid JMX API 1.3+ server
- if(_ApiVersion.greaterThanOrEqualTo(1, 3))
- {
- //if it is a fanout exchange
- if(isFanoutExchange())
- {
- //if there are any queue bindings, there is a single wildcard binding key
- //auto-select it to show all the queues bound to the exchange
- if (_keysTable.getItemCount() == 1)
- {
- _keysTable.setSelection(0);
- updateQueuesTable();
- }
- }
- }
-
- layout();
- }
-
- public void layout()
- {
- _form.layout(true);
- _form.getBody().layout(true, true);
- }
-
- private void createWidgets()
- {
- Group bindingsGroup = new Group(_paramsComposite, SWT.SHADOW_NONE);
- bindingsGroup.setBackground(_paramsComposite.getBackground());
- bindingsGroup.setText("Bindings");
- bindingsGroup.setLayout(new GridLayout(2,false));
- GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
- bindingsGroup.setLayoutData(gridData);
-
- Composite tablesComposite = _toolkit.createComposite(bindingsGroup);
- gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
- gridData.minimumHeight = 250;
- gridData.heightHint = 250;
- tablesComposite.setLayoutData(gridData);
- tablesComposite.setLayout(new GridLayout(2,false));
-
- _keysTable = new Table (tablesComposite, SWT.SINGLE | SWT.SCROLL_LINE | SWT.BORDER | SWT.FULL_SELECTION);
- _keysTable.setLinesVisible(true);
- _keysTable.setHeaderVisible(true);
- GridData data = new GridData(SWT.FILL, SWT.FILL, true, true);
- _keysTable.setLayoutData(data);
-
- _keysTableViewer = new TableViewer(_keysTable);
- final TableSorter tableSorter = new TableSorter(BINDING_KEY);
-
- String[] titles = {"Binding Key"};
- int[] bounds = {200};
- for (int i = 0; i < titles.length; i++)
- {
- final int index = i;
- final TableColumn column = new TableColumn (_keysTable, SWT.NONE);
-
- column.setText(titles[i]);
- column.setWidth(bounds[i]);
- column.setResizable(true);
-
- //Setting the right sorter
- column.addSelectionListener(new SelectionAdapter()
- {
- @Override
- public void widgetSelected(SelectionEvent e)
- {
- tableSorter.setColumn(index);
- final TableViewer viewer = _keysTableViewer;
- int dir = viewer .getTable().getSortDirection();
- if (viewer.getTable().getSortColumn() == column)
- {
- dir = dir == SWT.UP ? SWT.DOWN : SWT.UP;
- }
- else
- {
- dir = SWT.UP;
- }
- viewer.getTable().setSortDirection(dir);
- viewer.getTable().setSortColumn(column);
- viewer.refresh();
- }
- });
-
- }
-
- _keysTableViewer.setContentProvider(new ContentProviderImpl(BINDING_KEY));
- _keysTableViewer.setLabelProvider(new LabelProviderImpl(BINDING_KEY));
- _keysTableViewer.setSorter(tableSorter);
- _keysTable.setSortColumn(_keysTable.getColumn(0));
- _keysTable.setSortDirection(SWT.UP);
-
-
- _queuesTable = new Table (tablesComposite, SWT.SINGLE | SWT.SCROLL_LINE | SWT.BORDER | SWT.FULL_SELECTION);
- _queuesTable.setLinesVisible (true);
- _queuesTable.setHeaderVisible (true);
- data = new GridData(SWT.FILL, SWT.FILL, true, true);
- _queuesTable.setLayoutData(data);
-
- _queuesTableViewer = new TableViewer(_queuesTable);
- final TableSorter queuesTableSorter = new TableSorter(QUEUE_NAMES);
-
- titles = new String[]{"Queue Names"};
- bounds = new int[]{225};
- for (int i = 0; i < titles.length; i++)
- {
- final int index = i;
- final TableColumn column = new TableColumn (_queuesTable, SWT.NONE);
-
- column.setText(titles[i]);
- column.setWidth(bounds[i]);
- column.setResizable(true);
-
- //Setting the right sorter
- column.addSelectionListener(new SelectionAdapter()
- {
- @Override
- public void widgetSelected(SelectionEvent e)
- {
- queuesTableSorter.setColumn(index);
- final TableViewer viewer = _queuesTableViewer;
- int dir = viewer .getTable().getSortDirection();
- if (viewer.getTable().getSortColumn() == column)
- {
- dir = dir == SWT.UP ? SWT.DOWN : SWT.UP;
- }
- else
- {
- dir = SWT.UP;
- }
- viewer.getTable().setSortDirection(dir);
- viewer.getTable().setSortColumn(column);
- viewer.refresh();
- }
- });
-
- }
-
- _queuesTableViewer.setContentProvider(new ContentProviderImpl(QUEUE_NAMES));
- _queuesTableViewer.setLabelProvider(new LabelProviderImpl(QUEUE_NAMES));
- _queuesTableViewer.setSorter(queuesTableSorter);
- _queuesTable.setSortColumn(_queuesTable.getColumn(0));
- _queuesTable.setSortDirection(SWT.UP);
- _queuesTableViewer.setInput(new String[]{"Select a binding key to view queues"});
-
- //listener for double clicking to open the selection mbean
- _queuesTable.addMouseListener(new MouseListener()
- {
- // MouseListener implementation
- public void mouseDoubleClick(MouseEvent event)
- {
- openMBean(_queuesTable);
- }
-
- public void mouseDown(MouseEvent e){}
- public void mouseUp(MouseEvent e){}
- });
-
- _keysTableViewer.addSelectionChangedListener(new ISelectionChangedListener(){
- public void selectionChanged(SelectionChangedEvent evt)
- {
- updateQueuesTable();
- }
- });
-
- //Side Buttons
- Composite buttonsComposite = _toolkit.createComposite(bindingsGroup);
- gridData = new GridData(SWT.FILL, SWT.FILL, false, true);
- buttonsComposite.setLayoutData(gridData);
- buttonsComposite.setLayout(new GridLayout());
-
- final Button createBindingButton = _toolkit.createButton(buttonsComposite, "Create ...", SWT.PUSH);
- createBindingButton.addSelectionListener(new SelectionAdapter()
- {
- public void widgetSelected(SelectionEvent e)
- {
- createNewBinding(createBindingButton.getShell());
- }
- });
-
- if(_ApiVersion.greaterThanOrEqualTo(1, 9)
- && (isDirectExchange() ||isTopicExchange()))
- {
- final Button removeBindingButton = _toolkit.createButton(buttonsComposite, "Delete ...", SWT.PUSH);
- removeBindingButton.setEnabled(false);
- removeBindingButton.addSelectionListener(new SelectionAdapter()
- {
- public void widgetSelected(SelectionEvent e)
- {
- removeBinding(removeBindingButton.getShell());
- }
- });
-
- _queuesTableViewer.addSelectionChangedListener(new ISelectionChangedListener(){
- public void selectionChanged(SelectionChangedEvent evt)
- {
- int selectionIndex = _queuesTable.getSelectionIndex();
-
- if (selectionIndex != -1)
- {
- removeBindingButton.setEnabled(true);
- }
- else
- {
- removeBindingButton.setEnabled(false);
- }
- }
- });
- }
- }
-
- private void updateQueuesTable()
- {
- int selectionIndex = _keysTable.getSelectionIndex();
-
- if (selectionIndex != -1)
- {
- final CompositeData selectedMsg = (CompositeData)_keysTable.getItem(selectionIndex).getData();
-
- String[] queues = (String[]) selectedMsg.get(QUEUE_NAMES);
- _queuesTableViewer.setInput(queues);
- }
- else
- {
- _queuesTableViewer.setInput(new String[]{"Select a binding key to view queues"});
- }
- }
-
- private boolean isFanoutExchange()
- {
- return _mbean.getProperty(EXCHANGE_TYPE).equalsIgnoreCase(FANOUT_EXCHANGE);
- }
-
- private boolean isDirectExchange()
- {
- return _mbean.getProperty(EXCHANGE_TYPE).equalsIgnoreCase(DIRECT_EXCHANGE);
- }
-
- private boolean isTopicExchange()
- {
- return _mbean.getProperty(EXCHANGE_TYPE).equalsIgnoreCase(TOPIC_EXCHANGE);
- }
-
- /**
- * Content Provider class for the table viewer
- */
- private static class ContentProviderImpl implements IStructuredContentProvider
- {
- private String type;
-
- public ContentProviderImpl(String type)
- {
- this.type = type;
- }
-
- public void inputChanged(Viewer v, Object oldInput, Object newInput)
- {
-
- }
-
- public void dispose()
- {
-
- }
-
- public Object[] getElements(Object parent)
- {
- if(type.equals(BINDING_KEY))
- {
- Collection<Object> rowCollection = ((TabularDataSupport) parent).values();
-
- return rowCollection.toArray();
- }
- else
- {
- //we have the list of queues, return directly
- return (String[]) parent;
- }
- }
- }
-
- /**
- * Label Provider class for the routing key table viewer
- */
- private static class LabelProviderImpl extends LabelProvider implements ITableLabelProvider
- {
- private String type;
-
- public LabelProviderImpl(String type)
- {
- this.type = type;
- }
-
- public String getColumnText(Object element, int columnIndex)
- {
- if(type.equals(BINDING_KEY)) //binding num and queue name table
- {
- switch (columnIndex)
- {
- case 0 : // key column
- return String.valueOf(((CompositeDataSupport) element).get(BINDING_KEY));
- default :
- return "";
- }
- }
- else //binding key-value pair table
- {
- switch (columnIndex)
- {
- case 0 : //queue name column
- return String.valueOf(element);
- default :
- return "";
- }
- }
- }
-
- public Image getColumnImage(Object element, int columnIndex)
- {
- return null;
- }
- }
-
- /**
- * Sorter class for the table viewer.
- *
- */
- public static class TableSorter extends ViewerSorter
- {
- private int column;
- private static final int ASCENDING = 0;
- private static final int DESCENDING = 1;
-
- private int direction = DESCENDING;
-
- private String type;
-
- public TableSorter(String type)
- {
- this.type = type;
- this.column = 0;
- direction = ASCENDING;
- }
-
- public void setColumn(int column)
- {
- if (column == this.column)
- {
- // Same column as last sort; toggle the direction
- direction = 1 - direction;
- }
- else
- {
- // New column; do an ascending sort
- this.column = column;
- direction = ASCENDING;
- }
- }
-
- @Override
- public int compare(Viewer viewer, Object e1, Object e2)
- {
- int comparison = 0;
-
- if(type.equals(BINDING_KEY))//binding num and queue name table
- {
- CompositeData binding1 = (CompositeData) e1;
- CompositeData binding2 = (CompositeData) e2;
-
- switch(column)
- {
- case 0:
- comparison = ((String) binding1.get(BINDING_KEY)).compareTo((String) binding2.get(BINDING_KEY));
- break;
- default:
- comparison = 0;
- }
- }
- else //binding key-value pair table
- {
- switch(column)
- {
- case 0:
- comparison = ((String)e1).compareTo((String) e2);
- break;
- default:
- comparison = 0;
- }
- }
-
-
- // If descending order, flip the direction
- if(direction == DESCENDING)
- {
- comparison = -comparison;
- }
- return comparison;
- }
- }
-
- private void createNewBinding(Shell parent)
- {
- final Shell shell = ViewUtility.createModalDialogShell(parent, "Create New Binding");
-
- Composite destinationComposite = _toolkit.createComposite(shell, SWT.NONE);
- destinationComposite.setBackground(shell.getBackground());
- destinationComposite.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
- destinationComposite.setLayout(new GridLayout(2,false));
-
- _toolkit.createLabel(destinationComposite,"Queue:").setBackground(shell.getBackground());
- final Combo destinationCombo = new Combo(destinationComposite,SWT.NONE | SWT.READ_ONLY);
- destinationCombo.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
-
- Composite bindingComposite = _toolkit.createComposite(shell, SWT.NONE);
- bindingComposite.setBackground(shell.getBackground());
- bindingComposite.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
- bindingComposite.setLayout(new GridLayout(2,false));
-
- _toolkit.createLabel(bindingComposite,"Binding:").setBackground(shell.getBackground());
- final Text bindingText = new Text(bindingComposite, SWT.BORDER);
- bindingText.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
- if(isFanoutExchange())
- {
- bindingText.setText("*");
- }
-
- Composite okCancelButtonsComp = _toolkit.createComposite(shell);
- okCancelButtonsComp.setBackground(shell.getBackground());
- okCancelButtonsComp.setLayoutData(new GridData(SWT.RIGHT, SWT.FILL, true, true));
- okCancelButtonsComp.setLayout(new GridLayout(2,false));
-
- Button okButton = _toolkit.createButton(okCancelButtonsComp, "OK", SWT.PUSH);
- okButton.setLayoutData(new GridData(SWT.RIGHT, SWT.TOP, false, false));
- Button cancelButton = _toolkit.createButton(okCancelButtonsComp, "Cancel", SWT.PUSH);
- cancelButton.setLayoutData(new GridData(SWT.RIGHT, SWT.TOP, false, false));
-
- List<String> queueList = ApplicationRegistry.getServerRegistry(_mbean).getQueueNames(_mbean.getVirtualHostName());
-
- if(queueList.size() == 0)
- {
- destinationCombo.setItems(new String[]{"No queues available"});
- okButton.setEnabled(false);
- }
- else
- {
- Collections.sort(queueList);
- destinationCombo.setItems(queueList.toArray(new String[0]));
- }
- destinationCombo.select(0);
-
- okButton.addSelectionListener(new SelectionAdapter()
- {
- public void widgetSelected(SelectionEvent e)
- {
- String binding = bindingText.getText();
-
- if (!isFanoutExchange() && (binding == null || binding.length() == 0))
- {
- ViewUtility.popupErrorMessage("Create New Binding", "Please enter a valid binding");
- return;
- }
-
- String destQueue = destinationCombo.getItem(destinationCombo.getSelectionIndex()).toString();
-
- shell.dispose();
-
- try
- {
- _emb.createNewBinding(destQueue, binding);
- ViewUtility.operationResultFeedback(null, "Created new Binding", null);
- }
- catch (Exception e4)
- {
- ViewUtility.operationFailedStatusBarMessage("Error creating new Binding");
- MBeanUtility.handleException(_mbean, e4);
- }
-
- refresh(_mbean);
- }
- });
-
- cancelButton.addSelectionListener(new SelectionAdapter()
- {
- public void widgetSelected(SelectionEvent e)
- {
- shell.dispose();
- }
- });
-
- shell.setDefaultButton(okButton);
- shell.pack();
- ViewUtility.centerChildInParentShell(parent, shell);
-
- shell.open();
- }
-
- private void removeBinding(Shell parent)
- {
- int selectionIndex = _keysTable.getSelectionIndex();
- if (selectionIndex == -1)
- {
- return;
- }
-
- final CompositeData selectedBindingRecord = (CompositeData)_keysTable.getItem(selectionIndex).getData();
-
- final String bindingKey = (String) selectedBindingRecord.get(BINDING_KEY);
-
- selectionIndex = _queuesTable.getSelectionIndex();
- if (selectionIndex == -1)
- {
- return;
- }
-
- final String queueName = (String)_queuesTable.getItem(selectionIndex).getData();
-
-
- int response = ViewUtility.popupOkCancelConfirmationMessage("Delete Binding",
- "Delete the following binding?\n\n" +
- "Binding Key: " + bindingKey + "\n" +
- "Queue: " + queueName + "\n" +
- "Exchange: " + _mbean.getName());
-
- if (response == SWT.OK)
- {
- try
- {
- _emb.removeBinding(queueName, bindingKey);
- ViewUtility.operationResultFeedback(null, "Removed Binding", null);
- }
- catch (Exception e)
- {
- ViewUtility.operationFailedStatusBarMessage("Error removing Binding");
- MBeanUtility.handleException(_mbean, e);
- }
-
- refresh(_mbean);
- }
- }
-
- private void openMBean(Table table)
- {
- int selectionIndex = table.getSelectionIndex();
-
- if (selectionIndex == -1)
- {
- return;
- }
-
- String queueName = (String) table.getItem(selectionIndex).getData();
- ServerRegistry serverRegistry = ApplicationRegistry.getServerRegistry(_mbean);
- ManagedBean selectedMBean = serverRegistry.getQueue(queueName, _mbean.getVirtualHostName());
-
- if(selectedMBean == null)
- {
- ViewUtility.popupErrorMessage("Error", "Unable to retrieve the selected MBean to open it");
- return;
- }
-
- IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
- MBeanView view = (MBeanView) window.getActivePage().findView(MBeanView.ID);
- try
- {
- view.openMBean(selectedMBean);
- }
- catch (Exception ex)
- {
- MBeanUtility.handleException(selectedMBean, ex);
- }
- }
-}
diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/exchange/HeadersExchangeOperationsTabControl.java b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/exchange/HeadersExchangeOperationsTabControl.java
deleted file mode 100644
index 6b8b744c43..0000000000
--- a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/exchange/HeadersExchangeOperationsTabControl.java
+++ /dev/null
@@ -1,711 +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.exchange;
-
-import org.eclipse.jface.viewers.ISelectionChangedListener;
-import org.eclipse.jface.viewers.IStructuredContentProvider;
-import org.eclipse.jface.viewers.ITableLabelProvider;
-import org.eclipse.jface.viewers.LabelProvider;
-import org.eclipse.jface.viewers.SelectionChangedEvent;
-import org.eclipse.jface.viewers.TableViewer;
-import org.eclipse.jface.viewers.Viewer;
-import org.eclipse.jface.viewers.ViewerSorter;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.custom.ScrolledComposite;
-import org.eclipse.swt.events.MouseEvent;
-import org.eclipse.swt.events.MouseListener;
-import org.eclipse.swt.events.SelectionAdapter;
-import org.eclipse.swt.events.SelectionEvent;
-import org.eclipse.swt.graphics.Image;
-import org.eclipse.swt.layout.GridData;
-import org.eclipse.swt.layout.GridLayout;
-import org.eclipse.swt.widgets.Button;
-import org.eclipse.swt.widgets.Combo;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Control;
-import org.eclipse.swt.widgets.Group;
-import org.eclipse.swt.widgets.Label;
-import org.eclipse.swt.widgets.Shell;
-import org.eclipse.swt.widgets.TabFolder;
-import org.eclipse.swt.widgets.Table;
-import org.eclipse.swt.widgets.TableColumn;
-import org.eclipse.swt.widgets.Text;
-import org.eclipse.ui.IWorkbenchWindow;
-import org.eclipse.ui.PlatformUI;
-import org.eclipse.ui.forms.widgets.FormToolkit;
-import org.eclipse.ui.forms.widgets.ScrolledForm;
-
-import org.apache.qpid.management.common.mbeans.ManagedExchange;
-import org.apache.qpid.management.ui.ApplicationRegistry;
-import org.apache.qpid.management.ui.ManagedBean;
-import org.apache.qpid.management.ui.ServerRegistry;
-import org.apache.qpid.management.ui.jmx.JMXManagedObject;
-import org.apache.qpid.management.ui.jmx.MBeanUtility;
-import org.apache.qpid.management.ui.views.MBeanView;
-import org.apache.qpid.management.ui.views.TabControl;
-import org.apache.qpid.management.ui.views.ViewUtility;
-
-import static org.apache.qpid.management.common.mbeans.ManagedExchange.HDR_BINDING_NUMBER;
-import static org.apache.qpid.management.common.mbeans.ManagedExchange.HDR_QUEUE_BINDINGS;
-import static org.apache.qpid.management.common.mbeans.ManagedExchange.HDR_QUEUE_NAME;
-
-import javax.management.MBeanServerConnection;
-import javax.management.MBeanServerInvocationHandler;
-import javax.management.openmbean.CompositeData;
-import javax.management.openmbean.CompositeDataSupport;
-import javax.management.openmbean.TabularDataSupport;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-
-
-/**
- * Control class for the Headers Exchange mbean Operations tab.
- */
-public class HeadersExchangeOperationsTabControl extends TabControl
-{
- private FormToolkit _toolkit;
- private ScrolledForm _form;
- private Table _bindingNumberTable = null;
- private TableViewer _bindingNumberTableViewer = null;
- private Table _headersTable = null;
- private TableViewer _headersTableViewer = null;
- private Composite _paramsComposite = null;
-
- private TabularDataSupport _bindings = null;
- private ManagedExchange _emb;
-
- public HeadersExchangeOperationsTabControl(TabFolder tabFolder, JMXManagedObject mbean, MBeanServerConnection mbsc)
- {
- super(tabFolder);
- _mbean = mbean;
- _emb = (ManagedExchange) MBeanServerInvocationHandler.newProxyInstance(mbsc,
- mbean.getObjectName(), ManagedExchange.class, false);
- _toolkit = new FormToolkit(_tabFolder.getDisplay());
- _form = _toolkit.createScrolledForm(_tabFolder);
- _form.getBody().setLayout(new GridLayout());
- createComposites();
- createWidgets();
- }
-
- private void createComposites()
- {
- _paramsComposite = _toolkit.createComposite(_form.getBody(), SWT.NONE);
- _paramsComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
- _paramsComposite.setLayout(new GridLayout());
- }
-
- /**
- * @see TabControl#getControl()
- */
- public Control getControl()
- {
- return _form;
- }
-
- /**
- * @see TabControl#setFocus()
- */
- public void setFocus()
- {
- _bindingNumberTable.setFocus();
- }
-
- @Override
- public void refresh(ManagedBean mbean)
- {
-
- _bindings = null;
- try
- {
- //gather a list of all keys and queues for display and selection
- _bindings = (TabularDataSupport) _emb.bindings();
- }
- catch (Exception e)
- {
- MBeanUtility.handleException(_mbean,e);
- }
-
- _bindingNumberTableViewer.setInput(_bindings);
-
- layout();
- }
-
- public void layout()
- {
- _form.layout(true);
- _form.getBody().layout(true, true);
- }
-
- private void createWidgets()
- {
- Group bindingsGroup = new Group(_paramsComposite, SWT.SHADOW_NONE);
- bindingsGroup.setBackground(_paramsComposite.getBackground());
- bindingsGroup.setText("Bindings");
- bindingsGroup.setLayout(new GridLayout(2,false));
- GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
- bindingsGroup.setLayoutData(gridData);
-
- Composite tablesComposite = _toolkit.createComposite(bindingsGroup);
- gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
- gridData.minimumHeight = 250;
- gridData.heightHint = 250;
- tablesComposite.setLayoutData(gridData);
- tablesComposite.setLayout(new GridLayout(2,false));
-
- //table of bindings for the exchange
- _bindingNumberTable = new Table (tablesComposite, SWT.SINGLE | SWT.SCROLL_LINE | SWT.BORDER | SWT.FULL_SELECTION);
- _bindingNumberTable.setLinesVisible(true);
- _bindingNumberTable.setHeaderVisible(true);
- GridData data = new GridData(SWT.FILL, SWT.FILL, true, true);
- data.minimumHeight = 300;
- data.heightHint = 300;
- _bindingNumberTable.setLayoutData(data);
-
- _bindingNumberTableViewer = new TableViewer(_bindingNumberTable);
- final TableSorter tableSorter = new TableSorter(HDR_BINDING_NUMBER);
-
- String[] titles = {"Binding Number", "Queue Name"};
- int[] bounds = {135, 175};
- for (int i = 0; i < titles.length; i++)
- {
- final int index = i;
- final TableColumn column = new TableColumn (_bindingNumberTable, SWT.NONE);
-
- column.setText(titles[i]);
- column.setWidth(bounds[i]);
- column.setResizable(true);
-
- //Setting the right sorter
- column.addSelectionListener(new SelectionAdapter()
- {
- @Override
- public void widgetSelected(SelectionEvent e)
- {
- tableSorter.setColumn(index);
- final TableViewer viewer = _bindingNumberTableViewer;
- int dir = viewer .getTable().getSortDirection();
- if (viewer.getTable().getSortColumn() == column)
- {
- dir = dir == SWT.UP ? SWT.DOWN : SWT.UP;
- }
- else
- {
- dir = SWT.UP;
- }
- viewer.getTable().setSortDirection(dir);
- viewer.getTable().setSortColumn(column);
- viewer.refresh();
- }
- });
-
- }
-
- _bindingNumberTableViewer.setContentProvider(new ContentProviderImpl(HDR_BINDING_NUMBER));
- _bindingNumberTableViewer.setLabelProvider(new LabelProviderImpl(HDR_BINDING_NUMBER));
- _bindingNumberTableViewer.setSorter(tableSorter);
- _bindingNumberTable.setSortColumn(_bindingNumberTable.getColumn(0));
- _bindingNumberTable.setSortDirection(SWT.UP);
-
- //table of header bindings
- _headersTable = new Table (tablesComposite, SWT.SINGLE | SWT.SCROLL_LINE | SWT.BORDER | SWT.FULL_SELECTION);
- _headersTable.setLinesVisible (true);
- _headersTable.setHeaderVisible (true);
- data = new GridData(SWT.FILL, SWT.FILL, true, true);
- data.minimumHeight = 300;
- data.heightHint = 300;
- _headersTable.setLayoutData(data);
-
- _headersTableViewer = new TableViewer(_headersTable);
- final TableSorter queuesTableSorter = new TableSorter(HDR_QUEUE_BINDINGS);
-
- titles = new String[]{"Header Bindings"};
- bounds = new int[]{225};
- for (int i = 0; i < titles.length; i++)
- {
- final int index = i;
- final TableColumn column = new TableColumn (_headersTable, SWT.NONE);
-
- column.setText(titles[i]);
- column.setWidth(bounds[i]);
- column.setResizable(true);
-
- //Setting the right sorter
- column.addSelectionListener(new SelectionAdapter()
- {
- @Override
- public void widgetSelected(SelectionEvent e)
- {
- queuesTableSorter.setColumn(index);
- final TableViewer viewer = _headersTableViewer;
- int dir = viewer .getTable().getSortDirection();
- if (viewer.getTable().getSortColumn() == column)
- {
- dir = dir == SWT.UP ? SWT.DOWN : SWT.UP;
- }
- else
- {
- dir = SWT.UP;
- }
- viewer.getTable().setSortDirection(dir);
- viewer.getTable().setSortColumn(column);
- viewer.refresh();
- }
- });
-
- }
-
- _headersTableViewer.setContentProvider(new ContentProviderImpl(HDR_QUEUE_BINDINGS));
- _headersTableViewer.setLabelProvider(new LabelProviderImpl(HDR_QUEUE_BINDINGS));
- _headersTableViewer.setSorter(queuesTableSorter);
- _headersTable.setSortColumn(_headersTable.getColumn(0));
- _headersTable.setSortDirection(SWT.UP);
- _headersTableViewer.setInput(new String[]{"Select a binding to view key-value pairs"});
-
- _bindingNumberTableViewer.addSelectionChangedListener(new ISelectionChangedListener(){
- public void selectionChanged(SelectionChangedEvent evt)
- {
- int selectionIndex = _bindingNumberTable.getSelectionIndex();
-
- if (selectionIndex != -1)
- {
- final CompositeData selectedMsg = (CompositeData)_bindingNumberTable.getItem(selectionIndex).getData();
-
- String[] bindings = (String[]) selectedMsg.get(HDR_QUEUE_BINDINGS);
- _headersTableViewer.setInput(bindings);
- }
- else
- {
- _headersTableViewer.setInput(new String[]{"Select a binding to view key-value pairs"});
- }
- }
- });
-
- //listener for double clicking to open the selection mbean
- _bindingNumberTable.addMouseListener(new MouseListener()
- {
- // MouseListener implementation
- public void mouseDoubleClick(MouseEvent event)
- {
- openMBean(_bindingNumberTable);
- }
-
- public void mouseDown(MouseEvent e){}
- public void mouseUp(MouseEvent e){}
- });
-
- //Side Buttons
- Composite buttonsComposite = _toolkit.createComposite(bindingsGroup);
- gridData = new GridData(SWT.FILL, SWT.FILL, false, true);
- buttonsComposite.setLayoutData(gridData);
- buttonsComposite.setLayout(new GridLayout());
-
- final Button createBindingButton = _toolkit.createButton(buttonsComposite, "Create ...", SWT.PUSH);
- createBindingButton.addSelectionListener(new SelectionAdapter()
- {
- public void widgetSelected(SelectionEvent e)
- {
- createNewBinding(createBindingButton.getShell());
- }
- });
-
- }
-
-
- /**
- * Content Provider class for the table viewer
- */
- private static class ContentProviderImpl implements IStructuredContentProvider
- {
- private String type;
-
- public ContentProviderImpl(String type)
- {
- this.type = type;
- }
-
- public void inputChanged(Viewer v, Object oldInput, Object newInput)
- {
-
- }
-
- public void dispose()
- {
-
- }
-
- public Object[] getElements(Object parent)
- {
- if(type.equals(HDR_BINDING_NUMBER))
- {
- Collection<Object> rowCollection = ((TabularDataSupport) parent).values();
-
- return rowCollection.toArray();
- }
- else
- {
- //we have the list of bindings, return directly
- return (String[]) parent;
- }
- }
- }
-
- /**
- * Label Provider class for the routing key table viewer
- */
- private static class LabelProviderImpl extends LabelProvider implements ITableLabelProvider
- {
- private String type;
-
- public LabelProviderImpl(String type)
- {
- this.type = type;
- }
-
- public String getColumnText(Object element, int columnIndex)
- {
- if(type.equals(HDR_BINDING_NUMBER)) //binding num and queue name table
- {
- switch (columnIndex)
- {
- case 0 : // binding number column
- return String.valueOf(((CompositeDataSupport) element).get(HDR_BINDING_NUMBER));
- case 1 : // queue name column
- return (String) ((CompositeDataSupport) element).get(HDR_QUEUE_NAME);
- default :
- return "";
- }
- }
- else //binding key-value pair table
- {
- switch (columnIndex)
- {
- case 0 : //header binding column
- return String.valueOf(element);
- default :
- return "";
- }
- }
- }
-
- public Image getColumnImage(Object element, int columnIndex)
- {
- return null;
- }
- }
-
- /**
- * Sorter class for the table viewer.
- *
- */
- public static class TableSorter extends ViewerSorter
- {
- private int column;
- private static final int ASCENDING = 0;
- private static final int DESCENDING = 1;
-
- private int direction = DESCENDING;
-
- private String type;
-
- public TableSorter(String type)
- {
- this.type = type;
- this.column = 0;
- direction = ASCENDING;
- }
-
- public void setColumn(int column)
- {
- if (column == this.column)
- {
- // Same column as last sort; toggle the direction
- direction = 1 - direction;
- }
- else
- {
- // New column; do an ascending sort
- this.column = column;
- direction = ASCENDING;
- }
- }
-
- @Override
- public int compare(Viewer viewer, Object e1, Object e2)
- {
- int comparison = 0;
-
- if(type.equals(HDR_BINDING_NUMBER)) //binding num and queue name table
- {
- CompositeData binding1 = (CompositeData) e1;
- CompositeData binding2 = (CompositeData) e2;
-
- switch(column)
- {
- case 0: // binding number column
- comparison = ((Integer) binding1.get(HDR_BINDING_NUMBER)).compareTo((Integer) binding2.get(HDR_BINDING_NUMBER));
- break;
- case 1: // queue name column
- comparison = ((String) binding1.get(HDR_QUEUE_NAME)).compareTo((String) binding2.get(HDR_QUEUE_NAME));
- break;
- default:
- comparison = 0;
- }
- }
- else //binding key-value pair table
- {
- switch(column)
- {
- case 0: //header binding column
- comparison = ((String)e1).compareTo((String) e2);
- break;
- default:
- comparison = 0;
- }
- }
-
- // If descending order, flip the direction
- if(direction == DESCENDING)
- {
- comparison = -comparison;
- }
- return comparison;
- }
- }
-
- private void createNewBinding(Shell parent)
- {
- final Shell shell = ViewUtility.createModalDialogShell(parent, "Create New Binding");
-
- Composite queueNameComposite = _toolkit.createComposite(shell, SWT.NONE);
- queueNameComposite.setBackground(shell.getBackground());
- GridData layoutData = new GridData(SWT.CENTER, SWT.TOP, true, false);
- layoutData.minimumWidth = 300;
- queueNameComposite.setLayoutData(layoutData);
- queueNameComposite.setLayout(new GridLayout(2,false));
-
- _toolkit.createLabel(queueNameComposite,"Queue:").setBackground(shell.getBackground());
- final Combo destinationCombo = new Combo(queueNameComposite,SWT.NONE | SWT.READ_ONLY);
- destinationCombo.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
-
- final ScrolledComposite scrolledComposite = new ScrolledComposite(shell, SWT.V_SCROLL);
- scrolledComposite.setExpandHorizontal(true);
- scrolledComposite.setLayout(new GridLayout());
- scrolledComposite.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
- scrolledComposite.setBackground(shell.getBackground());
-
- final Composite bindingComposite = _toolkit.createComposite(scrolledComposite, SWT.NONE);
- bindingComposite.setBackground(scrolledComposite.getBackground());
- bindingComposite.setLayout(new GridLayout(2,true));
- layoutData = new GridData(SWT.FILL, SWT.TOP, true, false);
- bindingComposite.setLayoutData(layoutData);
- scrolledComposite.setContent(bindingComposite);
-
- Composite addMoreButtonComp = _toolkit.createComposite(shell);
- addMoreButtonComp.setBackground(shell.getBackground());
- addMoreButtonComp.setLayoutData(new GridData(SWT.RIGHT, SWT.FILL, true, true));
- addMoreButtonComp.setLayout(new GridLayout());
-
- final Button addMoreButton = _toolkit.createButton(addMoreButtonComp, "Add additional field", SWT.PUSH);
-
- Composite okCancelButtonsComp = _toolkit.createComposite(shell);
- okCancelButtonsComp.setBackground(shell.getBackground());
- okCancelButtonsComp.setLayoutData(new GridData(SWT.RIGHT, SWT.FILL, true, true));
- okCancelButtonsComp.setLayout(new GridLayout(2,false));
-
- Button okButton = _toolkit.createButton(okCancelButtonsComp, "OK", SWT.PUSH);
- okButton.setLayoutData(new GridData(SWT.RIGHT, SWT.TOP, false, false));
- Button cancelButton = _toolkit.createButton(okCancelButtonsComp, "Cancel", SWT.PUSH);
- cancelButton.setLayoutData(new GridData(SWT.RIGHT, SWT.TOP, false, false));
-
- List<String> queueList = ApplicationRegistry.getServerRegistry(_mbean).getQueueNames(_mbean.getVirtualHostName());
-
- if(queueList.size() == 0)
- {
- destinationCombo.setItems(new String[]{"No queues available"});
- okButton.setEnabled(false);
- }
- else
- {
- Collections.sort(queueList);
- destinationCombo.setItems(queueList.toArray(new String[0]));
- }
- destinationCombo.select(0);
-
- final HashMap<Text, Text> headerBindingHashMap = new HashMap<Text, Text>();
-
- //add headings
- Label keyLabel = _toolkit.createLabel(bindingComposite,"Key:");
- keyLabel.setBackground(bindingComposite.getBackground());
- keyLabel.setLayoutData(new GridData(SWT.CENTER, SWT.TOP, true, false));
-
- Label valueLabel = _toolkit.createLabel(bindingComposite,"Value:");
- valueLabel.setBackground(bindingComposite.getBackground());
- valueLabel.setLayoutData(new GridData(SWT.CENTER, SWT.TOP, true, false));
-
- //add the x-match key by default and offer a comobo to select its value
- final Text xmatchKeyText = new Text(bindingComposite, SWT.BORDER);
- xmatchKeyText.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
- xmatchKeyText.setText("x-match");
- xmatchKeyText.setEditable(false);
-
- final Combo xmatchValueCombo = new Combo(bindingComposite,SWT.NONE | SWT.READ_ONLY);
- xmatchValueCombo.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
- xmatchValueCombo.setItems(new String[]{"any", "all"});
- xmatchValueCombo.select(0);
-
- //make some empty key-value fields
- for(int i=0; i < 4; i++)
- {
- Text keyText = new Text(bindingComposite, SWT.BORDER);
- Text valueText = new Text(bindingComposite, SWT.BORDER);
- keyText.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
- valueText.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
-
- headerBindingHashMap.put(keyText, valueText);
- }
- bindingComposite.setSize(bindingComposite.computeSize(SWT.DEFAULT, SWT.DEFAULT));
-
- //allow adding more fields for additional key-value pairs
- addMoreButton.addSelectionListener(new SelectionAdapter()
- {
- public void widgetSelected(SelectionEvent e)
- {
- Text keyText = new Text(bindingComposite, SWT.BORDER);
- Text valueText = new Text(bindingComposite, SWT.BORDER);
- keyText.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
- valueText.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
-
- headerBindingHashMap.put(keyText, valueText);
-
- bindingComposite.setSize(bindingComposite.computeSize(SWT.DEFAULT, SWT.DEFAULT));
- bindingComposite.layout(true);
- scrolledComposite.layout(true);
- }
- });
-
- okButton.addSelectionListener(new SelectionAdapter()
- {
- public void widgetSelected(SelectionEvent e)
- {
- String xMatchString = xmatchValueCombo.getText();
-
- String destQueue = destinationCombo.getItem(destinationCombo.getSelectionIndex()).toString();
-
- StringBuffer bindingValue = new StringBuffer();
-
- //insert the x-match key-value pair
- if (xMatchString.equalsIgnoreCase("any"))
- {
- bindingValue.append("x-match=any");
- }
- else
- {
- bindingValue.append("x-match=all");
- }
-
- //insert the other key-value pairs
- for (Text keyText : headerBindingHashMap.keySet())
- {
-
- String key = keyText.getText();
- if(key == null || key.length() == 0)
- {
- continue;
- }
-
- Text valueText = headerBindingHashMap.get(keyText);
- String value = valueText.getText();
-
- bindingValue.append(",");
- bindingValue.append(key + "=");
- //empty values are permitted, signalling only key-presence is required
- if(value != null && value.length() > 0)
- {
- bindingValue.append(value);
- }
- }
-
- shell.dispose();
-
- try
- {
- _emb.createNewBinding(destQueue, bindingValue.toString());
- ViewUtility.operationResultFeedback(null, "Created new Binding", null);
- }
- catch (Exception e4)
- {
- ViewUtility.operationFailedStatusBarMessage("Error creating new Binding");
- MBeanUtility.handleException(_mbean, e4);
- }
-
- refresh(_mbean);
- }
- });
-
- cancelButton.addSelectionListener(new SelectionAdapter()
- {
- public void widgetSelected(SelectionEvent e)
- {
- shell.dispose();
- }
- });
-
- shell.setDefaultButton(okButton);
- shell.pack();
- ViewUtility.centerChildInParentShell(parent, shell);
-
- shell.open();
- }
-
- private void openMBean(Table table)
- {
- int selectionIndex = table.getSelectionIndex();
-
- if (selectionIndex == -1)
- {
- return;
- }
-
- CompositeData bindingResult = (CompositeData) table.getItem(selectionIndex).getData();
- String queueName = (String) bindingResult.get(HDR_QUEUE_NAME);
- ServerRegistry serverRegistry = ApplicationRegistry.getServerRegistry(_mbean);
- ManagedBean selectedMBean = serverRegistry.getQueue(queueName, _mbean.getVirtualHostName());
-
- if(selectedMBean == null)
- {
- ViewUtility.popupErrorMessage("Error", "Unable to retrieve the selected MBean to open it");
- return;
- }
-
- IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
- MBeanView view = (MBeanView) window.getActivePage().findView(MBeanView.ID);
- try
- {
- view.openMBean(selectedMBean);
- }
- catch (Exception ex)
- {
- MBeanUtility.handleException(selectedMBean, ex);
- }
- }
-}
diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/logging/ConfigurationFileTabControl.java b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/logging/ConfigurationFileTabControl.java
deleted file mode 100644
index f2f32fd068..0000000000
--- a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/logging/ConfigurationFileTabControl.java
+++ /dev/null
@@ -1,590 +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.logging;
-
-import org.eclipse.jface.viewers.ISelectionChangedListener;
-import org.eclipse.jface.viewers.SelectionChangedEvent;
-import org.eclipse.jface.viewers.TableViewer;
-import org.eclipse.jface.viewers.TableViewerColumn;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.events.MouseEvent;
-import org.eclipse.swt.events.MouseListener;
-import org.eclipse.swt.events.SelectionAdapter;
-import org.eclipse.swt.events.SelectionEvent;
-import org.eclipse.swt.layout.GridData;
-import org.eclipse.swt.layout.GridLayout;
-import org.eclipse.swt.widgets.Button;
-import org.eclipse.swt.widgets.Combo;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Control;
-import org.eclipse.swt.widgets.Group;
-import org.eclipse.swt.widgets.Label;
-import org.eclipse.swt.widgets.Shell;
-import org.eclipse.swt.widgets.TabFolder;
-import org.eclipse.swt.widgets.Table;
-import org.eclipse.swt.widgets.TableColumn;
-import org.eclipse.swt.widgets.Text;
-import org.eclipse.ui.forms.widgets.FormToolkit;
-import org.eclipse.ui.forms.widgets.ScrolledForm;
-
-import org.apache.qpid.management.common.mbeans.LoggingManagement;
-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.ui.jmx.JMXManagedObject;
-import org.apache.qpid.management.ui.jmx.MBeanUtility;
-import org.apache.qpid.management.ui.views.TabControl;
-import org.apache.qpid.management.ui.views.ViewUtility;
-
-import static org.apache.qpid.management.common.mbeans.LoggingManagement.LOGGER_LEVEL;
-import static org.apache.qpid.management.common.mbeans.LoggingManagement.LOGGER_NAME;
-import static org.apache.qpid.management.ui.Constants.FONT_BOLD;
-
-import javax.management.MBeanServerConnection;
-import javax.management.MBeanServerInvocationHandler;
-import javax.management.openmbean.CompositeData;
-import javax.management.openmbean.TabularDataSupport;
-import java.util.ArrayList;
-import java.util.HashMap;
-
-
-/**
- * Control class for the LoggingManagement mbean ConfigFile Options tab.
- */
-public class ConfigurationFileTabControl extends TabControl
-{
- private FormToolkit _toolkit;
- private ScrolledForm _form;
- private Table _table = null;
- private TableViewer _tableViewer = null;
- private Composite _headerComposite = null;
- private Composite _paramsComposite = null;
-
- private Label _configFileRootLoggerLevelLabel = null;
- private Label _logWatchIntervalLabel = null;
- private String[] _availableLoggerLevels;
- private TabularDataSupport _configFileLoggerLevels = null;
- private LoggingManagement _lmmb;
- private ApiVersion _ApiVersion;
-
- public ConfigurationFileTabControl(TabFolder tabFolder, JMXManagedObject mbean, MBeanServerConnection mbsc)
- {
- super(tabFolder);
- _mbean = mbean;
- _lmmb = (LoggingManagement)
- MBeanServerInvocationHandler.newProxyInstance(mbsc, mbean.getObjectName(),
- LoggingManagement.class, false);
- _ApiVersion = ApplicationRegistry.getServerRegistry(mbean).getManagementApiVersion();
- _toolkit = new FormToolkit(_tabFolder.getDisplay());
- _form = _toolkit.createScrolledForm(_tabFolder);
- _form.getBody().setLayout(new GridLayout());
- createComposites();
- createWidgets();
- }
-
- private void createComposites()
- {
-
- _headerComposite = _toolkit.createComposite(_form.getBody(), SWT.NONE);
- _headerComposite.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
- _headerComposite.setLayout(new GridLayout());
-
- _paramsComposite = _toolkit.createComposite(_form.getBody(), SWT.NONE);
- _paramsComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
- _paramsComposite.setLayout(new GridLayout());
- }
-
- /**
- * @see TabControl#getControl()
- */
- public Control getControl()
- {
- return _form;
- }
-
- /**
- * @see TabControl#setFocus()
- */
- public void setFocus()
- {
- _table.setFocus();
- }
-
- @Override
- public void refresh(ManagedBean mbean)
- {
- String configFileRootLoggerLevel = "-";
- try
- {
- configFileRootLoggerLevel = _lmmb.getConfigFileRootLoggerLevel();
- }
- catch (Exception e1)
- {
- MBeanUtility.handleException(_mbean, e1);
- }
-
- int log4jLogWatchInterval = -1;
- try
- {
- log4jLogWatchInterval = _lmmb.getLog4jLogWatchInterval();
- }
- catch (Exception e2)
- {
- MBeanUtility.handleException(_mbean, e2);
- }
-
- _configFileLoggerLevels = null;
- try
- {
- _configFileLoggerLevels = (TabularDataSupport) _lmmb.viewConfigFileLoggerLevels();
- }
- catch (Exception e3)
- {
- MBeanUtility.handleException(_mbean, e3);
- }
-
- _configFileRootLoggerLevelLabel.setText(String.valueOf(configFileRootLoggerLevel));
- if (log4jLogWatchInterval == 0)
- {
- _logWatchIntervalLabel.setText("Disabled (0 sec)");
- }
- else
- {
- _logWatchIntervalLabel.setText(String.valueOf(log4jLogWatchInterval) + " seconds");
- }
- _tableViewer.setInput(_configFileLoggerLevels);
-
- layout();
- }
-
- public void layout()
- {
- _form.layout(true);
- _form.getBody().layout(true, true);
- }
-
- private void createWidgets()
- {
- try
- {
- _availableLoggerLevels = _lmmb.getAvailableLoggerLevels();
- }
- catch(Exception e)
- {
- _availableLoggerLevels = new String[]{"ALL","TRACE","DEBUG","INFO","WARN","ERROR","FATAL","OFF"};
- }
-
- Label noteLabel = _toolkit.createLabel(_headerComposite,
- "NOTE: These options modify the configuration file. " +
- "Changes only take effect automatically if LogWatch is enabled.");
- Label noteLabel2 = _toolkit.createLabel(_headerComposite,
- "A child Logger set to a non-inherited Level in the Runtime tab " +
- "will retain that value after the file is reloaded.");
- GridData gridData = new GridData(SWT.FILL, SWT.FILL, false, true);
- noteLabel.setLayoutData(gridData);
- gridData = new GridData(SWT.FILL, SWT.FILL, false, true);
- noteLabel2.setLayoutData(gridData);
-
- Group configFileLoggerLevelsGroup = new Group(_paramsComposite, SWT.SHADOW_NONE);
- configFileLoggerLevelsGroup.setBackground(_paramsComposite.getBackground());
- configFileLoggerLevelsGroup.setText("Configuration File Logger Levels");
- configFileLoggerLevelsGroup.setLayout(new GridLayout());
- gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
- configFileLoggerLevelsGroup.setLayoutData(gridData);
-
- Composite tableComposite = _toolkit.createComposite(configFileLoggerLevelsGroup);
- gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
- gridData.heightHint = 250;
- gridData.minimumHeight = 250;
- tableComposite.setLayoutData(gridData);
- GridLayout gridLayout = new GridLayout();
-
- tableComposite.setLayout(gridLayout);
-
- _table = new Table (tableComposite, SWT.MULTI | SWT.SCROLL_LINE | SWT.BORDER | SWT.FULL_SELECTION);
- _table.setLinesVisible (true);
- _table.setHeaderVisible (true);
- GridData data = new GridData(SWT.FILL, SWT.FILL, true, true);
- _table.setLayoutData(data);
-
- _tableViewer = new TableViewer(_table);
- final LoggingTableSorter tableSorter = new LoggingTableSorter();
-
- String[] titles = { LOGGER_NAME, LOGGER_LEVEL };
- int[] bounds = { 600, 75 };
- for (int i = 0; i < titles.length; i++)
- {
- final int index = i;
- final TableViewerColumn viewerColumn = new TableViewerColumn(_tableViewer, SWT.NONE);
- final TableColumn column = viewerColumn.getColumn();
-
- column.setText(titles[i]);
- column.setWidth(bounds[i]);
- column.setResizable(true);
-
- //Setting the right sorter
- column.addSelectionListener(new SelectionAdapter()
- {
- @Override
- public void widgetSelected(SelectionEvent e)
- {
- tableSorter.setColumn(index);
- final TableViewer viewer = _tableViewer;
- int dir = viewer .getTable().getSortDirection();
- if (viewer.getTable().getSortColumn() == column)
- {
- dir = dir == SWT.UP ? SWT.DOWN : SWT.UP;
- }
- else
- {
- dir = SWT.UP;
- }
- viewer.getTable().setSortDirection(dir);
- viewer.getTable().setSortColumn(column);
- viewer.refresh();
- }
- });
-
- }
-
- _tableViewer.setContentProvider(new LoggingTableContentProvider());
- _tableViewer.setLabelProvider(new LoggingTableLabelProvider());
- _tableViewer.setSorter(tableSorter);
- _table.setSortColumn(_table.getColumn(0));
- _table.setSortDirection(SWT.UP);
- _table.addMouseListener(new MouseListener()
- {
- public void mouseDoubleClick(MouseEvent event)
- {
- editLoggerLevel(_table.getShell());
- }
-
- public void mouseDown(MouseEvent e){}
- public void mouseUp(MouseEvent e){}
- });
-
- final Button logLevelEditButton = _toolkit.createButton(configFileLoggerLevelsGroup, "Edit Selected Logger(s)...", SWT.PUSH);
- logLevelEditButton.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false));
- logLevelEditButton.setEnabled(false);
- logLevelEditButton.addSelectionListener(new SelectionAdapter()
- {
- public void widgetSelected(SelectionEvent e)
- {
- editLoggerLevel(logLevelEditButton.getShell());
- }
- });
-
- _tableViewer.addSelectionChangedListener(new ISelectionChangedListener(){
- public void selectionChanged(SelectionChangedEvent evt)
- {
- int selectionIndex = _table.getSelectionIndex();
-
- if(selectionIndex != -1)
- {
- logLevelEditButton.setEnabled(true);
- }
- else
- {
- logLevelEditButton.setEnabled(false);
- }
- }
- });
-
-
- Composite attributesComposite = _toolkit.createComposite(_paramsComposite);
- gridData = new GridData(SWT.LEFT, SWT.FILL, false, true);
- attributesComposite.setLayoutData(gridData);
- gridLayout = new GridLayout(3,false);
- attributesComposite.setLayout(gridLayout);
-
- Group configFileRootLoggerLevelGroup = new Group(attributesComposite, SWT.SHADOW_NONE);
- configFileRootLoggerLevelGroup.setBackground(attributesComposite.getBackground());
- configFileRootLoggerLevelGroup.setText("Config File RootLogger Level");
- gridData = new GridData(SWT.LEFT, SWT.TOP, true, false);
- configFileRootLoggerLevelGroup.setLayoutData(gridData);
- configFileRootLoggerLevelGroup.setLayout(new GridLayout(2,false));
-
- _configFileRootLoggerLevelLabel = _toolkit.createLabel(configFileRootLoggerLevelGroup, "-");
- _configFileRootLoggerLevelLabel.setFont(ApplicationRegistry.getFont(FONT_BOLD));
- _configFileRootLoggerLevelLabel.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false));
-
- final Button configFileRootLoggerLevelButton = _toolkit.createButton(configFileRootLoggerLevelGroup, "Edit ...", SWT.PUSH);
- configFileRootLoggerLevelButton.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, true, false));
- configFileRootLoggerLevelButton.addSelectionListener(new SelectionAdapter()
- {
- public void widgetSelected(SelectionEvent e)
- {
- editRootLoggerLevel(configFileRootLoggerLevelButton.getShell());
- }
- });
-
-
- Group logWatchIntervalGroup = new Group(attributesComposite, SWT.SHADOW_NONE);
- logWatchIntervalGroup.setBackground(attributesComposite.getBackground());
- logWatchIntervalGroup.setText("LogWatch Interval");
- gridData = new GridData(SWT.LEFT, SWT.FILL, true, false);
- logWatchIntervalGroup.setLayoutData(gridData);
- logWatchIntervalGroup.setLayout(new GridLayout());
-
- _logWatchIntervalLabel = _toolkit.createLabel(logWatchIntervalGroup, "-");
- _logWatchIntervalLabel.setFont(ApplicationRegistry.getFont(FONT_BOLD));
- _logWatchIntervalLabel.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, true));
-
- if(_ApiVersion.greaterThanOrEqualTo(1, 4))
- {
- Group reloadConfigFileGroup = new Group(attributesComposite, SWT.SHADOW_NONE);
- reloadConfigFileGroup.setBackground(attributesComposite.getBackground());
- reloadConfigFileGroup.setText("Reload Configuration File");
- gridData = new GridData(SWT.LEFT, SWT.TOP, true, false);
- reloadConfigFileGroup.setLayoutData(gridData);
- reloadConfigFileGroup.setLayout(new GridLayout());
-
- final Button reloadConfigFileButton = _toolkit.createButton(reloadConfigFileGroup, "Reload Config File", SWT.PUSH);
- reloadConfigFileButton.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, false));
- reloadConfigFileButton.addSelectionListener(new SelectionAdapter()
- {
- public void widgetSelected(SelectionEvent e)
- {
- int response = ViewUtility.popupOkCancelConfirmationMessage("Reload",
- "Reload Logging Configuration File?");
- if (response == SWT.OK)
- {
- try
- {
- _lmmb.reloadConfigFile();
- ViewUtility.operationResultFeedback(null, "Reloaded Logging Configuration File", null);
-
- }
- catch (Exception ex)
- {
- ViewUtility.operationFailedStatusBarMessage("Error Reloading Logging Configuration File");
- MBeanUtility.handleException(_mbean, ex);
- }
-
- refresh(_mbean);;
- }
- }
- });
- }
- }
-
-
-
- private void editLoggerLevel(Shell parent)
- {
- int selectionIndex = _table.getSelectionIndex();
-
- if (selectionIndex != -1)
- {
- int[] selectedIndices = _table.getSelectionIndices();
-
- final ArrayList<String> selectedLoggers = new ArrayList<String>();
-
- for(int index = 0; index < selectedIndices.length ; index++)
- {
- CompositeData selectedLogger = (CompositeData)_table.getItem(selectedIndices[index]).getData();
- String user = (String) selectedLogger.get(LOGGER_NAME);
- selectedLoggers.add(user);
- }
-
- final Shell shell = ViewUtility.createModalDialogShell(parent, "Set Config File Logger Level(s)");
-
- _toolkit.createLabel(shell, "Logger(s): ").setBackground(shell.getBackground());
-
- final Text headerText = new Text(shell, SWT.WRAP | SWT.V_SCROLL | SWT.BORDER );
- headerText.setEditable(false);
- GridData data = new GridData(SWT.FILL, SWT.FILL, false, false);
- data.minimumHeight = 125;
- data.heightHint = 125;
- data.minimumWidth = 575;
- data.widthHint = 575;
- headerText.setLayoutData(data);
-
- String lineSeperator = System.getProperty("line.separator");
- for(String loggerName : selectedLoggers)
- {
- headerText.append(loggerName + lineSeperator);
- }
- headerText.setSelection(0);
-
- Composite levelComp = _toolkit.createComposite(shell);
- levelComp.setBackground(shell.getBackground());
- levelComp.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
- levelComp.setLayout(new GridLayout(2,false));
-
- _toolkit.createLabel(levelComp,"Level: ").setBackground(levelComp.getBackground());
- final Combo levelCombo = new Combo (levelComp, SWT.READ_ONLY );
- levelCombo.setItems(_availableLoggerLevels);
- levelCombo.select(0);
-
- Composite okCancelButtonsComp = _toolkit.createComposite(shell);
- okCancelButtonsComp.setBackground(shell.getBackground());
- okCancelButtonsComp.setLayoutData(new GridData(SWT.RIGHT, SWT.FILL, true, true));
- okCancelButtonsComp.setLayout(new GridLayout(2,false));
-
- Button okButton = _toolkit.createButton(okCancelButtonsComp, "OK", SWT.PUSH);
- okButton.setLayoutData(new GridData(SWT.RIGHT, SWT.TOP, false, false));
- Button cancelButton = _toolkit.createButton(okCancelButtonsComp, "Cancel", SWT.PUSH);
- cancelButton.setLayoutData(new GridData(SWT.RIGHT, SWT.TOP, false, false));
-
- okButton.addSelectionListener(new SelectionAdapter()
- {
- public void widgetSelected(SelectionEvent e)
- {
- String level = levelCombo.getItem(levelCombo.getSelectionIndex()).toString();
-
- shell.close();
-
- try
- {
- HashMap<String,Boolean> results = new HashMap<String,Boolean>();
-
- //perform the updates, save the results.
- for(String logger : selectedLoggers)
- {
- boolean result = _lmmb.setConfigFileLoggerLevel(logger, level);
- results.put(logger, result);
- }
-
- //categorise the overall result
- boolean overallResult = true;
- for(boolean result : results.values())
- {
- if (!result)
- {
- overallResult = false;
- }
- }
-
- //output the result to status bar if all succeed, and dialogue if not
- if(overallResult)
- {
- ViewUtility.operationResultFeedback(overallResult, "Updated ConfigFile Logger Level(s)", null);
- }
- else
- {
- String failedToSetLevelOfLoggers = "";
- for(String logger : results.keySet())
- {
- if(!results.get(logger))
- {
- failedToSetLevelOfLoggers = failedToSetLevelOfLoggers.concat(logger + ", ");
- }
- }
-
- //cut off last ", "
- int lastIndex = failedToSetLevelOfLoggers.lastIndexOf(',');
- if (lastIndex != -1)
- {
- failedToSetLevelOfLoggers = failedToSetLevelOfLoggers.substring(0, lastIndex);
- }
-
- ViewUtility.operationResultFeedback(overallResult, null,
- "Failed to update ConfigFile Logger Level(s): "
- + failedToSetLevelOfLoggers);
- }
- }
- catch(Exception e4)
- {
- ViewUtility.operationFailedStatusBarMessage("Error updating Config File Logger Level(s)");
- MBeanUtility.handleException(_mbean, e4);
- }
-
- refresh(_mbean);
- }
- });
-
- cancelButton.addSelectionListener(new SelectionAdapter()
- {
- public void widgetSelected(SelectionEvent e)
- {
- shell.dispose();
- }
- });
-
- shell.setDefaultButton(okButton);
- shell.pack();
- ViewUtility.centerChildInParentShell(parent, shell);
-
- shell.open();
- }
- }
-
- private void editRootLoggerLevel(Shell parent)
- {
- final Shell shell = ViewUtility.createModalDialogShell(parent, "ConfigFile RootLogger Level");
-
- Composite levelComp = _toolkit.createComposite(shell);
- levelComp.setBackground(shell.getBackground());
- levelComp.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
- levelComp.setLayout(new GridLayout(2,false));
-
- _toolkit.createLabel(levelComp,"RootLogger level: ").setBackground(levelComp.getBackground());
- final Combo levelCombo = new Combo (levelComp, SWT.READ_ONLY );
- levelCombo.setItems(_availableLoggerLevels);
- levelCombo.select(0);
-
- Composite okCancelButtonsComp = _toolkit.createComposite(shell);
- okCancelButtonsComp.setBackground(shell.getBackground());
- okCancelButtonsComp.setLayoutData(new GridData(SWT.RIGHT, SWT.FILL, true, true));
- okCancelButtonsComp.setLayout(new GridLayout(2,false));
-
- Button okButton = _toolkit.createButton(okCancelButtonsComp, "OK", SWT.PUSH);
- okButton.setLayoutData(new GridData(SWT.RIGHT, SWT.TOP, false, false));
- Button cancelButton = _toolkit.createButton(okCancelButtonsComp, "Cancel", SWT.PUSH);
- cancelButton.setLayoutData(new GridData(SWT.RIGHT, SWT.TOP, false, false));
-
- okButton.addSelectionListener(new SelectionAdapter()
- {
- public void widgetSelected(SelectionEvent e)
- {
- String selection = levelCombo.getItem(levelCombo.getSelectionIndex()).toString();
- shell.dispose();
- try
- {
- boolean result = _lmmb.setConfigFileRootLoggerLevel(selection);
- ViewUtility.operationResultFeedback(result,
- "Updated ConfigFile RootLogger Level", "Failed to update ConfigFile RootLogger Level");
- }
- catch (Exception e5)
- {
- ViewUtility.operationFailedStatusBarMessage("Error updating ConfigFile RootLogger Level");
- MBeanUtility.handleException(_mbean, e5);
- }
- refresh(_mbean);
- }
- });
-
- cancelButton.addSelectionListener(new SelectionAdapter()
- {
- public void widgetSelected(SelectionEvent e)
- {
- shell.dispose();
- }
- });
-
- shell.setDefaultButton(okButton);
- shell.pack();
- ViewUtility.centerChildInParentShell(parent, shell);
-
- shell.open();
- }
-}
diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/logging/LoggingTableLabelProvider.java b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/logging/LoggingTableLabelProvider.java
deleted file mode 100644
index 821b3d1060..0000000000
--- a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/logging/LoggingTableLabelProvider.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.management.ui.views.logging;
-
-import org.eclipse.jface.viewers.ITableLabelProvider;
-import org.eclipse.jface.viewers.LabelProvider;
-import org.eclipse.swt.graphics.Image;
-
-import static org.apache.qpid.management.common.mbeans.LoggingManagement.LOGGER_LEVEL;
-import static org.apache.qpid.management.common.mbeans.LoggingManagement.LOGGER_NAME;
-
-import javax.management.openmbean.CompositeDataSupport;
-
-/**
- * Label Provider class for the LoggingManagement table viewers
- */
-public class LoggingTableLabelProvider extends LabelProvider implements ITableLabelProvider
-{
- @Override
- public String getColumnText(Object element, int columnIndex)
- {
- switch (columnIndex)
- {
- case 0 : // logger name column
- return (String) ((CompositeDataSupport) element).get(LOGGER_NAME);
- case 1 : // logger level column
- return (String) ((CompositeDataSupport) element).get(LOGGER_LEVEL);
- default :
- return "-";
- }
- }
-
- @Override
- public Image getColumnImage(Object element, int columnIndex)
- {
- return null;
- }
-
-
-}
diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/logging/LoggingTableSorter.java b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/logging/LoggingTableSorter.java
deleted file mode 100644
index e422b43888..0000000000
--- a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/logging/LoggingTableSorter.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.ui.views.logging;
-
-import org.eclipse.jface.viewers.Viewer;
-import org.eclipse.jface.viewers.ViewerSorter;
-
-import static org.apache.qpid.management.common.mbeans.LoggingManagement.LOGGER_LEVEL;
-import static org.apache.qpid.management.common.mbeans.LoggingManagement.LOGGER_NAME;
-
-import javax.management.openmbean.CompositeData;
-
-/**
- * Sorter class for the Logging Management table viewers.
- */
-public class LoggingTableSorter extends ViewerSorter
-{
- private static final int ASCENDING = 0;
- private static final int DESCENDING = 1;
-
- private int column;
- private int direction;
-
- public LoggingTableSorter()
- {
- this.column = 0;
- direction = ASCENDING;
- }
-
- public void setColumn(int column)
- {
- if (column == this.column)
- {
- // Same column as last sort; toggle the direction
- direction = 1 - direction;
- }
- else
- {
- // New column; do an ascending sort
- this.column = column;
- direction = ASCENDING;
- }
- }
-
- @Override
- public int compare(Viewer viewer, Object e1, Object e2)
- {
- CompositeData logger1 = (CompositeData) e1;
- CompositeData logger2 = (CompositeData) e2;
-
- int comparison = 0;
- switch(column)
- {
- case 0:
- comparison = String.valueOf(logger1.get(LOGGER_NAME)).compareTo(
- String.valueOf(logger2.get(LOGGER_NAME)));
- break;
- case 1:
- comparison = String.valueOf(logger1.get(LOGGER_LEVEL)).compareTo(
- String.valueOf(logger2.get(LOGGER_LEVEL)));
- break;
- default:
- comparison = 0;
- }
- // If descending order, flip the direction
- if (direction == DESCENDING)
- {
- comparison = -comparison;
- }
- return comparison;
- }
-}
diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/logging/RuntimeTabControl.java b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/logging/RuntimeTabControl.java
deleted file mode 100644
index b16978171b..0000000000
--- a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/logging/RuntimeTabControl.java
+++ /dev/null
@@ -1,594 +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.logging;
-
-import org.eclipse.jface.viewers.IColorProvider;
-import org.eclipse.jface.viewers.ISelectionChangedListener;
-import org.eclipse.jface.viewers.ITableLabelProvider;
-import org.eclipse.jface.viewers.LabelProvider;
-import org.eclipse.jface.viewers.SelectionChangedEvent;
-import org.eclipse.jface.viewers.TableViewer;
-import org.eclipse.jface.viewers.TableViewerColumn;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.events.MouseEvent;
-import org.eclipse.swt.events.MouseListener;
-import org.eclipse.swt.events.SelectionAdapter;
-import org.eclipse.swt.events.SelectionEvent;
-import org.eclipse.swt.graphics.Color;
-import org.eclipse.swt.graphics.Image;
-import org.eclipse.swt.layout.GridData;
-import org.eclipse.swt.layout.GridLayout;
-import org.eclipse.swt.widgets.Button;
-import org.eclipse.swt.widgets.Combo;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Control;
-import org.eclipse.swt.widgets.Display;
-import org.eclipse.swt.widgets.Group;
-import org.eclipse.swt.widgets.Label;
-import org.eclipse.swt.widgets.Shell;
-import org.eclipse.swt.widgets.TabFolder;
-import org.eclipse.swt.widgets.Table;
-import org.eclipse.swt.widgets.TableColumn;
-import org.eclipse.swt.widgets.Text;
-import org.eclipse.ui.forms.widgets.FormToolkit;
-import org.eclipse.ui.forms.widgets.ScrolledForm;
-
-import org.apache.qpid.management.common.mbeans.LoggingManagement;
-import org.apache.qpid.management.ui.ApplicationRegistry;
-import org.apache.qpid.management.ui.ManagedBean;
-import org.apache.qpid.management.ui.jmx.JMXManagedObject;
-import org.apache.qpid.management.ui.jmx.MBeanUtility;
-import org.apache.qpid.management.ui.views.TabControl;
-import org.apache.qpid.management.ui.views.ViewUtility;
-
-import static org.apache.qpid.management.common.mbeans.LoggingManagement.LOGGER_LEVEL;
-import static org.apache.qpid.management.common.mbeans.LoggingManagement.LOGGER_NAME;
-import static org.apache.qpid.management.ui.Constants.FONT_BOLD;
-
-import javax.management.MBeanServerConnection;
-import javax.management.MBeanServerInvocationHandler;
-import javax.management.openmbean.CompositeData;
-import javax.management.openmbean.CompositeDataSupport;
-import javax.management.openmbean.TabularDataSupport;
-import java.util.ArrayList;
-import java.util.HashMap;
-
-
-/**
- * Control class for the LoggingManagement mbean Runtime Options tab.
- */
-public class RuntimeTabControl extends TabControl
-{
- private FormToolkit _toolkit;
- private ScrolledForm _form;
- private Table _table = null;
- private TableViewer _tableViewer = null;
- private Composite _headerComposite = null;
- private Composite _paramsComposite = null;
-
- private Label _runtimeRootLoggerLevelLabel = null;
- private String[] _availableLoggerLevels;
- private TabularDataSupport _runtimeLoggerLevels = null;
- private ArrayList<String> _configFileLoggerNames = new ArrayList<String>();
- private LoggingManagement _lmmb;
-
- public RuntimeTabControl(TabFolder tabFolder, JMXManagedObject mbean, MBeanServerConnection mbsc)
- {
- super(tabFolder);
- _mbean = mbean;
- _lmmb = (LoggingManagement)
- MBeanServerInvocationHandler.newProxyInstance(mbsc, mbean.getObjectName(),
- LoggingManagement.class, false);
- _toolkit = new FormToolkit(_tabFolder.getDisplay());
- _form = _toolkit.createScrolledForm(_tabFolder);
- _form.getBody().setLayout(new GridLayout());
- createComposites();
- createWidgets();
- }
-
- private void createComposites()
- {
-
- _headerComposite = _toolkit.createComposite(_form.getBody(), SWT.NONE);
- _headerComposite.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
- _headerComposite.setLayout(new GridLayout());
-
- _paramsComposite = _toolkit.createComposite(_form.getBody(), SWT.NONE);
- _paramsComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
- _paramsComposite.setLayout(new GridLayout());
- }
-
- /**
- * @see TabControl#getControl()
- */
- public Control getControl()
- {
- return _form;
- }
-
- /**
- * @see TabControl#setFocus()
- */
- public void setFocus()
- {
- _table.setFocus();
- }
-
- @Override
- public void refresh(ManagedBean mbean)
- {
- String runtimeRootLoggerLevel = "-";
- try
- {
- runtimeRootLoggerLevel = _lmmb.getRuntimeRootLoggerLevel();
- }
- catch(Exception e1)
- {
- MBeanUtility.handleException(_mbean, e1);
- }
-
- _runtimeLoggerLevels = null;
- try
- {
- _runtimeLoggerLevels = (TabularDataSupport) _lmmb.viewEffectiveRuntimeLoggerLevels();
- }
- catch(Exception e2)
- {
- MBeanUtility.handleException(_mbean, e2);
- }
-
-
- try
- {
- TabularDataSupport confLoggers = (TabularDataSupport) _lmmb.viewConfigFileLoggerLevels();
- ArrayList<String> confLoggerNames = new ArrayList<String>();
-
- for(Object obj : confLoggers.values())
- {
- CompositeData comp = (CompositeData) obj;
- confLoggerNames.add((String) comp.get(LOGGER_NAME));
- }
-
- _configFileLoggerNames = confLoggerNames;
- }
- catch(Exception e2)
- {
- //dont signal the failure, just dont highlight the config file loggers, empty the existing list.
- _configFileLoggerNames.clear();
- }
-
- _runtimeRootLoggerLevelLabel.setText(String.valueOf(runtimeRootLoggerLevel));
- _tableViewer.setInput(_runtimeLoggerLevels);
-
- layout();
- }
-
- public void layout()
- {
- _form.layout(true);
- _form.getBody().layout(true, true);
- }
-
- private void createWidgets()
- {
- try
- {
- _availableLoggerLevels = _lmmb.getAvailableLoggerLevels();
- }
- catch(Exception e)
- {
- _availableLoggerLevels = new String[]{"ALL","TRACE","DEBUG","INFO","WARN","ERROR","FATAL","OFF"};
- }
-
- Label noteLabel = _toolkit.createLabel(_headerComposite,
- "NOTE: These options modify only the live runtime settings. " +
- "Non-default values will be lost following broker restart.");
- Label noteLabel2 = _toolkit.createLabel(_headerComposite,
- "Loggers currently defined in the configuration file are " +
- "highlighted. The other Loggers inherit a Level by default.");
- GridData gridData = new GridData(SWT.FILL, SWT.FILL, false, true);
- noteLabel.setLayoutData(gridData);
- gridData = new GridData(SWT.FILL, SWT.FILL, false, true);
- noteLabel2.setLayoutData(gridData);
-
- Group effectiveRuntimeLoggerLevelsGroup = new Group(_paramsComposite, SWT.SHADOW_NONE);
- effectiveRuntimeLoggerLevelsGroup.setBackground(_paramsComposite.getBackground());
- effectiveRuntimeLoggerLevelsGroup.setText("Effective Runtime Logger Levels");
- effectiveRuntimeLoggerLevelsGroup.setLayout(new GridLayout());
- gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
- effectiveRuntimeLoggerLevelsGroup.setLayoutData(gridData);
-
- Composite tableComposite = _toolkit.createComposite(effectiveRuntimeLoggerLevelsGroup);
- gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
- gridData.heightHint = 250;
- gridData.minimumHeight = 250;
- tableComposite.setLayoutData(gridData);
- GridLayout gridLayout = new GridLayout();
- tableComposite.setLayout(gridLayout);
-
- _table = new Table (tableComposite, SWT.MULTI | SWT.SCROLL_LINE | SWT.BORDER | SWT.FULL_SELECTION);
- _table.setLinesVisible (true);
- _table.setHeaderVisible (true);
- GridData data = new GridData(SWT.FILL, SWT.FILL, true, true);
- _table.setLayoutData(data);
-
- _tableViewer = new TableViewer(_table);
- final LoggingTableSorter tableSorter = new LoggingTableSorter();
-
- String[] titles = { LOGGER_NAME, LOGGER_LEVEL };
- int[] bounds = { 600, 75 };
- for (int i = 0; i < titles.length; i++)
- {
- final int index = i;
- final TableViewerColumn viewerColumn = new TableViewerColumn(_tableViewer, SWT.NONE);
- final TableColumn column = viewerColumn.getColumn();
-
- column.setText(titles[i]);
- column.setWidth(bounds[i]);
- column.setResizable(true);
-
- //Setting the right sorter
- column.addSelectionListener(new SelectionAdapter()
- {
- @Override
- public void widgetSelected(SelectionEvent e)
- {
- tableSorter.setColumn(index);
- final TableViewer viewer = _tableViewer;
- int dir = viewer.getTable().getSortDirection();
- if (viewer.getTable().getSortColumn() == column)
- {
- dir = (dir == SWT.UP ? SWT.DOWN : SWT.UP);
- }
- else
- {
- dir = SWT.UP;
- }
- viewer.getTable().setSortDirection(dir);
- viewer.getTable().setSortColumn(column);
- viewer.refresh();
- }
- });
-
- }
-
- _tableViewer.setContentProvider(new LoggingTableContentProvider());
- _tableViewer.setLabelProvider(new RuntimeLoggingTableLabelProvider());
- _tableViewer.setSorter(tableSorter);
- _table.setSortColumn(_table.getColumn(0));
- _table.setSortDirection(SWT.UP);
- _table.addMouseListener(new MouseListener()
- {
- public void mouseDoubleClick(MouseEvent event)
- {
- editLoggerLevel(_table.getShell());
- }
-
- public void mouseDown(MouseEvent e){}
- public void mouseUp(MouseEvent e){}
- });
-
- final Button logLevelEditButton = _toolkit.createButton(effectiveRuntimeLoggerLevelsGroup, "Edit Selected Logger(s)...", SWT.PUSH);
- logLevelEditButton.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false));
- logLevelEditButton.setEnabled(false);
- logLevelEditButton.addSelectionListener(new SelectionAdapter()
- {
- public void widgetSelected(SelectionEvent e)
- {
- editLoggerLevel(logLevelEditButton.getShell());
- }
- });
-
- _tableViewer.addSelectionChangedListener(new ISelectionChangedListener(){
- public void selectionChanged(SelectionChangedEvent evt)
- {
- int selectionIndex = _table.getSelectionIndex();
-
- if (selectionIndex != -1)
- {
- logLevelEditButton.setEnabled(true);
- }
- else
- {
- logLevelEditButton.setEnabled(false);
- }
- }
- });
-
- Composite attributesComposite = _toolkit.createComposite(_paramsComposite);
- gridData = new GridData(SWT.FILL, SWT.FILL, false, true);
- attributesComposite.setLayoutData(gridData);
- gridLayout = new GridLayout(3,false);
- attributesComposite.setLayout(gridLayout);
-
- Group runtimeRootLoggerGroup = new Group(attributesComposite, SWT.SHADOW_NONE);
- runtimeRootLoggerGroup.setBackground(attributesComposite.getBackground());
- runtimeRootLoggerGroup.setText("Runtime RootLogger Level");
- gridData = new GridData(SWT.LEFT, SWT.TOP, true, false);
- runtimeRootLoggerGroup.setLayoutData(gridData);
- runtimeRootLoggerGroup.setLayout(new GridLayout(2,false));
-
- _runtimeRootLoggerLevelLabel = _toolkit.createLabel(runtimeRootLoggerGroup, "-");
- _runtimeRootLoggerLevelLabel.setFont(ApplicationRegistry.getFont(FONT_BOLD));
- _runtimeRootLoggerLevelLabel.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false));
-
- final Button runtimeRootLoggerLevelButton = _toolkit.createButton(runtimeRootLoggerGroup, "Edit ...", SWT.PUSH);
- runtimeRootLoggerLevelButton.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, true, false));
- runtimeRootLoggerLevelButton.addSelectionListener(new SelectionAdapter()
- {
- public void widgetSelected(SelectionEvent e)
- {
- editRootLoggerLevel(runtimeRootLoggerLevelButton.getShell());
- }
- });
- }
-
- private void editLoggerLevel(Shell parent)
- {
- int selectionIndex = _table.getSelectionIndex();
-
- if (selectionIndex != -1)
- {
- int[] selectedIndices = _table.getSelectionIndices();
-
- final ArrayList<String> selectedLoggers = new ArrayList<String>();
-
- for(int index = 0; index < selectedIndices.length ; index++)
- {
- CompositeData selectedLogger = (CompositeData)_table.getItem(selectedIndices[index]).getData();
- String user = (String) selectedLogger.get(LOGGER_NAME);
- selectedLoggers.add(user);
- }
-
- final Shell shell = ViewUtility.createModalDialogShell(parent, "Set Runtime Logger Level(s)");
-
- _toolkit.createLabel(shell, "Logger(s): ").setBackground(shell.getBackground());
-
- final Text headerText = new Text(shell, SWT.WRAP | SWT.V_SCROLL | SWT.BORDER );
- headerText.setEditable(false);
- GridData data = new GridData(SWT.FILL, SWT.FILL, false, false);
- data.minimumHeight = 125;
- data.heightHint = 125;
- data.minimumWidth = 575;
- data.widthHint = 575;
- headerText.setLayoutData(data);
-
- String lineSeperator = System.getProperty("line.separator");
- for(String loggerName : selectedLoggers)
- {
- headerText.append(loggerName + lineSeperator);
- }
- headerText.setSelection(0);
-
- Composite levelComp = _toolkit.createComposite(shell);
- levelComp.setBackground(shell.getBackground());
- levelComp.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
- levelComp.setLayout(new GridLayout(2,false));
-
- _toolkit.createLabel(levelComp,"Level: ").setBackground(levelComp.getBackground());
- final Combo levelCombo = new Combo (levelComp, SWT.READ_ONLY );
- levelCombo.setItems(_availableLoggerLevels);
- levelCombo.select(0);
-
- Composite okCancelButtonsComp = _toolkit.createComposite(shell);
- okCancelButtonsComp.setBackground(shell.getBackground());
- okCancelButtonsComp.setLayoutData(new GridData(SWT.RIGHT, SWT.FILL, true, true));
- okCancelButtonsComp.setLayout(new GridLayout(2,false));
-
- Button okButton = _toolkit.createButton(okCancelButtonsComp, "OK", SWT.PUSH);
- okButton.setLayoutData(new GridData(SWT.RIGHT, SWT.TOP, false, false));
- Button cancelButton = _toolkit.createButton(okCancelButtonsComp, "Cancel", SWT.PUSH);
- cancelButton.setLayoutData(new GridData(SWT.RIGHT, SWT.TOP, false, false));
-
- okButton.addSelectionListener(new SelectionAdapter()
- {
- public void widgetSelected(SelectionEvent e)
- {
- String level = levelCombo.getItem(levelCombo.getSelectionIndex()).toString();
-
- shell.close();
-
- try
- {
- HashMap<String,Boolean> results = new HashMap<String,Boolean>();
-
- //perform the updates, save the results.
- for(String logger : selectedLoggers)
- {
- boolean result = _lmmb.setRuntimeLoggerLevel(logger, level);
- results.put(logger, result);
- }
-
- //categorise the overall result
- boolean overallResult = true;
- for(boolean result : results.values())
- {
- if (!result)
- {
- overallResult = false;
- }
- }
-
- //output the result to status bar if all succeed, and dialogue if not
- if(overallResult)
- {
- ViewUtility.operationResultFeedback(overallResult, "Updated Runtime Logger Level(s)", null);
- }
- else
- {
- String failedToSetLevelOfLoggers = "";
- for(String logger : results.keySet())
- {
- if(!results.get(logger))
- {
- failedToSetLevelOfLoggers = failedToSetLevelOfLoggers.concat(logger + ", ");
- }
- }
-
- //cut off last ", "
- int lastIndex = failedToSetLevelOfLoggers.lastIndexOf(',');
- if (lastIndex != -1)
- {
- failedToSetLevelOfLoggers = failedToSetLevelOfLoggers.substring(0, lastIndex);
- }
-
- ViewUtility.operationResultFeedback(overallResult, null,
- "Failed to update Runtime Logger Level(s): "
- + failedToSetLevelOfLoggers);
- }
- }
- catch(Exception e3)
- {
- ViewUtility.operationFailedStatusBarMessage("Error updating Runtime Logger Level(s)");
- MBeanUtility.handleException(_mbean, e3);
- }
-
- refresh(_mbean);
- }
- });
-
- cancelButton.addSelectionListener(new SelectionAdapter()
- {
- public void widgetSelected(SelectionEvent e)
- {
- shell.dispose();
- }
- });
-
- shell.setDefaultButton(okButton);
- shell.pack();
- ViewUtility.centerChildInParentShell(parent, shell);
-
- shell.open();
- }
- }
-
- private void editRootLoggerLevel(Shell parent)
- {
- final Shell shell = ViewUtility.createModalDialogShell(parent, "Runtime RootLogger Level");
-
- Composite levelComp = _toolkit.createComposite(shell);
- levelComp.setBackground(shell.getBackground());
- levelComp.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
- levelComp.setLayout(new GridLayout(2,false));
-
- _toolkit.createLabel(levelComp,"RootLogger level: ").setBackground(levelComp.getBackground());
- final Combo levelCombo = new Combo (levelComp, SWT.READ_ONLY );
- levelCombo.setItems(_availableLoggerLevels);
- levelCombo.select(0);
-
- Composite okCancelButtonsComp = _toolkit.createComposite(shell);
- okCancelButtonsComp.setBackground(shell.getBackground());
- okCancelButtonsComp.setLayoutData(new GridData(SWT.RIGHT, SWT.FILL, true, true));
- okCancelButtonsComp.setLayout(new GridLayout(2,false));
-
- Button okButton = _toolkit.createButton(okCancelButtonsComp, "OK", SWT.PUSH);
- okButton.setLayoutData(new GridData(SWT.RIGHT, SWT.TOP, false, false));
- Button cancelButton = _toolkit.createButton(okCancelButtonsComp, "Cancel", SWT.PUSH);
- cancelButton.setLayoutData(new GridData(SWT.RIGHT, SWT.TOP, false, false));
-
- okButton.addSelectionListener(new SelectionAdapter()
- {
- public void widgetSelected(SelectionEvent e)
- {
- String selection = levelCombo.getItem(levelCombo.getSelectionIndex()).toString();
- shell.dispose();
-
- try
- {
- boolean result = _lmmb.setRuntimeRootLoggerLevel(selection);
- ViewUtility.operationResultFeedback(result,
- "Updated Runtime RootLogger Level", "Failed to update Runtime Logger Level");
- }
- catch(Exception e4)
- {
- ViewUtility.operationFailedStatusBarMessage("Error updating Runtime Logger Level");
- MBeanUtility.handleException(_mbean, e4);
- }
-
- refresh(_mbean);
- }
- });
-
- cancelButton.addSelectionListener(new SelectionAdapter()
- {
- public void widgetSelected(SelectionEvent e)
- {
- shell.dispose();
- }
- });
-
- shell.setDefaultButton(okButton);
- shell.pack();
- ViewUtility.centerChildInParentShell(parent, shell);
-
- shell.open();
- }
-
- /**
- * Label Provider class for the RuntimeLoggers table viewer
- */
- public class RuntimeLoggingTableLabelProvider extends LabelProvider implements ITableLabelProvider, IColorProvider
- {
-
- @Override
- public String getColumnText(Object element, int columnIndex)
- {
- switch (columnIndex)
- {
- case 0 : // logger name column
- return (String) ((CompositeDataSupport) element).get(LOGGER_NAME);
- case 1 : // logger level column
- return (String) ((CompositeDataSupport) element).get(LOGGER_LEVEL);
- default :
- return "-";
- }
- }
-
- @Override
- public Image getColumnImage(Object element, int columnIndex)
- {
- return null;
- }
-
- @Override
- public Color getBackground(Object element)
- {
- return null;
- }
-
- @Override
- public Color getForeground(Object element)
- {
- String loggerName = (String) ((CompositeData) element).get(LOGGER_NAME);
- if(_configFileLoggerNames.contains(loggerName))
- {
- return Display.getCurrent().getSystemColor(SWT.COLOR_BLUE);
- }
- else
- {
- return null;
- }
- }
-
-
- }
-}
diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/queue/QueueOperationsTabControl.java b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/queue/QueueOperationsTabControl.java
deleted file mode 100644
index f9a26f544a..0000000000
--- a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/queue/QueueOperationsTabControl.java
+++ /dev/null
@@ -1,1111 +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.queue;
-
-import org.eclipse.jface.viewers.ISelectionChangedListener;
-import org.eclipse.jface.viewers.IStructuredContentProvider;
-import org.eclipse.jface.viewers.ITableLabelProvider;
-import org.eclipse.jface.viewers.LabelProvider;
-import org.eclipse.jface.viewers.SelectionChangedEvent;
-import org.eclipse.jface.viewers.TableViewer;
-import org.eclipse.jface.viewers.Viewer;
-import org.eclipse.jface.viewers.ViewerSorter;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.events.KeyAdapter;
-import org.eclipse.swt.events.KeyEvent;
-import org.eclipse.swt.events.MouseEvent;
-import org.eclipse.swt.events.MouseListener;
-import org.eclipse.swt.events.SelectionAdapter;
-import org.eclipse.swt.events.SelectionEvent;
-import org.eclipse.swt.graphics.Image;
-import org.eclipse.swt.layout.GridData;
-import org.eclipse.swt.layout.GridLayout;
-import org.eclipse.swt.widgets.Button;
-import org.eclipse.swt.widgets.Combo;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Control;
-import org.eclipse.swt.widgets.Display;
-import org.eclipse.swt.widgets.Group;
-import org.eclipse.swt.widgets.Shell;
-import org.eclipse.swt.widgets.TabFolder;
-import org.eclipse.swt.widgets.Table;
-import org.eclipse.swt.widgets.TableColumn;
-import org.eclipse.swt.widgets.Text;
-import org.eclipse.ui.forms.widgets.FormToolkit;
-import org.eclipse.ui.forms.widgets.ScrolledForm;
-
-import org.apache.qpid.management.common.mbeans.ManagedQueue;
-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.ui.jmx.JMXManagedObject;
-import org.apache.qpid.management.ui.jmx.MBeanUtility;
-import org.apache.qpid.management.ui.views.NumberVerifyListener;
-import org.apache.qpid.management.ui.views.TabControl;
-import org.apache.qpid.management.ui.views.ViewUtility;
-
-import static org.apache.qpid.management.common.mbeans.ManagedQueue.MSG_AMQ_ID;
-import static org.apache.qpid.management.common.mbeans.ManagedQueue.MSG_HEADER;
-import static org.apache.qpid.management.common.mbeans.ManagedQueue.MSG_QUEUE_POS;
-import static org.apache.qpid.management.common.mbeans.ManagedQueue.MSG_REDELIVERED;
-import static org.apache.qpid.management.common.mbeans.ManagedQueue.MSG_SIZE;
-import static org.apache.qpid.management.ui.Constants.CONSOLE_IMAGE;
-import static org.apache.qpid.management.ui.Constants.RESULT;
-
-import javax.management.MBeanServerConnection;
-import javax.management.MBeanServerInvocationHandler;
-import javax.management.openmbean.CompositeData;
-import javax.management.openmbean.CompositeDataSupport;
-import javax.management.openmbean.TabularDataSupport;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-import java.util.SortedSet;
-import java.util.TreeSet;
-
-
-/**
- * Control class for the Queue mbean Operations tab.
- */
-public class QueueOperationsTabControl extends TabControl
-{
- private FormToolkit _toolkit;
- private ScrolledForm _form;
- private Table _table = null;
- private TableViewer _tableViewer = null;
- private Composite _paramsComposite = null;
-
- private ApiVersion _ApiVersion;
-
- private Text _fromMsgText;
- private Text _toMsgText;
- private static final String FROM_DEFAULT = "1";
- private static final String TO_DEFAULT = "50";
- private long _interval = 50; //(to-from)+1
- private Long _fromMsg = new Long(FROM_DEFAULT);
- private Long _toMsg = new Long(TO_DEFAULT);
-
- private TabularDataSupport _messages = null;
- private ManagedQueue _qmb;
-
- private Button _previousButton;
- private Button _nextButton;
-
- public QueueOperationsTabControl(TabFolder tabFolder, JMXManagedObject mbean, MBeanServerConnection mbsc)
- {
- super(tabFolder);
- _mbean = mbean;
- _ApiVersion = ApplicationRegistry.getServerRegistry(mbean).getManagementApiVersion();
- _qmb = (ManagedQueue) MBeanServerInvocationHandler.newProxyInstance(mbsc,
- mbean.getObjectName(), ManagedQueue.class, false);
- _toolkit = new FormToolkit(_tabFolder.getDisplay());
- _form = _toolkit.createScrolledForm(_tabFolder);
- _form.getBody().setLayout(new GridLayout());
- createComposites();
- createWidgets();
- }
-
- private void createComposites()
- {
- _paramsComposite = _toolkit.createComposite(_form.getBody(), SWT.NONE);
- _paramsComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
- _paramsComposite.setLayout(new GridLayout());
- }
-
- /**
- * @see TabControl#getControl()
- */
- public Control getControl()
- {
- return _form;
- }
-
- /**
- * @see TabControl#setFocus()
- */
- public void setFocus()
- {
- _table.setFocus();
- }
-
- @Override
- public void refresh(ManagedBean mbean)
- {
- _messages = null;
- try
- {
- if(_ApiVersion.greaterThanOrEqualTo(1, 3))
- { //broker supports Qpid JMX API 1.3 and takes Long values
-
- //gather a list of all messages on the queue for display and selection
- _messages = (TabularDataSupport) _qmb.viewMessages(_fromMsg,_toMsg);
- }
- else
- { //broker supports Qpid JMX API 1.2 or below and takes int values
-
- if(_toMsg > Integer.MAX_VALUE || _toMsg > Integer.MAX_VALUE)
- {
- ViewUtility.popupErrorMessage("Error", "This broker only supports viewing up to message " + Integer.MAX_VALUE);
- _tableViewer.setInput(null);
- return;
- }
-
- //gather a list of all messages on the queue for display and selection
- _messages = (TabularDataSupport) _qmb.viewMessages(_fromMsg.intValue(), _toMsg.intValue());
- }
- }
- catch (Exception e)
- {
- MBeanUtility.handleException(mbean,e);
- }
-
- _tableViewer.setInput(_messages);
-
- layout();
- }
-
- public void layout()
- {
- _form.layout(true);
- _form.getBody().layout(true, true);
- }
-
- private void createWidgets()
- {
- Group messagesGroup = new Group(_paramsComposite, SWT.SHADOW_NONE | SWT.SCROLL_LINE);
- messagesGroup.setBackground(_paramsComposite.getBackground());
- messagesGroup.setText("Messages");
- messagesGroup.setLayout(new GridLayout());
- GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
- messagesGroup.setLayoutData(gridData);
-
- //from and to fields for selecting the viewing range
- Composite viewMessageRangeComposite = _toolkit.createComposite(messagesGroup);
- gridData = new GridData(SWT.LEFT, SWT.FILL, false, false);
- viewMessageRangeComposite.setLayoutData(gridData);
- viewMessageRangeComposite.setLayout(new GridLayout(8,false));
-
- _toolkit.createLabel(viewMessageRangeComposite, "Queue pos: ");
- _fromMsgText = new Text(viewMessageRangeComposite, SWT.BORDER);
- _fromMsgText.setText(FROM_DEFAULT);
- gridData = new GridData(SWT.LEFT, SWT.FILL, false, false);
- gridData.widthHint = 75;
- _fromMsgText.setLayoutData(gridData);
- _fromMsgText.addVerifyListener(new NumberVerifyListener());
- _fromMsgText.addKeyListener(new KeyAdapter()
- {
- public void keyPressed(KeyEvent event)
- {
- if (event.character == SWT.CR)
- {
- updateMessageInterval();
- }
- }
- });
-
- _toolkit.createLabel(viewMessageRangeComposite, "to");
-
- _toMsgText = new Text(viewMessageRangeComposite, SWT.BORDER);
- _toMsgText.setText(TO_DEFAULT);
- gridData = new GridData(SWT.LEFT, SWT.FILL, false, false);
- gridData.widthHint = 75;
- _toMsgText.setLayoutData(gridData);
- _toMsgText.addVerifyListener(new NumberVerifyListener());
- _toMsgText.addKeyListener(new KeyAdapter()
- {
- public void keyPressed(KeyEvent event)
- {
- if (event.character == SWT.CR)
- {
- updateMessageInterval();
- }
- }
- });
-
- final Button setButton = _toolkit.createButton(viewMessageRangeComposite, "Set", SWT.PUSH);
- setButton.setLayoutData(new GridData(SWT.LEFT, SWT.FILL, false, false));
- setButton.addSelectionListener(new SelectionAdapter()
- {
- public void widgetSelected(SelectionEvent e)
- {
- updateMessageInterval();
- }
- });
-
- _toolkit.createLabel(viewMessageRangeComposite, " "); //spacer
-
- _previousButton = _toolkit.createButton(viewMessageRangeComposite, "< Prev " + _interval, SWT.PUSH);
- _previousButton.setLayoutData(new GridData(SWT.LEFT, SWT.FILL, false, false));
- _previousButton.addSelectionListener(new SelectionAdapter()
- {
- public void widgetSelected(SelectionEvent e)
- {
- //make 'to' be 'from - 1' unless from is 1 (ie there are no previous messages)
- if(_fromMsg > 1)
- {
- _toMsg = _fromMsg - 1;
- _toMsgText.setText(_toMsg.toString());
- }
-
- //make 'from' be 'from - INTERVAL', or make it 1 if that would make it 0 or less
- _fromMsg = (_fromMsg - _interval < 1) ? 1 : _fromMsg - _interval;
- _fromMsgText.setText(_fromMsg.toString());
-
- refresh(_mbean);
- }
- });
-
- _nextButton = _toolkit.createButton(viewMessageRangeComposite, "Next " + _interval + " >", SWT.PUSH);
- _nextButton.setLayoutData(new GridData(SWT.LEFT, SWT.FILL, false, false));
- _nextButton.addSelectionListener(new SelectionAdapter()
- {
- public void widgetSelected(SelectionEvent e)
- {
- //make 'from' be 'to + 1' unless 'to' is already Long.MAX_VALUE
- if(_toMsg != Long.MAX_VALUE)
- {
- _fromMsg = _toMsg + 1;
- _fromMsgText.setText(_fromMsg.toString());
- }
-
- //make 'to' be 'to + INTERVAL', or make it Long.MAX_VALUE if that would too large
- _toMsg = (Long.MAX_VALUE - _toMsg > _interval) ? _toMsg + _interval : Long.MAX_VALUE;
- _toMsgText.setText(_toMsg.toString());
-
- refresh(_mbean);
- }
- });
-
- //message table
- Composite tableAndButtonsComposite = _toolkit.createComposite(messagesGroup);
- gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
- gridData.minimumHeight = 180;
- gridData.heightHint = 180;
- tableAndButtonsComposite.setLayoutData(gridData);
- tableAndButtonsComposite.setLayout(new GridLayout(2,false));
-
- _table = new Table (tableAndButtonsComposite, SWT.MULTI | SWT.SCROLL_LINE | SWT.BORDER | SWT.FULL_SELECTION);
- _table.setLinesVisible (true);
- _table.setHeaderVisible (true);
- GridData data = new GridData(SWT.FILL, SWT.FILL, true, true);
- _table.setLayoutData(data);
-
- _tableViewer = new TableViewer(_table);
- final TableSorter tableSorter = new TableSorter();
-
- String[] titles = {"AMQ ID", "Size(bytes)"};
- if(_ApiVersion.greaterThanOrEqualTo(1, 3))
- {
- //if server management API is >= 1.3, show message's queue position
- titles = new String[]{"AMQ ID", "Size(bytes)", "Queue Position"};
- }
-
- int[] bounds = { 175, 175, 140 };
- for (int i = 0; i < titles.length; i++)
- {
- final int index = i;
- final TableColumn column = new TableColumn (_table, SWT.NONE);
-
- column.setText(titles[i]);
- column.setWidth(bounds[i]);
- column.setResizable(true);
-
- //Setting the right sorter
- column.addSelectionListener(new SelectionAdapter()
- {
- @Override
- public void widgetSelected(SelectionEvent e)
- {
- tableSorter.setColumn(index);
- final TableViewer viewer = _tableViewer;
- int dir = viewer .getTable().getSortDirection();
- if (viewer.getTable().getSortColumn() == column)
- {
- dir = dir == SWT.UP ? SWT.DOWN : SWT.UP;
- }
- else
- {
- dir = SWT.UP;
- }
- viewer.getTable().setSortDirection(dir);
- viewer.getTable().setSortColumn(column);
- viewer.refresh();
- }
- });
-
- }
-
- _tableViewer.setContentProvider(new ContentProviderImpl());
- _tableViewer.setLabelProvider(new LabelProviderImpl());
- _tableViewer.setSorter(tableSorter);
- _table.setSortColumn(_table.getColumn(0));
- _table.setSortDirection(SWT.UP);
-
- //Side Buttons
- Composite buttonsComposite = _toolkit.createComposite(tableAndButtonsComposite);
- gridData = new GridData(SWT.FILL, SWT.FILL, false, true);
- buttonsComposite.setLayoutData(gridData);
- buttonsComposite.setLayout(new GridLayout());
-
- final Button viewSelectedMsgButton = _toolkit.createButton(buttonsComposite, "View Message Content ...", SWT.PUSH);
- viewSelectedMsgButton.setLayoutData(new GridData(SWT.FILL, SWT.TOP, false, false));
- viewSelectedMsgButton.setEnabled(false);
- viewSelectedMsgButton.addSelectionListener(new SelectionAdapter()
- {
- public void widgetSelected(SelectionEvent e)
- {
- if (_table.getSelectionIndex() == -1)
- {
- return;
- }
-
- viewMessageContent();
- }
- });
-
- if(_ApiVersion.lessThan(1, 3)) //if the server predates Qpid JMX API 1.3
- {
- final Button deleteFirstMessageButton = _toolkit.createButton(buttonsComposite, "Delete 1st Unacquired Msg", SWT.PUSH);
- deleteFirstMessageButton.setLayoutData(new GridData(SWT.FILL, SWT.TOP, false, false));
- deleteFirstMessageButton.addSelectionListener(new SelectionAdapter()
- {
- public void widgetSelected(SelectionEvent se)
- {
- int response = ViewUtility.popupOkCancelConfirmationMessage("Delete 1st unacquired message",
- "Delete 1st unacquired message on the queue?\n\n"
- + "NOTE: Any ongoing consumer activity may mean this is "
- + "not the first message listed in the table.");
- if (response == SWT.OK)
- {
- try
- {
- _qmb.deleteMessageFromTop();
- ViewUtility.operationResultFeedback(null, "Deleted 1st unacquired message on the queue", null);
- }
- catch (Exception e)
- {
- ViewUtility.operationFailedStatusBarMessage("Error deleting 1st unacquired message on queue");
- MBeanUtility.handleException(_mbean, e);
- }
-
- refresh(_mbean);;
- }
- }
- });
- }
-
- final Button moveMessagesButton;
- if(_ApiVersion.greaterThanOrEqualTo(1, 3))
- {
- //If the server supports Qpid JMX API 1.3, show the move message button.
- //This is being disabled for earlier brokers due to bugs affecting the result appearance
- //and impacting on the ability of the source queues to deliver further messages.
-
- moveMessagesButton = _toolkit.createButton(buttonsComposite, "Move Message(s) ...", SWT.PUSH);
-
- moveMessagesButton.setLayoutData(new GridData(SWT.FILL, SWT.TOP, false, false));
- moveMessagesButton.setEnabled(false);
- moveMessagesButton.addSelectionListener(new SelectionAdapter()
- {
- public void widgetSelected(SelectionEvent e)
- {
- if (_table.getSelectionIndex() == -1)
- {
- return;
- }
-
- moveOrCopyMessages(moveMessagesButton.getShell(), QueueOperations.MOVE);
- }
- });
- }
- else
- {
- moveMessagesButton = null;
- }
-
- final Button copyMessagesButton;
- if(_ApiVersion.greaterThanOrEqualTo(1, 3))//if the server supports Qpid JMX API 1.3
- {
- copyMessagesButton= _toolkit.createButton(buttonsComposite, "Copy Message(s) ...", SWT.PUSH);
- copyMessagesButton.setLayoutData(new GridData(SWT.FILL, SWT.TOP, false, false));
- copyMessagesButton.setEnabled(false);
- copyMessagesButton.addSelectionListener(new SelectionAdapter()
- {
- public void widgetSelected(SelectionEvent e)
- {
- if (_table.getSelectionIndex() == -1)
- {
- return;
- }
-
- moveOrCopyMessages(copyMessagesButton.getShell(), QueueOperations.COPY);
- }
- });
- }
- else
- {
- copyMessagesButton = null;
- }
-
- final Button deleteMessagesButton;
- if(_ApiVersion.greaterThanOrEqualTo(1, 3))//if the server supports Qpid JMX API 1.3
- {
- deleteMessagesButton = _toolkit.createButton(buttonsComposite, "Delete Message(s) ...", SWT.PUSH);
- deleteMessagesButton.setLayoutData(new GridData(SWT.FILL, SWT.TOP, false, false));
- deleteMessagesButton.setEnabled(false);
- deleteMessagesButton.addSelectionListener(new SelectionAdapter()
- {
- public void widgetSelected(SelectionEvent e)
- {
- if (_table.getSelectionIndex() == -1)
- {
- return;
- }
-
- deleteMessages(deleteMessagesButton.getShell());
- }
- });
- }
- else
- {
- deleteMessagesButton = null;
- }
-
- final Button clearQueueButton = _toolkit.createButton(buttonsComposite, "Clear Queue", SWT.PUSH);
- clearQueueButton.setLayoutData(new GridData(SWT.FILL, SWT.TOP, false, false));
- clearQueueButton.addSelectionListener(new SelectionAdapter()
- {
- public void widgetSelected(SelectionEvent e)
- {
- int response = ViewUtility.popupOkCancelConfirmationMessage("Clear Queue",
- "Clear queue ?");
- if (response == SWT.OK)
- {
- try
- {
- if(_ApiVersion.greaterThanOrEqualTo(1, 3))
- {
- //Qpid JMX API 1.3+, returns the number of messages deleted
- Long numDeleted = _qmb.clearQueue();
- String message = "Queue cleared of " + numDeleted +
- " non-acquired message" + (numDeleted == 1 ? "": "s");
-
- ViewUtility.operationResultFeedback(null, message, null);
- }
- else
- {
- //Qpid JMX API 1.2 or below, void return
- _qmb.clearQueue();
- ViewUtility.operationResultFeedback(null, "Queue cleared of non-acquired messages", null);
- }
- }
- catch (Exception e2)
- {
- ViewUtility.operationFailedStatusBarMessage("Error clearing Queue");
- MBeanUtility.handleException(_mbean, e2);
- }
-
- refresh(_mbean);;
- }
- }
- });
-
- _toolkit.createLabel(messagesGroup, "Message Header: ");
-
- //Redelivered status and header
- Composite headerEtcComposite = _toolkit.createComposite(messagesGroup);
- gridData = new GridData(SWT.FILL, SWT.FILL, true, false);
- headerEtcComposite.setLayoutData(gridData);
- headerEtcComposite.setLayout(new GridLayout());
-
- final Text headerText = new Text(headerEtcComposite, SWT.WRAP | SWT.BORDER | SWT.V_SCROLL);
- headerText.setText("Select a message to view its header.");
- headerText.setEditable(false);
- data = new GridData(SWT.LEFT, SWT.TOP, false, false);
- data.minimumHeight = 210;
- data.heightHint = 210;
- data.minimumWidth = 500;
- data.widthHint = 500;
- headerText.setLayoutData(data);
-
- Composite redeliveryComposite = _toolkit.createComposite(headerEtcComposite);
- redeliveryComposite.setLayout(new GridLayout(2,false));
- data = new GridData(SWT.LEFT, SWT.FILL, false, false);
- data.minimumWidth = 150;
- data.widthHint = 150;
- redeliveryComposite.setLayoutData(data);
-
- _toolkit.createLabel(redeliveryComposite, "Redelivered: ");
- final Text redeliveredText = new Text(redeliveryComposite, SWT.BORDER);
- redeliveredText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
- redeliveredText.setText("-");
- redeliveredText.setEditable(false);
-
- //listener for double clicking to view message content
- _table.addMouseListener(new MouseListener()
- {
- // MouseListener implementation
- public void mouseDoubleClick(MouseEvent event)
- {
- viewMessageContent();
- }
-
- public void mouseDown(MouseEvent e){}
- public void mouseUp(MouseEvent e){}
- });
-
- //selection listener to enable and disable buttons, update header and redelivered info
- _tableViewer.addSelectionChangedListener(new ISelectionChangedListener(){
- public void selectionChanged(SelectionChangedEvent evt)
- {
- int selectionIndex = _table.getSelectionIndex();
-
- if (selectionIndex == -1)
- {
- headerText.setText("Select a message to view its header.");
- redeliveredText.setText("-");
- viewSelectedMsgButton.setEnabled(false);
- if(moveMessagesButton != null)
- {
- moveMessagesButton.setEnabled(false);
- }
- if(copyMessagesButton != null)
- {
- copyMessagesButton.setEnabled(false);
- }
- if(deleteMessagesButton != null)
- {
- deleteMessagesButton.setEnabled(false);
- }
-
- return;
- }
- else
- {
- if(moveMessagesButton != null)
- {
- moveMessagesButton.setEnabled(true);
- }
- if(copyMessagesButton != null)
- {
- copyMessagesButton.setEnabled(true);
- }
- if(deleteMessagesButton != null)
- {
- deleteMessagesButton.setEnabled(true);
- }
-
- final CompositeData selectedMsg = (CompositeData)_table.getItem(selectionIndex).getData();
- Boolean redelivered = (Boolean) selectedMsg.get(MSG_REDELIVERED);
- redeliveredText.setText(redelivered.toString());
-
- String[] msgHeader = (String[]) selectedMsg.get(MSG_HEADER);
- headerText.setText("");
- String lineSeperator = System.getProperty("line.separator");
- int size = msgHeader.length;
- for(int i=0; i < size; i++)
- {
- headerText.append(msgHeader[i]);
- if(!(i == size - 1))
- {
- headerText.append(lineSeperator);
- }
- }
- headerText.setSelection(0);
- }
-
- if (_table.getSelectionCount() > 1)
- {
- viewSelectedMsgButton.setEnabled(false);
- }
- else
- {
- viewSelectedMsgButton.setEnabled(true);
- }
-
- }
- });
-
- }
-
- /**
- * Content Provider class for the table viewer
- */
- private static class ContentProviderImpl implements IStructuredContentProvider
- {
-
- public void inputChanged(Viewer v, Object oldInput, Object newInput)
- {
-
- }
-
- public void dispose()
- {
-
- }
-
- public Object[] getElements(Object parent)
- {
- Collection<Object> rowCollection = ((TabularDataSupport) parent).values();
-
- return rowCollection.toArray();
- }
- }
-
- /**
- * Label Provider class for the table viewer
- */
- private static class LabelProviderImpl extends LabelProvider implements ITableLabelProvider
- {
- public String getColumnText(Object element, int columnIndex)
- {
- switch (columnIndex)
- {
- case 0 : // msg id column
- return String.valueOf(((CompositeDataSupport) element).get(MSG_AMQ_ID));
- case 1 : // msg size column
- return String.valueOf(((CompositeDataSupport) element).get(MSG_SIZE));
- case 2 : // msg position in queue
- return String.valueOf(((CompositeDataSupport) element).get(MSG_QUEUE_POS));
- default :
- return "-";
- }
- }
-
- public Image getColumnImage(Object element, int columnIndex)
- {
- return null;
- }
-
- }
-
- /**
- * Sorter class for the table viewer.
- *
- */
- public static class TableSorter extends ViewerSorter
- {
- private int column;
- private static final int ASCENDING = 0;
- private static final int DESCENDING = 1;
-
- private int direction = DESCENDING;
-
- public TableSorter()
- {
- this.column = 0;
- direction = ASCENDING;
- }
-
- public void setColumn(int column)
- {
- if (column == this.column)
- {
- // Same column as last sort; toggle the direction
- direction = 1 - direction;
- }
- else
- {
- // New column; do an ascending sort
- this.column = column;
- direction = ASCENDING;
- }
- }
-
- @Override
- public int compare(Viewer viewer, Object e1, Object e2)
- {
- CompositeData msg1 = (CompositeData) e1;
- CompositeData msg2 = (CompositeData) e2;
-
- int comparison = 0;
- switch(column)
- {
- case 0:
- comparison = ((Long) msg1.get(MSG_AMQ_ID)).compareTo((Long)msg2.get(MSG_AMQ_ID));
- break;
- case 1:
- comparison = ((Long) msg1.get(MSG_SIZE)).compareTo((Long)msg2.get(MSG_SIZE));
- break;
- case 2:
- comparison = ((Long) msg1.get(MSG_QUEUE_POS)).compareTo((Long)msg2.get(MSG_QUEUE_POS));
- break;
- default:
- comparison = 0;
- }
- // If descending order, flip the direction
- if(direction == DESCENDING)
- {
- comparison = -comparison;
- }
- return comparison;
- }
- }
-
- private void updateMessageInterval()
- {
- Long from;
- try
- {
- from = Long.valueOf(_fromMsgText.getText());
- }
- catch(Exception e1)
- {
- ViewUtility.popupErrorMessage("Invalid Value", "Please enter a valid 'from' number");
- return;
- }
-
- Long to;
- try
- {
- to = Long.valueOf(_toMsgText.getText());
- }
- catch(Exception e1)
- {
- ViewUtility.popupErrorMessage("Invalid Value", "Please enter a valid 'to' number");
- return;
- }
-
- _fromMsg = from;
- _toMsg = to;
-
- _interval = (to - from) + 1;
- _previousButton.setText("< Prev " + _interval);
- _nextButton.setText("Next " + _interval + " >");
-
- refresh(_mbean);
- }
-
- private void viewMessageContent()
- {
- int selectionIndex = _table.getSelectionIndex();
-
- if (selectionIndex != -1)
- {
- try
- {
- final CompositeData selectedMsg = (CompositeData)_table.getItem(selectionIndex).getData();
- Long msgId = (Long) selectedMsg.get(MSG_AMQ_ID);
-
- Object result = _qmb.viewMessageContent(msgId);
-
- populateResults(result);
- }
- catch (Exception e3)
- {
- MBeanUtility.handleException(_mbean, e3);
- }
- }
- }
-
- private void populateResults(Object result)
- {
- Display display = Display.getCurrent();
- int width = 610;
- int height = 400;
- Shell shell = ViewUtility.createPopupShell(RESULT, width, height);
- shell.setImage(ApplicationRegistry.getImage(CONSOLE_IMAGE));
- ViewUtility.populateCompositeWithData(_toolkit, shell, result);
-
- shell.open();
- while (!shell.isDisposed())
- {
- if (!display.readAndDispatch())
- {
- display.sleep();
- }
- }
- shell.dispose();
- }
-
- private void moveOrCopyMessages(final Shell parent, final QueueOperations op)
- {
- final ArrayList<Long> rangeStarts = new ArrayList<Long>();
- final ArrayList<Long> rangeEnds = new ArrayList<Long>();
-
- gatherSelectedAMQMsgIDRanges(rangeStarts,rangeEnds);
- String rangeString = getRangesString(rangeStarts,rangeEnds);
-
- String windowTitle;
- String dialogueMessage;
- final String feedBackMessage;
- final String failureFeedBackMessage;
-
- if(op.equals(QueueOperations.MOVE))
- {
- windowTitle = "Move Messages";
- dialogueMessage = "Move message(s) with AMQ ID:";
- feedBackMessage = "Messages moved";
- failureFeedBackMessage = "Error moving messages";
- }
- else
- {
- windowTitle = "Copy Messages";
- dialogueMessage = "Copy message(s) with AMQ ID:";
- feedBackMessage = "Messages copied";
- failureFeedBackMessage = "Error copying messages";
- }
-
- final Shell shell = ViewUtility.createModalDialogShell(parent, windowTitle);
-
- Composite idComposite = _toolkit.createComposite(shell, SWT.NONE);
- idComposite.setBackground(shell.getBackground());
- idComposite.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
- idComposite.setLayout(new GridLayout());
-
- _toolkit.createLabel(idComposite,dialogueMessage).setBackground(shell.getBackground());
- _toolkit.createLabel(idComposite,rangeString).setBackground(shell.getBackground());
-
- Composite destinationComposite = _toolkit.createComposite(shell, SWT.NONE);
- destinationComposite.setBackground(shell.getBackground());
- destinationComposite.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
- destinationComposite.setLayout(new GridLayout(2,false));
-
- _toolkit.createLabel(destinationComposite,"To Queue:").setBackground(shell.getBackground());
- final Combo destinationCombo = new Combo(destinationComposite,SWT.NONE | SWT.READ_ONLY);
- destinationCombo.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
-
- Composite okCancelButtonsComp = _toolkit.createComposite(shell);
- okCancelButtonsComp.setBackground(shell.getBackground());
- okCancelButtonsComp.setLayoutData(new GridData(SWT.RIGHT, SWT.FILL, true, true));
- okCancelButtonsComp.setLayout(new GridLayout(2,false));
-
- Button okButton = _toolkit.createButton(okCancelButtonsComp, "OK", SWT.PUSH);
- okButton.setLayoutData(new GridData(SWT.RIGHT, SWT.TOP, false, false));
- Button cancelButton = _toolkit.createButton(okCancelButtonsComp, "Cancel", SWT.PUSH);
- cancelButton.setLayoutData(new GridData(SWT.RIGHT, SWT.TOP, false, false));
-
- List<String> queueList = ApplicationRegistry.getServerRegistry(_mbean).getQueueNames(_mbean.getVirtualHostName());
- queueList.remove(_mbean.getName());
-
- if(queueList.size() == 0)
- {
- destinationCombo.setItems(new String[]{"No other queues available"});
- okButton.setEnabled(false);
- }
- else
- {
- Collections.sort(queueList);
- destinationCombo.setItems(queueList.toArray(new String[0]));
- }
- destinationCombo.select(0);
-
- okButton.addSelectionListener(new SelectionAdapter()
- {
- public void widgetSelected(SelectionEvent e)
- {
- String destQueue = destinationCombo.getItem(destinationCombo.getSelectionIndex()).toString();
- shell.dispose();
-
- try
- {
- for(int i=0 ; i < rangeStarts.size() ; i++)
- {
- Long from = rangeStarts.get(i);
- Long to = rangeEnds.get(i);
-
- switch(op)
- {
- case COPY:
- _qmb.copyMessages(Long.valueOf(from), Long.valueOf(to), destQueue);
- break;
- case MOVE:
- _qmb.moveMessages(Long.valueOf(from), Long.valueOf(to), destQueue);
- break;
- }
- }
-
- ViewUtility.operationResultFeedback(null, feedBackMessage, null);
- }
- catch (Exception e4)
- {
- ViewUtility.operationFailedStatusBarMessage(failureFeedBackMessage);
- MBeanUtility.handleException(_mbean, e4);
- }
-
- refresh(_mbean);
- }
- });
-
- cancelButton.addSelectionListener(new SelectionAdapter()
- {
- public void widgetSelected(SelectionEvent e)
- {
- shell.dispose();
- }
- });
-
- shell.setDefaultButton(okButton);
- shell.pack();
- ViewUtility.centerChildInParentShell(parent, shell);
-
- shell.open();
- }
-
- private void deleteMessages(final Shell parent)
- {
- final ArrayList<Long> rangeStarts = new ArrayList<Long>();
- final ArrayList<Long> rangeEnds = new ArrayList<Long>();
-
- gatherSelectedAMQMsgIDRanges(rangeStarts,rangeEnds);
- String rangeString = getRangesString(rangeStarts,rangeEnds);
-
- final Shell shell = ViewUtility.createModalDialogShell(parent, "Delete Messages");
-
- Composite idComposite = _toolkit.createComposite(shell, SWT.NONE);
- idComposite.setBackground(shell.getBackground());
- idComposite.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
- idComposite.setLayout(new GridLayout());
-
- _toolkit.createLabel(idComposite,"Delete message(s) with AMQ ID:").setBackground(shell.getBackground());
- _toolkit.createLabel(idComposite,rangeString).setBackground(shell.getBackground());
-
- Composite okCancelButtonsComp = _toolkit.createComposite(shell);
- okCancelButtonsComp.setBackground(shell.getBackground());
- okCancelButtonsComp.setLayoutData(new GridData(SWT.RIGHT, SWT.FILL, true, true));
- okCancelButtonsComp.setLayout(new GridLayout(2,false));
-
- Button okButton = _toolkit.createButton(okCancelButtonsComp, "OK", SWT.PUSH);
- okButton.setLayoutData(new GridData(SWT.RIGHT, SWT.TOP, false, false));
- Button cancelButton = _toolkit.createButton(okCancelButtonsComp, "Cancel", SWT.PUSH);
- cancelButton.setLayoutData(new GridData(SWT.RIGHT, SWT.TOP, false, false));
-
- okButton.addSelectionListener(new SelectionAdapter()
- {
- public void widgetSelected(SelectionEvent e)
- {
- shell.dispose();
-
- try
- {
- for(int i=0 ; i < rangeStarts.size() ; i++)
- {
- Long from = rangeStarts.get(i);
- Long to = rangeEnds.get(i);
-
- _qmb.deleteMessages(Long.valueOf(from), Long.valueOf(to));
- }
-
- ViewUtility.operationResultFeedback(null, "Messages deleted", null);
- }
- catch (Exception e4)
- {
- ViewUtility.operationFailedStatusBarMessage("Error deleting messages");
- MBeanUtility.handleException(_mbean, e4);
- }
-
- refresh(_mbean);
- }
- });
-
- cancelButton.addSelectionListener(new SelectionAdapter()
- {
- public void widgetSelected(SelectionEvent e)
- {
- shell.dispose();
- }
- });
-
- shell.setDefaultButton(okButton);
- shell.pack();
- ViewUtility.centerChildInParentShell(parent, shell);
-
- shell.open();
- }
-
- private void gatherSelectedAMQMsgIDRanges(ArrayList<Long> starts, ArrayList<Long> ends)
- {
- SortedSet<Long> amqIDs = new TreeSet<Long>();
-
- for(Integer i : _table.getSelectionIndices())
- {
- CompositeData selectedMsg = (CompositeData)_table.getItem(i).getData();
- amqIDs.add((Long)selectedMsg.get(MSG_AMQ_ID));
- }
-
- //initialise the first range
- Long start = amqIDs.first();
- Long end = amqIDs.first();
-
- for(Long id : amqIDs)
- {
- if(id == amqIDs.first())
- {
- //skip first check, already initialised range
- continue;
- }
-
- if(id == end +1)
- {
- //part of previous range, append
- end = id;
- }
- else
- {
- //not in previous range, record existing start and end msg id values
- starts.add(start);
- ends.add(end);
-
- //begin new range with this msg id
- start = id;
- end = id;
- }
- }
-
- //record the last range created
- starts.add(start);
- ends.add(end);
- }
-
- private String getRangesString(ArrayList<Long> starts, ArrayList<Long> ends)
- {
- String idRangesString = "";
-
- for(int i=0 ; i < starts.size() ; i++)
- {
- long start = starts.get(i);
- long end = ends.get(i);
-
- if(i != 0)
- {
- idRangesString = idRangesString.concat(", ");
- }
-
- if(start == end)
- {
- idRangesString = idRangesString.concat(String.valueOf(starts.get(i)));
- }
- else
- {
- idRangesString = idRangesString.concat(starts.get(i) + "-" + ends.get(i));
- }
- }
-
- return idRangesString.concat(".");
- }
-
- private enum QueueOperations
- {
- MOVE,
- COPY;
- }
-}
diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/type/ConnectionTypeTabControl.java b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/type/ConnectionTypeTabControl.java
deleted file mode 100644
index 37bd17c3c3..0000000000
--- a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/type/ConnectionTypeTabControl.java
+++ /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.
- *
- */
-package org.apache.qpid.management.ui.views.type;
-
-import org.eclipse.swt.widgets.TabFolder;
-
-import org.apache.qpid.management.ui.ManagedBean;
-import org.apache.qpid.management.ui.ManagedServer;
-
-import static org.apache.qpid.management.ui.Constants.CONNECTION;
-
-import java.util.List;
-
-/**
- * Controller class, which takes care of displaying appropriate information and widgets for Connections.
- * This allows user to select Connections and add those to the navigation view
- */
-
-public class ConnectionTypeTabControl extends MBeanTypeTabControl
-{
-
- public ConnectionTypeTabControl(TabFolder tabFolder, ManagedServer server, String virtualHost)
- {
- super(tabFolder, server, virtualHost, CONNECTION);
- }
-
- @Override
- protected List<ManagedBean> getMbeans()
- {
- return getServerRegistry().getConnections(getVirtualHost());
- }
-
-}
diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/type/MBeanTypeTabControl.java b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/type/MBeanTypeTabControl.java
deleted file mode 100644
index 17d430efee..0000000000
--- a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/type/MBeanTypeTabControl.java
+++ /dev/null
@@ -1,521 +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.type;
-
-
-import org.eclipse.jface.viewers.ISelectionChangedListener;
-import org.eclipse.jface.viewers.IStructuredContentProvider;
-import org.eclipse.jface.viewers.ITableLabelProvider;
-import org.eclipse.jface.viewers.LabelProvider;
-import org.eclipse.jface.viewers.SelectionChangedEvent;
-import org.eclipse.jface.viewers.TableViewer;
-import org.eclipse.jface.viewers.TableViewerColumn;
-import org.eclipse.jface.viewers.Viewer;
-import org.eclipse.jface.viewers.ViewerSorter;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.events.MouseEvent;
-import org.eclipse.swt.events.MouseListener;
-import org.eclipse.swt.events.SelectionAdapter;
-import org.eclipse.swt.events.SelectionEvent;
-import org.eclipse.swt.graphics.Image;
-import org.eclipse.swt.layout.GridData;
-import org.eclipse.swt.layout.GridLayout;
-import org.eclipse.swt.widgets.Button;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Control;
-import org.eclipse.swt.widgets.TabFolder;
-import org.eclipse.swt.widgets.Table;
-import org.eclipse.swt.widgets.TableColumn;
-import org.eclipse.ui.IWorkbenchWindow;
-import org.eclipse.ui.PlatformUI;
-import org.eclipse.ui.forms.widgets.Form;
-import org.eclipse.ui.forms.widgets.FormToolkit;
-
-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.ui.ManagedServer;
-import org.apache.qpid.management.ui.jmx.JMXManagedObject;
-import org.apache.qpid.management.ui.jmx.JMXServerRegistry;
-import org.apache.qpid.management.ui.jmx.MBeanUtility;
-import org.apache.qpid.management.ui.views.MBeanView;
-import org.apache.qpid.management.ui.views.NavigationView;
-import org.apache.qpid.management.ui.views.TabControl;
-
-import java.util.ArrayList;
-import java.util.List;
-
-public abstract class MBeanTypeTabControl extends TabControl
-{
- private FormToolkit _toolkit;
- private Form _form;
- private Table _table = null;
- private TableViewer _tableViewer = null;
-
- private List<ManagedBean> _mbeanList = null;
- private String _type;
- private ApiVersion _ApiVersion;
- private JMXManagedObject _vhostMbean;
- private String _virtualHost;
- private JMXServerRegistry _serverRegistry;
- private Composite _tableComposite;
- private Button _favouritesButton;
- private Button _openButton;
-
- public MBeanTypeTabControl(TabFolder tabFolder, ManagedServer server, String virtualHost, String type)
- {
- super(tabFolder);
- _virtualHost = virtualHost;
- _serverRegistry = (JMXServerRegistry) ApplicationRegistry.getServerRegistry(server);
- _ApiVersion = _serverRegistry.getManagementApiVersion();
- _vhostMbean = (JMXManagedObject) _serverRegistry.getVirtualHostManagerMBean(_virtualHost);
- _type = type;
- _toolkit = new FormToolkit(_tabFolder.getDisplay());
- _form = _toolkit.createForm(_tabFolder);
- _form.getBody().setLayout(new GridLayout());
- init();
- createWidgets();
- }
-
- protected void init()
- {
-
- }
-
- /**
- * @see TabControl#getControl()
- */
- public Control getControl()
- {
- return _form;
- }
-
- /**
- * @see TabControl#setFocus()
- */
- public void setFocus()
- {
- _table.setFocus();
- }
-
- public void refresh()
- {
- refresh(null);
- }
-
-
- @Override
- public void refresh(ManagedBean mbean)
- {
- _mbeanList = getMbeans();
-
- _tableViewer.setInput(_mbeanList);
-
- layout();
- }
-
- public void layout()
- {
- _form.layout(true);
- _form.getBody().layout(true, true);
- }
-
- protected abstract List<ManagedBean> getMbeans();
-
- protected void createTable()
- {
- _table = new Table (_tableComposite, SWT.MULTI | SWT.SCROLL_LINE | SWT.BORDER | SWT.FULL_SELECTION);
- _table.setLinesVisible (true);
- _table.setHeaderVisible (true);
- GridData data = new GridData(SWT.FILL, SWT.FILL, true, true);
- _table.setLayoutData(data);
-
- _tableViewer = new TableViewer(_table);
- final TableSorter tableSorter = new TableSorter();
-
- String[] titles = { "Name"};
- int[] bounds = { 310};
- for (int i = 0; i < titles.length; i++)
- {
- final int index = i;
- final TableViewerColumn viewerColumn = new TableViewerColumn(_tableViewer, SWT.NONE);
- final TableColumn column = viewerColumn.getColumn();
-
- column.setText(titles[i]);
- column.setWidth(bounds[i]);
- column.setResizable(true);
-
- //Setting the right sorter
- column.addSelectionListener(new SelectionAdapter()
- {
- @Override
- public void widgetSelected(SelectionEvent e)
- {
- tableSorter.setColumn(index);
- final TableViewer viewer = _tableViewer;
- int dir = viewer .getTable().getSortDirection();
- if (viewer.getTable().getSortColumn() == column)
- {
- dir = dir == SWT.UP ? SWT.DOWN : SWT.UP;
- }
- else
- {
- dir = SWT.UP;
- }
- viewer.getTable().setSortDirection(dir);
- viewer.getTable().setSortColumn(column);
- viewer.refresh();
- }
- });
-
- }
-
- _tableViewer.setContentProvider(new ContentProviderImpl());
- _tableViewer.setLabelProvider(new LabelProviderImpl());
- _tableViewer.setSorter(tableSorter);
- _table.setSortColumn(_table.getColumn(0));
- _table.setSortDirection(SWT.UP);
-
- addTableListeners();
- }
-
- protected void addTableListeners()
- {
- _favouritesButton.setEnabled(false);
- _openButton.setEnabled(false);
-
- _tableViewer.addSelectionChangedListener(new ISelectionChangedListener(){
- public void selectionChanged(SelectionChangedEvent evt)
- {
- int selectionIndex = _table.getSelectionIndex();
-
- if (selectionIndex == -1)
- {
- _favouritesButton.setEnabled(false);
- _openButton.setEnabled(false);
- return;
- }
- else
- {
- _favouritesButton.setEnabled(true);
- }
-
- if(_table.getSelectionCount() > 1)
- {
- _openButton.setEnabled(false);
- }
- else
- {
- _openButton.setEnabled(true);
- }
- }
- });
-
- _table.addMouseListener(new MouseListener()
- {
- // MouseListener implementation
- public void mouseDoubleClick(MouseEvent event)
- {
- openMBean();
- }
-
- public void mouseDown(MouseEvent e){}
- public void mouseUp(MouseEvent e){}
- });
- }
-
-
- private void createWidgets()
- {
- Composite mainComposite = _toolkit.createComposite(_form.getBody(), SWT.NONE);
- mainComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
- mainComposite.setLayout(new GridLayout());
-
- Composite buttonComposite = _toolkit.createComposite(mainComposite, SWT.NONE);
- GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, false);
- buttonComposite.setLayoutData(gridData);
- buttonComposite.setLayout(new GridLayout(2,true));
-
- _favouritesButton = _toolkit.createButton(buttonComposite,
- "<-- Add " + _type + "(s) to favourites", SWT.PUSH);
- gridData = new GridData(SWT.LEFT, SWT.CENTER, true, false);
- _favouritesButton.setLayoutData(gridData);
- _favouritesButton.addSelectionListener(new SelectionAdapter()
- {
- public void widgetSelected(SelectionEvent e)
- {
- addMBeanToFavourites();
- }
- });
-
- _openButton = _toolkit.createButton(buttonComposite, "Open selected " + _type, SWT.PUSH);
- gridData = new GridData(SWT.RIGHT, SWT.CENTER, true, false);
- _openButton.setLayoutData(gridData);
- _openButton.addSelectionListener(new SelectionAdapter()
- {
- public void widgetSelected(SelectionEvent e)
- {
- openMBean();
- }
- });
-
- _tableComposite = _toolkit.createComposite(mainComposite);
- gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
- _tableComposite.setLayoutData(gridData);
- _tableComposite.setLayout(new GridLayout(1,false));
-
- createTable();
-
- createLowerAreaButton(mainComposite);
- }
-
- protected void createLowerAreaButton(Composite parent)
- {
-
- }
-
- protected FormToolkit getToolkit()
- {
- return _toolkit;
- }
-
- protected Table getTable()
- {
- return _table;
- }
-
- protected void setTable(Table table)
- {
- _table = table;
- }
-
- protected TableViewer getTableViewer()
- {
- return _tableViewer;
- }
-
- protected void setTableViewer(TableViewer tableViewer)
- {
- _tableViewer = tableViewer;
- }
-
- protected List<ManagedBean> getMbeanList()
- {
- return _mbeanList;
- }
-
- protected void setMbeanList(List<ManagedBean> mbeanList)
- {
- _mbeanList = mbeanList;
- }
-
- protected String getType()
- {
- return _type;
- }
-
- protected ApiVersion getApiVersion()
- {
- return _ApiVersion;
- }
-
- protected JMXManagedObject getVhostMbean()
- {
- return _vhostMbean;
- }
-
- protected String getVirtualHost()
- {
- return _virtualHost;
- }
-
- protected JMXServerRegistry getServerRegistry()
- {
- return _serverRegistry;
- }
-
- protected Composite getTableComposite()
- {
- return _tableComposite;
- }
-
- /**
- * Content Provider class for the table viewer
- */
- private static class ContentProviderImpl implements IStructuredContentProvider
- {
-
- public void inputChanged(Viewer v, Object oldInput, Object newInput)
- {
-
- }
-
- public void dispose()
- {
-
- }
-
- @SuppressWarnings("unchecked")
- public Object[] getElements(Object parent)
- {
- return ((List<ManagedBean>) parent).toArray();
- }
- }
-
- /**
- * Label Provider class for the table viewer
- */
- private static class LabelProviderImpl extends LabelProvider implements ITableLabelProvider
- {
- public String getColumnText(Object element, int columnIndex)
- {
- switch (columnIndex)
- {
- case 0 : // name column
- return ((ManagedBean) element).getName();
- default:
- return "-";
- }
- }
-
- public Image getColumnImage(Object element, int columnIndex)
- {
- return null;
- }
-
- }
-
- /**
- * Sorter class for the table viewer.
- *
- */
- private static class TableSorter extends ViewerSorter
- {
- private int column;
- private static final int ASCENDING = 0;
- private static final int DESCENDING = 1;
-
- private int direction;
-
- public TableSorter()
- {
- this.column = 0;
- direction = ASCENDING;
- }
-
- public void setColumn(int column)
- {
- if(column == this.column)
- {
- // Same column as last sort; toggle the direction
- direction = 1 - direction;
- }
- else
- {
- // New column; do an ascending sort
- this.column = column;
- direction = ASCENDING;
- }
- }
-
- @Override
- public int compare(Viewer viewer, Object e1, Object e2)
- {
- ManagedBean mbean1 = (ManagedBean) e1;
- ManagedBean mbean2 = (ManagedBean) e2;
-
- int comparison = 0;
- switch(column)
- {
- case 0:
- comparison = mbean1.getName().compareTo(mbean2.getName());
- break;
- default:
- comparison = 0;
- }
- // If descending order, flip the direction
- if(direction == DESCENDING)
- {
- comparison = -comparison;
- }
- return comparison;
- }
- }
-
- protected void addMBeanToFavourites()
- {
- int selectionIndex = _table.getSelectionIndex();
-
- if (selectionIndex == -1)
- {
- return;
- }
-
- int[] selectedIndices = _table.getSelectionIndices();
-
- ArrayList<ManagedBean> selectedMBeans = new ArrayList<ManagedBean>();
-
- for(int index = 0; index < selectedIndices.length ; index++)
- {
- ManagedBean selectedMBean = (ManagedBean)_table.getItem(selectedIndices[index]).getData();
- selectedMBeans.add(selectedMBean);
- }
-
- IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
- NavigationView view = (NavigationView)window.getActivePage().findView(NavigationView.ID);
-
- ManagedBean bean = null;
- try
- {
- for(ManagedBean mbean: selectedMBeans)
- {
- view.addManagedBean(mbean);
- }
- }
- catch (Exception ex)
- {
- MBeanUtility.handleException(bean, ex);
- }
- }
-
- protected void openMBean()
- {
- int selectionIndex = _table.getSelectionIndex();
-
- if (selectionIndex == -1)
- {
- return;
- }
-
- final ManagedBean selectedMBean = (ManagedBean)_table.getItem(selectionIndex).getData();
-
- IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
- MBeanView view = (MBeanView) window.getActivePage().findView(MBeanView.ID);
- try
- {
- view.openMBean(selectedMBean);
- }
- catch (Exception ex)
- {
- MBeanUtility.handleException(selectedMBean, ex);
- }
- }
-}
diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/type/QueueTypeTabControl.java b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/type/QueueTypeTabControl.java
deleted file mode 100644
index 6cf9981c9e..0000000000
--- a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/type/QueueTypeTabControl.java
+++ /dev/null
@@ -1,774 +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.type;
-
-import org.eclipse.jface.preference.PreferenceStore;
-import org.eclipse.jface.viewers.IStructuredContentProvider;
-import org.eclipse.jface.viewers.ITableLabelProvider;
-import org.eclipse.jface.viewers.LabelProvider;
-import org.eclipse.jface.viewers.TableViewer;
-import org.eclipse.jface.viewers.TableViewerColumn;
-import org.eclipse.jface.viewers.Viewer;
-import org.eclipse.jface.viewers.ViewerSorter;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.events.SelectionAdapter;
-import org.eclipse.swt.events.SelectionEvent;
-import org.eclipse.swt.graphics.Image;
-import org.eclipse.swt.layout.GridData;
-import org.eclipse.swt.layout.GridLayout;
-import org.eclipse.swt.widgets.Button;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Shell;
-import org.eclipse.swt.widgets.TabFolder;
-import org.eclipse.swt.widgets.Table;
-import org.eclipse.swt.widgets.TableColumn;
-import org.eclipse.ui.IWorkbenchWindow;
-import org.eclipse.ui.PlatformUI;
-
-import org.apache.qpid.management.common.mbeans.ManagedBroker;
-import org.apache.qpid.management.common.mbeans.ManagedQueue;
-import org.apache.qpid.management.ui.ApplicationRegistry;
-import org.apache.qpid.management.ui.ManagedBean;
-import org.apache.qpid.management.ui.ManagedServer;
-import org.apache.qpid.management.ui.jmx.MBeanUtility;
-import org.apache.qpid.management.ui.views.MBeanView;
-import org.apache.qpid.management.ui.views.NavigationView;
-import org.apache.qpid.management.ui.views.ViewUtility;
-
-import static org.apache.qpid.management.common.mbeans.ManagedQueue.*;
-import static org.apache.qpid.management.ui.ApplicationRegistry.DATA_DIR;
-import static org.apache.qpid.management.ui.Constants.QUEUE;
-
-import javax.management.MBeanServerConnection;
-import javax.management.MBeanServerInvocationHandler;
-import java.io.File;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.Semaphore;
-
-public class QueueTypeTabControl extends MBeanTypeTabControl
-{
- private MBeanServerConnection _mbsc;
- private ManagedBroker _vhmb;
-
- private List<String> _selectedAttributes;
- private PreferenceStore _preferences;
- private Semaphore _tableViewerSemaphore = new Semaphore(1);
-
- private static final String APP_DIR = ApplicationRegistry.DATA_DIR;
- private static final String INI_FILENAME = APP_DIR + File.separator + "qpidmc_queue_attributes.ini";
- private static final String INI_QUEUE_ATTRIBUES = "QueueAttributesSelection";
-
- private static final ArrayList<String> FALLBACK_ATTRIBUTES_LIST = new ArrayList<String>();
- static
- {
- FALLBACK_ATTRIBUTES_LIST.add(ATTR_NAME);
- FALLBACK_ATTRIBUTES_LIST.add(ATTR_ACTIVE_CONSUMER_COUNT);
- FALLBACK_ATTRIBUTES_LIST.add(ATTR_AUTODELETE);
- FALLBACK_ATTRIBUTES_LIST.add(ATTR_CONSUMER_COUNT);
- FALLBACK_ATTRIBUTES_LIST.add(ATTR_DURABLE);
- FALLBACK_ATTRIBUTES_LIST.add(ATTR_MAX_MSG_AGE);
- FALLBACK_ATTRIBUTES_LIST.add(ATTR_MAX_MSG_COUNT);
- FALLBACK_ATTRIBUTES_LIST.add(ATTR_MAX_MSG_SIZE);
- FALLBACK_ATTRIBUTES_LIST.add(ATTR_MAX_QUEUE_DEPTH);
- FALLBACK_ATTRIBUTES_LIST.add(ATTR_MSG_COUNT);
- FALLBACK_ATTRIBUTES_LIST.add(ATTR_OWNER);
- FALLBACK_ATTRIBUTES_LIST.add(ATTR_QUEUE_DEPTH);
- FALLBACK_ATTRIBUTES_LIST.add(ATTR_RCVD_MSG_COUNT);
- }
-
- private static final Map<String, Integer> DEFAULT_COLUMN_WIDTHS = new HashMap<String,Integer>();
- static
- {
- DEFAULT_COLUMN_WIDTHS.put(ATTR_NAME, 215);
- DEFAULT_COLUMN_WIDTHS.put(ATTR_OWNER,125);
- DEFAULT_COLUMN_WIDTHS.put(ATTR_QUEUE_DEPTH,125);
- }
-
- public QueueTypeTabControl(TabFolder tabFolder, ManagedServer server, String virtualHost)
- {
- super(tabFolder,server,virtualHost,QUEUE);
- _mbsc = (MBeanServerConnection) getServerRegistry().getServerConnection();
-
- //create a proxy for the VirtualHostManager mbean to use in retrieving the attribute names/values
- _vhmb = MBeanServerInvocationHandler.newProxyInstance(_mbsc,
- getVhostMbean().getObjectName(), ManagedBroker.class, false);
-
- }
-
- @Override
- protected void init()
- {
- createIniFileIfNecessary();
- loadAttributePreferences();
- }
-
- /**
- * Create the ini file if it doesn't already exist.
- */
- public static void createIniFileIfNecessary()
- {
- File dir = new File(DATA_DIR);
- if (!dir.exists())
- {
- if(!dir.mkdir())
- {
- System.err.println("Could not create application data directory " + DATA_DIR);
- ViewUtility.popupErrorMessage("Error", "Fatal Error: Unable to create the application data directory: " + DATA_DIR);
- System.exit(1);
- }
- }
-
- File file = new File(INI_FILENAME);
- try
- {
- if (!file.exists())
- {
- file.createNewFile();
- }
- }
- catch (IOException ex)
- {
- System.err.println("Error creating the configuration file " + INI_FILENAME);
- ViewUtility.popupErrorMessage("Error", "Fatal Error: Unable to create the configuration file: " + INI_FILENAME);
- System.exit(1);
- }
- }
-
- private void loadAttributePreferences()
- {
- _preferences = new PreferenceStore(INI_FILENAME);
- List<String> attributesList = new ArrayList<String>();
-
- //ensure the name is present, and first
- attributesList.add(ManagedQueue.ATTR_NAME);
-
- //add any others from the file
- try
- {
- _preferences.load();
-
- String selectedAttributes = _preferences.getString(INI_QUEUE_ATTRIBUES);
- if (selectedAttributes.length() != 0)
- {
- String[] attributes = selectedAttributes.split(",");
- for (String attr : attributes)
- {
- if(attr.equals(ManagedQueue.ATTR_NAME))
- {
- //the Name attribute is already present
- continue;
- }
-
- attributesList.add(attr);
- }
- }
- }
- catch (IOException e)
- {
- ViewUtility.popupErrorMessage("Error", "Unable to load previous attribute selections, defaulting to Name only");
- System.err.println(e);
- }
-
- _selectedAttributes = attributesList;
- }
-
- private void saveAttributePreferences()
- {
- String chosenAttributes = new String();
-
- for(String attr : _selectedAttributes)
- {
- chosenAttributes = chosenAttributes.concat(attr) + ",";
- }
- //cut off last ","
- int lastIndex = chosenAttributes.lastIndexOf(',');
- if (lastIndex != -1)
- {
- chosenAttributes = chosenAttributes.substring(0,lastIndex);
- }
-
- _preferences.putValue(INI_QUEUE_ATTRIBUES, chosenAttributes);
-
- try
- {
- _preferences.save();
- }
- catch (IOException e)
- {
- ViewUtility.popupErrorMessage("Error", "Unable to save the attribute selection, choices will be lost at shutdown");
- System.err.println(e);
- }
- }
-
- @Override
- public void refresh(ManagedBean mbean)
- {
- //Try locking. If we cant aquire the lock, dont bother getting new values.
- //Either the attributes are being changed and these values would be out of date,
- //or another thread is still in the process of refreshing
- if(_tableViewerSemaphore.tryAcquire())
- {
- try
- {
- List<List<Object>> values = null;
-
- if(getApiVersion().greaterThanOrEqualTo(1, 3))
- {
- //Qpid JMX API 1.3+, use this virtualhosts VirtualHostManager MBean
- //to retrieve the attributes values requested for all queues at once
- try
- {
- values = _vhmb.retrieveQueueAttributeValues(_selectedAttributes.toArray(new String[0]));
- }
- catch(Exception e)
- {
- MBeanUtility.handleException(getVhostMbean(), e);
- }
- }
- else
- {
- //Qpid JMX API 1.2 or below, use the local ManagedBeans and look
- //up the attribute values for each queue individually
- setMbeanList(getMbeans());
- values = MBeanUtility.getQueueAttributes(getMbeanList(), _selectedAttributes.toArray(new String[0]));
- }
-
- getTableViewer().setInput(values);
- layout();
- }
- finally
- {
- _tableViewerSemaphore.release();
- }
- }
-
- }
-
- @Override
- protected List<ManagedBean> getMbeans()
- {
- return getServerRegistry().getQueues(getVirtualHost());
- }
-
- private void clearTableComposite()
- {
- ViewUtility.disposeChildren(getTableComposite());
- }
-
- @Override
- protected void createTable()
- {
- setTable(new Table (getTableComposite(), SWT.MULTI | SWT.SCROLL_LINE | SWT.BORDER | SWT.FULL_SELECTION));
- getTable().setLinesVisible(true);
- getTable().setHeaderVisible(true);
- GridData data = new GridData(SWT.FILL, SWT.FILL, true, true);
- getTable().setLayoutData(data);
-
- setTableViewer(new TableViewer(getTable()));
-
- final QueueTableSorter tableSorter = new QueueTableSorter();
-
- for (int i = 0; i < _selectedAttributes.size(); i++)
- {
- final int index = i;
- final TableViewerColumn viewerColumn = new TableViewerColumn(getTableViewer(), SWT.NONE);
- final TableColumn column = viewerColumn.getColumn();
-
- String attrName = _selectedAttributes.get(i);
- column.setMoveable(true);
- column.setText(attrName);
- column.pack();
- if(DEFAULT_COLUMN_WIDTHS.containsKey(attrName))
- {
- //retrieve the desired default width
- column.setWidth(DEFAULT_COLUMN_WIDTHS.get(attrName));
- }
- else
- {
- //add padding for sort direction indicator
- column.setWidth(column.getWidth() + 15);
- }
- column.setResizable(true);
-
- //Setting the right sorter
- column.addSelectionListener(new SelectionAdapter()
- {
- @Override
- public void widgetSelected(SelectionEvent e)
- {
- tableSorter.setColumn(index);
- final TableViewer viewer = getTableViewer();
- int dir = viewer .getTable().getSortDirection();
- if (viewer.getTable().getSortColumn() == column)
- {
- dir = dir == SWT.UP ? SWT.DOWN : SWT.UP;
- }
- else
- {
- dir = SWT.UP;
- }
- viewer.getTable().setSortDirection(dir);
- viewer.getTable().setSortColumn(column);
- viewer.refresh();
- }
- });
-
- }
-
- getTableViewer().setContentProvider(new QueueContentProviderImpl());
- getTableViewer().setLabelProvider(new QueueLabelProviderImpl());
-
- getTableViewer().setUseHashlookup(true);
- getTableViewer().setSorter(tableSorter);
- getTable().setSortColumn(getTable().getColumn(0));
- getTable().setSortDirection(SWT.UP);
-
- addTableListeners();
- }
-
- protected void createLowerAreaButton(Composite parent)
- {
- Composite lowerButtonComposite = getToolkit().createComposite(parent, SWT.NONE);
- GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, false);
- lowerButtonComposite.setLayoutData(gridData);
- lowerButtonComposite.setLayout(new GridLayout());
-
- final Button attributesButton = getToolkit().createButton(lowerButtonComposite, "Select Attributes ...", SWT.PUSH);
- gridData = new GridData(SWT.RIGHT, SWT.CENTER, true, false);
- attributesButton.setLayoutData(gridData);
- attributesButton.addSelectionListener(new SelectionAdapter()
- {
- public void widgetSelected(SelectionEvent e)
- {
- chooseAttributes(attributesButton.getShell());
- }
- });
- }
-
- private void chooseAttributes(final Shell parent)
- {
-
- List<String> availableAttributes;
- if(getApiVersion().greaterThanOrEqualTo(1, 3))
- {
- //Qpid JMX API 1.3+, request the current queue attributes names from the broker
- try
- {
- availableAttributes = _vhmb.retrieveQueueAttributeNames();
- }
- catch (IOException e)
- {
- availableAttributes = new ArrayList<String>(FALLBACK_ATTRIBUTES_LIST);
- }
- }
- else
- {
- //Qpid JMX API 1.2 or below, use the falllback list of names.
- availableAttributes = new ArrayList<String>(FALLBACK_ATTRIBUTES_LIST);
- }
-
-
- final List<String> chosenAttributes = new ArrayList<String>();
-
- final Shell shell = ViewUtility.createModalDialogShell(parent, "Select Attributes");
-
- Composite attributesComposite = getToolkit().createComposite(shell, SWT.NONE);
- attributesComposite.setBackground(shell.getBackground());
- attributesComposite.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
- attributesComposite.setLayout(new GridLayout(2,false));
-
- //add a selected-but-disabled check box for the Name attribute (its a mandatory attribute)
- final Button nameCheckbox = new Button(attributesComposite, SWT.CHECK);
- nameCheckbox.setText(ManagedQueue.ATTR_NAME);
- nameCheckbox.setSelection(true);
- nameCheckbox.setEnabled(false);
-
- for(String attr : availableAttributes)
- {
- if(attr.equals(ManagedQueue.ATTR_NAME))
- {
- //Name attribute is mandatory and gets added to the front of the list later
- continue;
- }
-
- final Button attrButton = new Button(attributesComposite, SWT.CHECK);
- attrButton.setText(attr);
-
- //if it was checked before, select it again now
- if(_selectedAttributes.contains(attr))
- {
- attrButton.setSelection(true);
- chosenAttributes.add(attr);
- }
-
- //add a selection listener to update the selected attribute list
- attrButton.addSelectionListener(new SelectionAdapter()
- {
- public void widgetSelected(SelectionEvent e)
- {
- if(attrButton.getSelection())
- {
- chosenAttributes.add(attrButton.getText());
- }
- else
- {
- chosenAttributes.remove(attrButton.getText());
- }
- }
- });
- }
-
- Composite okCancelButtonsComp = getToolkit().createComposite(shell);
- okCancelButtonsComp.setBackground(shell.getBackground());
- okCancelButtonsComp.setLayoutData(new GridData(SWT.RIGHT, SWT.FILL, true, true));
- okCancelButtonsComp.setLayout(new GridLayout(2,false));
-
- Button okButton = getToolkit().createButton(okCancelButtonsComp, "OK", SWT.PUSH);
- okButton.setLayoutData(new GridData(SWT.RIGHT, SWT.TOP, false, false));
- Button cancelButton = getToolkit().createButton(okCancelButtonsComp, "Cancel", SWT.PUSH);
- cancelButton.setLayoutData(new GridData(SWT.RIGHT, SWT.TOP, false, false));
-
- okButton.addSelectionListener(new SelectionAdapter()
- {
- public void widgetSelected(SelectionEvent e)
- {
- shell.dispose();
-
- //The Name attribute is mandatory, add it now, also
- //ensuring it is left-most by placing it first in the list
- List<String> newSelection = new ArrayList<String>();
- newSelection.add(ManagedQueue.ATTR_NAME);
-
- //now add all remaining choices in alphabetical order
- Collections.sort(chosenAttributes);
- newSelection.addAll(chosenAttributes);
-
- _tableViewerSemaphore.acquireUninterruptibly();
- try
- {
- _selectedAttributes = newSelection;
-
- clearTableComposite();
- createTable();
- saveAttributePreferences();
- }
- finally
- {
- _tableViewerSemaphore.release();
- }
-
- refresh(_mbean);
- }
- });
-
- cancelButton.addSelectionListener(new SelectionAdapter()
- {
- public void widgetSelected(SelectionEvent e)
- {
- shell.dispose();
- }
- });
-
- shell.setDefaultButton(okButton);
- shell.pack();
- ViewUtility.centerChildInParentShell(parent, shell);
-
- shell.open();
- }
-
- private String getQueueDepthString(Long value)
- {
- if(value == null)
- {
- return "-";
- }
-
- if (getApiVersion().greaterThanOrEqualTo(1, 2))
- {
- //Qpid JMX API 1.2 or above, returns Bytes
- return convertLongBytesToText(value);
- }
- else
- {
- //Qpid JMX API 1.1 or below, returns KB
- double mb = 1024.0;
-
- if(value > mb) //MB
- {
- return String.format("%.3f", (Double)(value / mb)) + " MB";
- }
- else //KB
- {
- return value + " KB";
- }
- }
- }
-
- private String convertLongBytesToText(Long value)
- {
- if(value == null)
- {
- return "-";
- }
-
- double mb = 1024.0 * 1024.0;
- double kb = 1024.0;
-
- if(value >= mb) //MB
- {
- return String.format("%.3f", (Double)((double)value / mb)) + " MB";
- }
- else if (value >= kb) //KB
- {
- return String.format("%.3f", (Double)((double)value / kb)) + " KB";
- }
- else //Bytes
- {
- return value + " Bytes";
- }
- }
-
- /**
- * sorter class for the table viewer.
- *
- */
- private static class QueueTableSorter extends ViewerSorter
- {
- protected int column;
- protected static final int ASCENDING = 0;
- protected static final int DESCENDING = 1;
-
- protected int direction;
-
- public QueueTableSorter()
- {
- this.column = 0;
- direction = ASCENDING;
- }
-
- public void setColumn(int column)
- {
- if(column == this.column)
- {
- // Same column as last sort; toggle the direction
- direction = 1 - direction;
- }
- else
- {
- // New column; do an ascending sort
- this.column = column;
- direction = ASCENDING;
- }
- }
-
- @SuppressWarnings("unchecked")
- @Override
- public int compare(Viewer viewer, Object e1, Object e2)
- {
- List<Object> queue1 = (List<Object>) e1;
- List<Object> queue2 = (List<Object>) e2;
-
- int comparison = 0;
- switch(column)
- {
- default:
- if(queue1.get(column) instanceof Comparable)
- {
- comparison = ((Comparable)queue1.get(column)).compareTo((Comparable) queue2.get(column));
- }
- }
- // If descending order, flip the direction
- if(direction == DESCENDING)
- {
- comparison = -comparison;
- }
- return comparison;
- }
- }
-
- /**
- * Content Provider class for the table viewer for Qpid JMX API 1.3 and above.
- */
- private static class QueueContentProviderImpl implements IStructuredContentProvider
- {
-
- public void inputChanged(Viewer v, Object oldInput, Object newInput)
- {
-
- }
-
- public void dispose()
- {
-
- }
-
- @SuppressWarnings("unchecked")
- public Object[] getElements(Object parent)
- {
- return ((List<List<Object>>) parent).toArray();
- }
- }
-
- /**
- * Label Provider class for the table viewer for for Qpid JMX API 1.3 and above.
- */
- private class QueueLabelProviderImpl extends LabelProvider implements ITableLabelProvider
- {
- @SuppressWarnings("unchecked")
- public String getColumnText(Object element, int columnIndex)
- {
- List<Object> attributes = (List<Object>) element;
-
- switch (columnIndex)
- {
- default :
- String attrName = _selectedAttributes.get(columnIndex);
-
- if(ATTR_QUEUE_DEPTH.equals(attrName))
- {
- return getQueueDepthString((Long) attributes.get(columnIndex));
- }
- else if(ATTR_MAX_QUEUE_DEPTH.equals(attrName) || ATTR_MAX_MSG_SIZE.equals(attrName))
- {
- Number val = (Number)attributes.get(columnIndex);
- return convertLongBytesToText(val.longValue());
- }
- else if(ATTR_MAX_MSG_AGE.equals(attrName))
- {
- return String.valueOf(attributes.get(columnIndex) + "ms");
- }
-
- return String.valueOf(attributes.get(columnIndex));
- }
- }
-
- public Image getColumnImage(Object element, int columnIndex)
- {
- return null;
- }
- }
-
- @SuppressWarnings("unchecked")
- @Override
- protected void addMBeanToFavourites()
- {
- int selectionIndex = getTable().getSelectionIndex();
-
- if (selectionIndex == -1)
- {
- return;
- }
-
- int[] selectedIndices = getTable().getSelectionIndices();
-
- ArrayList<ManagedBean> selectedMBeans = new ArrayList<ManagedBean>();
-
- boolean allSucceded = true;
- //the entries are created from an List<Object> with the attribute values (name first)
- for(int index = 0; index < selectedIndices.length ; index++)
- {
- List<Object> queueEntry = (List<Object>) getTable().getItem(selectedIndices[index]).getData();
- String queueName = (String) queueEntry.get(0);
-
- ManagedBean queueMBean = getServerRegistry().getQueue(queueName, getVirtualHost());
-
- //check queue had not already been unregistered before trying to add it
- if(queueMBean != null)
- {
- selectedMBeans.add(queueMBean);
- }
- else
- {
- allSucceded = false;
- }
- }
-
- if(allSucceded)
- {
- //ensure the status bar is cleared of any previous failures added by the below
- ViewUtility.clearStatusBar();
- }
- else
- {
- ViewUtility.operationFailedStatusBarMessage("A selected queue could not be added as it was no longer registered");
- refresh();
- }
-
-
- IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
- NavigationView view = (NavigationView)window.getActivePage().findView(NavigationView.ID);
-
- ManagedBean bean = null;
- try
- {
- for(ManagedBean mbean: selectedMBeans)
- {
- bean = mbean;
- view.addManagedBean(mbean);
- }
- }
- catch (Exception ex)
- {
- MBeanUtility.handleException(bean, ex);
- }
- }
-
- @SuppressWarnings("unchecked")
- @Override
- protected void openMBean()
- {
- int selectionIndex = getTable().getSelectionIndex();
-
- if (selectionIndex == -1)
- {
- return;
- }
-
- ManagedBean selectedMBean;
-
- //the entries are created from an List<Object> with the attribute values (name first)
- List<Object> queueEntry = (List<Object>) getTable().getItem(selectionIndex).getData();
- String queueName = (String) queueEntry.get(0);
- selectedMBean = getServerRegistry().getQueue(queueName, getVirtualHost());
-
- if(selectedMBean == null)
- {
- ViewUtility.popupErrorMessage("Error", "Unable to retrieve the selected MBean to open it");
- return;
- }
-
- IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
- MBeanView view = (MBeanView) window.getActivePage().findView(MBeanView.ID);
- try
- {
- view.openMBean(selectedMBean);
- }
- catch (Exception ex)
- {
- MBeanUtility.handleException(selectedMBean, ex);
- }
- }
-}
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 cebf94007d..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 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;
-
-import javax.management.MBeanOperationInfo;
-
-/**
- * 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
deleted file mode 100644
index 75f48fdc31..0000000000
--- a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/users/UserManagementTabControl.java
+++ /dev/null
@@ -1,1016 +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 org.eclipse.jface.dialogs.InputDialog;
-import org.eclipse.jface.viewers.ISelectionChangedListener;
-import org.eclipse.jface.viewers.IStructuredContentProvider;
-import org.eclipse.jface.viewers.ITableLabelProvider;
-import org.eclipse.jface.viewers.LabelProvider;
-import org.eclipse.jface.viewers.SelectionChangedEvent;
-import org.eclipse.jface.viewers.TableViewer;
-import org.eclipse.jface.viewers.TableViewerColumn;
-import org.eclipse.jface.viewers.Viewer;
-import org.eclipse.jface.viewers.ViewerSorter;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.events.SelectionAdapter;
-import org.eclipse.swt.events.SelectionEvent;
-import org.eclipse.swt.graphics.Image;
-import org.eclipse.swt.layout.GridData;
-import org.eclipse.swt.layout.GridLayout;
-import org.eclipse.swt.widgets.Button;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Control;
-import org.eclipse.swt.widgets.Group;
-import org.eclipse.swt.widgets.Label;
-import org.eclipse.swt.widgets.Shell;
-import org.eclipse.swt.widgets.TabFolder;
-import org.eclipse.swt.widgets.Table;
-import org.eclipse.swt.widgets.TableColumn;
-import org.eclipse.swt.widgets.Text;
-import org.eclipse.ui.forms.widgets.FormToolkit;
-import org.eclipse.ui.forms.widgets.ScrolledForm;
-
-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.ui.jmx.JMXManagedObject;
-import org.apache.qpid.management.ui.jmx.MBeanUtility;
-import org.apache.qpid.management.ui.views.TabControl;
-import org.apache.qpid.management.ui.views.ViewUtility;
-
-import static org.apache.qpid.management.common.mbeans.UserManagement.RIGHTS_ADMIN;
-import static org.apache.qpid.management.common.mbeans.UserManagement.RIGHTS_READ_ONLY;
-import static org.apache.qpid.management.common.mbeans.UserManagement.RIGHTS_READ_WRITE;
-import static org.apache.qpid.management.common.mbeans.UserManagement.USERNAME;
-
-import javax.management.MBeanServerConnection;
-import javax.management.MBeanServerInvocationHandler;
-import javax.management.openmbean.CompositeData;
-import javax.management.openmbean.TabularDataSupport;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-
-
-/**
- * Control class for the UserManagement mbean.
- */
-public class UserManagementTabControl extends TabControl
-{
- private FormToolkit _toolkit;
- private ScrolledForm _form;
- private Table _table = null;
- private TableViewer _tableViewer = null;
-
- private TabularDataSupport _userDetails = null;
- private LegacySupportingUserManagement _ummb;
- private ApiVersion _ApiVersion;
-
- public UserManagementTabControl(TabFolder tabFolder, JMXManagedObject mbean, MBeanServerConnection mbsc)
- {
- super(tabFolder);
- _mbean = mbean;
- _ApiVersion = ApplicationRegistry.getServerRegistry(mbean).getManagementApiVersion();
- _ummb = (LegacySupportingUserManagement)
- MBeanServerInvocationHandler.newProxyInstance(mbsc, mbean.getObjectName(),
- LegacySupportingUserManagement.class, false);
- _toolkit = new FormToolkit(_tabFolder.getDisplay());
- _form = _toolkit.createScrolledForm(_tabFolder);
- _form.getBody().setLayout(new GridLayout());
- createWidgets();
- }
-
- /**
- * @see TabControl#getControl()
- */
- public Control getControl()
- {
- return _form;
- }
-
- /**
- * @see TabControl#setFocus()
- */
- public void setFocus()
- {
- _table.setFocus();
- }
-
- @Override
- public void refresh(ManagedBean mbean)
- {
- _userDetails = null;
- try
- {
- _userDetails = (TabularDataSupport) _ummb.viewUsers();
- }
- catch(Exception e)
- {
- MBeanUtility.handleException(_mbean, e);
-
- }
-
- _tableViewer.setInput(_userDetails);
-
- layout();
- }
-
- public void layout()
- {
- _form.layout(true);
- _form.getBody().layout(true, true);
- }
-
- private void createWidgets()
- {
- Composite paramsComposite = _toolkit.createComposite(_form.getBody(), SWT.NONE);
- paramsComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
- paramsComposite.setLayout(new GridLayout());
-
- Group viewUsersGroup = new Group(paramsComposite, SWT.SHADOW_NONE);
- viewUsersGroup.setBackground(paramsComposite.getBackground());
- viewUsersGroup.setText("Users");
- viewUsersGroup.setLayout(new GridLayout(2,false));
- viewUsersGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
-
- Composite tableComposite = _toolkit.createComposite(viewUsersGroup);
- GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
- gridData.heightHint = 250;
- gridData.minimumHeight = 250;
- tableComposite.setLayoutData(gridData);
- tableComposite.setLayout(new GridLayout(2,false));
-
- _table = new Table (tableComposite, SWT.MULTI | SWT.SCROLL_LINE | SWT.BORDER | SWT.FULL_SELECTION);
- _table.setLinesVisible (true);
- _table.setHeaderVisible (true);
- gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
- _table.setLayoutData(gridData);
-
- _tableViewer = new TableViewer(_table);
- final TableSorter tableSorter = new TableSorter();
-
- 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;
- final TableViewerColumn viewerColumn = new TableViewerColumn(_tableViewer, SWT.NONE);
- final TableColumn column = viewerColumn.getColumn();
-
- column.setText(titles[i]);
- column.setWidth(bounds[i]);
- column.setResizable(true);
-
- //Setting the right sorter
- column.addSelectionListener(new SelectionAdapter()
- {
- @Override
- public void widgetSelected(SelectionEvent e)
- {
- tableSorter.setColumn(index);
- final TableViewer viewer = _tableViewer;
- int dir = viewer .getTable().getSortDirection();
- if (viewer.getTable().getSortColumn() == column)
- {
- dir = dir == SWT.UP ? SWT.DOWN : SWT.UP;
- }
- else
- {
- dir = SWT.UP;
- }
- viewer.getTable().setSortDirection(dir);
- viewer.getTable().setSortColumn(column);
- viewer.refresh();
- }
- });
-
- }
-
- _tableViewer.setContentProvider(new ContentProviderImpl());
- _tableViewer.setLabelProvider(new LabelProviderImpl());
- _tableViewer.setSorter(tableSorter);
- _table.setSortColumn(_table.getColumn(0));
- _table.setSortDirection(SWT.UP);
-
- 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;
- }
- buttonsComposite.setLayoutData(gridData);
- buttonsComposite.setLayout(new GridLayout());
-
- final Button addUserButton = _toolkit.createButton(buttonsComposite, "Add New User ...", SWT.PUSH);
- gridData = new GridData(SWT.CENTER, SWT.TOP, false, true);
- gridData.widthHint = 125;
- addUserButton.setLayoutData(gridData);
- addUserButton.addSelectionListener(new SelectionAdapter()
- {
- public void widgetSelected(SelectionEvent e)
- {
- addUser(addUserButton.getShell());
- }
- });
-
- final Button deleteUsersButton = _toolkit.createButton(buttonsComposite, "Delete User(s)", SWT.PUSH);
- gridData = new GridData(SWT.CENTER, SWT.BOTTOM, false, false);
- gridData.widthHint = 125;
- deleteUsersButton.setLayoutData(gridData);
- deleteUsersButton.setEnabled(false);
- deleteUsersButton.addSelectionListener(new SelectionAdapter()
- {
- public void widgetSelected(SelectionEvent e)
- {
- int selectionIndex = _table.getSelectionIndex();
-
- if (selectionIndex != -1)
- {
- deleteUsers();
- }
- }
- });
-
- final Button setPasswordButton = _toolkit.createButton(buttonsComposite, "Set Password ...", SWT.PUSH);
- gridData = new GridData(SWT.CENTER, SWT.BOTTOM, false, false);
- gridData.widthHint = 125;
- setPasswordButton.setLayoutData(gridData);
- setPasswordButton.setEnabled(false);
- setPasswordButton.addSelectionListener(new SelectionAdapter()
- {
- public void widgetSelected(SelectionEvent e)
- {
- int selectionIndex = _table.getSelectionIndex();
-
- if (selectionIndex != -1)
- {
- final CompositeData selectedLogger = (CompositeData)_table.getItem(
- selectionIndex).getData();
- String user = selectedLogger.get(USERNAME).toString();
- InputDialog id = new InputDialog(setPasswordButton.getShell(),"Set Password",
- "Please enter the new password for '" + user + "':",null,null){
- @Override
- protected Control createDialogArea(Composite parent)
- {
- Control control = super.createDialogArea(parent);
- //set the Text field echo char to '*' to mask the password
- getText().setEchoChar('*');
- //return the normal result
- return control;
- }
- };
-
- int returnValue;
- while((returnValue = id.open()) == InputDialog.OK)
- {
- if (id.getValue() == null || id.getValue().toString().length() == 0)
- {
- ViewUtility.popupErrorMessage("Set Password", "Please enter a valid password");
- }
- else
- {
- break;
- }
- }
-
- if (returnValue == InputDialog.OK)
- {
- char[] passwordArray = 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());
- }
- catch (Exception hashException)
- {
- ViewUtility.popupErrorMessage("Set Password",
- "Unable to calculate hash for Password:"
- + hashException.getMessage());
- return;
- }
- }
-
- 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);
- }
-
- ViewUtility.operationResultFeedback(result, "Updated user password", "Failed to update user password");
- }
- catch(Exception e2)
- {
- ViewUtility.operationFailedStatusBarMessage("Error updating user password");
- MBeanUtility.handleException(_mbean, e2);
- }
- }
- }
- }
- });
-
- final Button setRightsButton;
- if(!settingManagementRightsSupported())
- {
- //The 'Set Rights' button is not used from Qpid JMX API 2.3 / 1.12 onward
- setRightsButton = null;
- }
- else
- {
- 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)
- {
- int selectionIndex = _table.getSelectionIndex();
-
- if (selectionIndex != -1)
- {
- setRights(setRightsButton.getShell());
- }
- }
- });
- }
-
- _tableViewer.addSelectionChangedListener(new ISelectionChangedListener(){
- public void selectionChanged(SelectionChangedEvent evt)
- {
- int selectionIndex = _table.getSelectionIndex();
-
- if (selectionIndex == -1)
- {
- deleteUsersButton.setEnabled(false);
- setPasswordButton.setEnabled(false);
- if(setRightsButton != null)
- {
- setRightsButton.setEnabled(false);
- }
- return;
- }
- else
- {
- deleteUsersButton.setEnabled(true);
- if(setRightsButton != null)
- {
- setRightsButton.setEnabled(true);
- }
- }
-
- if (_table.getSelectionCount() > 1)
- {
- setPasswordButton.setEnabled(false);
- }
- else
- {
- setPasswordButton.setEnabled(true);
- }
- }
- });
-
- Group miscGroup = new Group(paramsComposite, SWT.SHADOW_NONE);
- miscGroup.setBackground(paramsComposite.getBackground());
- miscGroup.setText("Misc");
- gridData = new GridData(SWT.LEFT, SWT.TOP, true, true);
- miscGroup.setLayoutData(gridData);
- miscGroup.setLayout(new GridLayout(2,false));
-
- final Button reloadUserDetails = _toolkit.createButton(miscGroup,
- "Reload User Details", SWT.PUSH);
- if(_ApiVersion.lessThan(1, 2))
- {
- //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");
- }
-
- reloadUserDetails.addSelectionListener(new SelectionAdapter()
- {
- public void widgetSelected(SelectionEvent e)
- {
- int response = ViewUtility.popupOkCancelConfirmationMessage("Reload User Data",
- "Do you want to reload user data ?");
- if (response == SWT.OK)
- {
- try
- {
- boolean result = _ummb.reloadData();
- ViewUtility.operationResultFeedback(result, "Reloaded user data", "Failed to reload user data");
- }
- catch(Exception e3)
- {
- ViewUtility.operationFailedStatusBarMessage("Error reloading user data");
- MBeanUtility.handleException(_mbean, e3);
- }
- refresh(_mbean);
- }
- }
- });
-
- }
-
-
- /**
- * Content Provider class for the table viewer
- */
- private static class ContentProviderImpl implements IStructuredContentProvider
- {
-
- public void inputChanged(Viewer v, Object oldInput, Object newInput)
- {
-
- }
-
- public void dispose()
- {
-
- }
-
- public Object[] getElements(Object parent)
- {
- Collection<Object> rowCollection = ((TabularDataSupport) parent).values();
-
- return rowCollection.toArray();
- }
- }
-
- /**
- * Label Provider class for the table viewer
- */
- private class LabelProviderImpl extends LabelProvider implements ITableLabelProvider
- {
- @Override
- public String getColumnText(Object element, int columnIndex)
- {
- switch (columnIndex)
- {
- case 0 : // username column
- return (String) ((CompositeData) element).get(USERNAME);
- case 1 : // rights column (used for API < 2.3 / 1.12)
- return classifyUserRights((CompositeData) element);
- default :
- return "-";
- }
- }
-
- @Override
- public Image getColumnImage(Object element, int columnIndex)
- {
- return null;
- }
-
- }
-
- /**
- * Sorter class for the table viewer.
- *
- */
- private class TableSorter extends ViewerSorter
- {
- private int column;
- private static final int ASCENDING = 0;
- private static final int DESCENDING = 1;
-
- private int direction;
-
- public TableSorter()
- {
- this.column = 0;
- direction = ASCENDING;
- }
-
- public void setColumn(int column)
- {
- if(column == this.column)
- {
- // Same column as last sort; toggle the direction
- direction = 1 - direction;
- }
- else
- {
- // New column; do an ascending sort
- this.column = column;
- direction = ASCENDING;
- }
- }
-
- @Override
- public int compare(Viewer viewer, Object e1, Object e2)
- {
- CompositeData user1 = (CompositeData) e1;
- CompositeData user2 = (CompositeData) e2;
-
- int comparison = 0;
- switch(column)
- {
- case 0: //username column
- comparison = String.valueOf(user1.get(USERNAME)).compareTo(
- String.valueOf(user2.get(USERNAME)));
- break;
- case 1: // rights column (used for API < 2.3 / 1.12)
- comparison = classifyUserRights(user1).compareTo(classifyUserRights(user2));
- break;
- default:
- comparison = 0;
- }
- // If descending order, flip the direction
- if(direction == DESCENDING)
- {
- comparison = -comparison;
- }
- return comparison;
- }
- }
-
- private String classifyUserRights(CompositeData user)
- {
- Boolean read = (Boolean)user.get(RIGHTS_READ_ONLY);
- Boolean write = (Boolean)user.get(RIGHTS_READ_WRITE);
- Boolean admin = (Boolean)user.get(RIGHTS_ADMIN);
-
- if(admin)
- {
- return "Admin";
- }
- else if(write)
- {
- return "Read & Write";
- }
- else if(read)
- {
- return "Read Only";
- }
- else
- {
- return "No Access";
- }
- }
-
- 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)
- {
- return;
- }
-
- int[] selectedIndices = _table.getSelectionIndices();
-
- final ArrayList<String> selectedUsers = new ArrayList<String>();
-
- for(int index = 0; index < selectedIndices.length ; index++)
- {
- CompositeData selectedUser = (CompositeData)_table.getItem(selectedIndices[index]).getData();
- String user = selectedUser.get(USERNAME).toString();
- selectedUsers.add(user);
- }
-
- String selectedUsersString = "";
- for(String user : selectedUsers)
- {
- selectedUsersString = selectedUsersString.concat(user + ", ");
- }
- //cut off last ", "
- int lastIndex = selectedUsersString.lastIndexOf(',');
- if (lastIndex != -1)
- {
- selectedUsersString = selectedUsersString.substring(0,lastIndex);
- }
-
-
-
- final Shell shell = ViewUtility.createModalDialogShell(parent, "Set Rights");
-
- Label overview = _toolkit.createLabel(shell,"Select rights for user(s): ");
- overview.setBackground(shell.getBackground());
- Label userNamesLabel= _toolkit.createLabel(shell,selectedUsersString);
- userNamesLabel.setBackground(shell.getBackground());
-
- Composite buttons = _toolkit.createComposite(shell, SWT.NONE);
- buttons.setBackground(shell.getBackground());
- buttons.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
- buttons.setLayout(new GridLayout(4,false));
-
- final Button noneButton = new Button(buttons, SWT.RADIO);
- noneButton.setText("No Access");
- noneButton.setSelection(true);
- final Button readButton = new Button(buttons, SWT.RADIO);
- readButton.setText("Read Only");
- final Button writeButton = new Button(buttons, SWT.RADIO);
- writeButton.setText("Read + Write");
- final Button adminButton = new Button(buttons, SWT.RADIO);
- adminButton.setText("Admin");
-
- Composite okCancelButtonsComp = _toolkit.createComposite(shell);
- okCancelButtonsComp.setBackground(shell.getBackground());
- okCancelButtonsComp.setLayoutData(new GridData(SWT.RIGHT, SWT.FILL, true, true));
- okCancelButtonsComp.setLayout(new GridLayout(2,false));
-
- Button okButton = _toolkit.createButton(okCancelButtonsComp, "OK", SWT.PUSH);
- okButton.setLayoutData(new GridData(SWT.RIGHT, SWT.TOP, false, false));
- Button cancelButton = _toolkit.createButton(okCancelButtonsComp, "Cancel", SWT.PUSH);
- cancelButton.setLayoutData(new GridData(SWT.RIGHT, SWT.TOP, false, false));
-
- okButton.addSelectionListener(new SelectionAdapter()
- {
- public void widgetSelected(SelectionEvent e)
- {
- boolean read = readButton.getSelection();
- boolean write = writeButton.getSelection();
- boolean admin = adminButton.getSelection();
-
- shell.dispose();
-
- HashMap<String,Boolean> results = new HashMap<String,Boolean>();
- try
- {
- //perform the rights updates, save the results.
- for(String user : selectedUsers)
- {
- boolean result = _ummb.setRights(user,read,write,admin);
- results.put(user, result);
- }
-
- //categorise the overall result
- boolean overallResult = true;
- for(boolean result : results.values())
- {
- if (!result)
- {
- overallResult = false;
- }
- }
-
- //output the result to status bar if all success, and dialogue if not
- if(overallResult)
- {
- ViewUtility.operationResultFeedback(overallResult, "Updated user rights", null);
- }
- else
- {
- String failedToUpdateRightsUsers = "";
- for(String user : results.keySet())
- {
- if(!results.get(user))
- {
- failedToUpdateRightsUsers = failedToUpdateRightsUsers.concat(user + ", ");
- }
- }
-
- //cut off last ", "
- int lastIndex2 = failedToUpdateRightsUsers.lastIndexOf(',');
- if (lastIndex2 != -1)
- {
- failedToUpdateRightsUsers = failedToUpdateRightsUsers.substring(0, lastIndex2);
- }
-
- ViewUtility.operationResultFeedback(overallResult, null, "Failed to update user(s) rights: " + failedToUpdateRightsUsers);
- }
- }
- catch(Exception e4)
- {
- ViewUtility.operationFailedStatusBarMessage("Error updating user rights");
- MBeanUtility.handleException(_mbean, e4);
- }
- refresh(_mbean);
- }
- });
-
- cancelButton.addSelectionListener(new SelectionAdapter()
- {
- public void widgetSelected(SelectionEvent e)
- {
- shell.dispose();
- }
- });
-
- shell.setDefaultButton(okButton);
- shell.pack();
- ViewUtility.centerChildInParentShell(parent, shell);
-
- 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)
- {
- final Shell shell = ViewUtility.createModalDialogShell(parent, "Add New User");
-
- 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.setLayout(new GridLayout(2,false));
-
- _toolkit.createLabel(usernameComposite,"Username:").setBackground(shell.getBackground());
- final Text usernameText = new Text(usernameComposite, SWT.BORDER);
- usernameText.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
-
- 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.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));
-
- 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;
- }
-
- Composite okCancelButtonsComp = _toolkit.createComposite(shell);
- okCancelButtonsComp.setBackground(shell.getBackground());
- okCancelButtonsComp.setLayoutData(new GridData(SWT.RIGHT, SWT.FILL, true, true));
- okCancelButtonsComp.setLayout(new GridLayout(2,false));
-
- Button okButton = _toolkit.createButton(okCancelButtonsComp, "OK", SWT.PUSH);
- okButton.setLayoutData(new GridData(SWT.RIGHT, SWT.TOP, false, false));
- Button cancelButton = _toolkit.createButton(okCancelButtonsComp, "Cancel", SWT.PUSH);
- cancelButton.setLayoutData(new GridData(SWT.RIGHT, SWT.TOP, false, false));
-
- okButton.addSelectionListener(new SelectionAdapter()
- {
- public void widgetSelected(SelectionEvent e)
- {
- String username = usernameText.getText();
- String password = passwordText.getText();
-
- if (username == null || username.length() == 0)
- {
- ViewUtility.popupErrorMessage("Add New User", "Please enter a valid username");
- return;
- }
-
- if (password == null || password.length() == 0)
- {
- ViewUtility.popupErrorMessage("Add New User", "Please enter a valid password");
- return;
- }
-
- char[] passwordChars = password.toCharArray();
-
- // Qpid JMX API 1.1 and below expects the password to be sent as a hashed value.
- if (_ApiVersion.lessThanOrEqualTo(1,1))
- {
- try
- {
- passwordChars = ViewUtility.getHash(password);
- }
- catch (Exception hashException)
- {
- ViewUtility.popupErrorMessage("Set Password",
- "Unable to calculate hash for Password:"
- + hashException.getMessage());
- 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();
- }
-
- 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.
- 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);
- }
-
- ViewUtility.operationResultFeedback(result, "Created user", "Failed to create user");
- }
- catch(Exception e5)
- {
- ViewUtility.operationFailedStatusBarMessage("Error creating user");
- MBeanUtility.handleException(_mbean, e5);
- }
-
- refresh(_mbean);
- }
- });
-
- cancelButton.addSelectionListener(new SelectionAdapter()
- {
- public void widgetSelected(SelectionEvent e)
- {
- shell.dispose();
- }
- });
-
- shell.setDefaultButton(okButton);
- shell.pack();
- ViewUtility.centerChildInParentShell(parent, shell);
-
- shell.open();
- }
-
- private void deleteUsers()
- {
- int selectionIndex = _table.getSelectionIndex();
- if (selectionIndex == -1)
- {
- return;
- }
-
- int[] selectedIndices = _table.getSelectionIndices();
-
- ArrayList<String> selectedUsers = new ArrayList<String>();
-
- for(int index = 0; index < selectedIndices.length ; index++)
- {
- CompositeData selectedUser = (CompositeData)_table.getItem(selectedIndices[index]).getData();
- String user = selectedUser.get(USERNAME).toString();
- selectedUsers.add(user);
- }
-
- String selectedUsersString = "";
- for(String user : selectedUsers)
- {
- selectedUsersString = selectedUsersString.concat(user + ", ");
- }
- //cut off last ", "
- int lastIndex = selectedUsersString.lastIndexOf(',');
- if (lastIndex != -1)
- {
- selectedUsersString = selectedUsersString.substring(0,lastIndex);
- }
-
- int response = ViewUtility.popupOkCancelConfirmationMessage(
- "User Management", "Delete user(s): " + selectedUsersString + " ?");
-
- if (response == SWT.OK)
- {
- HashMap<String,Boolean> results = new HashMap<String,Boolean>();
- try
- {
- //perform the deletes, save the results.
- for(String user : selectedUsers)
- {
- boolean result = _ummb.deleteUser(user);
- results.put(user, result);
- }
-
- //categorise the overall result
- boolean overallResult = true;
- for(boolean result : results.values())
- {
- if (!result)
- {
- overallResult = false;
- }
- }
-
- //output the result to status bar if all success, and dialogue if not
- if(overallResult)
- {
- ViewUtility.operationResultFeedback(overallResult, "Deleted user(s)", null);
- }
- else
- {
- String failedToDeleteUsers = "";
- for(String user : results.keySet())
- {
- if(!results.get(user))
- {
- failedToDeleteUsers = failedToDeleteUsers.concat(user + ", ");
- }
- }
-
- //cut off last ", "
- lastIndex = failedToDeleteUsers.lastIndexOf(',');
- if (lastIndex != -1)
- {
- failedToDeleteUsers = failedToDeleteUsers.substring(0, lastIndex);
- }
-
- ViewUtility.operationResultFeedback(overallResult, null, "Failed to delete user(s): " + failedToDeleteUsers);
- }
-
- }
- catch(Exception e1)
- {
- ViewUtility.operationFailedStatusBarMessage("Error deleting user(s)");
- MBeanUtility.handleException(_mbean, e1);
- }
-
- refresh(_mbean);;
- }
- }
-}
diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/vhost/VHostTabControl.java b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/vhost/VHostTabControl.java
deleted file mode 100644
index 28fba7ed05..0000000000
--- a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/vhost/VHostTabControl.java
+++ /dev/null
@@ -1,870 +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.vhost;
-
-import org.eclipse.jface.viewers.ISelectionChangedListener;
-import org.eclipse.jface.viewers.IStructuredContentProvider;
-import org.eclipse.jface.viewers.ITableLabelProvider;
-import org.eclipse.jface.viewers.LabelProvider;
-import org.eclipse.jface.viewers.SelectionChangedEvent;
-import org.eclipse.jface.viewers.TableViewer;
-import org.eclipse.jface.viewers.Viewer;
-import org.eclipse.jface.viewers.ViewerSorter;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.events.MouseEvent;
-import org.eclipse.swt.events.MouseListener;
-import org.eclipse.swt.events.SelectionAdapter;
-import org.eclipse.swt.events.SelectionEvent;
-import org.eclipse.swt.graphics.Image;
-import org.eclipse.swt.layout.GridData;
-import org.eclipse.swt.layout.GridLayout;
-import org.eclipse.swt.widgets.Button;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Control;
-import org.eclipse.swt.widgets.Group;
-import org.eclipse.swt.widgets.Shell;
-import org.eclipse.swt.widgets.TabFolder;
-import org.eclipse.swt.widgets.Table;
-import org.eclipse.swt.widgets.TableColumn;
-import org.eclipse.swt.widgets.Text;
-import org.eclipse.ui.IWorkbenchWindow;
-import org.eclipse.ui.PlatformUI;
-import org.eclipse.ui.forms.widgets.Form;
-import org.eclipse.ui.forms.widgets.FormToolkit;
-
-import org.apache.qpid.management.common.mbeans.ManagedBroker;
-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.ui.ServerRegistry;
-import org.apache.qpid.management.ui.jmx.JMXManagedObject;
-import org.apache.qpid.management.ui.jmx.MBeanUtility;
-import org.apache.qpid.management.ui.views.MBeanView;
-import org.apache.qpid.management.ui.views.TabControl;
-import org.apache.qpid.management.ui.views.ViewUtility;
-
-import static org.apache.qpid.management.ui.Constants.DEFAULT_EXCHANGE_TYPE_VALUES;
-
-import javax.management.MBeanServerConnection;
-import javax.management.MBeanServerInvocationHandler;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-
-
-/**
- * Control class for the VirtualHostManager mbean operations tab.
- */
-public class VHostTabControl extends TabControl
-{
- private FormToolkit _toolkit;
- private Form _form;
- private Table _queueTable = null;
- private TableViewer _queueTableViewer = null;
- private Table _exchangeTable = null;
- private TableViewer _exchangeTableViewer = null;
-
- private Composite _paramsComposite = null;
-
- private ManagedBroker _vhmb;
- private ApiVersion _ApiVersion;
- private List<ManagedBean> _queues;
- private List<ManagedBean> _exchanges;
- private ServerRegistry _serverRegistry;
-
- public VHostTabControl(TabFolder tabFolder, JMXManagedObject mbean, MBeanServerConnection mbsc)
- {
- super(tabFolder);
- _mbean = mbean;
- _serverRegistry = ApplicationRegistry.getServerRegistry(mbean);
- _ApiVersion = _serverRegistry.getManagementApiVersion();
- _vhmb = (ManagedBroker) MBeanServerInvocationHandler.newProxyInstance(mbsc,
- mbean.getObjectName(), ManagedBroker.class, false);
- _toolkit = new FormToolkit(_tabFolder.getDisplay());
- _form = _toolkit.createForm(_tabFolder);
- _form.getBody().setLayout(new GridLayout());
- createComposites();
- createWidgets();
- }
-
- private void createComposites()
- {
- _paramsComposite = _toolkit.createComposite(_form.getBody(), SWT.NONE);
- _paramsComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
- _paramsComposite.setLayout(new GridLayout(2, true));
- }
-
- /**
- * @see TabControl#getControl()
- */
- public Control getControl()
- {
- return _form;
- }
-
- /**
- * @see TabControl#setFocus()
- */
- public void setFocus()
- {
-
- }
-
- @Override
- public void refresh(ManagedBean mbean)
- {
- ServerRegistry serverRegistry = ApplicationRegistry.getServerRegistry(MBeanView.getServer());
- _queues = serverRegistry.getQueues(MBeanView.getVirtualHost());
- _exchanges = serverRegistry.getExchanges(MBeanView.getVirtualHost());
-
- _queueTableViewer.setInput(_queues);
- _exchangeTableViewer.setInput(_exchanges);
-
- layout();
- }
-
- public void layout()
- {
- _form.layout(true);
- _form.getBody().layout(true, true);
- }
-
- private void createWidgets()
- {
- Group queuesGroup = new Group(_paramsComposite, SWT.SHADOW_NONE);
- queuesGroup.setBackground(_paramsComposite.getBackground());
- queuesGroup.setText("Queues");
- queuesGroup.setLayout(new GridLayout(2,false));
- GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
- queuesGroup.setLayoutData(gridData);
-
- _queueTable = new Table (queuesGroup, SWT.MULTI | SWT.SCROLL_LINE | SWT.BORDER | SWT.FULL_SELECTION);
- _queueTable.setLinesVisible (true);
- _queueTable.setHeaderVisible (true);
- GridData data = new GridData(SWT.FILL, SWT.FILL, true, true);
- _queueTable.setLayoutData(data);
-
- _queueTableViewer = new TableViewer(_queueTable);
- final TableSorter tableSorter = new TableSorter();
-
- String[] titles = {"Name"};
- int[] bounds = { 250 };
- for (int i = 0; i < titles.length; i++)
- {
- final int index = i;
- final TableColumn column = new TableColumn (_queueTable, SWT.NONE);
-
- column.setText(titles[i]);
- column.setWidth(bounds[i]);
- column.setResizable(true);
-
- //Setting the right sorter
- column.addSelectionListener(new SelectionAdapter()
- {
- @Override
- public void widgetSelected(SelectionEvent e)
- {
- tableSorter.setColumn(index);
- final TableViewer viewer = _queueTableViewer;
- int dir = viewer .getTable().getSortDirection();
- if (viewer.getTable().getSortColumn() == column)
- {
- dir = dir == SWT.UP ? SWT.DOWN : SWT.UP;
- }
- else
- {
- dir = SWT.UP;
- }
- viewer.getTable().setSortDirection(dir);
- viewer.getTable().setSortColumn(column);
- viewer.refresh();
- }
- });
-
- }
-
- _queueTableViewer.setContentProvider(new ContentProviderImpl());
- _queueTableViewer.setLabelProvider(new LabelProviderImpl());
- _queueTableViewer.setSorter(tableSorter);
- _queueTable.setSortColumn(_queueTable.getColumn(0));
- _queueTable.setSortDirection(SWT.UP);
-
- Composite queuesRightComposite = _toolkit.createComposite(queuesGroup);
- gridData = new GridData(SWT.FILL, SWT.FILL, false, true);
- queuesRightComposite.setLayoutData(gridData);
- queuesRightComposite.setLayout(new GridLayout());
-
- final Button createQueueButton = _toolkit.createButton(queuesRightComposite, "Create ...", SWT.PUSH);
- createQueueButton.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, false, false));
- createQueueButton.addSelectionListener(new SelectionAdapter()
- {
- public void widgetSelected(SelectionEvent e)
- {
- createQueue(createQueueButton.getShell());
- }
- });
-
- final Button deleteQueueButton = _toolkit.createButton(queuesRightComposite, "Delete", SWT.PUSH);
- deleteQueueButton.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
- deleteQueueButton.setEnabled(false);
- deleteQueueButton.addSelectionListener(new SelectionAdapter()
- {
- public void widgetSelected(SelectionEvent e)
- {
- deleteQueuesOrExchanges(deleteQueueButton.getShell(), VhostOperations.DELETE_QUEUE);
- }
- });
-
- _queueTableViewer.addSelectionChangedListener(new ISelectionChangedListener(){
- public void selectionChanged(SelectionChangedEvent evt)
- {
- int selectionIndex = _queueTable.getSelectionIndex();
-
- if (selectionIndex != -1)
- {
- deleteQueueButton.setEnabled(true);
- }
- else
- {
- deleteQueueButton.setEnabled(false);
- }
- }
- });
-
- //listener for double clicking to open the selection mbean
- _queueTable.addMouseListener(new MouseListener()
- {
- // MouseListener implementation
- public void mouseDoubleClick(MouseEvent event)
- {
- openMBean(_queueTable);
- }
-
- public void mouseDown(MouseEvent e){}
- public void mouseUp(MouseEvent e){}
- });
-
- Group exchangesGroup = new Group(_paramsComposite, SWT.SHADOW_NONE);
- exchangesGroup.setBackground(_paramsComposite.getBackground());
- exchangesGroup.setText("Exchanges");
- exchangesGroup.setLayout(new GridLayout(2,false));
- gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
- exchangesGroup.setLayoutData(gridData);
-
- _exchangeTable = new Table (exchangesGroup, SWT.MULTI | SWT.SCROLL_LINE | SWT.BORDER | SWT.FULL_SELECTION);
- _exchangeTable.setLinesVisible (true);
- _exchangeTable.setHeaderVisible (true);
- data = new GridData(SWT.FILL, SWT.FILL, true, true);
- _exchangeTable.setLayoutData(data);
-
- _exchangeTableViewer = new TableViewer(_exchangeTable);
- final TableSorter exchangeTableSorter = new TableSorter();
-
- for (int i = 0; i < titles.length; i++)
- {
- final int index = i;
- final TableColumn column = new TableColumn (_exchangeTable, SWT.NONE);
-
- column.setText(titles[i]);
- column.setWidth(bounds[i]);
- column.setResizable(true);
-
- //Setting the right sorter
- column.addSelectionListener(new SelectionAdapter()
- {
- @Override
- public void widgetSelected(SelectionEvent e)
- {
- exchangeTableSorter.setColumn(index);
- final TableViewer viewer = _exchangeTableViewer;
- int dir = viewer .getTable().getSortDirection();
- if (viewer.getTable().getSortColumn() == column)
- {
- dir = dir == SWT.UP ? SWT.DOWN : SWT.UP;
- }
- else
- {
- dir = SWT.UP;
- }
- viewer.getTable().setSortDirection(dir);
- viewer.getTable().setSortColumn(column);
- viewer.refresh();
- }
- });
-
- }
-
- _exchangeTableViewer.setContentProvider(new ContentProviderImpl());
- _exchangeTableViewer.setLabelProvider(new LabelProviderImpl());
- _exchangeTableViewer.setSorter(exchangeTableSorter);
- _exchangeTable.setSortColumn(_exchangeTable.getColumn(0));
- _exchangeTable.setSortDirection(SWT.UP);
-
- Composite exchangesRightComposite = _toolkit.createComposite(exchangesGroup);
- gridData = new GridData(SWT.FILL, SWT.FILL, false, true);
- exchangesRightComposite.setLayoutData(gridData);
- exchangesRightComposite.setLayout(new GridLayout());
-
- final Button createExchangeButton = _toolkit.createButton(exchangesRightComposite, "Create ...", SWT.PUSH);
- createExchangeButton.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, false, false));
- createExchangeButton.addSelectionListener(new SelectionAdapter()
- {
- public void widgetSelected(SelectionEvent e)
- {
- createExchange(createQueueButton.getShell());
- }
- });
-
- final Button deleteExchangeButton = _toolkit.createButton(exchangesRightComposite, "Delete", SWT.PUSH);
- deleteExchangeButton.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
- deleteExchangeButton.setEnabled(false);
- deleteExchangeButton.addSelectionListener(new SelectionAdapter()
- {
- public void widgetSelected(SelectionEvent e)
- {
- deleteQueuesOrExchanges(deleteExchangeButton.getShell(), VhostOperations.DELETE_EXCHANGE);
- }
- });
-
- _exchangeTableViewer.addSelectionChangedListener(new ISelectionChangedListener(){
- public void selectionChanged(SelectionChangedEvent evt)
- {
- int selectionIndex = _exchangeTable.getSelectionIndex();
-
- if (selectionIndex != -1)
- {
- deleteExchangeButton.setEnabled(true);
- }
- else
- {
- deleteExchangeButton.setEnabled(false);
- }
- }
- });
-
- //listener for double clicking to open the selection mbean
- _exchangeTable.addMouseListener(new MouseListener()
- {
- // MouseListener implementation
- public void mouseDoubleClick(MouseEvent event)
- {
- openMBean(_exchangeTable);
- }
-
- public void mouseDown(MouseEvent e){}
- public void mouseUp(MouseEvent e){}
- });
- }
-
-
- /**
- * Content Provider class for the table viewer
- */
- private static class ContentProviderImpl implements IStructuredContentProvider
- {
-
- public void inputChanged(Viewer v, Object oldInput, Object newInput)
- {
-
- }
-
- public void dispose()
- {
-
- }
-
- @SuppressWarnings("unchecked")
- public Object[] getElements(Object parent)
- {
- return ((List<ManagedBean>) parent).toArray();
- }
- }
-
- /**
- * Label Provider class for the table viewer
- */
- private static class LabelProviderImpl extends LabelProvider implements ITableLabelProvider
- {
- @Override
- public String getColumnText(Object element, int columnIndex)
- {
- switch (columnIndex)
- {
- case 0 : // name column
- return ((ManagedBean) element).getName();
- default :
- return "-";
- }
- }
-
- @Override
- public Image getColumnImage(Object element, int columnIndex)
- {
- return null;
- }
-
- }
-
- /**
- * Sorter class for the table viewer.
- *
- */
- public static class TableSorter extends ViewerSorter
- {
- private int column;
- private static final int ASCENDING = 0;
- private static final int DESCENDING = 1;
-
- private int direction = DESCENDING;
-
- public TableSorter()
- {
- this.column = 0;
- direction = ASCENDING;
- }
-
- public void setColumn(int column)
- {
- if (column == this.column)
- {
- // Same column as last sort; toggle the direction
- direction = 1 - direction;
- }
- else
- {
- // New column; do an ascending sort
- this.column = column;
- direction = ASCENDING;
- }
- }
-
- @Override
- public int compare(Viewer viewer, Object e1, Object e2)
- {
- ManagedBean mbean1 = (ManagedBean ) e1;
- ManagedBean mbean2 = (ManagedBean ) e2;
-
- int comparison = 0;
- switch(column)
- {
- case 0:
- comparison = mbean1.getName().compareTo(mbean2.getName());
- break;
- default:
- comparison = 0;
- }
- // If descending order, flip the direction
- if(direction == DESCENDING)
- {
- comparison = -comparison;
- }
- return comparison;
- }
- }
-
- private void createQueue(final Shell parent)
- {
- final Shell shell = ViewUtility.createModalDialogShell(parent, "Create Queue");
-
- Composite nameComposite = _toolkit.createComposite(shell, SWT.NONE);
- nameComposite.setBackground(shell.getBackground());
- nameComposite.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
- nameComposite.setLayout(new GridLayout(2,false));
-
- _toolkit.createLabel(nameComposite,"Name:").setBackground(shell.getBackground());
- final Text nameText = new Text(nameComposite, SWT.BORDER);
- nameText.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
-
- Composite ownerComposite = _toolkit.createComposite(shell, SWT.NONE);
- ownerComposite.setBackground(shell.getBackground());
- ownerComposite.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
- ownerComposite.setLayout(new GridLayout(2,false));
-
- _toolkit.createLabel(ownerComposite,"Owner (optional):").setBackground(shell.getBackground());
- final Text ownerText = new Text(ownerComposite, SWT.BORDER);
- ownerText.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
-
- Composite durableComposite = _toolkit.createComposite(shell, SWT.NONE);
- durableComposite.setBackground(shell.getBackground());
- GridData gridData = new GridData(SWT.FILL, SWT.TOP, true, false);
- gridData.minimumWidth = 220;
- durableComposite.setLayoutData(gridData);
- durableComposite.setLayout(new GridLayout(2,false));
-
- _toolkit.createLabel(durableComposite,"Durable:").setBackground(shell.getBackground());
- final Button durableButton = new Button(durableComposite, SWT.CHECK);
- durableButton.setLayoutData(new GridData(SWT.LEFT, SWT.TOP, true, false));
-
- Composite okCancelButtonsComp = _toolkit.createComposite(shell);
- okCancelButtonsComp.setBackground(shell.getBackground());
- okCancelButtonsComp.setLayoutData(new GridData(SWT.RIGHT, SWT.FILL, true, true));
- okCancelButtonsComp.setLayout(new GridLayout(2,false));
-
- Button okButton = _toolkit.createButton(okCancelButtonsComp, "OK", SWT.PUSH);
- okButton.setLayoutData(new GridData(SWT.RIGHT, SWT.TOP, false, false));
- Button cancelButton = _toolkit.createButton(okCancelButtonsComp, "Cancel", SWT.PUSH);
- cancelButton.setLayoutData(new GridData(SWT.RIGHT, SWT.TOP, false, false));
-
- okButton.addSelectionListener(new SelectionAdapter()
- {
- public void widgetSelected(SelectionEvent e)
- {
- String name = nameText.getText();
-
- if (name == null || name.length() == 0)
- {
- ViewUtility.popupErrorMessage("Create Queue", "Please enter a valid name");
- return;
- }
-
- String owner = ownerText.getText();
-
- if (owner != null && owner.length() == 0)
- {
- owner = null;
- }
-
- boolean durable = durableButton.getSelection();
-
- shell.dispose();
-
- try
- {
- _vhmb.createNewQueue(name, owner, durable);
-
- ViewUtility.operationResultFeedback(null, "Created Queue", null);
- try
- {
- //delay to allow mbean registration notification processing
- Thread.sleep(250);
- }
- catch(InterruptedException ie)
- {
- //ignore
- }
- }
- catch(Exception e5)
- {
- ViewUtility.operationFailedStatusBarMessage("Error creating Queue");
- MBeanUtility.handleException(_mbean, e5);
- }
-
- refresh(_mbean);
- }
- });
-
- cancelButton.addSelectionListener(new SelectionAdapter()
- {
- public void widgetSelected(SelectionEvent e)
- {
- shell.dispose();
- }
- });
-
- shell.setDefaultButton(okButton);
- shell.pack();
- ViewUtility.centerChildInParentShell(parent, shell);
-
- shell.open();
- }
-
- private void createExchange(final Shell parent)
- {
- final Shell shell = ViewUtility.createModalDialogShell(parent, "Create Exchange");
-
- Composite nameComposite = _toolkit.createComposite(shell, SWT.NONE);
- nameComposite.setBackground(shell.getBackground());
- nameComposite.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
- nameComposite.setLayout(new GridLayout(2,false));
-
- _toolkit.createLabel(nameComposite,"Name:").setBackground(shell.getBackground());
- final Text nameText = new Text(nameComposite, SWT.BORDER);
- nameText.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
-
- Composite typeComposite = _toolkit.createComposite(shell, SWT.NONE);
- typeComposite.setBackground(shell.getBackground());
- typeComposite.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
- typeComposite.setLayout(new GridLayout(2,false));
-
- String[] exchangeTypes;
- if(_ApiVersion.greaterThanOrEqualTo(1, 3))//if the server supports Qpid JMX API 1.3
- {//request the current exchange types from the broker
- try
- {
- exchangeTypes = _vhmb.getExchangeTypes();
- }
- catch (IOException e1)
- {
- exchangeTypes = DEFAULT_EXCHANGE_TYPE_VALUES.toArray(new String[DEFAULT_EXCHANGE_TYPE_VALUES.size()]);
- }
- }
- else //use the fallback defaults.
- {
- exchangeTypes = DEFAULT_EXCHANGE_TYPE_VALUES.toArray(new String[DEFAULT_EXCHANGE_TYPE_VALUES.size()]);
- }
-
- _toolkit.createLabel(typeComposite,"Type:").setBackground(shell.getBackground());
- final org.eclipse.swt.widgets.List typeList = new org.eclipse.swt.widgets.List(typeComposite, SWT.SINGLE | SWT.BORDER);
- typeList.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
- typeList.setItems(exchangeTypes);
-
- Composite durableComposite = _toolkit.createComposite(shell, SWT.NONE);
- durableComposite.setBackground(shell.getBackground());
- GridData gridData = new GridData(SWT.FILL, SWT.TOP, true, false);
- gridData.minimumWidth = 220;
- durableComposite.setLayoutData(gridData);
- durableComposite.setLayout(new GridLayout(2,false));
-
- _toolkit.createLabel(durableComposite,"Durable:").setBackground(shell.getBackground());
- final Button durableButton = new Button(durableComposite, SWT.CHECK);
- durableButton.setLayoutData(new GridData(SWT.LEFT, SWT.TOP, true, false));
-
-
- Composite okCancelButtonsComp = _toolkit.createComposite(shell);
- okCancelButtonsComp.setBackground(shell.getBackground());
- okCancelButtonsComp.setLayoutData(new GridData(SWT.RIGHT, SWT.FILL, true, true));
- okCancelButtonsComp.setLayout(new GridLayout(2,false));
-
- Button okButton = _toolkit.createButton(okCancelButtonsComp, "OK", SWT.PUSH);
- okButton.setLayoutData(new GridData(SWT.RIGHT, SWT.TOP, false, false));
- Button cancelButton = _toolkit.createButton(okCancelButtonsComp, "Cancel", SWT.PUSH);
- cancelButton.setLayoutData(new GridData(SWT.RIGHT, SWT.TOP, false, false));
-
- okButton.addSelectionListener(new SelectionAdapter()
- {
- public void widgetSelected(SelectionEvent e)
- {
- String name = nameText.getText();
-
- if (name == null || name.length() == 0)
- {
- ViewUtility.popupErrorMessage("Create Exchange", "Please enter a valid name");
- return;
- }
-
- int selectedTypeIndex = typeList.getSelectionIndex();
-
- if (selectedTypeIndex == -1)
- {
- ViewUtility.popupErrorMessage("Create Exchange", "Please select an Exchange type");
- return;
- }
-
- String type = typeList.getItem(selectedTypeIndex);
-
- boolean durable = durableButton.getSelection();
-
- shell.dispose();
-
- try
- {
- _vhmb.createNewExchange(name, type, durable);
-
- ViewUtility.operationResultFeedback(null, "Created Exchange", null);
- try
- {
- //delay to allow mbean registration notification processing
- Thread.sleep(250);
- }
- catch(InterruptedException ie)
- {
- //ignore
- }
- }
- catch(Exception e5)
- {
- ViewUtility.operationFailedStatusBarMessage("Error creating Exchange");
- MBeanUtility.handleException(_mbean, e5);
- }
-
- refresh(_mbean);
- }
- });
-
- cancelButton.addSelectionListener(new SelectionAdapter()
- {
- public void widgetSelected(SelectionEvent e)
- {
- shell.dispose();
- }
- });
-
- shell.setDefaultButton(okButton);
- shell.pack();
- ViewUtility.centerChildInParentShell(parent, shell);
-
- shell.open();
- }
-
- private void deleteQueuesOrExchanges(Shell parent, final VhostOperations op)
- {
- Table table;
- String windowTitle;
- String dialogueMessage;
- final String feedBackMessage;
- final String failureFeedBackMessage;
-
- if(op.equals(VhostOperations.DELETE_QUEUE))
- {
- table = _queueTable;
- windowTitle = "Delete Queue(s)";
- dialogueMessage = "Delete Queue(s): ";
- feedBackMessage = "Queue(s) deleted";
- failureFeedBackMessage = "Error deleting Queue(s)";
- }
- else
- {
- table = _exchangeTable;
- windowTitle = "Delete Exchange(s)";
- dialogueMessage = "Delete Exchange(s): ";
- feedBackMessage = "Exchange(s) deleted";
- failureFeedBackMessage = "Error deleting Exchange(s)";
- }
-
- int selectionIndex = table.getSelectionIndex();
- if (selectionIndex == -1)
- {
- return;
- }
-
- int[] selectedIndices = table.getSelectionIndices();
-
- final ArrayList<ManagedBean> selectedMBeans = new ArrayList<ManagedBean>();
-
- for(int index = 0; index < selectedIndices.length ; index++)
- {
- ManagedBean selectedMBean = (ManagedBean)table.getItem(selectedIndices[index]).getData();
- selectedMBeans.add(selectedMBean);
- }
-
-
- final Shell shell = ViewUtility.createModalDialogShell(parent, windowTitle);
-
- _toolkit.createLabel(shell, dialogueMessage).setBackground(shell.getBackground());
-
- final Text headerText = new Text(shell, SWT.WRAP | SWT.V_SCROLL | SWT.BORDER );
- headerText.setEditable(false);
- GridData data = new GridData(SWT.FILL, SWT.FILL, false, false);
- data.minimumHeight = 150;
- data.heightHint = 150;
- data.minimumWidth = 400;
- data.widthHint = 400;
- headerText.setLayoutData(data);
-
- String lineSeperator = System.getProperty("line.separator");
- for(ManagedBean mbean : selectedMBeans)
- {
- headerText.append(mbean.getName() + lineSeperator);
- }
- headerText.setSelection(0);
-
- Composite okCancelButtonsComp = _toolkit.createComposite(shell);
- okCancelButtonsComp.setBackground(shell.getBackground());
- okCancelButtonsComp.setLayoutData(new GridData(SWT.RIGHT, SWT.FILL, true, true));
- okCancelButtonsComp.setLayout(new GridLayout(2,false));
-
- Button okButton = _toolkit.createButton(okCancelButtonsComp, "OK", SWT.PUSH);
- okButton.setLayoutData(new GridData(SWT.RIGHT, SWT.TOP, false, false));
- Button cancelButton = _toolkit.createButton(okCancelButtonsComp, "Cancel", SWT.PUSH);
- cancelButton.setLayoutData(new GridData(SWT.RIGHT, SWT.TOP, false, false));
-
- okButton.addSelectionListener(new SelectionAdapter()
- {
- public void widgetSelected(SelectionEvent e)
- {
- shell.dispose();
-
- try
- {
- //perform the deletes
- for(ManagedBean mbean : selectedMBeans)
- {
- switch(op)
- {
- case DELETE_QUEUE:
- _vhmb.deleteQueue(mbean.getName());
- _serverRegistry.removeManagedObject(mbean);
- break;
- case DELETE_EXCHANGE:
- _vhmb.unregisterExchange(mbean.getName());
- break;
- }
- //remove the mbean from the server registry now instead of
- //waiting for an mbean Unregistration Notification to do it
- _serverRegistry.removeManagedObject(mbean);
- }
-
- ViewUtility.operationResultFeedback(null, feedBackMessage, null);
- }
- catch(Exception e1)
- {
- ViewUtility.operationFailedStatusBarMessage(failureFeedBackMessage);
- MBeanUtility.handleException(_mbean, e1);
- }
-
- refresh(_mbean);;
- }
- });
-
- cancelButton.addSelectionListener(new SelectionAdapter()
- {
- public void widgetSelected(SelectionEvent e)
- {
- shell.dispose();
- }
- });
-
- shell.setDefaultButton(okButton);
- shell.pack();
- ViewUtility.centerChildInParentShell(parent, shell);
-
- shell.open();
- }
-
- private enum VhostOperations
- {
- DELETE_QUEUE,
- DELETE_EXCHANGE;
- }
-
- private void openMBean(Table table)
- {
- int selectionIndex = table.getSelectionIndex();
-
- if (selectionIndex == -1)
- {
- return;
- }
-
- ManagedBean selectedMBean = (ManagedBean) table.getItem(selectionIndex).getData();
-
- IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
- MBeanView view = (MBeanView) window.getActivePage().findView(MBeanView.ID);
- try
- {
- view.openMBean(selectedMBean);
- }
- catch (Exception ex)
- {
- MBeanUtility.handleException(selectedMBean, ex);
- }
- }
-}
diff --git a/java/management/eclipse-plugin/src/main/resources/.eclipseproduct b/java/management/eclipse-plugin/src/main/resources/.eclipseproduct
deleted file mode 100644
index 28ee27ca17..0000000000
--- a/java/management/eclipse-plugin/src/main/resources/.eclipseproduct
+++ /dev/null
@@ -1,23 +0,0 @@
-#Eclipse Product File
-#Fri Nov 03 14:47:54 GMT 2006
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-version=1.0-incubating-M2-SNAPSHOT
-name=Qpid Management Console
-id=org.apache.qpid.manager.gui.product
diff --git a/java/management/eclipse-plugin/src/main/resources/jmxremote.sasl-plugin/MANIFEST.MF b/java/management/eclipse-plugin/src/main/resources/jmxremote.sasl-plugin/MANIFEST.MF
deleted file mode 100644
index 83c7c9f435..0000000000
--- a/java/management/eclipse-plugin/src/main/resources/jmxremote.sasl-plugin/MANIFEST.MF
+++ /dev/null
@@ -1,20 +0,0 @@
-Manifest-Version: 1.0
-Bundle-License: http://www.apache.org/licenses/LICENSE-2.0.txt
-Bundle-ManifestVersion: 2
-Bundle-Name: jmx sasl Plug-in
-Bundle-SymbolicName: jmxremote.sasl
-Bundle-Version: 1.0.1
-Bundle-ClassPath: jmxremote_optional.jar
-Export-Package: com.sun.jmx.remote.generic,
- com.sun.jmx.remote.opt.internal,
- com.sun.jmx.remote.opt.security,
- com.sun.jmx.remote.opt.util,
- com.sun.jmx.remote.profile.sasl,
- com.sun.jmx.remote.profile.tls,
- com.sun.jmx.remote.protocol.jmxmp,
- com.sun.jmx.remote.socket,
- javax.management.remote.generic,
- javax.management.remote.jmxmp,
- javax.management.remote.message
-Bundle-Vendor:
-Bundle-Localization: plugin
diff --git a/java/management/eclipse-plugin/src/main/resources/linux-gtk-x86/Configuration/config.ini b/java/management/eclipse-plugin/src/main/resources/linux-gtk-x86/Configuration/config.ini
deleted file mode 100644
index dc15366740..0000000000
--- a/java/management/eclipse-plugin/src/main/resources/linux-gtk-x86/Configuration/config.ini
+++ /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.
-###############################################################################
-
-#Product Runtime Configuration File
-
-osgi.splashPath=platform:/base/plugins/org.apache.qpid.management.ui
-eclipse.product=org.apache.qpid.management.ui.product
-osgi.bundles.defaultStartLevel=4
-osgi.bundles=jmxremote.sasl, \
-qpid-management-common, \
-org.apache.qpid.management.ui, \
-com.ibm.icu, \
-org.eclipse.core.commands, \
-org.eclipse.core.contenttype, \
-org.eclipse.core.databinding, \
-org.eclipse.core.expressions, \
-org.eclipse.core.jobs, \
-org.eclipse.core.runtime@start, \
-org.eclipse.core.runtime.compatibility.registry, \
-org.eclipse.equinox.app,org.eclipse.equinox.common, \
-org.eclipse.equinox.preferences, \
-org.eclipse.equinox.registry, \
-org.eclipse.help, \
-org.eclipse.jface, \
-org.eclipse.jface.databinding, \
-org.eclipse.swt, \
-org.eclipse.swt.gtk.linux.x86, \
-org.eclipse.ui, \
-org.eclipse.ui.forms, \
-org.eclipse.ui.workbench, \
-org.eclipse.equinox.launcher, \
-org.eclipse.equinox.launcher.gtk.linux.x86, \
-org.apache.commons.codec
diff --git a/java/management/eclipse-plugin/src/main/resources/linux-gtk-x86/libcairo-swt.so b/java/management/eclipse-plugin/src/main/resources/linux-gtk-x86/libcairo-swt.so
deleted file mode 100644
index b66f95814e..0000000000
--- a/java/management/eclipse-plugin/src/main/resources/linux-gtk-x86/libcairo-swt.so
+++ /dev/null
Binary files differ
diff --git a/java/management/eclipse-plugin/src/main/resources/linux-gtk-x86/qpidmc b/java/management/eclipse-plugin/src/main/resources/linux-gtk-x86/qpidmc
deleted file mode 100644
index 0cc5c65455..0000000000
--- a/java/management/eclipse-plugin/src/main/resources/linux-gtk-x86/qpidmc
+++ /dev/null
Binary files differ
diff --git a/java/management/eclipse-plugin/src/main/resources/linux-gtk-x86/qpidmc.ini b/java/management/eclipse-plugin/src/main/resources/linux-gtk-x86/qpidmc.ini
deleted file mode 100644
index 19ceb6f717..0000000000
--- a/java/management/eclipse-plugin/src/main/resources/linux-gtk-x86/qpidmc.ini
+++ /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.
-###############################################################################
-
--vmargs
--Xms40m
--Xmx256m
--XX:MaxPermSize=256m
--Dosgi.requiredJavaVersion=1.5
--Declipse.consoleLog=true
-
-#===============================================
-# SSL trust store configuration options.
-#===============================================
-
-# Uncomment lines below to specify custom truststore for server SSL
-# certificate verification, eg when using self-signed server certs.
-#
-#-Djavax.net.ssl.trustStore=<path.to.truststore>
-#-Djavax.net.ssl.trustStorePassword=<truststore.password>
-
-
diff --git a/java/management/eclipse-plugin/src/main/resources/linux-gtk-x86_64/Configuration/config.ini b/java/management/eclipse-plugin/src/main/resources/linux-gtk-x86_64/Configuration/config.ini
deleted file mode 100644
index f437e830b5..0000000000
--- a/java/management/eclipse-plugin/src/main/resources/linux-gtk-x86_64/Configuration/config.ini
+++ /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.
-###############################################################################
-
-#Product Runtime Configuration File
-
-osgi.splashPath=platform:/base/plugins/org.apache.qpid.management.ui
-eclipse.product=org.apache.qpid.management.ui.product
-osgi.bundles.defaultStartLevel=4
-osgi.bundles=jmxremote.sasl, \
-qpid-management-common, \
-org.apache.qpid.management.ui, \
-com.ibm.icu, \
-org.eclipse.core.commands, \
-org.eclipse.core.contenttype, \
-org.eclipse.core.databinding, \
-org.eclipse.core.expressions, \
-org.eclipse.core.jobs, \
-org.eclipse.core.runtime@start, \
-org.eclipse.core.runtime.compatibility.registry, \
-org.eclipse.equinox.app,org.eclipse.equinox.common, \
-org.eclipse.equinox.preferences, \
-org.eclipse.equinox.registry, \
-org.eclipse.help, \
-org.eclipse.jface, \
-org.eclipse.jface.databinding, \
-org.eclipse.swt, \
-org.eclipse.swt.gtk.linux.x86_64, \
-org.eclipse.ui, \
-org.eclipse.ui.forms, \
-org.eclipse.ui.workbench, \
-org.eclipse.equinox.launcher, \
-org.eclipse.equinox.launcher.gtk.linux.x86_64, \
-org.apache.commons.codec
diff --git a/java/management/eclipse-plugin/src/main/resources/linux-gtk-x86_64/libcairo-swt.so b/java/management/eclipse-plugin/src/main/resources/linux-gtk-x86_64/libcairo-swt.so
deleted file mode 100644
index 5734427fb8..0000000000
--- a/java/management/eclipse-plugin/src/main/resources/linux-gtk-x86_64/libcairo-swt.so
+++ /dev/null
Binary files differ
diff --git a/java/management/eclipse-plugin/src/main/resources/linux-gtk-x86_64/qpidmc b/java/management/eclipse-plugin/src/main/resources/linux-gtk-x86_64/qpidmc
deleted file mode 100644
index ff1f3a7507..0000000000
--- a/java/management/eclipse-plugin/src/main/resources/linux-gtk-x86_64/qpidmc
+++ /dev/null
Binary files differ
diff --git a/java/management/eclipse-plugin/src/main/resources/linux-gtk-x86_64/qpidmc.ini b/java/management/eclipse-plugin/src/main/resources/linux-gtk-x86_64/qpidmc.ini
deleted file mode 100644
index 19ceb6f717..0000000000
--- a/java/management/eclipse-plugin/src/main/resources/linux-gtk-x86_64/qpidmc.ini
+++ /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.
-###############################################################################
-
--vmargs
--Xms40m
--Xmx256m
--XX:MaxPermSize=256m
--Dosgi.requiredJavaVersion=1.5
--Declipse.consoleLog=true
-
-#===============================================
-# SSL trust store configuration options.
-#===============================================
-
-# Uncomment lines below to specify custom truststore for server SSL
-# certificate verification, eg when using self-signed server certs.
-#
-#-Djavax.net.ssl.trustStore=<path.to.truststore>
-#-Djavax.net.ssl.trustStorePassword=<truststore.password>
-
-
diff --git a/java/management/eclipse-plugin/src/main/resources/macosx/Configuration/config.ini b/java/management/eclipse-plugin/src/main/resources/macosx/Configuration/config.ini
deleted file mode 100644
index 3ac3aa20f3..0000000000
--- a/java/management/eclipse-plugin/src/main/resources/macosx/Configuration/config.ini
+++ /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.
-###############################################################################
-
-#Product Runtime Configuration File
-
-osgi.splashPath=platform:/base/plugins/org.apache.qpid.management.ui
-eclipse.product=org.apache.qpid.management.ui.product
-osgi.bundles.defaultStartLevel=4
-osgi.bundles=jmxremote.sasl, \
-qpid-management-common, \
-org.apache.qpid.management.ui, \
-com.ibm.icu, \
-org.eclipse.core.commands, \
-org.eclipse.core.contenttype, \
-org.eclipse.core.databinding, \
-org.eclipse.core.expressions, \
-org.eclipse.core.jobs, \
-org.eclipse.core.runtime@start, \
-org.eclipse.core.runtime.compatibility.registry, \
-org.eclipse.equinox.app,org.eclipse.equinox.common, \
-org.eclipse.equinox.preferences, \
-org.eclipse.equinox.registry, \
-org.eclipse.help, \
-org.eclipse.jface, \
-org.eclipse.jface.databinding, \
-org.eclipse.swt, \
-org.eclipse.swt.carbon.macosx, \
-org.eclipse.ui, \
-org.eclipse.ui.forms, \
-org.eclipse.ui.workbench, \
-org.eclipse.equinox.launcher, \
-org.eclipse.equinox.launcher.carbon.macosx, \
-org.apache.commons.codec
diff --git a/java/management/eclipse-plugin/src/main/resources/macosx/Contents/Info.plist b/java/management/eclipse-plugin/src/main/resources/macosx/Contents/Info.plist
deleted file mode 100644
index c6482a9254..0000000000
--- a/java/management/eclipse-plugin/src/main/resources/macosx/Contents/Info.plist
+++ /dev/null
@@ -1,55 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.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.
- -
- -->
-<plist version="1.0">
-<dict>
- <key>CFBundleExecutable</key>
- <string>qpidmc</string>
- <key>CFBundleGetInfoString</key>
- <string>Apache Qpid Management Console for Mac OS X</string>
- <key>CFBundleIconFile</key>
- <string>Console.icns</string>
- <key>CFBundleIdentifier</key>
- <string>org.apache.qpid.management.ui</string>
- <key>CFBundleInfoDictionaryVersion</key>
- <string>6.0</string>
- <key>CFBundleName</key>
- <string>Qpid Management Console</string>
- <key>CFBundlePackageType</key>
- <string>APPL</string>
- <key>CFBundleShortVersionString</key>
- <string>3.4</string>
- <key>CFBundleSignature</key>
- <string>????</string>
- <key>CFBundleVersion</key>
- <string>3.4</string>
- <key>Qpid Management Console</key>
- <array>
- <string>-consoleLog</string>
- <string>-showlocation</string>
- <!-- WARNING:
- If you try to add a single VM argument (-vmargs) here,
- *all* vmargs specified in qpidmc.ini will be ignored.
- We recommend to add all arguments in MacOS/qpidmc.ini -->
- </array>
-</dict>
-</plist>
diff --git a/java/management/eclipse-plugin/src/main/resources/macosx/Contents/MacOS/qpidmc b/java/management/eclipse-plugin/src/main/resources/macosx/Contents/MacOS/qpidmc
deleted file mode 100755
index 36247a08e4..0000000000
--- a/java/management/eclipse-plugin/src/main/resources/macosx/Contents/MacOS/qpidmc
+++ /dev/null
Binary files differ
diff --git a/java/management/eclipse-plugin/src/main/resources/macosx/Contents/MacOS/qpidmc.ini b/java/management/eclipse-plugin/src/main/resources/macosx/Contents/MacOS/qpidmc.ini
deleted file mode 100644
index 2a31b9b2c7..0000000000
--- a/java/management/eclipse-plugin/src/main/resources/macosx/Contents/MacOS/qpidmc.ini
+++ /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.
-###############################################################################
-
--startup
-../../plugins/org.eclipse.equinox.launcher_1.0.101.R34x_v20080819.jar
---launcher.library
-../../plugins/org.eclipse.equinox.launcher.carbon.macosx_1.0.101.R34x_v20080731
--vmargs
--XstartOnFirstThread
--Xms40m
--Xmx512m
--XX:MaxPermSize=256m
--Dosgi.requiredJavaVersion=1.5
--Declipse.consoleLog=true
--Dorg.eclipse.swt.internal.carbon.smallFonts
-
-#===============================================
-# SSL trust store configuration options.
-#===============================================
-
-# Uncomment lines below to specify custom truststore for server SSL
-# certificate verification, eg when using self-signed server certs.
-#
-#-Djavax.net.ssl.trustStore=<path.to.truststore>
-#-Djavax.net.ssl.trustStorePassword=<truststore.password>
-
diff --git a/java/management/eclipse-plugin/src/main/resources/macosx/Contents/Resources/Console.icns b/java/management/eclipse-plugin/src/main/resources/macosx/Contents/Resources/Console.icns
deleted file mode 100644
index 610976efab..0000000000
--- a/java/management/eclipse-plugin/src/main/resources/macosx/Contents/Resources/Console.icns
+++ /dev/null
Binary files differ
diff --git a/java/management/eclipse-plugin/src/main/resources/solaris-gtk-sparc/Configuration/config.ini b/java/management/eclipse-plugin/src/main/resources/solaris-gtk-sparc/Configuration/config.ini
deleted file mode 100644
index a99a8b3f7d..0000000000
--- a/java/management/eclipse-plugin/src/main/resources/solaris-gtk-sparc/Configuration/config.ini
+++ /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.
-###############################################################################
-
-#Product Runtime Configuration File
-
-osgi.splashPath=platform:/base/plugins/org.apache.qpid.management.ui
-eclipse.product=org.apache.qpid.management.ui.product
-osgi.bundles.defaultStartLevel=4
-osgi.bundles=jmxremote.sasl, \
-qpid-management-common, \
-org.apache.qpid.management.ui, \
-com.ibm.icu, \
-org.eclipse.core.commands, \
-org.eclipse.core.contenttype, \
-org.eclipse.core.databinding, \
-org.eclipse.core.expressions, \
-org.eclipse.core.jobs, \
-org.eclipse.core.runtime@start, \
-org.eclipse.core.runtime.compatibility.registry, \
-org.eclipse.equinox.app,org.eclipse.equinox.common, \
-org.eclipse.equinox.preferences, \
-org.eclipse.equinox.registry, \
-org.eclipse.help, \
-org.eclipse.jface, \
-org.eclipse.jface.databinding, \
-org.eclipse.swt, \
-org.eclipse.swt.gtk.solaris.sparc, \
-org.eclipse.ui, \
-org.eclipse.ui.forms, \
-org.eclipse.ui.workbench, \
-org.eclipse.equinox.launcher, \
-org.eclipse.equinox.launcher.gtk.solaris.sparc, \
-org.apache.commons.codec
diff --git a/java/management/eclipse-plugin/src/main/resources/solaris-gtk-sparc/Qpidmc.l.pm b/java/management/eclipse-plugin/src/main/resources/solaris-gtk-sparc/Qpidmc.l.pm
deleted file mode 100644
index 995d7c9bb0..0000000000
--- a/java/management/eclipse-plugin/src/main/resources/solaris-gtk-sparc/Qpidmc.l.pm
+++ /dev/null
@@ -1,311 +0,0 @@
-/* XPM */
-static char *ProductIcon48[] = {
-/* columns rows colors chars-per-pixel */
-"48 48 257 2",
-" c black",
-". c gray100",
-"X c #69695A5AE8E8",
-"o c #494949499191",
-"O c #CECE9292BFBF",
-"+ c #E7E7CACAE0E0",
-"@ c #C8C88C8CBBBB",
-"# c #C2C28A8ABABA",
-"$ c #EAEAD7D7E8E8",
-"% c #CFCFA9A9CCCC",
-"& c #D9D9BCBCD8D8",
-"* c #B6B68787B9B9",
-"= c #C3C39999C7C7",
-"- c #A7A77D7DB5B5",
-"; c #BDBDA3A3CDCD",
-": c #D8D8CACAE3E3",
-"> c #A8A88D8DC4C4",
-", c #92927575B2B2",
-"< c #87876C6CAAAA",
-"1 c #9A9A8383BABA",
-"2 c #7B7B6363A3A3",
-"3 c #666654549595",
-"4 c #73735F5FADAD",
-"5 c #626251519292",
-"6 c #7F7F7272A7A7",
-"7 c #6D6D5E5E9E9E",
-"8 c #64645454A9A9",
-"9 c #77776969B1B1",
-"0 c #49493E3E8282",
-"q c #7D7D7373B6B6",
-"w c #5B5B4E4EADAD",
-"e c #55554949BABA",
-"r c #56564949BABA",
-"t c #56564A4ABABA",
-"y c #56564949B9B9",
-"u c #55554949B8B8",
-"i c #4F4F4444ACAC",
-"p c #53534848B4B4",
-"a c #53534848B3B3",
-"s c #54544949B5B5",
-"d c #52524747B0B0",
-"f c #52524747AFAF",
-"g c #54544949B3B3",
-"h c #DEDEDCDCEEEE",
-"j c #3E3E36369898",
-"k c #43433B3B9F9F",
-"l c #33332C2C7777",
-"z c #42423A3A9C9C",
-"x c #4A4A4040A8A8",
-"c c #55554A4ABABA",
-"v c #55554A4AB9B9",
-"b c #54544949B7B7",
-"n c #52524848B1B1",
-"m c #51514747AEAE",
-"M c #4E4E4545A9A9",
-"N c #49494141A0A0",
-"B c #52524848AFAF",
-"V c #51514848AEAE",
-"C c #50504747ACAC",
-"Z c #4F4F4646AAAA",
-"A c #51514848ADAD",
-"S c #50504747ABAB",
-"D c #50504848ACAC",
-"F c #50504747A9A9",
-"G c #4E4E4646A7A7",
-"H c #4E4E4545A4A4",
-"J c #4D4D4545A4A4",
-"K c #4F4F4747A8A8",
-"L c #4E4E4646A5A5",
-"P c #4D4D4545A3A3",
-"I c #3B3B35357D7D",
-"U c #4E4E4646A3A3",
-"Y c #55554D4D9F9F",
-"T c #4A4A43438989",
-"R c #51514B4B9090",
-"E c #67676060A5A5",
-"W c #1D1D18186A6A",
-"Q c #272722227D7D",
-"! c #282823237D7D",
-"~ c #2B2B26268181",
-"^ c #33332C2C8989",
-"/ c #3B3B36368E8E",
-"( c #454540409797",
-") c #4D4D4646A4A4",
-"_ c #4C4C4545A1A1",
-"` c #4D4D4646A2A2",
-"' c #4B4B4545A0A0",
-"] c #4D4D4646A1A1",
-"[ c #4C4C45459F9F",
-"{ c #4B4B45459E9E",
-"} c #4A4A44449C9C",
-"| c #494944449898",
-" . c #484843439696",
-".. c #4A4A45459999",
-"X. c #4F4F4A4AA0A0",
-"o. c #68686363AAAA",
-"O. c #21211D1D7676",
-"+. c #242420207575",
-"@. c #2D2D2A2A7F7F",
-"#. c #2D2D2A2A7B7B",
-"$. c #3D3D39398F8F",
-"%. c #484844449696",
-"&. c #474743439393",
-"*. c #464643439191",
-"=. c #454542428E8E",
-"-. c #4D4D4A4A9C9C",
-";. c #57575454A3A3",
-":. c #5A5A58589797",
-">. c #5F5F5D5D9999",
-",. c #85858282C1C1",
-"<. c #95959292C9C9",
-"1. c #B8B8B6B6DCDC",
-"2. c #070705055353",
-"3. c #080807075555",
-"4. c #0A0A09095757",
-"5. c #0C0C0B0B5858",
-"6. c #0F0F0D0D5C5C",
-"7. c #10100F0F5C5C",
-"8. c #131311116464",
-"9. c #141413136060",
-"0. c #141413135F5F",
-"q. c #171715156767",
-"w. c #161615156262",
-"e. c #161615156161",
-"r. c #181817176464",
-"t. c #1A1A19196666",
-"y. c #1C1C1A1A6464",
-"u. c #1D1D1C1C6868",
-"i. c #1F1F1E1E6A6A",
-"p. c #222221216C6C",
-"a. c #242423236F6F",
-"s. c #272725257171",
-"d. c #272726267272",
-"f. c #272726267171",
-"g. c #292928287474",
-"h. c #2A2A29297474",
-"j. c #2C2C2B2B7777",
-"k. c #2F2F2E2E7C7C",
-"l. c #2E2E2D2D7979",
-"z. c #343433337E7E",
-"x. c #393937378686",
-"c. c #373736368181",
-"v. c #3A3A39398484",
-"b. c #3A3A39398383",
-"n. c #3D3D3B3B8686",
-"m. c #424241418C8C",
-"M. c #424241418B8B",
-"N. c #444442428B8B",
-"B. c #434341418989",
-"V. c #454544448E8E",
-"C. c #454544448D8D",
-"Z. c #424241418787",
-"A. c #434342428888",
-"S. c #444442428787",
-"D. c #424241418585",
-"F. c #414140408383",
-"G. c #484847479090",
-"H. c #434342428686",
-"J. c #4A4A49499393",
-"K. c #464645458A8A",
-"L. c #4D4D4C4C9595",
-"P. c #54545252A0A0",
-"I. c #50504F4F9898",
-"U. c #58585757A0A0",
-"Y. c #525250509393",
-"T. c #5B5B5959A2A2",
-"R. c #585857579F9F",
-"E. c #62626161A9A9",
-"W. c #64646363ACAC",
-"Q. c #6B6B6A6AB2B2",
-"!. c #6B6B6A6AB1B1",
-"~. c #75757474B8B8",
-"^. c #7F7F7D7DBDBD",
-"/. c #9C9C9B9BCFCF",
-"(. c #0B0B0B0B5858",
-"). c #0D0D0D0D5A5A",
-"_. c #111111115E5E",
-"`. c #131313136060",
-"'. c #212121216D6D",
-"]. c #242424246F6F",
-"[. c #2B2B2C2C7777",
-"{. c #2B2B2B2B7777",
-"}. c #2C2C2C2C7777",
-"|. c #2E2E2E2E7979",
-" X c #313131317C7C",
-".X c #313131317B7B",
-"XX c #343434347E7E",
-"oX c #3C3C3C3C8686",
-"OX c #3F3F3F3F8989",
-"+X c #414142428B8B",
-"@X c #424242428B8B",
-"#X c #474747479090",
-"$X c #414141418484",
-"%X c #404040408181",
-"&X c #4A4A4A4A9494",
-"*X c #4A4A4A4A9393",
-"=X c #4D4D4D4D9696",
-"-X c #4F4F4F4F9898",
-";X c #505050509898",
-":X c #525252529B9B",
-">X c #555555559E9E",
-",X c #555555559D9D",
-"<X c #57575858A0A0",
-"1X c #58585858A0A0",
-"2X c #575758589F9F",
-"3X c #575757579F9F",
-"4X c #5A5A5A5AA2A2",
-"5X c #5D5D5D5DA5A5",
-"6X c #5F5F5F5FA7A7",
-"7X c #61616262AAAA",
-"8X c #61616161A9A9",
-"9X c #61616262A9A9",
-"0X c #62626262AAAA",
-"qX c #64646464ACAC",
-"wX c #62626262A9A9",
-"eX c #64646464ABAB",
-"rX c #66666666AEAE",
-"tX c #66666666ADAD",
-"yX c #68686868B0B0",
-"uX c #69696969AFAF",
-"iX c #6D6D6D6DB4B4",
-"pX c #6F6F6F6FB5B5",
-"aX c #73737373BABA",
-"sX c #71717171B7B7",
-"dX c #76767676BCBC",
-"fX c #79797979BFBF",
-"gX c #77777777B9B9",
-"hX c #80808080C1C1",
-"jX c #8C8C8C8CC5C5",
-"kX c #90909090C9C9",
-"lX c #98989898CBCB",
-"zX c #A0A0A0A0CFCF",
-"xX c #A5A5A5A5D3D3",
-"cX c #ABABABABD6D6",
-"vX c #C4C4C4C4E3E3",
-"bX c #D1D1D1D1E9E9",
-"nX c #E5E5E5E5F3F3",
-"mX c #9F9FA0A0D1D1",
-"MX c #B6B6C5C5E5E5",
-"NX c #8E8EA6A6D6D6",
-"BX c #9090A7A7D7D7",
-"VX c #9191A9A9D7D7",
-"CX c #9595ABABD8D8",
-"ZX c #9999AFAFDADA",
-"AX c #9D9DB2B2DCDC",
-"SX c #A1A1B5B5DDDD",
-"DX c #A5A5B8B8DEDE",
-"FX c #A9A9BBBBE0E0",
-"GX c #ACACBDBDE1E1",
-"HX c #B0B0C1C1E3E3",
-"JX c #B4B4C4C4E4E4",
-"KX c #B8B8C7C7E5E5",
-"LX c #BBBBC9C9E6E6",
-"PX c #AEAEC0C0E2E2",
-"IX c #B2B2C3C3E3E3",
-"UX c gray100",
-"YX c None",
-/* pixels */
-"YXX X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X YX",
-"X %X%X%XF.F.F.F.$XD.Z.Z.Z.B.B.B.N.N.=.=.=.*.*.*.&.&. . .| ....} } { { _ _ P P H G G G K S S C o ",
-"X %X%X%X%XF.F.$XD.D.Z.Z.B.A.B.N.N.N.=.=.=.*.*.&.&.%.%.%.| | ..} { { [ _ _ ` U J L G K F Z S C o ",
-"X %X%X%X%XF.F.F.D.D.H.Z.Z.A.B.N.N.N.C.=.=.*.*.&.&. . .%.| | ..} } { [ [ _ P P H G G K F S S C o ",
-"X %XF.%XF.F.$XF.$XZ.Z.Z.B.A.K.Y.7 , - - 1 1 ^.^.~.aX~.q 9 6XY { } { ' _ ] P P H L G K F Z S C o ",
-"X %XF.F.F.F.F.D.D.Z.Z.Z.K.:.1 ; % ; <.hXfXfXdXaXaXsXpXiX!.yXrXo.;.X.[ _ _ ` H H G K K F S S C o ",
-"X F.F.F.F.F.D.D.D.Z.H.Y.1 & & 1.cXmX/.kXfXdXaXaXsXpXiXQ.yXtXeXE.6X5XP.X._ ` J L G G K F Z S C o ",
-"X D.$XF.$XD.D.Z.Z.S.>.% + : vX1.1.cXmX/.dXaXaXsXpXiXQ.uXrXqX8X6X5XT.R.P.X.P ) H G K K S S S m o ",
-"X D.$XD.D.D.D.D.S.6 & $ h bXvXvX1.xX/.kXfXaXsXpXiXQ.yXrXW.E.6X5X4XU.,X:XI.-.` L G G K F Z C C o ",
-"X D.D.D.D.D.Z.H.6 & $ h h h bXvX1.cXmXkX,.dXpXiXQ.yXtXqXwX6X5XT.U.,X:XI.=X*X..` G K K Z S S m o ",
-"X Z.D.Z.H.Z.Z.7 & $ h h nXh bXvX1.cXmXkX,.gXiXQ.uXrXW.E.6X5X4XU.,X:X-XL.J.#XV. .P G F S S C m o ",
-"X Z.Z.Z.H.Z.R % + : bXh h h bXvX1.cX/.kXhX~.Q.yXrXqX9X6X5X4X2X,X:X;X=X*X#XV.M.OX( K Z S S C m o ",
-"X Z.Z.Z.A.A.* & & vXvXbXbXbXvXvX1.xXlXjX^.pXuXrXeXwX6X5X4XU.,X:X-XL.*XG.V.@XOXoXb.( Z S C C V o ",
-"X B.B.B.A.2 % % 1.1.vXvXvXvXvX1.cXzX<.,.gXiXrXW.E.6X5X4XU.,X:XI.=X*X#XV.@XOXn.b.c.x.N S S C m o ",
-"X B.B.B.S.* % ; xX1.1.1.1.1.cXcXzXlXjX^.pXrXeX7X6X5X4XR.,X:X-XL.J.#XV.@XOXn.b.c.XX X$.S C C m o ",
-"X N.N.N.2 O = /.mXxXcXcXcXcXxXzXlXjXhX~.uXeXE.6X5X4XU.,X:X-XL.J.#XV.M.OXn.v.c.z. X|.k.N D V f o ",
-"X N.N.N.- @ > kX<././.mXzXzXlX<.jXhXgXuXeXE.6X5X4X1X,X:XI.L.*X#XV.m.OXn.b.c.z. Xl.j.g./ C m V o ",
-"X N.N.R @ # ,.,.jXkXkX<.kXkXjX,.^.~.uXwXE.6X5X4X1X,X:XI.=XJ.#XC.M.OXn.v.c.z..X|.j.g.d.#.M m B o ",
-"X =.M.< @ * fXfXhXhX,.,.,.hX^.gXpXuXqX9X6X5X4XU.,X:XI.L.*XG.V.+XOXn.b.c.z..X|.[.g.d.a.p.z V B o ",
-"X =.N.- @ NXNXBXBXBXVXCXCXCXCXZXZXZXZXAXAXSXSXSXDXDXDXFXFXFXGXPXPXHXHXIXJXMXMXMXKXKXLXLXLXB d o ",
-"X =.=.* @ 1 dXdXaXaXsXpXiX!.yXrXeXwX6X5X4X<X,X:XI.=X*XG.V.M.OXn.v.c.XX.X|.j.g.d.a.p.i.u.@.f d o ",
-"X *.=.# @ ^.dXaXaXsXpXiXQ.yXrXeXwX6X5XT.U.,X:X-XL.&XG.C.m.OXoXv.c.z..X|.j.g.f.a.p.i.u.t.+.d d o ",
-"X *.*.@ @ NXNXNXBXVXVXCXCXCXCXZXZXZXZXAXAXAXSXSXDXDXDXFXFXGXGXPXPXHXHXJXJXJXMXKXKXKXLXLXLXd n o ",
-"X &.*.@ @ dXaXsXpXiXQ.yXtXeXE.6X5X4XU.>X:XI.L.*XG.V.m.OXoXv.c.z. X|.j.g.d.a.'.i.u.t.r.w.9.d n o ",
-"X &.&.@ @ ~.sXpXiXQ.yXtXW.E.6X5X4X1X,X:XI.=X*X#XC.m.OXn.b.c.z. X|.[.g.f.a.p.i.u.t.r.w.9.0.n a o ",
-"X &.&.@ @ NXNXBXBXVXVXVXCXCXCXZXZXZXZXAXAXSXSXSXDXDXDXFXFXGXGXPXPXHXIXIXJXMXMXKXKXKXLXLXLXn n o ",
-"X %. .# @ q iXQ.yXrXW.0X6X5X4XU.>X:XI.L.*X#XV.@XOXn.b.c.XX.X|.{.g.f.].'.i.u.t.r.w.0._.7.W n a o ",
-"X %. .* # , Q.yXtXeX7X6X5X4XU.,X:X-XL.*X#XV.@XOXn.b.c.XX Xl.{.g.d.a.p.i.u.t.r.e.0._.7.).+.a a o ",
-"X | | - # NXNXNXBXVXVXCXCXCXCXZXZXZXAXAXAXAXSXSXDXDXDXFXFXGXGXPXPXHXHXIXJXMXMXMXKXKXLXLXLXa a o ",
-"X | | < # - rXeX9X6X5X4XU.,X:X-XL.*X#XC.@XOXoXb.c.z. X|.j.h.s.a.'.i.u.t.r.w.9._.7.).5.4.j a p o ",
-"X | } Y # * 9 8X6X5X4X3X,X:XI.=X*XG.V.@XOXn.v.c.XX X|.j.g.f.a.p.i.u.t.r.e.0._.7.).5.4.q.i g p o ",
-"X } } | - # , 6X5X4XR.,X:XI.=X*XG.V.m.OXoXb.c.XX X|.j.g.f.a.p.i.u.t.r.e.9._.7.).5.4.3.~ a s s o ",
-"X } } } 4 # - E 4XU.>X:X-X=XJ.#XV.M.OXoXb.c.XX X|.{.h.d.a.'.i.u.t.r.e.9._.7.).5.4.3.6.z p s s o ",
-"X { { } } - # < U.,X:XI.=X*XG.V.+XOXoXb.c.z. X|.}.g.d.a.'.i.u.t.r.w.0._.7.).5.4.3.2.! g p s s o ",
-"X [ { ' [ 4 * - E :X;XL.J.#XV.m.OXoXb.c.z..X|.j.h.f.a.'.i.u.t.r.w.9._.6.).(.4.3.2.8.k p s s s o ",
-"X [ [ ' _ [ , * , ;XL.J.#XV.@XOXoXv.c.z..X|.{.g.f.a.p.i.u.t.r.w.`._.7.).(.4.3.2.2.^ s p s s s o ",
-"X _ _ _ _ P ] - * 2 *X#XV.m.OXn.v.c.XX X|.j.h.f.a.p.i.u.t.r.w.`._.7.).(.4.3.2.2.Q p s s s b u o ",
-"X ` ` ` ` ` ` 8 - - 7 V.@XOXoXv.c.XX.X|.j.g.d.a.'.i.u.t.r.w.0._.7.).5.4.3.2.2.O.x p s s s u u o ",
-"X P P ) P U U ) 8 - - 7 OXn.v.c.XX X|.j.h.f.a.p.i.u.t.r.w.0._.7.).5.4.3.2.2.O.x s s s s b u u o ",
-"X L L ) H ) L L L 8 1 - 7 b.c.z. X|.j.h.f.a.'.i.u.t.r.w.0._.7.).5.4.3.2.2.Q x p s s s b b u e o ",
-"X L G L G G G G G G G , * 2 T .Xl.j.h.f.a.p.i.u.t.r.e.0._.7.).5.4.3.2.8.^ p p s s s s u u e e o ",
-"X G G G G G G G K K M M 4 , , 3 I g.d.a.p.i.u.t.r.e.`._.7.).5.4.3.7.! k p s p s s s u u u e v o ",
-"X K G K K K K K K Z Z M F F 4 , < 3 I p.i.u.t.r.w.9._.7.).5.4.W ~ z a p p s s b s u u u e e e o ",
-"X F Z F F F F Z Z F F S S S S S w 9 < 2 5 0 l p.e.9.y.a.l ^ j i a p p p s s b b b u e v y r e o ",
-"X S Z Z S Z S Z S S S S S C C C A m d V f m B m B d d n d a a a p s p s s b u u u u e v e r t o ",
-"X S S S S S S S S S S C C C m m A V V B B B d d d n n a a a p p s p s s b u u u e e e c t r t o ",
-"X C C C C C C C C m C A m A m f V f f B d d d n n n a a a a s s s s s u b u u u u v t t r t t o ",
-"YXo o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o YX"
-};
diff --git a/java/management/eclipse-plugin/src/main/resources/solaris-gtk-sparc/Qpidmc.m.pm b/java/management/eclipse-plugin/src/main/resources/solaris-gtk-sparc/Qpidmc.m.pm
deleted file mode 100644
index e64aa0cc06..0000000000
--- a/java/management/eclipse-plugin/src/main/resources/solaris-gtk-sparc/Qpidmc.m.pm
+++ /dev/null
@@ -1,295 +0,0 @@
-/* XPM */
-static char *ProductIcon32[] = {
-/* columns rows colors chars-per-pixel */
-"32 32 257 2",
-" c black",
-". c gray100",
-"X c #69695A5AE8E8",
-"o c #494949499191",
-"O c #E8E8CBCBE0E0",
-"+ c #DDDDB3B3D2D2",
-"@ c #F0F0DDDDEBEB",
-"# c #CDCD9191BEBE",
-"$ c #C8C88B8BBBBB",
-"% c #CACA9898C2C2",
-"& c #C3C38A8ABBBB",
-"* c #BABA8787B9B9",
-"= c #DCDCC4C4DEDE",
-"- c #C5C5A3A3CACA",
-"; c #ADAD8181B8B8",
-": c #A3A37A7AB5B5",
-"> c #E2E2D6D6E9E9",
-", c #B3B39A9AC4C4",
-"< c #EBEBE3E3F0F0",
-"1 c #C9C9B6B6D6D6",
-"2 c #96967676B8B8",
-"3 c #8C8C7171ABAB",
-"4 c #A4A49292BEBE",
-"5 c #7D7D6565A6A6",
-"6 c #83836D6DABAB",
-"7 c #9A9A8787C2C2",
-"8 c #7B7B6464B7B7",
-"9 c #5E5E50509191",
-"0 c #646457579A9A",
-"q c #85857B7BBEBE",
-"w c #7C7C7373B6B6",
-"e c #62625353D5D5",
-"r c #61615353D4D4",
-"t c #60605252D1D1",
-"y c #5F5F5252D0D0",
-"u c #5F5F5151CFCF",
-"i c #60605353D2D2",
-"p c #5F5F5252CFCF",
-"a c #5E5E5151CDCD",
-"s c #5C5C4F4FC7C7",
-"d c #5F5F5252CDCD",
-"f c #5E5E5151CBCB",
-"g c #5B5B4F4FC4C4",
-"h c #5A5A4E4EC1C1",
-"j c #71716969B0B0",
-"k c #48483E3EADAD",
-"l c #5D5D5151CDCD",
-"z c #5C5C5050C9C9",
-"x c #5D5D5151CBCB",
-"c c #5C5C5050C7C7",
-"v c #5B5B4F4FC6C6",
-"b c #5B5B5050C6C6",
-"n c #59594E4EC1C1",
-"m c #58584D4DBFBF",
-"M c #59594F4FC2C2",
-"N c #5A5A4F4FC2C2",
-"B c #58584D4DBCBC",
-"V c #57574D4DBCBC",
-"C c #59594E4EBEBE",
-"Z c #58584E4EBDBD",
-"A c #58584D4DBBBB",
-"S c #57574D4DBABA",
-"D c #56564D4DB9B9",
-"F c #56564C4CB6B6",
-"G c #55554C4CB6B6",
-"H c #54544B4BB4B4",
-"J c #54544B4BB1B1",
-"K c #53534B4BB1B1",
-"L c #52524A4AAEAE",
-"P c #51514949ACAC",
-"I c #51514949ABAB",
-"U c #474741418787",
-"Y c #32322C2C8F8F",
-"T c #2B2B25257777",
-"R c #36362F2F9696",
-"E c #2B2B26266E6E",
-"W c #4D4D4545ACAC",
-"Q c #55554D4DB8B8",
-"! c #54544C4CB4B4",
-"~ c #54544C4CB3B3",
-"^ c #51514A4AACAC",
-"/ c #51514A4AABAB",
-"( c #50504949A9A9",
-") c #4F4F4949A6A6",
-"_ c #4C4C4747A1A1",
-"` c #4E4E4848A3A3",
-"' c #4D4D4848A1A1",
-"] c #4B4B46469C9C",
-"[ c #4C4C47479E9E",
-"{ c #51514C4CA6A6",
-"} c #A9A9A6A6D5D5",
-"| c #1E1E1A1A6666",
-" . c #292925258181",
-".. c #3D3D39399292",
-"X. c #4A4A46469B9B",
-"o. c #53534E4EABAB",
-"O. c #494945459797",
-"+. c #4A4A46469999",
-"@. c #474744449494",
-"#. c #484845459494",
-"$. c #474744449292",
-"%. c #464643439090",
-"&. c #464642428D8D",
-"*. c #54545050A9A9",
-"=. c #474744448F8F",
-"-. c #4C4C49499999",
-";. c #57575454A6A6",
-":. c #5B5B5757AAAA",
-">. c #545451519B9B",
-",. c #5A5A57579C9C",
-"<. c #65656262A7A7",
-"1. c #68686666A2A2",
-"2. c #CACAC9C9E5E5",
-"3. c #050504045151",
-"4. c #080807075454",
-"5. c #0A0A09095858",
-"6. c #0C0C0A0A5858",
-"7. c #10100E0E6262",
-"8. c #0E0E0D0D5A5A",
-"9. c #121211115D5D",
-"0. c #131312125D5D",
-"q. c #161615156161",
-"w. c #171716166161",
-"e. c #1A1A19196565",
-"r. c #20201E1E7070",
-"t. c #1E1E1D1D6969",
-"y. c #2A2A29297676",
-"u. c #2F2F2D2D7676",
-"i. c #3A3A39398787",
-"p. c #3A3A39398383",
-"a. c #3F3F3E3E8888",
-"s. c #414140408989",
-"d. c #454543438D8D",
-"f. c #444442428B8B",
-"g. c #444443438C8C",
-"h. c #434342428A8A",
-"j. c #434341418888",
-"k. c #434342428989",
-"l. c #424241418787",
-"z. c #434342428787",
-"x. c #424241418585",
-"c. c #41413F3F8181",
-"v. c #414140408282",
-"b. c #484846468D8D",
-"n. c #494948489090",
-"m. c #4B4B4A4A9191",
-"M. c #4B4B49498E8E",
-"N. c #525251519A9A",
-"B. c #525251519999",
-"V. c #565654549A9A",
-"C. c #545453539494",
-"Z. c #60605F5FA7A7",
-"A. c #64646363ABAB",
-"S. c #5A5A59599797",
-"D. c #68686767ADAD",
-"F. c #6C6C6B6BB2B2",
-"G. c #5E5E5D5D9A9A",
-"H. c #76767575BABA",
-"J. c #78787777BBBB",
-"K. c #76767474B5B5",
-"L. c #7E7E7D7DBABA",
-"P. c #A5A5A4A4D2D2",
-"I. c #040404045252",
-"U. c #070707075454",
-"Y. c #070708085353",
-"T. c #080808085454",
-"R. c #0A0A0B0B5757",
-"E. c #0E0E0E0E5A5A",
-"W. c #111112125E5E",
-"Q. c #111111115E5E",
-"!. c #111111115D5D",
-"~. c #111112125D5D",
-"^. c #161616166868",
-"/. c #151516166161",
-"(. c #151515156161",
-"). c #19191A1A6565",
-"_. c #191919196565",
-"`. c #1A1A1A1A6464",
-"'. c #1D1D1E1E6969",
-"]. c #1E1E1E1E6969",
-"[. c #222222226D6D",
-"{. c #272727277171",
-"}. c #2B2B2C2C7676",
-"|. c #2B2B2B2B7676",
-" X c #2B2B2B2B7575",
-".X c #303030307A7A",
-"XX c #303030307979",
-"oX c #353535357F7F",
-"OX c #393939398383",
-"+X c #3A3A3A3A8383",
-"@X c #3F3F3F3F8787",
-"#X c #434343438C8C",
-"$X c #434344448C8C",
-"%X c #424242428686",
-"&X c #414141418484",
-"*X c #484848489191",
-"=X c #484849499090",
-"-X c #4D4D4D4D9696",
-";X c #515151519D9D",
-":X c #4D4D4D4D9595",
-">X c #515152529A9A",
-",X c #515152529999",
-"<X c #525252529A9A",
-"1X c #525252529999",
-"2X c #565657579E9E",
-"3X c #575757579D9D",
-"4X c #5B5B5B5BA2A2",
-"5X c #5F5F6060A6A6",
-"6X c #5F5F5F5FA6A6",
-"7X c #63636464AAAA",
-"8X c #64646464AAAA",
-"9X c #67676767AEAE",
-"0X c #67676868AEAE",
-"qX c #68686868AEAE",
-"wX c #6F6F6F6FB5B5",
-"eX c #6C6C6C6CB1B1",
-"rX c #73737373B8B8",
-"tX c #82828282BEBE",
-"yX c #86868686C2C2",
-"uX c #89898989C4C4",
-"iX c #98989898CBCB",
-"pX c #A0A0A0A0CFCF",
-"aX c #A9A9A9A9D5D5",
-"sX c #B0B0B0B0D8D8",
-"dX c #B8B8B8B8DDDD",
-"fX c #BDBDBDBDE0E0",
-"gX c #D9D9D9D9EDED",
-"hX c #90909191C6C6",
-"jX c #71718989BCBC",
-"kX c #73738B8BBFBF",
-"lX c #72728989BCBC",
-"zX c #79799090C3C3",
-"xX c #7E7E9595C7C7",
-"cX c #81819898CACA",
-"vX c #84849B9BCCCC",
-"bX c #8C8CA3A3D4D4",
-"nX c #71718A8ABCBC",
-"mX c #73738B8BBDBD",
-"MX c #75758D8DBFBF",
-"NX c #74748C8CBEBE",
-"BX c #76768E8EC0C0",
-"VX c #7C7C9494C6C6",
-"CX c #7B7B9393C4C4",
-"ZX c #7F7F9797C9C9",
-"AX c #82829A9ACBCB",
-"SX c #85859E9ECECE",
-"DX c #8888A0A0D1D1",
-"FX c #87879F9FD0D0",
-"GX c #8B8BA4A4D4D4",
-"HX c #8B8BA3A3D4D4",
-"JX c #8989A1A1D2D2",
-"KX c #8D8DA5A5D6D6",
-"LX c #8B8BA3A3D3D3",
-"PX c #8E8EA6A6D6D6",
-"IX c #8D8DA5A5D5D5",
-"UX c gray100",
-"YX c None",
-/* pixels */
-"YXX X X X X X X X X X X X X X X X X X X X X X X X X X X X X X YX",
-"X v.v.v.v.&Xl.z.k.&.d.%.$.@.O.+.] [ _ ` ) ( ^ L K ! G D V m m o ",
-"X c.c.c.v.&Xx.z.f.f.d.%.$.#.O.+.X.[ _ ` ) ( / L K H F D V C n o ",
-"X v.c.v.v.x.x.z.k.f.n.V.,.>.-.+.] [ _ ` ) ( ^ L K H G D V C h o ",
-"X &Xv.&Xx.x.l.j.M.1.4 - - , 7 q J.H.K.j :.*.P L K H F S B C n o ",
-"X x.&Xx.x.z.j.S., = = 1 } iXuXH.rXwXF.qX7XZ.;.o.J ! F S B m n o ",
-"X x.l.z.%Xz.G.1 @ > 2.dXaXiXuXrXwXF.qX8X5X4X2X;X{ H F S V C n o ",
-"X z.j.j.j.C.1 @ < gX2.fXaXpXuXwXeX9X7X5X4X2XN.:X*X_ D S Z m h o ",
-"X k.k.h.b., O > gXgX2.dXaXiXyXF.D.A.Z.4X3X1X:Xn.g.a._ V B m N o ",
-"X f.f.f.3 + = 2.2.2.fXsXpXhXtXD.8XZ.4X2X1X:X*X$X@Xp.i.W C n N o ",
-"X d.&.%.% + 1 dXdXdXsXP.iXyXK.8X5X4X2X>X:X*Xg.a.+XoX.X..m n N o ",
-"X %.=.5 % - P.} aXP.pXiXyXK.D.Z.4X3X1X-Xn.$X@X+XoX.X Xy.W h g o ",
-"X $.$.: # PXIXGXGXLXJXFXFXSXvXAXcXZXxXVXCXzXzXBXMXkXmXnXjXh g o ",
-"X #.@.* $ 7 yXuXyXtXL.K.D.6X4X2X1X:Xo g.a.OXoX.X|.{.[.t. .g v o ",
-"X O.#.$ $ q H.rXwXF.0XA.6X4X2X1X:Xo $Xa.p.oX.X|.{.[.'.`.r.g b o ",
-"X X.+.$ $ PXKXbXbXLXJXDXFXSXvXAXcXZXxXCXCXzXBXBXMXNXmXlXjXb c o ",
-"X ] ] $ $ H.wXF.0X7X6X4X2X<X:Xo #Xa.+XoX.X|.{.[.].)./.~.Q.c z o ",
-"X [ [ & & w F.qX7XZ.4X2X,X:Xo #Xa.+XoX.X}.{.[.'.e./.9.E.^.c z o ",
-"X ' _ * & PXKXbXHXLXJXDXSXSXvXAXcXZXxXVXCXzXzXBXMXNXkXjXjXz x o ",
-"X ` ` : & 2 8XZ.4X2XB.:X*Xg.@Xp.oX.X|.{.[.].).q.!.E.R.U.Y z f o ",
-"X ) ) 5 & ; <.4X2X>X:Xo #Xa.+XoXXX|.{.[.t._.q.~.E.R.4.5.k x a o ",
-"X ( ( I ; * 6 2X>X:X=X$X@X+XoX.X|.{.[.t.e./.W.E.R.Y.3. .z a a o ",
-"X I ^ / 8 * : 0 :X*X#X@X+XoX.X|.{.[.'._.(.~.E.R.T.3.7.k x a p o ",
-"X L L L ^ 2 * 3 m.$Xa.p.oX.X}.{.[.t.).(.~.E.6.T.3.I.R x a a y o ",
-"X J K K K K 2 * 5 s.OXoX.X}.{.[.'._.(.9.8.R.4.3.I.Y x l a p t o ",
-"X ~ H H ! ! ! 2 ; 5 U XX}.{.[.].e.(.W.E.R.U.3.7.R x l u u y t o ",
-"X G F G G G Q Q 8 : 3 9 u.[.]._./.Q.E.R.T.6. .k x a a u t t t o ",
-"X D S D S D S S S V 8 2 6 9 c.E w.0.| T Y k z z a a p t t i r o ",
-"X A V B V V V B B m m n n h h g g g c z z z l l d p y t i r r o ",
-"X m C C C C C C C n n n M N g g b c z z x a a a u y t t r r e o ",
-"X n n n n n h h h N N g g v b s z z z x a p p u t t r r r e e o ",
-"YXo o o o o o o o o o o o o o o o o o o o o o o o o o o o o o YX"
-};
diff --git a/java/management/eclipse-plugin/src/main/resources/solaris-gtk-sparc/Qpidmc.s.pm b/java/management/eclipse-plugin/src/main/resources/solaris-gtk-sparc/Qpidmc.s.pm
deleted file mode 100644
index e2b9379f3a..0000000000
--- a/java/management/eclipse-plugin/src/main/resources/solaris-gtk-sparc/Qpidmc.s.pm
+++ /dev/null
@@ -1,287 +0,0 @@
-/* XPM */
-static char *ProductIcon24[] = {
-/* columns rows colors chars-per-pixel */
-"24 24 257 2",
-" c black",
-". c gray100",
-"X c #69695A5AE8E8",
-"o c #494949499191",
-"O c #F1F1DFDFECEC",
-"+ c #D7D7ACACCDCD",
-"@ c #DFDFBBBBD6D6",
-"# c #E2E2C4C4DBDB",
-"$ c #CECE9C9CC4C4",
-"% c #C4C48B8BBABA",
-"& c #C2C28A8ABABA",
-"* c #C4C48E8EBCBC",
-"= c #BFBF8A8AB9B9",
-"- c #EBEBD9D9E9E9",
-"; c #BFBF8888B9B9",
-": c #D8D8B9B9D6D6",
-"> c #B9B98686B9B9",
-", c #B8B88989B9B9",
-"< c #BBBB9393BFBF",
-"1 c #A9A97B7BB2B2",
-"2 c #E4E4D4D4E7E7",
-"3 c #C6C6AFAFCECE",
-"4 c #A6A68080B6B6",
-"5 c #A2A27E7EB4B4",
-"6 c #9E9E7E7EB1B1",
-"7 c #ABAB9090BBBB",
-"8 c #B7B7A0A0C5C5",
-"9 c #9D9D7C7CB2B2",
-"0 c #AAAA8B8BBEBE",
-"q c #AAAA9090BCBC",
-"w c #8C8C6B6BABAB",
-"e c #90907070B1B1",
-"r c #C4C4B3B3D7D7",
-"t c #CDCDBFBFDDDD",
-"y c #EAEAE4E4F1F1",
-"u c #88886A6AADAD",
-"i c #9E9E8585C1C1",
-"p c #84846A6AAFAF",
-"a c #81816B6BAAAA",
-"s c #D7D7CFCFE6E6",
-"d c #81816969B1B1",
-"f c #78786363A5A5",
-"g c #6E6E5D5D9C9C",
-"h c #717160609D9D",
-"j c #83837474AAAA",
-"k c #6A6A5757A3A3",
-"l c #6E6E5E5EA0A0",
-"z c #5E5E50509292",
-"x c #88887B7BBCBC",
-"c c #68685858ABAB",
-"v c #5A5A4D4DA2A2",
-"b c #7D7D7373B4B4",
-"n c #5A5A4E4EA6A6",
-"m c #5F5F56569595",
-"M c #56564A4ABBBB",
-"N c #56564949B9B9",
-"B c #55554949B8B8",
-"V c #53534848B3B3",
-"C c #54544949B4B4",
-"Z c #52524747B0B0",
-"A c #52524747AFAF",
-"S c #5B5B53539393",
-"D c #3E3E36369797",
-"F c #49494040A6A6",
-"G c #48484040A5A5",
-"H c #55554A4ABABA",
-"J c #54544949B7B7",
-"K c #53534949B4B4",
-"L c #51514747AFAF",
-"P c #52524848B1B1",
-"I c #51514848B0B0",
-"U c #51514848AEAE",
-"Y c #51514747ADAD",
-"T c #51514848ADAD",
-"R c #4F4F4747ABAB",
-"E c #50504747ABAB",
-"W c #50504646A9A9",
-"Q c #4F4F4646A8A8",
-"! c #4E4E4646A7A7",
-"~ c #4E4E4545A4A4",
-"^ c #4D4D4545A4A4",
-"/ c #4E4E4646A5A5",
-"( c #4D4D4545A1A1",
-") c #3D3D36367E7E",
-"_ c #4B4B44449C9C",
-"` c #2A2A25257F7F",
-"' c #3E3E37379898",
-"] c #474740409C9C",
-"[ c #4D4D4646A4A4",
-"{ c #4C4C4545A2A2",
-"} c #4D4D4646A2A2",
-"| c #4D4D4646A1A1",
-" . c #4B4B45459F9F",
-".. c #4C4C45459F9F",
-"X. c #4C4C46469F9F",
-"o. c #4B4B45459D9D",
-"O. c #494943439898",
-"+. c #494944449A9A",
-"@. c #4A4A45459A9A",
-"#. c #494944449898",
-"$. c #484843439696",
-"%. c #494944449797",
-"&. c #484843439595",
-"*. c #51514C4CA1A1",
-"=. c #6B6B6767AEAE",
-"-. c #95959191C9C9",
-";. c #23231F1F7676",
-":. c #21211E1E7070",
-">. c #292925257F7F",
-",. c #252521217070",
-"<. c #242421216D6D",
-"1. c #2B2B27278080",
-"2. c #393935358C8C",
-"3. c #444440409494",
-"4. c #3B3B38388282",
-"5. c #474743439494",
-"6. c #484844449595",
-"7. c #474743439393",
-"8. c #474744449393",
-"9. c #464643439191",
-"0. c #454542428F8F",
-"q. c #4A4A47479898",
-"w. c #464643438F8F",
-"e. c #454542428D8D",
-"r. c #444441418B8B",
-"t. c #484844449191",
-"y. c #444441418989",
-"u. c #494946469090",
-"i. c #4C4C48489393",
-"p. c #51514E4E9E9E",
-"a. c #73737070B6B6",
-"s. c #77777474BBBB",
-"d. c #A0A09E9ED1D1",
-"f. c #D6D6D5D5EBEB",
-"g. c #0E0E0D0D5A5A",
-"h. c #11110F0F5E5E",
-"j. c #121211115E5E",
-"k. c #131312125F5F",
-"l. c #171716166363",
-"z. c #1D1D1B1B6868",
-"x. c #1D1D1C1C6868",
-"c. c #222221216E6E",
-"v. c #222221216D6D",
-"b. c #282827277474",
-"n. c #282827277373",
-"m. c #292928287373",
-"M. c #2F2F2E2E7979",
-"N. c #353534347F7F",
-"B. c #363635358181",
-"V. c #3C3C3B3B8585",
-"C. c #424241418C8C",
-"Z. c #424241418B8B",
-"A. c #444442428B8B",
-"S. c #434341418989",
-"D. c #434342428989",
-"F. c #424241418787",
-"G. c #414140408484",
-"H. c #474745458D8D",
-"J. c #434342428787",
-"K. c #424241418585",
-"L. c #414140408282",
-"P. c #494948489191",
-"I. c #4F4F4E4E9797",
-"U. c #59595757A6A6",
-"Y. c #5F5F5D5DA4A4",
-"T. c #6C6C6B6BB3B3",
-"R. c #7C7C7B7BB9B9",
-"E. c #A8A8A7A7D3D3",
-"W. c #0D0D0D0D5A5A",
-"Q. c #1F1F1F1F6C6C",
-"!. c #222222226E6E",
-"~. c #3B3B3B3B8585",
-"^. c #414141418C8C",
-"/. c #414141418B8B",
-"(. c #424242428B8B",
-"). c #484848489292",
-"_. c #404040408181",
-"`. c #4E4E4E4E9898",
-"'. c #555555559E9E",
-"]. c #555555559D9D",
-"[. c #5B5B5B5BA3A3",
-"{. c #5C5C5C5CA3A3",
-"}. c #61616161A9A9",
-"|. c #66666666AEAE",
-" X c #66666666ADAD",
-".X c #6B6B6B6BB2B2",
-"XX c #70707070B7B7",
-"oX c #6A6A6A6AADAD",
-"OX c #74747474BBBB",
-"+X c #89898989C2C2",
-"@X c #90909090C8C8",
-"#X c #8F8F8F8FC6C6",
-"$X c #92929292C6C6",
-"%X c #9F9F9F9FCFCF",
-"&X c #A5A5A5A5D2D2",
-"*X c #B5B5B5B5DBDB",
-"=X c #B8B8B8B8DEDE",
-"-X c #B7B7B7B7DCDC",
-";X c #BBBBBBBBDEDE",
-":X c #BDBDBDBDDFDF",
-">X c #C9C9C9C9E5E5",
-",X c #D1D1D1D1EAEA",
-"<X c #7C7C7D7DBABA",
-"1X c #89898A8AC7C7",
-"2X c #8F8F9090C7C7",
-"3X c #A3A3A4A4D3D3",
-"4X c #A2A2B5B5DEDE",
-"5X c #ADADBDBDE1E1",
-"6X c #B9B9C7C7E5E5",
-"7X c #BABAC8C8E6E6",
-"8X c #8E8EA6A6D6D6",
-"9X c #9090A7A7D7D7",
-"0X c #9191A9A9D7D7",
-"qX c #9292A9A9D8D8",
-"wX c #9494ABABD8D8",
-"eX c #9898AEAED9D9",
-"rX c #9B9BB0B0DADA",
-"tX c #9E9EB3B3DCDC",
-"yX c #A1A1B5B5DDDD",
-"uX c #A5A5B8B8DEDE",
-"iX c #A8A8BBBBE0E0",
-"pX c #ACACBEBEE1E1",
-"aX c #AFAFC0C0E3E3",
-"sX c #B3B3C3C3E4E4",
-"dX c #B2B2C2C2E3E3",
-"fX c #B5B5C5C5E5E5",
-"gX c #B8B8C7C7E6E6",
-"hX c #B6B6C5C5E4E4",
-"jX c #9797AEAED9D9",
-"kX c #A1A1B6B6DDDD",
-"lX c #A8A8BBBBDFDF",
-"zX c gray100",
-"xX c black",
-"cX c black",
-"vX c black",
-"bX c black",
-"nX c black",
-"mX c black",
-"MX c black",
-"NX c black",
-"BX c black",
-"VX c black",
-"CX c black",
-"ZX c black",
-"AX c black",
-"SX c black",
-"DX c black",
-"FX c black",
-"GX c black",
-"HX c black",
-"JX c black",
-"KX c black",
-"LX c black",
-"PX c black",
-"IX c black",
-"UX c black",
-"YX c None",
-/* pixels */
-"YXX X X X X X X X X X X X X X X X X X X X X X YX",
-"X _._.L.G.K.F.D.A.e.0.9.&.$.%.+._ ..{ ^ ! W E o ",
-"X L.L.L.G.F.F.D.r.e.0.9.7.&.O.@.o. .{ ~ ! Q E o ",
-"X L.G.G.K.F.S.y.r.e.w.9.5.$.+.@.o...( ~ ! W E o ",
-"X G.K.K.F.J.D.h 6 0 i x s.a.=.U.*...} ~ ! W E o ",
-"X K.F.F.F.S 7 : r d.1XOXXX.X|.}.[.p.| / ! W E o ",
-"X F.F.F.m 3 - s =X3X@XXXT. X}.[.].I.q.{ Q E T o ",
-"X S.D.H.8 O y ,X;X&X2X.X|.}.[.].I.P.C.3.Q E Y o ",
-"X A.r.j # 2 f.>X*X%X+X|.}.[.].I.P.^.~.B.] E Y o ",
-"X e.u.q @ t :X-XE.$X<X}.[.].`.P.Z.V.N.M.2.Y L o ",
-"X 0.i.< + 8X8XqXwXeXrXtX4XuXlXpXaXsXfXgX7XY A o ",
-"X 9.t.* $ -.#X+XR.oX{.'.`.P.(.~.N.M.m.c.Q.T Z o ",
-"X 8.7.; % 8X9X0XwXeXrXtXyXuXiXpXaXdXfXgX7XL Z o ",
-"X 6.&.1 & b X}.[.'.I.P./.~.N.M.n.!.x.l.:.I P o ",
-"X #.#.w = 8X9XqXwXjXrXtXkXuXiX5XaXsXhX6X7XP V o ",
-"X +.+.k > 5 Y.].I.)./.~.N.M.b.v.x.l.k.h.' V C o ",
-"X o.o.o.u , a I.).Z.V.N.M.n.c.z.l.j.W.` P V C o ",
-"X .. .X.v e 4 l ^.V.N.M.m.!.x.l.j.g.;.F V C J o ",
-"X ( | ( ( n p 9 g 4.M.n.c.x.l.j.h.>.G V K C J o ",
-"X ~ [ [ ^ / / c d f z ) <.z.,.1.D P V C C B B o ",
-"X ! Q ! Q Q Q Q W E E Y T A Z P V V K C J B B o ",
-"X Q W Q W R W E E T T T L Z P V V K J J J B N o ",
-"X R E E E E E Y Y U L Z P P P C V J J B B H M o ",
-"YXo o o o o o o o o o o o o o o o o o o o o o YX"
-};
diff --git a/java/management/eclipse-plugin/src/main/resources/solaris-gtk-sparc/Qpidmc.t.pm b/java/management/eclipse-plugin/src/main/resources/solaris-gtk-sparc/Qpidmc.t.pm
deleted file mode 100644
index 3f6b21f428..0000000000
--- a/java/management/eclipse-plugin/src/main/resources/solaris-gtk-sparc/Qpidmc.t.pm
+++ /dev/null
@@ -1,279 +0,0 @@
-/* XPM */
-static char *ProductIcon16[] = {
-/* columns rows colors chars-per-pixel */
-"16 16 257 2",
-" c black",
-". c gray100",
-"X c #E2E2C0C0D9D9",
-"o c #EDEDD9D9E8E8",
-"O c #D5D5ABABCDCD",
-"+ c #E2E2C3C3DCDC",
-"@ c #C5C58E8EBCBC",
-"# c #D4D4ABABCDCD",
-"$ c #CACA9F9FC6C6",
-"% c #D6D6B4B4D3D3",
-"& c #CACAA0A0C8C8",
-"* c #C6C69D9DC6C6",
-"= c #C5C59F9FC8C8",
-"- c #CCCCACACCECE",
-"; c #CCCCB0B0D3D3",
-": c #A6A68383B3B3",
-"> c #BABA9A9AC6C6",
-", c #B7B79A9AC2C2",
-"< c #E3E3D5D5E9E9",
-"1 c #B0B08E8EC0C0",
-"2 c #9F9F8080B8B8",
-"3 c #AFAF9898C1C1",
-"4 c #DBDBCFCFE5E5",
-"5 c #96967878B2B2",
-"6 c #9A9A7E7EBABA",
-"7 c #8E8E7878AFAF",
-"8 c #91917F7FBDBD",
-"9 c #D3D3CCCCE4E4",
-"0 c #535348488B8B",
-"q c #69695A5AE8E8",
-"w c #55554949B9B9",
-"e c #55554949B8B8",
-"r c #54544848B6B6",
-"t c #53534848B4B4",
-"y c #54544848B4B4",
-"u c #53534848B3B3",
-"i c #53534848B2B2",
-"p c #52524747AFAF",
-"a c #53534848B1B1",
-"s c #54544949B8B8",
-"d c #54544949B6B6",
-"f c #52524848B3B3",
-"g c #52524848B2B2",
-"h c #53534949B3B3",
-"j c #52524848B1B1",
-"k c #52524848B0B0",
-"l c #51514747AEAE",
-"z c #52524848AFAF",
-"x c #51514848AEAE",
-"c c #51514747ADAD",
-"v c #51514747ACAC",
-"b c #4F4F4646AAAA",
-"n c #51514848ADAD",
-"m c #50504747ABAB",
-"M c #50504747AAAA",
-"N c #4F4F4646A8A8",
-"B c #50504747A9A9",
-"V c #4E4E4646A7A7",
-"C c #4E4E4646A6A6",
-"Z c #4F4F4646A6A6",
-"A c #4F4F4747A7A7",
-"S c #4D4D4545A3A3",
-"D c #4D4D4545A2A2",
-"F c #4C4C45459E9E",
-"G c #74746E6EB3B3",
-"H c #2E2E29298383",
-"J c #383832329090",
-"K c #464640409999",
-"L c #4D4D4646A2A2",
-"P c #4E4E4747A3A3",
-"I c #4B4B45459F9F",
-"U c #4B4B45459E9E",
-"Y c #4C4C46469F9F",
-"T c #4A4A44449B9B",
-"R c #4A4A44449A9A",
-"E c #494943439797",
-"W c #494944449797",
-"Q c #484843439494",
-"! c #78787474B8B8",
-"~ c #272724247878",
-"^ c #2D2D2A2A7575",
-"/ c #484844449797",
-"( c #474743439393",
-") c #454542429090",
-"_ c #4B4B48489A9A",
-"` c #464643438F8F",
-"' c #464643438E8E",
-"] c #454542428C8C",
-"[ c #51514D4DA0A0",
-"{ c #5C5C5959A5A5",
-"} c #535350509090",
-"| c #C8C8C7C7E3E3",
-" . c #121211115D5D",
-".. c #1A1A19196565",
-"X. c #242422226D6D",
-"o. c #3F3F3E3E8888",
-"O. c #444442428D8D",
-"+. c #444442428989",
-"@. c #424241418787",
-"#. c #454543438A8A",
-"$. c #434342428888",
-"%. c #424241418686",
-"&. c #414140408484",
-"*. c #414140408383",
-"=. c #424240408383",
-"-. c #414140408282",
-";. c #474746468D8D",
-":. c #464644448989",
-">. c #525251519999",
-",. c #64646363AAAA",
-"<. c #61615F5FA2A2",
-"1. c #6E6E6C6CB2B2",
-"2. c #A5A5A4A4D3D3",
-"3. c #B0B0AFAFD6D6",
-"4. c #111112125D5D",
-"5. c #19191A1A6565",
-"6. c #1E1E1E1E6C6C",
-"7. c #222222226D6D",
-"8. c #2B2B2B2B7676",
-"9. c #2B2B2B2B7575",
-"0. c #2B2B2C2C7575",
-"q. c #343435357F7F",
-"w. c #343435357E7E",
-"e. c #353535357F7F",
-"r. c #3E3E3E3E8888",
-"t. c #3E3E3E3E8787",
-"y. c #414141418484",
-"u. c #404040408282",
-"i. c #484849499191",
-"p. c #494949499191",
-"a. c #484848489090",
-"s. c #484849499090",
-"d. c #404040408080",
-"f. c #525252529A9A",
-"g. c #525252529999",
-"h. c #5B5B5B5BA3A3",
-"j. c #5B5B5B5BA2A2",
-"k. c #64646464ABAB",
-"l. c #63636464AAAA",
-"z. c #6B6B6C6CB2B2",
-"x. c #72727373B9B9",
-"c. c #71717171A4A4",
-"v. c #78787878ABAB",
-"b. c #7F7F7F7FB1B1",
-"n. c #8C8C8C8CBEBE",
-"m. c #A5A5A5A5D2D2",
-"M. c #C9C9C9C9E5E5",
-"N. c #85858686B7B7",
-"B. c #91919292C4C4",
-"V. c #71718989BCBC",
-"C. c #73738B8BBEBE",
-"Z. c #75758D8DC0C0",
-"A. c #78789090C3C3",
-"S. c #7A7A9292C5C5",
-"D. c #71718A8ABDBD",
-"F. c #76768E8EC0C0",
-"G. c #78789090C2C2",
-"H. c #7B7B9393C5C5",
-"J. c #7D7D9595C7C7",
-"K. c #80809999CACA",
-"L. c #7E7E9696C7C7",
-"P. c #83839B9BCDCD",
-"I. c #83839B9BCCCC",
-"U. c #86869E9ECFCF",
-"Y. c #8888A1A1D1D1",
-"T. c #8A8AA2A2D3D3",
-"R. c #8989A1A1D1D1",
-"E. c #8B8BA3A3D3D3",
-"W. c gray100",
-"Q. c black",
-"!. c black",
-"~. c black",
-"^. c black",
-"/. c black",
-"(. c black",
-"). c black",
-"_. c black",
-"`. c black",
-"'. c black",
-"]. c black",
-"[. c black",
-"{. c black",
-"}. c black",
-"|. c black",
-" X c black",
-".X c black",
-"XX c black",
-"oX c black",
-"OX c black",
-"+X c black",
-"@X c black",
-"#X c black",
-"$X c black",
-"%X c black",
-"&X c black",
-"*X c black",
-"=X c black",
-"-X c black",
-";X c black",
-":X c black",
-">X c black",
-",X c black",
-"<X c black",
-"1X c black",
-"2X c black",
-"3X c black",
-"4X c black",
-"5X c black",
-"6X c black",
-"7X c black",
-"8X c black",
-"9X c black",
-"0X c black",
-"qX c black",
-"wX c black",
-"eX c black",
-"rX c black",
-"tX c black",
-"yX c black",
-"uX c black",
-"iX c black",
-"pX c black",
-"aX c black",
-"sX c black",
-"dX c black",
-"fX c black",
-"gX c black",
-"hX c black",
-"jX c black",
-"kX c black",
-"lX c black",
-"zX c black",
-"xX c black",
-"cX c black",
-"vX c black",
-"bX c black",
-"nX c black",
-"mX c black",
-"MX c black",
-"NX c black",
-"BX c black",
-"VX c black",
-"CX c black",
-"ZX c black",
-"AX c black",
-"SX c black",
-"DX c black",
-"FX c black",
-"GX c black",
-"HX c black",
-"JX c black",
-"KX c black",
-"LX c black",
-"PX c black",
-"IX c black",
-"UX c black",
-"YX c None",
-/* pixels */
-"YXq q q q q q q q q q q q q q YX",
-"q d.-.y.%.+.O.` ( E R U D C B p.",
-"q u.*.&.$.#.] ) Q W T F L V M p.",
-"q =.y.} , % ; 8 ! 1.{ [ S Z b p.",
-"q @.:.- o 4 2.x.z.,.j.>._ A m p.",
-"q +.: X < M.m.z.l.j.g.s.r.K v p.",
-"q ' $ + 9 | 3.B.n.N.b.v.c.<.n p.",
-"q ` O T.Y.U.P.K.L.S.G.F.C.D.l p.",
-"q ( # @ G k.h.g.i.t.e.9.7.6.z p.",
-"q / * E.R.U.I.K.J.H.A.Z.C.V.a p.",
-"q T 2 & 5 f.a.o.q.8.7...4.J u p.",
-"q I Y 1 = 7 ;.w.0.7.5. .H f y p.",
-"q L D P 6 > 3 0 ^ X.~ J i t d p.",
-"q C C V A N M m n p k g y r e p.",
-"q M b M m m c x p j h y d s w p.",
-"YXp.p.p.p.p.p.p.p.p.p.p.p.p.p.YX"
-};
diff --git a/java/management/eclipse-plugin/src/main/resources/solaris-gtk-sparc/qpidmc b/java/management/eclipse-plugin/src/main/resources/solaris-gtk-sparc/qpidmc
deleted file mode 100755
index b88ff49e8e..0000000000
--- a/java/management/eclipse-plugin/src/main/resources/solaris-gtk-sparc/qpidmc
+++ /dev/null
Binary files differ
diff --git a/java/management/eclipse-plugin/src/main/resources/solaris-gtk-sparc/qpidmc.ini b/java/management/eclipse-plugin/src/main/resources/solaris-gtk-sparc/qpidmc.ini
deleted file mode 100644
index cfa715e5a8..0000000000
--- a/java/management/eclipse-plugin/src/main/resources/solaris-gtk-sparc/qpidmc.ini
+++ /dev/null
@@ -1,40 +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.
-###############################################################################
--startup
-plugins/org.eclipse.equinox.launcher_1.0.101.R34x_v20080819.jar
---launcher.library
-plugins/org.eclipse.equinox.launcher.gtk.solaris.sparc_1.0.101.R34x_v20080731
--vmargs
--Xms40m
--Xmx256m
--XX:MaxPermSize=256m
--Dosgi.requiredJavaVersion=1.5
--Declipse.consoleLog=true
-
-#===============================================
-# SSL trust store configuration options.
-#===============================================
-
-# Uncomment lines below to specify custom truststore for server SSL
-# certificate verification, eg when using self-signed server certs.
-#
-#-Djavax.net.ssl.trustStore=<path.to.truststore>
-#-Djavax.net.ssl.trustStorePassword=<truststore.password>
-
-
diff --git a/java/management/eclipse-plugin/src/main/resources/win32-win32-x86/Configuration/config.ini b/java/management/eclipse-plugin/src/main/resources/win32-win32-x86/Configuration/config.ini
deleted file mode 100644
index a61bea2fa8..0000000000
--- a/java/management/eclipse-plugin/src/main/resources/win32-win32-x86/Configuration/config.ini
+++ /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.
-###############################################################################
-
-#Product Runtime Configuration File
-
-osgi.splashPath=platform:/base/plugins/org.apache.qpid.management.ui
-eclipse.product=org.apache.qpid.management.ui.product
-osgi.bundles.defaultStartLevel=4
-osgi.bundles=jmxremote.sasl, \
-qpid-management-common, \
-org.apache.qpid.management.ui, \
-com.ibm.icu, \
-org.eclipse.core.commands, \
-org.eclipse.core.contenttype, \
-org.eclipse.core.databinding, \
-org.eclipse.core.expressions, \
-org.eclipse.core.jobs, \
-org.eclipse.core.runtime@start, \
-org.eclipse.core.runtime.compatibility.registry, \
-org.eclipse.equinox.app,org.eclipse.equinox.common, \
-org.eclipse.equinox.preferences, \
-org.eclipse.equinox.registry, \
-org.eclipse.help, \
-org.eclipse.jface, \
-org.eclipse.jface.databinding, \
-org.eclipse.swt, \
-org.eclipse.swt.win32.win32.x86, \
-org.eclipse.ui, \
-org.eclipse.ui.forms, \
-org.eclipse.ui.workbench, \
-org.eclipse.equinox.launcher, \
-org.eclipse.equinox.launcher.win32.win32.x86, \
-org.apache.commons.codec
diff --git a/java/management/eclipse-plugin/src/main/resources/win32-win32-x86/qpidmc.exe b/java/management/eclipse-plugin/src/main/resources/win32-win32-x86/qpidmc.exe
deleted file mode 100644
index 3999884bfb..0000000000
--- a/java/management/eclipse-plugin/src/main/resources/win32-win32-x86/qpidmc.exe
+++ /dev/null
Binary files differ
diff --git a/java/management/eclipse-plugin/src/main/resources/win32-win32-x86/qpidmc.ini b/java/management/eclipse-plugin/src/main/resources/win32-win32-x86/qpidmc.ini
deleted file mode 100644
index 312580769e..0000000000
--- a/java/management/eclipse-plugin/src/main/resources/win32-win32-x86/qpidmc.ini
+++ /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.
-###############################################################################
-
--vmargs
--Xms40m
--Xmx256m
--XX:MaxPermSize=256m
--Dosgi.requiredJavaVersion=1.5
--Declipse.consoleLog=true
-
-#===============================================
-# SSL trust store configuration options.
-#===============================================
-
-# Uncomment lines below to specify custom truststore for server SSL
-# certificate verification, eg when using self-signed server certs.
-#
-#-Djavax.net.ssl.trustStore=<path.to.truststore>
-#-Djavax.net.ssl.trustStorePassword=<truststore.password>
-
diff --git a/java/management/eclipse-plugin/src/test/java/org/apache/qpid/management/ui/ApiVersionTest.java b/java/management/eclipse-plugin/src/test/java/org/apache/qpid/management/ui/ApiVersionTest.java
deleted file mode 100644
index b4f6aea57b..0000000000
--- a/java/management/eclipse-plugin/src/test/java/org/apache/qpid/management/ui/ApiVersionTest.java
+++ /dev/null
@@ -1,177 +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;
-
-import junit.framework.TestCase;
-
-public class ApiVersionTest extends TestCase
-{
-
- public void testGetMajor()
- {
- ApiVersion ver = new ApiVersion(1,3);
- assertEquals(1, ver.getMajor());
- }
-
- public void testGetMinor()
- {
- ApiVersion ver = new ApiVersion(1,3);
- assertEquals(3, ver.getMinor());
- }
-
- public void testGreaterThanOrEqualTo()
- {
- ApiVersion ver = new ApiVersion(1,3);
-
- //equal
- assertTrue(ver.greaterThanOrEqualTo(1, 3));
- //same major, higher minor
- assertFalse(ver.greaterThanOrEqualTo(1, 4));
- //same major, lower minor
- assertTrue(ver.greaterThanOrEqualTo(1, 2));
-
- //higher major, lower minor
- assertFalse(ver.greaterThanOrEqualTo(2, 0));
- //higher major, same minor
- assertFalse(ver.greaterThanOrEqualTo(2, 3));
- //higher major, higher minor
- assertFalse(ver.greaterThanOrEqualTo(2, 4));
-
- //lower major, higher minor
- assertTrue(ver.greaterThanOrEqualTo(0, 9));
- //lower major, lower minor
- assertTrue(ver.greaterThanOrEqualTo(0, 2));
- //lower major, same minor
- assertTrue(ver.greaterThanOrEqualTo(0, 3));
- }
-
- public void testLessThanOrEqualTo()
- {
- ApiVersion ver = new ApiVersion(1,3);
-
- //equal
- assertTrue(ver.lessThanOrEqualTo(1, 3));
- //same major, higher minor
- assertTrue(ver.lessThanOrEqualTo(1, 4));
- //same major, lower minor
- assertFalse(ver.lessThanOrEqualTo(1, 2));
-
- //higher major, lower minor
- assertTrue(ver.lessThanOrEqualTo(2, 0));
- //higher major, same minor
- assertTrue(ver.lessThanOrEqualTo(2, 3));
- //higher major, higher minor
- assertTrue(ver.lessThanOrEqualTo(2, 4));
-
- //lower major, higher minor
- assertFalse(ver.lessThanOrEqualTo(0, 9));
- //lower major, lower minor
- assertFalse(ver.lessThanOrEqualTo(0, 2));
- //lower major, same minor
- assertFalse(ver.lessThanOrEqualTo(0, 3));
- }
-
- public void testGreaterThan()
- {
- ApiVersion ver = new ApiVersion(1,3);
-
- //equal
- assertFalse(ver.greaterThan(1, 3));
- //same major, higher minor
- assertFalse(ver.greaterThan(1, 4));
- //same major, lower minor
- assertTrue(ver.greaterThan(1, 2));
-
- //higher major, lower minor
- assertFalse(ver.greaterThan(2, 0));
- //higher major, same minor
- assertFalse(ver.greaterThan(2, 3));
- //higher major, higher minor
- assertFalse(ver.greaterThan(2, 4));
-
- //lower major, higher minor
- assertTrue(ver.greaterThan(0, 9));
- //lower major, lower minor
- assertTrue(ver.greaterThan(0, 2));
- //lower major, same minor
- assertTrue(ver.greaterThan(0, 3));
- }
-
- public void testLessThan()
- {
- ApiVersion ver = new ApiVersion(1,3);
-
- //equal
- assertFalse(ver.lessThan(1, 3));
- //same major, higher minor
- assertTrue(ver.lessThan(1, 4));
- //same major, lower minor
- assertFalse(ver.lessThan(1, 2));
-
- //higher major, lower minor
- assertTrue(ver.lessThan(2, 0));
- //higher major, same minor
- assertTrue(ver.lessThan(2, 3));
- //higher major, higher minor
- assertTrue(ver.lessThan(2, 4));
-
- //lower major, higher minor
- assertFalse(ver.lessThan(0, 9));
- //lower major, lower minor
- assertFalse(ver.lessThan(0, 2));
- //lower major, same minor
- assertFalse(ver.lessThan(0, 3));
- }
-
- public void testEqualsIntInt()
- {
- ApiVersion ver = new ApiVersion(1,3);
-
- //equal
- assertTrue(ver.equals(1, 3));
- //same major, higher minor
- assertFalse(ver.equals(1, 4));
- //same major, lower minor
- assertFalse(ver.equals(1, 2));
-
- //higher major, lower minor
- assertFalse(ver.equals(2, 0));
- //higher major, same minor
- assertFalse(ver.equals(2, 3));
- //higher major, higher minor
- assertFalse(ver.equals(2, 4));
-
- //lower major, higher minor
- assertFalse(ver.equals(0, 9));
- //lower major, lower minor
- assertFalse(ver.equals(0, 2));
- //lower major, same minor
- assertFalse(ver.equals(0, 3));
- }
-
- public void testToString()
- {
- ApiVersion ver = new ApiVersion(1,3);
-
- assertEquals("major=1,minor=3", ver.toString());
- }
-
-}
diff --git a/java/management/eclipse-plugin/src/test/java/org/apache/qpid/management/ui/ApplicationRegistryTest.java b/java/management/eclipse-plugin/src/test/java/org/apache/qpid/management/ui/ApplicationRegistryTest.java
deleted file mode 100644
index 06896087ae..0000000000
--- a/java/management/eclipse-plugin/src/test/java/org/apache/qpid/management/ui/ApplicationRegistryTest.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.management.ui;
-
-import junit.framework.TestCase;
-
-import org.apache.qpid.management.common.mbeans.ServerInformation;
-
-public class ApplicationRegistryTest extends TestCase
-{
- public void testSupportedManagementApiVersion()
- {
- //ensure that the console supported API version is kept in sync with the broker
-
- assertEquals("The management console does not support the same major version of management API as the broker. " +
- "Make any required changes and update the supported value.",
- ServerInformation.QPID_JMX_API_MAJOR_VERSION,
- ApplicationRegistry.SUPPORTED_QPID_JMX_API_MAJOR_VERSION);
-
- assertEquals("The management console does not support the same minor version of management API as the broker. " +
- "Make any required changes and update the supported value.",
- ServerInformation.QPID_JMX_API_MINOR_VERSION,
- ApplicationRegistry.SUPPORTED_QPID_JMX_API_MINOR_VERSION);
- }
-}
diff --git a/java/management/eclipse-plugin/src/test/java/org/apache/qpid/management/ui/ManagementConsoleTest.java b/java/management/eclipse-plugin/src/test/java/org/apache/qpid/management/ui/ManagementConsoleTest.java
deleted file mode 100644
index eef6356642..0000000000
--- a/java/management/eclipse-plugin/src/test/java/org/apache/qpid/management/ui/ManagementConsoleTest.java
+++ /dev/null
@@ -1,123 +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;
-
-import org.apache.qpid.exchange.ExchangeDefaults;
-import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpid.server.exchange.DirectExchange;
-import org.apache.qpid.server.management.AMQManagedObject;
-import org.apache.qpid.server.model.UUIDGenerator;
-import org.apache.qpid.server.queue.AMQQueue;
-import org.apache.qpid.server.queue.AMQQueueFactory;
-import org.apache.qpid.server.queue.AMQQueueMBean;
-import org.apache.qpid.server.registry.ApplicationRegistry;
-import org.apache.qpid.server.registry.IApplicationRegistry;
-import org.apache.qpid.server.util.InternalBrokerBaseCase;
-import org.apache.qpid.server.virtualhost.VirtualHost;
-
-import javax.management.MBeanFeatureInfo;
-import javax.management.MBeanInfo;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.UUID;
-
-
-/**
- * Test class to test if any change in the broker JMX code is affesting the management console
- * There are some hardcoding of management feature names and parameter names to create a customized
- * look in the console.
- */
-public class ManagementConsoleTest extends InternalBrokerBaseCase
-{
- private VirtualHost _virtualHost;
-
- @Override
- public void setUp() throws Exception
- {
- super.setUp();
- IApplicationRegistry applicationRegistry = ApplicationRegistry.getInstance();
- _virtualHost = applicationRegistry.getVirtualHostRegistry().getVirtualHost("test");
- }
-
-
- /**
- * Test for AMQQueueMBean attribute and operation names, which are used in the management console
- * @throws Exception
- */
- public void testAMQQueueMBeanInfo() throws Exception
- {
- // If this test fails due to changes in the broker code,
- // then the constants in the Constants.java shoule be updated accordingly
- AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(new AMQShortString("testQueueForManagement"), false, null, false, false,
- _virtualHost, null);
- AMQManagedObject mbean = new AMQQueueMBean(queue);
- MBeanInfo mbeanInfo = mbean.getMBeanInfo();
-
- List<String> operationNames = getNamesList(mbeanInfo.getOperations());
- assertTrue(operationNames.contains(Constants.OPERATION_MOVE_MESSAGES));
-
- List<String> attributesList = getNamesList(mbeanInfo.getAttributes());
- assertTrue(attributesList.contains(Constants.ATTRIBUTE_QUEUE_CONSUMERCOUNT));
- assertTrue(attributesList.contains(Constants.ATTRIBUTE_QUEUE_DEPTH));
- }
-
- /**
- * Test for Exchange MBean attribute and operation names, which are used in the management console
- * @throws Exception
- */
- public void testExchangeMBeanInfo() throws Exception
- {
- // If this test fails due to changes in the broker code,
- // then the constants in the Constants.java shoule be updated accordingly
- DirectExchange exchange = new DirectExchange();
- exchange.initialise(UUIDGenerator.generateUUID(), _virtualHost, ExchangeDefaults.DIRECT_EXCHANGE_NAME, false, 0, true);
- AMQManagedObject mbean = (AMQManagedObject)exchange.getManagedObject();
- MBeanInfo mbeanInfo = mbean.getMBeanInfo();
-
- // Check for the Exchange Type property in the ObjectName
- assertNotNull(mbean.getObjectName().getKeyProperty(Constants.EXCHANGE_TYPE));
-
- // Check for operation names
- List<String> operationNames = getNamesList(mbeanInfo.getOperations());
- assertTrue(operationNames.contains(Constants.OPERATION_CREATE_BINDING));
- }
-
- /**
- * Test for VirtualHostManagerMBean features used in Management console for customizing the GUI
- * @throws Exception
- */
- public void testVirtualHostManagerMBeanInfo() throws Exception
- {
- AMQManagedObject mbean = (AMQManagedObject)_virtualHost.getManagedObject();
- assertTrue(mbean.getType().equals(Constants.VIRTUAL_HOST));
- }
-
- private List<String> getNamesList(MBeanFeatureInfo[] features)
- {
- List<String> names = new ArrayList<String>();
- for (MBeanFeatureInfo feature : features)
- {
- names.add(feature.getName());
- }
-
- return names;
- }
-}
diff --git a/java/management/example/build.xml b/java/management/example/build.xml
index 8bcd615282..e195d4bd47 100644
--- a/java/management/example/build.xml
+++ b/java/management/example/build.xml
@@ -19,7 +19,6 @@
-
-->
<project name="Management Examples" default="build">
-
<property name="module.depends" value="management/common"/>
<import file="../../module.xml"/>
diff --git a/java/module.xml b/java/module.xml
index 1aea77b488..af77d84e86 100644
--- a/java/module.xml
+++ b/java/module.xml
@@ -22,7 +22,9 @@
<import file="common.xml"/>
- <path id="maven-ant-tasks.classpath" path="${project.root}/lib/maven-ant-tasks-2.1.1.jar" />
+ <property file="${project.root}/build.deps"/>
+
+ <path id="maven-ant-tasks.classpath" path="${project.root}/${maven-ant-tasks}" />
<typedef resource="org/apache/maven/artifact/ant/antlib.xml"
uri="antlib:org.apache.maven.artifact.ant"
classpathref="maven-ant-tasks.classpath" />
@@ -39,8 +41,6 @@
<echo message="Running ant for module : ${module}" level="info"/>
- <property file="${project.root}/build.deps"/>
-
<property name="module.build" location="${build.scratch}/${module}"/>
<property name="module.classes" location="${module.build}/classes"/>
<property name="module.instrumented" location="${module.build}/classes-instrumented"/>
@@ -55,6 +55,8 @@
<property name="module.test.src" location="src/test/java"/>
<property name="module.bin" location="bin"/>
<property name="module.etc" location="etc"/>
+ <property name="module.src.resources.metainf" location="src/main/resources/META-INF"/>
+ <property name="module.metainf" location="${module.build}/META-INF"/>
<property name="module.namever" value="${project.name}-${module.name}-${project.version}"/>
<property name="module.namever.osgi" value="${project.name}-${module.name}_${project.version}.0.osgi"/>
@@ -82,6 +84,7 @@
<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}"/>
+ <available property="module.src.resources.metainf.exists" file="${module.src.resources.metainf}"/>
<property name="module.source.jar"
location="${build.lib}/${project.name}-${module.name}-${project.version}-sources.jar"/>
@@ -325,8 +328,42 @@
<contains substring="${module.name}" string="${exclude.modules}" />
</condition>
+ <!-- JVM args pass to forked Junit JVM -->
<property name="jvm.args" value=""/>
+ <!-- Following properties are used by the tests -->
+ <property name="test.output" value="${module.results}"/>
+ <property name="QPID_HOME" value="${qpid.home}"/>
+ <property name="QPID_WORK" value="${qpid.work}"/>
<property name="broker.existing.qpid.work" value=""/>
+ <!-- Used by PluginTest -->
+ <property name="example.plugin.target" value="${project.root}/build/lib/plugins"/>
+
+ <propertyset id="all.test.systemproperties">
+ <propertyref prefix="test"/>
+ <propertyref prefix="profile"/>
+ <propertyref prefix="javax.net.ssl"/>
+ <propertyref prefix="broker"/>
+
+ <propertyref name="amqj.logging.level"/>
+ <propertyref name="amqj.server.logging.level"/>
+ <propertyref name="amqj.protocol.logging.level"/>
+
+ <propertyref name="log4j.debug"/>
+ <propertyref name="log4j.configuration"/>
+
+ <propertyref name="root.logging.level"/>
+ <propertyref name="java.naming.factory.initial"/>
+ <propertyref name="java.naming.provider.url"/>
+ <propertyref name="messagestore.class.name" />
+ <propertyref name="qpid.amqp.version"/>
+ <propertyref name="max_prefetch"/>
+ <propertyref name="qpid.dest_syntax"/>
+
+ <propertyref name="test.output"/>
+ <propertyref name="QPID_HOME"/>
+ <propertyref name="QPID_WORK"/>
+ <propertyref name="example.plugin.target"/>
+ </propertyset>
<target name="test" depends="build,compile-tests" if="module.test.src.exists"
unless="${dontruntest}" description="execute unit tests">
@@ -341,38 +378,7 @@
<jvmarg line="${jvm.args}" />
- <sysproperty key="amqj.logging.level" value="${amqj.logging.level}"/>
- <sysproperty key="amqj.server.logging.level" value="${amqj.server.logging.level}"/>
- <sysproperty key="amqj.protocol.logging.level" value="${amqj.protocol.logging.level}"/>
- <sysproperty key="log4j.debug" value="${log4j.debug}"/>
- <sysproperty key="root.logging.level" value="${root.logging.level}"/>
- <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="messagestorefactory.class.name" value="${messagestorefactory.class.name}" />
- <sysproperty key="test.output" value="${module.results}"/>
- <sysproperty key="qpid.amqp.version" value="${qpid.amqp.version}"/>
-
- <syspropertyset>
- <propertyref prefix="test"/>
- </syspropertyset>
- <syspropertyset>
- <propertyref prefix="profile"/>
- </syspropertyset>
- <syspropertyset>
- <propertyref prefix="javax.net.ssl"/>
- </syspropertyset>
- <syspropertyset>
- <propertyref prefix="broker"/>
- </syspropertyset>
-
- <sysproperty key="max_prefetch" value ="${max_prefetch}"/>
- <sysproperty key="qpid.dest_syntax" value ="${qpid.dest_syntax}"/>
-
- <sysproperty key="example.plugin.target" value="${project.root}/build/lib/plugins"/>
- <sysproperty key="QPID_EXAMPLE_HOME" value="${qpid.home}"/>
- <sysproperty key="QPID_HOME" value="${qpid.home}"/>
- <sysproperty key="QPID_WORK" value="${qpid.work}"/>
+ <syspropertyset refid="all.test.systemproperties"/>
<formatter type="plain"/>
<formatter type="xml"/>
@@ -442,16 +448,31 @@
<target name="postbuild" description="run after a build"/>
<target name="build" depends="jar,jar-tests,jar-sources,libs,copy-bin,copy-etc,postbuild" description="compile and copy resources into build tree"/>
- <target name="jar.manifest" depends="compile" if="module.manifest">
- <jar destfile="${module.jar}" basedir="${module.classes}" manifest="${module.manifest}"/>
+
+ <target name="jar.manifest" depends="compile, copy-module-metainf" if="module.manifest">
+ <jar destfile="${module.jar}" basedir="${module.classes}" manifest="${module.manifest}">
+ <metainf dir="${module.metainf}" />
+ </jar>
</target>
- <target name="jar.nomanifest" depends="compile" unless="module.manifest">
+ <target name="jar.nomanifest" depends="compile, copy-module-metainf" unless="module.manifest">
<jar destfile="${module.jar}" basedir="${module.classes}">
- <metainf dir="${project.root}/resources/" />
+ <metainf dir="${module.metainf}" />
</jar>
</target>
+ <target name="copy-module-metainf" depends="copy-metainf-resources" if="module.src.resources.metainf.exists">
+ <copy todir="${module.metainf}" failonerror="true">
+ <fileset dir="${module.src.resources.metainf}"/>
+ </copy>
+ </target>
+
+ <target name="copy-metainf-resources">
+ <copy todir="${module.metainf}" failonerror="true">
+ <fileset dir="${project.root}/resources/"/>
+ </copy>
+ </target>
+
<target name="jar" depends="jar.manifest,jar.nomanifest" description="create jar"/>
<target name="jar-tests" depends="compile-tests" description="create unit test jar">
@@ -599,7 +620,7 @@
<target name="bundle" description="Build module osgi artifact. Override and depend on bundle-tasks to use"/>
<target name="bundle-tasks" depends="jar">
- <taskdef resource="aQute/bnd/ant/taskdef.properties" classpath="${project.root}/lib/bnd-0.0.384.jar"/>
+ <taskdef resource="aQute/bnd/ant/taskdef.properties" classpath="${project.root}/${bnd}"/>
<echo message="Bundling ${build}/lib/${module.namever}.jar with ${module.src}/${module.name}.bnd"/>
<bnd
classpath="${build}/lib/${module.namever}.jar"
@@ -657,41 +678,19 @@
</cobertura-instrument>
</target>
- <target name="cover-test" depends="instrument">
+ <target name="cover-test" depends="instrument" if="module.test.src.exists">
- <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}" >
+ <jvmarg line="${jvm.args}" />
- <sysproperty key="amqj.logging.level" value="${amqj.logging.level}"/>
- <sysproperty key="amqj.protocol.logging.level" value="${amqj.protocol.logging.level}"/>
- <sysproperty key="log4j.debug" value="${log4j.debug}"/>
- <sysproperty key="root.logging.level" value="${root.logging.level}"/>
- <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.version" value="${broker.version}"/>
- <sysproperty key="broker.ready" value="${broker.ready}" />
- <sysproperty key="test.output" value="${module.results}"/>
-
- <syspropertyset>
- <propertyref prefix="test"/>
- </syspropertyset>
- <syspropertyset>
- <propertyref prefix="broker"/>
- </syspropertyset>
-
- <sysproperty key="max_prefetch" value ="${max_prefetch}"/>
- <sysproperty key="example.plugin.target" value="${project.root}/build/lib/plugins"/>
- <sysproperty key="QPID_EXAMPLE_HOME" value="${project.root}/build"/>
- <sysproperty key="QPID_HOME" value="${project.root}/build"/>
+ <syspropertyset refid="all.test.systemproperties"/>
<sysproperty key="net.sourceforge.cobertura.datafile"
file="${cobertura.datafile}" />
-
+
<formatter type="plain"/>
<formatter type="xml"/>
@@ -713,14 +712,13 @@
</target>
<target name="coverage-report" depends="cobertura-init">
- <echo message="${cobertura.datafile}"/>
<cobertura-report format="html"
destdir="${module.coverage}"
datafile="${cobertura.datafile}">
<fileset dir="${module.src}" includes="**/*.java" />
</cobertura-report>
</target>
-
+
<property name="version.file" location="${module.classes}/qpidversion.properties"/>
<property file="${version.file}" prefix="old."/>
@@ -809,7 +807,7 @@ qpid.name=${project.name}
<classpath>
<pathelement path="${module.src}"/>
<pathelement path="${velocity.compile.dir}" />
- <fileset dir="${project.root}/lib">
+ <fileset dir="${project.root}/lib/required">
<include name="**/*.jar"/>
</fileset>
<pathelement path="${gentools.home}/lib/velocity-1.4.jar" />
diff --git a/java/perftests/build.xml b/java/perftests/build.xml
index 75d75b4f5a..c59986c06d 100644
--- a/java/perftests/build.xml
+++ b/java/perftests/build.xml
@@ -20,10 +20,16 @@
-->
<project name="Performance Tests" default="build">
<condition property="perftests.optional.test.depends" value="bdbstore" else="">
+ <or>
<and>
<contains string="${modules.opt}" substring="bdbstore"/>
<contains string="${profile}" substring="bdb"/>
</and>
+ <and>
+ <istrue value="${optional}"/>
+ <contains string="${profile}" substring="bdb"/>
+ </and>
+ </or>
</condition>
<property name="module.depends" value="client common"/>
@@ -38,4 +44,24 @@
<property name="log4j.config" value="-Dlog4j.configuration=perftests.log4j"/>
<property name="properties" value="perftests.properties"/>
+ <target name="release-bin" depends="release-bin-tasks"/>
+
+ <target name="libs-release" description="overridden to not copy depended-on modules or their dependencies, so that a perf tests release is not tied to a particular client version">
+ <!-- Copy the module dependencies -->
+ <echo message="${module.libs}"/>
+ <echo message="overridden to not copy qpid-client or its dependencies so that this release is not tied to a particular client version"/>
+
+ <copylist todir="${module.release}/lib" dir="${project.root}" files="${module.libs}"/>
+ <!-- Copy the jar for this module -->
+ <copy todir="${module.release}/lib" failonerror="true">
+ <fileset file="${module.jar}"/>
+ </copy>
+ </target>
+
+ <target name="copy-etc-release" description="override target from module.xml to set flatten=false">
+ <copy todir="${module.release}/etc" failonerror="false" flatten="false">
+ <fileset dir="${module.etc}"/>
+ </copy>
+ </target>
+
</project>
diff --git a/java/perftests/etc/chartdefs/MessageSizeNonPersistent.chartdef b/java/perftests/etc/chartdefs/1001-MessageSize-Transient.chartdef
index 22d78042d8..757a396dff 100644
--- a/java/perftests/etc/chartdefs/MessageSizeNonPersistent.chartdef
+++ b/java/perftests/etc/chartdefs/1001-MessageSize-Transient.chartdef
@@ -17,11 +17,16 @@
# under the License.
#
-chartType=LINE
-chartTitle=Impact of Message Size (Non-Persistent)
+chartType=XYLINE
+chartTitle=Impact of Message Size
+chartSubtitle=Transient messages
xAxisTitle=Message Size (B)
yAxisTitle=Throughput (KB/s)
-series.1.statement=SELECT payloadSizeB, throughputKbPerS FROM MessageSize WHERE testName like '%NON_PERSISTENT' AND participantName = 'All'
+series.1.statement=SELECT payloadSizeB, throughputKbPerS FROM MessageSize WHERE testName like '%TRANSIENT' AND participantName = 'All'
series.1.legend=Current
series.1.dir=${csvCurrentDir}
+
+series.2.statement=SELECT payloadSizeB, throughputKbPerS FROM MessageSize WHERE testName like '%TRANSIENT' AND participantName = 'All'
+series.2.legend=Baseline
+series.2.dir=${csvBaselineDir}
diff --git a/java/perftests/etc/chartdefs/MessageSizePersistent.chartdef b/java/perftests/etc/chartdefs/1002-MessageSize-Persistent.chartdef
index 4a57215714..58c280e227 100644
--- a/java/perftests/etc/chartdefs/MessageSizePersistent.chartdef
+++ b/java/perftests/etc/chartdefs/1002-MessageSize-Persistent.chartdef
@@ -17,8 +17,9 @@
# under the License.
#
-chartType=LINE
-chartTitle=Impact of Message Size (Persistent)
+chartType=XYLINE
+chartTitle=Impact of Message Size
+chartSubtitle=Persistent messages
xAxisTitle=Message Size (B)
yAxisTitle=Throughput (KB/s)
@@ -26,4 +27,6 @@ series.1.statement=SELECT payloadSizeB, throughputKbPerS FROM MessageSize WHERE
series.1.legend=Current
series.1.dir=${csvCurrentDir}
-# Define series3/4 to chart the baseline
+series.2.statement=SELECT payloadSizeB, throughputKbPerS FROM MessageSize WHERE testName like '% PERSISTENT' AND participantName = 'All'
+series.2.legend=Baseline
+series.2.dir=${csvBaselineDir}
diff --git a/java/perftests/etc/chartdefs/VaryingNumberOfProducers.chartdef b/java/perftests/etc/chartdefs/1011-VaryingNumberOfProducers.chartdef
index 51ea92b909..f39e7c3d0d 100644
--- a/java/perftests/etc/chartdefs/VaryingNumberOfProducers.chartdef
+++ b/java/perftests/etc/chartdefs/1011-VaryingNumberOfProducers.chartdef
@@ -17,8 +17,9 @@
# under the License.
#
-chartType=LINE
+chartType=XYLINE
chartTitle=Varying number of producers
+chartSubtitle=Persistent 1KB messages
xAxisTitle=Producers
yAxisTitle=Throughput (KB/s)
@@ -33,3 +34,7 @@ series.2.dir=${csvCurrentDir}
series.3.statement=SELECT totalNumberOfProducers, throughputKbPerS FROM VaryingNumberOfParticipants WHERE participantName = 'All' and totalNumberOfConsumers = '10'
series.3.legend=10 Consumer
series.3.dir=${csvCurrentDir}
+
+series.4.statement=SELECT totalNumberOfProducers, throughputKbPerS FROM VaryingNumberOfParticipants WHERE participantName = 'All' and totalNumberOfConsumers = '1'
+series.4.legend=1 Consumer (baseline)
+series.4.dir=${csvBaselineDir}
diff --git a/java/perftests/etc/chartdefs/VaryingNumberOfConsumers.chartdef b/java/perftests/etc/chartdefs/1012-VaryingNumberOfConsumers.chartdef
index 83d6fe2659..0f0b35a7c8 100644
--- a/java/perftests/etc/chartdefs/VaryingNumberOfConsumers.chartdef
+++ b/java/perftests/etc/chartdefs/1012-VaryingNumberOfConsumers.chartdef
@@ -17,8 +17,9 @@
# under the License.
#
-chartType=LINE
+chartType=XYLINE
chartTitle=Varying number of consumers
+chartSubtitle=Persistent 1KB messages
xAxisTitle=Consumers
yAxisTitle=Throughput (KB/s)
@@ -33,3 +34,7 @@ series.2.dir=${csvCurrentDir}
series.3.statement=SELECT totalNumberOfConsumers, throughputKbPerS FROM VaryingNumberOfParticipants WHERE participantName = 'All' and totalNumberOfProducers = '10'
series.3.legend=10 Producers
series.3.dir=${csvCurrentDir}
+
+series.4.statement=SELECT totalNumberOfConsumers, throughputKbPerS FROM VaryingNumberOfParticipants WHERE participantName = 'All' and totalNumberOfProducers = '10'
+series.4.legend=10 Producers (baseline)
+series.4.dir=${csvBaselineDir}
diff --git a/java/perftests/etc/chartdefs/AcknowledgementModesAutoAck.chartdef b/java/perftests/etc/chartdefs/1021-AcknowledgementModes-AutoAck.chartdef
index 42e4a0c11e..009ac6d80f 100644
--- a/java/perftests/etc/chartdefs/AcknowledgementModesAutoAck.chartdef
+++ b/java/perftests/etc/chartdefs/1021-AcknowledgementModes-AutoAck.chartdef
@@ -18,7 +18,8 @@
#
chartType=BAR
-chartTitle=Performance of acknowledgement modes (Auto-acknowledgement)
+chartTitle=Performance of acknowledgement modes
+chartSubtitle=Auto-acknowledge
xAxisTitle=Persistence
yAxisTitle=Throughput (KB/s)
@@ -26,3 +27,7 @@ series.1.statement=SELECT testName, throughputKbPerS FROM AcknowledgementModes W
series.1.legend=Current
series.1.dir=${csvCurrentDir}
+series.2.statement=SELECT testName, throughputKbPerS FROM AcknowledgementModes WHERE acknowledgeMode = '1' AND participantName = 'All'
+series.2.legend=Baseline
+series.2.dir=${csvBaselineDir}
+
diff --git a/java/perftests/etc/chartdefs/AcknowledgementModesTransacted.chartdef b/java/perftests/etc/chartdefs/1022-AcknowledgementModes-Transacted.chartdef
index 3bbee462a0..5dcfa5a85e 100644
--- a/java/perftests/etc/chartdefs/AcknowledgementModesTransacted.chartdef
+++ b/java/perftests/etc/chartdefs/1022-AcknowledgementModes-Transacted.chartdef
@@ -18,7 +18,8 @@
#
chartType=BAR
-chartTitle=Performance of acknowledgement modes (Transacted)
+chartTitle=Performance of acknowledgement modes
+chartSubtitle=Transacted
xAxisTitle=Persistence
yAxisTitle=Throughput (KB/s)
@@ -26,3 +27,6 @@ series.1.statement=SELECT testName, throughputKbPerS FROM AcknowledgementModes W
series.1.legend=Current
series.1.dir=${csvCurrentDir}
+series.2.statement=SELECT testName, throughputKbPerS FROM AcknowledgementModes WHERE acknowledgeMode = '0' AND participantName = 'All'
+series.2.legend=Baseline
+series.2.dir=${csvBaselineDir}
diff --git a/java/perftests/etc/chartdefs/BatchSize.chartdef b/java/perftests/etc/chartdefs/1030-BatchSize.chartdef
index 13c42b2ebf..1f01aa85aa 100644
--- a/java/perftests/etc/chartdefs/BatchSize.chartdef
+++ b/java/perftests/etc/chartdefs/1030-BatchSize.chartdef
@@ -17,8 +17,9 @@
# under the License.
#
-chartType=LINE
+chartType=XYLINE
chartTitle=Transaction Batch Size
+chartSubtitle=Persistent 1KB messages
xAxisTitle=Batch Size
yAxisTitle=Throughput (KB/s)
@@ -26,3 +27,7 @@ series.1.statement=SELECT batchSize, throughputKbPerS FROM BatchSize WHERE parti
series.1.legend=Current
series.1.dir=${csvCurrentDir}
+series.2.statement=SELECT batchSize, throughputKbPerS FROM BatchSize WHERE participantName = 'All'
+series.2.legend=Baseline
+series.2.dir=${csvBaselineDir}
+
diff --git a/java/perftests/etc/chartdefs/QueueTypes.chartdef b/java/perftests/etc/chartdefs/1040-QueueTypes.chartdef
index 770b5cc719..42ed69c19d 100644
--- a/java/perftests/etc/chartdefs/QueueTypes.chartdef
+++ b/java/perftests/etc/chartdefs/1040-QueueTypes.chartdef
@@ -19,6 +19,7 @@
chartType=BAR
chartTitle=Queue Types
+chartSubtitle=Persistent 1KB messages
xAxisTitle=Queue Types
yAxisTitle=Throughput (KB/s)
@@ -26,3 +27,6 @@ series.1.statement=SELECT testName, throughputKbPerS FROM QueueTypes WHERE parti
series.1.legend=Current
series.1.dir=${csvCurrentDir}
+series.2.statement=SELECT testName, throughputKbPerS FROM QueueTypes WHERE participantName = 'All'
+series.2.legend=Baseline
+series.2.dir=${csvBaselineDir}
diff --git a/java/perftests/etc/chartdefs/1500-Topic-NumberOfConsumers.chartdef b/java/perftests/etc/chartdefs/1500-Topic-NumberOfConsumers.chartdef
new file mode 100644
index 0000000000..305c5009e2
--- /dev/null
+++ b/java/perftests/etc/chartdefs/1500-Topic-NumberOfConsumers.chartdef
@@ -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.
+#
+
+chartType=XYLINE
+chartTitle=Number of topic consumers
+chartSubtitle=Transient 1KB messages
+xAxisTitle=Numer of consumers
+yAxisTitle=Throughput (KB/s)
+
+series.1.statement=SELECT testName, throughputKbPerS FROM Topic-NumberOfConsumers WHERE participantName = 'All'
+series.1.legend=Current
+series.1.dir=${csvCurrentDir}
+
+series.2.statement=SELECT testName, throughputKbPerS FROM Topic-NumberOfConsumers WHERE participantName = 'All'
+series.2.legend=Baseline
+series.2.dir=${csvBaselineDir}
diff --git a/java/perftests/etc/chartdefs/1501-Topic-NumberOfTopics.chartdef b/java/perftests/etc/chartdefs/1501-Topic-NumberOfTopics.chartdef
new file mode 100644
index 0000000000..9bc53e5a9e
--- /dev/null
+++ b/java/perftests/etc/chartdefs/1501-Topic-NumberOfTopics.chartdef
@@ -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.
+#
+
+chartType=XYLINE
+chartTitle=Number of topics
+chartSubtitle=Transient 1KB messages
+xAxisTitle=Numer of topics
+yAxisTitle=Throughput (KB/s)
+
+series.1.statement=SELECT testName, throughputKbPerS FROM Topic-NumberOfTopics WHERE participantName = 'All'
+series.1.legend=Current
+series.1.dir=${csvCurrentDir}
+
+series.2.statement=SELECT testName, throughputKbPerS FROM Topic-NumberOfTopics WHERE participantName = 'All'
+series.2.legend=Baseline
+series.2.dir=${csvBaselineDir}
diff --git a/java/perftests/etc/chartdefs/1502-Topic-Persistence.chartdef b/java/perftests/etc/chartdefs/1502-Topic-Persistence.chartdef
new file mode 100644
index 0000000000..ce64d14ac4
--- /dev/null
+++ b/java/perftests/etc/chartdefs/1502-Topic-Persistence.chartdef
@@ -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.
+#
+
+chartType=BAR
+chartTitle=Topic transient/durable subscriptions
+chartSubtitle=1KB messages
+xAxisTitle=Durable subscription
+yAxisTitle=Throughput (KB/s)
+
+series.1.statement=SELECT isDurableSubscription, throughputKbPerS FROM Topic-Persistence WHERE participantName = 'All Consumers'
+series.1.legend=Current
+series.1.dir=${csvCurrentDir}
+
+series.2.statement=SELECT isDurableSubscription, throughputKbPerS FROM Topic-Persistence WHERE participantName = 'All Consumers'
+series.2.legend=Baseline
+series.2.dir=${csvBaselineDir}
diff --git a/java/perftests/etc/chartdefs/1503-Topic-AckModes.chartdef b/java/perftests/etc/chartdefs/1503-Topic-AckModes.chartdef
new file mode 100644
index 0000000000..5ccc166fc8
--- /dev/null
+++ b/java/perftests/etc/chartdefs/1503-Topic-AckModes.chartdef
@@ -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.
+#
+
+chartType=BAR
+chartTitle=Topic acknowledge modes
+chartSubtitle=Transient 1KB messages
+xAxisTitle=Ack Mode
+yAxisTitle=Throughput (KB/s)
+
+series.1.statement=SELECT acknowledgeMode, throughputKbPerS FROM Topic-AckModes WHERE participantName = 'All'
+series.1.legend=Current
+series.1.dir=${csvCurrentDir}
+
+series.2.statement=SELECT acknowledgeMode, throughputKbPerS FROM Topic-AckModes WHERE participantName = 'All'
+series.2.legend=Baseline
+series.2.dir=${csvBaselineDir}
diff --git a/java/perftests/etc/chartdefs/2001-Latency-MessageSize-Transient.chartdef b/java/perftests/etc/chartdefs/2001-Latency-MessageSize-Transient.chartdef
new file mode 100644
index 0000000000..c892ea16cf
--- /dev/null
+++ b/java/perftests/etc/chartdefs/2001-Latency-MessageSize-Transient.chartdef
@@ -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.
+#
+
+chartType=STATISTICAL_BAR
+chartTitle=Impact of message size on latency
+chartSubtitle=Transient messages
+xAxisTitle=Message Size (B)
+yAxisTitle=Latency (millis)
+
+series.1.statement=SELECT payloadSizeB, maxLatency, 0 FROM Latency-MessageSize WHERE testName like '%TRANSIENT' AND participantName = 'All Consumers'
+series.1.legend=Maximum latency
+series.1.dir=${csvCurrentDir}
+
+series.2.statement=SELECT payloadSizeB, averageLatency,latencyStandardDeviation FROM Latency-MessageSize WHERE testName like '%TRANSIENT' AND participantName = 'All Consumers'
+series.2.legend=Average latency
+series.2.dir=${csvCurrentDir}
+
+series.3.statement=SELECT payloadSizeB, averageLatency,latencyStandardDeviation FROM Latency-MessageSize WHERE testName like '%TRANSIENT' AND participantName = 'All Consumers'
+series.3.legend=Average latency (baseline)
+series.3.dir=${csvBaselineDir}
+
+series.4.statement=SELECT payloadSizeB, minLatency,0 FROM Latency-MessageSize WHERE testName like '%TRANSIENT' AND participantName = 'All Consumers'
+series.4.legend=Minimum latency
+series.4.dir=${csvCurrentDir}
diff --git a/java/perftests/etc/chartdefs/2002-Latency-MessageSize-Persistent.chartdef b/java/perftests/etc/chartdefs/2002-Latency-MessageSize-Persistent.chartdef
new file mode 100644
index 0000000000..167e62603a
--- /dev/null
+++ b/java/perftests/etc/chartdefs/2002-Latency-MessageSize-Persistent.chartdef
@@ -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.
+#
+
+chartType=STATISTICAL_BAR
+chartTitle=Impact of message size on latency
+chartSubtitle=Persistent messages
+xAxisTitle=Message Size (B)
+yAxisTitle=Latency (millis)
+
+series.1.statement=SELECT payloadSizeB, maxLatency, 0 FROM Latency-MessageSize WHERE testName like '%PERSISTENT' AND participantName = 'All Consumers'
+series.1.legend=Maximum latency
+series.1.dir=${csvCurrentDir}
+
+series.2.statement=SELECT payloadSizeB, averageLatency, latencyStandardDeviation FROM Latency-MessageSize WHERE testName like '%PERSISTENT' AND participantName = 'All Consumers'
+series.2.legend=Average latency
+series.2.dir=${csvCurrentDir}
+
+series.3.statement=SELECT payloadSizeB, averageLatency, latencyStandardDeviation FROM Latency-MessageSize WHERE testName like '%PERSISTENT' AND participantName = 'All Consumers'
+series.3.legend=Average latency (baseline)
+series.3.dir=${csvBaselineDir}
+
+series.4.statement=SELECT payloadSizeB, minLatency, 0 FROM Latency-MessageSize WHERE testName like '%PERSISTENT' AND participantName = 'All Consumers'
+series.4.legend=Minimum latency
+series.4.dir=${csvCurrentDir}
diff --git a/java/perftests/etc/chartdefs/2011-Latency-QueuesWithNonOverlappingSelectors-Transient.chartdef b/java/perftests/etc/chartdefs/2011-Latency-QueuesWithNonOverlappingSelectors-Transient.chartdef
new file mode 100644
index 0000000000..45c6031b1e
--- /dev/null
+++ b/java/perftests/etc/chartdefs/2011-Latency-QueuesWithNonOverlappingSelectors-Transient.chartdef
@@ -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.
+#
+
+chartType=STATISTICAL_BAR
+chartTitle=Latency with consumers having non-overlapping selectors
+chartSubtitle=Transient 1KB messages
+xAxisTitle=Consumers
+yAxisTitle=Latency (millis)
+
+series.1.statement=SELECT totalNumberOfConsumers, maxLatency, 0 FROM Latency-QueuesWithSelectors WHERE participantName = 'All Consumers' and testName like '%non overlapping - NON_PERSISTENT%'
+series.1.legend=Max latency
+series.1.dir=${csvCurrentDir}
+
+series.2.statement=SELECT totalNumberOfConsumers, averageLatency,latencyStandardDeviation FROM Latency-QueuesWithSelectors WHERE participantName = 'All Consumers' and testName like '%non overlapping - NON_PERSISTENT%'
+series.2.legend=Average latency
+series.2.dir=${csvCurrentDir}
+
+series.3.statement=SELECT totalNumberOfConsumers, averageLatency,latencyStandardDeviation FROM Latency-QueuesWithSelectors WHERE participantName = 'All Consumers' and testName like '%non overlapping - NON_PERSISTENT%'
+series.3.legend=Average latency (baseline)
+series.3.dir=${csvBaselineDir}
+
+series.4.statement=SELECT totalNumberOfConsumers, minLatency, 0 FROM Latency-QueuesWithSelectors WHERE participantName = 'All Consumers' and testName like '%non overlapping - NON_PERSISTENT%'
+series.4.legend=Min latency
+series.4.dir=${csvCurrentDir}
diff --git a/java/perftests/etc/chartdefs/2012-Latency-QueuesWithOverlappingSelectors-Transient.chartdef b/java/perftests/etc/chartdefs/2012-Latency-QueuesWithOverlappingSelectors-Transient.chartdef
new file mode 100644
index 0000000000..351a4639b1
--- /dev/null
+++ b/java/perftests/etc/chartdefs/2012-Latency-QueuesWithOverlappingSelectors-Transient.chartdef
@@ -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.
+#
+
+chartType=STATISTICAL_BAR
+chartTitle=Latency with consumers having 50%-overlapping selectors
+chartSubtitle=Transient 1KB messages
+xAxisTitle=Consumers
+yAxisTitle=Latency (millis)
+
+series.1.statement=SELECT totalNumberOfConsumers, maxLatency, 0 FROM Latency-QueuesWithSelectors WHERE participantName = 'All Consumers' and testName like '%overlapping 50% - NON_PERSISTENT%'
+series.1.legend=Max latency
+series.1.dir=${csvCurrentDir}
+
+series.2.statement=SELECT totalNumberOfConsumers, averageLatency,latencyStandardDeviation FROM Latency-QueuesWithSelectors WHERE participantName = 'All Consumers' and testName like '%overlapping 50% - NON_PERSISTENT%'
+series.2.legend=Average latency
+series.2.dir=${csvCurrentDir}
+
+series.3.statement=SELECT totalNumberOfConsumers, averageLatency,latencyStandardDeviation FROM Latency-QueuesWithSelectors WHERE participantName = 'All Consumers' and testName like '%overlapping 50% - NON_PERSISTENT%'
+series.3.legend=Average latency (baseline)
+series.3.dir=${csvBaselineDir}
+
+series.4.statement=SELECT totalNumberOfConsumers, minLatency, 0 FROM Latency-QueuesWithSelectors WHERE participantName = 'All Consumers' and testName like '%overlapping 50% - NON_PERSISTENT%'
+series.4.legend=Min latency
+series.4.dir=${csvCurrentDir}
diff --git a/java/perftests/etc/chartdefs/2021-Latency-QueuesWithNonOverlappingSelectors-Persistent.chartdef b/java/perftests/etc/chartdefs/2021-Latency-QueuesWithNonOverlappingSelectors-Persistent.chartdef
new file mode 100644
index 0000000000..9d95075b3d
--- /dev/null
+++ b/java/perftests/etc/chartdefs/2021-Latency-QueuesWithNonOverlappingSelectors-Persistent.chartdef
@@ -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.
+#
+
+chartType=STATISTICAL_BAR
+chartTitle=Latency with consumers having non-overlapping selectors
+chartSubtitle=Persistent 1KB messages
+xAxisTitle=Consumers
+yAxisTitle=Latency (millis)
+
+series.1.statement=SELECT totalNumberOfConsumers, maxLatency,0 FROM Latency-QueuesWithSelectors WHERE participantName = 'All Consumers' and testName like '%non overlapping - PERSISTENT'
+series.1.legend=Max latency
+series.1.dir=${csvCurrentDir}
+
+series.2.statement=SELECT totalNumberOfConsumers, averageLatency, latencyStandardDeviation FROM Latency-QueuesWithSelectors WHERE participantName = 'All Consumers' and testName like '%non overlapping - PERSISTENT'
+series.2.legend=Average latency
+series.2.dir=${csvCurrentDir}
+
+series.3.statement=SELECT totalNumberOfConsumers, averageLatency, latencyStandardDeviation FROM Latency-QueuesWithSelectors WHERE participantName = 'All Consumers' and testName like '%non overlapping - PERSISTENT'
+series.3.legend=Average latency (baseline)
+series.3.dir=${csvBaselineDir}
+
+series.4.statement=SELECT totalNumberOfConsumers, minLatency, 0 FROM Latency-QueuesWithSelectors WHERE participantName = 'All Consumers' and testName like '%non overlapping - PERSISTENT'
+series.4.legend=Min latency
+series.4.dir=${csvCurrentDir}
diff --git a/java/perftests/etc/chartdefs/2022-Latency-QueuesWithOverlappingSelectors-Persistent.chartdef b/java/perftests/etc/chartdefs/2022-Latency-QueuesWithOverlappingSelectors-Persistent.chartdef
new file mode 100644
index 0000000000..9a323d4044
--- /dev/null
+++ b/java/perftests/etc/chartdefs/2022-Latency-QueuesWithOverlappingSelectors-Persistent.chartdef
@@ -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.
+#
+
+chartType=STATISTICAL_BAR
+chartTitle=Latency with consumers having 50%-overlapping selectors
+chartSubtitle=Persistent 1KB messages
+xAxisTitle=Consumers
+yAxisTitle=Latency (millis)
+
+series.1.statement=SELECT totalNumberOfConsumers, maxLatency, 0 FROM Latency-QueuesWithSelectors WHERE participantName = 'All Consumers' and testName like '%overlapping 50% - PERSISTENT%'
+series.1.legend=Max latency
+series.1.dir=${csvCurrentDir}
+
+series.2.statement=SELECT totalNumberOfConsumers, averageLatency,latencyStandardDeviation FROM Latency-QueuesWithSelectors WHERE participantName = 'All Consumers' and testName like '%overlapping 50% - PERSISTENT%'
+series.2.legend=Average latency
+series.2.dir=${csvCurrentDir}
+
+series.3.statement=SELECT totalNumberOfConsumers, averageLatency,latencyStandardDeviation FROM Latency-QueuesWithSelectors WHERE participantName = 'All Consumers' and testName like '%overlapping 50% - PERSISTENT%'
+series.3.legend=Average latency (baseline)
+series.3.dir=${csvBaselineDir}
+
+series.4.statement=SELECT totalNumberOfConsumers, minLatency, 0 FROM Latency-QueuesWithSelectors WHERE participantName = 'All Consumers' and testName like '%overlapping 50% - PERSISTENT%'
+series.4.legend=Min latency
+series.4.dir=${csvCurrentDir}
diff --git a/java/perftests/etc/chartdefs/2031-Latency-VaryingNumberOfParticipants.chartdef b/java/perftests/etc/chartdefs/2031-Latency-VaryingNumberOfParticipants.chartdef
new file mode 100644
index 0000000000..82cf1168ef
--- /dev/null
+++ b/java/perftests/etc/chartdefs/2031-Latency-VaryingNumberOfParticipants.chartdef
@@ -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.
+#
+
+chartType=STATISTICAL_BAR
+chartTitle=Latency, varying number of participants
+chartSubtitle=Persistent 1KB messages
+xAxisTitle=Consumers
+yAxisTitle=Latency (millis)
+
+series.1.statement=SELECT totalNumberOfConsumers, averageLatency,latencyStandardDeviation FROM Latency-VaryingNumberOfParticipants WHERE participantName = 'All Consumers' and testName like '% - 1 producer - PERSISTENT'
+series.1.legend=1 producer
+series.1.dir=${csvCurrentDir}
+
+series.2.statement=SELECT totalNumberOfConsumers, averageLatency,latencyStandardDeviation FROM Latency-VaryingNumberOfParticipants WHERE participantName = 'All Consumers' and testName like '% - 2 producers - PERSISTENT'
+series.2.legend=2 producers
+series.2.dir=${csvCurrentDir}
+
+series.3.statement=SELECT totalNumberOfConsumers, averageLatency,latencyStandardDeviation FROM Latency-VaryingNumberOfParticipants WHERE participantName = 'All Consumers' and testName like '% - 5 producers - PERSISTENT'
+series.3.legend=5 producers
+series.3.dir=${csvCurrentDir}
+
+series.4.statement=SELECT totalNumberOfConsumers, averageLatency,latencyStandardDeviation FROM Latency-VaryingNumberOfParticipants WHERE participantName = 'All Consumers' and testName like '% - 10 producers - PERSISTENT'
+series.4.legend=10 producers
+series.4.dir=${csvCurrentDir}
+
+series.5.statement=SELECT totalNumberOfConsumers, averageLatency,latencyStandardDeviation FROM Latency-VaryingNumberOfParticipants WHERE participantName = 'All Consumers' and testName like '% - 10 producers - PERSISTENT'
+series.5.legend=10 producers (baseline)
+series.5.dir=${csvBaselineDir}
diff --git a/java/perftests/etc/chartdefs/2041-Latency-QueueTypes.chartdef b/java/perftests/etc/chartdefs/2041-Latency-QueueTypes.chartdef
new file mode 100644
index 0000000000..c1aae19376
--- /dev/null
+++ b/java/perftests/etc/chartdefs/2041-Latency-QueueTypes.chartdef
@@ -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.
+#
+
+chartType=STATISTICAL_BAR
+chartTitle=Latency on different queues
+chartSubtitle=Persistent 1KB messages
+xAxisTitle=Queue type
+yAxisTitle=Latency (millis)
+
+series.1.statement=SELECT testName, maxLatency,0 FROM Latency-QueueTypes WHERE participantName = 'All Consumers'
+series.1.legend=Maximum latency
+series.1.dir=${csvCurrentDir}
+
+series.2.statement=SELECT testName, averageLatency,latencyStandardDeviation FROM Latency-QueueTypes WHERE participantName = 'All Consumers'
+series.2.legend=Average Latency
+series.2.dir=${csvCurrentDir}
+
+series.3.statement=SELECT testName, averageLatency,latencyStandardDeviation FROM Latency-QueueTypes WHERE participantName = 'All Consumers'
+series.3.legend=Average Latency (baseline)
+series.3.dir=${csvBaselineDir}
+
+series.4.statement=SELECT testName, minLatency,0 FROM Latency-QueueTypes WHERE participantName = 'All Consumers'
+series.4.legend=Minimum latency
+series.4.dir=${csvCurrentDir}
diff --git a/java/perftests/etc/log4j.properties b/java/perftests/etc/log4j.properties
index 60e15d0817..ec00e022ac 100644
--- a/java/perftests/etc/log4j.properties
+++ b/java/perftests/etc/log4j.properties
@@ -25,4 +25,4 @@ log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.Threshold=all
log4j.appender.console.layout=org.apache.log4j.PatternLayout
-log4j.appender.console.layout.ConversionPattern=%d %p [%c{1}] %m%n \ No newline at end of file
+log4j.appender.console.layout.ConversionPattern=%d %p [%t] [%c{1}] %m%n
diff --git a/java/perftests/etc/perftests-jndi.properties b/java/perftests/etc/perftests-jndi.properties
index 8ad0decaad..f33af6fdd5 100644
--- a/java/perftests/etc/perftests-jndi.properties
+++ b/java/perftests/etc/perftests-jndi.properties
@@ -15,12 +15,8 @@
# specific language governing permissions and limitations
# under the License.
-# this file is used for running system tests of the performance test framework,
-# (i.e. not for running the performance tests themselves!)
-
java.naming.factory.initial = org.apache.qpid.jndi.PropertiesFileInitialContextFactory
-# use QpidBrokerTestCase's default port
connectionfactory.connectionfactory = amqp://guest:guest@clientid/test?brokerlist='tcp://localhost:5672'
-destination.controllerqueue = direct://amq.direct//controllerqueue
+destination.controllerqueue = direct://amq.direct//controllerqueue?autodelete='true'
diff --git a/java/perftests/etc/testdefs/short/AcknowledgementModes.json b/java/perftests/etc/testdefs/AcknowledgementModes.json
index d504c486aa..071edf3f0e 100644
--- a/java/perftests/etc/testdefs/short/AcknowledgementModes.json
+++ b/java/perftests/etc/testdefs/AcknowledgementModes.json
@@ -1,17 +1,15 @@
{
"_tests":[
{
- "_name": "Acknowledgement Modes - NON_PERSISTENT";
+ "_name": "Transient Ack Modes";
"_iterations":[
{
"_messageSize": 1024,
- "_numberOfMessages": 1000000,
"_acknowledgeMode": 1,
"_deliveryMode": 1
},
{
"_messageSize": 1024,
- "_numberOfMessages": 250000,
"_acknowledgeMode": 0,
"_deliveryMode": 1
}
@@ -39,7 +37,8 @@
"_producers": [
{
"_name": "Producer1",
- "_destinationName": "direct://amq.direct//testQueue"
+ "_destinationName": "direct://amq.direct//testQueue",
+ "_maximumDuration": 30000
}
]
}
@@ -59,7 +58,8 @@
"_consumers": [
{
"_name": "Consumer1",
- "_destinationName": "direct://amq.direct//testQueue"
+ "_destinationName": "direct://amq.direct//testQueue",
+ "_maximumDuration": 30000
}
]
}
@@ -70,17 +70,15 @@
]
},
{
- "_name": "Acknowledgement Modes - PERSISTENT";
+ "_name": "Persistent Ack Modes";
"_iterations":[
{
"_messageSize": 1024,
- "_numberOfMessages": 100000,
"_acknowledgeMode": 1,
"_deliveryMode": 2
},
{
"_messageSize": 1024,
- "_numberOfMessages": 25000,
"_acknowledgeMode": 0,
"_deliveryMode": 2
}
@@ -104,7 +102,8 @@
"_producers": [
{
"_name": "Producer1",
- "_destinationName": "direct://amq.direct//testQueue?durable='true'"
+ "_destinationName": "direct://amq.direct//testQueue?durable='true'",
+ "_maximumDuration": 30000
}
]
}
@@ -124,7 +123,8 @@
"_consumers": [
{
"_name": "Consumer1",
- "_destinationName": "direct://amq.direct//testQueue?durable='true'"
+ "_destinationName": "direct://amq.direct//testQueue?durable='true'",
+ "_maximumDuration": 30000
}
]
}
diff --git a/java/perftests/etc/testdefs/short/BatchSize.json b/java/perftests/etc/testdefs/BatchSize.json
index eeb446bad6..eeb446bad6 100644
--- a/java/perftests/etc/testdefs/short/BatchSize.json
+++ b/java/perftests/etc/testdefs/BatchSize.json
diff --git a/java/perftests/etc/testdefs/standard/MessageSize.json b/java/perftests/etc/testdefs/Latency-MessageSize.json
index b679f81926..47eb703337 100644
--- a/java/perftests/etc/testdefs/standard/MessageSize.json
+++ b/java/perftests/etc/testdefs/Latency-MessageSize.json
@@ -1,61 +1,45 @@
{
"_tests":[
{
- "_name": "Message Size - 1P-1C - NON_PERSISTENT";
+ "_name": "Latency - Message Size - TRANSIENT";
"_iterations":[
{
- "_messageSize": 256,
- "_numberOfMessages": 10000000
+ "_messageSize": 256
},
{
- "_messageSize": 512,
- "_numberOfMessages": 5000000
+ "_messageSize": 512
},
{
- "_messageSize": 1024,
- "_numberOfMessages": "2500000"
+ "_messageSize": 1024
},
{
- "_messageSize": 2048,
- "_numberOfMessages": "1250000"
+ "_messageSize": 2048
},
{
- "_messageSize": 4096,
- "_numberOfMessages": "625000"
+ "_messageSize": 4096
},
{
- "_messageSize": 8192,
- "_numberOfMessages": 312500
+ "_messageSize": 8192
},
{
- "_messageSize": 16384,
- "_numberOfMessages": 156250
+ "_messageSize": 16384
},
{
- "_messageSize": 32768,
- "_numberOfMessages": 78125
+ "_messageSize": 32768
},
{
- "_messageSize": 65536,
- "_numberOfMessages": 39062
+ "_messageSize": 65536
},
{
- "_messageSize": 131072,
- "_numberOfMessages": 1953
+ "_messageSize": 131072
},
{
- "_messageSize": 262144,
- "_numberOfMessages": 976
+ "_messageSize": 262144
}
],
"_queues":[
{
- "_name": "direct://amq.direct//messageSize",
- "_attributes":
- {
- "x-qpid-capacity": 10485760,
- "x-qpid-flow-resume-capacity": 8388608
- }
+ "_name": "direct://amq.direct//latency-message-size-transient"
}
],
"_clients":[
@@ -72,8 +56,10 @@
"_producers": [
{
"_name": "Producer1",
- "_destinationName": "direct://amq.direct//messageSize",
- "_deliveryMode": 1
+ "_destinationName": "direct://amq.direct//latency-message-size-transient",
+ "_deliveryMode": 1,
+ "_maximumDuration": 60000,
+ "_interval": 1000
}
]
}
@@ -94,7 +80,9 @@
"_consumers": [
{
"_name": "Consumer1",
- "_destinationName": "direct://amq.direct//messageSize"
+ "_destinationName": "direct://amq.direct//latency-message-size-transient",
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true
}
]
}
@@ -105,62 +93,46 @@
]
},
{
- "_name": "Message Size - 1P-1C - PERSISTENT";
+ "_name": "Latency - Message Size - PERSISTENT";
"_iterations":[
{
- "_messageSize": 256,
- "_numberOfMessages": 200000
+ "_messageSize": 256
},
{
- "_messageSize": 512,
- "_numberOfMessages": 200000
+ "_messageSize": 512
},
{
- "_messageSize": 1024,
- "_numberOfMessages": 200000
+ "_messageSize": 1024
},
{
- "_messageSize": 2048,
- "_numberOfMessages": 200000
+ "_messageSize": 2048
},
{
- "_messageSize": 4096,
- "_numberOfMessages": 40000
+ "_messageSize": 4096
},
{
- "_messageSize": 8192,
- "_numberOfMessages": 40000
+ "_messageSize": 8192
},
{
- "_messageSize": 16384,
- "_numberOfMessages": 40000
+ "_messageSize": 16384
},
{
- "_messageSize": 32768,
- "_numberOfMessages": 20000
+ "_messageSize": 32768
},
{
- "_messageSize": 65536,
- "_numberOfMessages": 20000
+ "_messageSize": 65536
},
{
- "_messageSize": 131072,
- "_numberOfMessages": 20000
+ "_messageSize": 131072
},
{
- "_messageSize": 262144,
- "_numberOfMessages": 20000
+ "_messageSize": 262144
}
],
"_queues":[
{
- "_name": "direct://amq.direct//messageSize?durable='true'",
- "_durable": true,
- "_attributes":
- {
- "x-qpid-capacity": 10485760,
- "x-qpid-flow-resume-capacity": 8388608
- }
+ "_name": "direct://amq.direct//latency-message-size-persistent?durable='true'",
+ "_durable": true
}
],
"_clients":[
@@ -177,8 +149,10 @@
"_producers": [
{
"_name": "Producer1",
- "_destinationName": "direct://amq.direct//messageSize?durable='true'",
- "_deliveryMode": 2
+ "_destinationName": "direct://amq.direct//latency-message-size-persistent?durable='true'",
+ "_deliveryMode": 2,
+ "_maximumDuration": 60000,
+ "_interval": 1000
}
]
}
@@ -199,7 +173,9 @@
"_consumers": [
{
"_name": "Consumer1",
- "_destinationName": "direct://amq.direct//messageSize?durable='true'"
+ "_destinationName": "direct://amq.direct//latency-message-size-persistent?durable='true'",
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true
}
]
}
diff --git a/java/perftests/etc/testdefs/Latency-QueueTypes.json b/java/perftests/etc/testdefs/Latency-QueueTypes.json
new file mode 100644
index 0000000000..9f6f690306
--- /dev/null
+++ b/java/perftests/etc/testdefs/Latency-QueueTypes.json
@@ -0,0 +1,261 @@
+{
+ "_tests":[
+ {
+ "_name": "simple";
+ "_queues":[
+ {
+ "_name": "direct://amq.direct//simple-queue?durable='true'",
+ "_durable": true
+ }
+ ],
+ "_clients":[
+ {
+ "_name": "producingClient",
+ "_connections":[
+ {
+ "_name": "connection1",
+ "_factory": "connectionfactory",
+ "_sessions": [
+ {
+ "_sessionName": "session1",
+ "_acknowledgeMode": 1,
+ "_producers": [
+ {
+ "_name": "Producer1",
+ "_destinationName": "direct://amq.direct//simple-queue?durable='true'",
+ "_deliveryMode": 2,
+ "_messageSize": 1024,
+ "_maximumDuration": 60000,
+ "_interval": 1000
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_name": "consumingClient",
+ "_connections":[
+ {
+ "_name": "connection1",
+ "_factory": "connectionfactory",
+ "_sessions": [
+ {
+ "_sessionName": "session1",
+ "_acknowledgeMode": 1,
+ "_consumers": [
+ {
+ "_name": "Consumer1",
+ "_destinationName": "direct://amq.direct//simple-queue?durable='true'",
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_name": "sorted";
+ "_queues":[
+ {
+ "_name": "direct://amq.direct//sorted-queue?durable='true'",
+ "_durable": true,
+ "_attributes":
+ {
+ "qpid.queue_sort_key": "sort-key"
+ }
+ }
+ ],
+ "_clients":[
+ {
+ "_name": "producingClient",
+ "_messageProviders": [
+ {
+ "_name": "messageProvider",
+ "_messageProperties":{ "sort-key": {"@def": "list", "_items": [
+"GWqqXCp3mZ","b29RJ45cIH","7hyVvgtCA5","16lHcCxVEf","jzUqRuPX7G","0Wr5y4QMc9","pWiOsLbRTH","Dz1R3BGaQY","Cfgr39y4lw","Zv7z0FxX9q",
+"lj07QxXTI4","RACuj9XyT9","MGlTF55rfB","0Wr5yW3VFH","lweGyVprf2","lpF6WuJScX","lCMxy2TRI7","KZamHl83Ud","5drc6jiVBP","rKDLJwDajX",
+"CK5W7MezSW","2TRI7LbRTH","zqH0WiwzGk","hYBCKUvlv4","Mkgy8Q6hMC","8FmFHjtn0X","8FmFH5Mg9r","hUTw7rz7Ut","pmeCdQnJ1S","euZA5dQ586",
+"sqVrfQWxoT","RsQUqTwano","7ku1ptlILt","jzUqRpiJSk","0YAGH5Drn0","7ku1pCxVEf","QbxXc8hJdt","4W0Tldpe1v","MK07Ys7Mxk","zHF1qCNHmv",
+"uoStwRzaZA","KZamHVLTy6","XyPZN5Drn0","7fKYU07n1c","HfyNQiwzGk","mX2GEoGu6x","9eoRcydG8U","pAhR1iKqhr","LbRTHb29RJ","Waim6DLhzM",
+"bgJAzReKEW","pmeCdjeskS","gdQsSguMb8","Oz8yZI7p2a","ogLgculk41","HfyNQ0MR5X","24ARFWDVWJ","uAWypwDajX","lH1kt6AFT0","EOE1oZhwG1",
+"AIYUu0Kyfs","prNT6uTacx","TwanoFPfSE","OUYuFAXpwE","euZA5FVMxo","ni2v10BmCy","5Mg9rJRJQB","nlaBya00b5","7X3uyL7cGc","ECMvU55rfB",
+"JXljW2TRI7","Z4I1vY1mC0","lj07QFhtgl","fqypycmXIX","Ul4a1GrDg7","LDk6fulk41","2Nslm2hEEU","LbRTHuTacx","gIYvEK4GS8","Cfgr3i7WMQ",
+"pWiOss4786","mX2GETCgPp","8xEKzjeskS","uTacxDQimp","ksJbyfFDrJ","7fKYUAOgEe","5Drn0azIWp","he9IAIKxdL","HfyNQTwano","FcWrW0ao3l",
+"iKqhrn8pJ9","BbwgArhl0J","M6qcGjiVBP","b29RJ8U2nU","MK07Y8cVD3","dhSuHjfREu","azIWpjS1aj","qQxHPTwano","QChxsJRJQB","YjB9tuZPqg",
+"zFgtB9GXkX","FnPFB5VZjS","VNCPdpv0i7","WmadAHP433","x3LDeokgRi","uLtKsChuy3","uQIczRBhp0","pAhR1lViBv","pAhR1ThjNn","QChxsQChxs",
+"a00b5wDajX","StlDJMm8si","QWxoTVprf2","zbIYY7lUXZ","Mm8siazIWp","lsQGoGSQwj","AgJHQFPfSE","JKWYRpiJSk","StlDJCp3mZ","rKDLJ580YD",
+"uupzkKASQ8","uZPqgEdBKc","Chuy3gtCA5","5NammfcwDa","xReecAOgEe","fLNg8Oz8yZ","RzaZAjfREu","t98iWSWfou","RkQkeO3iyQ","7X3uyjS1aj",
+"ECMvULewvM","jfREuJKWYR","GrDg72DREs","CxVEfoVQp6","ix74rFPfSE","5drc6FxX9q","9iGoTzHF1q","0BmCyjSjS3","JkzUn7hyVv","FxX9qdhSuH",
+"SbRYyMezSW","lj07QFcWrW","CqqaDW3VFH","lkMUA5nmWv","AgJHQQssNC","5NammyEfy9","Qworu5drc6","AOgEefmIK1","P6bcg5Namm","QWxoTJ2mQi",
+"Uvlv4guMb8","Ul4a1Rxrsm","EdBKcGrDg7","aDGtS2hEEU","taOXK0PktI","iqv4kuLtKs","yEfy924ARF","Y1mC0yEfy9","jzUqRxciqp","2TRI7uupzk",
+"0PktIfcwDa","GrDg707n1c","lweGy4QMc9","dpe1vRpBQm","SmGzvmX2GE","LbRTHWMiS3","FLsphv2eC3","yofH3In3NS","y94nwyluBx","Vprf2ogLgc",
+"5nmWvgdQsS","Dz1R3k85Ae","24ARF7Ow5C","rhl0JLbRTH","wiHrZVNCPd","uupzk2TRI7","kZANmMojnP","ZJTXHRBhp0","GXdoHogLgc","8RCUAfmIK1",
+"tvdkDJIqXi","9rlg9i3pyd","fcwDazz4ZU","s7MxkYh1hF","jS1ajjtn0X","PYBf4prNT6","29QAz64s8N","he9IAS77LH","zmLYDVBjhz","HfyNQbZLvS",
+"aFFssW3VFH","ThjNnM6qcG","D6rByGv3Fq","ulk41M6qcG","WMiS3cL0aE","TXQ0ZQClRL","O3iyQQClRL","JKWYRqUJMd","Dz1R3WaWsv","L7cGcatef2",
+"d85a9NAFuw","9GXkXFGzgp","DLhzMM6qcG","lXFOB07n1c","9rlg9b29RJ","XyPZN24ARF","JJs5mm4bxU","29QAzatef2","MojnPguMb8","suY4xOz8yZ",
+"lViBv9y4lw","AIYUuLDk6f","J2mQiAIYUu","DcpWBo8Uyd","he9IABGaQY","lCMxyiqv4k","soy9t0PktI","BGaQY4W0Tl","h1zcHlkMUA","RBhp0rz7Ut",
+"gtCA50ao3l","gtCA55Drn0","TwanogtCA5","RsQUqKr8ys","5IhmGYf2Ec","EdBKcni2v1","ZuDtD0PktI","sx5GlTa8f6","RpBQmo8Uyd","tuDySAkKTk",
+"5iGN5CIShG","BGaQYsqVrf","IjTwPRmDcr","ciuWz9GXkX","FGzgpvkCHH","fmIK15Namm","i3pydVjCZq","MmsIo618Di","8xEKzciuWz","WreyPx3LDe",
+"S77LHpFrrl","FVMxo2TRI7","gf8rIQClRL","X6PinDcpWB","RxrsmS77LH","EdBKc2ZHdk","gIYvEgdQsS","qQxHPNOHsz","uQIczciuWz","K20wK7X3uy",
+"Z4I1vzQt6Q","vLsmSMmsIo","yofH3ZUnqt","yofH31v5hH","FLsphECMvU","FnPFBFhtgl","azIWpguMb8","G1RhSiqv4k","Cp3mZyvOMI","2TRI7Chuy3",
+"okgRi7fKYU","yvOMIUvlv4","5ZaEz7X3uy","O3iyQhe9IA","UmaEvQbxXc","Zv7z0faHir","K4GS8jzUqR","d7vjM0BmCy","b29RJyluBx","IRh483otm6",
+"yvOMI0BmCy","ReKEWQWxoT","jeskSZhwG1","HfyNQTa8f6","0Kyfsn8pJ9","s4786FVMxo","tAOsrRpBQm","ru4UGGWqqX","LewvMpmeCd","7Ow5CiwzGk",
+"6AFT0OHaBz","n8pJ9Ta8f6","lsQGoNAFuw","dhSuH0BmCy","2hEEUXflUq","WMiS35nmWv","6q6L9KsjRK","mX2GEFNYIM","8RCUA5ZaEz","HlUbFMmKGJ",
+"2DREst98iW","v1Hlna00b5","5drc6VNCPd","RxrsmpWiOs","B3qemcQOnv","Mm8siKr8ys","yofH32ZHdk","v8yFNW7cTs","UlU3McQOnv","K4GS8iqv4k",
+"v2eC3guMb8","Waim6Dz1R3","SjskQYf2Ec","bgJAz0BmCy","OHaBzjiVBP","HRxd8TXQ0Z","b29RJPYBf4","piJSkJJs5m","mX2GEcL0aE","FGzgp2DREs",
+"MK07YfcwDa","faHiroQ87r","FcWrW8TxD7","tlILtVerEA","8FmFHiqv4k","OUYuFVjCZq","tlILtMGlTF","24ARFOz8yZ","8FmFHQ6hMC","okgRiFLsph",
+"b29RJ618Di","faHirBCxeC","fFDrJTa8f6","FGzgp8cVD3","nFqik8FmFH","RACujVNCPd","B3qemuLtKs","RpBQmxciqp","gdQsSpiJSk","8RCUA9rlg9",
+"GWqqX1v5hH","l83UdiKqhr","5Mg9rl83Ud","TwanoQ6hMC","K4GS8pv0i7","48cHLyEfy9","i7WMQrKDLJ","IRh48Ta8f6","sx5GlI7p2a","4dEz629QAz",
+"6q6L95IhmG","RACujDcpWB","WmadAStlDJ","Mm8siVNCPd","Ta8f6Fhtgl","RsQUqqQxHP","FnPFBQbxXc","0ao3l2Yz7E","7fsYMKr8ys","3weIF7X3uy",
+"azIWptuDyS","m4bxUazIWp","soy9tVprf2","VLTy6iKqhr","Z4I1vFjHXR","0MR5XNcICA","580YD8hJdt","MaJQsI7p2a","mz8gxfqypy","aL6AJpiJSk",
+"Pb1paDLhzM","7Ow5CU3yw5","uJScXiKqhr","5IhmG45cIH","ru4UG580YD","S77LHoQ87r","RkQkeOxWIH","uJScXlkMUA","0KyfsAXpwE","qUJMdUvlv4",
+"OHaBzYh1hF","ciuWzX6Pin","FwEJzL7cGc","i3pydsuY4x","zFgtBuoStw","QWxoTyluBx","uN6r3Cp3mZ","QWxoTM6qcG","pvgjS16lHc","v2eC3Yw2oU",
+"Gv3FqVBjhz","Y1mC0AgJHQ","3otm6618Di","1LB1Lfqypy","TCgPp7Ow5C","1v5hHVIlwP","CNHmvfcwDa","JRJQBv2eC3","lXFOBulk41","0BmCyy94nw",
+"LewvM9GXkX","rz7Uts4786","7fKYUZzJHW","vkCHHHfyNQ","PYBf4gf8rI","iqv4kt98iW","ulk41s93Ml","v2eC3gtCA5","kB5nPRzaZA","ThjNnUl4a1",
+"0KyfsJXljW","brhlQpAhR1","Waim6gjUTu","WDVWJVIlwP","Chuy3jfREu","b29RJuQIcz","v8yFNFhtgl","Yh1hF5VZjS","cL0aEfcJOy","CK5W7TXQ0Z",
+"OxWIHb29RJ","m4bxUzFgtB","GWqqXAmdQd","o8Uyd0BmCy","t98iWTXQ0Z","NcICA1LB1L","MmsIo580YD","kB5nPECMvU","LbRTHtuDyS","t59lRlm0pD",
+"CqqaDQClRL","cmXIXLewvM","KZamHpWiOs","S2DfuGv3Fq","W3VFHiB08l","vOqCEqaofN","v1Hlnfqypy","iB08laez9y","ThjNnIjTwP","uAWypgdQsS",
+"StlDJtlILt","zmLYDReKEW","9iGoTzY1GY","tAOsrTXQ0Z","JRJQBAIYUu","618Die6e4z","FjHXRzFgtB","aL6AJ9iGoT","FPfSEoVQp6","RACujK20wK",
+"yEfy9FjHXR","uQIczMGlTF","v2eC32TRI7","24ARFfqypy","9eoRcAXpwE","WreyPjS1aj","n8pJ9Z4I1v","29QAztl72W","zY1GYAmdQd","JJs5m5VZjS"
+] } }
+}
+ ],
+ "_connections":[
+ {
+ "_name": "connection1",
+ "_factory": "connectionfactory",
+ "_sessions": [
+ {
+ "_sessionName": "session1",
+ "_acknowledgeMode": 1,
+ "_producers": [
+ {
+ "_name": "Producer1",
+ "_destinationName": "direct://amq.direct//sorted-queue?durable='true'",
+ "_deliveryMode": 2,
+ "_messageSize": 1024,
+ "_messageProviderName": "messageProvider",
+ "_maximumDuration": 60000,
+ "_interval": 1000
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_name": "consumingClient",
+ "_connections":[
+ {
+ "_name": "connection1",
+ "_factory": "connectionfactory",
+ "_sessions": [
+ {
+ "_sessionName": "session1",
+ "_acknowledgeMode": 1,
+ "_consumers": [
+ {
+ "_name": "Consumer1",
+ "_destinationName": "direct://amq.direct//sorted-queue?durable='true'",
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_name": "priority";
+ "_queues":[
+ {
+ "_name": "direct://amq.direct//priority-queue?durable='true'",
+ "_durable": true,
+ "_attributes":
+ {
+ "x-qpid-priorities": 10
+ }
+ }
+ ],
+ "_clients":[
+ {
+ "_name": "producingClient",
+ "_messageProviders": [
+ {
+ "_name": "messageProvider",
+ "_messageProperties":{ "priority": {"@def": "list", "_items": [
+0,1,0,2,3,9,9,5,0,7,8,2,2,1,8,4,3,6,7,1,
+9,9,8,7,3,5,5,8,1,1,0,6,9,4,2,2,0,6,2,2,
+8,5,3,2,9,6,7,4,4,9,2,8,7,5,0,3,8,8,2,3,
+1,3,7,9,0,0,2,5,4,3,2,1,0,1,2,3,4,5,6,9,
+0,0,8,6,7,4,5,2,5,7,4,2,6,7,5,2,3,4,5,2,
+8,5,3,6,3,6,7,3,6,7,8,4,3,5,3,5,8,1,0,9,
+2,4,6,1,6,1,7,8,9,2,4,0,0,3,5,7,8,9,0,2,
+5,3,2,4,5,3,2,4,6,7,4,8,2,7,2,8,9,3,8,0,
+2,7,8,2,4,8,3,7,9,2,6,6,7,3,3,5,7,9,0,0,
+9,8,8,8,4,5,6,8,9,2,3,7,8,9,3,2,2,4,5,6,
+2,2,8,4,9,2,6,4,3,2,4,9,7,5,7,8,0,9,4,5
+], "_type": "int"} }
+ }
+ ],
+ "_connections":[
+ {
+ "_name": "connection1",
+ "_factory": "connectionfactory",
+ "_sessions": [
+ {
+ "_sessionName": "session1",
+ "_acknowledgeMode": 1,
+ "_producers": [
+ {
+ "_name": "Producer1",
+ "_destinationName": "direct://amq.direct//priority-queue?durable='true'",
+ "_deliveryMode": 2,
+ "_messageSize": 1024,
+ "_messageProviderName": "messageProvider",
+ "_maximumDuration": 60000,
+ "_interval": 1000
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_name": "consumingClient",
+ "_connections":[
+ {
+ "_name": "connection1",
+ "_factory": "connectionfactory",
+ "_sessions": [
+ {
+ "_sessionName": "session1",
+ "_acknowledgeMode": 1,
+ "_consumers": [
+ {
+ "_name": "Consumer1",
+ "_destinationName": "direct://amq.direct//priority-queue?durable='true'",
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/java/perftests/etc/testdefs/standard/QueuesWithSelectors.json b/java/perftests/etc/testdefs/Latency-QueuesWithSelectors.json
index 2e8175c602..49e6c23b89 100644
--- a/java/perftests/etc/testdefs/standard/QueuesWithSelectors.json
+++ b/java/perftests/etc/testdefs/Latency-QueuesWithSelectors.json
@@ -34,7 +34,8 @@
{
"_name": "Producer1",
"_destinationName": "direct://amq.direct//queue-selectors-durable?durable='true'",
- "_numberOfMessages": 100000,
+ "_maximumDuration": 60000,
+ "_interval": 1000,
"_deliveryMode": 2,
"_messageSize": 1024,
"_messageProviderName": "messageProvider"
@@ -59,7 +60,8 @@
{
"_name": "Consumer1",
"_destinationName": "direct://amq.direct//queue-selectors-durable?durable='true'",
- "_numberOfMessages": 100000,
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true,
"_selector": "id=1"
}
]
@@ -108,7 +110,8 @@
{
"_name": "Producer1",
"_destinationName": "direct://amq.direct//queue-selectors-durable?durable='true'",
- "_numberOfMessages": 200000,
+ "_maximumDuration": 60000,
+ "_interval": 1000,
"_deliveryMode": 2,
"_messageSize": 1024,
"_messageProviderName": "messageProvider"
@@ -133,7 +136,8 @@
{
"_name": "Consumer1",
"_destinationName": "direct://amq.direct//queue-selectors-durable?durable='true'",
- "_numberOfMessages": 100000,
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true,
"_selector": "id=1"
}
]
@@ -151,7 +155,8 @@
{
"_name": "Consumer2",
"_destinationName": "direct://amq.direct//queue-selectors-durable?durable='true'",
- "_numberOfMessages": 100000,
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true,
"_selector": "id=2"
}
]
@@ -200,7 +205,8 @@
{
"_name": "Producer1",
"_destinationName": "direct://amq.direct//queue-selectors-durable?durable='true'",
- "_numberOfMessages": 500000,
+ "_maximumDuration": 60000,
+ "_interval": 1000,
"_deliveryMode": 2,
"_messageSize": 1024,
"_messageProviderName": "messageProvider"
@@ -225,7 +231,8 @@
{
"_name": "Consumer1",
"_destinationName": "direct://amq.direct//queue-selectors-durable?durable='true'",
- "_numberOfMessages": 100000,
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true,
"_selector": "id=1"
}
]
@@ -243,7 +250,8 @@
{
"_name": "Consumer2",
"_destinationName": "direct://amq.direct//queue-selectors-durable?durable='true'",
- "_numberOfMessages": 100000,
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true,
"_selector": "id=2"
}
]
@@ -261,7 +269,8 @@
{
"_name": "Consumer3",
"_destinationName": "direct://amq.direct//queue-selectors-durable?durable='true'",
- "_numberOfMessages": 100000,
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true,
"_selector": "id=3"
}
]
@@ -279,7 +288,8 @@
{
"_name": "Consumer4",
"_destinationName": "direct://amq.direct//queue-selectors-durable?durable='true'",
- "_numberOfMessages": 100000,
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true,
"_selector": "id=4"
}
]
@@ -297,7 +307,8 @@
{
"_name": "Consumer5",
"_destinationName": "direct://amq.direct//queue-selectors-durable?durable='true'",
- "_numberOfMessages": 100000,
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true,
"_selector": "id=5"
}
]
@@ -345,7 +356,8 @@
{
"_name": "Producer1",
"_destinationName": "direct://amq.direct//queue-selectors-durable?durable='true'",
- "_numberOfMessages": 1000000,
+ "_maximumDuration": 60000,
+ "_interval": 1000,
"_deliveryMode": 2,
"_messageSize": 1024,
"_messageProviderName": "messageProvider"
@@ -370,7 +382,8 @@
{
"_name": "Consumer1",
"_destinationName": "direct://amq.direct//queue-selectors-durable?durable='true'",
- "_numberOfMessages": 100000,
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true,
"_selector": "id=1"
}
]
@@ -388,7 +401,8 @@
{
"_name": "Consumer2",
"_destinationName": "direct://amq.direct//queue-selectors-durable?durable='true'",
- "_numberOfMessages": 100000,
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true,
"_selector": "id=2"
}
]
@@ -406,7 +420,8 @@
{
"_name": "Consumer3",
"_destinationName": "direct://amq.direct//queue-selectors-durable?durable='true'",
- "_numberOfMessages": 100000,
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true,
"_selector": "id=3"
}
]
@@ -424,7 +439,8 @@
{
"_name": "Consumer4",
"_destinationName": "direct://amq.direct//queue-selectors-durable?durable='true'",
- "_numberOfMessages": 100000,
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true,
"_selector": "id=4"
}
]
@@ -442,7 +458,8 @@
{
"_name": "Consumer5",
"_destinationName": "direct://amq.direct//queue-selectors-durable?durable='true'",
- "_numberOfMessages": 100000,
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true,
"_selector": "id=5"
}
]
@@ -460,7 +477,8 @@
{
"_name": "Consumer6",
"_destinationName": "direct://amq.direct//queue-selectors-durable?durable='true'",
- "_numberOfMessages": 100000,
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true,
"_selector": "id=6"
}
]
@@ -478,7 +496,8 @@
{
"_name": "Consumer7",
"_destinationName": "direct://amq.direct//queue-selectors-durable?durable='true'",
- "_numberOfMessages": 100000,
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true,
"_selector": "id=7"
}
]
@@ -496,7 +515,8 @@
{
"_name": "Consumer8",
"_destinationName": "direct://amq.direct//queue-selectors-durable?durable='true'",
- "_numberOfMessages": 100000,
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true,
"_selector": "id=8"
}
]
@@ -514,7 +534,8 @@
{
"_name": "Consumer9",
"_destinationName": "direct://amq.direct//queue-selectors-durable?durable='true'",
- "_numberOfMessages": 100000,
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true,
"_selector": "id=9"
}
]
@@ -532,7 +553,8 @@
{
"_name": "Consumer10",
"_destinationName": "direct://amq.direct//queue-selectors-durable?durable='true'",
- "_numberOfMessages": 100000,
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true,
"_selector": "id=10"
}
]
@@ -581,7 +603,8 @@
{
"_name": "Producer1",
"_destinationName": "direct://amq.direct//queue-selectors-durable-overlapping?durable='true'",
- "_numberOfMessages": 100000,
+ "_maximumDuration": 60000,
+ "_interval": 1000,
"_deliveryMode": 2,
"_messageSize": 1024,
"_messageProviderName": "messageProvider"
@@ -606,7 +629,8 @@
{
"_name": "Consumer1",
"_destinationName": "direct://amq.direct//queue-selectors-durable-overlapping?durable='true'",
- "_numberOfMessages": 25000,
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true,
"_selector": "id =1 or id= 2 or id= 3"
}
]
@@ -624,7 +648,8 @@
{
"_name": "Consumer2",
"_destinationName": "direct://amq.direct//queue-selectors-durable-overlapping?durable='true'",
- "_numberOfMessages": 25000,
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true,
"_selector": "id =2 or id= 3 or id= 4"
}
]
@@ -674,7 +699,8 @@
{
"_name": "Producer1",
"_destinationName": "direct://amq.direct//queue-selectors-durable-overlapping?durable='true'",
- "_numberOfMessages": 500000,
+ "_maximumDuration": 60000,
+ "_interval": 1000,
"_deliveryMode": 2,
"_messageSize": 1024,
"_messageProviderName": "messageProvider"
@@ -699,7 +725,8 @@
{
"_name": "Consumer1",
"_destinationName": "direct://amq.direct//queue-selectors-durable-overlapping?durable='true'",
- "_numberOfMessages": 50000,
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true,
"_selector": "id =1 or id=2 or id= 10"
}
]
@@ -717,7 +744,8 @@
{
"_name": "Consumer2",
"_destinationName": "direct://amq.direct//queue-selectors-durable-overlapping?durable='true'",
- "_numberOfMessages": 50000,
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true,
"_selector": "id =2 or id=3 or id= 4"
}
]
@@ -735,7 +763,8 @@
{
"_name": "Consumer3",
"_destinationName": "direct://amq.direct//queue-selectors-durable-overlapping?durable='true'",
- "_numberOfMessages": 50000,
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true,
"_selector": "id =4 or id= 5 or id= 6"
}
]
@@ -753,7 +782,8 @@
{
"_name": "Consumer4",
"_destinationName": "direct://amq.direct//queue-selectors-durable-overlapping?durable='true'",
- "_numberOfMessages": 50000,
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true,
"_selector": "id =6 or id= 7 or id =8"
}
]
@@ -771,7 +801,8 @@
{
"_name": "Consumer5",
"_destinationName": "direct://amq.direct//queue-selectors-durable-overlapping?durable='true'",
- "_numberOfMessages": 50000,
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true,
"_selector": "id =8 or id =9 or id =10"
}
]
@@ -819,7 +850,8 @@
{
"_name": "Producer1",
"_destinationName": "direct://amq.direct//queue-selectors-durable-overlapping?durable='true'",
- "_numberOfMessages": 500000,
+ "_maximumDuration": 60000,
+ "_interval": 1000,
"_deliveryMode": 2,
"_messageSize": 1024,
"_messageProviderName": "messageProvider"
@@ -844,7 +876,8 @@
{
"_name": "Consumer1",
"_destinationName": "direct://amq.direct//queue-selectors-durable-overlapping?durable='true'",
- "_numberOfMessages": 25000,
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true,
"_selector": "id =1 or id =2 or id =3"
}
]
@@ -862,7 +895,8 @@
{
"_name": "Consumer2",
"_destinationName": "direct://amq.direct//queue-selectors-durable-overlapping?durable='true'",
- "_numberOfMessages": 25000,
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true,
"_selector": "id =2 or id =3 or id= 4"
}
]
@@ -880,7 +914,8 @@
{
"_name": "Consumer3",
"_destinationName": "direct://amq.direct//queue-selectors-durable-overlapping?durable='true'",
- "_numberOfMessages": 25000,
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true,
"_selector": "id =5 or id=6 or id =7"
}
]
@@ -898,7 +933,8 @@
{
"_name": "Consumer4",
"_destinationName": "direct://amq.direct//queue-selectors-durable-overlapping?durable='true'",
- "_numberOfMessages": 25000,
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true,
"_selector": "id =6 or id =7 or id =8"
}
]
@@ -916,7 +952,8 @@
{
"_name": "Consumer5",
"_destinationName": "direct://amq.direct//queue-selectors-durable-overlapping?durable='true'",
- "_numberOfMessages": 25000,
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true,
"_selector": "id =9 or id = 10 or id = 11"
}
]
@@ -934,7 +971,8 @@
{
"_name": "Consumer6",
"_destinationName": "direct://amq.direct//queue-selectors-durable-overlapping?durable='true'",
- "_numberOfMessages": 25000,
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true,
"_selector": "id =10 or id = 11 or id =12"
}
]
@@ -952,7 +990,8 @@
{
"_name": "Consumer7",
"_destinationName": "direct://amq.direct//queue-selectors-durable-overlapping?durable='true'",
- "_numberOfMessages": 25000,
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true,
"_selector": "id = 13 or id = 14 or id =15"
}
]
@@ -970,7 +1009,8 @@
{
"_name": "Consumer8",
"_destinationName": "direct://amq.direct//queue-selectors-durable-overlapping?durable='true'",
- "_numberOfMessages": 25000,
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true,
"_selector": "id = 14 or id =15 or id =16"
}
]
@@ -988,7 +1028,8 @@
{
"_name": "Consumer9",
"_destinationName": "direct://amq.direct//queue-selectors-durable-overlapping?durable='true'",
- "_numberOfMessages": 25000,
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true,
"_selector": "id =17 or id =18 or id= 19"
}
]
@@ -1006,7 +1047,8 @@
{
"_name": "Consumer10",
"_destinationName": "direct://amq.direct//queue-selectors-durable-overlapping?durable='true'",
- "_numberOfMessages": 25000,
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true,
"_selector": "id = 18 or id = 19 or id =20"
}
]
@@ -1052,7 +1094,8 @@
{
"_name": "Producer1",
"_destinationName": "direct://amq.direct//queue-selectors",
- "_numberOfMessages": 100000,
+ "_maximumDuration": 60000,
+ "_interval": 1000,
"_deliveryMode": 1,
"_messageSize": 1024,
"_messageProviderName": "messageProvider"
@@ -1077,7 +1120,8 @@
{
"_name": "Consumer1",
"_destinationName": "direct://amq.direct//queue-selectors",
- "_numberOfMessages": 100000,
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true,
"_selector": "id=1"
}
]
@@ -1125,7 +1169,8 @@
{
"_name": "Producer1",
"_destinationName": "direct://amq.direct//queue-selectors",
- "_numberOfMessages": 200000,
+ "_maximumDuration": 60000,
+ "_interval": 1000,
"_deliveryMode": 1,
"_messageSize": 1024,
"_messageProviderName": "messageProvider"
@@ -1150,7 +1195,8 @@
{
"_name": "Consumer1",
"_destinationName": "direct://amq.direct//queue-selectors",
- "_numberOfMessages": 100000,
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true,
"_selector": "id=1"
}
]
@@ -1168,7 +1214,8 @@
{
"_name": "Consumer2",
"_destinationName": "direct://amq.direct//queue-selectors",
- "_numberOfMessages": 100000,
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true,
"_selector": "id=2"
}
]
@@ -1217,7 +1264,8 @@
{
"_name": "Producer1",
"_destinationName": "direct://amq.direct//queue-selectors",
- "_numberOfMessages": 500000,
+ "_maximumDuration": 60000,
+ "_interval": 1000,
"_deliveryMode": 1,
"_messageSize": 1024,
"_messageProviderName": "messageProvider"
@@ -1242,7 +1290,8 @@
{
"_name": "Consumer1",
"_destinationName": "direct://amq.direct//queue-selectors",
- "_numberOfMessages": 100000,
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true,
"_selector": "id=1"
}
]
@@ -1260,7 +1309,8 @@
{
"_name": "Consumer2",
"_destinationName": "direct://amq.direct//queue-selectors",
- "_numberOfMessages": 100000,
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true,
"_selector": "id=2"
}
]
@@ -1278,7 +1328,8 @@
{
"_name": "Consumer3",
"_destinationName": "direct://amq.direct//queue-selectors",
- "_numberOfMessages": 100000,
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true,
"_selector": "id=3"
}
]
@@ -1296,7 +1347,8 @@
{
"_name": "Consumer4",
"_destinationName": "direct://amq.direct//queue-selectors",
- "_numberOfMessages": 100000,
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true,
"_selector": "id=4"
}
]
@@ -1314,7 +1366,8 @@
{
"_name": "Consumer5",
"_destinationName": "direct://amq.direct//queue-selectors",
- "_numberOfMessages": 100000,
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true,
"_selector": "id=5"
}
]
@@ -1361,7 +1414,8 @@
{
"_name": "Producer1",
"_destinationName": "direct://amq.direct//queue-selectors",
- "_numberOfMessages": 1000000,
+ "_maximumDuration": 60000,
+ "_interval": 1000,
"_deliveryMode": 1,
"_messageSize": 1024,
"_messageProviderName": "messageProvider"
@@ -1386,7 +1440,8 @@
{
"_name": "Consumer1",
"_destinationName": "direct://amq.direct//queue-selectors",
- "_numberOfMessages": 100000,
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true,
"_selector": "id=1"
}
]
@@ -1404,7 +1459,8 @@
{
"_name": "Consumer2",
"_destinationName": "direct://amq.direct//queue-selectors",
- "_numberOfMessages": 100000,
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true,
"_selector": "id=2"
}
]
@@ -1422,7 +1478,8 @@
{
"_name": "Consumer3",
"_destinationName": "direct://amq.direct//queue-selectors",
- "_numberOfMessages": 100000,
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true,
"_selector": "id=3"
}
]
@@ -1440,7 +1497,8 @@
{
"_name": "Consumer4",
"_destinationName": "direct://amq.direct//queue-selectors",
- "_numberOfMessages": 100000,
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true,
"_selector": "id=4"
}
]
@@ -1458,7 +1516,8 @@
{
"_name": "Consumer5",
"_destinationName": "direct://amq.direct//queue-selectors",
- "_numberOfMessages": 100000,
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true,
"_selector": "id=5"
}
]
@@ -1476,7 +1535,8 @@
{
"_name": "Consumer6",
"_destinationName": "direct://amq.direct//queue-selectors",
- "_numberOfMessages": 100000,
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true,
"_selector": "id=6"
}
]
@@ -1494,7 +1554,8 @@
{
"_name": "Consumer7",
"_destinationName": "direct://amq.direct//queue-selectors",
- "_numberOfMessages": 100000,
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true,
"_selector": "id=7"
}
]
@@ -1512,7 +1573,8 @@
{
"_name": "Consumer8",
"_destinationName": "direct://amq.direct//queue-selectors",
- "_numberOfMessages": 100000,
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true,
"_selector": "id=8"
}
]
@@ -1530,7 +1592,8 @@
{
"_name": "Consumer9",
"_destinationName": "direct://amq.direct//queue-selectors",
- "_numberOfMessages": 100000,
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true,
"_selector": "id=9"
}
]
@@ -1548,7 +1611,8 @@
{
"_name": "Consumer10",
"_destinationName": "direct://amq.direct//queue-selectors",
- "_numberOfMessages": 100000,
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true,
"_selector": "id=10"
}
]
@@ -1565,7 +1629,7 @@
{
- "_name": "Queues with selectors: 2 consumers - 1 producer - overlapping selectors 50% - NON_PERSISTENT",
+ "_name": "Queues with selectors: 2 consumers - 1 producer - overlapping 50% - NON_PERSISTENT",
"_queues":[
{
"_name": "direct://amq.direct//queue-selectors-overlapping",
@@ -1597,7 +1661,8 @@
{
"_name": "Producer1",
"_destinationName": "direct://amq.direct//queue-selectors-overlapping",
- "_numberOfMessages": 200000,
+ "_maximumDuration": 60000,
+ "_interval": 1000,
"_deliveryMode": 1,
"_messageSize": 1024,
"_messageProviderName": "messageProvider"
@@ -1622,7 +1687,8 @@
{
"_name": "Consumer1",
"_destinationName": "direct://amq.direct//queue-selectors-overlapping",
- "_numberOfMessages": 25000,
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true,
"_selector": "id =1 or id= 2 or id= 3"
}
]
@@ -1640,7 +1706,8 @@
{
"_name": "Consumer2",
"_destinationName": "direct://amq.direct//queue-selectors-overlapping",
- "_numberOfMessages": 25000,
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true,
"_selector": "id =2 or id= 3 or id= 4"
}
]
@@ -1657,7 +1724,7 @@
{
- "_name": "Queues with selectors: 5 consumers - 1 producer - overlapping selectors 50% - NON_PERSISTENT",
+ "_name": "Queues with selectors: 5 consumers - 1 producer - overlapping 50% - NON_PERSISTENT",
"_queues":[
{
"_name": "direct://amq.direct//queue-selectors-overlapping",
@@ -1689,7 +1756,8 @@
{
"_name": "Producer1",
"_destinationName": "direct://amq.direct//queue-selectors-overlapping",
- "_numberOfMessages": 500000,
+ "_maximumDuration": 60000,
+ "_interval": 1000,
"_deliveryMode": 1,
"_messageSize": 1024,
"_messageProviderName": "messageProvider"
@@ -1714,7 +1782,8 @@
{
"_name": "Consumer1",
"_destinationName": "direct://amq.direct//queue-selectors-overlapping",
- "_numberOfMessages": 50000,
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true,
"_selector": "id =1 or id=2 or id= 10"
}
]
@@ -1732,7 +1801,8 @@
{
"_name": "Consumer2",
"_destinationName": "direct://amq.direct//queue-selectors-overlapping",
- "_numberOfMessages": 50000,
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true,
"_selector": "id =2 or id=3 or id= 4"
}
]
@@ -1750,7 +1820,8 @@
{
"_name": "Consumer3",
"_destinationName": "direct://amq.direct//queue-selectors-overlapping",
- "_numberOfMessages": 50000,
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true,
"_selector": "id =4 or id= 5 or id= 6"
}
]
@@ -1768,7 +1839,8 @@
{
"_name": "Consumer4",
"_destinationName": "direct://amq.direct//queue-selectors-overlapping",
- "_numberOfMessages": 50000,
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true,
"_selector": "id =6 or id= 7 or id =8"
}
]
@@ -1786,7 +1858,8 @@
{
"_name": "Consumer5",
"_destinationName": "direct://amq.direct//queue-selectors-overlapping",
- "_numberOfMessages": 50000,
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true,
"_selector": "id =8 or id =9 or id =10"
}
]
@@ -1801,7 +1874,7 @@
{
- "_name": "Queues with selectors: 10 consumers - 1 producer - overlapping selectors 50% - NON_PERSISTENT",
+ "_name": "Queues with selectors: 10 consumers - 1 producer - overlapping 50% - NON_PERSISTENT",
"_queues":[
{
"_name": "direct://amq.direct//queue-selectors-overlapping",
@@ -1833,7 +1906,8 @@
{
"_name": "Producer1",
"_destinationName": "direct://amq.direct//queue-selectors-overlapping",
- "_numberOfMessages": 500000,
+ "_maximumDuration": 60000,
+ "_interval": 1000,
"_deliveryMode": 1,
"_messageSize": 1024,
"_messageProviderName": "messageProvider"
@@ -1858,7 +1932,8 @@
{
"_name": "Consumer1",
"_destinationName": "direct://amq.direct//queue-selectors-overlapping",
- "_numberOfMessages": 25000,
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true,
"_selector": "id =1 or id =2 or id =3"
}
]
@@ -1876,7 +1951,8 @@
{
"_name": "Consumer2",
"_destinationName": "direct://amq.direct//queue-selectors-overlapping",
- "_numberOfMessages": 25000,
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true,
"_selector": "id =2 or id =3 or id= 4"
}
]
@@ -1894,7 +1970,8 @@
{
"_name": "Consumer3",
"_destinationName": "direct://amq.direct//queue-selectors-overlapping",
- "_numberOfMessages": 25000,
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true,
"_selector": "id =5 or id=6 or id =7"
}
]
@@ -1912,7 +1989,8 @@
{
"_name": "Consumer4",
"_destinationName": "direct://amq.direct//queue-selectors-overlapping",
- "_numberOfMessages": 25000,
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true,
"_selector": "id =6 or id =7 or id =8"
}
]
@@ -1930,7 +2008,8 @@
{
"_name": "Consumer5",
"_destinationName": "direct://amq.direct//queue-selectors-overlapping",
- "_numberOfMessages": 25000,
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true,
"_selector": "id =9 or id = 10 or id = 11"
}
@@ -1949,7 +2028,8 @@
{
"_name": "Consumer6",
"_destinationName": "direct://amq.direct//queue-selectors-overlapping",
- "_numberOfMessages": 25000,
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true,
"_selector": "id =10 or id = 11 or id =12"
}
]
@@ -1967,7 +2047,8 @@
{
"_name": "Consumer7",
"_destinationName": "direct://amq.direct//queue-selectors-overlapping",
- "_numberOfMessages": 25000,
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true,
"_selector": "id = 13 or id = 14 or id =15"
}
]
@@ -1985,7 +2066,8 @@
{
"_name": "Consumer8",
"_destinationName": "direct://amq.direct//queue-selectors-overlapping",
- "_numberOfMessages": 25000,
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true,
"_selector": "id = 14 or id =15 or id =16"
}
]
@@ -2003,7 +2085,8 @@
{
"_name": "Consumer9",
"_destinationName": "direct://amq.direct//queue-selectors-overlapping",
- "_numberOfMessages": 25000,
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true,
"_selector": "id =17 or id =18 or id= 19"
}
]
@@ -2021,7 +2104,8 @@
{
"_name": "Consumer10",
"_destinationName": "direct://amq.direct//queue-selectors-overlapping",
- "_numberOfMessages": 25000,
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true,
"_selector": "id = 18 or id = 19 or id =20"
}
]
diff --git a/java/perftests/etc/testdefs/standard/VaryingNumberOfParticipants.json b/java/perftests/etc/testdefs/Latency-VaryingNumberOfParticipants.json
index 6cf67cbbf0..c147866591 100644
--- a/java/perftests/etc/testdefs/standard/VaryingNumberOfParticipants.json
+++ b/java/perftests/etc/testdefs/Latency-VaryingNumberOfParticipants.json
@@ -4,7 +4,7 @@
"_name": "Varying number of participants: 1 consumer - 1 producer - PERSISTENT",
"_queues":[
{
- "_name": "direct://amq.direct//varying-consumers?durable='true'",
+ "_name": "direct://amq.direct//latency-varying-consumers?durable='true'",
"_durable": true
}
],
@@ -22,10 +22,11 @@
"_producers": [
{
"_name": "Producer1",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000,
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
"_deliveryMode": 2,
- "_messageSize": 1024
+ "_messageSize": 1024,
+ "_maximumDuration": 60000,
+ "_interval": 1000
}
]
}
@@ -46,8 +47,9 @@
"_consumers": [
{
"_name": "Consumer1",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true
}
]
}
@@ -61,7 +63,7 @@
"_name": "Varying number of participants: 2 consumers - 1 producer - PERSISTENT",
"_queues":[
{
- "_name": "direct://amq.direct//varying-consumers?durable='true'",
+ "_name": "direct://amq.direct//latency-varying-consumers?durable='true'",
"_durable": true
}
],
@@ -79,10 +81,11 @@
"_producers": [
{
"_name": "Producer1",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000,
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
"_deliveryMode": 2,
- "_messageSize": 1024
+ "_messageSize": 1024,
+ "_interval": 1000
}
]
}
@@ -103,8 +106,9 @@
"_consumers": [
{
"_name": "Consumer1",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true
}
]
}
@@ -120,8 +124,9 @@
"_consumers": [
{
"_name": "Consumer2",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true
}
]
}
@@ -135,7 +140,7 @@
"_name": "Varying number of participants: 5 consumers - 1 producer - PERSISTENT",
"_queues":[
{
- "_name": "direct://amq.direct//varying-consumers?durable='true'",
+ "_name": "direct://amq.direct//latency-varying-consumers?durable='true'",
"_durable": true
}
],
@@ -153,8 +158,9 @@
"_producers": [
{
"_name": "Producer1",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000,
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_interval": 1000,
"_deliveryMode": 2,
"_messageSize": 1024
}
@@ -177,8 +183,9 @@
"_consumers": [
{
"_name": "Consumer1",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true
}
]
}
@@ -194,8 +201,9 @@
"_consumers": [
{
"_name": "Consumer2",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true
}
]
}
@@ -211,8 +219,9 @@
"_consumers": [
{
"_name": "Consumer3",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true
}
]
}
@@ -228,8 +237,9 @@
"_consumers": [
{
"_name": "Consumer4",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true
}
]
}
@@ -245,8 +255,9 @@
"_consumers": [
{
"_name": "Consumer5",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true
}
]
}
@@ -263,7 +274,7 @@
"_name": "Varying number of participants: 10 consumers - 1 producer - PERSISTENT",
"_queues":[
{
- "_name": "direct://amq.direct//varying-consumers?durable='true'",
+ "_name": "direct://amq.direct//latency-varying-consumers?durable='true'",
"_durable": true
}
],
@@ -281,8 +292,9 @@
"_producers": [
{
"_name": "Producer1",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000,
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_interval": 1000,
"_deliveryMode": 2,
"_messageSize": 1024
}
@@ -305,8 +317,9 @@
"_consumers": [
{
"_name": "Consumer1",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true
}
]
}
@@ -322,8 +335,9 @@
"_consumers": [
{
"_name": "Consumer2",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true
}
]
}
@@ -339,8 +353,9 @@
"_consumers": [
{
"_name": "Consumer3",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true
}
]
}
@@ -356,8 +371,9 @@
"_consumers": [
{
"_name": "Consumer4",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true
}
]
}
@@ -373,8 +389,9 @@
"_consumers": [
{
"_name": "Consumer5",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true
}
]
}
@@ -390,8 +407,9 @@
"_consumers": [
{
"_name": "Consumer6",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true
}
]
}
@@ -407,8 +425,9 @@
"_consumers": [
{
"_name": "Consumer7",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true
}
]
}
@@ -424,8 +443,9 @@
"_consumers": [
{
"_name": "Consumer8",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true
}
]
}
@@ -441,8 +461,9 @@
"_consumers": [
{
"_name": "Consumer9",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true
}
]
}
@@ -458,8 +479,9 @@
"_consumers": [
{
"_name": "Consumer10",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true
}
]
}
@@ -476,7 +498,7 @@
"_name": "Varying number of participants: 1 consumer - 2 producers - PERSISTENT",
"_queues":[
{
- "_name": "direct://amq.direct//varying-consumers?durable='true'",
+ "_name": "direct://amq.direct//latency-varying-consumers?durable='true'",
"_durable": true
}
],
@@ -494,8 +516,9 @@
"_producers": [
{
"_name": "Producer1",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000,
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_interval": 1500,
"_deliveryMode": 2,
"_messageSize": 1024
}
@@ -513,8 +536,9 @@
"_producers": [
{
"_name": "Producer2",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000,
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_interval": 1500,
"_deliveryMode": 2,
"_messageSize": 1024
}
@@ -537,8 +561,9 @@
"_consumers": [
{
"_name": "Consumer1",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true
}
]
}
@@ -556,7 +581,7 @@
"_name": "Varying number of participants: 2 consumers - 2 producers - PERSISTENT",
"_queues":[
{
- "_name": "direct://amq.direct//varying-consumers?durable='true'",
+ "_name": "direct://amq.direct//latency-varying-consumers?durable='true'",
"_durable": true
}
],
@@ -574,8 +599,9 @@
"_producers": [
{
"_name": "Producer1",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000,
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_interval": 1500,
"_deliveryMode": 2,
"_messageSize": 1024
}
@@ -593,8 +619,9 @@
"_producers": [
{
"_name": "Producer2",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000,
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_interval": 1500,
"_deliveryMode": 2,
"_messageSize": 1024
}
@@ -617,8 +644,9 @@
"_consumers": [
{
"_name": "Consumer1",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true
}
]
}
@@ -634,8 +662,9 @@
"_consumers": [
{
"_name": "Consumer2",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true
}
]
}
@@ -653,7 +682,7 @@
"_name": "Varying number of participants: 5 consumers - 2 producers - PERSISTENT",
"_queues":[
{
- "_name": "direct://amq.direct//varying-consumers?durable='true'",
+ "_name": "direct://amq.direct//latency-varying-consumers?durable='true'",
"_durable": true
}
],
@@ -671,8 +700,9 @@
"_producers": [
{
"_name": "Producer1",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000,
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_interval": 1500,
"_deliveryMode": 2,
"_messageSize": 1024
}
@@ -690,8 +720,9 @@
"_producers": [
{
"_name": "Producer2",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000,
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_interval": 1500,
"_deliveryMode": 2,
"_messageSize": 1024
}
@@ -714,8 +745,9 @@
"_consumers": [
{
"_name": "Consumer1",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true
}
]
}
@@ -731,8 +763,9 @@
"_consumers": [
{
"_name": "Consumer2",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true
}
]
}
@@ -748,8 +781,9 @@
"_consumers": [
{
"_name": "Consumer3",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true
}
]
}
@@ -765,8 +799,9 @@
"_consumers": [
{
"_name": "Consumer4",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true
}
]
}
@@ -782,8 +817,9 @@
"_consumers": [
{
"_name": "Consumer5",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true
}
]
}
@@ -800,7 +836,7 @@
"_name": "Varying number of participants: 10 consumers - 2 producers - PERSISTENT",
"_queues":[
{
- "_name": "direct://amq.direct//varying-consumers?durable='true'",
+ "_name": "direct://amq.direct//latency-varying-consumers?durable='true'",
"_durable": true
}
],
@@ -818,8 +854,9 @@
"_producers": [
{
"_name": "Producer1",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000,
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_interval": 1500,
"_deliveryMode": 2,
"_messageSize": 1024
}
@@ -837,8 +874,9 @@
"_producers": [
{
"_name": "Producer2",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000,
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_interval": 1500,
"_deliveryMode": 2,
"_messageSize": 1024
}
@@ -861,8 +899,9 @@
"_consumers": [
{
"_name": "Consumer1",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true
}
]
}
@@ -878,8 +917,9 @@
"_consumers": [
{
"_name": "Consumer2",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true
}
]
}
@@ -895,8 +935,9 @@
"_consumers": [
{
"_name": "Consumer3",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true
}
]
}
@@ -912,8 +953,9 @@
"_consumers": [
{
"_name": "Consumer4",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true
}
]
}
@@ -929,8 +971,9 @@
"_consumers": [
{
"_name": "Consumer5",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true
}
]
}
@@ -946,8 +989,9 @@
"_consumers": [
{
"_name": "Consumer6",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true
}
]
}
@@ -963,8 +1007,9 @@
"_consumers": [
{
"_name": "Consumer7",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true
}
]
}
@@ -980,8 +1025,9 @@
"_consumers": [
{
"_name": "Consumer8",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true
}
]
}
@@ -997,8 +1043,9 @@
"_consumers": [
{
"_name": "Consumer9",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true
}
]
}
@@ -1014,8 +1061,9 @@
"_consumers": [
{
"_name": "Consumer10",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true
}
]
}
@@ -1032,7 +1080,7 @@
"_name": "Varying number of participants: 1 consumer - 5 producers - PERSISTENT",
"_queues":[
{
- "_name": "direct://amq.direct//varying-consumers?durable='true'",
+ "_name": "direct://amq.direct//latency-varying-consumers?durable='true'",
"_durable": true
}
],
@@ -1050,8 +1098,9 @@
"_producers": [
{
"_name": "Producer1",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000,
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_interval": 2000,
"_deliveryMode": 2,
"_messageSize": 1024
}
@@ -1069,8 +1118,9 @@
"_producers": [
{
"_name": "Producer2",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000,
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_interval": 2000,
"_deliveryMode": 2,
"_messageSize": 1024
}
@@ -1088,8 +1138,9 @@
"_producers": [
{
"_name": "Producer3",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000,
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_interval": 2000,
"_deliveryMode": 2,
"_messageSize": 1024
}
@@ -1107,8 +1158,9 @@
"_producers": [
{
"_name": "Producer4",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000,
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_interval": 2000,
"_deliveryMode": 2,
"_messageSize": 1024
}
@@ -1126,8 +1178,9 @@
"_producers": [
{
"_name": "Producer5",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000,
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_interval": 2000,
"_deliveryMode": 2,
"_messageSize": 1024
}
@@ -1150,8 +1203,9 @@
"_consumers": [
{
"_name": "Consumer1",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true
}
]
}
@@ -1169,7 +1223,7 @@
"_name": "Varying number of participants: 2 consumers - 5 producers - PERSISTENT",
"_queues":[
{
- "_name": "direct://amq.direct//varying-consumers?durable='true'",
+ "_name": "direct://amq.direct//latency-varying-consumers?durable='true'",
"_durable": true
}
],
@@ -1187,8 +1241,9 @@
"_producers": [
{
"_name": "Producer1",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000,
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_interval": 2000,
"_deliveryMode": 2,
"_messageSize": 1024
}
@@ -1206,8 +1261,9 @@
"_producers": [
{
"_name": "Producer2",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000,
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_interval": 2000,
"_deliveryMode": 2,
"_messageSize": 1024
}
@@ -1225,8 +1281,9 @@
"_producers": [
{
"_name": "Producer3",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000,
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_interval": 2000,
"_deliveryMode": 2,
"_messageSize": 1024
}
@@ -1244,8 +1301,9 @@
"_producers": [
{
"_name": "Producer4",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000,
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_interval": 2000,
"_deliveryMode": 2,
"_messageSize": 1024
}
@@ -1263,8 +1321,9 @@
"_producers": [
{
"_name": "Producer5",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000,
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_interval": 2000,
"_deliveryMode": 2,
"_messageSize": 1024
}
@@ -1287,8 +1346,9 @@
"_consumers": [
{
"_name": "Consumer1",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true
}
]
}
@@ -1304,8 +1364,9 @@
"_consumers": [
{
"_name": "Consumer2",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true
}
]
}
@@ -1324,7 +1385,7 @@
"_name": "Varying number of participants: 5 consumers - 5 producers - PERSISTENT",
"_queues":[
{
- "_name": "direct://amq.direct//varying-consumers?durable='true'",
+ "_name": "direct://amq.direct//latency-varying-consumers?durable='true'",
"_durable": true
}
],
@@ -1342,8 +1403,9 @@
"_producers": [
{
"_name": "Producer1",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000,
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_interval": 2000,
"_deliveryMode": 2,
"_messageSize": 1024
}
@@ -1361,8 +1423,9 @@
"_producers": [
{
"_name": "Producer2",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000,
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_interval": 2000,
"_deliveryMode": 2,
"_messageSize": 1024
}
@@ -1380,8 +1443,9 @@
"_producers": [
{
"_name": "Producer3",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000,
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_interval": 2000,
"_deliveryMode": 2,
"_messageSize": 1024
}
@@ -1399,8 +1463,9 @@
"_producers": [
{
"_name": "Producer4",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000,
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_interval": 2000,
"_deliveryMode": 2,
"_messageSize": 1024
}
@@ -1418,8 +1483,9 @@
"_producers": [
{
"_name": "Producer5",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000,
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_interval": 2000,
"_deliveryMode": 2,
"_messageSize": 1024
}
@@ -1442,8 +1508,9 @@
"_consumers": [
{
"_name": "Consumer1",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true
}
]
}
@@ -1459,8 +1526,9 @@
"_consumers": [
{
"_name": "Consumer2",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true
}
]
}
@@ -1476,8 +1544,9 @@
"_consumers": [
{
"_name": "Consumer3",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true
}
]
}
@@ -1493,8 +1562,9 @@
"_consumers": [
{
"_name": "Consumer4",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true
}
]
}
@@ -1510,8 +1580,9 @@
"_consumers": [
{
"_name": "Consumer5",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true
}
]
}
@@ -1528,7 +1599,7 @@
"_name": "Varying number of participants: 10 consumers - 5 producers - PERSISTENT",
"_queues":[
{
- "_name": "direct://amq.direct//varying-consumers?durable='true'",
+ "_name": "direct://amq.direct//latency-varying-consumers?durable='true'",
"_durable": true
}
],
@@ -1546,8 +1617,9 @@
"_producers": [
{
"_name": "Producer1",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000,
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_interval": 2000,
"_deliveryMode": 2,
"_messageSize": 1024
}
@@ -1565,8 +1637,9 @@
"_producers": [
{
"_name": "Producer2",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000,
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_interval": 2000,
"_deliveryMode": 2,
"_messageSize": 1024
}
@@ -1584,8 +1657,9 @@
"_producers": [
{
"_name": "Producer3",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000,
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_interval": 2000,
"_deliveryMode": 2,
"_messageSize": 1024
}
@@ -1603,8 +1677,9 @@
"_producers": [
{
"_name": "Producer4",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000,
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_interval": 2000,
"_deliveryMode": 2,
"_messageSize": 1024
}
@@ -1622,8 +1697,9 @@
"_producers": [
{
"_name": "Producer5",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000,
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_interval": 2000,
"_deliveryMode": 2,
"_messageSize": 1024
}
@@ -1646,8 +1722,9 @@
"_consumers": [
{
"_name": "Consumer1",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true
}
]
}
@@ -1663,8 +1740,9 @@
"_consumers": [
{
"_name": "Consumer2",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true
}
]
}
@@ -1680,8 +1758,9 @@
"_consumers": [
{
"_name": "Consumer3",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true
}
]
}
@@ -1697,8 +1776,9 @@
"_consumers": [
{
"_name": "Consumer4",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true
}
]
}
@@ -1714,8 +1794,9 @@
"_consumers": [
{
"_name": "Consumer5",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true
}
]
}
@@ -1731,8 +1812,9 @@
"_consumers": [
{
"_name": "Consumer6",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true
}
]
}
@@ -1748,8 +1830,9 @@
"_consumers": [
{
"_name": "Consumer7",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true
}
]
}
@@ -1765,8 +1848,9 @@
"_consumers": [
{
"_name": "Consumer8",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true
}
]
}
@@ -1782,8 +1866,9 @@
"_consumers": [
{
"_name": "Consumer9",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true
}
]
}
@@ -1799,8 +1884,9 @@
"_consumers": [
{
"_name": "Consumer10",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true
}
]
}
@@ -1818,7 +1904,7 @@
"_name": "Varying number of participants: 1 consumer - 10 producers - PERSISTENT",
"_queues":[
{
- "_name": "direct://amq.direct//varying-consumers?durable='true'",
+ "_name": "direct://amq.direct//latency-varying-consumers?durable='true'",
"_durable": true
}
],
@@ -1836,8 +1922,9 @@
"_producers": [
{
"_name": "Producer1",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000,
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_interval": 3000,
"_deliveryMode": 2,
"_messageSize": 1024
}
@@ -1855,8 +1942,9 @@
"_producers": [
{
"_name": "Producer2",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000,
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_interval": 3000,
"_deliveryMode": 2,
"_messageSize": 1024
}
@@ -1874,8 +1962,9 @@
"_producers": [
{
"_name": "Producer3",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000,
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_interval": 3000,
"_deliveryMode": 2,
"_messageSize": 1024
}
@@ -1893,8 +1982,9 @@
"_producers": [
{
"_name": "Producer4",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000,
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_interval": 3000,
"_deliveryMode": 2,
"_messageSize": 1024
}
@@ -1912,8 +2002,9 @@
"_producers": [
{
"_name": "Producer5",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000,
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_interval": 3000,
"_deliveryMode": 2,
"_messageSize": 1024
}
@@ -1931,8 +2022,9 @@
"_producers": [
{
"_name": "Producer6",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000,
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_interval": 3000,
"_deliveryMode": 2,
"_messageSize": 1024
}
@@ -1950,8 +2042,9 @@
"_producers": [
{
"_name": "Producer7",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000,
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_interval": 3000,
"_deliveryMode": 2,
"_messageSize": 1024
}
@@ -1969,8 +2062,9 @@
"_producers": [
{
"_name": "Producer8",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000,
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_interval": 3000,
"_deliveryMode": 2,
"_messageSize": 1024
}
@@ -1988,8 +2082,9 @@
"_producers": [
{
"_name": "Producer9",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000,
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_interval": 3000,
"_deliveryMode": 2,
"_messageSize": 1024
}
@@ -2007,8 +2102,9 @@
"_producers": [
{
"_name": "Producer10",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000,
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_interval": 3000,
"_deliveryMode": 2,
"_messageSize": 1024
}
@@ -2031,8 +2127,9 @@
"_consumers": [
{
"_name": "Consumer1",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true
}
]
}
@@ -2050,7 +2147,7 @@
"_name": "Varying number of participants: 2 consumers - 10 producers - PERSISTENT",
"_queues":[
{
- "_name": "direct://amq.direct//varying-consumers?durable='true'",
+ "_name": "direct://amq.direct//latency-varying-consumers?durable='true'",
"_durable": true
}
],
@@ -2068,8 +2165,9 @@
"_producers": [
{
"_name": "Producer1",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000,
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_interval": 3000,
"_deliveryMode": 2,
"_messageSize": 1024
}
@@ -2087,8 +2185,9 @@
"_producers": [
{
"_name": "Producer2",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000,
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_interval": 3000,
"_deliveryMode": 2,
"_messageSize": 1024
}
@@ -2106,8 +2205,9 @@
"_producers": [
{
"_name": "Producer3",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000,
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_interval": 3000,
"_deliveryMode": 2,
"_messageSize": 1024
}
@@ -2125,8 +2225,9 @@
"_producers": [
{
"_name": "Producer4",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000,
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_interval": 3000,
"_deliveryMode": 2,
"_messageSize": 1024
}
@@ -2144,8 +2245,9 @@
"_producers": [
{
"_name": "Producer5",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000,
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_interval": 3000,
"_deliveryMode": 2,
"_messageSize": 1024
}
@@ -2163,8 +2265,9 @@
"_producers": [
{
"_name": "Producer6",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000,
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_interval": 3000,
"_deliveryMode": 2,
"_messageSize": 1024
}
@@ -2182,8 +2285,9 @@
"_producers": [
{
"_name": "Producer7",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000,
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_interval": 3000,
"_deliveryMode": 2,
"_messageSize": 1024
}
@@ -2201,8 +2305,9 @@
"_producers": [
{
"_name": "Producer8",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000,
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_interval": 3000,
"_deliveryMode": 2,
"_messageSize": 1024
}
@@ -2220,8 +2325,9 @@
"_producers": [
{
"_name": "Producer9",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000,
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_interval": 3000,
"_deliveryMode": 2,
"_messageSize": 1024
}
@@ -2239,8 +2345,9 @@
"_producers": [
{
"_name": "Producer10",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000,
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_interval": 3000,
"_deliveryMode": 2,
"_messageSize": 1024
}
@@ -2263,8 +2370,9 @@
"_consumers": [
{
"_name": "Consumer1",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true
}
]
}
@@ -2280,8 +2388,9 @@
"_consumers": [
{
"_name": "Consumer2",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true
}
]
}
@@ -2300,7 +2409,7 @@
"_name": "Varying number of participants: 5 consumers - 10 producers - PERSISTENT",
"_queues":[
{
- "_name": "direct://amq.direct//varying-consumers?durable='true'",
+ "_name": "direct://amq.direct//latency-varying-consumers?durable='true'",
"_durable": true
}
],
@@ -2318,8 +2427,9 @@
"_producers": [
{
"_name": "Producer1",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000,
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_interval": 3000,
"_deliveryMode": 2,
"_messageSize": 1024
}
@@ -2337,8 +2447,9 @@
"_producers": [
{
"_name": "Producer2",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000,
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_interval": 3000,
"_deliveryMode": 2,
"_messageSize": 1024
}
@@ -2356,8 +2467,9 @@
"_producers": [
{
"_name": "Producer3",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000,
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_interval": 3000,
"_deliveryMode": 2,
"_messageSize": 1024
}
@@ -2375,8 +2487,9 @@
"_producers": [
{
"_name": "Producer4",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000,
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_interval": 3000,
"_deliveryMode": 2,
"_messageSize": 1024
}
@@ -2394,8 +2507,9 @@
"_producers": [
{
"_name": "Producer5",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000,
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_interval": 3000,
"_deliveryMode": 2,
"_messageSize": 1024
}
@@ -2413,8 +2527,9 @@
"_producers": [
{
"_name": "Producer6",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000,
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_interval": 3000,
"_deliveryMode": 2,
"_messageSize": 1024
}
@@ -2432,8 +2547,9 @@
"_producers": [
{
"_name": "Producer7",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000,
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_interval": 3000,
"_deliveryMode": 2,
"_messageSize": 1024
}
@@ -2451,8 +2567,9 @@
"_producers": [
{
"_name": "Producer8",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000,
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_interval": 3000,
"_deliveryMode": 2,
"_messageSize": 1024
}
@@ -2470,8 +2587,9 @@
"_producers": [
{
"_name": "Producer9",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000,
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_interval": 3000,
"_deliveryMode": 2,
"_messageSize": 1024
}
@@ -2489,8 +2607,9 @@
"_producers": [
{
"_name": "Producer10",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000,
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_interval": 3000,
"_deliveryMode": 2,
"_messageSize": 1024
}
@@ -2513,8 +2632,9 @@
"_consumers": [
{
"_name": "Consumer1",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true
}
]
}
@@ -2530,8 +2650,9 @@
"_consumers": [
{
"_name": "Consumer2",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true
}
]
}
@@ -2547,8 +2668,9 @@
"_consumers": [
{
"_name": "Consumer3",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true
}
]
}
@@ -2564,8 +2686,9 @@
"_consumers": [
{
"_name": "Consumer4",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true
}
]
}
@@ -2581,8 +2704,9 @@
"_consumers": [
{
"_name": "Consumer5",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true
}
]
}
@@ -2600,7 +2724,7 @@
"_name": "Varying number of participants: 10 consumers - 10 producers - PERSISTENT",
"_queues":[
{
- "_name": "direct://amq.direct//varying-consumers?durable='true'",
+ "_name": "direct://amq.direct//latency-varying-consumers?durable='true'",
"_durable": true
}
],
@@ -2618,8 +2742,9 @@
"_producers": [
{
"_name": "Producer1",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000,
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_interval": 3000,
"_deliveryMode": 2,
"_messageSize": 1024
}
@@ -2637,8 +2762,9 @@
"_producers": [
{
"_name": "Producer2",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000,
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_interval": 3000,
"_deliveryMode": 2,
"_messageSize": 1024
}
@@ -2656,8 +2782,9 @@
"_producers": [
{
"_name": "Producer3",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000,
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_interval": 3000,
"_deliveryMode": 2,
"_messageSize": 1024
}
@@ -2675,8 +2802,9 @@
"_producers": [
{
"_name": "Producer4",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000,
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_interval": 3000,
"_deliveryMode": 2,
"_messageSize": 1024
}
@@ -2694,8 +2822,9 @@
"_producers": [
{
"_name": "Producer5",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000,
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_interval": 3000,
"_deliveryMode": 2,
"_messageSize": 1024
}
@@ -2713,8 +2842,9 @@
"_producers": [
{
"_name": "Producer6",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000,
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_interval": 3000,
"_deliveryMode": 2,
"_messageSize": 1024
}
@@ -2732,8 +2862,9 @@
"_producers": [
{
"_name": "Producer7",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000,
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_interval": 3000,
"_deliveryMode": 2,
"_messageSize": 1024
}
@@ -2751,8 +2882,9 @@
"_producers": [
{
"_name": "Producer8",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000,
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_interval": 3000,
"_deliveryMode": 2,
"_messageSize": 1024
}
@@ -2770,8 +2902,9 @@
"_producers": [
{
"_name": "Producer9",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000,
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_interval": 3000,
"_deliveryMode": 2,
"_messageSize": 1024
}
@@ -2789,8 +2922,9 @@
"_producers": [
{
"_name": "Producer10",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000,
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_interval": 3000,
"_deliveryMode": 2,
"_messageSize": 1024
}
@@ -2813,8 +2947,9 @@
"_consumers": [
{
"_name": "Consumer1",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true
}
]
}
@@ -2830,8 +2965,9 @@
"_consumers": [
{
"_name": "Consumer2",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true
}
]
}
@@ -2847,8 +2983,9 @@
"_consumers": [
{
"_name": "Consumer3",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true
}
]
}
@@ -2864,8 +3001,9 @@
"_consumers": [
{
"_name": "Consumer4",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true
}
]
}
@@ -2881,8 +3019,9 @@
"_consumers": [
{
"_name": "Consumer5",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true
}
]
}
@@ -2898,8 +3037,9 @@
"_consumers": [
{
"_name": "Consumer6",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true
}
]
}
@@ -2915,8 +3055,9 @@
"_consumers": [
{
"_name": "Consumer7",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true
}
]
}
@@ -2932,8 +3073,9 @@
"_consumers": [
{
"_name": "Consumer8",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true
}
]
}
@@ -2949,8 +3091,9 @@
"_consumers": [
{
"_name": "Consumer9",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true
}
]
}
@@ -2966,8 +3109,9 @@
"_consumers": [
{
"_name": "Consumer10",
- "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
- "_maximumDuration": 180000
+ "_destinationName": "direct://amq.direct//latency-varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_evaluateLatency": true
}
]
}
diff --git a/java/perftests/etc/testdefs/short/MessageSize.json b/java/perftests/etc/testdefs/MessageSize.json
index 3354d72d3e..6d796bd824 100644
--- a/java/perftests/etc/testdefs/short/MessageSize.json
+++ b/java/perftests/etc/testdefs/MessageSize.json
@@ -1,51 +1,40 @@
{
"_tests":[
{
- "_name": "Message Size - 1P-1C - NON_PERSISTENT";
+ "_name": "Message Size - 1P-1C - TRANSIENT";
"_iterations":[
{
- "_messageSize": 256,
- "_numberOfMessages": 1000000
+ "_messageSize": 256
},
{
- "_messageSize": 512,
- "_numberOfMessages": 500000
+ "_messageSize": 512
},
{
- "_messageSize": 1024,
- "_numberOfMessages": "250000"
+ "_messageSize": 1024
},
{
- "_messageSize": 2048,
- "_numberOfMessages": "125000"
+ "_messageSize": 2048
},
{
- "_messageSize": 4096,
- "_numberOfMessages": "62500"
+ "_messageSize": 4096
},
{
- "_messageSize": 8192,
- "_numberOfMessages": 31250
+ "_messageSize": 8192
},
{
- "_messageSize": 16384,
- "_numberOfMessages": 15625
+ "_messageSize": 16384
},
{
- "_messageSize": 32768,
- "_numberOfMessages": 7812
+ "_messageSize": 32768
},
{
- "_messageSize": 65536,
- "_numberOfMessages": 3906
+ "_messageSize": 65536
},
{
- "_messageSize": 131072,
- "_numberOfMessages": 195
+ "_messageSize": 131072
},
{
- "_messageSize": 262144,
- "_numberOfMessages": 97
+ "_messageSize": 262144
}
],
"_queues":[
@@ -73,7 +62,8 @@
{
"_name": "Producer1",
"_destinationName": "direct://amq.direct//messageSize",
- "_deliveryMode": 1
+ "_deliveryMode": 1,
+ "_maximumDuration": 30000
}
]
}
@@ -94,7 +84,8 @@
"_consumers": [
{
"_name": "Consumer1",
- "_destinationName": "direct://amq.direct//messageSize"
+ "_destinationName": "direct://amq.direct//messageSize",
+ "_maximumDuration": 30000
}
]
}
@@ -108,48 +99,37 @@
"_name": "Message Size - 1P-1C - PERSISTENT";
"_iterations":[
{
- "_messageSize": 256,
- "_numberOfMessages": 20000
+ "_messageSize": 256
},
{
- "_messageSize": 512,
- "_numberOfMessages": 20000
+ "_messageSize": 512
},
{
- "_messageSize": 1024,
- "_numberOfMessages": 20000
+ "_messageSize": 1024
},
{
- "_messageSize": 2048,
- "_numberOfMessages": 20000
+ "_messageSize": 2048
},
{
- "_messageSize": 4096,
- "_numberOfMessages": 4000
+ "_messageSize": 4096
},
{
- "_messageSize": 8192,
- "_numberOfMessages": 4000
+ "_messageSize": 8192
},
{
- "_messageSize": 16384,
- "_numberOfMessages": 4000
+ "_messageSize": 16384
},
{
- "_messageSize": 32768,
- "_numberOfMessages": 2000
+ "_messageSize": 32768
},
{
- "_messageSize": 65536,
- "_numberOfMessages": 2000
+ "_messageSize": 65536
},
{
- "_messageSize": 131072,
- "_numberOfMessages": 2000
+ "_messageSize": 131072
},
{
- "_messageSize": 262144,
- "_numberOfMessages": 2000
+ "_messageSize": 262144
}
],
"_queues":[
@@ -178,7 +158,9 @@
{
"_name": "Producer1",
"_destinationName": "direct://amq.direct//messageSize?durable='true'",
- "_deliveryMode": 2
+ "_deliveryMode": 2,
+ "_maximumDuration": 30000
+
}
]
}
@@ -199,7 +181,8 @@
"_consumers": [
{
"_name": "Consumer1",
- "_destinationName": "direct://amq.direct//messageSize?durable='true'"
+ "_destinationName": "direct://amq.direct//messageSize?durable='true'",
+ "_maximumDuration": 30000
}
]
}
diff --git a/java/perftests/etc/testdefs/short/QueueTypes.json b/java/perftests/etc/testdefs/QueueTypes.json
index 2237e8d8b9..427f3d9795 100644
--- a/java/perftests/etc/testdefs/short/QueueTypes.json
+++ b/java/perftests/etc/testdefs/QueueTypes.json
@@ -16036,7 +16036,7 @@
"_destinationName": "direct://amq.direct//sorted-queue?durable='true'",
"_deliveryMode": 2,
"_messageSize": 1024,
- "_numberOfMessages": 20000,
+ "_maximumDuration": 30000,
"_messageProviderName": "messageProvider"
}
]
@@ -16059,7 +16059,7 @@
{
"_name": "Consumer1",
"_destinationName": "direct://amq.direct//sorted-queue?durable='true'",
- "_numberOfMessages": 20000
+ "_maximumDuration": 30000
}
]
}
@@ -16094,7 +16094,7 @@
"_destinationName": "direct://amq.direct//simple-queue?durable='true'",
"_deliveryMode": 2,
"_messageSize": 1024,
- "_numberOfMessages": 20000
+ "_maximumDuration": 30000
}
]
}
@@ -16116,7 +16116,7 @@
{
"_name": "Consumer1",
"_destinationName": "direct://amq.direct//simple-queue?durable='true'",
- "_numberOfMessages": 20000
+ "_maximumDuration": 30000
}
]
}
@@ -16161,7 +16161,7 @@
"_destinationName": "direct://amq.direct//priority-queue?durable='true'",
"_deliveryMode": 2,
"_messageSize": 1024,
- "_numberOfMessages": 20000,
+ "_maximumDuration": 30000,
"_messageProviderName": "messageProvider"
}
]
@@ -16184,7 +16184,7 @@
{
"_name": "Consumer1",
"_destinationName": "direct://amq.direct//priority-queue?durable='true'",
- "_numberOfMessages": 20000
+ "_maximumDuration": 30000
}
]
}
diff --git a/java/perftests/etc/testdefs/Topic-AckModes.js b/java/perftests/etc/testdefs/Topic-AckModes.js
new file mode 100644
index 0000000000..5c4dee88e3
--- /dev/null
+++ b/java/perftests/etc/testdefs/Topic-AckModes.js
@@ -0,0 +1,68 @@
+var duration = 30000;
+var topicName = "topic://amq.topic/?routingkey='testTopic'";
+
+var jsonObject = {
+ _tests: [
+ {
+ "_name": "Topic ack modes",
+ "_iterations": [
+ {
+ "_acknowledgeMode": 1
+ },
+ {
+ "_acknowledgeMode": 2
+ },
+ {
+ "_acknowledgeMode": 3
+ }
+ ],
+ "_clients": [
+ {
+ "_name": "producingClient",
+ "_connections":[
+ {
+ "_name": "connection1",
+ "_factory": "connectionfactory",
+ "_sessions": [
+ {
+ "_sessionName": "session1",
+ "_producers": [
+ {
+ "_name": "Producer",
+ "_destinationName": topicName,
+ "_maximumDuration": duration,
+ "_startDelay": 2000 // gives the consumers time to implicitly create the topic
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ .concat(QPID.times(10,
+ {
+ "_name": "consumingClient-__INDEX",
+ "_connections":[
+ {
+ "_name": "connection1",
+ "_factory": "connectionfactory",
+ "_sessions": [
+ {
+ "_sessionName": "session1",
+ "_consumers": [
+ {
+ "_name": "Consumer-__INDEX",
+ "_destinationName": topicName,
+ "_maximumDuration": duration,
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ "__INDEX"))
+ }]
+};
+
diff --git a/java/perftests/etc/testdefs/Topic-NumberOfConsumers.js b/java/perftests/etc/testdefs/Topic-NumberOfConsumers.js
new file mode 100644
index 0000000000..751b8b1528
--- /dev/null
+++ b/java/perftests/etc/testdefs/Topic-NumberOfConsumers.js
@@ -0,0 +1,65 @@
+var jsonObject = {
+ _tests:[]
+};
+
+var duration = 30000;
+var topicName = "topic://amq.topic/?routingkey='testTopic.1'";
+
+var numbersOfConsumers = [1, 10, 50, 100];
+
+for(i=0; i < numbersOfConsumers.length ; i++)
+{
+ var numberOfConsumers = numbersOfConsumers[i];
+ var test = {
+ "_name": numberOfConsumers,
+ "_clients":[
+ {
+ "_name": "producingClient",
+ "_connections":[
+ {
+ "_name": "connection1",
+ "_factory": "connectionfactory",
+ "_sessions": [
+ {
+ "_sessionName": "session1",
+ "_producers": [
+ {
+ "_name": "Producer1",
+ "_destinationName": topicName,
+ "_maximumDuration": duration,
+ "_startDelay": 2000 // gives the consumers time to implicitly create the topic
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ].concat(QPID.times(numberOfConsumers,
+ {
+ "_name": "consumingClient-__INDEX",
+ "_connections":[
+ {
+ "_name": "connection1",
+ "_factory": "connectionfactory",
+ "_sessions": [
+ {
+ "_sessionName": "session1",
+ "_consumers": [
+ {
+ "_name": "Consumer-__INDEX",
+ "_destinationName": topicName,
+ "_maximumDuration": duration
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ "__INDEX"))
+ };
+
+ jsonObject._tests= jsonObject._tests.concat(test);
+}
+
diff --git a/java/perftests/etc/testdefs/Topic-NumberOfTopics.js b/java/perftests/etc/testdefs/Topic-NumberOfTopics.js
new file mode 100644
index 0000000000..89e5ecf56c
--- /dev/null
+++ b/java/perftests/etc/testdefs/Topic-NumberOfTopics.js
@@ -0,0 +1,70 @@
+var jsonObject = {
+ _tests:[]
+};
+
+var duration = 30000;
+var topicName = "topic://amq.topic/?routingkey='testTopic.__INDEX'";
+
+var numbersOfTopics = [1, 10, 50, 100];
+
+// Each test has n pairs of producers and consumers, each with a different topic
+
+for(i=0; i < numbersOfTopics.length ; i++)
+{
+ var numberOfTopics = numbersOfTopics[i];
+ var test = {
+ "_name": numberOfTopics,
+ "_clients":
+ QPID.times(numberOfTopics,
+ {
+ "_name": "producingClient-__INDEX",
+ "_connections":[
+ {
+ "_name": "connection1",
+ "_factory": "connectionfactory",
+ "_sessions": [
+ {
+ "_sessionName": "session1",
+ "_producers": [
+ {
+ "_name": "Producer-__INDEX",
+ "_destinationName": topicName,
+ "_maximumDuration": duration,
+ "_startDelay": 2000 // gives the consumers time to implicitly create the topic
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ "__INDEX")
+ .concat(
+ QPID.times(numberOfTopics,
+ {
+ "_name": "consumingClient-__INDEX",
+ "_connections":[
+ {
+ "_name": "connection1",
+ "_factory": "connectionfactory",
+ "_sessions": [
+ {
+ "_sessionName": "session1",
+ "_consumers": [
+ {
+ "_name": "Consumer-__INDEX",
+ "_destinationName": topicName,
+ "_maximumDuration": duration
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ "__INDEX"))
+ };
+
+ jsonObject._tests= jsonObject._tests.concat(test);
+}
+
diff --git a/java/perftests/etc/testdefs/Topic-Persistence.js b/java/perftests/etc/testdefs/Topic-Persistence.js
new file mode 100644
index 0000000000..fd92560fc3
--- /dev/null
+++ b/java/perftests/etc/testdefs/Topic-Persistence.js
@@ -0,0 +1,70 @@
+var duration = 30000;
+var topicName = "topic://amq.topic/?routingkey='testTopic'";
+
+var jsonObject = {
+ _tests: [
+ {
+ "_name": "Topic persistence",
+ "_iterations": [
+ // note that we use _durableSubscription (the JaveBeans property name)
+ // rather than _isDurableSubscription (the field name)
+ {
+ "_deliveryMode": 1,
+ "_durableSubscription": false
+ },
+ {
+ "_deliveryMode": 2,
+ "_durableSubscription": true
+ }
+ ],
+ "_clients": [
+ {
+ "_name": "producingClient",
+ "_connections":[
+ {
+ "_name": "connection1",
+ "_factory": "connectionfactory",
+ "_sessions": [
+ {
+ "_sessionName": "session1",
+ "_producers": [
+ {
+ "_name": "Producer",
+ "_destinationName": topicName,
+ "_maximumDuration": duration,
+ "_startDelay": 2000 // gives the consumers time to implicitly create the topic
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ .concat(QPID.times(10,
+ {
+ "_name": "consumingClient-__INDEX",
+ "_connections":[
+ {
+ "_name": "connection1",
+ "_factory": "connectionfactory",
+ "_sessions": [
+ {
+ "_sessionName": "session1",
+ "_consumers": [
+ {
+ "_name": "Consumer-__INDEX",
+ "_destinationName": topicName,
+ "_isTopic": true,
+ "_maximumDuration": duration,
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ "__INDEX"))
+ }]
+};
+
diff --git a/java/perftests/etc/testdefs/short/VaryingNumberOfParticipants.json b/java/perftests/etc/testdefs/VaryingNumberOfParticipants.json
index 457b0bc348..457b0bc348 100644
--- a/java/perftests/etc/testdefs/short/VaryingNumberOfParticipants.json
+++ b/java/perftests/etc/testdefs/VaryingNumberOfParticipants.json
diff --git a/java/perftests/etc/testdefs/standard/AcknowledgementModes.json b/java/perftests/etc/testdefs/standard/AcknowledgementModes.json
deleted file mode 100644
index db68939a94..0000000000
--- a/java/perftests/etc/testdefs/standard/AcknowledgementModes.json
+++ /dev/null
@@ -1,138 +0,0 @@
-{
- "_tests":[
- {
- "_name": "Acknowledgement Modes - NON_PERSISTENT";
- "_iterations":[
- {
- "_messageSize": 1024,
- "_numberOfMessages": 10000000,
- "_acknowledgeMode": 1,
- "_deliveryMode": 1
- },
- {
- "_messageSize": 1024,
- "_numberOfMessages": 2500000,
- "_acknowledgeMode": 0,
- "_deliveryMode": 1
- }
- ],
- "_queues":[
- {
- "_name": "direct://amq.direct//testQueue",
- "_attributes":
- {
- "x-qpid-capacity": 10485760,
- "x-qpid-flow-resume-capacity": 8388608
- }
- }
- ],
- "_clients":[
- {
- "_name": "producingClient",
- "_connections":[
- {
- "_name": "connection1",
- "_factory": "connectionfactory",
- "_sessions": [
- {
- "_sessionName": "session1",
- "_producers": [
- {
- "_name": "Producer1",
- "_destinationName": "direct://amq.direct//testQueue"
- }
- ]
- }
- ]
- }
- ]
- },
- {
- "_name": "consumingClient",
- "_connections":[
- {
- "_name": "connection1",
- "_factory": "connectionfactory",
- "_sessions": [
- {
- "_sessionName": "session1",
- "_consumers": [
- {
- "_name": "Consumer1",
- "_destinationName": "direct://amq.direct//testQueue"
- }
- ]
- }
- ]
- }
- ]
- }
- ]
- },
- {
- "_name": "Acknowledgement Modes - PERSISTENT";
- "_iterations":[
- {
- "_messageSize": 1024,
- "_numberOfMessages": 1000000,
- "_acknowledgeMode": 1,
- "_deliveryMode": 2
- },
- {
- "_messageSize": 1024,
- "_numberOfMessages": 250000,
- "_acknowledgeMode": 0,
- "_deliveryMode": 2
- }
- ],
- "_queues":[
- {
- "_name": "direct://amq.direct//testQueue?durable='true'",
- "_durable" : "true"
- }
- ],
- "_clients":[
- {
- "_name": "producingClient",
- "_connections":[
- {
- "_name": "connection1",
- "_factory": "connectionfactory",
- "_sessions": [
- {
- "_sessionName": "session1",
- "_producers": [
- {
- "_name": "Producer1",
- "_destinationName": "direct://amq.direct//testQueue?durable='true'"
- }
- ]
- }
- ]
- }
- ]
- },
- {
- "_name": "consumingClient",
- "_connections":[
- {
- "_name": "connection1",
- "_factory": "connectionfactory",
- "_sessions": [
- {
- "_sessionName": "session1",
- "_consumers": [
- {
- "_name": "Consumer1",
- "_destinationName": "direct://amq.direct//testQueue?durable='true'"
- }
- ]
- }
- ]
- }
- ]
- }
- ]
- }
- ]
-}
diff --git a/java/perftests/etc/testdefs/standard/BatchSize.json b/java/perftests/etc/testdefs/standard/BatchSize.json
deleted file mode 100644
index 309cd4d5ed..0000000000
--- a/java/perftests/etc/testdefs/standard/BatchSize.json
+++ /dev/null
@@ -1,84 +0,0 @@
-{
- "_tests":[
- {
- "_name": "Batch Size- PERSISTENT";
- "_iterations":[
- {
- "_batchSize": 1
- },
- {
- "_batchSize": 2
- },
- {
- "_batchSize": 5
- },
- {
- "_batchSize": 10
- },
- {
- "_batchSize": 20
- },
- {
- "_batchSize": 50
- },
- {
- "_batchSize": 100
- }
- ],
- "_queues":[
- {
- "_name": "direct://amq.direct//batchSize?durable='true'",
- "_durable" : true
- }
- ],
- "_clients":[
- {
- "_name": "producingClient",
- "_connections":[
- {
- "_name": "connection1",
- "_factory": "connectionfactory",
- "_sessions": [
- {
- "_sessionName": "session1",
- "_acknowledgeMode": 0,
- "_producers": [
- {
- "_name": "Producer1",
- "_destinationName": "direct://amq.direct//batchSize?durable='true'",
- "_messageSize": 1024,
- "_maximumDuration": 120000,
- "_deliveryMode": 2
- }
- ]
- }
- ]
- }
- ]
- },
- {
- "_name": "consumingClient",
- "_connections":[
- {
- "_name": "connection1",
- "_factory": "connectionfactory",
- "_sessions": [
- {
- "_sessionName": "session1",
- "_acknowledgeMode": 0,
- "_consumers": [
- {
- "_name": "Consumer1",
- "_destinationName": "direct://amq.direct//batchSize?durable='true'",
- "_maximumDuration": 120000
- }
- ]
- }
- ]
- }
- ]
- }
- ]
- }
- ]
-}
diff --git a/java/perftests/etc/testdefs/standard/QueueTypes.json b/java/perftests/etc/testdefs/standard/QueueTypes.json
deleted file mode 100644
index 479b3be9f1..0000000000
--- a/java/perftests/etc/testdefs/standard/QueueTypes.json
+++ /dev/null
@@ -1,16205 +0,0 @@
-{
- "_tests":[
- {
- "_name": "queue-type:sorted-queue";
- "_queues":[
- {
- "_name": "direct://amq.direct//sorted-queue?durable='true'",
- "_durable": true,
- "_attributes":
- {
- "x-qpid-capacity": 10485760,
- "x-qpid-flow-resume-capacity": 8388608,
- "qpid.queue_sort_key": "sort-key"
- }
- }
- ],
- "_clients":[
- {
- "_name": "producingClient",
- "_messageProviders": [
- {
- "_name": "messageProvider",
- "_messageProperties":{ "sort-key": {"@def": "list", "_items": [
-"GWqqXCp3mZ","b29RJ45cIH","7hyVvgtCA5","16lHcCxVEf","jzUqRuPX7G","0Wr5y4QMc9","pWiOsLbRTH","Dz1R3BGaQY","Cfgr39y4lw","Zv7z0FxX9q",
-"lj07QxXTI4","RACuj9XyT9","MGlTF55rfB","0Wr5yW3VFH","lweGyVprf2","lpF6WuJScX","lCMxy2TRI7","KZamHl83Ud","5drc6jiVBP","rKDLJwDajX",
-"CK5W7MezSW","2TRI7LbRTH","zqH0WiwzGk","hYBCKUvlv4","Mkgy8Q6hMC","8FmFHjtn0X","8FmFH5Mg9r","hUTw7rz7Ut","pmeCdQnJ1S","euZA5dQ586",
-"sqVrfQWxoT","RsQUqTwano","7ku1ptlILt","jzUqRpiJSk","0YAGH5Drn0","7ku1pCxVEf","QbxXc8hJdt","4W0Tldpe1v","MK07Ys7Mxk","zHF1qCNHmv",
-"uoStwRzaZA","KZamHVLTy6","XyPZN5Drn0","7fKYU07n1c","HfyNQiwzGk","mX2GEoGu6x","9eoRcydG8U","pAhR1iKqhr","LbRTHb29RJ","Waim6DLhzM",
-"bgJAzReKEW","pmeCdjeskS","gdQsSguMb8","Oz8yZI7p2a","ogLgculk41","HfyNQ0MR5X","24ARFWDVWJ","uAWypwDajX","lH1kt6AFT0","EOE1oZhwG1",
-"AIYUu0Kyfs","prNT6uTacx","TwanoFPfSE","OUYuFAXpwE","euZA5FVMxo","ni2v10BmCy","5Mg9rJRJQB","nlaBya00b5","7X3uyL7cGc","ECMvU55rfB",
-"JXljW2TRI7","Z4I1vY1mC0","lj07QFhtgl","fqypycmXIX","Ul4a1GrDg7","LDk6fulk41","2Nslm2hEEU","LbRTHuTacx","gIYvEK4GS8","Cfgr3i7WMQ",
-"pWiOss4786","mX2GETCgPp","8xEKzjeskS","uTacxDQimp","ksJbyfFDrJ","7fKYUAOgEe","5Drn0azIWp","he9IAIKxdL","HfyNQTwano","FcWrW0ao3l",
-"iKqhrn8pJ9","BbwgArhl0J","M6qcGjiVBP","b29RJ8U2nU","MK07Y8cVD3","dhSuHjfREu","azIWpjS1aj","qQxHPTwano","QChxsJRJQB","YjB9tuZPqg",
-"FVMxoMmKGJ","JKWYRZUnqt","AIYUuhUTw7","U3yw5Cp3mZ","zz4ZUGXdoH","8hJdtBbwgA","Ul4a155rfB","oVQp6DLhzM","DG4sTfmIK1","zY1GYAXpwE",
-"M3zXLGrDg7","CK5W7jSjS3","fmIK1uTacx","OxWIHkB5nP","xXTI4BFkb8","OUYuFblLA9","RkQkeqaofN","YjB9tuTacx","uLtKsW7cTs","l83UdDcpWB",
-"brhlQRsQUq","GSQwjCIShG","GSQwjFwEJz","HlUbF2DREs","Mkgy8xReec","16lHcwDajX","MaJQs5IhmG","9iGoTdmoS7","DQimplpF6W","bgJAzVjCZq",
-"vLsmSwDajX","DG4sTciuWz","ECMvU48cHL","nlaByqaofN","QWxoTv1Hln","WaWsvqUJMd","F6PT28cVD3","lweGyLewvM","IRh48xciqp","9y4lw8U2nU",
-"2TRI7NOHsz","uAWypuTacx","FhtglcQOnv","bZLvS0PktI","v2eC3DcpWB","ReKEWksJby","ECMvUPOUYS","8RCUATa8f6","gjUTu0YAGH","FcWrWcmXIX",
-"QYxC0zQt6Q","MK07Y7fKYU","qQxHPoGu6x","faHirNo0Qb","aFFss0MR5X","RpBQmokgRi","IBe8kVerEA","OHaBzy94nw","0ao3lDLhzM","tuDySpT8wu",
-"jSjS3JJs5m","VerEA7Ow5C","5NammJXljW","gf8rIhi5X7","M3zXLRsQUq","K4GS8y94nw","aez9yvkCHH","uTacxix74r","RpBQmCqqaD","4dEz6L7cGc",
-"ix74rJKWYR","4W0TlNhXdu","VjCZqogLgc","45cIHNcICA","pT8wufqypy","nnP8odQ586","dpe1vGSQwj","2ZHdkvkCHH","zz4ZUhe9IA","nnP8oCqqaD",
-"vLsmSYw2oU","4QMc9GSQwj","yluBxOz8yZ","0ao3lsqVrf","K20wKCK5W7","fcwDa8FmFH","GWqqXX6Pin","faHird7vjM","RBhp0ZzJHW","EOE1owDajX",
-"QssNC0Kyfs","iqv4kCp3mZ","4W0TlMkgy8","aDGtSdhSuH","uQIcz5Drn0","1v5hHUmaEv","pAhR1MmKGJ","2Yz7EQWxoT","nFqikKASQ8","ZJTXHpT8wu",
-"5iGN5MojnP","gf8rIsuY4x","l83UdHzZT8","uoStwtAOsr","wDajXzFgtB","mz8gxAOgEe","dhSuHMm8si","ZzJHW6q6L9","FjHXRuPX7G","8cVD3MmsIo",
-"Pb1pagdQsS","m4bxUuAWyp","4QMc9suY4x","nnP8ouZPqg","7X3uynFqik","FnPFBRxrsm","Waim6NcICA","KASQ8JIqXi","s7MxkguMb8","KASQ8AkKTk",
-"fFDrJtuDyS","l83UdD6rBy","ZhwG1dmoS7","7ku1pnnP8o","uPX7GpFrrl","7ku1p4W0Tl","zmLYDQbxXc","zY1GYPb1pa","x3LDe3weIF","zbIYYKsjRK",
-"7Ow5COHaBz","dhSuHJJs5m","RzaZAZhwG1","HRxd8DQimp","IjTwPCK5W7","AOgEelpF6W","8FmFHn1pmO","e6e4z0Kyfs","blLA95nmWv","s4786LbRTH",
-"VBjhzuPX7G","WPmlx7Ow5C","soy9tK4GS8","qaofNfcwDa","iB08lOHaBz","4W0Tl0MR5X","FLsphNo0Qb","kZANmZJTXH","fmIK19iGoT","zFgtB7fsYM",
-"tlILtKZamH","zHF1qvkCHH","HzZT8O3iyQ","i3pydMkgy8","GXdoHy94nw","HlUbFyToGW","e6e4za00b5","aDGtSi3pyd","ZJTXHjzUqR","pAhR1FNYIM",
-"5Mg9rhUTw7","QWxoTL7cGc","aFFssfcwDa","GSQwjni2v1","Vprf2Nxx9V","7ku1peuZA5","MaJQsokgRi","DcpWBQ6hMC","HlUbFM6qcG","iqv4kKr8ys",
-"hi5X7cL0aE","fLNg8Nxx9V","zHF1qQbxXc","Yf2EcB3qem","gIYvEQWxoT","CIShGlViBv","8xEKzBCxeC","UmaEvh1zcH","ogLgcfcJOy","ZUnqtGSQwj",
-"2hEEUzQt6Q","rKDLJTXQ0Z","MmsIoru4UG","mz8gxOxWIH","zFgtBhYBCK","bZLvSqUJMd","hi5X7lsQGo","hSSvQs4786","SjskQoGu6x","07n1cJ2mQi",
-"hYBCKjeskS","Chuy324ARF","s4786UlU3M","AkKTkBFkb8","W3VFHulk41","tl72W7fsYM","ZhwG1Rxrsm","K4GS8YOfrY","0PktIxciqp","9rlg90h1b1",
-"Pb1paAgJHQ","WmadAsx5Gl","GWqqXnFqik","QnJ1SFcWrW","XyPZNNo0Qb","9rlg9TXQ0Z","4dEz6oQ87r","WaWsvZ4I1v","7hyVv4dEz6","a00b5TXQ0Z",
-"iqv4kblLA9","pv0i7ciuWz","9GXkXsx5Gl","Yh1hFyEfy9","SWfouQssNC","5NammlsQGo","ciuWzJKWYR","RmDcrWmadA","s47862ZHdk","RACujo8Uyd",
-"hYBCKm4bxU","l83UdMaJQs","9rlg9Qworu","J2mQiTa8f6","jzUqR7ku1p","64s8NSmGzv","ZhwG1NOHsz","fFDrJuoStw","Chuy3RACuj","aL6AJ5drc6",
-"hYBCKS2Dfu","OHaBzJXljW","djsrv0ao3l","zz4ZUsqVrf","TXQ0ZIBe8k","lViBv2Yz7E","cQOnvMm8si","aL6AJLDk6f","ThjNnru4UG","14FLRo8Uyd",
-"pv0i7rz7Ut","tlILtCIShG","WMiS37fKYU","xXTI4b29RJ","8FmFHThjNn","8cVD34QMc9","8xEKzqaofN","Oz8yZs93Ml","tjQxsJRJQB","Chuy3TCgPp",
-"P6bcgfmIK1","OUYuFI7p2a","tlILtQssNC","k85Aem4bxU","RpBQm7lUXZ","StlDJyvOMI","DcpWBFxX9q","iwzGk0ao3l","KASQ8BbwgA","gdQsS45cIH",
-"bZLvSpWiOs","RACujGrDg7","tuDySZv7z0","d85a9Pb1pa","0BmCyQWxoT","ECMvUs93Ml","CIShGmX2GE","uupzktAOsr","1LB1Lgf8rI","24ARFbgJAz",
-"HRxd8hi5X7","1v5hHyluBx","RACujWreyP","vLsmS0ao3l","BFkb8uTacx","7lUXZVjCZq","RACujSbRYy","K20wK1v5hH","uPX7GUvlv4","tvdkDOHaBz",
-"dpe1vKr8ys","5NammJ2mQi","aDGtSQClRL","M6qcGRzaZA","WMiS3SWfou","0KyfsSmGzv","P6bcg0Wr5y","pvgjSfLNg8","RpBQmCK5W7","gf8rIFxX9q",
-"sqVrf8FmFH","lpF6Wzz4ZU","AOgEeTwano","7lUXZNhXdu","64s8NJIqXi","ni2v1d85a9","2DREscQOnv","Mm8silm0pD","xXTI4MK07Y","Q6Lix9XyT9",
-"64s8NG1RhS","RkQkevOqCE","zz4ZUpv0i7","QnJ1SBpYhV","a00b5IKxdL","BpYhV8xEKz","s7MxkPYBf4","ThjNn5Drn0","jfREu7Ow5C","cShY2VjCZq",
-"M3zXLtAOsr","ru4UGRzaZA","5NammF6PT2","CNHmvtjQxs","MmsIoFxX9q","fqypyWPmlx","K20wKMaJQs","7lUXZ0h1b1","sx5Gln1pmO","ZhwG14QMc9",
-"45cIHUvlv4","i3pyd8U2nU","RmDcrXyPZN","Nxx9Ve6e4z","uPX7GO3iyQ","5VZjSbZLvS","jS1ajh1zcH","0Kyfs5iGN5","7X3uyn8pJ9","3weIFOHaBz",
-"IjTwPIRh48","CdyBV1v5hH","hi5X72Nslm","atef2KsjRK","K20wKMmKGJ","nnP8o4QMc9","7ku1pcShY2","Mm8siGv3Fq","dhSuHrz7Ut","5drc6IjTwP",
-"lkMUAjzUqR","lweGyiKqhr","7Ow5Czz4ZU","AmdQdCfgr3","aFFssL7cGc","P6bcggjUTu","s7MxkY1mC0","FVMxoQbxXc","uPX7GblLA9","BFkb8jeskS",
-"8FmFHt59lR","hi5X7pv0i7","DQimpuvf7A","MezSWHlUbF","9y4lw2Yz7E","QssNC2TRI7","HzZT8EOE1o","Ta8f65drc6","WMiS35VZjS","LDk6fGSQwj",
-"uTacxgjUTu","n8pJ9L7cGc","fcJOyQYxC0","8RCUApFrrl","azIWpReKEW","uN6r3Chuy3","CNHmvL7cGc","jzUqR2Nslm","uPX7GGv3Fq","CqqaDlkMUA",
-"zY1GYSbRYy","AgJHQMGlTF","0PktIpT8wu","RxrsmU3yw5","yvOMI6q6L9","Kr8ysStlDJ","QClRLsqVrf","2Yz7EyofH3","7Ow5CprNT6","IKxdLTa8f6",
-"n8pJ92TRI7","qUJMdvOqCE","jSjS3pT8wu","S2DfusuY4x","AXpwEAgJHQ","1j5L8ZhwG1","uAWyp2Nslm","IRh488FmFH","dmoS7VLTy6","CNHmvECMvU",
-"RACujhUTw7","Uvlv4ix74r","Gv3FqaL6AJ","Waim6DG4sT","QYxC0gdQsS","3weIFzY1GY","pvgjSCfgr3","ZJTXHlj07Q","2hEEU29QAz","Cfgr3s93Ml",
-"wiHrZMmKGJ","XyPZNMaJQs","zbIYYNOHsz","brhlQECMvU","J2mQilweGy","fqypyOxWIH","BbwgAyofH3","W3VFHrKDLJ","sx5Gl2TRI7","AXpwE8TxD7",
-"I7p2anlaBy","NhXduqQxHP","fcJOy4QMc9","SWfouKZamH","GSQwjuoStw","fmIK17X3uy","tAOsrQ6hMC","k85Ae45cIH","Y1mC0uQIcz","zbIYY8FmFH",
-"uZPqg3weIF","8TxD7OHaBz","pmeCd4W0Tl","WaWsv0Wr5y","IRh482TRI7","nlaByvLsmS","hSSvQdpe1v","hi5X7xciqp","tl72WAIYUu","OUqFM9rlg9",
-"VBjhzQ6Lix","Cp3mZSWfou","5drc6ksJby","faHirMmsIo","fFDrJvLsmS","ReKEWfqypy","QWxoTGrDg7","2DREsRpBQm","WaWsvZv7z0","8U2nU3weIF",
-"Rxrsmv2eC3","7X3uyaez9y","0MR5XJJs5m","5IhmGdQ586","BpYhVoQ87r","8FmFH8xEKz","ZUnqtqaofN","45cIHlH1kt","48cHLhUTw7","LewvMnnP8o",
-"CNHmvHzZT8","WMiS39iGoT","QChxsjfREu","RmDcr5iGN5","4dEz68RCUA","64s8NOz8yZ","yluBxuoStw","7hyVvWPmlx","FLsphprNT6","ogLgchE1Ql",
-"uPX7G2TRI7","M6qcGv1Hln","n8pJ9t59lR","cmXIXaL6AJ","1j5L8ni2v1","zz4ZUJKWYR","VBjhzru4UG","oVQp6CNHmv","lViBvTXQ0Z","Pb1paGrDg7",
-"FjHXRFjHXR","yEfy9MmsIo","hE1QlJRJQB","xXTI407n1c","8FmFHtaOXK","fqypyReKEW","AXpwEVprf2","RBhp0ECMvU","Chuy3K4GS8","nFqikTa8f6",
-"lkMUARxrsm","a00b5ulk41","64s8NciuWz","IKxdLHfyNQ","2Nslmt59lR","5drc6580YD","uupzk0h1b1","7fsYMdjsrv","CdyBVoQ87r","Yh1hFMezSW",
-"prNT6hE1Ql","Yh1hFSWfou","CIShGG1RhS","2Yz7EJkzUn","zHF1qZUnqt","xXTI4tjQxs","ZzJHWCxVEf","I7p2akB5nP","2NslmMkgy8","KsjRKVLTy6",
-"TXQ0ZFwEJz","HlUbFazIWp","M3zXLs4786","VerEAzFgtB","VNCPdJIqXi","Pb1pafLNg8","8TxD74QMc9","gIYvEv8yFN","FNYIMgIYvE","YOfrYd7vjM",
-"9rlg914FLR","zFgtBC2Irc","4QMc9D6rBy","uLtKsQssNC","Yw2oUWreyP","WaWsvFhtgl","MGlTFdjsrv","tlILtLDk6f","QClRLhSSvQ","QssNCaL6AJ",
-"fcJOy2ZHdk","d85a9RBhp0","lpF6W7fKYU","qUJMdlXFOB","JIqXidpe1v","45cIHCxVEf","t59lR0Wr5y","zFgtBhe9IA","uLtKsCfgr3","YOfrYReKEW",
-"AgJHQhE1Ql","2ZHdk6q6L9","AgJHQChuy3","RACujuAWyp","Yw2oUDz1R3","pAhR1HfyNQ","jeskSaDGtS","CK5W7Dz1R3","3otm6blLA9","X6PinKASQ8",
-"aez9ygIYvE","K20wKhi5X7","suY4xiKqhr","s4786Z4I1v","gIYvEydG8U","AmdQdQ6hMC","gjUTuAXpwE","FPfSEW3VFH","bgJAzatef2","gf8rIO3iyQ",
-"gtCA5blLA9","FVMxoVjCZq","7hyVvfLNg8","zqH0WC2Irc","yEfy9lweGy","JXljWDQimp","wDajXGXdoH","s93MlFwEJz","G1RhS618Di","l83Ud5IhmG",
-"45cIHzFgtB","8RCUAlsQGo","ni2v11LB1L","yvOMI2Yz7E","zz4ZUnnP8o","L7cGcRsQUq","v8yFNdhSuH","5IhmGzz4ZU","yvOMIo8Uyd","Cp3mZS77LH",
-"zz4ZUGSQwj","P6bcgIjTwP","hYBCKDQimp","8cVD3SjskQ","EoToP64s8N","6q6L9QbxXc","wiHrZqaofN","cmXIXxXTI4","3otm6zqH0W","24ARFulk41",
-"VLTy6cShY2","soy9tOHaBz","StlDJ2Nslm","AkKTkwiHrZ","VerEAyEfy9","HfyNQCK5W7","cShY2M6qcG","bZLvSXyPZN","J2mQiWmadA","0ao3lRxrsm",
-"QChxs4dEz6","0ao3lhi5X7","yvOMITa8f6","hSSvQMmKGJ","OHaBzFNYIM","16lHcy94nw","1LB1L8hJdt","SbRYyWmadA","MGlTFKZamH","rKDLJGWqqX",
-"IjTwPdjsrv","EOE1oHP433","Gv3FqZzJHW","RsQUqfLNg8","G1RhS5ZaEz","JKWYR7fKYU","JXljWTa8f6","FPfSEo8Uyd","4QMc9yToGW","HfyNQM6qcG",
-"S77LHFPfSE","fqypyvkCHH","tuDySfFDrJ","gf8rIuQIcz","Oz8yZFNYIM","FGzgpyToGW","8hJdtKr8ys","pAhR1618Di","pmeCdfFDrJ","AkKTkhUTw7",
-"0MR5XoQ87r","RACujs93Ml","dQ586kB5nP","uoStwYOfrY","UmaEvUlU3M","9GXkXxReec","pv0i7tjQxs","OUqFMQssNC","FnPFBuAWyp","WreyPiKqhr",
-"aFFssUlU3M","dhSuHS77LH","vkCHHFNYIM","Oz8yZG1RhS","C2Irc6AFT0","2ZHdkzbIYY","BpYhVTwano","Mkgy8yEfy9","PYBf4RsQUq","FxX9qlpF6W",
-"WaWsvjfREu","M3zXLU3yw5","VjCZqfcJOy","mz8gxIKxdL","WPmlxCNHmv","1v5hHzqH0W","v1HlnjzUqR","G1RhSNo0Qb","Yh1hFNo0Qb","6AFT0ksJby",
-"dhSuHAOgEe","pv0i7JXljW","djsrv29QAz","D6rByix74r","M6qcG4W0Tl","ThjNneuZA5","5drc6S77LH","TXQ0ZfcJOy","UlU3MgIYvE","ReKEW16lHc",
-"lXFOBSmGzv","aL6AJMGlTF","Yf2Ec7fKYU","0MR5XvLsmS","HzZT8NAFuw","gdQsSIRh48","TXQ0ZAOgEe","HfyNQQWxoT","2TRI7aFFss","xXTI4ReKEW",
-"2Yz7EpT8wu","Ta8f6lXFOB","blLA9pFrrl","0h1b1WMiS3","ThjNnAmdQd","FnPFBsoy9t","hUTw7M3zXL","ksJbyZUnqt","taOXKVIlwP","XflUqtlILt",
-"BpYhVpmeCd","zHF1q5IhmG","gdQsSZzJHW","uAWypYh1hF","BCxeCTXQ0Z","yluBxPOUYS","nnP8oaL6AJ","qQxHPFnPFB","VNCPdcL0aE","s93Ml5VZjS",
-"zHF1qIn3NS","jeskSTXQ0Z","v2eC3sqVrf","uAWyp8hJdt","lXFOB5Drn0","OHaBzAXpwE","uTacxGSQwj","Dz1R3VLTy6","zHF1qulk41","EdBKcRpBQm",
-"Gv3Fq5nmWv","Y1mC01j5L8","45cIHfcJOy","ZJTXHuJScX","bZLvSThjNn","3weIF9XyT9","qQxHPHRxd8","55rfBXyPZN","DG4sTXyPZN","suY4xxXTI4",
-"cL0aEjS1aj","pFrrlAXpwE","uoStwlH1kt","vOqCEaL6AJ","RmDcrfLNg8","suY4xZv7z0","TCgPptuDyS","JJs5m45cIH","F6PT2Ul4a1","B3qem8U2nU",
-"K20wK6q6L9","brhlQWaWsv","FjHXRJJs5m","gf8rI3weIF","BGaQY7fKYU","NhXdu7lUXZ","3weIFSmGzv","Cfgr3FVMxo","LewvMlsQGo","55rfBW7cTs",
-"qaofNQ6hMC","NhXduFnPFB","iwzGkhE1Ql","M6qcGPYBf4","XyPZNVjCZq","S2DfuAgJHQ","vLsmS9GXkX","X6PinVprf2","B3qemMezSW","MmKGJKsjRK",
-"FNYIMDLhzM","U3yw5dpe1v","FFDuiFcWrW","JkzUniB08l","azIWpS2Dfu","0KyfsuTacx","lXFOBfaHir","VerEA7fsYM","StlDJQWxoT","brhlQ5Mg9r",
-"CqqaDFxX9q","4dEz6dQ586","nnP8oFjHXR","CNHmvI7p2a","LewvMazIWp","qaofNVNCPd","KsjRKdjsrv","GXdoHJIqXi","aDGtSFcWrW","RkQkepAhR1",
-"RkQkeGWqqX","F6PT229QAz","JKWYRuJScX","v1HlnguMb8","FVMxot59lR","oQ87rrhl0J","WaWsv7Ow5C","Q6hMClweGy","POUYSbgJAz","16lHcRsQUq",
-"qQxHPWaim6","lViBvRpBQm","G1RhS8TxD7","0PktIBpYhV","CIShG2DREs","2ZHdk24ARF","Yh1hFv1Hln","CdyBVxciqp","jiVBPuQIcz","v8yFNPOUYS",
-"OUqFMazIWp","RpBQm5nmWv","6AFT0JJs5m","VBjhz5Drn0","O3iyQSs0Zu","JJs5mRkQke","yvOMIQChxs","fmIK1Yh1hF","LbRTHXflUq","4W0TlqQxHP",
-"ulk41I7p2a","UlU3MtvdkD","5IhmGIjTwP","ciuWzFGzgp","0KyfsxXTI4","580YD2TRI7","tjQxspiJSk","lm0pDrKDLJ","14FLR8hJdt","29QAzWMiS3",
-"t59lRMGlTF","14FLRrz7Ut","lm0pDUl4a1","X6PinCp3mZ","7ku1pAmdQd","48cHLix74r","aL6AJaez9y","t98iWkB5nP","ru4UG2Yz7E","In3NShYBCK",
-"S2DfuQssNC","uLtKsuN6r3","G1RhSsx5Gl","618DiWPmlx","2ZHdkRpBQm","AOgEeIBe8k","lj07QVprf2","TXQ0ZJkzUn","CK5W7zmLYD","AOgEeaFFss",
-"StlDJJIqXi","VjCZqWDVWJ","W7cTsGSQwj","580YDMmKGJ","TwanoS2Dfu","lH1ktRzaZA","uupzko8Uyd","k85AeguMb8","64s8NNcICA","VLTy6uTacx",
-"oVQp67lUXZ","Zv7z0Q6hMC","Q6LixLDk6f","9rlg92Yz7E","ulk41ydG8U","JKWYRQWxoT","ciuWzaFFss","7fKYUQClRL","8FmFH0h1b1","4W0TlMezSW",
-"euZA5gjUTu","lViBv07n1c","uPX7GGXdoH","VjCZq0MR5X","6q6L9nFqik","K20wKHRxd8","580YDIBe8k","aFFss8TxD7","RpBQmHP433","5Drn0gdQsS",
-"5ZaEz9eoRc","fmIK1M3zXL","tAOsruTacx","K20wK8TxD7","48cHL9eoRc","tvdkDzFgtB","Waim6wiHrZ","SjskQWreyP","cQOnvn8pJ9","dQ586AIYUu",
-"SjskQguMb8","hYBCK5Mg9r","ogLgcFNYIM","Chuy3Ss0Zu","580YDReKEW","jzUqRDcpWB","Z4I1vyEfy9","Cfgr3MmsIo","HRxd88RCUA","FnPFBqUJMd",
-"MGlTFBCxeC","NOHszrz7Ut","M6qcGtvdkD","RzaZATwano","s93MlogLgc","tl72WZUnqt","Mkgy8Qworu","m4bxU5Namm","jeskScmXIX","cL0aE5VZjS",
-"FwEJzNOHsz","jS1ajYf2Ec","gtCA5MmKGJ","fFDrJZzJHW","QWxoT24ARF","pT8wuuJScX","5ZaEzxXTI4","QnJ1SY1mC0","cQOnvAkKTk","Ta8f6fqypy",
-"uoStwCxVEf","SbRYytAOsr","MaJQscmXIX","G1RhS2Nslm","okgRiHRxd8","16lHcuN6r3","b29RJ8FmFH","POUYS4QMc9","IKxdLi7WMQ","pvgjSnnP8o",
-"Ss0ZuuAWyp","t59lRiKqhr","0YAGHCp3mZ","WPmlxzbIYY","n8pJ9gjUTu","jSjS3zQt6Q","aez9yFVMxo","pmeCdvkCHH","jiVBP9eoRc","5Mg9r5Drn0",
-"djsrvTa8f6","v1Hln8FmFH","e6e4zZ4I1v","GSQwjBGaQY","fqypyYh1hF","RBhp0aFFss","QChxsnlaBy","gjUTuxciqp","MojnPuLtKs","SWfou8cVD3",
-"HP433HfyNQ","uupzkMezSW","Yf2Ec7hyVv","lkMUAzY1GY","oVQp6MojnP","CK5W7WMiS3","lsQGoKr8ys","v1HlnL7cGc","S2DfucmXIX","Yf2EcpAhR1",
-"v1Hln7hyVv","vkCHHzQt6Q","a00b5RzaZA","StlDJNxx9V","AXpwEHRxd8","OUqFMgtCA5","tuDySaez9y","P6bcgWDVWJ","Chuy3S2Dfu","BpYhVguMb8",
-"cmXIX8hJdt","BGaQYP6bcg","S2DfuydG8U","i7WMQYjB9t","L7cGcFPfSE","cQOnv0Kyfs","t59lRcL0aE","uQIczdpe1v","FLsph7ku1p","CNHmvWDVWJ",
-"EOE1ojS1aj","0BmCymX2GE","TXQ0ZokgRi","lkMUAWDVWJ","3otm6M3zXL","RmDcrPOUYS","AkKTkoGu6x","S2Dfu5Namm","qUJMdAIYUu","soy9tQbxXc",
-"BpYhVDQimp","NcICAyluBx","l83UdYf2Ec","K20wKKZamH","WaWsv0PktI","uJScX9XyT9","HP433tuDyS","dpe1vaDGtS","LDk6f16lHc","oGu6xx3LDe",
-"lm0pDDcpWB","fcwDajS1aj","ru4UGCNHmv","MezSWaez9y","0YAGHHRxd8","5NammfFDrJ","FNYIMBbwgA","faHirWPmlx","ydG8U580YD","tjQxsEdBKc",
-"gjUTucShY2","ydG8UAXpwE","bZLvSIRh48","AgJHQs93Ml","CK5W70MR5X","iKqhrtl72W","MK07YFFDui","ZUnqtbZLvS","GXdoHFnPFB","lkMUAHzZT8",
-"tl72WChuy3","Dz1R3iB08l","uLtKsNhXdu","AXpwEMGlTF","ZJTXHEOE1o","Kr8ysRmDcr","OUYuFWDVWJ","48cHLtl72W","UlU3M2ZHdk","Z4I1vd7vjM",
-"4QMc9K4GS8","SbRYyChuy3","WreyPAmdQd","IKxdL8U2nU","Cfgr3jzUqR","vOqCEguMb8","uQIczn8pJ9","VLTy6xReec","pvgjSYh1hF","kZANmjiVBP",
-"MezSWMmsIo","IKxdLfcJOy","cQOnveuZA5","hi5X7pWiOs","ksJbyKr8ys","uAWypulk41","AIYUuoGu6x","JIqXi0MR5X","5drc6W3VFH","pmeCdtAOsr",
-"yluBxTa8f6","FFDuilH1kt","48cHLuJScX","S2Dfux3LDe","5ZaEzCxVEf","h1zcHCqqaD","jfREufmIK1","s4786ZUnqt","wDajXAIYUu","Qworu2TRI7",
-"5VZjSzmLYD","618DituDyS","tAOsrpiJSk","RkQkePYBf4","RxrsmPOUYS","NhXdumz8gx","kZANmDG4sT","AmdQdlsQGo","QYxC0soy9t","9XyT9he9IA",
-"3otm6ZzJHW","aez9yRACuj","v2eC3iwzGk","lViBvNcICA","lXFOBazIWp","brhlQLewvM","SbRYycQOnv","ZzJHWtAOsr","soy9tuPX7G","0YAGHo8Uyd",
-"zFgtBSs0Zu","h1zcHECMvU","ru4UG5nmWv","AgJHQK4GS8","jtn0XzFgtB","AOgEeW7cTs","Ss0Zu2hEEU","IBe8kReKEW","SWfouEoToP","hSSvQlViBv",
-"euZA5K4GS8","1j5L8lweGy","Q6LixQworu","azIWpazIWp","uQIczVIlwP","okgRiCIShG","YOfrYYf2Ec","PYBf455rfB","nFqikGv3Fq","7lUXZpmeCd",
-"EdBKctvdkD","Mkgy8tlILt","VerEAiwzGk","gdQsSaDGtS","W7cTsbrhlQ","yEfy9wDajX","Dz1R3LbRTH","ksJbyNxx9V","DG4sTYf2Ec","5NammPYBf4",
-"64s8NYh1hF","fcwDaGrDg7","9y4lwni2v1","5nmWv2ZHdk","X6PinvLsmS","sqVrfKASQ8","9rlg97fsYM","DLhzMkB5nP","s7Mxkmz8gx","jtn0X5ZaEz",
-"GSQwjqUJMd","5iGN5NOHsz","yofH3jtn0X","xXTI4HfyNQ","qQxHPS2Dfu","pv0i7Q6Lix","iKqhr7ku1p","3otm6rhl0J","FPfSEZzJHW","Cfgr3ksJby",
-"brhlQ5nmWv","Q6LixCK5W7","lkMUAS2Dfu","BFkb8cQOnv","S2DfuYw2oU","OUqFMQ6hMC","5IhmGvLsmS","Ta8f65ZaEz","sx5GlQssNC","m4bxU7lUXZ",
-"NOHszZuDtD","lH1kt5Namm","kZANmS2Dfu","cShY2FjHXR","ZzJHWpiJSk","FPfSEl83Ud","LewvMlpF6W","ZhwG15nmWv","hi5X7VLTy6","s4786LDk6f",
-"dpe1vQClRL","yofH3JKWYR","iKqhrVLTy6","BGaQYCIShG","ciuWz5Namm","MojnPVerEA","pFrrlbZLvS","VerEA8hJdt","hi5X77ku1p","O3iyQY1mC0",
-"JkzUn48cHL","nFqikCdyBV","48cHLlsQGo","lH1ktzHF1q","FFDuiSjskQ","nnP8oiwzGk","1v5hHaFFss","55rfBvOqCE","Ss0ZuHRxd8","O3iyQ48cHL",
-"faHirfLNg8","Mkgy8FnPFB","8FmFHFVMxo","RxrsmcL0aE","fLNg8gf8rI","MezSWWaim6","okgRiTCgPp","YjB9t7hyVv","7lUXZS77LH","Rxrsmsx5Gl",
-"a00b5xReec","h1zcHoVQp6","QworuHlUbF","xXTI4ix74r","n8pJ9okgRi","h1zcHqUJMd","ciuWzd7vjM","wDajXVIlwP","J2mQigdQsS","SjskQiwzGk",
-"fcwDablLA9","ZUnqtaFFss","lCMxyzHF1q","AgJHQJkzUn","ZUnqtQClRL","gIYvEtvdkD","taOXKydG8U","RxrsmvkCHH","k85AejiVBP","WDVWJ6AFT0",
-"CIShGOUYuF","aFFsshi5X7","taOXKjzUqR","M3zXLHP433","WMiS3wiHrZ","xXTI47fKYU","QworuZUnqt","aL6AJFPfSE","yToGWRkQke","HzZT8oGu6x",
-"IBe8kMojnP","o8Uyd7hyVv","BGaQYvOqCE","vOqCERsQUq","HRxd8HfyNQ","soy9tRBhp0","ksJbysqVrf","wDajX7fsYM","J2mQiTXQ0Z","uvf7AMK07Y",
-"AXpwEyToGW","YjB9tyofH3","LbRTHCxVEf","cQOnvqUJMd","Yf2Ecsx5Gl","5drc66AFT0","XyPZN9XyT9","5Mg9rFGzgp","BFkb8K4GS8","blLA9FNYIM",
-"oVQp67X3uy","jSjS307n1c","HzZT8lm0pD","Cp3mZKZamH","SbRYyBbwgA","n1pmOfqypy","vLsmSni2v1","5drc6L7cGc","he9IA1LB1L","aez9y0Wr5y",
-"5Mg9r24ARF","FGzgp2hEEU","OxWIHRBhp0","aFFssStlDJ","FLsphyToGW","1LB1LAkKTk","uAWypRxrsm","azIWpLDk6f","DQimptl72W","LewvM8RCUA",
-"gIYvEYw2oU","X6PinNcICA","PYBf4iwzGk","jSjS38U2nU","JIqXipvgjS","XyPZNtl72W","UmaEvrKDLJ","uvf7A1LB1L","0YAGHAkKTk","k85AeQssNC",
-"FLsphYjB9t","hYBCKuZPqg","azIWpt98iW","wDajXgdQsS","Mkgy8dmoS7","gtCA5OHaBz","pmeCd45cIH","wDajXfaHir","TXQ0ZOUqFM","K4GS8ru4UG",
-"W3VFHfLNg8","oGu6x45cIH","hSSvQHlUbF","y94nwkZANm","0YAGHoGu6x","M6qcGMmsIo","uPX7GJRJQB","MGlTFlViBv","CNHmv0PktI","iKqhrEOE1o",
-"cQOnvfFDrJ","JXljWMezSW","iqv4kyvOMI","CIShG5IhmG","ru4UGNxx9V","lj07Q7Ow5C","HlUbFZv7z0","Z4I1vyToGW","hE1QlfcJOy","DG4sTgdQsS",
-"CK5W7S2Dfu","Waim6HRxd8","lH1ktTCgPp","Yf2EcgdQsS","5nmWvYOfrY","EdBKcWreyP","bZLvSd7vjM","1j5L88cVD3","lCMxyoVQp6","9XyT90PktI",
-"4dEz6zqH0W","Cp3mZ2DREs","TwanoW3VFH","9XyT907n1c","jzUqRe6e4z","nFqik5drc6","7lUXZEOE1o","2DREshE1Ql","RkQkegf8rI","t98iWAgJHQ",
-"pAhR1LewvM","dmoS7NcICA","9iGoTrz7Ut","gIYvEatef2","FLsphIjTwP","gf8rIk85Ae","K20wKd7vjM","b29RJRpBQm","wiHrZpWiOs","L7cGcM6qcG",
-"oGu6xyofH3","CxVEf48cHL","StlDJP6bcg","Cfgr3GWqqX","pmeCd7fKYU","PYBf4yluBx","RBhp0piJSk","AgJHQCxVEf","ydG8UuAWyp","0YAGHn1pmO",
-"VLTy6EOE1o","Gv3FqzFgtB","WDVWJqQxHP","atef2gtCA5","pT8wu9rlg9","dpe1vDQimp","mz8gxs93Ml","5Drn07ku1p","t98iWwiHrZ","5iGN5PYBf4",
-"29QAzgtCA5","L7cGcNhXdu","618DiDLhzM","Oz8yZWmadA","a00b5JJs5m","cmXIX9XyT9","L7cGcrKDLJ","Zv7z00YAGH","lm0pDn1pmO","EOE1omX2GE",
-"Oz8yZn8pJ9","t59lRlH1kt","mX2GEOUqFM","7hyVvVjCZq","7ku1pn8pJ9","I7p2aRsQUq","Gv3Fqsoy9t","FPfSEiKqhr","uJScXuJScX","9iGoT0Kyfs",
-"zbIYYL7cGc","2hEEUAmdQd","55rfB7lUXZ","jzUqRYjB9t","8xEKzogLgc","BCxeC5Namm","WaWsvZzJHW","GrDg7HzZT8","3weIFMmsIo","rz7Ut0h1b1",
-"Nxx9Vd85a9","8FmFHYOfrY","Ta8f6ix74r","FhtgllXFOB","0BmCypT8wu","HfyNQ7fsYM","pvgjSuupzk","9rlg9FPfSE","sqVrfCNHmv","fLNg8jSjS3",
-"W7cTsL7cGc","07n1cWreyP","yToGWaFFss","okgRiWMiS3","0MR5X45cIH","StlDJoVQp6","pT8wuP6bcg","oQ87rjzUqR","UlU3Mlm0pD","fcJOyyvOMI",
-"azIWp29QAz","0KyfsVIlwP","9y4lwlsQGo","uLtKsiwzGk","0ao3leuZA5","7ku1pKsjRK","QChxszqH0W","VBjhzi3pyd","9XyT9okgRi","RkQkeNAFuw",
-"HRxd8VBjhz","suY4xn1pmO","ciuWzC2Irc","RpBQm07n1c","WPmlxZJTXH","sqVrfCK5W7","jzUqRsqVrf","FnPFBfaHir","hYBCKqUJMd","MaJQs5ZaEz",
-"5nmWvJKWYR","x3LDeWmadA","TwanonlaBy","1j5L8i3pyd","FhtglpFrrl","jiVBPk85Ae","FFDuitaOXK","v2eC3lCMxy","FhtglcShY2","y94nwjzUqR",
-"SbRYySjskQ","AmdQdciuWz","QnJ1SfmIK1","lH1ktv1Hln","pv0i7618Di","i3pydYOfrY","uJScXv1Hln","QChxsaez9y","M6qcGJXljW","6AFT0ogLgc",
-"qaofN2TRI7","pAhR12ZHdk","kB5nP1j5L8","XyPZNbrhlQ","Dz1R39iGoT","tlILtoGu6x","fqypy9rlg9","iwzGkpmeCd","ogLgcpmeCd","KsjRKfcJOy",
-"zqH0WcmXIX","B3qemVIlwP","djsrvZ4I1v","xXTI4ydG8U","pmeCdKZamH","ix74ruLtKs","uvf7AFVMxo","16lHc5drc6","aFFssWPmlx","euZA5G1RhS",
-"2ZHdk8xEKz","iB08l1j5L8","yToGWQssNC","FNYIMB3qem","ksJbyAIYUu","Q6LixZhwG1","djsrvNo0Qb","Mm8siAOgEe","aL6AJtvdkD","lXFOBtaOXK",
-"qQxHP0MR5X","FnPFBWaWsv","NcICAksJby","D6rByWMiS3","Ta8f6uZPqg","MK07Y07n1c","1v5hHb29RJ","dQ586n8pJ9","M3zXLHRxd8","UlU3MQ6hMC",
-"nlaByPYBf4","YOfrYBbwgA","FNYIMkZANm","14FLR580YD","faHir2DREs","AIYUuC2Irc","0PktIiB08l","VIlwPuupzk","ThjNnWMiS3","oGu6xS2Dfu",
-"lXFOBCxVEf","qQxHPt98iW","580YDlCMxy","uAWypl83Ud","P6bcg8hJdt","FGzgp7fsYM","B3qemMGlTF","POUYS0MR5X","P6bcg07n1c","WreyPFNYIM",
-"hYBCKVerEA","iqv4kxXTI4","M6qcGoVQp6","uZPqgY1mC0","pv0i7C2Irc","618DiAkKTk","rz7Ut29QAz","Y1mC0dhSuH","4W0TllweGy","nFqikI7p2a",
-"F6PT20Kyfs","618DiuZPqg","0KyfsPb1pa","azIWptl72W","Qworu8FmFH","n8pJ9G1RhS","lXFOB5drc6","Q6hMCFjHXR","NhXduAOgEe","d85a9rz7Ut",
-"azIWpVBjhz","0ao3l0BmCy","Yf2EcfaHir","ReKEWlweGy","HfyNQVjCZq","Ta8f65nmWv","Chuy3vOqCE","ksJbyoGu6x","DG4sTzqH0W","MmsIolH1kt",
-"KASQ86q6L9","XyPZN5IhmG","faHirHfyNQ","FVMxofcJOy","NAFuwdQ586","GrDg7Mkgy8","yvOMIEoToP","nFqikgdQsS","5ZaEzv2eC3","BbwgAK4GS8",
-"ECMvUy94nw","BFkb8jiVBP","Nxx9VOUYuF","v8yFNSbRYy","VBjhzSjskQ","5IhmG618Di","5iGN5QssNC","jSjS3lXFOB","pvgjSKZamH","BGaQYsuY4x",
-"1v5hHTa8f6","StlDJhi5X7","I7p2a7fKYU","NOHszMmsIo","n8pJ9ReKEW","CNHmv3otm6","D6rByAmdQd","vOqCEZUnqt","GSQwjUlU3M","4dEz6yvOMI",
-"CqqaDgjUTu","CdyBVYjB9t","iwzGkjS1aj","ru4UG8FmFH","k85AeRBhp0","1LB1LMezSW","Mkgy8CIShG","8hJdtFhtgl","euZA5B3qem","a00b516lHc",
-"HzZT8FPfSE","MojnPMK07Y","xciqpM3zXL","KASQ8KASQ8","aL6AJb29RJ","8cVD3x3LDe","e6e4zOxWIH","8FmFHCfgr3","zz4ZUfLNg8","0Wr5yReKEW",
-"IBe8kBbwgA","4W0TlhE1Ql","zz4ZUB3qem","55rfBNAFuw","hYBCK0h1b1","Ta8f6JXljW","SmGzvL7cGc","FVMxo0PktI","No0QbazIWp","9eoRcNxx9V",
-"AgJHQKZamH","VerEAhSSvQ","QssNCd85a9","okgRi5IhmG","MK07Y1v5hH","U3yw5i7WMQ","RpBQmhSSvQ","Yw2oUsuY4x","6AFT0AmdQd","GXdoH3weIF",
-"sx5GlbrhlQ","FLsphFGzgp","9y4lwfcwDa","MaJQswiHrZ","K20wKuJScX","yvOMIK20wK","L7cGclsQGo","yofH3AkKTk","pWiOsDz1R3","7fsYMulk41",
-"K4GS8aez9y","ZJTXHxReec","5ZaEzMGlTF","DcpWByToGW","RmDcrJJs5m","YOfrYS77LH","Ul4a1bgJAz","DG4sT9y4lw","hSSvQfmIK1","Dz1R3piJSk",
-"uoStw55rfB","6q6L9MezSW","CK5W7FVMxo","l83Udlj07Q","NAFuwKASQ8","W3VFHAXpwE","MmKGJGWqqX","rhl0JRBhp0","QClRLYw2oU","oVQp6cL0aE",
-"K4GS8FwEJz","5NammyvOMI","zz4ZUv8yFN","uLtKsMkgy8","AgJHQMezSW","BCxeCKr8ys","zqH0WuJScX","DQimpGrDg7","MmKGJoGu6x","bZLvSBGaQY",
-"OHaBzogLgc","5VZjS7fKYU","cmXIXGXdoH","RpBQmSs0Zu","NOHszRsQUq","0ao3le6e4z","J2mQi5Namm","EdBKcSjskQ","uoStwdQ586","LbRTHyvOMI",
-"v1HlnWMiS3","FNYIMtvdkD","48cHLv1Hln","0KyfsqQxHP","xReecUvlv4","wiHrZx3LDe","HzZT8cQOnv","JJs5m2hEEU","uJScXnFqik","5nmWvXyPZN",
-"okgRi0Kyfs","l83UdFNYIM","Zv7z0GWqqX","fmIK1pAhR1","JRJQBDQimp","fcwDadjsrv","nFqiks7Mxk","55rfBMkgy8","BbwgAYw2oU","xReecksJby",
-"pT8wurKDLJ","zQt6QF6PT2","OxWIHKASQ8","WmadA2Yz7E","5drc6618Di","d7vjMwDajX","n8pJ9iwzGk","OHaBzpWiOs","FVMxoCIShG","WPmlx8hJdt",
-"hUTw7J2mQi","dpe1vOUYuF","VjCZqjfREu","FnPFBLDk6f","CqqaDciuWz","ZuDtDWDVWJ","EoToPzbIYY","S2DfuQYxC0","t98iWMmKGJ","ZzJHW7X3uy",
-"he9IA55rfB","xciqpWreyP","8FmFHwDajX","YjB9tW7cTs","55rfB5IhmG","blLA9ZJTXH","Mkgy8OUqFM","8U2nU0MR5X","BGaQY8xEKz","LbRTHDQimp",
-"HlUbFpWiOs","POUYSQ6Lix","zFgtBlm0pD","cShY25nmWv","SWfouThjNn","DG4sTUl4a1","ZJTXHa00b5","14FLRUvlv4","h1zcHCK5W7","FPfSEwiHrZ",
-"GWqqXdQ586","9y4lwgIYvE","ix74rzmLYD","uZPqg7ku1p","i3pydpmeCd","M3zXL2Yz7E","JKWYReuZA5","xReecIBe8k","QnJ1SBbwgA","gdQsSzbIYY",
-"8TxD7cL0aE","0YAGHQworu","uLtKsWaWsv","DQimpjzUqR","JRJQBbrhlQ","Uvlv4kB5nP","SWfouWmadA","JJs5m0BmCy","ThjNnaez9y","d85a9AmdQd",
-"pvgjS5iGN5","Chuy3nnP8o","ECMvUBbwgA","RsQUqYh1hF","l83Ud5Drn0","Vprf2POUYS","pv0i7jfREu","1v5hHReKEW","lCMxyReKEW","aDGtSwiHrZ",
-"Chuy3AOgEe","WreyPlj07Q","Gv3FqQbxXc","zY1GYjzUqR","pWiOsaDGtS","Oz8yZ5VZjS","Nxx9VxReec","ulk41cShY2","Cp3mZZUnqt","XflUqIBe8k",
-"5drc6gjUTu","J2mQiYOfrY","Nxx9Vo8Uyd","F6PT27ku1p","wiHrZ7fKYU","aL6AJcmXIX","M3zXLyToGW","QnJ1Stl72W","Ta8f6KZamH","8FmFHIBe8k",
-"Zv7z09XyT9","iB08lYjB9t","k85AePb1pa","HlUbF5drc6","16lHcdjsrv","guMb8DG4sT","guMb81LB1L","JJs5mulk41","8TxD7ZhwG1","m4bxU0MR5X",
-"Yw2oUDQimp","rz7Ut5Namm","Ta8f6cQOnv","D6rBylXFOB","5ZaEzFNYIM","Q6LixFNYIM","5NammzmLYD","VjCZqZUnqt","v1HlnDz1R3","prNT6DcpWB",
-"WDVWJIBe8k","POUYSIn3NS","n1pmONo0Qb","7fsYMK20wK","zY1GY0PktI","nnP8o5Drn0","ix74r1v5hH","JkzUnQYxC0","nlaByQbxXc","S2DfufmIK1",
-"aFFssAIYUu","Zv7z0JIqXi","SmGzvF6PT2","iKqhruJScX","HfyNQGWqqX","2ZHdkfmIK1","5IhmG14FLR","k85AegdQsS","sqVrfNOHsz","ZuDtDVBjhz",
-"o8Uydh1zcH","K20wKM3zXL","U3yw5JRJQB","uoStwDG4sT","AIYUuMojnP","dmoS7FFDui","yvOMI9eoRc","AkKTkfFDrJ","GXdoHEoToP","DcpWBIBe8k",
-"HRxd8pWiOs","XyPZNulk41","iwzGk7Ow5C","4W0TlTa8f6","y94nwRmDcr","Uvlv4fmIK1","FNYIMS2Dfu","n1pmORBhp0","uZPqgKsjRK","s93MluPX7G",
-"CNHmvHlUbF","ogLgcv8yFN","n1pmOReKEW","QChxsix74r","BbwgAgIYvE","W3VFHxReec","Oz8yZUvlv4","UmaEvpFrrl","fmIK1aDGtS","euZA5rz7Ut",
-"JJs5muTacx","hE1Qlfqypy","XyPZNazIWp","0ao3latef2","wiHrZCIShG","pmeCdtuDyS","StlDJNo0Qb","aFFssQssNC","5ZaEzOUqFM","uQIczcmXIX",
-"soy9tQWxoT","zHF1qVLTy6","7hyVvEOE1o","tl72WcShY2","kZANmnFqik","gjUTuJJs5m","ix74rnlaBy","lpF6WFGzgp","s93MlQbxXc","NhXduIRh48",
-"Pb1pa45cIH","9rlg9fcJOy","P6bcguZPqg","QChxs0h1b1","9y4lwMmKGJ","HP433AkKTk","iqv4kru4UG","ix74rgf8rI","WDVWJRsQUq","d7vjMfqypy",
-"t59lRtjQxs","WDVWJ45cIH","CqqaDpv0i7","Uvlv44QMc9","FcWrWYOfrY","okgRiAXpwE","nnP8otvdkD","azIWpQWxoT","HP433FLsph","wiHrZEdBKc",
-"faHiri3pyd","P6bcgfLNg8","nlaByQClRL","O3iyQgf8rI","zHF1q1j5L8","IjTwPmz8gx","7ku1pbrhlQ","RsQUqlCMxy","uupzkkZANm","fcJOyguMb8",
-"i3pydQssNC","d7vjMb29RJ","lXFOBhE1Ql","bgJAzMK07Y","Oz8yZtuDyS","IKxdLChuy3","WmadAhe9IA","ru4UGQYxC0","7hyVvtaOXK","yEfy9djsrv",
-"Q6hMCRxrsm","K4GS80Kyfs","n8pJ9m4bxU","y94nwFxX9q","ru4UGFwEJz","a00b51LB1L","iKqhrMkgy8","pT8wusx5Gl","S77LHEOE1o","JRJQBAgJHQ",
-"prNT6VBjhz","WaWsvlXFOB","faHirIjTwP","jtn0Xv2eC3","ZJTXHhE1Ql","Ul4a1Yw2oU","2ZHdkWMiS3","2Yz7E24ARF","soy9tazIWp","8xEKzUlU3M",
-"W3VFHcShY2","gjUTuFVMxo","SmGzvFnPFB","C2IrcMK07Y","Oz8yZHzZT8","NOHszgtCA5","guMb8CNHmv","lViBvdhSuH","zmLYDPOUYS","lm0pDiqv4k",
-"Uvlv4VIlwP","7ku1pF6PT2","jeskSpiJSk","5Drn0cShY2","yluBxrz7Ut","M3zXLVerEA","CK5W7M3zXL","nFqikBFkb8","MGlTF0ao3l","FwEJzxXTI4",
-"Uvlv4taOXK","Yh1hFMojnP","vLsmS7ku1p","cQOnvTCgPp","ulk41t98iW","ru4UGVprf2","s93MlVerEA","uJScXuPX7G","AOgEeVjCZq","fcwDapmeCd",
-"DQimpVLTy6","9XyT9J2mQi","gIYvEuAWyp","azIWplH1kt","CNHmvFVMxo","SWfouh1zcH","jS1ajM6qcG","Ul4a12Nslm","cQOnvEoToP","Gv3FqFwEJz",
-"KZamHfmIK1","he9IAuLtKs","EdBKc5iGN5","pWiOs16lHc","Yf2EcqQxHP","blLA9lViBv","d7vjMNxx9V","d85a9RzaZA","iKqhrPb1pa","m4bxURxrsm",
-"MK07YJkzUn","suY4xlkMUA","AXpwE0YAGH","Yh1hFTa8f6","taOXKvkCHH","QssNCRpBQm","hSSvQ5VZjS","2TRI7CqqaD","soy9tStlDJ","Gv3Fq9y4lw",
-"OxWIH5iGN5","G1RhSaDGtS","dhSuH7fsYM","Kr8ys5VZjS","ZhwG1Vprf2","DG4sTRzaZA","SbRYy5Namm","FNYIMLDk6f","1v5hHix74r","dQ5860ao3l",
-"ThjNnpmeCd","b29RJAOgEe","zqH0W5iGN5","VerEAoQ87r","7ku1pM6qcG","uZPqgsoy9t","DQimpI7p2a","s4786AXpwE","Ss0ZuS2Dfu","v8yFNVjCZq",
-"Waim6djsrv","RBhp0Vprf2","iB08lcShY2","iqv4k9rlg9","FNYIMjSjS3","9rlg96q6L9","MK07YLewvM","jzUqRvOqCE","ksJbyvOqCE","Q6LixxReec",
-"t98iW5ZaEz","POUYSVNCPd","tlILtyluBx","prNT6RpBQm","pv0i7Twano","oGu6xCIShG","OHaBzx3LDe","y94nwKZamH","FjHXRJXljW","YjB9tWaWsv",
-"JRJQBEdBKc","Rxrsma00b5","gjUTu64s8N","2DREs8RCUA","xciqpJIqXi","24ARFAIYUu","Waim6S2Dfu","guMb8ThjNn","iB08lZJTXH","aL6AJMmsIo",
-"OHaBzQ6hMC","e6e4zs7Mxk","vOqCEBCxeC","QChxs5IhmG","8RCUAqUJMd","lj07QtAOsr","dQ586hE1Ql","8hJdtyEfy9","lViBvvLsmS","euZA5b29RJ",
-"lViBvaFFss","Uvlv4v8yFN","h1zcHjeskS","WMiS3tl72W","7lUXZKsjRK","HlUbFokgRi","MmKGJhUTw7","ulk41b29RJ","2NslmQChxs","DcpWBSmGzv",
-"Kr8ys5drc6","vkCHHi7WMQ","uAWype6e4z","ogLgcECMvU","gf8rIrKDLJ","FcWrWmX2GE","euZA5Yw2oU","qQxHPpiJSk","55rfBmX2GE","WPmlxlweGy",
-"Zv7z0Pb1pa","7ku1pRpBQm","8cVD3DLhzM","s7MxkFcWrW","blLA9Mm8si","bgJAzfFDrJ","pvgjSQ6hMC","QWxoTCp3mZ","XflUqTwano","pT8wu24ARF",
-"HlUbFx3LDe","EOE1olViBv","NhXduWMiS3","iwzGkt98iW","YjB9tuupzk","vOqCEHfyNQ","IRh48ZzJHW","XflUqjzUqR","oVQp62Yz7E","KZamHOUqFM",
-"9y4lw0Kyfs","SWfouXflUq","GWqqXFLsph","9iGoTXflUq","ni2v15Drn0","aDGtSQChxs","n8pJ9zFgtB","XyPZNMezSW","zmLYDhUTw7","CxVEfpWiOs",
-"3weIFnFqik","8U2nUXflUq","uvf7A2DREs","aDGtSWMiS3","uLtKszQt6Q","JXljWDcpWB","WDVWJ8cVD3","M6qcGCp3mZ","nlaByDLhzM","piJSkRmDcr",
-"lsQGo7hyVv","SbRYyoVQp6","RBhp0D6rBy","MGlTFvkCHH","yToGWVjCZq","2hEEUogLgc","VerEA8U2nU","O3iyQRmDcr","d85a9HfyNQ","K20wKUmaEv",
-"pAhR1fLNg8","FjHXRL7cGc","ksJbyi3pyd","Ul4a1Cp3mZ","JXljWogLgc","faHirMK07Y","fmIK1rKDLJ","64s8NAgJHQ","CK5W7RzaZA","G1RhStAOsr",
-"5IhmGQChxs","BFkb8zQt6Q","O3iyQi3pyd","guMb85drc6","NcICABpYhV","M6qcGd85a9","MezSWjtn0X","QWxoT4dEz6","FNYIMwiHrZ","gjUTufLNg8",
-"oGu6xYOfrY","MezSWhSSvQ","dmoS7TCgPp","K20wKrz7Ut","0YAGHVLTy6","K4GS8EoToP","FGzgp8TxD7","AgJHQQnJ1S","5nmWvokgRi","jtn0Xix74r",
-"7ku1ptAOsr","8hJdtUmaEv","FNYIMGXdoH","okgRix3LDe","Vprf2VIlwP","l83Ud45cIH","StlDJZv7z0","s4786lweGy","9eoRcJIqXi","5iGN5CNHmv",
-"Yh1hFFxX9q","GSQwjZUnqt","5nmWvDQimp","v2eC3tAOsr","IRh48piJSk","B3qemMkgy8","5iGN59rlg9","t98iWuN6r3","9XyT9zY1GY","TwanoksJby",
-"faHir2ZHdk","aL6AJydG8U","tl72WPOUYS","StlDJzmLYD","6q6L9RACuj","S2Dfu48cHL","gtCA5ZUnqt","2DREsMGlTF","ru4UGJkzUn","mX2GEDQimp",
-"nlaBySWfou","0YAGHuPX7G","KASQ829QAz","Chuy3NcICA","3otm6ciuWz","l83UdM3zXL","e6e4zQClRL","cmXIXLDk6f","KASQ8dQ586","Vprf2vkCHH",
-"ZUnqt5Mg9r","WMiS3nFqik","9iGoTsx5Gl","ReKEW48cHL","IjTwPjzUqR","jiVBPmX2GE","F6PT2JRJQB","prNT6xXTI4","QbxXca00b5","Cp3mZBpYhV",
-"BbwgAQworu","3otm6MK07Y","mX2GEyToGW","lCMxy9y4lw","Nxx9VQClRL","5Drn0djsrv","Gv3FqzHF1q","FFDuiazIWp","KASQ8CqqaD","suY4xQbxXc",
-"lkMUAMaJQs","oQ87rNxx9V","BbwgA9XyT9","AkKTkuupzk","jSjS3BbwgA","QworuX6Pin","FwEJzW3VFH","CNHmvlj07Q","Z4I1vtjQxs","W3VFHgf8rI",
-"BCxeCuN6r3","ulk41580YD","KASQ89rlg9","xXTI4pAhR1","tvdkDpmeCd","jiVBPlCMxy","uLtKsAkKTk","S2DfuVIlwP","5VZjSFcWrW","soy9t9y4lw",
-"LDk6fMmKGJ","sx5GlTCgPp","Mm8siSmGzv","8xEKzJXljW","CdyBVPYBf4","9eoRcRBhp0","NOHszJkzUn","vOqCEFwEJz","vLsmSnFqik","qQxHPMojnP",
-"pWiOsECMvU","IjTwPaez9y","8TxD7CNHmv","B3qems7Mxk","OxWIHMK07Y","piJSkWaim6","s4786Mkgy8","oVQp6ZJTXH","jS1ajEOE1o","hE1Qlru4UG",
-"xXTI44dEz6","Gv3FqQClRL","v2eC3s7Mxk","QYxC0okgRi","h1zcHBbwgA","i3pydS2Dfu","zQt6QRmDcr","3otm61v5hH","GrDg7AIYUu","o8Uyd7ku1p",
-"aL6AJK20wK","QYxC0WMiS3","zFgtBbrhlQ","IRh48tlILt","tvdkDFLsph","Dz1R3faHir","KZamHUlU3M","M6qcGrhl0J","9eoRcbZLvS","UmaEvmz8gx",
-"uAWyp5ZaEz","9iGoTJXljW","OUYuFlsQGo","cQOnvjS1aj","48cHLDQimp","aL6AJqQxHP","DLhzMtjQxs","GSQwjtvdkD","Zv7z0M6qcG","EdBKcrhl0J",
-"5IhmGhSSvQ","jiVBPFjHXR","Zv7z0Zv7z0","lCMxyM3zXL","azIWpuTacx","rhl0JK4GS8","AgJHQy94nw","Yw2oUMK07Y","HzZT8SjskQ","bZLvS8RCUA",
-"ydG8U8cVD3","FjHXRrKDLJ","fcwDavLsmS","MaJQsJRJQB","7ku1pGXdoH","dQ586ZzJHW","8FmFHQClRL","07n1cn8pJ9","e6e4zBpYhV","Ul4a1fFDrJ",
-"Yf2Ec9y4lw","HRxd8vLsmS","jS1aj9GXkX","lweGyQbxXc","RBhp0dQ586","8U2nUJXljW","lweGyY1mC0","x3LDeguMb8","jfREuuTacx","fLNg8Waim6",
-"YjB9tZUnqt","FFDui8xEKz","zmLYDblLA9","zz4ZUqaofN","djsrvSWfou","8FmFHn8pJ9","pWiOso8Uyd","lkMUAF6PT2","HlUbFfqypy","Chuy3zHF1q",
-"QnJ1SU3yw5","faHirOUqFM","oGu6xh1zcH","2hEEUAgJHQ","gf8rIG1RhS","OHaBzRxrsm","3weIFuJScX","ksJbyeuZA5","ciuWz4dEz6","fLNg8v8yFN",
-"8TxD7RpBQm","24ARF8TxD7","6AFT0fLNg8","xXTI4lXFOB","Yh1hF5ZaEz","FPfSEO3iyQ","LewvMBGaQY","xReecAIYUu","i3pydhYBCK","MmKGJNcICA",
-"POUYShE1Ql","07n1c55rfB","M3zXLTCgPp","4dEz6nFqik","uPX7GnlaBy","RxrsmpiJSk","RpBQmt59lR","XflUqazIWp","qQxHPciuWz","TXQ0Zs93Ml",
-"IRh48Nxx9V","No0QbyofH3","ThjNnhi5X7","1LB1LlpF6W","kB5nPd85a9","fFDrJt59lR","qQxHPlViBv","8U2nU1v5hH","bgJAzoGu6x","0BmCy7fsYM",
-"L7cGcQbxXc","ReKEW8FmFH","M6qcGYw2oU","8RCUAGXdoH","5Drn03weIF","5nmWvzz4ZU","Uvlv4kZANm","No0QbHRxd8","WPmlxIRh48","4dEz6CqqaD",
-"MojnPsqVrf","Chuy3JIqXi","Cfgr3YjB9t","l83UdNcICA","07n1ct98iW","bZLvSHlUbF","1LB1LsuY4x","5drc6aL6AJ","FPfSEgIYvE","Mkgy8pv0i7",
-"5ZaEzzHF1q","Ul4a1brhlQ","Mm8siStlDJ","FGzgpHfyNQ","zbIYYjSjS3","v1HlnQYxC0","h1zcHQssNC","IKxdL9y4lw","S2Dfu3otm6","WMiS3EdBKc",
-"v8yFNWaim6","FPfSEVjCZq","QClRLNhXdu","HzZT8gtCA5","XyPZNqQxHP","lm0pDuAWyp","pWiOsfaHir","hUTw7CdyBV","RpBQmJkzUn","uZPqgAXpwE",
-"DQimp9y4lw","k85AecShY2","uvf7A9iGoT","aL6AJqUJMd","MmsIoW3VFH","uvf7AJRJQB","uTacxStlDJ","45cIHgIYvE","Yh1hF0PktI","QWxoTZzJHW",
-"tAOsrtjQxs","SWfou4dEz6","ni2v1hSSvQ","atef22TRI7","3weIF8cVD3","4QMc9zz4ZU","t59lRQbxXc","rKDLJ5ZaEz","bgJAzzqH0W","ulk41s7Mxk",
-"xReecaFFss","WMiS38cVD3","0ao3l1v5hH","HRxd8vkCHH","tuDySX6Pin","s4786gf8rI","ReKEWCp3mZ","POUYSRxrsm","cQOnvSbRYy","Chuy3a00b5",
-"Yf2Ec5Drn0","d85a9l83Ud","8TxD7gf8rI","xciqpPb1pa","RBhp0JJs5m","yluBxaez9y","iqv4k7X3uy","i7WMQru4UG","1LB1LBCxeC","QWxoTt59lR",
-"ZhwG1ZJTXH","LewvMQYxC0","GXdoHtaOXK","OUYuFFVMxo","MaJQszbIYY","NOHsz4W0Tl","prNT6EdBKc","jtn0XkB5nP","5Namm8U2nU","lsQGoCdyBV",
-"NhXdu2Nslm","Z4I1vJIqXi","zqH0WdQ586","5Mg9rKsjRK","Yw2oUJKWYR","uQIczh1zcH","G1RhSwDajX","tlILt4W0Tl","2DREspmeCd","soy9tOxWIH",
-"CxVEf55rfB","8RCUAyvOMI","7lUXZFnPFB","yofH3CK5W7","1LB1LiB08l","14FLRUlU3M","gtCA53weIF","29QAzCIShG","CNHmvK20wK","29QAzzmLYD",
-"5VZjSatef2","6AFT0uN6r3","RsQUqoGu6x","55rfB0YAGH","AOgEeCIShG","oGu6xt59lR","In3NSW3VFH","55rfBVBjhz","VjCZqOUYuF","OUqFMCK5W7",
-"VerEAHlUbF","JJs5mWPmlx","AXpwE2Nslm","HP433lweGy","pT8wuQChxs","tAOsr580YD","Yh1hFm4bxU","zY1GYL7cGc","sqVrfQClRL","FjHXRiB08l",
-"AIYUuyvOMI","24ARFZv7z0","RBhp08FmFH","IRh48FVMxo","uoStwZv7z0","FxX9qRBhp0","BbwgACdyBV","QworuguMb8","guMb8v1Hln","kZANm7fsYM",
-"pvgjSY1mC0","bZLvSEdBKc","l83Udhi5X7","VjCZq8TxD7","s4786n1pmO","CdyBVCfgr3","KASQ8AOgEe","vLsmSh1zcH","O3iyQxciqp","RxrsmJKWYR",
-"LewvMyvOMI","fcwDaD6rBy","ydG8U7hyVv","v8yFN9iGoT","SWfouMm8si","gdQsSjSjS3","8RCUAtl72W","d7vjMHP433","AmdQda00b5","AIYUuD6rBy",
-"azIWpSWfou","tAOsrOUqFM","RsQUqHRxd8","d85a90Wr5y","MGlTFhSSvQ","DG4sTFPfSE","64s8NogLgc","VjCZqhUTw7","55rfBPOUYS","DQimp0PktI",
-"BpYhVStlDJ","8xEKzZzJHW","bZLvS7lUXZ","JIqXi0BmCy","zmLYDGSQwj","e6e4zksJby","SmGzvFjHXR","AmdQdWaim6","fcJOyEdBKc","7lUXZQChxs",
-"o8Uyd1LB1L","8cVD3CIShG","suY4xcShY2","QChxsGv3Fq","48cHLsoy9t","ZJTXHFGzgp","jiVBP8U2nU","MaJQs5Namm","pFrrl2hEEU","ulk41QChxs",
-"tl72WLDk6f","O3iyQlpF6W","yToGWn1pmO","AIYUuv1Hln","lH1ktNo0Qb","nFqik580YD","Vprf2xXTI4","RmDcrpAhR1","vkCHH8FmFH","zQt6QGWqqX",
-"i7WMQJKWYR","7Ow5CguMb8","gtCA5lsQGo","BbwgAYh1hF","sx5Glv1Hln","0KyfsyofH3","euZA5mz8gx","Mm8si7Ow5C","xciqpIn3NS","faHirgIYvE",
-"ZhwG1wiHrZ","MaJQsru4UG","jiVBPS77LH","jeskSokgRi","tuDySa00b5","oVQp6y94nw","FPfSEVprf2","Oz8yZSWfou","GXdoHuZPqg","vkCHHyEfy9",
-"QnJ1SPYBf4","HP433AIYUu","aez9y9y4lw","PYBf4nnP8o","uAWypQnJ1S","AIYUuxciqp","XflUqFFDui","cQOnvKr8ys","S2DfufFDrJ","uN6r3ReKEW",
-"HP433WmadA","9rlg9Oz8yZ","KASQ8zmLYD","S2DfuzHF1q","6q6L9VIlwP","Dz1R3iwzGk","Mkgy8QWxoT","VIlwPQYxC0","LewvMtlILt","djsrvQYxC0",
-"SmGzvRBhp0","UmaEvDQimp","KsjRKSjskQ","zz4ZUzHF1q","prNT6WmadA","gtCA5iqv4k","RpBQmMGlTF","hUTw7Chuy3","ni2v1wDajX","a00b5Waim6",
-"lj07QyEfy9","Rxrsm7Ow5C","0ao3lQ6Lix","VerEAuJScX","uoStwQ6Lix","FVMxo29QAz","O3iyQtl72W","d7vjMFcWrW","yvOMISWfou","OUYuFFGzgp",
-"pvgjSoQ87r","lweGyzmLYD","JkzUnrz7Ut","taOXKzmLYD","JkzUnfcJOy","QClRLulk41","pFrrlAmdQd","zqH0WOUqFM","0MR5Xrz7Ut","U3yw5J2mQi",
-"Q6hMCYh1hF","FcWrWpAhR1","ru4UG2ZHdk","P6bcgjzUqR","cmXIXatef2","VLTy6zmLYD","KZamHtuDyS","jiVBPkB5nP","NcICAKASQ8","OUqFMGXdoH",
-"0PktI3otm6","QClRLdQ586","zQt6QVerEA","MK07YtvdkD","RBhp0NhXdu","dhSuHFnPFB","IKxdLo8Uyd","24ARFeuZA5","9XyT9t98iW","brhlQVprf2",
-"I7p2aaDGtS","RACujKASQ8","taOXK5ZaEz","Chuy3nlaBy","ZUnqtyvOMI","lXFOBW7cTs","8xEKzbZLvS","LbRTHCNHmv","kZANmZ4I1v","DcpWBzY1GY",
-"M6qcGUmaEv","F6PT2VLTy6","TXQ0ZIRh48","guMb87X3uy","i7WMQuJScX","mz8gxe6e4z","fFDrJjSjS3","AIYUuJXljW","lsQGolkMUA","MmKGJ5iGN5",
-"HRxd8ciuWz","zQt6Q55rfB","EdBKcpT8wu","K20wKcQOnv","ReKEWJKWYR","AmdQdOHaBz","Q6LixFhtgl","mX2GE7Ow5C","VerEAMkgy8","yluBxzbIYY",
-"x3LDeNAFuw","MojnP3weIF","M6qcGuQIcz","yofH3atef2","AOgEeNxx9V","1v5hHzY1GY","48cHLSs0Zu","3weIFFLsph","L7cGc3weIF","o8UydzqH0W",
-"OHaBzuQIcz","24ARFlm0pD","nnP8ohYBCK","ogLgc5drc6","0ao3lIKxdL","FcWrWVerEA","ZuDtDlpF6W","tlILtChuy3","suY4xuupzk","ulk41IjTwP",
-"uupzkjtn0X","k85AejzUqR","No0Qblm0pD","hSSvQx3LDe","lpF6WI7p2a","nlaByThjNn","dQ5869eoRc","wDajXk85Ae","zQt6Q5IhmG","ZuDtDm4bxU",
-"580YDQworu","uN6r3UlU3M","8RCUAOz8yZ","tjQxslpF6W","ZuDtDqUJMd","AgJHQNOHsz","aez9yuN6r3","48cHLrKDLJ","d85a9DG4sT","14FLRlm0pD",
-"o8Uyd5Drn0","AOgEehe9IA","2TRI7pT8wu","dmoS7C2Irc","fFDrJtaOXK","BGaQYlViBv","TwanoQnJ1S","ZhwG1kB5nP","lm0pDQworu","ni2v1QssNC",
-"zHF1qJRJQB","hi5X7tjQxs","29QAzMGlTF","SbRYyfcJOy","RzaZAlj07Q","2ZHdko8Uyd","580YDogLgc","OUqFM5Drn0","J2mQib29RJ","NOHszRkQke",
-"fLNg8uLtKs","pAhR1W3VFH","Q6LixhUTw7","RBhp0BGaQY","Waim6pmeCd","vLsmS8cVD3","a00b5NOHsz","uupzkJ2mQi","9rlg92ZHdk","xXTI4KASQ8",
-"bZLvS5VZjS","64s8N48cHL","2NslmWmadA","AIYUuQYxC0","IBe8kqQxHP","W7cTs1LB1L","zFgtBa00b5","LewvM16lHc","nlaByOUqFM","BGaQYgdQsS",
-"WmadAJKWYR","FnPFBEOE1o","AXpwErhl0J","BFkb8ECMvU","iB08lv8yFN","6AFT0RsQUq","cL0aE16lHc","FxX9q8hJdt","DG4sT2Nslm","hSSvQJJs5m",
-"FxX9q2Nslm","HlUbFMkgy8","dpe1vxciqp","2ZHdkAOgEe","lViBvPOUYS","5nmWvdmoS7","jSjS3J2mQi","4dEz6RzaZA","YjB9tFxX9q","9GXkXZUnqt",
-"HlUbFZhwG1","k85AeYOfrY","SmGzvuPX7G","S2DfuFxX9q","FnPFB4W0Tl","6q6L9WMiS3","7fKYUMK07Y","ydG8U2hEEU","zz4ZUIn3NS","KsjRKzz4ZU",
-"FNYIMlViBv","JRJQBaL6AJ","ZuDtDuoStw","gf8rIlsQGo","NcICAydG8U","AkKTk1v5hH","KsjRKzQt6Q","GXdoHjS1aj","6q6L9rKDLJ","oQ87rZJTXH",
-"1j5L8HRxd8","2ZHdkWDVWJ","ThjNnQbxXc","YjB9tFhtgl","AkKTkyEfy9","MojnPi3pyd","uvf7AFwEJz","NOHszFwEJz","16lHczHF1q","CxVEfSWfou",
-"m4bxUCNHmv","2DREsa00b5","uPX7G45cIH","M6qcGn8pJ9","uvf7AtjQxs","TwanoFhtgl","FjHXRYOfrY","s7MxkyToGW","NhXduPYBf4","Mkgy8ThjNn",
-"64s8NZJTXH","AIYUuFwEJz","618Di7fsYM","jzUqRCqqaD","EdBKct59lR","v2eC3bgJAz","kZANmokgRi","l83UdgIYvE","WPmlxuvf7A","9y4lwzQt6Q",
-"WDVWJn1pmO","lViBvxReec","FxX9qzmLYD","yluBx16lHc","taOXKtaOXK","IBe8kTXQ0Z","fFDrJ8xEKz","FFDui0YAGH","yToGWhi5X7","O3iyQUmaEv",
-"ThjNnatef2","9y4lwlkMUA","4W0TlfcJOy","m4bxU0BmCy","No0Qb48cHL","kZANmFcWrW","GrDg7580YD","t98iWRzaZA","BbwgAS77LH","DQimpni2v1",
-"BbwgA7X3uy","Cp3mZkB5nP","7Ow5CW3VFH","FPfSERACuj","64s8NRACuj","okgRinlaBy","FFDuijS1aj","MojnPb29RJ","U3yw5XyPZN","ThjNnU3yw5",
-"GXdoHX6Pin","Nxx9VpAhR1","7ku1pM3zXL","07n1cMmKGJ","x3LDekB5nP","lweGy5drc6","aez9y5drc6","CNHmvl83Ud","DQimpMGlTF","24ARFP6bcg",
-"QClRLyluBx","HRxd8a00b5","qQxHPZuDtD","TXQ0ZZJTXH","lm0pDFGzgp","JJs5muN6r3","OUYuFqaofN","Q6hMCfcJOy","suY4xjSjS3","Y1mC0Gv3Fq",
-"S2Dfu24ARF","djsrvK20wK","zFgtB14FLR","rhl0Jl83Ud","I7p2aeuZA5","L7cGcqQxHP","8FmFHuZPqg","IKxdLaL6AJ","xciqpXflUq","HzZT8fLNg8",
-"MK07YM3zXL","fcJOyuAWyp","EdBKclpF6W","xReeczz4ZU","GrDg7XflUq","J2mQi2ZHdk","3otm64QMc9","Cp3mZuLtKs","EOE1oAIYUu","xXTI4aez9y",
-"xciqpjiVBP","W3VFHOz8yZ","jtn0XzHF1q","QClRLAXpwE","Q6LixKsjRK","zmLYDSWfou","nlaByK4GS8","3otm6gdQsS","ulk41Vprf2","8cVD3NhXdu",
-"2DREsFFDui","okgRi14FLR","8RCUAmz8gx","FnPFBhi5X7","oQ87rB3qem","dhSuHb29RJ","m4bxURkQke","aL6AJxciqp","1LB1LCdyBV","iKqhrJRJQB",
-"s93MlaFFss","pWiOs7lUXZ","kB5nPS77LH","6AFT08U2nU","aez9y1v5hH","taOXKhUTw7","o8UydGrDg7","vLsmSKsjRK","CIShGpAhR1","wDajXy94nw",
-"BFkb8t98iW","jS1ajFLsph","QWxoTqQxHP","FLsphlH1kt","2Yz7ElCMxy","gjUTuMGlTF","WaWsveuZA5","AIYUurhl0J","t59lRTCgPp","s4786gjUTu",
-"ciuWz5VZjS","azIWpUl4a1","Uvlv4KASQ8","K4GS8VLTy6","tuDyS9eoRc","zQt6QlweGy","suY4xUvlv4","lCMxytAOsr","oVQp6h1zcH","BbwgABpYhV",
-"lpF6WJ2mQi","KASQ83weIF","uupzks93Ml","x3LDexciqp","lViBvv2eC3","5drc6BGaQY","gIYvEhYBCK","pmeCdo8Uyd","MGlTFL7cGc","lkMUAjfREu",
-"0Wr5y5Mg9r","DcpWBrz7Ut","EdBKcCqqaD","C2Ircjtn0X","FPfSEuTacx","9eoRcuupzk","K4GS8CdyBV","VLTy68U2nU","2DREs2DREs","nFqiktAOsr",
-"0ao3lhYBCK","PYBf4m4bxU","POUYStvdkD","xReec0YAGH","PYBf4djsrv","gf8rI8cVD3","ni2v19rlg9","pmeCddhSuH","MK07Y8U2nU","wiHrZb29RJ",
-"0Kyfsmz8gx","ksJbySs0Zu","WMiS3VNCPd","CNHmvUmaEv","MmsIo4dEz6","FcWrWv2eC3","oQ87r4QMc9","wDajXatef2","jSjS3MmKGJ","aez9ytlILt",
-"hi5X7Vprf2","fFDrJBCxeC","Pb1pa55rfB","7fsYMChuy3","FxX9qK4GS8","uQIczHP433","okgRiMmKGJ","16lHcO3iyQ","EdBKcDLhzM","HP433wDajX",
-"5iGN57Ow5C","gtCA5AOgEe","EOE1oTXQ0Z","pWiOsoQ87r","BGaQYFcWrW","FwEJzXflUq","i3pydTa8f6","m4bxUUmaEv","7lUXZtvdkD","BpYhVFVMxo",
-"ZJTXHJIqXi","vOqCEFGzgp","QYxC0S77LH","piJSkJRJQB","FcWrWlViBv","JRJQBpWiOs","W7cTsfaHir","Q6Lix1LB1L","16lHcfLNg8","DQimp1LB1L",
-"prNT629QAz","uoStw5ZaEz","TXQ0ZIn3NS","nFqikzqH0W","Z4I1vuJScX","ZUnqttvdkD","HP433CNHmv","t98iWsuY4x","uupzk2hEEU","piJSkDz1R3",
-"JRJQBQ6hMC","45cIHYh1hF","FVMxoM3zXL","5Mg9rtuDyS","vkCHHjSjS3","VLTy6brhlQ","1v5hHsuY4x","SmGzvGWqqX","FFDuiHzZT8","Yw2oUs4786",
-"l83UduLtKs","GXdoHZzJHW","Cfgr3S2Dfu","In3NSokgRi","7fsYMGrDg7","pv0i7Ta8f6","AkKTkFVMxo","Cfgr3SjskQ","FVMxoNxx9V","guMb8iKqhr",
-"3otm6vLsmS","KASQ8K4GS8","8RCUAD6rBy","7Ow5CWDVWJ","okgRi8RCUA","lkMUAGXdoH","9y4lw3otm6","AOgEeDcpWB","fLNg8618Di","UlU3MYh1hF",
-"l83UdStlDJ","GWqqXWPmlx","e6e4z45cIH","pWiOs580YD","5NammOxWIH","7Ow5CZzJHW","l83UdhYBCK","tjQxsZuDtD","ZJTXHgjUTu","8hJdtrKDLJ",
-"D6rByo8Uyd","WreyPRBhp0","ZzJHWrhl0J","oQ87r9iGoT","dmoS7lkMUA","D6rByRBhp0","ZJTXHb29RJ","4dEz6a00b5","Gv3Fq64s8N","Q6hMCLbRTH",
-"5ZaEzXflUq","1LB1LVIlwP","J2mQiYjB9t","55rfBFjHXR","FjHXRni2v1","ThjNntuDyS","5Mg9rEdBKc","zz4ZUoGu6x","FGzgpCdyBV","0BmCyRACuj",
-"CqqaDaL6AJ","Yw2oUYOfrY","7ku1pdhSuH","zqH0WP6bcg","aez9yMojnP","9rlg9D6rBy","faHirwDajX","Q6Lix9GXkX","2Nslmlj07Q","MGlTFOz8yZ",
-"9rlg9KZamH","B3qemBpYhV","euZA5Pb1pa","14FLRAOgEe","ThjNnFhtgl","QWxoTP6bcg","0KyfslkMUA","FnPFBlkMUA","J2mQiwDajX","2Yz7EZUnqt",
-"FPfSESbRYy","yofH3qQxHP","MmKGJm4bxU","55rfBfqypy","zbIYYn8pJ9","cShY2fcwDa","dmoS7Rxrsm","Chuy3QnJ1S","JIqXiRBhp0","NcICAjzUqR",
-"zz4ZU6q6L9","IBe8kThjNn","FPfSESs0Zu","7X3uyyvOMI","IKxdLcL0aE","okgRiVerEA","VIlwPC2Irc","tuDySjtn0X","zmLYDDcpWB","lCMxydhSuH",
-"lweGylViBv","kZANmpWiOs","VNCPdgdQsS","v8yFN7lUXZ","fLNg8FPfSE","k85Aev2eC3","nnP8ouN6r3","16lHc2DREs","uPX7GzQt6Q","ZJTXHBbwgA",
-"Oz8yZpiJSk","h1zcHGrDg7","ZuDtDk85Ae","yofH3gjUTu","uZPqgWaWsv","blLA9MmsIo","ZhwG1DcpWB","618DiiB08l","5iGN5y94nw","5ZaEzydG8U",
-"ciuWzLDk6f","iB08lfcwDa","S2DfuHzZT8","ZhwG1fFDrJ","Cfgr3JRJQB","zFgtBWaWsv","Cfgr3JkzUn","U3yw5dQ586","ru4UGxciqp","JIqXiaDGtS",
-"HlUbFogLgc","pFrrln1pmO","ZJTXHcShY2","tvdkDCp3mZ","yvOMIYw2oU","2ZHdkMezSW","hUTw7zQt6Q","bgJAznFqik","5drc61v5hH","8FmFHiKqhr",
-"StlDJ5ZaEz","ReKEW1v5hH","rKDLJHRxd8","0ao3ltlILt","n1pmOZzJHW","F6PT2VNCPd","qaofNzz4ZU","1LB1LfLNg8","fcwDayofH3","DQimp618Di",
-"8hJdt5IhmG","uAWyptuDyS","5IhmGVerEA","pWiOsjfREu","Pb1pauAWyp","RmDcrTXQ0Z","5ZaEztuDyS","n1pmOfaHir","5nmWv14FLR","oVQp6RpBQm",
-"FVMxo1j5L8","uN6r3zz4ZU","Fhtgl29QAz","K20wK29QAz","0h1b18FmFH","7fKYUNo0Qb","AXpwEWaim6","pT8wuYw2oU","OUYuFi3pyd","s47865Mg9r",
-"qQxHPa00b5","yvOMIbrhlQ","9eoRc55rfB","VjCZqtjQxs","GXdoHtlILt","U3yw5ECMvU","RBhp0azIWp","yofH3i7WMQ","FnPFBZv7z0","k85AeYjB9t",
-"GXdoHFGzgp","J2mQiGSQwj","OUYuFhYBCK","AgJHQUlU3M","ECMvUHzZT8","oVQp6b29RJ","JXljWcL0aE","djsrvAkKTk","5VZjS7lUXZ","gtCA51LB1L",
-"RzaZAtjQxs","t98iW3otm6","hUTw7Vprf2","RxrsmW7cTs","Yh1hFwDajX","NOHszP6bcg","LDk6f45cIH","ZJTXHv8yFN","Nxx9V7X3uy","TwanoRBhp0",
-"ru4UGLbRTH","uPX7GHP433","oVQp6Rxrsm","xciqp0ao3l","pvgjSn8pJ9","GWqqXPYBf4","9rlg9ZJTXH","SmGzvzHF1q","KASQ8iwzGk","0Kyfs9GXkX",
-"5VZjSRACuj","JJs5mlweGy","x3LDe9eoRc","WmadAGrDg7","HP433a00b5","MGlTFX6Pin","zFgtBpmeCd","y94nw0Wr5y","jtn0XtaOXK","uN6r3uupzk",
-"rhl0JZhwG1","XyPZNMojnP","RpBQmCxVEf","uLtKs4dEz6","okgRiUvlv4","JRJQBFwEJz","jiVBPMGlTF","AmdQdOUqFM","2TRI78cVD3","e6e4zCIShG",
-"lXFOBa00b5","Yf2EcCxVEf","ksJbyMmsIo","HzZT83weIF","29QAzhi5X7","HfyNQuvf7A","mz8gxaFFss","xciqpCp3mZ","XflUq2Nslm","bZLvStaOXK",
-"he9IAFxX9q","o8UydLbRTH","9y4lwOHaBz","euZA5blLA9","0MR5XiKqhr","5Drn0jS1aj","4QMc9AkKTk","EdBKcuQIcz","blLA98cVD3","OxWIHNAFuw",
-"t59lRv2eC3","Rxrsmd85a9","OHaBz4QMc9","tAOsraFFss","sqVrfuTacx","07n1cbZLvS","mX2GE9eoRc","0YAGHqaofN","7Ow5CI7p2a","JXljWv8yFN",
-"jfREud7vjM","n8pJ9FVMxo","x3LDen8pJ9","LewvMFnPFB","ZhwG1JIqXi","Waim6gtCA5","BFkb8FGzgp","O3iyQDQimp","SmGzvQWxoT","0MR5XFLsph",
-"Fhtgl0Wr5y","1LB1LRBhp0","hE1Qluupzk","FxX9q5Mg9r","dmoS7mX2GE","zqH0WjeskS","Mm8siJJs5m","nFqikuupzk","POUYSuoStw","wDajXh1zcH",
-"KASQ8tvdkD","8cVD3wiHrZ","pv0i72Nslm","2TRI7FGzgp","JkzUntjQxs","aFFssgtCA5","ulk41aez9y","uJScXrhl0J","5ZaEzHRxd8","wDajXxReec",
-"VBjhzCIShG","RBhp0ulk41","BCxeCpFrrl","prNT6Nxx9V","0Wr5ylXFOB","ni2v1jfREu","kB5nPnnP8o","aL6AJX6Pin","lsQGo9iGoT","0KyfsZhwG1",
-"lH1ktThjNn","POUYS2hEEU","n8pJ98TxD7","7ku1poQ87r","KZamHG1RhS","XflUqpvgjS","Q6hMCVprf2","VIlwPk85Ae","8cVD3CqqaD","NAFuwCp3mZ",
-"3weIFJJs5m","4QMc9580YD","AkKTkJRJQB","pmeCdRsQUq","azIWphYBCK","I7p2aXyPZN","L7cGcCp3mZ","5Drn0soy9t","IKxdL0PktI","NAFuw5Drn0",
-"JKWYRP6bcg","5iGN5SWfou","iB08lgdQsS","8RCUANo0Qb","k85AeM3zXL","gIYvEAkKTk","FwEJzaFFss","JXljW45cIH","VBjhzTXQ0Z","MmsIoMaJQs",
-"Ul4a1ciuWz","VerEA4dEz6","B3qembZLvS","StlDJdpe1v","jS1ajChuy3","jSjS35VZjS","gtCA5okgRi","uN6r316lHc","RBhp09y4lw","pFrrlLDk6f",
-"aez9yMezSW","EoToPlkMUA","4dEz6K4GS8","aez9y0ao3l","RpBQmQbxXc","fcwDarKDLJ","SWfoucShY2","prNT6wDajX","VLTy6Vprf2","rz7Ute6e4z",
-"mX2GEMojnP","NAFuwFhtgl","BGaQY7lUXZ","8TxD7rKDLJ","RACuj3weIF","07n1cPOUYS","0MR5XJXljW","5Mg9r0h1b1","7Ow5CZv7z0","Ul4a1faHir",
-"NcICALewvM","9y4lw2TRI7","OUYuFuupzk","uPX7GcmXIX","xReecQYxC0","AgJHQVprf2","45cIHfFDrJ","xReecqUJMd","taOXKuPX7G","CqqaD5ZaEz",
-"FGzgppv0i7","G1RhScL0aE","lm0pDfLNg8","F6PT2QYxC0","0ao3lJXljW","8xEKzGXdoH","t98iWd85a9","vOqCE7fsYM","n8pJ9Yh1hF","TXQ0Z5drc6",
-"uvf7Aix74r","G1RhSo8Uyd","HP433lXFOB","ZuDtDguMb8","uPX7GMmKGJ","cL0aE5ZaEz","0BmCycShY2","HlUbFtl72W","8hJdtgf8rI","uAWypdQ586",
-"K20wKzY1GY","d7vjMpv0i7","uJScX07n1c","gf8rI2DREs","QChxs9y4lw","CdyBVfcJOy","VNCPdsqVrf","lm0pDblLA9","D6rByDQimp","KsjRKWDVWJ",
-"QYxC0yluBx","7fsYMD6rBy","5nmWvjSjS3","gdQsSMezSW","piJSkFNYIM","lXFOBvOqCE","JkzUn8cVD3","rz7Utv1Hln","djsrvOUqFM","M3zXLuN6r3",
-"RkQkeWDVWJ","7Ow5CHzZT8","WaWsvrz7Ut","CqqaDUmaEv","B3qemHzZT8","64s8N4QMc9","uvf7A9y4lw","6q6L9lm0pD","FVMxoTXQ0Z","wDajXSmGzv",
-"hYBCKNOHsz","d85a9hE1Ql","zHF1qNo0Qb","FPfSEGSQwj","LewvMx3LDe","KsjRK618Di","nFqikbZLvS","s93MlZ4I1v","9GXkXt59lR","jtn0XhSSvQ",
-"7X3uyaL6AJ","cQOnvFVMxo","0h1b1uTacx","oGu6xs93Ml","oVQp6CK5W7","he9IAlj07Q","JJs5mIn3NS","lm0pDbgJAz","okgRiDcpWB","07n1cZzJHW",
-"8RCUAGWqqX","hUTw7cShY2","WreyPvkCHH","piJSkUmaEv","b29RJkZANm","IKxdLokgRi","Cp3mZYw2oU","0h1b116lHc","7Ow5C24ARF","gjUTuQworu",
-"PYBf4TXQ0Z","tuDySFLsph","faHirmX2GE","lj07Qt98iW","ciuWz7fKYU","0PktI6q6L9","VerEANo0Qb","Uvlv40h1b1","pWiOsa00b5","piJSk5VZjS",
-"OHaBzjtn0X","zHF1qzmLYD","Q6LixNhXdu","okgRiuPX7G","iqv4kIjTwP","45cIHn1pmO","U3yw5JkzUn","FnPFBFnPFB","dmoS7i3pyd","I7p2auPX7G",
-"nlaByAIYUu","YOfrYYjB9t","1LB1LThjNn","oGu6x9y4lw","NOHszUl4a1","pT8wufcwDa","lkMUANhXdu","Q6LixGrDg7","wDajX9rlg9","IKxdLIn3NS",
-"GWqqXIRh48","FjHXR8cVD3","7lUXZuQIcz","Y1mC0O3iyQ","EOE1ociuWz","n8pJ9DLhzM","AmdQdRACuj","jfREud85a9","CqqaDcL0aE","5nmWvfcJOy",
-"BFkb8rhl0J","O3iyQFxX9q","iB08lK20wK","Cp3mZlpF6W","JIqXi2ZHdk","5nmWv5drc6","6AFT0wiHrZ","i7WMQTCgPp","i7WMQjSjS3","Gv3FqHfyNQ",
-"lm0pDL7cGc","HzZT8GrDg7","ru4UGiKqhr","aez9yfFDrJ","S2Dfuhe9IA","FxX9qpiJSk","8RCUAKr8ys","9iGoTGXdoH","MezSWnlaBy","ThjNnNAFuw",
-"JJs5mh1zcH","pv0i7BbwgA","QworukZANm","8xEKz2Yz7E","Qworu7fKYU","S2DfugIYvE","MaJQst98iW","PYBf4x3LDe","lViBvMGlTF","EdBKcQworu",
-"suY4xKASQ8","jSjS30ao3l","FjHXRMaJQs","tAOsruPX7G","Yw2oUs7Mxk","pT8wuReKEW","Chuy3SbRYy","0Wr5yZJTXH","jfREunnP8o","hE1Qle6e4z",
-"Ta8f6uPX7G","pvgjSX6Pin","AIYUugIYvE","NhXduMK07Y","zY1GYoQ87r","FcWrWS77LH","hSSvQBFkb8","QssNC2hEEU","DcpWB9y4lw","v1Hln48cHL",
-"FGzgpZ4I1v","AkKTkVprf2","FxX9qOUYuF","FwEJzSbRYy","ydG8Uhi5X7","L7cGcWmadA","guMb8RmDcr","MojnPXyPZN","uPX7GSs0Zu","aez9yHfyNQ",
-"RsQUqqUJMd","U3yw5atef2","7X3uy2Nslm","MaJQs5VZjS","ECMvUh1zcH","8RCUAQ6Lix","MmKGJgdQsS","wDajXQnJ1S","sqVrfS2Dfu","gtCA5pWiOs",
-"pT8wuW3VFH","Mm8siVerEA","hSSvQt98iW","Nxx9Vs93Ml","BFkb8Yf2Ec","FcWrWM3zXL","MezSWatef2","fFDrJAgJHQ","hUTw7pmeCd","m4bxUd7vjM",
-"blLA9BCxeC","oQ87r5iGN5","0Wr5ydQ586","No0QbNAFuw","LewvMPb1pa","TwanoCxVEf","J2mQiM3zXL","Cp3mZY1mC0","3otm6AOgEe","Yw2oUBbwgA",
-"oQ87r64s8N","HP433n8pJ9","O3iyQWDVWJ","VIlwPOHaBz","VerEAbgJAz","cQOnv14FLR","W3VFHXflUq","ReKEWpWiOs","VerEAuvf7A","POUYSv8yFN",
-"5iGN5RBhp0","uvf7Ajtn0X","Y1mC0djsrv","pT8wuWreyP","uQIczGv3Fq","SWfoux3LDe","WmadAmX2GE","Cp3mZEdBKc","hSSvQY1mC0","QClRL6AFT0",
-"AIYUu2TRI7","zFgtBPb1pa","StlDJi3pyd","4QMc9SbRYy","LbRTHSWfou","zmLYDiwzGk","AkKTkCIShG","In3NSe6e4z","taOXKPOUYS","pAhR10Wr5y",
-"yToGWPOUYS","gdQsS5IhmG","EdBKcFNYIM","ru4UGWaWsv","he9IAKr8ys","AOgEePOUYS","Kr8ysPYBf4","JXljWksJby","VNCPdFPfSE","tlILtb29RJ",
-"gIYvEvOqCE","QYxC03otm6","pFrrlMkgy8","EoToPWreyP","CqqaDhE1Ql","QChxsguMb8","JJs5mQ6hMC","MaJQsLbRTH","d7vjMCxVEf","0MR5Xi7WMQ",
-"kZANmgIYvE","ni2v1OHaBz","nFqik7ku1p","BFkb82ZHdk","lpF6W5IhmG","nlaBysx5Gl","uN6r39GXkX","XyPZN7Ow5C","45cIHVprf2","fLNg8AOgEe",
-"suY4xdjsrv","lCMxyciuWz","POUYSWDVWJ","v2eC3uN6r3","0KyfsGrDg7","he9IAMK07Y","lH1ktjtn0X","brhlQZhwG1","EOE1oUvlv4","lViBvZUnqt",
-"aDGtSrhl0J","uTacx8cVD3","7ku1pMmsIo","Gv3Fq07n1c","dQ586Dz1R3","48cHLAXpwE","l83UdRsQUq","iwzGkQChxs","CNHmv5Mg9r","D6rBy9y4lw",
-"Q6hMCWMiS3","yluBxMGlTF","X6PinZv7z0","tvdkD2hEEU","rz7UtFwEJz","fmIK1FLsph","SWfoucmXIX","nFqikCK5W7","8hJdtDG4sT","BGaQYlXFOB",
-"Zv7z0wiHrZ","OHaBz7lUXZ","lpF6Wuvf7A","9iGoTQbxXc","W3VFHuoStw","lXFOB5nmWv","QYxC0VNCPd","OHaBzMaJQs","i7WMQjS1aj","iwzGk1LB1L",
-"ix74rtl72W","4W0Tlhe9IA","t98iWyEfy9","rz7UtHzZT8","Z4I1vi7WMQ","3weIFiwzGk","1j5L8rhl0J","XflUqC2Irc","kZANmn8pJ9","U3yw50Kyfs",
-"nnP8oQClRL","AOgEelViBv","8FmFHzFgtB","t98iWIKxdL","nlaByd7vjM","0Wr5yP6bcg","QWxoTpAhR1","YjB9tFFDui","RmDcr9y4lw","Q6LixF6PT2",
-"5VZjSxciqp","QChxsvOqCE","PYBf4hi5X7","CK5W7NAFuw","CNHmvi3pyd","24ARFuQIcz","DLhzMfcJOy","PYBf4atef2","b29RJhe9IA","a00b5zqH0W",
-"QbxXc8RCUA","1j5L8vOqCE","BFkb8GWqqX","ZuDtDWreyP","NcICAEdBKc","J2mQiX6Pin","VjCZqhi5X7","8xEKzQworu","FGzgpwDajX","nnP8oi3pyd",
-"F6PT2lkMUA","Y1mC0FcWrW","MmsIoXflUq","8RCUAokgRi","l83UdZ4I1v","S2DfuQWxoT","lViBvOxWIH","HRxd8BbwgA","CIShGNcICA","Yh1hFzmLYD",
-"2TRI7KASQ8","LewvMdhSuH","sx5Gl7Ow5C","Mkgy89y4lw","yluBxUvlv4","fcJOyuTacx","AmdQdyEfy9","14FLRhi5X7","C2IrcM6qcG","P6bcgfcwDa",
-"lm0pDQssNC","IBe8kDcpWB","ECMvUMaJQs","RACujRpBQm","2TRI7Yh1hF","Y1mC0YjB9t","MmKGJuAWyp","1v5hHtaOXK","JkzUnTCgPp","Gv3Fq0Kyfs",
-"atef2cmXIX","5Mg9rLbRTH","pmeCduvf7A","v2eC3zqH0W","7ku1ptjQxs","blLA9jzUqR","O3iyQtaOXK","zbIYY1v5hH","FxX9qGv3Fq","t98iWuupzk",
-"C2IrcFVMxo","JRJQB0Kyfs","cmXIXTXQ0Z","uN6r3dmoS7","RBhp0FNYIM","BFkb8WPmlx","zQt6QkZANm","zbIYYJJs5m","ZuDtD0MR5X","Gv3FqL7cGc",
-"SjskQfcJOy","NOHszzqH0W","8xEKzIKxdL","KASQ8Mm8si","HP433QClRL","2Yz7EYh1hF","wiHrZMK07Y","i3pydTwano","S77LHRBhp0","POUYSix74r",
-"uPX7G6q6L9","S2DfuHlUbF","zFgtBvkCHH","yofH355rfB","zY1GYd85a9","ciuWzVjCZq","zFgtBJRJQB","MmsIoFLsph","uupzk2Yz7E","FhtglHzZT8",
-"NOHszW7cTs","lXFOBPb1pa","uN6r3J2mQi","5iGN5AmdQd","fcJOyPOUYS","dmoS7atef2","FLsphJJs5m","RzaZAm4bxU","faHirlH1kt","OUqFMJJs5m",
-"xReecCp3mZ","Ss0ZuY1mC0","cQOnvOUYuF","7X3uy55rfB","taOXK5nmWv","0YAGHv2eC3","AIYUuM3zXL","Gv3FquLtKs","wDajXru4UG","RmDcr9XyT9",
-"ydG8U3weIF","jfREutjQxs","X6PinCfgr3","K20wKWreyP","CqqaDSmGzv","lCMxyL7cGc","EoToPm4bxU","Ss0ZuMojnP","oGu6x14FLR","C2IrcXyPZN",
-"tlILthYBCK","azIWp5nmWv","9y4lwoVQp6","AmdQdRmDcr","cQOnvuZPqg","QbxXc8FmFH","m4bxUOUqFM","F6PT2IBe8k","OHaBzyToGW","aFFssVLTy6",
-"Q6hMCZhwG1","m4bxUVBjhz","AXpwEOUYuF","8TxD7cmXIX","zFgtBeuZA5","WDVWJJ2mQi","4dEz6Pb1pa","HfyNQxciqp","v8yFNJkzUn","ru4UGDcpWB",
-"taOXKksJby","vkCHHuAWyp","ZzJHW618Di","UmaEv8U2nU","i3pydPOUYS","oQ87r5Mg9r","WmadAVjCZq","zqH0Wh1zcH","rKDLJAIYUu","9GXkXs7Mxk",
-"pT8wuJJs5m","WMiS3RmDcr","PYBf4uLtKs","CK5W7Oz8yZ","45cIHhYBCK","9iGoTi3pyd","FVMxoIKxdL","ThjNnv1Hln","aFFssDz1R3","JXljWAOgEe",
-"prNT6aez9y","Chuy3HRxd8","F6PT2xXTI4","AIYUuZJTXH","pv0i7HP433","yluBxuvf7A","Nxx9VcQOnv","O3iyQFNYIM","lsQGoCK5W7","AIYUuix74r",
-"yofH34QMc9","NhXduHRxd8","K20wKxXTI4","5VZjSY1mC0","MK07YTCgPp","8RCUAQbxXc","uoStwSs0Zu","Yf2EcQbxXc","GWqqXIjTwP","0MR5XJkzUn",
-"qaofN64s8N","tlILtyvOMI","a00b5lweGy","XflUqAkKTk","gdQsSHlUbF","azIWpD6rBy","NcICAC2Irc","Yw2oU14FLR","IRh48Rxrsm","HRxd8BFkb8",
-"uvf7AW3VFH","RzaZAqQxHP","ni2v1uQIcz","0BmCyHfyNQ","AOgEe7fsYM","2NslmcQOnv","IBe8kYw2oU","x3LDehe9IA","RpBQmv1Hln","tjQxsVjCZq",
-"vkCHH8RCUA","djsrvl83Ud","Ta8f6ZhwG1","s4786uQIcz","5Mg9rlsQGo","HzZT8piJSk","gIYvEn1pmO","5Mg9ruTacx","Pb1paTwano","iKqhrWaWsv",
-"lCMxyCqqaD","QbxXctl72W","LewvM2hEEU","2ZHdk4QMc9","azIWpVprf2","b29RJW7cTs","MojnP4QMc9","QWxoTMGlTF","v2eC39eoRc","0h1b1e6e4z",
-"uvf7A0ao3l","0h1b1Q6hMC","F6PT2Qworu","1j5L8KsjRK","Yw2oURmDcr","0PktIdQ586","soy9t2Nslm","v1HlnQChxs","yluBxECMvU","EoToPpFrrl",
-"64s8NReKEW","8TxD75iGN5","hSSvQVjCZq","W3VFHGWqqX","QYxC0taOXK","618DiLDk6f","DQimpMaJQs","5drc6AIYUu","JRJQBx3LDe","ksJbyJKWYR",
-"tAOsrW7cTs","5nmWv4dEz6","5drc65drc6","Yf2EcpiJSk","vOqCEBGaQY","uTacxuQIcz","NcICApv0i7","fcJOyogLgc","B3qem14FLR","U3yw5rz7Ut",
-"cmXIX8FmFH","yEfy9Gv3Fq","uLtKsgdQsS","5ZaEzIRh48","yluBxfaHir","faHiriKqhr","o8Uyd2ZHdk","Ul4a1prNT6","FLsph8TxD7","okgRipiJSk",
-"7Ow5Csx5Gl","5Mg9rd7vjM","5Mg9rpT8wu","XyPZNGrDg7","BpYhVVerEA","UmaEvlpF6W","jeskStvdkD","PYBf4cQOnv","hi5X7WmadA","FxX9q7hyVv",
-"QWxoT2hEEU","DQimpX6Pin","4dEz6QYxC0","kZANmUvlv4","iqv4k5Drn0","xXTI4AOgEe","qUJMdzbIYY","TXQ0ZyEfy9","MmsIolsQGo","lj07Q5drc6",
-"SjskQReKEW","gf8rIMezSW","CdyBVQChxs","wiHrZuAWyp","cL0aECxVEf","lweGyfmIK1","7X3uy16lHc","HP433l83Ud","Nxx9VZuDtD","5ZaEzVprf2",
-"dQ586d7vjM","RzaZA5Mg9r","lH1ktjiVBP","i7WMQOUqFM","WMiS3fcwDa","GXdoH5Mg9r","NOHszTwano","9y4lwiqv4k","FNYIM9GXkX","ThjNn8xEKz",
-"JRJQBsx5Gl","RBhp0lViBv","3otm6HfyNQ","2DREsQ6Lix","Yw2oU7lUXZ","d85a9ZUnqt","Mkgy8ZJTXH","Ss0ZuOz8yZ","8xEKzzHF1q","45cIH7Ow5C",
-"hSSvQStlDJ","he9IAWPmlx","Ss0Zum4bxU","e6e4z6AFT0","3weIFHfyNQ","atef2MojnP","W3VFHv2eC3","WmadA2ZHdk","wiHrZtvdkD","0Wr5yRBhp0",
-"zHF1qGSQwj","KsjRKWMiS3","K20wKpv0i7","taOXKi3pyd","W7cTse6e4z","Vprf2NhXdu","iKqhr5VZjS","VjCZqTa8f6","Rxrsm1v5hH","6AFT06AFT0",
-"2NslmTwano","sx5GlKr8ys","5Drn0vOqCE","FFDuicmXIX","CK5W70ao3l","BGaQYtvdkD","Mkgy82DREs","ZzJHWh1zcH","FFDui7lUXZ","16lHcQ6hMC",
-"m4bxUt98iW","DcpWBVNCPd","4dEz65ZaEz","tvdkDCK5W7","qUJMdFnPFB","CqqaDX6Pin","HzZT8qUJMd","W7cTsAkKTk","X6PinaDGtS","FPfSECfgr3",
-"9rlg9JKWYR","BCxeCs93Ml","8U2nU5Namm","48cHLKsjRK","OHaBzo8Uyd","5Mg9rCNHmv","hE1QlCfgr3","6AFT0YOfrY","t98iWJJs5m","t98iWM3zXL",
-"MK07YS2Dfu","AkKTkiB08l","IKxdLECMvU","GXdoHjfREu","ZuDtDxReec","64s8NxXTI4","XyPZNSs0Zu","v8yFNO3iyQ","RxrsmFNYIM","xReec6AFT0",
-"Kr8ysfaHir","bgJAz48cHL","zmLYDFLsph","fLNg8fqypy","WDVWJuTacx","KASQ80h1b1","mX2GEfaHir","blLA9MojnP","G1RhSKZamH","5iGN5lpF6W",
-"iKqhr0ao3l","4dEz64W0Tl","CqqaDuvf7A","8FmFHogLgc","C2IrcDz1R3","JRJQB24ARF","JkzUnYf2Ec","NhXduC2Irc","VerEAtaOXK","rKDLJ9rlg9",
-"M6qcG8TxD7","14FLRtvdkD","brhlQ64s8N","5IhmGReKEW","lsQGosx5Gl","07n1cLewvM","5Mg9r0Kyfs","MaJQs29QAz","5NammEOE1o","0Wr5yThjNn",
-"5VZjS55rfB","zqH0WyEfy9","MmKGJdjsrv","8xEKzVNCPd","EOE1o5drc6","CIShG8U2nU","DG4sTP6bcg","P6bcg8cVD3","M6qcGi3pyd","9y4lwQ6hMC",
-"yToGWtjQxs","rz7UtG1RhS","tuDySCIShG","azIWpCxVEf","CNHmv8xEKz","rz7UtDcpWB","9iGoTEoToP","4QMc9atef2","K4GS8e6e4z","DcpWByluBx",
-"zQt6QVBjhz","5VZjSCNHmv","ulk41h1zcH","lj07QS77LH","2DREsRzaZA","0ao3lzQt6Q","oQ87rMGlTF","C2IrcOxWIH","i7WMQuvf7A","x3LDeQClRL",
-"Q6hMCDLhzM","Ul4a18hJdt","t98iWFVMxo","yofH3Nxx9V","BFkb8AOgEe","ZJTXHdpe1v","tl72WqaofN","gtCA5qaofN","MK07YSbRYy","iqv4k3otm6",
-"P6bcgwiHrZ","AIYUuwiHrZ","JkzUndQ586","e6e4z29QAz","ZUnqtYw2oU","6q6L90YAGH","atef2Y1mC0","he9IAjS1aj","HfyNQt59lR","5drc6s93Ml",
-"G1RhSHfyNQ","IKxdLBbwgA","DLhzM07n1c","pvgjSSmGzv","7hyVvaL6AJ","cL0aEfaHir","TwanohE1Ql","gdQsSYjB9t","v8yFNThjNn","HzZT8nnP8o",
-"L7cGc8RCUA","M6qcGfLNg8","rKDLJydG8U","POUYShSSvQ","0ao3lv8yFN","BFkb8soy9t","CIShGIKxdL","lpF6WNcICA","jiVBPtvdkD","WaWsvcmXIX",
-"FjHXRAIYUu","dQ586uPX7G","i7WMQi7WMQ","Kr8ys7fKYU","d85a9DQimp","RpBQmEdBKc","XflUqpAhR1","qUJMdUmaEv","J2mQiblLA9","v8yFNqQxHP",
-"zFgtBhSSvQ","gtCA5m4bxU","EoToPn1pmO","MaJQs7fsYM","okgRiChuy3","BFkb8xciqp","FnPFBU3yw5","9GXkXHP433","No0QbS2Dfu","CIShGuupzk",
-"Ul4a15ZaEz","X6PingdQsS","ksJbyM6qcG","QChxshSSvQ","nFqikyvOMI","Ss0ZuWDVWJ","Pb1palpF6W","xReecaez9y","vLsmSlpF6W","okgRivkCHH",
-"cL0aEhE1Ql","rz7UtNxx9V","TCgPp6AFT0","GSQwjlsQGo","LDk6f7ku1p","1j5L8BCxeC","1v5hH0ao3l","tuDySCxVEf","29QAzIKxdL","FNYIMRmDcr",
-"jSjS3UlU3M","1v5hHSs0Zu","StlDJjiVBP","5Mg9rv2eC3","zbIYYWPmlx","kB5nP0BmCy","Mm8siHRxd8","LDk6fVBjhz","3otm60h1b1","wDajX2hEEU",
-"FVMxo8hJdt","yvOMIQworu","xciqpDLhzM","rhl0Jlm0pD","W7cTsciuWz","AgJHQuAWyp","F6PT2Waim6","No0QbStlDJ","uPX7GvLsmS","ECMvU8U2nU",
-"a00b5cL0aE","VBjhzMK07Y","AgJHQzmLYD","v1HlnbZLvS","8FmFHIKxdL","IjTwPRkQke","HRxd8he9IA","IRh48zmLYD","I7p2aRBhp0","55rfBVNCPd",
-"GSQwjnlaBy","IRh48P6bcg","8cVD3ThjNn","xXTI4hUTw7","prNT6DQimp","O3iyQlXFOB","sqVrfAXpwE","IjTwPcmXIX","0BmCyfaHir","pWiOsiwzGk",
-"Kr8ysRxrsm","rhl0JUlU3M","cmXIX2hEEU","48cHLPYBf4","UmaEvAXpwE","7fsYMHzZT8","MK07YuAWyp","BbwgATCgPp","Q6LixM6qcG","48cHLn8pJ9",
-"AmdQdtvdkD","SWfoujzUqR","5Nammuupzk","jiVBPh1zcH","blLA90ao3l","lH1kt9y4lw","8xEKz3otm6","0Wr5yQChxs","9GXkXokgRi","iwzGkbrhlQ",
-"8hJdtI7p2a","uAWypTwano","X6Pin3otm6","7fKYUPOUYS","Cfgr34QMc9","mX2GE14FLR","QssNCPOUYS","fcJOyqaofN","fmIK1zY1GY","vOqCEUl4a1",
-"FVMxoHfyNQ","oVQp68FmFH","14FLROz8yZ","tAOsrv8yFN","pT8wuOUqFM","9y4lwVerEA","StlDJFcWrW","xXTI44QMc9","9eoRcCqqaD","t59lRNAFuw",
-"0BmCyPOUYS","ydG8UbrhlQ","pAhR1zmLYD","45cIHNo0Qb","HRxd8QssNC","uN6r3piJSk","OUYuFuQIcz","KsjRKhSSvQ","hE1Ql7X3uy","ReKEWnlaBy",
-"LewvMMojnP","48cHL5iGN5","EoToPMK07Y","Z4I1vni2v1","XflUqzz4ZU","9eoRcFwEJz","RsQUq0Kyfs","cL0aEOUqFM","lH1kti3pyd","o8UydDG4sT",
-"5Drn0gjUTu","AmdQd5drc6","5drc6iB08l","J2mQiJ2mQi","vkCHHP6bcg","I7p2aQssNC","jeskS0MR5X","LDk6fYh1hF","guMb8Oz8yZ","yEfy99y4lw",
-"nlaBylweGy","07n1cjtn0X","0h1b1Qworu","MezSW7fKYU","lkMUA2Yz7E","rz7UtJRJQB","cQOnvNhXdu","ksJbyd7vjM","QYxC0Rxrsm","DG4sTJRJQB",
-"hYBCKPb1pa","n1pmOCxVEf","yluBxmX2GE","o8Uydsoy9t","lViBvtuDyS","Q6LixhE1Ql","qUJMd7X3uy","pvgjSkB5nP","X6PinG1RhS","uQIczFVMxo",
-"pvgjSuTacx","WaWsvFVMxo","CIShGI7p2a","ni2v1k85Ae","D6rBy8RCUA","K4GS8F6PT2","rz7UtyvOMI","zY1GYblLA9","GrDg7gtCA5","AIYUu1j5L8",
-"Mkgy8KASQ8","zmLYDgdQsS","mX2GEWreyP","qaofNAkKTk","5iGN5blLA9","nlaByEdBKc","2Yz7EoGu6x","OxWIH9rlg9","dhSuHIjTwP","NcICA9y4lw",
-"ZUnqts93Ml","C2IrcyEfy9","8U2nUe6e4z","2DREsDcpWB","Uvlv4Nxx9V","9rlg9hE1Ql","5VZjSbgJAz","CIShGMGlTF","hE1QlKASQ8","SbRYy7Ow5C",
-"dpe1vfFDrJ","YjB9tFNYIM","Twano16lHc","14FLRSbRYy","rhl0JQssNC","oGu6x5Namm","wDajXWPmlx","pmeCdzqH0W","Zv7z0DLhzM","MmsIoNxx9V",
-"cL0aEyluBx","FcWrWuoStw","7hyVv55rfB","fFDrJOHaBz","gIYvEJJs5m","sx5GlLewvM","HzZT8FcWrW","FFDuis4786","cL0aESWfou","piJSkMK07Y",
-"gIYvEJkzUn","hE1QlOUYuF","7fsYMhE1Ql","BCxeCJRJQB","s7MxkKASQ8","ThjNnI7p2a","suY4xGXdoH","nnP8o580YD","VIlwPCIShG","dQ586qaofN",
-"yofH3UlU3M","JKWYRiwzGk","S2DfupvgjS","0Wr5yuTacx","oVQp6uPX7G","mz8gxjfREu","TwanoG1RhS","Ul4a1S2Dfu","qaofNGrDg7","TwanoI7p2a",
-"AXpwE24ARF","bgJAz0ao3l","zFgtBQWxoT","7fsYMEoToP","PYBf40BmCy","8xEKzWMiS3","FwEJzyluBx","Yh1hFrhl0J","prNT6rz7Ut","n1pmOGXdoH",
-"x3LDeQbxXc","VBjhzCp3mZ","RpBQmOxWIH","azIWpRBhp0","lsQGoM6qcG","hUTw7s4786","rhl0J4W0Tl","6q6L9S2Dfu","JRJQB29QAz","AIYUugdQsS",
-"DQimpgIYvE","QWxoTUlU3M","CK5W7LDk6f","pFrrlZv7z0","gIYvEgjUTu","okgRiFVMxo","fLNg8taOXK","AIYUuTwano","HzZT8TXQ0Z","JKWYRJIqXi",
-"Ta8f6hYBCK","KASQ8Kr8ys","uoStwogLgc","uTacxl83Ud","FcWrWIKxdL","CxVEf9GXkX","SWfouZzJHW","5VZjSix74r","dmoS72hEEU","RxrsmJ2mQi",
-"GXdoHuoStw","VNCPdRACuj","tl72Wd7vjM","tl72WEOE1o","WMiS3BpYhV","Nxx9Vn8pJ9","yluBx8xEKz","RmDcr9rlg9","ix74rfcJOy","tvdkDk85Ae",
-"Gv3FqMezSW","k85AeNcICA","s7MxkBCxeC","uAWypQ6hMC","QChxsdmoS7","uQIczo8Uyd","kZANmqQxHP","BCxeCSWfou","TCgPpx3LDe","vkCHHrz7Ut",
-"blLA92hEEU","n8pJ91v5hH","QnJ1SaFFss","4dEz6sx5Gl","yofH3lm0pD","P6bcgMezSW","wiHrZ8TxD7","0MR5XyluBx","In3NSU3yw5","jSjS3xXTI4",
-"8xEKzZ4I1v","Cp3mZdQ586","RsQUqHfyNQ","t59lRD6rBy","t59lRpAhR1","ix74rpvgjS","POUYSAmdQd","oGu6xogLgc","4QMc9WaWsv","x3LDeXflUq",
-"lj07Qhe9IA","gjUTuuLtKs","B3qemTXQ0Z","Chuy3I7p2a","VBjhzQYxC0","qQxHPlkMUA","tvdkDyvOMI","uTacxB3qem","7fKYUo8Uyd","FhtglCfgr3",
-"SmGzvlXFOB","s93MlFcWrW","Cfgr3B3qem","9y4lwatef2","tl72WFhtgl","Cp3mZvOqCE","OxWIHni2v1","fcJOyFNYIM","tjQxsCNHmv","lH1ktGrDg7",
-"v8yFNgdQsS","yEfy9WMiS3","vOqCEQworu","CdyBVvOqCE","EdBKcyluBx","azIWptlILt","OUqFMPb1pa","Mkgy8faHir","hYBCKpv0i7","C2IrcRACuj",
-"3otm6Ss0Zu","48cHLXyPZN","JIqXiKr8ys","yvOMI5drc6","rz7UtMmsIo","Y1mC0AOgEe","JXljWlpF6W","7lUXZIKxdL","AmdQdqQxHP","Q6LixDLhzM",
-"RmDcr3weIF","gIYvE7ku1p","gjUTucL0aE","iwzGklj07Q","uoStwSjskQ","UlU3MpT8wu","GWqqX4W0Tl","I7p2aydG8U","8hJdtcQOnv","RxrsmlweGy",
-"lXFOBUmaEv","dmoS7uQIcz","C2IrcVerEA","L7cGc4QMc9","Cp3mZhE1Ql","9eoRcjS1aj","lm0pDv1Hln","8cVD3Zv7z0","hi5X7ix74r","jzUqRAIYUu",
-"x3LDezHF1q","x3LDeuPX7G","fcwDatl72W","SbRYyGXdoH","aFFssh1zcH","8FmFH48cHL","FwEJzhUTw7","CdyBV07n1c","gf8rIVprf2","POUYSFhtgl",
-"7fKYUxXTI4","K4GS8t98iW","HfyNQzmLYD","8xEKzdhSuH","BGaQYF6PT2","jiVBPxXTI4","55rfBcL0aE","gdQsSZUnqt","0Kyfs4QMc9","8cVD3AIYUu",
-"Zv7z05IhmG","580YD5drc6","xReec45cIH","tl72WMkgy8","8cVD3LbRTH","tlILtHzZT8","ydG8U6AFT0","JIqXipiJSk","zz4ZU4dEz6","iqv4kv8yFN",
-"JJs5m1LB1L","CxVEfOUqFM","iKqhr24ARF","v8yFN24ARF","WPmlxdjsrv","JRJQBuoStw","CIShGhUTw7","oGu6xJXljW","aL6AJ0PktI","aL6AJUvlv4",
-"WMiS3tlILt","mX2GEAkKTk","jzUqR9rlg9","MmsIoAXpwE","JkzUntAOsr","wiHrZFhtgl","4QMc9Dz1R3","uQIczt98iW","uAWyppmeCd","4dEz6jfREu",
-"iKqhrRsQUq","M6qcGuTacx","8cVD3ydG8U","TwanoOUqFM","sqVrf6q6L9","lCMxyGWqqX","euZA524ARF","v2eC32DREs","guMb8uN6r3","gf8rI48cHL",
-"2DREsqUJMd","bZLvSvOqCE","jS1ajfqypy","MezSWfaHir","VBjhztaOXK","0h1b1MaJQs","jfREuqUJMd","QnJ1SqUJMd","7Ow5C2Nslm","NOHsz2TRI7",
-"618DiCxVEf","SWfouCdyBV","gdQsSnnP8o","nnP8ofFDrJ","XflUq0BmCy","YjB9tFnPFB","C2IrchUTw7","CIShG9eoRc","sqVrf7fsYM","fqypyfcJOy",
-"Dz1R3WMiS3","b29RJMojnP","FLsph0BmCy","tuDySzqH0W","DLhzMTCgPp","i7WMQfcJOy","5Mg9rOHaBz","pT8wuOxWIH","1j5L87fsYM","618DiMm8si",
-"KZamHFcWrW","2TRI7lpF6W","WmadAuLtKs","EoToPNOHsz","QChxsDQimp","UmaEvcL0aE","FwEJzpiJSk","v2eC3pv0i7","LDk6fbgJAz","Z4I1vdjsrv",
-"MGlTFLDk6f","cQOnvsoy9t","bZLvSlj07Q","Yf2Ec9rlg9","WPmlxtaOXK","Cp3mZK20wK","C2IrccL0aE","1LB1LOUYuF","WreyPjtn0X","yofH3FGzgp",
-"7fKYUWMiS3","24ARFVerEA","24ARFL7cGc","G1RhSk85Ae","0ao3ldjsrv","okgRipWiOs","e6e4z2Nslm","dmoS7uTacx","MezSWuupzk","WPmlxChuy3",
-"vkCHHsuY4x","e6e4z3weIF","Yf2EcJKWYR","Vprf2IjTwP","t98iW9rlg9","ulk41fFDrJ","DcpWBGv3Fq","jtn0X0YAGH","oVQp6BbwgA","l83UdGv3Fq",
-"8hJdtcL0aE","ydG8Ulm0pD","LDk6fhSSvQ","Ss0ZujzUqR","24ARFMojnP","lpF6W8TxD7","BGaQYMojnP","07n1ch1zcH","BGaQYQ6hMC","yToGWVNCPd",
-"FhtglHP433","ReKEW2TRI7","MK07YKASQ8","gdQsSni2v1","4dEz6cShY2","Ul4a1uvf7A","AOgEeOz8yZ","BFkb8RpBQm","blLA91v5hH","iwzGksoy9t",
-"pT8wupWiOs","Gv3FqdQ586","Vprf2IRh48","AgJHQBbwgA","qaofNCfgr3","WPmlx9rlg9","h1zcHBFkb8","jtn0Xe6e4z","fmIK1tAOsr","Ta8f6No0Qb",
-"5Drn0fcJOy","8cVD39GXkX","ZuDtDpv0i7","2DREsBCxeC","2Yz7EAmdQd","I7p2a45cIH","MojnPvkCHH","0KyfsksJby","WaWsvJkzUn","FFDuiL7cGc",
-"AmdQde6e4z","hSSvQCfgr3","ZJTXHVLTy6","hYBCKMm8si","2Yz7EwiHrZ","ZUnqtCfgr3","bgJAzRxrsm","M6qcGuvf7A","VLTy6zHF1q","v1HlnnnP8o",
-"MmKGJJXljW","OHaBzQworu","tl72WBFkb8","618DiyEfy9","Kr8ys07n1c","Ss0ZuPYBf4","16lHcuLtKs","uvf7AKASQ8","9rlg9sqVrf","MmsIoxReec",
-"qQxHPsqVrf","U3yw55drc6","tvdkDtAOsr","TwanoCNHmv","2hEEUYw2oU","zFgtBguMb8","atef2ksJby","ReKEWSjskQ","iqv4k4QMc9","hUTw76q6L9",
-"d85a9lXFOB","uupzkM3zXL","RpBQmsoy9t","45cIHm4bxU","FxX9qQnJ1S","prNT6TXQ0Z","X6PinDLhzM","FLsph9GXkX","okgRiUmaEv","0KyfslweGy",
-"WaWsvpiJSk","blLA9AXpwE","W3VFHJ2mQi","G1RhStaOXK","qaofNvLsmS","2NslmW7cTs","dhSuHQnJ1S","iqv4kQ6hMC","RsQUqRACuj","0ao3lF6PT2",
-"tl72WIjTwP","StlDJY1mC0","LDk6fd85a9","pFrrlFGzgp","RpBQmGXdoH","tjQxslweGy","fLNg8GSQwj","ix74rprNT6","7lUXZGXdoH","KASQ8jeskS",
-"FFDuiD6rBy","pWiOsfFDrJ","EdBKcSbRYy","rhl0Jru4UG","uTacxW3VFH","lsQGozqH0W","qaofNuN6r3","EdBKcrz7Ut","U3yw57hyVv","7hyVv618Di",
-"faHir8xEKz","SbRYyuoStw","rz7Ut5IhmG","zmLYDUmaEv","F6PT245cIH","XyPZNDG4sT","7ku1pYh1hF","Ul4a1FcWrW","55rfB8hJdt","5iGN55IhmG",
-"0ao3lWaWsv","K4GS8B3qem","Zv7z0ciuWz","yvOMIZuDtD","gjUTuUmaEv","ciuWzgf8rI","t98iWs93Ml","gdQsSHRxd8","yToGWv1Hln","cShY2s93Ml",
-"0Wr5yjfREu","J2mQi0MR5X","1v5hH8FmFH","Fhtgld85a9","KASQ8gf8rI","BpYhVQnJ1S","kZANm2ZHdk","M6qcG55rfB","QnJ1SaDGtS","TCgPp7ku1p",
-"uJScXJXljW","nnP8oOz8yZ","IBe8kjtn0X","yEfy9AkKTk","48cHLWPmlx","8RCUA8RCUA","djsrvB3qem","IRh48JRJQB","iwzGkQnJ1S","WMiS3lpF6W",
-"zqH0WOxWIH","FcWrW48cHL","VBjhzxciqp","hUTw7B3qem","2NslmtlILt","zQt6Qxciqp","vLsmS7hyVv","0YAGHyofH3","MmKGJCNHmv","MmKGJTwano",
-"YjB9tLewvM","hUTw7zqH0W","jS1aj8FmFH","NOHsz5nmWv","qUJMdfqypy","EdBKc55rfB","UmaEvOz8yZ","7fKYUOHaBz","ciuWztlILt","lXFOBVprf2",
-"S77LHjzUqR","XflUqWreyP","yEfy9WmadA","prNT6HfyNQ","Oz8yZJRJQB","t98iWFnPFB","t98iWCxVEf","FGzgpZhwG1","EoToPRxrsm","8TxD7QnJ1S",
-"hi5X7taOXK","lpF6WcmXIX","okgRiLDk6f","mX2GE5ZaEz","uvf7AKsjRK","Yw2oUlH1kt","Yw2oUPYBf4","8RCUAFxX9q","AIYUutlILt","TXQ0Zru4UG",
-"5nmWvuupzk","WreyPsqVrf","DG4sTy94nw","BFkb8d7vjM","LDk6fYOfrY","ZuDtD0BmCy","qUJMdRsQUq","Mkgy8VjCZq","ECMvU24ARF","55rfBJJs5m",
-"zFgtBCK5W7","9GXkXzQt6Q","In3NSSbRYy","s93Mll83Ud","In3NSa00b5","OxWIH3otm6","45cIH8U2nU","dhSuHCxVEf","d85a9HlUbF","jtn0XBbwgA",
-"lpF6WfFDrJ","5VZjSLDk6f","2hEEUnFqik","aDGtS4dEz6","Fhtglzz4ZU","zY1GYJKWYR","8RCUAFPfSE","TCgPpSjskQ","8TxD7SmGzv","FFDuibgJAz",
-"bgJAzh1zcH","nnP8oQnJ1S","07n1c2ZHdk","CIShGPYBf4","EOE1oQnJ1S","faHir6q6L9","AXpwE0BmCy","jtn0XZuDtD","9y4lwIRh48","Nxx9ViKqhr",
-"uZPqgzz4ZU","StlDJD6rBy","7fKYUs7Mxk","iwzGki7WMQ","XyPZNF6PT2","MK07Y0YAGH","fmIK1i7WMQ","uPX7GL7cGc","o8UydyEfy9","i7WMQHzZT8",
-"LewvMWaim6","zmLYDuTacx","atef2CIShG","FLsphdpe1v","pT8wuSbRYy","ix74rdQ586","yToGWuJScX","O3iyQO3iyQ","o8Uyd29QAz","RkQkeS2Dfu",
-"QYxC0aFFss","0BmCytjQxs","IBe8kGv3Fq","azIWp8RCUA","Yh1hFQClRL","7lUXZHlUbF","ogLgcDcpWB","NAFuw64s8N","QClRLnnP8o","s4786GrDg7",
-"5ZaEzDcpWB","5IhmGPOUYS","580YDNOHsz","Dz1R3S77LH","QssNC07n1c","0ao3lrhl0J","qaofNXyPZN","HfyNQzHF1q","iqv4kFGzgp","lH1ktCqqaD",
-"KZamH2DREs","rhl0JiB08l","F6PT2Oz8yZ","tjQxsAkKTk","I7p2a16lHc","UmaEv6q6L9","Z4I1vbZLvS","VerEAd85a9","gdQsSBFkb8","FNYIMMmKGJ",
-"Kr8yslpF6W","Yf2EcxXTI4","0KyfsQbxXc","45cIHdmoS7","pWiOsguMb8","h1zcHOHaBz","m4bxUQChxs","9GXkXzz4ZU","FhtglIjTwP","FVMxo9y4lw",
-"pWiOsBbwgA","0YAGHuTacx","e6e4zU3yw5","QnJ1SYw2oU","S77LHReKEW","ReKEWtAOsr","lj07QGSQwj","BGaQYZuDtD","8FmFHlCMxy","RmDcrciuWz",
-"StlDJYh1hF","x3LDeVerEA","580YDtlILt","lweGyK20wK","5iGN5Nxx9V","lsQGoMm8si","55rfB48cHL","O3iyQ0YAGH","AXpwEWDVWJ","xReecDcpWB",
-"ix74rdpe1v","aFFssatef2","2Nslmuupzk","lj07QgdQsS","4W0TliwzGk","djsrvBGaQY","aDGtSY1mC0","8xEKzQnJ1S","DLhzM3otm6","TwanohSSvQ",
-"EdBKcW7cTs","HfyNQsoy9t","OUqFMQnJ1S","QWxoTyvOMI","uTacxokgRi","d85a9IRh48","C2Irc0MR5X","k85AeMaJQs","jiVBPuTacx","5iGN5J2mQi",
-"uupzkcL0aE","OxWIHSbRYy","FVMxo6AFT0","rz7UtRmDcr","gf8rIRxrsm","brhlQZuDtD","HlUbFG1RhS","b29RJ9GXkX","HRxd8oQ87r","zz4ZUkB5nP",
-"n8pJ9pFrrl","CNHmvAXpwE","cL0aEhUTw7","wDajXW7cTs","FLsphtuDyS","CNHmvGv3Fq","NcICATwano","jfREuuLtKs","WmadA07n1c","RBhp0AXpwE",
-"AmdQdi3pyd","580YDv2eC3","LDk6fKASQ8","fLNg8uTacx","1j5L8JIqXi","KASQ8Mkgy8","4QMc9tl72W","XyPZN0MR5X","lweGyCfgr3","YjB9t5nmWv",
-"VNCPd8TxD7","t59lRnFqik","gdQsSFnPFB","TXQ0ZZuDtD","Ta8f6CdyBV","BpYhVBpYhV","FwEJzCIShG","0PktI8xEKz","fmIK1XflUq","NOHszU3yw5",
-"FPfSE3otm6","YOfrYZuDtD","nlaByQYxC0","FFDuiNcICA","Ss0Zu5VZjS","CNHmvaDGtS","AIYUuqaofN","zQt6QjiVBP","gdQsSRkQke","Yh1hFuvf7A",
-"EOE1ofcJOy","jtn0XfFDrJ","o8Uyd1j5L8","s7MxkKsjRK","F6PT2hUTw7","wiHrZuTacx","VIlwPdpe1v","Q6LixcShY2","HzZT8tvdkD","AOgEeGXdoH",
-"7ku1p5iGN5","YjB9ty94nw","lkMUAulk41","RkQkeW3VFH","aDGtSHlUbF","HlUbFuAWyp","7Ow5CZUnqt","tjQxsjzUqR","FFDuifFDrJ","Oz8yZVprf2",
-"DQimpFcWrW","MmKGJDz1R3","zHF1qQworu","55rfBWmadA","FnPFBRkQke","uoStwgf8rI","2TRI7Yw2oU","EoToPpmeCd","iwzGkDcpWB","ECMvUUmaEv",
-"IjTwPzQt6Q","uJScX5Namm","8TxD7P6bcg","h1zcHJ2mQi","IjTwP8RCUA","jfREuM3zXL","RsQUqhUTw7","i7WMQiqv4k","dpe1vECMvU","Gv3Fqd7vjM",
-"64s8NyToGW","gdQsSGXdoH","YjB9tECMvU","580YD2DREs","QWxoTNhXdu","FNYIMFVMxo","VNCPdFVMxo","dpe1vBFkb8","cmXIXW7cTs","POUYSCxVEf",
-"mz8gx7Ow5C","RBhp0OxWIH","e6e4zReKEW","hSSvQulk41","EoToPtvdkD","hYBCKmX2GE","Zv7z0dQ586","LewvMF6PT2","jSjS30PktI","fcJOyYf2Ec",
-"SjskQt98iW","OHaBzFcWrW","FxX9qW3VFH","RBhp0HfyNQ","QbxXcJRJQB","0MR5X14FLR","GWqqXlH1kt","FLsphvLsmS","l83Udrhl0J","wDajXZJTXH",
-"Ss0ZuRxrsm","VNCPdlpF6W","BpYhVLDk6f","uTacxfqypy","XyPZNEdBKc","MezSWhi5X7","F6PT216lHc","BFkb8Mm8si","C2IrctuDyS","v2eC3VIlwP",
-"7Ow5C4W0Tl","XflUqAOgEe","FNYIMnFqik","POUYSTXQ0Z","Dz1R3jtn0X","rKDLJReKEW","9y4lwxciqp","ECMvU0YAGH","MezSW8hJdt","8FmFHuTacx",
-"RmDcrFLsph","lweGyWmadA","y94nwSWfou","pWiOsNAFuw","StlDJW7cTs","SbRYyZ4I1v","uN6r32DREs","VNCPdWMiS3","zY1GY8RCUA","K20wKBCxeC",
-"uQIczYw2oU","rhl0Jtl72W","zz4ZUM6qcG","ECMvUo8Uyd","uZPqgbgJAz","ZhwG1WaWsv","tuDySs93Ml","NAFuwzQt6Q","uN6r3CdyBV","HfyNQHzZT8",
-"WPmlxJkzUn","d85a9W3VFH","gdQsSCqqaD","07n1c0MR5X","WPmlxcQOnv","euZA5FPfSE","0YAGHhUTw7","VIlwPuPX7G","OUqFMKr8ys","No0Qbiqv4k",
-"n8pJ97lUXZ","guMb8yToGW","AkKTkgjUTu","dQ586jtn0X","SbRYy45cIH","L7cGcCxVEf","RsQUqdjsrv","aL6AJ9eoRc","5ZaEz2Yz7E","uLtKsokgRi",
-"0BmCy2DREs","ru4UG8RCUA","lH1ktS77LH","ix74ratef2","tjQxsYf2Ec","StlDJVprf2","XyPZNn1pmO","9GXkX55rfB","JJs5miwzGk","S2DfuiB08l",
-"iKqhr9GXkX","k85AeFxX9q","lweGyVBjhz","In3NSxciqp","iwzGkdjsrv","P6bcgCNHmv","b29RJlweGy","y94nwjeskS","lm0pDzY1GY","QChxsGSQwj",
-"EoToPfcJOy","4QMc90h1b1","9rlg9uN6r3","OxWIHbrhlQ","RpBQmK4GS8","uN6r3Yh1hF","hE1QlvLsmS","9eoRcaDGtS","0h1b1h1zcH","S77LHokgRi",
-"7hyVv14FLR","MGlTF5Drn0","okgRi618Di","0Wr5yBCxeC","TwanoCIShG","hi5X7uZPqg","VerEAdhSuH","taOXKru4UG","oVQp6QClRL","oGu6xLDk6f",
-"yofH3piJSk","rKDLJzmLYD","TCgPpru4UG","pT8wuTa8f6","FwEJzFxX9q","RpBQmulk41","fcJOyZUnqt","WDVWJpAhR1","QWxoTbZLvS","aez9yhe9IA",
-"2NslmYw2oU","tjQxs6AFT0","fLNg8bgJAz","qUJMd2Yz7E","cmXIX9eoRc","vkCHH0Wr5y","FcWrWSmGzv","pv0i7pAhR1","zFgtBzbIYY","ZhwG1s93Ml",
-"VIlwPVNCPd","h1zcHHzZT8","rz7UtI7p2a","i3pyd5nmWv","fFDrJFcWrW","7fsYMrhl0J","Twanod85a9","Yf2EcdQ586","jSjS3soy9t","WMiS3P6bcg",
-"ZJTXHAgJHQ","EdBKckB5nP","pWiOspWiOs","uLtKsYh1hF","J2mQiUlU3M","1j5L8HfyNQ","CdyBV9XyT9","iKqhrjfREu","OxWIHTXQ0Z","5VZjSeuZA5",
-"0ao3llpF6W","F6PT2dhSuH","lkMUA8U2nU","lweGypiJSk","uZPqguupzk","oVQp6yofH3","MezSWBpYhV","QYxC0ulk41","FGzgpprNT6","6q6L9580YD",
-"nlaByZzJHW","MojnPlsQGo","9rlg9i7WMQ","RpBQmlCMxy","0BmCyK4GS8","Oz8yZdQ586","d85a9NhXdu","LbRTHFhtgl","WreyPk85Ae","n1pmOv8yFN",
-"UlU3MW7cTs","BpYhVThjNn","MK07YfLNg8","45cIH8FmFH","0KyfsogLgc","mX2GEaL6AJ","OUqFMFVMxo","F6PT2hSSvQ","VBjhzHP433","Ul4a1Nxx9V",
-"blLA9Q6Lix","tlILt0Wr5y","4W0TlHP433","Oz8yZpvgjS","3weIF1LB1L","BCxeCvkCHH","uPX7GQClRL","RzaZATXQ0Z","GWqqXL7cGc","DQimpFGzgp",
-"8TxD7cQOnv","8hJdtYf2Ec","uPX7GxXTI4","2DREshSSvQ","ksJbyn8pJ9","NOHszfaHir","NAFuwh1zcH","Zv7z0i3pyd","8cVD3lsQGo","jeskSfcwDa",
-"7X3uyzFgtB","5IhmGGXdoH","gdQsSyluBx","rz7Ut7X3uy","SWfouX6Pin","Ss0ZuiKqhr","Dz1R30MR5X","fcJOy0h1b1","cmXIXjzUqR","uTacx9y4lw",
-"0MR5XjzUqR","IKxdLuoStw","fmIK1EOE1o","EoToPJJs5m","Pb1pajzUqR","P6bcgaL6AJ","F6PT27fsYM","CxVEfFhtgl","lkMUAbgJAz","Ul4a1Ul4a1",
-"S77LHksJby","a00b5sx5Gl","nnP8olm0pD","07n1c9eoRc","b29RJJKWYR","bgJAziwzGk","WaWsvMK07Y","v2eC3t98iW","4QMc94dEz6","iKqhrdQ586",
-"jS1ajjiVBP","iB08lCNHmv","zQt6QgdQsS","Z4I1vv1Hln","okgRi7X3uy","CxVEf45cIH","sx5GlAIYUu","tl72WbZLvS","S2DfunFqik","C2IrcTa8f6",
-"WmadAn8pJ9","y94nwUlU3M","uTacxjtn0X","ZhwG1ni2v1","QClRLQChxs","uZPqg48cHL","0PktIpAhR1","fcJOys7Mxk","pvgjSzQt6Q","pWiOsciuWz",
-"s7Mxk618Di","1LB1LWmadA","lj07QzmLYD","Vprf2TCgPp","xReecGv3Fq","zqH0Wk85Ae","3weIFdhSuH","9iGoTFxX9q","3otm6uN6r3","UmaEvn1pmO",
-"W3VFHAOgEe","jiVBPCfgr3","IjTwPfcJOy","In3NSydG8U","X6PinvkCHH","ogLgcHRxd8","IRh48kZANm","YOfrYi3pyd","0BmCylViBv","7fsYM618Di",
-"DG4sTIRh48","VLTy6pAhR1","RACujzFgtB","lViBv55rfB","jfREusqVrf","WPmlxTCgPp","YjB9tjfREu","SbRYyKZamH","aDGtStuDyS","bZLvSqaofN",
-"Kr8ysQssNC","ReKEWYw2oU","Nxx9VJKWYR","xReecuoStw","7X3uyTXQ0Z","xXTI4MmKGJ","Vprf28RCUA","d7vjMaL6AJ","7fsYMRBhp0","5nmWv2hEEU",
-"FcWrW9eoRc","ydG8UBbwgA","y94nwHRxd8","fLNg8BCxeC","fFDrJZhwG1","iqv4kguMb8","GXdoHVprf2","jSjS3Ul4a1","iqv4kpFrrl","zHF1qYf2Ec",
-"oGu6x9GXkX","580YD9iGoT","2DREsfcJOy","jtn0XYOfrY","azIWp9iGoT","aDGtSogLgc","uvf7ARxrsm","RpBQmZuDtD","8RCUAQClRL","BbwgAxciqp",
-"RzaZAW7cTs","lCMxyOUqFM","wiHrZGWqqX","JJs5maFFss","4dEz6brhlQ","lweGy7fsYM","HlUbF5Drn0","14FLRgjUTu","uN6r3pmeCd","zz4ZUjzUqR",
-"JkzUnQssNC","FVMxoazIWp","8U2nUJIqXi","RBhp0t98iW","In3NSVjCZq","yofH3ulk41","24ARFW3VFH","SbRYyYOfrY","aL6AJlkMUA","2NslmQnJ1S",
-"580YD7ku1p","HRxd8gjUTu","0ao3l4dEz6","prNT6Yf2Ec","FFDuiM6qcG","ksJbyrKDLJ","m4bxU3otm6","CxVEfyluBx","RxrsmhE1Ql","Zv7z0brhlQ",
-"hUTw7piJSk","lm0pDZzJHW","HRxd8Pb1pa","lm0pDaez9y","zFgtB2TRI7","hYBCK2Nslm","BCxeCaL6AJ","BGaQYSjskQ","Yf2EcMK07Y","SmGzvYw2oU",
-"cL0aEyToGW","GXdoHFLsph","FVMxoStlDJ","bZLvSaL6AJ","6AFT0hYBCK","0PktIkZANm","yEfy9Mkgy8","rz7UtFjHXR","yToGWBpYhV","Nxx9VVjCZq",
-"vOqCERzaZA","cL0aE2TRI7","oQ87ryluBx","MmsIolweGy","0ao3lZuDtD","In3NSDLhzM","he9IAMezSW","zQt6Q580YD","fqypy0Wr5y","2DREsmz8gx",
-"jiVBPAOgEe","d85a9WreyP","L7cGcB3qem","I7p2aOHaBz","1j5L84W0Tl","tuDySni2v1","QChxss4786","lm0pDm4bxU","fqypys93Ml","ZJTXHoGu6x",
-"uupzkmz8gx","jeskSuPX7G","uN6r3blLA9","DQimp1j5L8","sqVrf5ZaEz","jS1ajokgRi","n8pJ9DQimp","k85AewDajX","MK07YKZamH","XyPZNAmdQd",
-"NcICAQClRL","hi5X79XyT9","WreyPtjQxs","gjUTufqypy","0PktIGSQwj","MojnPv1Hln","e6e4z7ku1p","Waim6LewvM","fcwDafcJOy","pFrrlix74r",
-"5iGN5G1RhS","U3yw5LbRTH","AkKTkB3qem","soy9tpT8wu","ix74rTCgPp","AkKTkSWfou","gIYvE8TxD7","pWiOsNo0Qb","45cIHQWxoT","AOgEeNAFuw",
-"K20wKZUnqt","Uvlv4In3NS","i7WMQatef2","VLTy6AmdQd","45cIHlm0pD","Vprf2VBjhz","guMb89iGoT","hUTw7oGu6x","yofH3CxVEf","lpF6W9rlg9",
-"uAWyplweGy","y94nwFNYIM","uJScXIn3NS","1LB1L5IhmG","XyPZNx3LDe","vLsmSl83Ud","RpBQmF6PT2","iqv4kiKqhr","5nmWvtl72W","hYBCK64s8N",
-"pvgjSP6bcg","AgJHQEoToP","Q6Lixo8Uyd","y94nwfqypy","64s8NPb1pa","YOfrYuTacx","qaofNbgJAz","AkKTkUl4a1","BFkb85nmWv","ZJTXHsoy9t",
-"JXljWGrDg7","DLhzMiKqhr","DG4sT55rfB","uupzkfaHir","FjHXRydG8U","CIShG0YAGH","zQt6QGSQwj","VerEAFVMxo","uoStwZ4I1v","Yh1hFIjTwP",
-"ru4UGWaim6","qUJMd6q6L9","iB08lrhl0J","oQ87rWaWsv","pWiOs9iGoT","vkCHHy94nw","EdBKcPb1pa","fqypy0ao3l","hUTw7RBhp0","Vprf2Pb1pa",
-"tuDySwiHrZ","dQ586580YD","hi5X74W0Tl","HlUbFo8Uyd","9iGoTFVMxo","2ZHdkyvOMI","DLhzMPb1pa","Qworu5VZjS","VIlwPBGaQY","ni2v1iqv4k",
-"Waim6ydG8U","VLTy6jfREu","618DilViBv","tl72W9y4lw","n8pJ9rhl0J","AgJHQL7cGc","7fKYUVIlwP","Nxx9VOz8yZ","a00b5D6rBy","yluBxIjTwP",
-"IKxdL5VZjS","QnJ1SiB08l","zHF1qIRh48","k85AeJRJQB","euZA5uvf7A","gdQsSAXpwE","hUTw7pAhR1","P6bcgFVMxo","16lHc5Namm","faHirtuDyS",
-"ni2v1vOqCE","2ZHdkiwzGk","VNCPdqUJMd","D6rByd85a9","ECMvUQnJ1S","9rlg9AIYUu","5Drn0MaJQs","MezSWDcpWB","dpe1v48cHL","DG4sTgjUTu",
-"Gv3Fqrhl0J","hUTw7a00b5","iqv4k2DREs","5Mg9r48cHL","HzZT864s8N","VerEAfaHir","JIqXisuY4x","9y4lweuZA5","lm0pDOUYuF","Mm8sijtn0X",
-"Chuy3MmsIo","YOfrYThjNn","xReecAmdQd","o8UydCK5W7","FFDuiFwEJz","KASQ8In3NS","ZhwG1U3yw5","8TxD79XyT9","MojnPAgJHQ","S77LHChuy3",
-"b29RJWreyP","VIlwPECMvU","n8pJ9cL0aE","BFkb8DQimp","aez9yrz7Ut","4W0TlEdBKc","CIShGOz8yZ","taOXKyEfy9","Yh1hFfFDrJ","lXFOB0Wr5y",
-"rhl0J5Namm","2Yz7EfcJOy","atef2AXpwE","16lHc16lHc","cShY2MmKGJ","GXdoHnFqik","7fKYUP6bcg","JkzUnaez9y","M3zXLBCxeC","NAFuwAkKTk",
-"tuDySFcWrW","fqypySjskQ","Oz8yZD6rBy","UlU3MThjNn","8U2nU0Kyfs","ciuWzSs0Zu","RsQUqFGzgp","MmsIos93Ml","lsQGoQnJ1S","OUYuF8FmFH",
-"Q6Lixd7vjM","Ss0ZuEoToP","7X3uy9iGoT","t59lRYh1hF","W7cTs0BmCy","uQIczMkgy8","OHaBzwiHrZ","qaofNYh1hF","nFqik3weIF","dQ586VjCZq",
-"lpF6Wk85Ae","lsQGos93Ml","cShY2GSQwj","mz8gxI7p2a","7X3uyuoStw","lkMUAI7p2a","fmIK1NOHsz","K4GS8mz8gx","Chuy3RmDcr","WreyPuupzk",
-"dmoS7jeskS","JKWYRl83Ud","3otm6Ta8f6","9iGoTyluBx","tAOsr5IhmG","TCgPpJkzUn","jiVBPK4GS8","FGzgpRkQke","Pb1pay94nw","uQIczksJby",
-"RsQUqpiJSk","QbxXcv1Hln","qUJMdNAFuw","Mm8siYw2oU","5Mg9rrKDLJ","M6qcGuZPqg","KsjRK7Ow5C","HRxd8d7vjM","iqv4kk85Ae","CK5W7euZA5",
-"B3qemJkzUn","cShY2AkKTk","CqqaDlH1kt","POUYSNOHsz","BCxeCYw2oU","KsjRK8xEKz","1j5L8zmLYD","d85a9XyPZN","d7vjMOz8yZ","L7cGcECMvU",
-"YjB9tcmXIX","AXpwEAOgEe","9y4lw8xEKz","Nxx9VStlDJ","t98iWZJTXH","5drc6m4bxU","GrDg7WmadA","4QMc9v2eC3","F6PT2kZANm","CdyBVyEfy9",
-"RxrsmtaOXK","uQIczjzUqR","cmXIXNhXdu","cQOnvRkQke","CxVEfRkQke","GXdoHzbIYY","NhXduRkQke","AkKTkWDVWJ","lm0pDuZPqg","pmeCdtjQxs",
-"8RCUAjiVBP","b29RJFGzgp","o8UydVerEA","StlDJxciqp","0BmCyzY1GY","tuDySpFrrl","SjskQnlaBy","BbwgAbrhlQ","zmLYDuJScX","CdyBVQssNC",
-"JkzUnrKDLJ","TwanoIKxdL","BpYhVulk41","l83Ud7fKYU","6q6L9LewvM","iqv4klweGy","NOHsztuDyS","UlU3MpmeCd","NcICAnnP8o","0MR5X0YAGH",
-"he9IAm4bxU","guMb814FLR","aL6AJfcwDa","HfyNQMezSW","gtCA524ARF","RzaZAuTacx","MK07YPYBf4","fqypyxXTI4","ThjNn6q6L9","jzUqRjfREu",
-"LewvMfFDrJ","8hJdtpFrrl","AXpwEzHF1q","FPfSERBhp0","xReec1v5hH","GrDg7brhlQ","ZJTXHCfgr3","jtn0XTXQ0Z","o8UydZJTXH","gf8rIoGu6x",
-"FhtglJKWYR","guMb8fmIK1","HzZT81LB1L","tvdkD2ZHdk","VerEAJIqXi","hYBCKK20wK","euZA5RpBQm","i7WMQ2TRI7","WaWsvfLNg8","xciqpGrDg7",
-"s93MlOxWIH","hE1QlSjskQ","KASQ8VjCZq","x3LDet59lR","JIqXiksJby","cmXIXM3zXL","Yh1hF9iGoT","J2mQi9rlg9","FFDuiHP433","ix74rlm0pD",
-"lH1ktuoStw","ZJTXHaL6AJ","cL0aE5Namm","tlILtprNT6","fqypylkMUA","MaJQsNcICA","UlU3MJIqXi","t98iWBCxeC","uLtKsQworu","2TRI7WPmlx",
-"fcJOyMaJQs","jSjS3uAWyp","zmLYDRxrsm","5Mg9rfcJOy","okgRi1v5hH","5Namme6e4z","7lUXZJkzUn","iB08lCqqaD","0Kyfszz4ZU","Y1mC0EdBKc",
-"9XyT9soy9t","FcWrW3otm6","fmIK17fsYM","IBe8k8hJdt","7X3uy1LB1L","BGaQYoVQp6","2DREsTwano","lCMxy8RCUA","rz7UtUl4a1","taOXKAIYUu",
-"1LB1LReKEW","s7MxkiB08l","xReec4QMc9","a00b57lUXZ","TXQ0ZStlDJ","2ZHdk0YAGH","VLTy6s93Ml","nFqikuvf7A","QbxXcVprf2","uoStwAXpwE",
-"zHF1q3otm6","cShY2NcICA","Ss0ZuzHF1q","CqqaDCfgr3","7fKYUUvlv4","jeskSn1pmO","DcpWBqUJMd","y94nwhYBCK","wDajXLbRTH","soy9t8FmFH",
-"XflUquoStw","NhXduaez9y","Ss0ZumX2GE","OHaBzFPfSE","BpYhVBbwgA","oGu6x8cVD3","M6qcGeuZA5","7X3uydjsrv","tlILtEdBKc","4W0TltAOsr",
-"oVQp6X6Pin","9eoRcx3LDe","lweGyCIShG","iwzGk16lHc","5ZaEzbZLvS","gIYvENo0Qb","sx5GlhSSvQ","lCMxyNhXdu","fqypy5Mg9r","Rxrsm7ku1p",
-"bZLvStvdkD","l83UdBGaQY","2NslmGv3Fq","DQimpWPmlx","CdyBVBGaQY","2DREs7ku1p","MmsIoFVMxo","POUYSWMiS3","tjQxsS77LH","kB5nPFGzgp",
-"YjB9taL6AJ","EoToPokgRi","Ta8f6aL6AJ","suY4x7hyVv","FPfSEh1zcH","9y4lwGWqqX","zmLYDd85a9","JIqXi3weIF","ru4UGQ6hMC","2hEEUi3pyd",
-"zqH0W7hyVv","pWiOssoy9t","0PktIB3qem","lpF6WHP433","jeskSzY1GY","uQIcztlILt","hUTw72Yz7E","jeskSZzJHW","bgJAzCxVEf","djsrvuLtKs",
-"7lUXZ8U2nU","ru4UGChuy3","29QAzNAFuw","EoToPdQ586","bgJAzjSjS3","xciqpKsjRK","9eoRc6AFT0","ZJTXHBCxeC","14FLRb29RJ","GWqqXY1mC0",
-"jeskSMm8si","sx5GllCMxy","fmIK13weIF","XyPZNG1RhS","wDajXrhl0J","7lUXZPYBf4","AmdQdjSjS3","dpe1v7lUXZ","ix74r1j5L8","Dz1R3Yw2oU",
-"SmGzvzqH0W","RzaZA2hEEU","8TxD7M3zXL","CNHmvzHF1q","sqVrfNcICA","FVMxotjQxs","uoStwMezSW","k85AeX6Pin","vkCHHRpBQm","Waim6d7vjM",
-"pT8wuQClRL","fLNg8ni2v1","2TRI7CxVEf","SjskQ0h1b1","LewvMM3zXL","7X3uyAkKTk","HP433LewvM","P6bcg9y4lw","tAOsrprNT6","lm0pD9eoRc",
-"JkzUn2Nslm","guMb8ZuDtD","LbRTHVerEA","bgJAzHlUbF","m4bxU5VZjS","zqH0W16lHc","fcJOyYw2oU","yofH3lCMxy","QWxoToQ87r","v8yFNGXdoH",
-"FhtglBFkb8","BFkb8yToGW","o8UydtuDyS","zbIYYx3LDe","HfyNQlm0pD","k85AeblLA9","guMb8Rxrsm","d85a9n8pJ9","lj07Q5IhmG","azIWpsuY4x",
-"8U2nUuvf7A","ZzJHWm4bxU","EoToPaL6AJ","Yh1hFlViBv","FFDuidhSuH","618Di580YD","D6rBySWfou","9eoRc9rlg9","aez9y580YD","jS1aj3otm6",
-"0MR5X7Ow5C","ECMvU07n1c","VLTy6KZamH","zqH0WazIWp","No0QbPb1pa","h1zcHlCMxy","jfREu2ZHdk","uLtKsxXTI4","MezSWVIlwP","AOgEeokgRi",
-"uPX7GOUqFM","lweGyVNCPd","Mm8sinlaBy","aFFssI7p2a","0BmCy5Drn0","Yw2oURACuj","mz8gxk85Ae","MmKGJv1Hln","aez9yuAWyp","W3VFHgtCA5",
-"QnJ1SyEfy9","Q6hMCs93Ml","gjUTu24ARF","In3NS5IhmG","Qworu7fsYM","uvf7APOUYS","mz8gxlCMxy","KASQ8HP433","v2eC3faHir","gjUTuZhwG1",
-"SbRYyYh1hF","GrDg7rhl0J","RkQkeuN6r3","W7cTsBpYhV","0ao3lQChxs","29QAzTCgPp","jS1ajaL6AJ","WDVWJQnJ1S","GSQwjlXFOB","0BmCyYjB9t",
-"8xEKzjS1aj","5nmWvo8Uyd","QnJ1SaL6AJ","mX2GERmDcr","nFqikuJScX","jfREu8cVD3","m4bxUcL0aE","xXTI4FjHXR","NAFuwZUnqt","QYxC0dpe1v",
-"29QAz618Di","YjB9tpAhR1","Cfgr3dQ586","hUTw7ZzJHW","0YAGHQssNC","ksJbyt98iW","lweGyMm8si","mz8gxiB08l","b29RJ9rlg9","okgRiaL6AJ",
-"vkCHH7X3uy","l83UdVLTy6","Cfgr3LewvM","tjQxsO3iyQ","J2mQiCdyBV","SWfouyToGW","s93MlaL6AJ","YjB9tIn3NS","JRJQBM3zXL","mX2GED6rBy",
-"dQ586guMb8","m4bxUL7cGc","s7MxkSjskQ","mX2GE5VZjS","RBhp0s93Ml","5iGN5QChxs","4dEz68hJdt","5Drn014FLR","djsrvlj07Q","jtn0X6AFT0",
-"vkCHHo8Uyd","7lUXZkB5nP","t59lRyofH3","RpBQmKr8ys","7X3uyQbxXc","OHaBzn1pmO","fcJOyQChxs","Yf2Ec5Mg9r","24ARF64s8N","4QMc9yofH3",
-"9iGoTlkMUA","LDk6fGWqqX","QbxXcQClRL","brhlQReKEW","XyPZNpmeCd","QworuPOUYS","GXdoHRkQke","s93MlU3yw5","Yh1hFatef2","azIWp07n1c",
-"rhl0JVNCPd","HfyNQuN6r3","uvf7AfcJOy","SWfoudpe1v","QWxoT2TRI7","AXpwEa00b5","qaofNMmsIo","3otm6580YD","mz8gxW3VFH","0h1b1b29RJ",
-"DQimpVjCZq","yvOMItl72W","K20wKRxrsm","v2eC36AFT0","CIShGTCgPp","Cfgr3FwEJz","lCMxy0YAGH","dmoS7AkKTk","hUTw7nFqik","55rfBzz4ZU",
-"azIWpMezSW","NAFuwEoToP","4QMc95iGN5","Q6hMC7ku1p","v1HlnokgRi","Ul4a1OUYuF","K20wKpFrrl","a00b5uLtKs","5drc6MGlTF","TXQ0Zt59lR",
-"GSQwjQnJ1S","jeskS07n1c","tlILt3weIF","2Yz7EFNYIM","Ul4a1jS1aj","CxVEfMojnP","jtn0Xs93Ml","EoToPQssNC","RkQkeNOHsz","nlaByDG4sT",
-"uLtKs1LB1L","SWfouOHaBz","I7p2aIn3NS","okgRiuLtKs","uQIczuAWyp","Nxx9VUlU3M","BGaQY1v5hH","hSSvQZzJHW","euZA5xReec","RkQkeNhXdu",
-"oVQp6QChxs","x3LDeNxx9V","tjQxsG1RhS","blLA907n1c","IRh48fFDrJ","hE1Qldpe1v","2DREsyEfy9","ulk419GXkX","POUYSJJs5m","cL0aEeuZA5",
-"Q6hMC1j5L8","iqv4kOz8yZ","oVQp6vOqCE","OUqFMSbRYy","MmKGJEOE1o","brhlQ8cVD3","v2eC3HlUbF","l83UdgtCA5","2NslmFGzgp","5iGN5StlDJ",
-"AXpwEUvlv4","Pb1pa1j5L8","s93MlEOE1o","3otm67ku1p","ECMvUMm8si","s4786azIWp","gf8rIsx5Gl","fqypyzmLYD","VjCZq8FmFH","BGaQYpFrrl",
-"ZuDtD7ku1p","MaJQsUvlv4","ZJTXHK20wK","Yf2Ec7X3uy","QbxXcnFqik","lj07Qs4786","Ss0ZupWiOs","hi5X7LbRTH","FcWrWuPX7G","Uvlv4618Di",
-"G1RhSuLtKs","Pb1paUl4a1","YjB9tB3qem","i7WMQpFrrl","IKxdLNxx9V","pWiOsoVQp6","ZJTXHuZPqg","jSjS3EoToP","FVMxoDz1R3","2TRI7J2mQi",
-"CxVEfs7Mxk","5VZjSuN6r3","uvf7AiB08l","Vprf2h1zcH","cmXIXulk41","jS1ajRBhp0","zHF1q580YD","HfyNQTCgPp","MmsIoVerEA","StlDJFhtgl",
-"XflUqAgJHQ","hYBCKQbxXc","RsQUqI7p2a","lkMUA5Mg9r","pFrrlBbwgA","WDVWJv8yFN","iB08lYf2Ec","X6PinpmeCd","Kr8ysCIShG","Ta8f6zmLYD",
-"uPX7G0Kyfs","MGlTFAIYUu","d85a9S77LH","0Kyfsrz7Ut","xXTI4ru4UG","14FLRs4786","he9IA2Nslm","07n1cyluBx","QnJ1SQnJ1S","WPmlxHP433",
-"iB08lQssNC","e6e4zAOgEe","B3qemm4bxU","pT8wuQworu","hUTw70Wr5y","jS1ajpiJSk","ZhwG1HP433","rz7UtAIYUu","tAOsr07n1c","RACujC2Irc",
-"ZzJHW5Mg9r","jS1ajAXpwE","SWfouWMiS3","gIYvEiwzGk","HP433Gv3Fq","FPfSEcQOnv","jtn0XTwano","suY4x0ao3l","fFDrJeuZA5","soy9tpFrrl",
-"ix74rhYBCK","7Ow5C9rlg9","i7WMQCp3mZ","iKqhrUl4a1","9rlg9SWfou","VBjhzIBe8k","29QAzFxX9q","lkMUARsQUq","0Kyfs4dEz6","D6rByWmadA",
-"MaJQsCfgr3","HlUbF2hEEU","hi5X7zmLYD","LbRTHnlaBy","5Drn0dpe1v","JJs5mru4UG","lweGySbRYy","7ku1pzqH0W","ZJTXHW7cTs","t98iW2TRI7",
-"NhXdu5Drn0","hi5X75VZjS","OxWIHYf2Ec","ZUnqtdjsrv","JkzUn2ZHdk","0MR5Xn8pJ9","C2IrcU3yw5","4W0TlZv7z0","AgJHQgjUTu","5Drn0Y1mC0",
-"7X3uyiqv4k","SWfou0h1b1","dpe1vn1pmO","vLsmS5ZaEz","5NammnlaBy","5iGN5WDVWJ","faHir1LB1L","tlILtNOHsz","HRxd8t98iW","qQxHPbgJAz",
-"DLhzMWaWsv","VLTy6In3NS","F6PT2kB5nP","TXQ0ZEoToP","OHaBzgIYvE","gIYvEVerEA","Vprf2mz8gx","OUYuF9rlg9","0Wr5y618Di","fqypyRBhp0",
-"RzaZAiqv4k","x3LDedmoS7","M3zXLUl4a1","FGzgpmX2GE","NOHszHP433","soy9tQssNC","fmIK1hE1Ql","nnP8o2Yz7E","fcJOyqQxHP","Ul4a1n1pmO",
-"MmsIoWMiS3","tAOsrAmdQd","5Mg9r5drc6","yEfy9zqH0W","FjHXRW3VFH","5nmWvQChxs","PYBf4cShY2","pWiOsx3LDe","DQimpThjNn","24ARFsx5Gl",
-"HP433pmeCd","BFkb8nnP8o","cL0aE0MR5X","45cIHb29RJ","7hyVvK4GS8","618DiWMiS3","OxWIHfLNg8","sx5GlIKxdL","B3qemjiVBP","lH1ktCIShG",
-"Cp3mZDLhzM","HRxd8LewvM","zqH0WQChxs","W3VFH7lUXZ","0MR5XQssNC","azIWp2hEEU","7lUXZlsQGo","9XyT92DREs","KZamHogLgc","wDajXzqH0W",
-"3otm6Vprf2","AmdQdJJs5m","MezSW5Namm","uJScXSs0Zu","KZamHGWqqX","pv0i7uupzk","BbwgAAOgEe","qUJMd5VZjS","zY1GYdQ586","uoStw24ARF",
-"ZzJHWoVQp6","ydG8UfLNg8","M3zXLD6rBy","qQxHPs7Mxk","dmoS7Yf2Ec","Yw2oUjtn0X","EOE1oJkzUn","blLA9iB08l","FLspha00b5","EoToPFLsph",
-"IjTwPXflUq","zQt6QmX2GE","6q6L9zQt6Q","RpBQmlkMUA","S77LHguMb8","s7MxktaOXK","piJSkiqv4k","b29RJfaHir","GWqqX9XyT9","he9IAhi5X7",
-"2Nslm45cIH","tAOsrF6PT2","580YD8U2nU","JJs5mnnP8o","blLA9MK07Y","29QAzFnPFB","rKDLJuTacx","48cHLFPfSE","Uvlv4Q6hMC","jS1aj0MR5X",
-"mz8gx7ku1p","MojnPJ2mQi","S77LH9XyT9","8FmFHpv0i7","tAOsrnlaBy","VNCPdb29RJ","d85a9pAhR1","Ul4a1vkCHH","nlaBytjQxs","yluBxGWqqX",
-"FGzgpuTacx","FFDuiWaWsv","dmoS7QssNC","JkzUns7Mxk","OHaBz0Kyfs","hUTw7DQimp","RzaZAQssNC","sx5GltjQxs","618DifLNg8","v8yFNQWxoT",
-"EdBKcgf8rI","0h1b1Mm8si","uPX7Gni2v1","X6PinqUJMd","DLhzM0h1b1","xXTI4ZuDtD","TXQ0Z29QAz","5nmWv0ao3l","wiHrZ1v5hH","Ul4a1kB5nP",
-"gdQsSaez9y","hE1QllweGy","StlDJ0BmCy","BGaQYv2eC3","qaofNNAFuw","580YDa00b5","KASQ8d85a9","FjHXRd7vjM","IKxdLAkKTk","kB5nPVNCPd",
-"tjQxswDajX","D6rByuvf7A","GWqqXWmadA","fqypyvOqCE","M3zXLY1mC0","gf8rIuJScX","Q6hMC618Di","IBe8kulk41","AkKTkTwano","CqqaDiB08l",
-"pT8wuWMiS3","ZJTXHBpYhV","suY4x5Namm","K4GS8wDajX","8TxD7IBe8k","RkQke5nmWv","ksJbyFFDui","8U2nUWDVWJ","Yw2oUQ6Lix","tl72WwiHrZ",
-"FPfSErhl0J","FxX9qAgJHQ","45cIHVNCPd","jiVBPXyPZN","m4bxUxReec","yofH37fKYU","X6PinuN6r3","MGlTFpAhR1","9rlg9JXljW","Oz8yZoGu6x",
-"m4bxUlH1kt","MezSW3otm6","6q6L9sqVrf","ZJTXHfcwDa","XyPZNjeskS","QssNCuLtKs","DG4sTYOfrY","pv0i7brhlQ","MGlTFn1pmO","l83UdMojnP",
-"blLA924ARF","2DREsm4bxU","AmdQdnnP8o","FnPFBx3LDe","uupzkHP433","gdQsSoVQp6","oVQp6KsjRK","0Wr5yfmIK1","ZJTXH7lUXZ","lkMUAyvOMI",
-"xciqpNo0Qb","9iGoTiwzGk","cQOnvl83Ud","Q6hMC16lHc","4QMc9MezSW","Waim6b29RJ","uTacx7hyVv","tlILtzz4ZU","hE1Qlpv0i7","prNT6D6rBy",
-"QWxoTFLsph","UlU3MX6Pin","sx5GluJScX","YjB9tWMiS3","nnP8ojSjS3","MmKGJVjCZq","S2DfuyluBx","QssNCa00b5","h1zcH16lHc","7hyVvQ6Lix",
-"UmaEvCqqaD","pAhR1i3pyd","RmDcrOxWIH","POUYSEoToP","2hEEU07n1c","ZuDtDIn3NS","6AFT0G1RhS","CK5W74dEz6","jtn0XbrhlQ","y94nwoGu6x",
-"29QAzvLsmS","ciuWzJXljW","tl72WlViBv","GSQwj0Kyfs","7Ow5C3otm6","oGu6xRxrsm","4QMc9QssNC","he9IA9eoRc","CIShGWDVWJ","pFrrlCp3mZ",
-"aez9yuPX7G","jiVBPWPmlx","RxrsmtuDyS","dpe1vprNT6","Dz1R3lCMxy","Kr8yssoy9t","5Mg9rix74r","ECMvUfcJOy","Ta8f6MojnP","16lHcjS1aj",
-"cmXIXECMvU","IRh48uQIcz","blLA9580YD","WaWsvAXpwE","iB08lh1zcH","Chuy3jtn0X","I7p2a9rlg9","QssNC7fKYU","8cVD3zqH0W","OxWIHBCxeC",
-"blLA9JXljW","jzUqRWaim6","ZuDtDfFDrJ","618Din1pmO","LDk6f1j5L8","5iGN5KsjRK","WmadA6q6L9","9rlg9CxVEf","lm0pDIKxdL","rhl0JX6Pin",
-"0PktIGrDg7","tl72Wix74r","i3pydlpF6W","UmaEvksJby","zmLYDGWqqX","rhl0Jatef2","MGlTFM6qcG","s93MlNAFuw","HP433yvOMI","ogLgc0YAGH",
-"zQt6QJ2mQi","JIqXituDyS","W3VFHzmLYD","5NammzqH0W","lm0pDY1mC0","iB08llpF6W","Ss0ZuJXljW","BbwgABCxeC","Q6hMCGSQwj","JRJQBMojnP",
-"Ta8f6IKxdL","b29RJZhwG1","ZJTXH4dEz6","CqqaDBCxeC","FwEJziKqhr","atef2CdyBV","W7cTspT8wu","9rlg9DcpWB","xXTI4ZUnqt","zQt6QyluBx",
-"Q6LixzY1GY","HfyNQThjNn","hE1QlFxX9q","jeskS1LB1L","o8Uyd5IhmG","S2Dfu4W0Tl","QssNCgjUTu","55rfBd7vjM","uvf7ARsQUq","y94nw7ku1p",
-"atef2tuDyS","RpBQmpmeCd","lweGybZLvS","Vprf2nlaBy","QnJ1Sru4UG","zFgtBs4786","0BmCyKASQ8","3weIF0Kyfs","v2eC3ZzJHW","mz8gxAXpwE",
-"ulk41ulk41","wiHrZt59lR","lkMUAHRxd8","zz4ZUOxWIH","X6PinFnPFB","W3VFHNAFuw","hE1QluZPqg","fmIK1FnPFB","7fKYUwiHrZ","8xEKzRmDcr",
-"pAhR14QMc9","2NslmGXdoH","uupzkSs0Zu","Yw2oUaDGtS","UmaEvAmdQd","zqH0W0YAGH","NcICATXQ0Z","K4GS8K4GS8","ThjNnfLNg8","uJScXYOfrY",
-"HlUbFFLsph","0Kyfsy94nw","ulk41W3VFH","PYBf4Y1mC0","3otm6pv0i7","EoToP6AFT0","lXFOB4dEz6","VBjhzBbwgA","QWxoTQWxoT","7Ow5CVjCZq",
-"pT8wupmeCd","L7cGcoGu6x","S2DfugjUTu","d7vjMMK07Y","5ZaEz4dEz6","VLTy6Chuy3","VjCZq5iGN5","GXdoHQssNC","HlUbFQssNC","FNYIMTXQ0Z",
-"qUJMdx3LDe","QYxC0RpBQm","RzaZAFxX9q","5nmWv9rlg9","QWxoTqaofN","FcWrW8RCUA","uZPqgVLTy6","FhtgljzUqR","55rfBrz7Ut","jS1ajd7vjM",
-"m4bxUFLsph","rKDLJTa8f6","55rfBChuy3","JKWYRaez9y","gjUTu6AFT0","piJSkZ4I1v","DLhzMWMiS3","sqVrfSbRYy","WmadA9GXkX","U3yw5ZUnqt",
-"NAFuwoQ87r","DLhzMjfREu","FjHXRokgRi","5Mg9rlViBv","ru4UGjfREu","Z4I1vprNT6","pv0i7UlU3M","RACujgIYvE","uvf7AFGzgp","yToGWXflUq",
-"WPmlxRzaZA","CIShGdmoS7","iKqhrcL0aE","7fsYMFGzgp","7hyVvCxVEf","i7WMQMaJQs","BFkb87fsYM","l83UdWMiS3","yvOMIni2v1","dpe1vpAhR1",
-"zbIYY3otm6","FhtglEOE1o","tlILtYOfrY","7fsYMiKqhr","0MR5XQ6Lix","NhXdus7Mxk","MojnPogLgc","yluBx0Kyfs","HP43364s8N","AXpwEQWxoT",
-"pv0i7sx5Gl","8TxD7HzZT8","7fsYMyvOMI","0h1b1n8pJ9","qaofNsoy9t","SbRYyOUYuF","d85a9jS1aj","VIlwPTXQ0Z","lsQGoaL6AJ","wiHrZzFgtB",
-"D6rByS2Dfu","HfyNQuTacx","dmoS7n8pJ9","jSjS3Ta8f6","l83Ud1LB1L","fFDrJx3LDe","QChxsJKWYR","55rfBTwano","qQxHPS77LH","VerEAPOUYS",
-"aDGtSTa8f6","iKqhrLDk6f","C2Irco8Uyd","e6e4zv2eC3","GrDg7uZPqg","HlUbFFcWrW","Q6hMCUmaEv","atef2FnPFB","hE1QlCNHmv","prNT6Z4I1v",
-"l83UdlViBv","GWqqXWaim6","7Ow5CoVQp6","1j5L8dmoS7","jeskSsuY4x","MaJQskZANm","s4786dQ586","Q6hMCeuZA5","lj07QnnP8o","uAWypvLsmS",
-"WreyPO3iyQ","vOqCEokgRi","aFFssuQIcz","3weIFUmaEv","5IhmGk85Ae","zFgtB8U2nU","8cVD3JRJQB","VNCPddjsrv","i7WMQv8yFN","5IhmGNAFuw",
-"D6rByXflUq","guMb8OUYuF","7X3uyJIqXi","AIYUu48cHL","GWqqXQbxXc","ZhwG1n1pmO","JXljWRBhp0","ReKEWCqqaD","aDGtSfcwDa","QnJ1ShSSvQ",
-"uJScXKZamH","uN6r3uQIcz","lViBvpFrrl","d7vjMyToGW","YjB9tpmeCd","jzUqRdmoS7","DQimpTa8f6","mX2GEhUTw7","5drc6lm0pD","FwEJzbrhlQ",
-"cShY28xEKz","Kr8ysEOE1o","64s8N0BmCy","F6PT2Chuy3","ZzJHWbgJAz","QWxoT8xEKz","ciuWzWaim6","G1RhSdhSuH","Ta8f6ZuDtD","o8UydxReec",
-"oGu6xhSSvQ","RxrsmgIYvE","tvdkD4dEz6","ciuWzCqqaD","K20wKfLNg8","ru4UG8hJdt","kB5nP8TxD7","XyPZNOUqFM","K20wKhe9IA","uLtKsRsQUq",
-"PYBf4t59lR","fcJOyRsQUq","tl72We6e4z","djsrvcL0aE","1v5hHGWqqX","HzZT80MR5X","bgJAzRmDcr","Q6Lix4QMc9","okgRiBFkb8","pT8wuDLhzM",
-"vkCHHYh1hF","7ku1p2Yz7E","6q6L9HRxd8","ZzJHWUlU3M","jiVBPoVQp6","uQIczNo0Qb","soy9tqUJMd","TXQ0Z2Nslm","2Yz7E8xEKz","Yf2EcNOHsz",
-"gtCA5fLNg8","pT8wu9XyT9","OHaBzOUqFM","faHirQ6Lix","Waim6a00b5","kZANmaDGtS","oQ87rsoy9t","hE1Ql0ao3l","7lUXZfFDrJ","55rfBBFkb8",
-"lkMUAlkMUA","JIqXiZv7z0","lj07QnlaBy","3otm6FjHXR","yluBxL7cGc","ix74r45cIH","SWfouAOgEe","SjskQQworu","k85AeThjNn","RkQkeIRh48",
-"Yh1hFblLA9","SWfouvkCHH","5nmWvYw2oU","24ARF0PktI","FcWrWcL0aE","vLsmSs4786","Chuy3yofH3","mz8gxCK5W7","uupzkzqH0W","2TRI7JRJQB",
-"0YAGHQ6Lix","D6rByUl4a1","qQxHPReKEW","U3yw5pv0i7","AmdQdiKqhr","OUYuF24ARF","yEfy9JJs5m","G1RhSt98iW","Gv3FqK4GS8","P6bcguLtKs",
-"5VZjS45cIH","WPmlxgdQsS","qQxHPFhtgl","5nmWvpmeCd","8RCUA9y4lw","D6rByy94nw","1v5hHBFkb8","gf8rIlH1kt","qaofNMezSW","KZamHkZANm",
-"BGaQYuupzk","n1pmOoQ87r","nFqikjiVBP","Uvlv4VerEA","Zv7z0sqVrf","Ta8f6NAFuw","Yh1hFtlILt","5ZaEzzY1GY","2DREsfqypy","CxVEfTXQ0Z",
-"NOHszWaim6","lCMxylXFOB","J2mQilXFOB","HzZT8Fhtgl","5NammAOgEe","0ao3lqUJMd","Ta8f6gtCA5","ZUnqtblLA9","W7cTsYf2Ec","qaofNUl4a1",
-"ogLgcVLTy6","zbIYYs93Ml","IKxdLOUqFM","WPmlxGSQwj","Qworu9iGoT","B3qemZUnqt","pT8wuWmadA","Yf2EckB5nP","RBhp016lHc","pvgjSKr8ys",
-"7hyVvFhtgl","Q6LixMK07Y","RzaZACfgr3","EoToPblLA9","ZzJHWQssNC","gdQsSIKxdL","jiVBPb29RJ","AOgEe2TRI7","2NslmzHF1q","xciqpQnJ1S",
-"b29RJtjQxs","tl72WNhXdu","bgJAzY1mC0","pvgjSJXljW","aDGtSEoToP","lViBvZJTXH","Oz8yZdmoS7","Uvlv41v5hH","sx5GlChuy3","5nmWvWDVWJ",
-"OHaBzdpe1v","Mm8si0Kyfs","S2DfuW3VFH","QworuAgJHQ","9iGoTLbRTH","l83UdIRh48","t59lRSmGzv","fcwDaWaim6","rKDLJI7p2a","U3yw50h1b1",
-"IBe8kpWiOs","KsjRK24ARF","rz7UtqQxHP","Q6LixUvlv4","7hyVvEdBKc","WPmlxFnPFB","hYBCK2ZHdk","pmeCdpiJSk","Mm8si7ku1p","Q6hMCFLsph",
-"yluBx9rlg9","DcpWBF6PT2","7hyVvnFqik","Mkgy8Ul4a1","VNCPdMezSW","aez9y0BmCy","tvdkDaFFss","lH1kt9rlg9","vkCHHbgJAz","lCMxyRpBQm",
-"Mkgy8UmaEv","hi5X7WreyP","VjCZqzbIYY","HlUbF07n1c","Kr8ysuupzk","QnJ1S9GXkX","W7cTshi5X7","NcICAvkCHH","zHF1quZPqg","TCgPpMmKGJ",
-"suY4xkB5nP","K4GS8Cfgr3","aL6AJHP433","Q6Lix9rlg9","C2IrcnFqik","ZuDtD580YD","faHir4QMc9","29QAzOUqFM","QClRLHlUbF","XyPZNFLsph",
-"Kr8yspmeCd","fLNg8JJs5m","Y1mC0BGaQY","UmaEvCIShG","mX2GEFLsph","HP433Q6Lix","Y1mC0WMiS3","MmKGJlH1kt","Pb1paEOE1o","FcWrW5drc6",
-"Ta8f6VjCZq","IKxdLAIYUu","QChxsVBjhz","StlDJIKxdL","XyPZNn8pJ9","Qworu7lUXZ","AIYUujS1aj","zHF1qWaWsv","5nmWvzbIYY","SbRYya00b5",
-"48cHLhi5X7","VIlwPLDk6f","16lHct98iW","uZPqgEoToP","zmLYDqUJMd","guMb8ciuWz","AmdQdjiVBP","0h1b1ZhwG1","X6PinCNHmv","2Nslm7hyVv",
-"pWiOsQssNC","ciuWz5IhmG","0Wr5y9XyT9","wDajXNxx9V","tlILtv8yFN","NAFuwgf8rI","Vprf23otm6","jS1ajCdyBV","4W0Tl7hyVv","DLhzMhi5X7",
-"2NslmFxX9q","h1zcHuPX7G","s93MlRACuj","uZPqgFxX9q","IjTwP14FLR","TXQ0ZsuY4x","pFrrlJXljW","ZUnqtzmLYD","OHaBzTa8f6","I7p2ajSjS3",
-"5IhmGtlILt","Pb1paPb1pa","okgRi7ku1p","AOgEepAhR1","cQOnv7hyVv","ydG8Urhl0J","NOHszSWfou","atef2xXTI4","oGu6xMaJQs","OHaBzuLtKs",
-"h1zcHqQxHP","vOqCExciqp","SbRYyatef2","AIYUuZv7z0","DcpWBRsQUq","K4GS8MojnP","AOgEeuvf7A","uN6r3EdBKc","jeskSReKEW","soy9txXTI4",
-"xXTI4MaJQs","I7p2agf8rI","HfyNQs93Ml","3weIFpmeCd","JKWYRGXdoH","WmadAi3pyd","wiHrZSjskQ","Uvlv4DG4sT","Nxx9VtjQxs","ksJbytjQxs",
-"FjHXRUl4a1","JIqXiaez9y","MmsIouJScX","0MR5XhSSvQ","Mkgy8euZA5","6AFT0CNHmv","QnJ1S24ARF","n1pmOQssNC","BGaQY6AFT0","1v5hHM6qcG",
-"lweGyVIlwP","5ZaEzEoToP","mz8gxlm0pD","TwanoYh1hF","kB5nPlH1kt","dmoS7sqVrf","TXQ0ZoQ87r","X6PinzHF1q","Mkgy8AIYUu","5iGN507n1c",
-"PYBf4hSSvQ","iKqhre6e4z","64s8Nfqypy","0MR5XfLNg8","XflUqUl4a1","KsjRKbrhlQ","a00b5jiVBP","7X3uyTa8f6","CqqaDlViBv","9XyT955rfB",
-"nnP8olsQGo","s4786zY1GY","EOE1o5iGN5","BpYhVRACuj","EOE1oblLA9","DcpWBWMiS3","VBjhzNxx9V","guMb8ni2v1","B3qemVerEA","dmoS73otm6",
-"5IhmGuPX7G","jzUqRUl4a1","S77LHhYBCK","FhtglPb1pa","l83Ud8TxD7","s93Mlatef2","lkMUAv1Hln","Mm8siprNT6","8cVD3lweGy","L7cGcwDajX",
-"NhXduvOqCE","uPX7GDG4sT","fcwDav8yFN","7lUXZk85Ae","he9IAC2Irc","yofH3iB08l","CxVEft98iW","MGlTFpmeCd","VLTy6FPfSE","Q6Lix0MR5X",
-"VNCPdFhtgl","FwEJzn8pJ9","RACuj2DREs","wiHrZ4dEz6","t98iWCqqaD","7ku1pDLhzM","KASQ8Z4I1v","NOHsz6AFT0","lm0pD5Mg9r","zmLYDuN6r3",
-"8RCUAaDGtS","s93MlDcpWB","FFDuicQOnv","KsjRKn8pJ9","aDGtSZJTXH","WmadARxrsm","lsQGouJScX","2hEEUoVQp6","FPfSEs4786","2Yz7EuoStw",
-"YjB9tNOHsz","ZzJHWHlUbF","S2DfufcJOy","Chuy3DcpWB","W7cTsi3pyd","5nmWvtjQxs","CK5W77fKYU","aL6AJSWfou","uAWypIjTwP","7hyVviB08l",
-"CdyBV0Wr5y","QnJ1SGrDg7","29QAzF6PT2","lCMxybgJAz","CIShGNhXdu","0h1b1t59lR","4QMc9FLsph","HlUbFRpBQm","AIYUubrhlQ","y94nwvLsmS",
-"lsQGoGWqqX","fqypyDLhzM","FGzgpBFkb8","K20wKaez9y","bgJAztaOXK","HRxd8Q6hMC","9rlg9MaJQs","oVQp6GWqqX","cQOnvxciqp","VNCPdNo0Qb",
-"CdyBVOHaBz","EOE1oJRJQB","8FmFHDcpWB","vLsmSmz8gx","jfREuOxWIH","FhtglIRh48","JIqXiMK07Y","ThjNnaDGtS","6q6L9OxWIH","ogLgct98iW",
-"nlaByCIShG","DG4sTcmXIX","uJScXzY1GY","Mkgy8GrDg7","StlDJ9eoRc","RACujcQOnv","ulk41U3yw5","vLsmSCxVEf","64s8Nv1Hln","MmsIov1Hln",
-"zbIYY5nmWv","WreyPgIYvE","uAWypS77LH","EoToPOxWIH","NAFuw2Nslm","hi5X7Waim6","EOE1o5nmWv","lj07Q24ARF","VIlwPNAFuw","pT8wuvLsmS",
-"tAOsrFGzgp","S2DfulkMUA","0MR5XRBhp0","B3qemG1RhS","oGu6xMmKGJ","S77LHVerEA","xReec8cVD3","B3qemn8pJ9","dmoS7fmIK1","atef2VBjhz",
-"UlU3MWreyP","hi5X7DG4sT","Nxx9Vm4bxU","580YDjfREu","NcICA5iGN5","DcpWBHzZT8","cShY2cQOnv","hUTw7NOHsz","SbRYyWreyP","618DiTwano",
-"lViBvJKWYR","AkKTkaL6AJ","s93Mlh1zcH","SmGzvEdBKc","Nxx9Vatef2","JKWYRNhXdu","L7cGcCqqaD","EoToPhi5X7","suY4xuZPqg","cShY2dQ586",
-"BpYhVVprf2","uZPqgaL6AJ","5Drn0Mm8si","RBhp00Wr5y","O3iyQjfREu","9iGoTpvgjS","QbxXccShY2","ru4UGqaofN","B3qemiB08l","oGu6xdmoS7",
-"Mkgy8OUYuF","RsQUqY1mC0","lm0pD4W0Tl","5drc60PktI","ogLgcZuDtD","JkzUnzQt6Q","NcICA6q6L9","5nmWvn1pmO","FnPFBRmDcr","Cp3mZs93Ml",
-"hE1QlJkzUn","mz8gxuLtKs","14FLRdmoS7","jzUqRFPfSE","Nxx9VTXQ0Z","JKWYR4W0Tl","M3zXLBGaQY","yvOMIOUYuF","K4GS8x3LDe","DQimpMK07Y",
-"s4786tAOsr","ksJbyDcpWB","OxWIH7Ow5C","mz8gx5drc6","m4bxUatef2","m4bxUtlILt","7Ow5CWreyP","5iGN5aL6AJ","Uvlv4O3iyQ","HP4337Ow5C",
-"azIWpEdBKc","aFFssyToGW","nFqikguMb8","iqv4kprNT6","0h1b1tAOsr","7lUXZciuWz","QssNCZJTXH","zHF1q8RCUA","KsjRK8TxD7","lpF6WQ6hMC",
-"MezSWFcWrW","jS1ajG1RhS","CK5W7Cp3mZ","0PktIi7WMQ","bgJAzuJScX","iqv4krhl0J","Dz1R32ZHdk","HRxd8EoToP","zbIYYBpYhV","Dz1R3hUTw7",
-"mz8gxS2Dfu","X6PinGv3Fq","GXdoHdpe1v","tlILthSSvQ","0YAGHtl72W","16lHcmX2GE","5iGN5zz4ZU","3weIFRACuj","fcwDat59lR","6q6L9zFgtB",
-"piJSkFLsph","FGzgp14FLR","5iGN58hJdt","iB08lGXdoH","D6rByI7p2a","KASQ8uoStw","b29RJMmsIo","Yw2oUqQxHP","uoStw4W0Tl","lsQGoiKqhr",
-"VjCZqwDajX","KsjRKh1zcH","ReKEW7X3uy","8cVD3JkzUn","jiVBPaL6AJ","MmKGJSjskQ","ciuWzGXdoH","VIlwPxciqp","Chuy38hJdt","3weIFyvOMI",
-"v2eC3QChxs","6q6L9Pb1pa","9eoRcZhwG1","TXQ0ZBGaQY","Cfgr3Yw2oU","oQ87ruQIcz","t98iWNo0Qb","lXFOBCqqaD","yEfy9KZamH","7fsYM8U2nU",
-"okgRio8Uyd","X6Pinzz4ZU","5Mg9rFcWrW","he9IAFPfSE","d7vjMpmeCd","5Drn0UmaEv","jSjS3iqv4k","h1zcHQWxoT","O3iyQNo0Qb","2NslmAIYUu",
-"lCMxycShY2","zY1GYGWqqX","W7cTsG1RhS","BCxeCl83Ud","FjHXR8xEKz","BpYhV64s8N","0BmCybZLvS","Yw2oUvkCHH","29QAzBFkb8","uTacxPb1pa",
-"0Kyfs1v5hH","BbwgA5iGN5","jtn0X55rfB","JkzUnWreyP","Ss0ZuuJScX","48cHL0ao3l","9GXkXQClRL","M6qcGNcICA","n1pmOWmadA","uPX7Ghi5X7",
-"uJScXNo0Qb","FxX9quZPqg","pFrrlVLTy6","K4GS8580YD","gtCA5SmGzv","Kr8ysxReec","IKxdLuvf7A","tuDyS0Kyfs","brhlQTa8f6","TwanoVLTy6",
-"s4786RBhp0","RxrsmQChxs","KsjRKWaWsv","OHaBz2Yz7E","O3iyQa00b5","XflUqksJby","YjB9t9y4lw","AkKTklViBv","8RCUAxciqp","Q6hMCiKqhr",
-"uupzkOUYuF","uAWypC2Irc","uN6r3Yw2oU","nFqik5Mg9r","pT8wuCfgr3","tvdkD6q6L9","euZA5J2mQi","GXdoHatef2","FPfSE48cHL","VBjhz2Yz7E",
-"pFrrllj07Q","UlU3Mhe9IA","QbxXczmLYD","aFFss0BmCy","rKDLJJRJQB","blLA92ZHdk","hi5X7AgJHQ","9GXkXyofH3","cL0aEmz8gx","cShY2fmIK1",
-"FGzgpP6bcg","3otm624ARF","VBjhz5Mg9r","dpe1vLbRTH","x3LDe618Di","I7p2aO3iyQ","2ZHdkLDk6f","wiHrZ9y4lw","zQt6QQbxXc","s7Mxkv2eC3",
-"0Wr5yVLTy6","lweGy8RCUA","1j5L8MaJQs","b29RJDz1R3","Zv7z0Yf2Ec","vOqCEWaWsv","DcpWBDQimp","3weIFlkMUA","dQ586iB08l","XflUqsqVrf",
-"7fKYUt98iW","JJs5mgf8rI","qUJMdcShY2","NhXdu55rfB","GXdoHwiHrZ","i3pydm4bxU","55rfBBbwgA","zbIYYo8Uyd","U3yw5Y1mC0","blLA9dpe1v",
-"5drc664s8N","1v5hHdQ586","2DREsuAWyp","9y4lwFxX9q","cShY2oVQp6","x3LDewiHrZ","Mm8siBbwgA","MaJQsjzUqR","qUJMdTwano","7lUXZIRh48",
-"hYBCKqQxHP","nFqiklweGy","XyPZNtaOXK","MezSWY1mC0","o8UydNhXdu","M3zXLFnPFB","GXdoHdjsrv","OxWIHDcpWB","0YAGHeuZA5","3otm6Qworu",
-"7fsYMuoStw","hUTw7v2eC3","OUYuFWmadA","ZhwG1hSSvQ","yofH32hEEU","55rfBulk41","BCxeCGWqqX","7ku1pGrDg7","BGaQY7ku1p","BpYhV1j5L8",
-"0YAGHjeskS","QWxoTPb1pa","MojnPX6Pin","DQimpRzaZA","2DREs3weIF","UmaEvqaofN","gf8rIoQ87r","3weIFBFkb8","rhl0Jt59lR","oVQp6hYBCK",
-"jS1ajFNYIM","kZANmKASQ8","IjTwP2Nslm","O3iyQTa8f6","SWfourhl0J","dmoS7IBe8k","wDajXksJby","uJScXgjUTu","8TxD7jtn0X","M3zXLVjCZq",
-"IBe8k5drc6","1v5hHzHF1q","YjB9t0PktI","ksJbyQnJ1S","5drc6SmGzv","tjQxsUl4a1","14FLR24ARF","sx5GlMmKGJ","zbIYYfqypy","FcWrWn8pJ9",
-"DLhzMNcICA","HP433RkQke","FwEJz5Drn0","uoStwOUYuF","lpF6W5Mg9r","nlaByogLgc","TCgPpJIqXi","FLsph1j5L8","AXpwEpAhR1","nlaByyofH3",
-"azIWptaOXK","K20wKDz1R3","YjB9ttvdkD","brhlQlViBv","FGzgpiKqhr","QWxoTY1mC0","TCgPpOUqFM","oVQp6L7cGc","MGlTFFFDui","5iGN5ZuDtD",
-"uoStwd7vjM","ulk418RCUA","2Yz7EBGaQY","i3pydpvgjS","8RCUASs0Zu","vkCHHSs0Zu","dhSuHlpF6W","FGzgppT8wu","yToGWiB08l","RpBQm29QAz",
-"OxWIH7ku1p","FLsphaFFss","tvdkDFnPFB","jSjS3D6rBy","RmDcruN6r3","Ul4a1uN6r3","9y4lwBbwgA","14FLRydG8U","0KyfszQt6Q","IKxdLTCgPp",
-"jzUqRQssNC","D6rByfcwDa","AXpwE8RCUA","GWqqXt98iW","24ARFa00b5","2hEEUFxX9q","dQ586lweGy","FxX9qdjsrv","MK07YWMiS3","uPX7Gix74r",
-"lweGygf8rI","FwEJzMezSW","WMiS35drc6","ReKEW3otm6","KsjRKfLNg8","ciuWzK4GS8","In3NSHlUbF","4W0TlYh1hF","fLNg8OUqFM","dhSuHKsjRK",
-"uLtKsQbxXc","XyPZNwiHrZ","pFrrlt59lR","DcpWBzbIYY","9y4lwNo0Qb","pv0i7QnJ1S","BGaQYoGu6x","7fsYMciuWz","HP433VerEA","GWqqX0Kyfs",
-"yofH33otm6","CK5W7Vprf2","Twano9y4lw","yEfy9uN6r3","8RCUA5Drn0","WaWsvPOUYS","uJScXfcwDa","n8pJ9JJs5m","yvOMI9GXkX","FcWrWCqqaD",
-"CNHmvbrhlQ","2NslmP6bcg","RpBQmpT8wu","uvf7AHfyNQ","lj07QLbRTH","0YAGHpT8wu","2TRI7hSSvQ","2TRI7I7p2a","Uvlv4I7p2a","mz8gx1v5hH",
-"tuDySpAhR1","5VZjSCK5W7","OHaBzQChxs","n1pmOnlaBy","tuDyS9iGoT","BpYhVhi5X7","qUJMdVLTy6","UmaEvuupzk","618DiAIYUu","MezSWKZamH",
-"v8yFNazIWp","jeskSrz7Ut","X6PinbrhlQ","uJScXTwano","5iGN5NAFuw","0MR5XgtCA5","x3LDetjQxs","zY1GYNAFuw","jSjS3B3qem","RsQUqsuY4x",
-"ciuWzvLsmS","TCgPppv0i7","OUYuFVBjhz","yEfy9ix74r","pv0i7UmaEv","ksJbyVBjhz","FVMxoDG4sT","ZhwG1azIWp","Waim6WPmlx","8hJdtlXFOB",
-"tuDySguMb8","2NslmB3qem","QssNC2Yz7E","9y4lw2hEEU","CIShGGSQwj","AIYUuaDGtS","hE1Qlrz7Ut","7lUXZfLNg8","HRxd8QYxC0","HP433oGu6x",
-"jtn0XyofH3","zmLYDQ6Lix","FPfSEhUTw7","bgJAzkB5nP","zHF1qyofH3","xciqpFPfSE","QClRLaez9y","Gv3Fq14FLR","RBhp0taOXK","5Drn0lH1kt",
-"ZUnqtOUqFM","lpF6Wxciqp","ix74razIWp","n8pJ9Cp3mZ","atef2OxWIH","SjskQokgRi","GSQwj9XyT9","YOfrYOz8yZ","yEfy9StlDJ","WMiS30h1b1",
-"DLhzMOUqFM","29QAzQClRL","fqypysuY4x","HP433cQOnv","K4GS8MaJQs","qaofNdQ586","0BmCyzz4ZU","WmadAzz4ZU","WPmlxlH1kt","RzaZAuPX7G",
-"hSSvQpvgjS","jfREu07n1c","DcpWBciuWz","5nmWvyofH3","uAWypVLTy6","fqypyyToGW","Chuy3FPfSE","MGlTFaDGtS","vOqCE9rlg9","Zv7z0tAOsr",
-"pvgjSECMvU","Yf2EcjeskS","lH1ktU3yw5","bgJAz8xEKz","euZA58FmFH","QYxC0guMb8","Yw2oULewvM","tlILtFhtgl","FFDuiCIShG","JKWYRqQxHP",
-"IBe8kW7cTs","7X3uytvdkD","RkQkeuTacx","EoToP4W0Tl","Vprf2UmaEv","AgJHQyEfy9","07n1cHRxd8","nFqik2hEEU","ni2v1rz7Ut","DLhzMjtn0X",
-"J2mQipiJSk","7ku1poGu6x","gf8rI64s8N","euZA5zQt6Q","jS1aj5VZjS","lpF6Wd85a9","uoStwzY1GY","lkMUACK5W7","1LB1LblLA9","aL6AJoGu6x",
-"iwzGkuvf7A","5IhmGCK5W7","RsQUqUmaEv","gjUTud7vjM","2DREsTCgPp","NcICAHlUbF","cL0aE5iGN5","uAWyp7ku1p","fLNg8M6qcG","FhtglFPfSE",
-"fmIK1oQ87r","8U2nUoGu6x","WmadAFNYIM","3otm6jfREu","CdyBVjiVBP","ReKEWCxVEf","8TxD7rz7Ut","fLNg8ReKEW","GSQwjblLA9","XyPZN0Wr5y",
-"sx5GlOUYuF","MmsIoQssNC","5nmWvJ2mQi","FFDuiF6PT2","9iGoTpv0i7","kB5nPKsjRK","ni2v1ZJTXH","fcwDafmIK1","PYBf4VNCPd","zFgtB29QAz",
-"In3NSRmDcr","nlaByqUJMd","StlDJYw2oU","7hyVvFGzgp","lweGyRxrsm","t98iWjfREu","OHaBzcL0aE","LbRTHix74r","No0Qb9XyT9","7hyVvrhl0J",
-"AgJHQ5iGN5","4QMc9Yh1hF","ciuWz8cVD3","AIYUuv8yFN","CNHmv8U2nU","WMiS3xciqp","QnJ1SMmKGJ","gdQsSFPfSE","WreyPzHF1q","xciqpnFqik",
-"0h1b12DREs","AXpwEgjUTu","9y4lw6q6L9","lj07QoGu6x","EoToPK20wK","FVMxo9iGoT","bgJAz0MR5X","AmdQdMmsIo","POUYSv2eC3","QClRLnFqik",
-"gIYvENAFuw","VLTy6djsrv","nnP8osqVrf","pAhR1lXFOB","2TRI71j5L8","Cfgr32ZHdk","cmXIXwDajX","5Nammh1zcH","sx5GlzbIYY","pv0i7MGlTF",
-"CNHmv4QMc9","mX2GE6AFT0","Gv3FqRmDcr","RmDcr3otm6","C2Ircx3LDe","Zv7z0d85a9","5NammGXdoH","UmaEvaDGtS","FPfSESWfou","Mkgy8AkKTk",
-"hi5X7gIYvE","0PktIDQimp","lH1kty94nw","suY4xs93Ml","Mkgy8cQOnv","Chuy3pT8wu","dQ586gtCA5","J2mQizFgtB","Zv7z0uLtKs","GXdoHn1pmO",
-"XflUqtaOXK","RmDcruTacx","SjskQcShY2","Q6LixhYBCK","ni2v1FFDui","GSQwjIRh48","Gv3FqqQxHP","OHaBzOHaBz","pv0i7gjUTu","618Diuupzk",
-"QWxoTFNYIM","FGzgpFnPFB","OUqFMx3LDe","K4GS8uZPqg","PYBf4Qworu","lweGy9XyT9","k85AevOqCE","ydG8UAkKTk","14FLRtaOXK","0MR5XYw2oU",
-"atef2VIlwP","CNHmvt98iW","tlILtQChxs","5IhmGHzZT8","IRh48GXdoH","xciqpfaHir","RBhp0QChxs","t59lRwiHrZ","QbxXcIBe8k","ciuWzJIqXi",
-"VerEAokgRi","brhlQRACuj","CqqaDxciqp","VerEABGaQY","rKDLJogLgc","rKDLJAgJHQ","dmoS7pAhR1","fcwDaKZamH","euZA5Mm8si","Fhtglaez9y",
-"FGzgpIKxdL","VIlwPL7cGc","Y1mC0s7Mxk","7fKYUdmoS7","QbxXcWaim6","qQxHPIRh48","yvOMIb29RJ","pFrrlJIqXi","RBhp05drc6","jSjS3CNHmv",
-"fLNg8ulk41","RmDcrMm8si","DLhzMjeskS","nFqikqaofN","KZamHP6bcg","kB5nPZhwG1","MmsIosuY4x","Uvlv4FNYIM","5iGN5rKDLJ","ECMvUuvf7A",
-"zbIYYRBhp0","jS1ajNo0Qb","FhtglYOfrY","D6rByBGaQY","azIWpYh1hF","fLNg8nnP8o","KsjRKVjCZq","ix74rZv7z0","KASQ85Mg9r","VjCZqBCxeC",
-"0YAGH0h1b1","FGzgpCqqaD","tlILts93Ml","OxWIHuvf7A","iKqhrLewvM","RzaZAhe9IA","RACujTXQ0Z","jzUqRbZLvS","RxrsmUmaEv","v1HlnLbRTH",
-"YOfrYChuy3","8cVD3pAhR1","MezSWi7WMQ","azIWp5VZjS","lXFOBokgRi","YjB9t9GXkX","O3iyQ2Nslm","tuDyS3otm6","0YAGHMm8si","FGzgpb29RJ",
-"FNYIMFnPFB","64s8NDcpWB","zqH0WIn3NS","EOE1oYjB9t","Waim6yToGW","Kr8yssuY4x","ogLgcxXTI4","pvgjSuJScX","CqqaDtuDyS","hYBCKv8yFN",
-"he9IASs0Zu","P6bcgyEfy9","24ARFl83Ud","JJs5mYh1hF","No0QbmX2GE","2TRI7Zv7z0","RpBQm5ZaEz","sqVrfk85Ae","cShY2djsrv","U3yw5mz8gx",
-"tlILt7fKYU","FNYIMuAWyp","VerEA48cHL","OHaBzVprf2","55rfByvOMI","zFgtBe6e4z","P6bcgzmLYD","FLsphKr8ys","07n1cFcWrW","3weIFQClRL",
-"soy9tWmadA","QnJ1SsqVrf","uJScXydG8U","NAFuw0MR5X","HfyNQVNCPd","OUqFMAOgEe","WmadA5IhmG","W3VFHECMvU","mX2GEKZamH","0MR5XAOgEe",
-"FGzgp9eoRc","AgJHQ1j5L8","14FLR1v5hH","hi5X745cIH","i7WMQG1RhS","8xEKz580YD","ydG8UNcICA","2Yz7EFcWrW","lm0pDMmsIo","zY1GYCxVEf",
-"v1HlnGXdoH","XyPZNpiJSk","1LB1L14FLR","x3LDe6q6L9","QClRLOxWIH","6q6L9AOgEe","OHaBziB08l","5Drn0SjskQ","TwanoS77LH","6q6L9uoStw",
-"iKqhrBFkb8","ix74rYjB9t","dmoS7o8Uyd","d7vjMlsQGo","jtn0XCp3mZ","soy9tMkgy8","2ZHdktlILt","9XyT9VIlwP","6AFT0rhl0J","CdyBV1j5L8",
-"dmoS70Kyfs","gjUTuFFDui","v2eC3I7p2a","RxrsmhYBCK","v8yFN45cIH","yofH3uJScX","0h1b1Rxrsm","7ku1px3LDe","AIYUuGWqqX","s7Mxk6q6L9",
-"fmIK14dEz6","jeskS0PktI","MojnPyToGW","WmadAuQIcz","uPX7GlViBv","7fKYUCp3mZ","SbRYybZLvS","IjTwPfqypy","s7MxkQssNC","Pb1paVIlwP",
-"OUqFM8RCUA","tjQxs16lHc","rhl0JyEfy9","FwEJzcShY2","5iGN5SjskQ","5IhmGqaofN","oQ87rF6PT2","07n1c2TRI7","mX2GEVIlwP","55rfBStlDJ",
-"6q6L9AIYUu","0h1b107n1c","7X3uy5IhmG","cL0aEFGzgp","hUTw7yToGW","nlaByv1Hln","lm0pDQbxXc","MK07YNxx9V","xReeci3pyd","Vprf29XyT9",
-"SmGzvaL6AJ","NAFuwZzJHW","L7cGcUlU3M","cQOnv4dEz6","brhlQ2DREs","Cfgr3lpF6W","Yh1hFCxVEf","K20wKjS1aj","zmLYDFjHXR","HzZT8L7cGc",
-"GWqqXO3iyQ","guMb8jfREu","2DREsNxx9V","o8UydyToGW","WMiS3t59lR","ciuWzOUqFM","Nxx9VdQ586","Cp3mZCqqaD","Cfgr3kZANm","Kr8yscShY2",
-"0YAGHS2Dfu","FGzgp4dEz6","dpe1vIn3NS","zHF1qJIqXi","Z4I1vVLTy6","5VZjSs4786","sx5Glsoy9t","azIWpAOgEe","he9IAb29RJ","gjUTu2hEEU",
-"RkQkeRzaZA","MmKGJS77LH","S2Dfud85a9","X6Pins7Mxk","2DREsjiVBP","MmKGJfaHir","0ao3lKr8ys","3weIFAIYUu","ZzJHWi3pyd","J2mQisoy9t",
-"XyPZNMm8si","pmeCdgdQsS","Y1mC0JIqXi","7Ow5Ce6e4z","3weIFGSQwj","QbxXcYf2Ec","pFrrlSs0Zu","AOgEe07n1c","2hEEUlXFOB","yToGW5nmWv",
-"lkMUA5drc6","Mkgy8Q6Lix","0ao3llsQGo","16lHcjfREu","6AFT00Wr5y","KASQ8RpBQm","6AFT0zFgtB","FjHXR0ao3l","2TRI7BCxeC","StlDJ0YAGH",
-"CdyBVazIWp","JXljW6AFT0","gjUTuCK5W7","2Yz7ECfgr3","2TRI7ix74r","QssNCUl4a1","i3pydHRxd8","k85Ae5ZaEz","7ku1pv2eC3","0Kyfs8U2nU",
-"5IhmGs93Ml","HP433Mkgy8","uAWyp5iGN5","KASQ8a00b5","I7p2azz4ZU","7ku1pUl4a1","ksJbyK4GS8","cShY2EdBKc","zbIYYrhl0J","7X3uyl83Ud",
-"UlU3M5Mg9r","JIqXiJIqXi","M3zXLMaJQs","6AFT0i3pyd","FcWrWUl4a1","iB08ls4786","KASQ8Yf2Ec","okgRixReec","AOgEen8pJ9","8TxD71v5hH",
-"9eoRcWaWsv","2NslmguMb8","D6rBy8FmFH","ix74rgtCA5","n1pmOZUnqt","5VZjStl72W","nnP8oblLA9","Y1mC07fsYM","0BmCywiHrZ","fcwDahe9IA",
-"aL6AJni2v1","jfREuRmDcr","QClRLCxVEf","StlDJuQIcz","EdBKcSmGzv","QChxsv8yFN","7hyVv1j5L8","2NslmyluBx","MK07Yuupzk","jfREuFLsph",
-"hUTw755rfB","LDk6fFLsph","xXTI4QClRL","0YAGHhYBCK","ZuDtDMm8si","6AFT0VNCPd","Mkgy89iGoT","0BmCyUlU3M","b29RJv8yFN","oVQp6tvdkD",
-"EOE1ouJScX","16lHcQssNC","B3qemaez9y","MmsIoGXdoH","FxX9qjSjS3","wDajXyvOMI","8hJdtStlDJ","Nxx9Va00b5","S77LHSbRYy","D6rByUlU3M",
-"FPfSEfcJOy","45cIH9GXkX","guMb8IjTwP","618DiBFkb8","5VZjSoVQp6","e6e4zuTacx","2TRI7nlaBy","lCMxyRBhp0","5iGN5RACuj","cShY2hYBCK",
-"DG4sTi3pyd","5Drn00MR5X","lkMUAQChxs","CdyBVciuWz","GSQwjYh1hF","Y1mC00Wr5y","9GXkXF6PT2","M6qcGjSjS3","NcICAoVQp6","2hEEUprNT6",
-"iwzGkbZLvS","Kr8ysReKEW","FnPFBCK5W7","FwEJzKsjRK","5Mg9rlm0pD","EoToP16lHc","uvf7AHRxd8","S2DfuNcICA","EdBKcRACuj","FGzgp7ku1p",
-"ReKEWWmadA","dpe1vrz7Ut","0MR5XWreyP","HlUbFiqv4k","RBhp0zmLYD","dpe1vFnPFB","lj07Q5Mg9r","NcICAWaim6","Kr8ys5IhmG","jSjS3SbRYy",
-"JRJQBXflUq","OUqFMbgJAz","7Ow5CJKWYR","MojnPtuDyS","uvf7A4QMc9","k85Ae1j5L8","2TRI7bZLvS","mz8gxYw2oU","LewvMs4786","16lHchSSvQ",
-"MezSWSjskQ","Zv7z0azIWp","nFqikS77LH","okgRiuAWyp","suY4xcL0aE","CdyBVGXdoH","0Kyfsd85a9","SbRYyQClRL","0Wr5ylViBv","bZLvSWMiS3",
-"faHirAIYUu","FVMxouPX7G","WreyP9XyT9","BFkb8jtn0X","FVMxoaDGtS","zY1GYZuDtD","RkQkeM6qcG","bgJAz7fsYM","prNT6XflUq","HP433WMiS3",
-"JKWYRFFDui","o8Uydiqv4k","Dz1R3a00b5","CNHmv580YD","xXTI4JIqXi","8xEKzYf2Ec","zY1GYNxx9V","P6bcgOUYuF","580YDpmeCd","xXTI4uPX7G",
-"WMiS3IBe8k","3otm67Ow5C","tlILtBCxeC","nFqikl83Ud","NhXduMkgy8","okgRiAkKTk","LDk6f7hyVv","7lUXZCNHmv","580YDKZamH","8RCUAzY1GY",
-"vLsmScShY2","pWiOsS2Dfu","gdQsSzmLYD","dQ586soy9t","jeskSvkCHH","Mm8siLbRTH","pFrrlAOgEe","GSQwjCfgr3","FVMxoydG8U","kB5nPSs0Zu",
-"0PktIsqVrf","cShY2ZzJHW","tjQxsaFFss","iB08laL6AJ","jeskSOxWIH","yvOMIFVMxo","jtn0XnFqik","K4GS80h1b1","AIYUu7lUXZ","QClRLlViBv",
-"guMb8K20wK","8hJdt1LB1L","Cfgr3U3yw5","brhlQBFkb8","B3qemzHF1q","JkzUnEoToP","ru4UGLDk6f","ZhwG1RsQUq","fmIK1GWqqX","rKDLJFxX9q",
-"d7vjMBFkb8","euZA5Twano","QYxC0Qworu","yofH30PktI","AgJHQYjB9t","ni2v1gIYvE","ZJTXHprNT6","S77LHo8Uyd","In3NSaDGtS","JIqXiChuy3",
-"VNCPdRmDcr","lCMxy29QAz","OxWIHUl4a1","gtCA5QWxoT","7X3uyW3VFH","pAhR1FcWrW","lpF6Wa00b5","EOE1o8U2nU","yvOMICNHmv","dmoS7Ta8f6",
-"9y4lwsqVrf","blLA9W7cTs","QssNCGv3Fq","618DigtCA5","b29RJNo0Qb","iKqhrQ6hMC","S77LHlCMxy","suY4xAIYUu","JXljWBbwgA","DLhzMyluBx",
-"FFDui07n1c","YOfrYVBjhz","fqypybZLvS","bZLvSVjCZq","rhl0JjzUqR","s93MlHP433","14FLRx3LDe","VjCZq2DREs","RpBQm5VZjS","uupzksuY4x",
-"MezSW0ao3l","L7cGcs93Ml","Vprf2Q6Lix","W7cTsKZamH","618Di5ZaEz","uoStwAmdQd","7lUXZlH1kt","ZuDtDs93Ml","U3yw5k85Ae","l83UdHP433",
-"RmDcrIjTwP","NAFuwkZANm","5VZjSJkzUn","YjB9txXTI4","KASQ8i7WMQ","iB08lyToGW","NAFuw9rlg9","6q6L9uN6r3","FxX9qK20wK","5NammuAWyp",
-"HP4333otm6","M6qcG16lHc","L7cGcKsjRK","FNYIMhYBCK","s7MxkdhSuH","uQIczpmeCd","Zv7z0U3yw5","ix74rG1RhS","SbRYypAhR1","WDVWJni2v1",
-"VerEA7ku1p","lCMxy4W0Tl","KZamHVBjhz","cL0aElsQGo","07n1czY1GY","WMiS3sqVrf","Yh1hFkB5nP","QYxC0lViBv","oVQp6blLA9","XflUquupzk",
-"5iGN5dhSuH","0h1b1pvgjS","8cVD38RCUA","HRxd8In3NS","JRJQBciuWz","brhlQMm8si","NhXdu7Ow5C","tlILts7Mxk","rKDLJCIShG","Pb1payvOMI",
-"cQOnvK20wK","1LB1LtvdkD","Pb1pa6AFT0","6AFT01v5hH","EOE1o2ZHdk","DLhzMQssNC","HzZT8QssNC","LbRTHiwzGk","Oz8yZQworu","X6Pinl83Ud",
-"tAOsrCxVEf","MK07YSmGzv","KASQ807n1c","zHF1qWMiS3","9iGoTAgJHQ","TCgPpjS1aj","qQxHPI7p2a","5VZjS2ZHdk","FVMxoiB08l","45cIHtaOXK",
-"5Drn0t98iW","gdQsSvLsmS","G1RhSKr8ys","djsrv16lHc","ydG8U5drc6","8RCUAReKEW","hE1QlIn3NS","5ZaEzjzUqR","Waim6jS1aj","Gv3FqpWiOs",
-"dhSuHsx5Gl","lCMxyFjHXR","kB5nP9GXkX","LewvMyofH3","ZuDtD5ZaEz","uLtKs48cHL","GXdoHcShY2","lkMUAW7cTs","SjskQJIqXi","B3qemPb1pa",
-"TXQ0ZguMb8","ThjNnuLtKs","P6bcg1v5hH","brhlQgIYvE","fmIK1CqqaD","wiHrZtuDyS","wDajXNcICA","piJSkpv0i7","LDk6fVIlwP","4W0Tldjsrv",
-"BpYhVlm0pD","In3NS1v5hH","6q6L9pT8wu","2TRI7a00b5","dhSuHFwEJz","TCgPpCK5W7","J2mQivkCHH","Ul4a1aFFss","K4GS8aDGtS","580YDzQt6Q",
-"aL6AJ0Kyfs","n1pmOYOfrY","J2mQi8TxD7","PYBf4ZhwG1","RBhp0Yh1hF","lsQGogtCA5","HRxd85drc6","Mkgy8RsQUq","BpYhVB3qem","fFDrJyToGW",
-"nlaByCdyBV","WreyPguMb8","2hEEUdpe1v","8FmFHprNT6","KsjRKMmsIo","XyPZN9iGoT","AkKTk0MR5X","v8yFNMkgy8","piJSkogLgc","WaWsvYh1hF",
-"580YDTXQ0Z","aez9ydhSuH","FnPFBcQOnv","yofH3Waim6","7Ow5CQssNC","RkQkeTwano","hUTw76AFT0","rKDLJzz4ZU","fmIK12DREs","2Yz7ERpBQm",
-"Q6LixJXljW","gtCA57fsYM","3weIFd7vjM","Ul4a1D6rBy","9GXkXBFkb8","16lHc2TRI7","oQ87r0ao3l","07n1cgdQsS","azIWp55rfB","KZamHCp3mZ",
-"Q6LixgdQsS","Gv3Fq5Mg9r","lm0pDXflUq","6q6L9dQ586","rz7Utatef2","vLsmSoQ87r","EOE1oBFkb8","v1HlnW3VFH","iqv4kQ6Lix","BpYhVcShY2",
-"KsjRKyToGW","SjskQ16lHc","5IhmG7fKYU","OUqFMWreyP","4QMc9rKDLJ","NhXduciuWz","uoStwi3pyd","0YAGH64s8N","9y4lwJRJQB","DLhzMTa8f6",
-"4QMc9OHaBz","rz7UtVjCZq","J2mQi8xEKz","jzUqR4QMc9","CK5W7W7cTs","2Yz7EKr8ys","uPX7GguMb8","M6qcGzmLYD","VIlwPdjsrv","bgJAztAOsr",
-"TCgPp7lUXZ","5nmWviqv4k","UlU3MfLNg8","ZUnqtLDk6f","ZzJHWRzaZA","DQimpNo0Qb","k85AeHzZT8","v1HlnQssNC","ZzJHWix74r","FhtglblLA9",
-"29QAzfcwDa","G1RhSAkKTk","0ao3lDcpWB","RsQUqQssNC","MezSWHfyNQ","FnPFBFcWrW","uvf7AQnJ1S","RsQUqs7Mxk","MojnPdjsrv","0BmCyQbxXc",
-"W7cTsSbRYy","ru4UGfFDrJ","QbxXcAgJHQ","cQOnv0ao3l","blLA9nlaBy","LewvMKsjRK","pFrrl7lUXZ","nlaByeuZA5","DLhzMru4UG","7lUXZFNYIM",
-"v1HlnChuy3","aFFss7X3uy","qaofNYw2oU","zz4ZU1j5L8","uLtKsThjNn","ZJTXHM3zXL","FhtglXflUq","dQ586jiVBP","G1RhSJKWYR","prNT6VerEA",
-"MojnPlweGy","x3LDeyToGW","yofH3wDajX","8RCUAzFgtB","0h1b1TCgPp","okgRiIRh48","MojnPOHaBz","0Wr5ycL0aE","8TxD7t98iW","gIYvE7lUXZ",
-"faHirdhSuH","5ZaEzogLgc","8hJdtQssNC","WreyPBpYhV","O3iyQ9iGoT","okgRiQssNC","OUYuFhi5X7","CNHmvUvlv4","CqqaDRpBQm","HfyNQfLNg8",
-"7fKYUVLTy6","he9IATa8f6","VIlwPDz1R3","KZamHnlaBy","mX2GEMK07Y","QnJ1Sa00b5","2DREsguMb8","aFFsskZANm","fcwDaVprf2","HfyNQRBhp0",
-"5IhmG8RCUA","uPX7GJ2mQi","7fKYUuN6r3","FNYIMlCMxy","zmLYDpFrrl","soy9t1LB1L","hi5X7uN6r3","nnP8oZUnqt","JXljWjS1aj","8cVD3o8Uyd",
-"pv0i7ZzJHW","NhXdun1pmO","rhl0J5drc6","gtCA5Uvlv4","MmsIojS1aj","yEfy9BCxeC","ru4UG8cVD3","Dz1R3uupzk","AmdQdrz7Ut","FVMxon8pJ9",
-"OUqFMdhSuH","HlUbFOUqFM","taOXK07n1c","1v5hHDLhzM","Kr8ys1j5L8","GrDg7fcJOy","pv0i7VIlwP","5ZaEzn1pmO","0Kyfsdpe1v","brhlQuvf7A",
-"dhSuHix74r","8TxD7SjskQ","soy9tP6bcg","WreyP1j5L8","e6e4ztlILt","LewvMIKxdL","IjTwPpWiOs","tjQxsWDVWJ","JkzUnpmeCd","BGaQYVIlwP",
-"C2Irc7X3uy","zHF1qvLsmS","guMb8FxX9q","5ZaEzNAFuw","EoToPnFqik","Cp3mZVLTy6","VBjhz2Nslm","b29RJ0Wr5y","v1HlncmXIX","POUYShUTw7",
-"UlU3Mn1pmO","9y4lwHlUbF","QbxXcRzaZA","jfREuqQxHP","VLTy6Zv7z0","gjUTupvgjS","5Mg9rbZLvS","fcwDa8xEKz","dQ586bgJAz","pvgjStjQxs",
-"SjskQRpBQm","8RCUA0PktI","n1pmOzbIYY","kB5nP14FLR","7lUXZZuDtD","FjHXR5nmWv","wiHrZcL0aE","Yw2oUbrhlQ","FPfSEQ6Lix","LDk6fpT8wu",
-"prNT6ix74r","brhlQhe9IA","guMb8Q6Lix","9y4lws93Ml","yvOMIdQ586","5nmWv5nmWv","hi5X7gtCA5","RACujZhwG1","iqv4kSbRYy","FhtglFnPFB",
-"lViBvQbxXc","2hEEUo8Uyd","1j5L83otm6","YjB9tblLA9","k85AeuTacx","NAFuwB3qem","FVMxoJXljW","suY4xAXpwE","jfREulm0pD","D6rBy24ARF",
-"RpBQmVprf2","yEfy9QYxC0","BpYhVIn3NS","64s8N6q6L9","lH1ktpWiOs","fLNg8lj07Q","uN6r39iGoT","7fKYU5drc6","ciuWzdmoS7","n8pJ9X6Pin",
-"ZhwG1fcJOy","64s8NNo0Qb","ulk41JJs5m","HlUbF580YD","C2Irclj07Q","45cIH7fsYM","9eoRcgf8rI","SjskQAgJHQ","8RCUAB3qem","MGlTFfaHir",
-"TXQ0ZksJby","9rlg90PktI","M6qcGpvgjS","FFDuiHlUbF","n1pmOsx5Gl","JXljWAXpwE","WmadAaez9y","RxrsmyToGW","HlUbFhi5X7","B3qemDz1R3",
-"i7WMQHRxd8","t98iW0ao3l","K4GS8Q6Lix","uvf7AFFDui","F6PT2n8pJ9","FNYIMU3yw5","GrDg7FPfSE","BFkb8FNYIM","KASQ8FcWrW","JRJQB5VZjS",
-"2Yz7EDcpWB","suY4xuQIcz","CNHmvn1pmO","MmsIoS2Dfu","XyPZNK20wK","TXQ0ZCp3mZ","5nmWvTwano","IjTwPPOUYS","zY1GYcQOnv","FNYIMeuZA5",
-"EoToPCqqaD","k85AeDG4sT","0YAGH8xEKz","9y4lwKASQ8","GXdoHksJby","RmDcrDz1R3","5IhmGVBjhz","Y1mC0In3NS","uPX7G2hEEU","Oz8yZM3zXL",
-"MK07YhYBCK","oQ87rzFgtB","pWiOsmz8gx","hi5X7tvdkD","taOXKlsQGo","7hyVvazIWp","QssNCAXpwE","LewvMh1zcH","Mm8siQnJ1S","okgRibgJAz",
-"kB5nPfqypy","Oz8yZ0BmCy","gIYvEaL6AJ","XflUqG1RhS","ciuWzpWiOs","CxVEftvdkD","oVQp6dhSuH","ix74rOUqFM","Yw2oUokgRi","zbIYYqaofN",
-"CIShGaez9y","nnP8o7fsYM","07n1cl83Ud","1j5L8rKDLJ","xReecdpe1v","yluBxzqH0W","VerEA0h1b1","FxX9qL7cGc","ciuWzaDGtS","yToGWOz8yZ",
-"hSSvQzQt6Q","fLNg8cL0aE","Yw2oU9y4lw","ni2v1oQ87r","DQimp580YD","hi5X7CxVEf","iB08lv2eC3","n8pJ9gIYvE","ZJTXHi7WMQ","2Yz7ENo0Qb",
-"t98iWsqVrf","Cfgr3FcWrW","pT8wu16lHc","HRxd8X6Pin","DG4sTxReec","In3NSOUYuF","Y1mC07hyVv","BpYhV0h1b1","JXljWqUJMd","ReKEWNhXdu",
-"oQ87rBpYhV","prNT6pv0i7","Yh1hFkZANm","0PktI5VZjS","RmDcrmX2GE","hUTw79y4lw","FhtglwDajX","n8pJ9BCxeC","55rfBUlU3M","5nmWvXflUq",
-"0ao3lEoToP","yEfy9rKDLJ","lpF6Wt59lR","ZUnqt2TRI7","29QAzwiHrZ","J2mQi3otm6","0PktIW3VFH","CqqaDL7cGc","Z4I1v3weIF","0h1b1CdyBV",
-"WaWsvjtn0X","FFDuiQworu","qUJMduN6r3","MezSWguMb8","azIWpZv7z0","F6PT2e6e4z","5Mg9rlXFOB","hSSvQWaim6","4W0Tlb29RJ","OxWIHVerEA",
-"ciuWz0ao3l","WaWsv7X3uy","suY4xgjUTu","MezSWBbwgA","ogLgcFVMxo","Zv7z07Ow5C","d7vjMblLA9","24ARF16lHc","StlDJciuWz","9y4lwmz8gx",
-"faHiruLtKs","Cp3mZMojnP","EOE1oCdyBV","pWiOs7hyVv","ThjNnfaHir","MaJQsBFkb8","0YAGHNcICA","dQ586VLTy6","LDk6fD6rBy","QYxC0OUqFM",
-"lXFOBjiVBP","tAOsrJKWYR","W3VFHJRJQB","48cHLSmGzv","NAFuwCIShG","C2IrciwzGk","zqH0WEoToP","FnPFB3otm6","Qworud7vjM","9rlg9pAhR1",
-"CIShGJXljW","ogLgca00b5","SWfou8hJdt","RkQkeoGu6x","ix74rlpF6W","WMiS3i3pyd","nFqikMmKGJ","2ZHdkd85a9","L7cGcQChxs","ulk41DG4sT",
-"NOHszSmGzv","I7p2arKDLJ","JJs5mStlDJ","uPX7G7hyVv","xReec8xEKz","yofH3K4GS8","tvdkDpv0i7","9eoRcIKxdL","ThjNnVprf2","K20wKIjTwP",
-"QbxXcJJs5m","uTacx2TRI7","IjTwPyEfy9","XflUqdhSuH","faHirciuWz","8RCUABpYhV","0Wr5yZzJHW","pT8wuB3qem","9iGoTv1Hln","fcwDa07n1c",
-"9eoRc0ao3l","uQIczQbxXc","MmsIo5ZaEz","CNHmvIjTwP","sx5GlTwano","cL0aE6q6L9","Q6hMCyToGW","x3LDe6AFT0","zQt6Qpv0i7","uJScXVjCZq",
-"7fsYM5VZjS","Waim6AIYUu","07n1c3weIF","SWfouuPX7G","taOXK0h1b1","D6rBywDajX","HP433ZuDtD","he9IAlpF6W","0YAGHtlILt","tuDySIn3NS",
-"xReece6e4z","5IhmG5drc6","2NslmVprf2","qQxHPQChxs","lkMUAVBjhz","MojnPt98iW","6AFT0DcpWB","JXljWm4bxU","gIYvEVNCPd","atef20h1b1",
-"EOE1oqUJMd","5Mg9rDQimp","F6PT2RsQUq","iwzGkFhtgl","bgJAzv1Hln","Ta8f6oVQp6","lj07Q8TxD7","fLNg8U3yw5","EdBKcaez9y","U3yw58FmFH",
-"bgJAzpT8wu","DcpWBrhl0J","5Mg9rZhwG1","WmadAWreyP","rKDLJo8Uyd","7fKYUJkzUn","wiHrZQ6hMC","XflUqEOE1o","8cVD3blLA9","MGlTFIRh48",
-"xReecgdQsS","suY4xKsjRK","S77LHNxx9V","CK5W75Drn0","qaofNIKxdL","ru4UGuZPqg","oQ87rtaOXK","IKxdLThjNn","h1zcHCxVEf","5iGN5uPX7G",
-"UmaEvZuDtD","FLsphOUYuF","WDVWJ5ZaEz","FLsphaez9y","fmIK1Yf2Ec","NAFuwF6PT2","azIWp618Di","kZANmGXdoH","tl72WLewvM","QChxst98iW",
-"MojnPjeskS","PYBf48cVD3","24ARFRBhp0","RACuj7fsYM","VBjhzS2Dfu","QworupAhR1","i7WMQ7hyVv","MojnPhUTw7","FVMxosuY4x","qUJMdKr8ys",
-"W3VFHB3qem","FxX9qFVMxo","CqqaD8TxD7","AmdQdXflUq","tvdkDCxVEf","rhl0J8RCUA","RsQUqkZANm","C2IrcpiJSk","Qworu48cHL","X6PinS2Dfu",
-"sqVrfFPfSE","zY1GYxXTI4","Mm8siYh1hF","pvgjSv1Hln","7lUXZjzUqR","GWqqXyofH3","HP433K4GS8","8cVD3jfREu","8cVD3iKqhr","uAWypDz1R3",
-"jtn0XFVMxo","uZPqgydG8U","lsQGo0Kyfs","K4GS8pvgjS","azIWp64s8N","Twanosx5Gl","QssNCGXdoH","pvgjS55rfB","EoToPP6bcg","gdQsS2hEEU",
-"2TRI7SWfou","W3VFHSmGzv","he9IA618Di","lsQGopAhR1","5drc6nlaBy","pvgjSFLsph","RBhp0LewvM","CxVEfd85a9","JkzUn5VZjS","PYBf4Z4I1v",
-"CK5W7DcpWB","5IhmGb29RJ","CNHmv7Ow5C","MojnPMojnP","ZJTXH07n1c","hUTw7lweGy","i7WMQFNYIM","AkKTkmX2GE","WMiS3Yh1hF","FwEJzhE1Ql",
-"XflUqs7Mxk","7fKYUFwEJz","0Wr5yYf2Ec","zqH0W9XyT9","48cHLkZANm","FhtglOUYuF","Mkgy8kB5nP","GWqqX7fsYM","DG4sTL7cGc","BCxeCbrhlQ",
-"No0QbBGaQY","LDk6f618Di","MezSWRmDcr","t98iWUmaEv","uupzk0BmCy","FFDuiCdyBV","gdQsShYBCK","Mkgy8cmXIX","16lHcciuWz","suY4xX6Pin",
-"VNCPdyEfy9","QbxXcFhtgl","zbIYYiKqhr","azIWplViBv","hi5X7QssNC","kB5nPIjTwP","Dz1R3fcwDa","gf8rIPYBf4","No0QbIBe8k","IBe8kzbIYY",
-"4dEz6gdQsS","fcwDavOqCE","lm0pDQnJ1S","EoToPvOqCE","s4786SWfou","DG4sTlkMUA","5drc65Mg9r","PYBf4FLsph","FNYIMYh1hF","RpBQm9iGoT",
-"tuDyS6AFT0","7lUXZGWqqX","FcWrWYjB9t","Ss0Zuo8Uyd","5nmWv0h1b1","3weIFVNCPd","SbRYylViBv","QssNCvOqCE","CxVEfB3qem","lweGy45cIH",
-"VjCZquPX7G","0h1b1kB5nP","FxX9quTacx","iKqhrIRh48","RkQkepiJSk","JkzUngIYvE","8FmFHCp3mZ","oGu6xGWqqX","9rlg9LbRTH","GSQwjGSQwj",
-"IjTwPcL0aE","DQimp0Kyfs","pT8wuFhtgl","mz8gxHlUbF","RpBQm5drc6","W7cTs48cHL","s93Mlo8Uyd","AmdQdGWqqX","FxX9qFnPFB","zHF1qEoToP",
-"e6e4zoGu6x","9GXkXD6rBy","5drc6euZA5","ReKEW4W0Tl","Kr8ysdpe1v","aez9yb29RJ","b29RJcmXIX","uZPqgjfREu","t59lRTXQ0Z","ECMvUEoToP",
-"uZPqgfaHir","djsrvL7cGc","9y4lwMezSW","pv0i7uAWyp","jeskSKr8ys","4QMc9Yf2Ec","4dEz6Cfgr3","5NammBFkb8","0ao3l2Nslm","tl72W8cVD3",
-"uLtKstl72W","KZamHjtn0X","NOHszuJScX","Pb1paUlU3M","lj07QzbIYY","Nxx9VLewvM","i7WMQ2Nslm","i7WMQVprf2","9XyT9jtn0X","55rfBG1RhS",
-"TwanoK20wK","CdyBV5ZaEz","gjUTuSbRYy","I7p2aAgJHQ","KZamHYf2Ec","24ARFZzJHW","Rxrsms7Mxk","oGu6xBGaQY","uTacxvOqCE","zbIYYe6e4z",
-"9GXkXUmaEv","Q6hMC0PktI","WreyPVLTy6","2DREsUmaEv","iqv4kCdyBV","RACujru4UG","ReKEWKsjRK","Zv7z0ZuDtD","uoStwHP433","tAOsrnnP8o",
-"iwzGkTCgPp","I7p2aBGaQY","s93MlBFkb8","v8yFN8hJdt","QssNCiwzGk","zHF1q64s8N","oQ87rUlU3M","IKxdL2DREs","5ZaEzzFgtB","AkKTkpAhR1",
-"14FLRcShY2","QnJ1SiwzGk","7fsYMECMvU","QClRLxXTI4","KsjRKGrDg7","WPmlxW3VFH","YjB9tvLsmS","MmKGJReKEW","rKDLJFFDui","9y4lwrKDLJ",
-"WPmlx0h1b1","v1HlnOxWIH","1v5hHMkgy8","8U2nUBCxeC","yofH3zqH0W","QbxXc8xEKz","JIqXin8pJ9","uupzkB3qem","FxX9q0YAGH","EdBKcsoy9t",
-"BFkb8sqVrf","JIqXiXyPZN","MGlTFogLgc","KASQ8azIWp","Cp3mZRmDcr","DLhzMDcpWB","AOgEe2DREs","qUJMdY1mC0","CxVEfStlDJ","zHF1qOxWIH",
-"IRh48uoStw","9eoRcZ4I1v","Oz8yZzmLYD","1j5L8W3VFH","BGaQYqaofN","Nxx9VuAWyp","IRh48lkMUA","RxrsmguMb8","LewvMb29RJ","uAWypWDVWJ",
-"Ul4a1LbRTH","ZzJHWMm8si","OUqFMtaOXK","55rfBFNYIM","7Ow5C2hEEU","ZhwG17X3uy","cQOnv580YD","jfREuTCgPp","xReeccShY2","oVQp6s93Ml",
-"he9IA4dEz6","WDVWJeuZA5","VjCZqazIWp","gf8rIuN6r3","gtCA5zmLYD","n1pmOyEfy9","POUYSQnJ1S","faHirTa8f6","a00b5VerEA","GSQwjWreyP",
-"VLTy6ogLgc","FNYIMqaofN","dQ586ZhwG1","GWqqXd85a9","jfREu2TRI7","8xEKzxciqp","xXTI40h1b1","RkQkeHRxd8","ZuDtDhSSvQ","FVMxoCp3mZ",
-"tjQxsogLgc","4QMc9xXTI4","U3yw55Mg9r","hi5X7Y1mC0","YOfrYXyPZN","EoToPe6e4z","uoStwlkMUA","ix74rksJby","MaJQsFNYIM","d85a91v5hH",
-"gf8rIhSSvQ","0h1b1Pb1pa","ZhwG1fmIK1","Zv7z0lXFOB","NOHszyToGW","uLtKs1v5hH","9eoRcX6Pin","X6Pin2Yz7E","8TxD7CqqaD","Chuy3FwEJz",
-"uvf7A8xEKz","1LB1LIjTwP","hUTw7uPX7G","s93Ml5IhmG","7lUXZdpe1v","2ZHdkChuy3","6AFT04QMc9","X6PinM3zXL","6AFT0oGu6x","5Namm5Namm",
-"OUqFMgIYvE","ThjNnhE1Ql","yToGWogLgc","WMiS3S2Dfu","kB5nPvkCHH","Q6Lixmz8gx","0ao3lWreyP","580YDlXFOB","0ao3lWDVWJ","MGlTFgdQsS",
-"M6qcG8FmFH","VLTy6yluBx","GXdoHTXQ0Z","jS1ajMm8si","EOE1oDG4sT","3weIF0Wr5y","piJSkY1mC0","t98iWTwano","sqVrfsuY4x","JIqXi5Mg9r",
-"DG4sTQnJ1S","uZPqg5drc6","FPfSEAXpwE","wiHrZt98iW","qaofNBpYhV","0h1b1NOHsz","5NammRACuj","lXFOBQbxXc","uupzkKZamH","BGaQY2DREs",
-"S77LH6q6L9","lj07QCNHmv","uLtKsIjTwP","GrDg7nlaBy","QnJ1SPb1pa","AmdQdTXQ0Z","kB5nPVLTy6","G1RhSQssNC","ciuWzlCMxy","8FmFHAOgEe",
-"rKDLJFjHXR","FjHXR0Wr5y","Rxrsmn8pJ9","ECMvUpFrrl","tvdkDFjHXR","e6e4zIBe8k","Yw2oUyluBx","JKWYR7X3uy","Kr8ys2DREs","nnP8opvgjS",
-"O3iyQgtCA5","F6PT2CdyBV","WreyP2TRI7","guMb8iwzGk","8xEKzy94nw","7X3uyprNT6","he9IAfmIK1","ZJTXHDcpWB","Kr8ys9y4lw","ix74rFcWrW",
-"ZJTXH8cVD3","piJSklH1kt","2DREs0Wr5y","zHF1quQIcz","4QMc97hyVv","AOgEe4QMc9","VjCZqzQt6Q","8U2nU7hyVv","48cHLlViBv","dpe1vWDVWJ",
-"Nxx9VO3iyQ","okgRigtCA5","AkKTkzqH0W","RsQUqiwzGk","3otm6DLhzM","IKxdLqQxHP","jeskSXflUq","lCMxy5ZaEz","HP433djsrv","fcJOy5Namm",
-"AOgEeTa8f6","pv0i70ao3l","ZhwG1LDk6f","pmeCdXflUq","lViBvyofH3","jSjS30BmCy","JJs5mCqqaD","7ku1pW7cTs","48cHLdjsrv","qUJMdO3iyQ",
-"8cVD3RACuj","VIlwPtaOXK","DLhzMYOfrY","jeskSOUqFM","ThjNnKZamH","9eoRc5drc6","StlDJbgJAz","cmXIXNAFuw","LDk6f4W0Tl","KZamHM3zXL",
-"JKWYRJkzUn","Waim67hyVv","1v5hH9eoRc","M6qcGVBjhz","FwEJz7fsYM","aFFss1v5hH","C2IrcWreyP","NcICAAXpwE","C2IrcoGu6x","VerEAMmsIo",
-"X6PinwDajX","CxVEfni2v1","cL0aEyofH3","P6bcgx3LDe","lsQGociuWz","QClRLYh1hF","qaofNhYBCK","pAhR1HlUbF","C2Ircsoy9t","QworuRsQUq",
-"pAhR1aDGtS","RxrsmuTacx","RxrsmVBjhz","7fsYMzQt6Q","QnJ1S0h1b1","hE1QlQWxoT","W3VFHnnP8o","SjskQa00b5","cL0aEs4786","2DREs9rlg9",
-"lj07QogLgc","ix74r2TRI7","ix74rpAhR1","S2DfuUlU3M","VjCZqCNHmv","7lUXZOUYuF","GrDg7Yh1hF","In3NSwiHrZ","3otm6zbIYY","RpBQmIRh48",
-"NAFuwix74r","gIYvE0ao3l","I7p2a4W0Tl","yvOMIzmLYD","lm0pDfcJOy","AXpwEzQt6Q","FwEJz2hEEU","piJSkeuZA5","iwzGkC2Irc","nlaBytaOXK",
-"nFqikCIShG","Gv3FqUvlv4","oVQp6rKDLJ","1j5L8XyPZN","M3zXLZ4I1v","gtCA54QMc9","WMiS3s4786","8U2nUa00b5","0ao3ls7Mxk","Nxx9VHP433",
-"hi5X74dEz6","pv0i7580YD","h1zcH5Mg9r","guMb8jS1aj","n8pJ9kZANm","CIShG8FmFH","55rfBzmLYD","aL6AJO3iyQ","IBe8kQworu","VBjhzlCMxy",
-"EoToPlpF6W","Uvlv4uLtKs","DG4sTNAFuw","CIShGJRJQB","Uvlv4uupzk","GrDg7oQ87r","Kr8ysk85Ae","s7MxkGv3Fq","sqVrf14FLR","9GXkXzHF1q",
-"KASQ8fLNg8","gtCA5lj07Q","8U2nUQnJ1S","lsQGoQworu","UlU3MJRJQB","CNHmv4dEz6","FLsphM6qcG","oGu6xTXQ0Z","JRJQBFxX9q","HP433gjUTu",
-"1j5L8n8pJ9","vkCHHCqqaD","cShY2JKWYR","uPX7GiKqhr","7fsYMzqH0W","Chuy3pWiOs","2NslmuoStw","POUYSciuWz","F6PT2ZuDtD","fcJOyF6PT2",
-"oQ87raDGtS","s47866AFT0","O3iyQBCxeC","0YAGHQnJ1S","HzZT8KZamH","GSQwjAIYUu","blLA9EdBKc","mX2GE7hyVv","1LB1Ldjsrv","yvOMIlpF6W",
-"fcJOycQOnv","oGu6xJkzUn","CqqaDlCMxy","ydG8UVerEA","BGaQY1LB1L","dpe1v14FLR","iqv4kjSjS3","lCMxyRmDcr","I7p2aMkgy8","SbRYyazIWp",
-"tuDySjS1aj","HzZT8jtn0X","VerEAGSQwj","AgJHQaFFss","4dEz6ZuDtD","FNYIMjiVBP","FVMxoQssNC","zQt6Qru4UG","rhl0JuJScX","iqv4kCxVEf",
-"JRJQBhYBCK","6q6L9RpBQm","yluBxgtCA5","Mm8siksJby","uLtKsVIlwP","a00b5VjCZq","StlDJCK5W7","mz8gxvkCHH","VBjhzK20wK","IjTwPJIqXi",
-"ciuWzn1pmO","UlU3MfcwDa","CIShGl83Ud","m4bxUvLsmS","zqH0WdhSuH","WreyPMm8si","64s8NhSSvQ","FjHXRWMiS3","48cHLQChxs","KZamHjfREu",
-"0PktIZ4I1v","djsrvI7p2a","h1zcHYf2Ec","jtn0XtlILt","wDajXMmsIo","WPmlx0MR5X","zmLYDpmeCd","5drc6gIYvE","zqH0WlkMUA","MojnPTa8f6",
-"AIYUu64s8N","IRh48uN6r3","FNYIMiB08l","FwEJzFcWrW","gIYvEyluBx","dQ586MezSW","RBhp08xEKz","FxX9qRzaZA","VNCPdK4GS8","aez9yQClRL",
-"W3VFHlkMUA","rKDLJs4786","Q6hMCdmoS7","BFkb8suY4x","s7Mxk8TxD7","POUYSMK07Y","yEfy9X6Pin","64s8NQ6Lix","euZA5ZzJHW","xXTI4MojnP",
-"Chuy3WMiS3","Yw2oUpAhR1","VNCPd5Mg9r","GrDg7aDGtS","ECMvUQYxC0","Qworu0Kyfs","d85a9VBjhz","JKWYREdBKc","WPmlxPYBf4","kB5nP9eoRc",
-"Uvlv4v1Hln","sx5GlFFDui","n1pmOVLTy6","S2DfuBGaQY","CxVEfQClRL","Yh1hFDcpWB","LbRTHqaofN","hYBCKM3zXL","ZJTXHo8Uyd","gIYvEVjCZq",
-"tAOsrtvdkD","gdQsSuAWyp","TXQ0ZBpYhV","W7cTsLbRTH","1LB1LzQt6Q","RzaZA7fKYU","HP433ni2v1","29QAzMkgy8","24ARFuN6r3","lsQGovLsmS",
-"prNT6W3VFH","1j5L89rlg9","brhlQX6Pin","SmGzvuZPqg","Fhtgly94nw","XflUq55rfB","2NslmDLhzM","WPmlxNAFuw","Ss0ZuzQt6Q","lkMUAYh1hF",
-"Cfgr3AmdQd","RmDcrjeskS","mz8gxVprf2","M3zXLDG4sT","zY1GYCNHmv","Uvlv4lm0pD","5Drn0FjHXR","MaJQspvgjS","uPX7GThjNn","RmDcrUvlv4",
-"LDk6f7lUXZ","qUJMd9eoRc","8xEKz9iGoT","KZamHlj07Q","IjTwPciuWz","dmoS7kB5nP","gdQsSnFqik","rhl0Jdjsrv","DLhzM9y4lw","07n1cHfyNQ",
-"yluBxZhwG1","t98iWIBe8k","RzaZA7ku1p","ECMvUk85Ae","RzaZAQChxs","7Ow5CXyPZN","tl72WlweGy","ThjNnCxVEf","0MR5XJIqXi","AXpwEQChxs",
-"8xEKz8U2nU","9rlg9zbIYY","WMiS3RkQke","FhtglUmaEv","AIYUutaOXK","HP433WDVWJ","jS1ajzHF1q","9rlg9LDk6f","Cfgr3MojnP","B3qemWmadA",
-"J2mQiogLgc","QnJ1Szz4ZU","1v5hH618Di","14FLROxWIH","GXdoHgf8rI","EoToPYf2Ec","a00b5K20wK","B3qemFNYIM","pFrrl9rlg9","Yw2oUyvOMI",
-"ru4UG2Nslm","OUqFMni2v1","qUJMdMK07Y","SmGzvJXljW","TXQ0ZYOfrY","QssNC5IhmG","LbRTHS77LH","TXQ0ZMm8si","FVMxoKASQ8","iqv4kAIYUu",
-"s4786RkQke","i7WMQJRJQB","GXdoHDLhzM","jS1aj7fKYU","Waim68RCUA","NhXduHzZT8","BCxeCW7cTs","mX2GEydG8U","LDk6fyEfy9","CK5W7SWfou",
-"QWxoTK20wK","k85AeDz1R3","I7p2atl72W","jeskSuN6r3","QbxXc45cIH","AIYUus93Ml","5nmWvatef2","BpYhVbrhlQ","DcpWBAgJHQ","Oz8yZx3LDe",
-"aL6AJ48cHL","5nmWvL7cGc","9XyT9P6bcg","prNT6FjHXR","uLtKsMojnP","lj07QEdBKc","uN6r3oGu6x","8xEKzgIYvE","CxVEfJRJQB","XyPZNguMb8",
-"xciqpGv3Fq","Nxx9Vpv0i7","CqqaDrhl0J","Y1mC0M6qcG","wDajX9GXkX","GrDg7x3LDe","b29RJCqqaD","tAOsrlj07Q","djsrvMojnP","VIlwPo8Uyd",
-"Y1mC0GrDg7","Uvlv4aFFss","euZA55ZaEz","lXFOBru4UG","FPfSEUlU3M","ZUnqtQworu","ZUnqtRBhp0","uPX7GTCgPp","Yh1hF55rfB","yvOMI8FmFH",
-"5nmWvsqVrf","lXFOBJIqXi","7fKYUKr8ys","MGlTFHP433","jtn0XtvdkD","VjCZqatef2","uLtKsgtCA5","sqVrfQYxC0","DG4sTSs0Zu","qUJMdoGu6x",
-"F6PT2LewvM","Dz1R3Oz8yZ","jiVBPK20wK","FwEJzx3LDe","a00b52ZHdk","1j5L8lkMUA","Z4I1vEdBKc","o8UydKsjRK","55rfBhE1Ql","x3LDeBCxeC",
-"WPmlxsqVrf","m4bxUhUTw7","yofH314FLR","uZPqg64s8N","BFkb8Yh1hF","uAWypFxX9q","RkQkeWaim6","qUJMd7ku1p","5Drn0CK5W7","RmDcr2Yz7E",
-"C2IrcxReec","qaofNokgRi","QWxoTsx5Gl","MmsIoJJs5m","yluBxlH1kt","45cIHnnP8o","RBhp0qQxHP","faHirprNT6","lkMUAiKqhr","M6qcGgtCA5",
-"iqv4kix74r","jSjS3uQIcz","tuDySNAFuw","fmIK1B3qem","n8pJ907n1c","HP433fmIK1","In3NSnFqik","lkMUA5iGN5","xReec3otm6","HlUbFzqH0W",
-"ix74ruN6r3","G1RhS0YAGH","5IhmGsqVrf","M3zXL618Di","Ta8f6JIqXi","ZhwG1CxVEf","guMb8hE1Ql","uPX7GdmoS7","0h1b1ogLgc","fqypyNAFuw",
-"o8UydDLhzM","VLTy6uZPqg","soy9tMezSW","Mm8siQClRL","1v5hHW7cTs","GSQwjKASQ8","uTacx9XyT9","VBjhzZv7z0","EdBKc0BmCy","hSSvQgf8rI",
-"Yw2oUzY1GY","FhtglXyPZN","rhl0JW3VFH","yEfy9dmoS7","CNHmvs7Mxk","ydG8UFLsph","jiVBPt59lR","a00b5Mkgy8","tvdkDjfREu","ZuDtDFGzgp",
-"QbxXcpWiOs","0PktId85a9","piJSklm0pD","9eoRcfcwDa","Gv3Fq8xEKz","fcJOyJkzUn","aL6AJZzJHW","YOfrYmz8gx","ZuDtDNhXdu","GWqqXwiHrZ",
-"9rlg9tuDyS","Gv3FqQnJ1S","tvdkDO3iyQ","aL6AJWDVWJ","t59lRCxVEf","lweGyOxWIH","QClRL8TxD7","hi5X7Kr8ys","D6rByzY1GY","0PktIbrhlQ",
-"MGlTFMK07Y","ThjNnuoStw","LewvMdpe1v","ZJTXH16lHc","uTacxSmGzv","s4786uoStw","ciuWzTwano","GrDg7Chuy3","64s8NOUqFM","iB08lMmKGJ",
-"fmIK1OUqFM","lm0pDRmDcr","azIWpVerEA","lweGyGXdoH","t59lRNOHsz","Mm8siru4UG","S2DfujSjS3","AXpwECqqaD","Chuy3CxVEf","7fKYUbrhlQ",
-"lweGyD6rBy","7X3uy8cVD3","lViBvprNT6","2TRI7L7cGc","AOgEe0h1b1","pmeCdRzaZA","Ta8f6POUYS","TwanoLDk6f","S2DfugtCA5","pT8wuJXljW",
-"QworuhE1Ql","Yf2EcxReec","FPfSEFLsph","jeskSyvOMI","RBhp0pFrrl","xciqpoVQp6","okgRis4786","MezSWs93Ml","uAWypoGu6x","dpe1vFhtgl",
-"HP4332TRI7","AIYUuIjTwP","ulk419y4lw","GSQwjpT8wu","48cHLK4GS8","IRh48EOE1o","FcWrWnlaBy","HRxd80ao3l","0BmCyxciqp","faHiryvOMI",
-"JXljW0MR5X","M3zXLSbRYy","pFrrlIjTwP","xReec2ZHdk","yofH3POUYS","Dz1R3s93Ml","soy9tWreyP","tvdkDAmdQd","4QMc9Mm8si","vOqCEvLsmS",
-"8hJdttvdkD","mX2GElsQGo","AkKTkjiVBP","POUYSaFFss","oGu6xuvf7A","GWqqXWreyP","faHirzY1GY","okgRiciuWz","IBe8kQ6hMC","pvgjSlkMUA",
-"gjUTu5Mg9r","EOE1oMmKGJ","v1Hlne6e4z","Cp3mZQ6Lix","FNYIMTCgPp","cQOnvjzUqR","i3pydjtn0X","x3LDed7vjM","0Wr5yyEfy9","CK5W7hi5X7",
-"WmadAni2v1","pT8wuatef2","7fsYMaFFss","pmeCduZPqg","JXljW0PktI","Ta8f607n1c","BCxeClViBv","i3pydCIShG","ZUnqtHfyNQ","gjUTuQ6Lix",
-"QYxC0ogLgc","zFgtBThjNn","cmXIXRsQUq","hSSvQW3VFH","M3zXLVBjhz","1v5hHOUqFM","b29RJfcwDa","KsjRK0h1b1","1j5L8e6e4z","WaWsvzFgtB",
-"JkzUnMmsIo","MaJQsmX2GE","FwEJzlkMUA","FLsphzHF1q","HzZT8aL6AJ","nFqik55rfB","Yf2EcuTacx","ogLgcMmsIo","DQimpbrhlQ","6AFT0qUJMd",
-"tlILtyEfy9","jzUqRYf2Ec","cQOnvt98iW","i3pyd5ZaEz","7fsYMdhSuH","JkzUnIKxdL","MmsIoQ6hMC","JKWYRs4786","ulk41FwEJz","hE1QlB3qem",
-"ZhwG1yEfy9","5VZjSpv0i7","In3NSgjUTu","W7cTsHzZT8","CqqaDVLTy6","Q6hMCsuY4x","ZUnqtnFqik","nnP8oDG4sT","In3NSBFkb8","brhlQbrhlQ",
-"lm0pDt59lR","uTacxRxrsm","v8yFNyofH3","WreyPBGaQY","WDVWJ0YAGH","ECMvUqaofN","FhtglJIqXi","AIYUuYjB9t","jSjS3F6PT2","gdQsSMmsIo",
-"NAFuwFNYIM","dmoS7Dz1R3","EdBKc9XyT9","AOgEecShY2","jzUqRx3LDe","Kr8yspv0i7","nFqikVprf2","Cfgr3Rxrsm","I7p2aM6qcG","VerEA9iGoT",
-"Ss0Zu45cIH","qQxHPjSjS3","Gv3FqDcpWB","NAFuwIBe8k","a00b5RmDcr","StlDJpWiOs","NAFuwOHaBz","XflUqfFDrJ","5VZjS5Mg9r","tlILth1zcH",
-"2hEEUZv7z0","5ZaEz2Nslm","uAWyp8RCUA","WmadA8cVD3","Zv7z0QClRL","faHirvOqCE","UmaEv55rfB","v8yFNZhwG1","tAOsrbgJAz","lpF6WStlDJ",
-"iKqhrTwano","VLTy6ZJTXH","P6bcgn8pJ9","5IhmGX6Pin","jfREupFrrl","2NslmlsQGo","fFDrJStlDJ","Y1mC0DG4sT","uupzkzHF1q","ZUnqtC2Irc",
-"9XyT98FmFH","B3qemlCMxy","QworuRxrsm","uN6r3ix74r","G1RhSIBe8k","FGzgp9y4lw","VjCZqWaWsv","TXQ0ZiKqhr","4QMc92hEEU","Q6hMCCxVEf",
-"RmDcrB3qem","brhlQHfyNQ","M3zXLThjNn","0h1b1gdQsS","lpF6WoGu6x","FxX9quN6r3","cL0aERmDcr","faHirStlDJ","s4786JIqXi","qaofN5Mg9r",
-"QYxC09rlg9","FxX9qEoToP","tl72WlkMUA","ReKEWgtCA5","KASQ8kZANm","Q6hMCxReec","EdBKcMGlTF","s93MlfcwDa","M6qcG5nmWv","lCMxyDcpWB",
-"WmadATXQ0Z","AOgEehYBCK","S2Dfu7Ow5C","pWiOsqaofN","EOE1ouPX7G","yofH3yofH3","uPX7GjeskS","lkMUAfaHir","0KyfsbgJAz","uAWypGSQwj",
-"n8pJ9ZhwG1","fmIK1Chuy3","HfyNQWreyP","tvdkD8cVD3","WMiS3lViBv","Vprf2W7cTs","uLtKsgf8rI","v2eC3StlDJ","i7WMQSmGzv","GXdoHNxx9V",
-"G1RhSLDk6f","GXdoHCxVEf","CdyBVv2eC3","t98iWfqypy","FnPFBEoToP","jfREu6AFT0","s4786ix74r","8hJdtFcWrW","tAOsrrz7Ut","fqypypWiOs",
-"uAWypvkCHH","pmeCd8xEKz","45cIHNAFuw","YOfrYGrDg7","CNHmvlweGy","tuDySOxWIH","Cfgr3gf8rI","lsQGov1Hln","UlU3MHzZT8","W7cTs8hJdt",
-"RACuj1j5L8","9GXkXjzUqR","lm0pDBpYhV","BCxeCCfgr3","FhtglqaofN","16lHc0MR5X","FFDuiVNCPd","FVMxom4bxU","zQt6Qrhl0J","aDGtSqUJMd",
-"8hJdtyvOMI","fLNg8W7cTs","HfyNQYh1hF","Waim6dpe1v","s7MxkHfyNQ","GSQwjG1RhS","Q6hMCAOgEe","2Yz7E8hJdt","MojnP4W0Tl","AXpwEoQ87r",
-"tlILthe9IA","1j5L8yluBx","kB5nP7X3uy","5ZaEz7fsYM","OUqFMyEfy9","45cIH618Di","azIWpStlDJ","TCgPpzqH0W","nnP8oXyPZN","atef2fqypy",
-"GXdoH45cIH","K4GS8blLA9","pv0i7Q6hMC","uupzkHlUbF","lH1ktVNCPd","piJSkBGaQY","XyPZNWreyP","IKxdLVLTy6","gjUTua00b5","zQt6Q5Drn0",
-"dpe1vsqVrf","2DREsoGu6x","lXFOBYf2Ec","tvdkDuQIcz","dpe1vpiJSk","EoToPQnJ1S","VLTy6lpF6W","rz7Ut4W0Tl","n8pJ9Yf2Ec","5Nammx3LDe",
-"9eoRcS2Dfu","8FmFHSjskQ","cL0aEVIlwP","YOfrYG1RhS","tuDyShYBCK","FjHXR8RCUA","BpYhV7hyVv","GWqqXFhtgl","M6qcGFcWrW","Q6LixdhSuH",
-"O3iyQC2Irc","LDk6fChuy3","JkzUns93Ml","G1RhSQChxs","AXpwEIBe8k","jeskSChuy3","rhl0JBGaQY","VjCZqZuDtD","2DREs4W0Tl","5drc6QWxoT",
-"zz4ZUprNT6","1LB1Le6e4z","o8Uydv8yFN","GrDg7O3iyQ","FPfSEQYxC0","RxrsmI7p2a","8TxD7S77LH","WDVWJjS1aj","ni2v1Zv7z0","uPX7GQssNC",
-"vOqCEWPmlx","HP433uTacx","dhSuHjeskS","IBe8kzQt6Q","uAWypnnP8o","zqH0WkB5nP","9XyT9dhSuH","l83UdOHaBz","sqVrfciuWz","8RCUAxXTI4",
-"FcWrWhE1Ql","rhl0JLDk6f","CdyBVqaofN","Q6hMCAIYUu","K20wKK4GS8","y94nwdpe1v","Kr8ys0Kyfs","v2eC3OUYuF","i7WMQ0MR5X","7fKYUCxVEf",
-"FjHXRMK07Y","gIYvEVLTy6","FnPFB7ku1p","2Nslm0BmCy","LDk6fksJby","h1zcHjzUqR","JRJQBxciqp","fqypyIRh48","2Yz7Ev8yFN","8FmFHMGlTF",
-"5iGN5FxX9q","1v5hHOHaBz","2TRI7Nxx9V","8U2nUblLA9","uZPqgKZamH","FFDuiPOUYS","1LB1LGWqqX","29QAzFNYIM","kZANmGrDg7","zqH0WJkzUn",
-"lsQGo0YAGH","0MR5XpmeCd","Mkgy8gjUTu","D6rByFjHXR","FjHXR5iGN5","gf8rI45cIH","d85a9jeskS","X6PinZhwG1","LewvMWDVWJ","ThjNnYOfrY",
-"I7p2aYw2oU","07n1cYOfrY","Yf2Eclj07Q","0h1b18xEKz","AOgEelweGy","5Drn0hE1Ql","fFDrJJRJQB","X6PinHfyNQ","FGzgpjiVBP","MojnPI7p2a",
-"djsrvFnPFB","brhlQGSQwj","BCxeCG1RhS","0KyfsReKEW","Kr8yszqH0W","sx5GlzY1GY","hYBCKVLTy6","uPX7GxReec","0PktIuJScX","a00b5RACuj",
-"5IhmGW3VFH","2ZHdkpFrrl","ix74rjtn0X","0PktI7fKYU","gtCA5IRh48","HP4332hEEU","ru4UGzmLYD","OUYuF2TRI7","0KyfsMmsIo","he9IAX6Pin",
-"a00b5ciuWz","QworuUvlv4","9GXkXMK07Y","YjB9tKZamH","cQOnv2Nslm","uvf7AQYxC0","BGaQYS2Dfu","ZJTXHDz1R3","JJs5mMezSW","fFDrJoVQp6",
-"lpF6WXflUq","45cIHQworu","NhXduOUqFM","uLtKsZv7z0","C2IrcGv3Fq","jtn0Xfqypy","Yh1hFsx5Gl","DLhzMCfgr3","LbRTHPYBf4","uvf7A2TRI7",
-"8FmFHKASQ8","POUYS0Kyfs","Fhtgle6e4z","IjTwPQChxs","xReecNxx9V","No0Qbaez9y","FFDuiWaim6","24ARFvLsmS","F6PT26AFT0","tl72WoVQp6",
-"prNT6vkCHH","Yh1hFKASQ8","FxX9qQworu","i7WMQDcpWB","BpYhV5nmWv","UmaEvoVQp6","HRxd84dEz6","4QMc9s4786","aFFssAXpwE","pT8wud85a9",
-"8hJdtIn3NS","gdQsSgtCA5","8TxD7YOfrY","1v5hHPb1pa","FjHXRHfyNQ","AkKTktvdkD","oQ87rRACuj","Kr8yszFgtB","uLtKsNo0Qb","ZzJHWd85a9",
-"jtn0XogLgc","M3zXL9XyT9","7fKYUjfREu","pv0i7uZPqg","48cHL5Namm","uJScXpv0i7","RzaZAzQt6Q","MmsIoksJby","7lUXZM6qcG","KsjRKQ6hMC",
-"suY4xRzaZA","0MR5XfcJOy","JIqXiBGaQY","WMiS36AFT0","jSjS3FxX9q","NOHszQChxs","Cp3mZatef2","x3LDe2DREs","X6PinK4GS8","SjskQK20wK",
-"618DiogLgc","64s8NECMvU","bZLvSfcJOy","lj07Q7lUXZ","ydG8UFPfSE","5iGN5gdQsS","Pb1pauLtKs","hYBCKHzZT8","4W0TlzFgtB","pAhR1TCgPp",
-"cmXIX4QMc9","blLA9i3pyd","14FLRLDk6f","9XyT9vLsmS","7fKYUSbRYy","7fsYMoVQp6","Yw2oUgjUTu","14FLRzz4ZU","wDajXZzJHW","WaWsvcShY2",
-"HP433Zv7z0","BFkb864s8N","fLNg80YAGH","W7cTs0YAGH","3weIFI7p2a","Cp3mZRsQUq","cL0aE9eoRc","FNYIM7hyVv","QYxC0WDVWJ","zHF1qBFkb8",
-"KsjRKrhl0J","1LB1LoGu6x","taOXKM3zXL","FcWrWhUTw7","NAFuwdmoS7","RmDcrpT8wu","lCMxyNxx9V","TXQ0ZL7cGc","9rlg9cmXIX","yluBxaL6AJ",
-"LDk6fnnP8o","AgJHQZhwG1","pv0i7vLsmS","lj07QtlILt","lpF6W8hJdt","VNCPduN6r3","FPfSEYjB9t","GWqqXBpYhV","MGlTFtlILt","n8pJ9BGaQY",
-"yvOMIHfyNQ","lkMUAS77LH","qaofNQnJ1S","RmDcrpv0i7","7lUXZL7cGc","AmdQdNcICA","jzUqRTCgPp","BGaQYeuZA5","mX2GEyluBx","AgJHQCIShG",
-"HRxd8P6bcg","qaofNl83Ud","IBe8kTwano","1LB1Li7WMQ","4W0Tlv2eC3","618Di0YAGH","ReKEWtaOXK","faHirnlaBy","tlILtpFrrl","Mkgy8wiHrZ",
-"i7WMQzz4ZU","ix74rKr8ys","tuDySs7Mxk","fmIK1he9IA","tuDySAgJHQ","ogLgcaez9y","hi5X755rfB","Z4I1vv2eC3","zHF1qMojnP","Oz8yZ5IhmG",
-"fcwDalH1kt","OUYuFHzZT8","1v5hHyEfy9","oGu6xvkCHH","zmLYDo8Uyd","QYxC0wiHrZ","oQ87ryToGW","lj07Q0MR5X","x3LDeK4GS8","JJs5mQWxoT",
-"RkQkeazIWp","FwEJzvLsmS","CIShGwiHrZ","W7cTsQworu","2Nslmtl72W","i7WMQSs0Zu","aDGtSyluBx","CqqaDtlILt","ZuDtDI7p2a","fqypy6q6L9",
-"FPfSE2TRI7","U3yw5okgRi","DQimpJkzUn","FNYIMCIShG","MezSWuQIcz","8U2nUNOHsz","RBhp0soy9t","0h1b1piJSk","rKDLJaFFss","nnP8oCK5W7",
-"wDajX8RCUA","618DiOxWIH","WreyPi7WMQ","45cIHFxX9q","RpBQmMaJQs","pvgjSDG4sT","lpF6WQWxoT","In3NSAOgEe","uLtKstjQxs","MaJQs2hEEU",
-"WDVWJuN6r3","QnJ1Sb29RJ","Q6hMCzmLYD","zqH0Wv2eC3","aez9y7ku1p","FGzgpqUJMd","I7p2arz7Ut","ru4UGzY1GY","4W0TlBFkb8","2Yz7ERzaZA",
-"F6PT2vOqCE","o8UydLewvM","lH1kt1v5hH","X6PinuJScX","tuDySCK5W7","tjQxsBbwgA","CqqaDlsQGo","Vprf2AIYUu","uoStwyToGW","gtCA5CNHmv",
-"OUqFMtlILt","aDGtSX6Pin","taOXKRsQUq","Cp3mZXyPZN","he9IAQworu","aL6AJpT8wu","MmsIovkCHH","BGaQYyvOMI","FFDuiCxVEf","BpYhVYw2oU",
-"zQt6QXyPZN","U3yw5Zv7z0","BbwgArKDLJ","jiVBPBbwgA","ydG8URmDcr","AOgEeMaJQs","fmIK15Drn0","KZamH0MR5X","hSSvQjSjS3","lViBvtaOXK",
-"jiVBPeuZA5","xciqpVjCZq","7X3uyWaim6","TwanoUlU3M","0Wr5yECMvU","S2DfulXFOB","4W0TlFcWrW","uPX7GFnPFB","6AFT0fcJOy","ZJTXHDG4sT",
-"WMiS3HRxd8","vOqCE2hEEU","v1Hln2hEEU","aL6AJuZPqg","Chuy31v5hH","t59lRru4UG","CxVEfBFkb8","W7cTsx3LDe","Mkgy87lUXZ","gdQsS7hyVv",
-"XyPZNJJs5m","FGzgpcQOnv","oGu6xyToGW","WmadAbZLvS","8cVD3OHaBz","No0Qbd85a9","JIqXis93Ml","8xEKzMGlTF","JXljW9GXkX","tvdkDhi5X7",
-"9iGoTpmeCd","K4GS8jiVBP","Y1mC0Z4I1v","uQIczblLA9","RkQkeLDk6f","cmXIXK4GS8","gtCA52Nslm","IKxdLPYBf4","zFgtBWaim6","XyPZNCdyBV",
-"suY4xnlaBy","he9IAlweGy","uAWypxciqp","ni2v1fFDrJ","mX2GEe6e4z","tjQxsZJTXH","pWiOsru4UG","K20wKJJs5m","X6Pin14FLR","oQ87rtvdkD",
-"Ss0ZuCK5W7","lj07QK4GS8","VLTy6fqypy","ogLgc48cHL","VLTy61j5L8","pT8wuC2Irc","pmeCdYOfrY","3weIF5drc6","kZANmChuy3","ulk41G1RhS",
-"5nmWv0BmCy","55rfBi7WMQ","8cVD3VerEA","RkQkeLewvM","Kr8ysFPfSE","YjB9tcL0aE","0h1b1POUYS","uPX7GjiVBP","RmDcr0h1b1","BGaQYpvgjS",
-"kZANmwiHrZ","16lHcfqypy","oGu6xYf2Ec","hE1QlO3iyQ","HfyNQOxWIH","taOXKzbIYY","kZANmOHaBz","qQxHPVjCZq","xReec5IhmG","oGu6xfLNg8",
-"kB5nP7ku1p","CqqaDjSjS3","gtCA5n1pmO","uvf7AW7cTs","o8UydMmsIo","dQ586lj07Q","07n1cvOqCE","7X3uy29QAz","EoToP8TxD7","YjB9tMojnP",
-"3otm6bgJAz","VerEARkQke","lsQGojfREu","UmaEvRACuj","64s8NCp3mZ","qQxHPQYxC0","o8UyduAWyp","jiVBPQChxs","pWiOsQClRL","sqVrf2Yz7E",
-"rz7UtMaJQs","4QMc95Drn0","s7MxkVBjhz","0ao3lAOgEe","7ku1pydG8U","gdQsSlm0pD","n1pmOpvgjS","OxWIH580YD","cQOnvpv0i7","uoStwHlUbF",
-"rKDLJdmoS7","VBjhzrz7Ut","jSjS3ix74r","pAhR1QbxXc","blLA9iqv4k","FPfSEbrhlQ","MGlTFQClRL","M6qcGqaofN","MGlTF0YAGH","hUTw7EdBKc",
-"ix74ryToGW","oVQp6J2mQi","P6bcg7lUXZ","7fKYUqUJMd","fqypyiB08l","EOE1otaOXK","BGaQYy94nw","29QAzK20wK","Mkgy8FNYIM","cL0aEi3pyd",
-"EdBKcU3yw5","4QMc9AmdQd","1v5hHgjUTu","JJs5md7vjM","No0QbLbRTH","BFkb8CxVEf","5IhmGAkKTk","zbIYYpiJSk","ru4UG0YAGH","fqypy9GXkX",
-"16lHc6AFT0","lH1ktM6qcG","KsjRKMm8si","zz4ZURmDcr","a00b5tlILt","ZzJHW3weIF","CNHmvHP433","8cVD3BFkb8","RmDcrrhl0J","FPfSEsx5Gl",
-"d85a9CqqaD","P6bcgd85a9","HRxd8AkKTk","Zv7z0Yh1hF","VLTy6fLNg8","dpe1vGWqqX","o8UydFjHXR","ReKEWW7cTs","hYBCKECMvU","YOfrYXflUq",
-"oQ87rsqVrf","RmDcrzY1GY","M3zXL7Ow5C","FVMxolsQGo","1LB1L0h1b1","Mkgy85nmWv","aez9yguMb8","xReecblLA9","uTacxh1zcH","4dEz6M6qcG",
-"iwzGkHlUbF","zz4ZUCK5W7","GXdoHjzUqR","MmsIoOHaBz","tjQxsAOgEe","JRJQBMK07Y","ydG8USWfou","zQt6QJXljW","uLtKsIKxdL","VIlwP5VZjS",
-"jtn0XuPX7G","W7cTsBbwgA","pAhR1IjTwP","NcICAaDGtS","VBjhzHlUbF","h1zcHNAFuw","0Wr5yhUTw7","GSQwjokgRi","EOE1o2DREs","7fKYUIKxdL",
-"v8yFNtvdkD","l83UdBbwgA","0PktIChuy3","qaofNzQt6Q","MezSW2hEEU","aDGtSyEfy9","vkCHHOHaBz","YjB9t7ku1p","zQt6QhYBCK","W3VFHAkKTk",
-"e6e4zsoy9t","guMb8Z4I1v","Cfgr38RCUA","2hEEUW7cTs","t98iWUlU3M","RBhp0i7WMQ","WmadAtaOXK","KZamHRpBQm","UmaEv7hyVv","CdyBVSWfou",
-"1LB1Ll83Ud","In3NSlViBv","nlaBy8TxD7","kB5nPzY1GY","uQIczyEfy9","1v5hHo8Uyd","ReKEW0YAGH","s93MlYh1hF","9GXkXgf8rI","piJSkuJScX",
-"vLsmSpvgjS","dQ586SmGzv","zz4ZUuPX7G","lViBvIjTwP","2Nslm9XyT9","7lUXZ2ZHdk","MojnPAXpwE","t59lRlkMUA","14FLRHRxd8","jSjS3atef2",
-"d85a9kB5nP","RzaZAU3yw5","zFgtBX6Pin","8cVD3b29RJ","b29RJIn3NS","bZLvS0YAGH","6q6L9ydG8U","dhSuH4W0Tl","bgJAzQChxs","VerEAAmdQd",
-"yvOMIsqVrf","Uvlv4JXljW","2NslmiB08l","aez9yksJby","zFgtBEdBKc","9XyT95Drn0","JRJQBFhtgl","7hyVvVIlwP","AmdQdThjNn","MmsIodjsrv",
-"QClRLpvgjS","hUTw7vkCHH","In3NSgdQsS","X6PiniwzGk","XyPZNWaim6","5VZjSZUnqt","X6PinYOfrY","JKWYRJKWYR","AIYUuOUYuF","5Drn0ciuWz",
-"1LB1LDG4sT","9XyT9gIYvE","ReKEWFPfSE","7fsYMTCgPp","v8yFNECMvU","Q6Lix29QAz","iKqhrpFrrl","mX2GEOz8yZ","M3zXLlj07Q","WaWsvYOfrY",
-"qQxHPMm8si","tl72WiwzGk","K20wKAXpwE","55rfBSbRYy","KZamHgjUTu","JIqXiSjskQ","4W0TlRACuj","8xEKzyluBx","cShY2yofH3","FxX9qlXFOB",
-"VerEAzHF1q","8U2nUMmKGJ","faHirFjHXR","29QAzKr8ys","RzaZA4QMc9","0Kyfs9XyT9","BbwgACIShG","2ZHdkJJs5m","pWiOsMojnP","jzUqRHzZT8",
-"AXpwEUmaEv","BGaQYWPmlx","sx5GlUlU3M","y94nwaL6AJ","iB08lzQt6Q","ni2v1GWqqX","ciuWzeuZA5","LewvMYOfrY","s93MlqQxHP","RACuj3otm6",
-"W3VFHCp3mZ","rhl0Jm4bxU","fmIK1F6PT2","ix74rWaim6","MojnPLewvM","LbRTHFxX9q","Waim6nnP8o","gjUTuokgRi","lkMUA0PktI","0Wr5ygIYvE",
-"FwEJzB3qem","7Ow5CUvlv4","MmKGJlViBv","Rxrsm64s8N","FjHXR7X3uy","WDVWJsx5Gl","pWiOsn1pmO","i3pydtaOXK","Ss0ZuGXdoH","S77LHL7cGc",
-"JRJQB14FLR","brhlQ24ARF","OUqFMRsQUq","oQ87rcmXIX","OHaBz55rfB","NAFuwxXTI4","UmaEvsoy9t","ZuDtDBCxeC","v8yFN55rfB","OxWIHCdyBV",
-"yEfy9zFgtB","hYBCKpmeCd","cShY26AFT0","uN6r3lsQGo","FcWrWQChxs","LewvM5Mg9r","VjCZqVerEA","LDk6fbZLvS","qUJMd9y4lw","C2IrcYOfrY",
-"K4GS8FVMxo","aFFss5Drn0","oQ87rciuWz","8xEKzlViBv","JJs5mDz1R3","SWfouFjHXR","rKDLJQssNC","b29RJ1j5L8","RxrsmmX2GE","9rlg9taOXK",
-"1v5hHSmGzv","x3LDeTa8f6","KsjRKIBe8k","v1HlnwDajX","fFDrJuAWyp","ZuDtD24ARF","cShY2lViBv","Zv7z00h1b1","hYBCKDcpWB","yofH3W3VFH",
-"CIShG5Namm","a00b5FjHXR","rhl0JBbwgA","RkQkeJ2mQi","YjB9tIBe8k","KZamHh1zcH","uvf7ACxVEf","0PktIYOfrY","FFDui2Nslm","gtCA5DcpWB",
-"GSQwjfFDrJ","i3pydQ6hMC","JKWYRAIYUu","5VZjSMkgy8","VLTy6uoStw","lH1ktuvf7A","pv0i7CqqaD","tvdkDOz8yZ","rhl0JlsQGo","djsrvJJs5m",
-"4QMc98U2nU","PYBf4ZuDtD","uupzk07n1c","gjUTuzHF1q","yToGWzqH0W","tAOsrt98iW","07n1c9GXkX","QworujS1aj","0YAGH2Yz7E","8FmFHJKWYR",
-"8RCUAksJby","soy9t1j5L8","qUJMdFjHXR","Mkgy84W0Tl","HP433OUYuF","2TRI7yEfy9","rKDLJUvlv4","lj07QLewvM","B3qemBCxeC","5Nammiqv4k",
-"qaofNXflUq","JKWYR0ao3l","v2eC3FLsph","IRh48FFDui","fqypyeuZA5","GrDg72Nslm","P6bcgl83Ud","n1pmOIBe8k","oQ87rUvlv4","sx5GlGXdoH",
-"okgRim4bxU","k85Ae9XyT9","aez9yThjNn","nlaByCfgr3","yluBxn1pmO","2TRI7AXpwE","VNCPdNOHsz","2DREs580YD","Fhtgl9y4lw","XyPZNWMiS3",
-"XflUq1LB1L","mz8gxNxx9V","jtn0XRmDcr","No0Qbuupzk","zmLYDFwEJz","ZzJHW45cIH","KZamH1v5hH","jSjS3uZPqg","Kr8ysdQ586","hE1QlZv7z0",
-"0PktI4dEz6","djsrvWreyP","0BmCyFwEJz","BCxeCNhXdu","ThjNn8cVD3","IKxdLSjskQ","VIlwPpmeCd","AgJHQjtn0X","OxWIHIRh48","Waim6lweGy",
-"uoStwCqqaD","CNHmvtl72W","NAFuwfaHir","pAhR1S77LH","iqv4k7lUXZ","jtn0Xm4bxU","55rfB618Di","RkQkejzUqR","VjCZqOxWIH","gIYvEUvlv4",
-"QssNCzmLYD","8FmFHnnP8o","2Yz7E0PktI","CdyBVvLsmS","WDVWJnlaBy","FnPFBl83Ud","ogLgczqH0W","9rlg9580YD","CqqaDfqypy","cShY2AmdQd",
-"WPmlxIjTwP","580YDCqqaD","s4786YOfrY","zbIYYDG4sT","n8pJ93otm6","zHF1qatef2","J2mQihE1Ql","JkzUn8TxD7","t59lRcmXIX","uupzk8U2nU",
-"sqVrfgtCA5","fFDrJlCMxy","JJs5mBpYhV","FnPFBAOgEe","0h1b1s7Mxk","tvdkDQnJ1S","Yf2EcNAFuw","BpYhVjfREu","ZzJHWpv0i7","IRh48QWxoT",
-"618DiZv7z0","jS1ajMmKGJ","8U2nURACuj","tl72WCqqaD","zbIYYaDGtS","CK5W7WaWsv","gdQsSpT8wu","Yf2EcLewvM","QChxsJIqXi","HzZT8C2Irc",
-"lsQGoAkKTk","x3LDe5ZaEz","vOqCEAkKTk","i3pydIjTwP","pFrrl1LB1L","VBjhzjzUqR","WmadAKASQ8","24ARFCxVEf","bgJAzZuDtD","aez9yulk41",
-"580YDuoStw","LewvMgf8rI","QWxoTuN6r3","dQ586618Di","DG4sTDz1R3","FGzgpSmGzv","X6Pin9rlg9","K20wKZzJHW","SbRYySmGzv","wiHrZECMvU",
-"suY4xxReec","JIqXi0YAGH","7fKYUFLsph","lweGyvOqCE","OHaBzSmGzv","9GXkXhi5X7","QChxsQWxoT","Pb1pah1zcH","fqypyydG8U","KZamHm4bxU",
-"pFrrlzmLYD","DcpWBJKWYR","B3qem07n1c","ix74rNo0Qb","pAhR1m4bxU","Y1mC0M3zXL","Mm8sijfREu","sx5Glt59lR","fcwDah1zcH","Qworulm0pD",
-"lXFOBpiJSk","LDk6fPOUYS","Q6Lix0PktI","MK07YuJScX","FcWrWiwzGk","pFrrlRzaZA","M3zXLQssNC","0Wr5y2DREs","uPX7Gpv0i7","vkCHHsx5Gl",
-"MGlTFqQxHP","bZLvSBCxeC","ni2v1MmKGJ","QnJ1S5nmWv","ZUnqtuoStw","uJScX2Yz7E","AIYUuGrDg7","GXdoHlweGy","7hyVv3otm6","dmoS7fFDrJ",
-"GSQwjMojnP","cShY2o8Uyd","WmadAguMb8","4W0Tl8hJdt","n1pmO8U2nU","C2IrclCMxy","QWxoTCdyBV","ciuWzMGlTF","Mkgy8TCgPp","vLsmSsoy9t",
-"6q6L9aez9y","QbxXcFFDui","BFkb8vkCHH","uoStwfmIK1","uLtKs8cVD3","POUYSdmoS7","lsQGoSbRYy","jSjS329QAz","gtCA5kZANm","SjskQyluBx",
-"uZPqgSWfou","HRxd8VIlwP","sqVrflCMxy","Mkgy88FmFH","WmadAnnP8o","iKqhrRBhp0","8xEKzgtCA5","RpBQmdmoS7","aL6AJ6AFT0","uupzkgdQsS",
-"lj07QaL6AJ","VjCZqNhXdu","GrDg7dpe1v","RACujBCxeC","rz7UtOxWIH","2Yz7E0BmCy","dpe1vB3qem","gjUTu6q6L9","WDVWJWMiS3","DQimpm4bxU",
-"45cIH5iGN5","Chuy3aez9y","4W0Tl55rfB","55rfB45cIH","U3yw5jSjS3","BFkb85IhmG","yToGWPb1pa","zFgtBSWfou","YjB9thSSvQ","fFDrJnFqik",
-"1j5L8FnPFB","atef2fLNg8","v2eC34QMc9","xReeclkMUA","soy9tLbRTH","ZJTXHvLsmS","OUYuFCxVEf","XyPZNTXQ0Z","CdyBVMkgy8","JJs5mTXQ0Z",
-"lj07QfcJOy","fcJOycmXIX","QssNCgIYvE","a00b5CNHmv","VIlwPNOHsz","cL0aEChuy3","uAWyptjQxs","RBhp0nlaBy","M6qcGWreyP","7fsYMzmLYD",
-"WMiS3Zv7z0","d85a9tl72W","5Namm9GXkX","EdBKcfmIK1","EoToPuTacx","AXpwE8hJdt","UmaEviB08l","P6bcgD6rBy","9rlg9AXpwE","djsrvZJTXH",
-"AmdQdm4bxU","RsQUqk85Ae","lj07Q5VZjS","zHF1qHfyNQ","cL0aE5nmWv","FnPFBUvlv4","PYBf4lViBv","9GXkXulk41","nFqikGXdoH","lm0pDjiVBP",
-"IRh48yEfy9","MGlTFulk41","hE1QlnFqik","B3qemKr8ys","jfREuydG8U","9rlg9uLtKs","3otm65ZaEz","fcJOy5ZaEz","uPX7GHfyNQ","y94nw5Namm",
-"14FLRhE1Ql","ni2v1CxVEf","n8pJ9DcpWB","ZUnqtlm0pD","dmoS77Ow5C","qaofNzqH0W","D6rBycShY2","POUYSYh1hF","jiVBPydG8U","4dEz6JkzUn",
-"uoStwCfgr3","16lHcNxx9V","5iGN5ru4UG","QssNCTXQ0Z","KZamHS77LH","GXdoHaez9y","NOHszZ4I1v","JXljWMK07Y","JJs5mZzJHW","XyPZNSmGzv",
-"azIWpFNYIM","AgJHQcShY2","azIWprz7Ut","KASQ8Oz8yZ","FFDuinFqik","WMiS3Uvlv4","lkMUAAgJHQ","bgJAzRzaZA","hE1QlNcICA","Yw2oUuLtKs",
-"sx5Gl0Wr5y","uZPqg2Nslm","HlUbFFGzgp","POUYSYjB9t","zY1GYZJTXH","M3zXLDcpWB","VerEA9XyT9","0Wr5ylH1kt","jtn0XRxrsm","hSSvQ7fKYU",
-"8xEKzRkQke","CdyBVEoToP","gf8rIt59lR","9XyT9ru4UG","G1RhSqaofN","PYBf4VBjhz","zmLYDJJs5m","lweGye6e4z","qUJMdQ6Lix","qaofNJ2mQi",
-"L7cGcxXTI4","Mkgy8CdyBV","aFFsscQOnv","v2eC3ulk41","x3LDeFLsph","t98iW6AFT0","TXQ0Z55rfB","MojnP8hJdt","RBhp0No0Qb","WaWsvprNT6",
-"1v5hHWMiS3","OxWIHlsQGo","jeskSfFDrJ","QworuFLsph","24ARFQssNC","TCgPpPYBf4","tAOsr8U2nU","Gv3FqcShY2","HP433v1Hln","uPX7GvOqCE",
-"brhlQx3LDe","5ZaEzqUJMd","l83UdoVQp6","CqqaDk85Ae","9rlg9GXdoH","07n1cAmdQd","NOHsz55rfB","8U2nUDz1R3","7Ow5CNOHsz","BGaQYLbRTH",
-"S2DfuEdBKc","618DiksJby","v8yFNpAhR1","S2DfuAkKTk","Chuy3BFkb8","7fKYU8FmFH","xReecTwano","NcICAqUJMd","dhSuHReKEW","LDk6fqUJMd",
-"L7cGcJRJQB","MmsIo2ZHdk","lH1ktKsjRK","StlDJCqqaD","uN6r3yofH3","9rlg9s7Mxk","KZamHix74r","azIWpsoy9t","OUYuFazIWp","fFDrJi3pyd",
-"Uvlv40Wr5y","BFkb81v5hH","xReecyToGW","9iGoT0BmCy","DQimptAOsr","mX2GEtaOXK","zHF1qPb1pa","Ta8f6MezSW","ZzJHWRACuj","e6e4zbZLvS",
-"iwzGksx5Gl","5Mg9rgf8rI","qUJMdYh1hF","bgJAzrKDLJ","zY1GY5ZaEz","uPX7GrKDLJ","6q6L9SWfou","9eoRcJKWYR","2hEEUjfREu","Oz8yZhYBCK",
-"JRJQBSbRYy","n8pJ9cmXIX","yofH3618Di","uoStw6AFT0","RxrsmJIqXi","POUYS6AFT0","blLA9AIYUu","iqv4kokgRi","bgJAzM3zXL","Dz1R3SjskQ",
-"fqypyCK5W7","i7WMQ64s8N","580YDDG4sT","SWfousx5Gl","piJSkHfyNQ","VBjhzsqVrf","HlUbFIn3NS","LbRTHn8pJ9","t59lRBbwgA","Chuy3AmdQd",
-"soy9tlViBv","AOgEeQ6Lix","LbRTHX6Pin","uvf7AlCMxy","Vprf2dhSuH","RACujVprf2","NhXduhSSvQ","QbxXcogLgc","dQ5868FmFH","soy9tpvgjS",
-"8cVD3kZANm","5ZaEz5VZjS","SmGzvJIqXi","CNHmvX6Pin","0Kyfs580YD","zFgtBx3LDe","n1pmOblLA9","azIWp2Yz7E","sx5GliKqhr","X6PinaL6AJ",
-"AmdQd2hEEU","JKWYRogLgc","uvf7Atl72W","QssNCQssNC","StlDJx3LDe","ydG8UlsQGo","F6PT2rKDLJ","aDGtSDcpWB","14FLRSs0Zu","K20wKC2Irc",
-"CNHmvlCMxy","qUJMdtjQxs","cmXIXJIqXi","8RCUAs93Ml","Yf2EcsqVrf","TCgPpyEfy9","xciqp580YD","DG4sTv8yFN","WDVWJhi5X7","s93MlFPfSE",
-"jiVBPyluBx","UmaEv0Wr5y","gjUTuOHaBz","wDajXUl4a1","FFDuiZhwG1","LbRTHJ2mQi","8RCUAhSSvQ","VjCZqRxrsm","VerEA0YAGH","zbIYYAkKTk",
-"rhl0JCIShG","ksJbyEoToP","WPmlxcShY2","BpYhVReKEW","uZPqgogLgc","aDGtSfLNg8","Yh1hFFnPFB","gf8rIuvf7A","pmeCdMezSW","DLhzMzbIYY",
-"taOXKiB08l","DQimpt59lR","L7cGcnlaBy","dQ586pWiOs","7lUXZ14FLR","guMb8U3yw5","GWqqXUl4a1","uPX7GECMvU","MmKGJ4dEz6","RBhp0ciuWz",
-"nlaByblLA9","tl72Wn1pmO","RkQkeC2Irc","14FLRv2eC3","fcwDa6AFT0","pvgjS7lUXZ","zQt6QQClRL","gIYvE5Mg9r","580YDWaim6","Dz1R3m4bxU",
-"JXljWjSjS3","s7Mxktl72W","t59lRZUnqt","2Nslmuvf7A","CNHmv9y4lw","EdBKc7ku1p","QWxoTZUnqt","SmGzvVIlwP","IjTwPsx5Gl","ulk41RmDcr",
-"vOqCEix74r","UlU3MRACuj","OUYuF4W0Tl","RBhp0QssNC","iB08lFLsph","Kr8ysBFkb8","NOHszxXTI4","lXFOBbZLvS","v8yFNfLNg8","JRJQBdQ586",
-"xciqpJJs5m","QChxs2DREs","ReKEWPb1pa","Q6LixiwzGk","5IhmGCp3mZ","DLhzMvkCHH","uPX7Gzz4ZU","24ARF9GXkX","AIYUuAkKTk","prNT6fqypy",
-"Yh1hFVIlwP","580YDS2Dfu","B3qemtjQxs","jzUqR5iGN5","sx5GlzHF1q","WmadA7ku1p","FNYIMdjsrv","v8yFNBbwgA","580YDnnP8o","64s8NuPX7G",
-"UmaEvv1Hln","taOXKECMvU","QYxC0NAFuw","QbxXclsQGo","v2eC3rKDLJ","2NslmPb1pa","J2mQis93Ml","ReKEWSbRYy","1LB1L9iGoT","4dEz6580YD",
-"fmIK1uLtKs","ni2v1OUqFM","t59lR8xEKz","Mm8siJRJQB","nnP8oBFkb8","jiVBPO3iyQ","JXljW16lHc","jfREuKASQ8","jzUqRoQ87r","8cVD3QnJ1S",
-"s7Mxk0YAGH","blLA9VjCZq","pv0i7D6rBy","MaJQsUlU3M","QYxC0aez9y","yluBxgf8rI","VBjhz3weIF","JXljWSmGzv","VIlwPMmKGJ","K4GS8atef2",
-"t98iWokgRi","jSjS3aFFss","HP433prNT6","VIlwPMkgy8","jzUqRRxrsm","UmaEvKr8ys","s4786qUJMd","6q6L9QYxC0","0PktIMK07Y","taOXKP6bcg",
-"D6rByJRJQB","UlU3MmX2GE","16lHcpFrrl","PYBf4jzUqR","wDajXhE1Ql","0h1b1O3iyQ","s93Ml6q6L9","W7cTsB3qem","jeskSJRJQB","vOqCEYOfrY",
-"ydG8UfaHir","CxVEfzbIYY","TCgPpHlUbF","Cfgr3BGaQY","C2IrcFFDui","WmadAuAWyp","zbIYYRsQUq","7fsYMuAWyp","CNHmvv8yFN","CNHmvWaWsv",
-"uTacxbrhlQ","tvdkDlpF6W","jfREub29RJ","mz8gxFLsph","JXljWAmdQd","Fhtgld7vjM","aez9yMkgy8","jiVBPRACuj","uPX7GIBe8k","XyPZNaFFss",
-"FLsphIKxdL","Yh1hFLDk6f","MmKGJOUYuF","QnJ1Shi5X7","lpF6WRmDcr","YjB9tvOqCE","JJs5me6e4z","9GXkXDQimp","uLtKsUmaEv","7fsYMOz8yZ",
-"KZamHjeskS","vOqCEMezSW","Gv3FqXyPZN","ZJTXH7X3uy","7X3uyNOHsz","OUYuFZUnqt","l83UdgjUTu","Mkgy8C2Irc","aFFssAkKTk","XflUqVprf2",
-"euZA5AgJHQ","TCgPpjSjS3","RxrsmlH1kt","29QAzhSSvQ","FVMxo8RCUA","JRJQBtuDyS","k85Ae7fKYU","FVMxo5Mg9r","okgRiW3VFH","3weIFbrhlQ",
-"aDGtS0PktI","Twanoy94nw","yluBx6AFT0","16lHcMmKGJ","jiVBPMezSW","FFDuiUvlv4","pv0i7gtCA5","yToGW2DREs","pFrrlTa8f6","o8Uydhe9IA",
-"SjskQFcWrW","ru4UGEOE1o","y94nwF6PT2","W7cTsUl4a1","WreyPFxX9q","DG4sTFLsph","iwzGkmX2GE","d85a9CK5W7","lkMUAFFDui","Z4I1v7X3uy",
-"IBe8kLbRTH","FVMxofaHir","cShY2Waim6","Vprf2FjHXR","jtn0XIRh48","MojnPCp3mZ","VLTy6ulk41","MK07Y0h1b1","7Ow5CqaofN","lpF6WJRJQB",
-"aFFssW7cTs","dhSuHoQ87r","5VZjSYh1hF","hi5X7ni2v1","5NammazIWp","Pb1pa9iGoT","VBjhz7Ow5C","Vprf2DQimp","9rlg9K4GS8","t98iW8cVD3",
-"6q6L9Mm8si","lCMxyjzUqR","xReecIn3NS","5iGN5TXQ0Z","fmIK1l83Ud","Q6LixRsQUq","CK5W7QbxXc","hE1QltvdkD","oQ87rcShY2","OxWIHB3qem",
-"bZLvSCp3mZ","fqypyG1RhS","bZLvSjeskS","SbRYyHzZT8","2NslmLbRTH","16lHch1zcH","ZhwG1v8yFN","LDk6fVerEA","dpe1voQ87r","IjTwPGWqqX",
-"jeskSLbRTH","WDVWJ0ao3l","GXdoH0MR5X","aDGtSGWqqX","nFqikix74r","M6qcG0MR5X","aDGtSOz8yZ","Ul4a1HP433","MaJQsStlDJ","lj07QcL0aE",
-"mX2GEuQIcz","QnJ1St59lR","e6e4zlpF6W","v2eC3ThjNn","pAhR10YAGH","07n1cO3iyQ","2TRI7YOfrY","zHF1qhSSvQ","OUqFM0BmCy","azIWpCp3mZ",
-"NcICAPOUYS","45cIHiB08l","X6PinvOqCE","1v5hHYw2oU","oQ87r0BmCy","5nmWvCqqaD","POUYSMkgy8","FVMxoFwEJz","e6e4zfmIK1","MojnPJKWYR",
-"qQxHPzbIYY","Twanok85Ae","mX2GE580YD","S2DfuWmadA","mX2GE7ku1p","iwzGkLbRTH","6q6L9JRJQB","cShY2Yf2Ec","iwzGkOUqFM","aez9yWmadA",
-"PYBf4DG4sT","GSQwjB3qem","fcJOyprNT6","FnPFBRzaZA","blLA9CK5W7","jiVBPEdBKc","FGzgp0YAGH","sqVrfAmdQd","Q6LixFwEJz","suY4xRpBQm",
-"nlaBy580YD","ZzJHWQ6hMC","M3zXLM6qcG","jSjS3bZLvS","OxWIHQClRL","zqH0WFxX9q","lXFOBMmKGJ","dhSuHlsQGo","BbwgAHfyNQ","ix74rUvlv4",
-"MmsIolm0pD","BCxeCSjskQ","taOXKJJs5m","S2DfuksJby","VIlwP5IhmG","sqVrf0Kyfs","kB5nPNo0Qb","tuDySix74r","2Yz7EGWqqX","9iGoT0PktI",
-"14FLRuLtKs","0ao3lb29RJ","0Wr5yGrDg7","2DREsGSQwj","zHF1q7fKYU","piJSkD6rBy","ulk41nnP8o","jSjS3mz8gx","FGzgpOUqFM","BbwgAcQOnv",
-"QssNCtaOXK","wDajXYh1hF","NcICAogLgc","m4bxUFhtgl","JkzUnVerEA","uPX7GokgRi","he9IAPb1pa","G1RhSb29RJ","he9IAzQt6Q","Ss0Zuv8yFN",
-"WreyPKASQ8","i3pydoGu6x","AOgEe5nmWv","jiVBPVLTy6","NhXduG1RhS","lH1kt5drc6","tjQxs0MR5X","EOE1o7Ow5C","yluBxCqqaD","WPmlx8FmFH",
-"W3VFH55rfB","bgJAz3weIF","ydG8UWaWsv","7fKYU8RCUA","ogLgcgdQsS","Ta8f6jfREu","gdQsSS2Dfu","6AFT09rlg9","QworuKr8ys","Chuy3ECMvU",
-"gf8rIZuDtD","8TxD7GrDg7","0KyfsuoStw","d7vjMNAFuw","atef2HzZT8","8xEKzXflUq","6q6L9YjB9t","iKqhrYw2oU","aez9ycQOnv","FVMxoyvOMI",
-"hUTw7AkKTk","RmDcraFFss","KZamHjS1aj","RkQke618Di","AmdQdTa8f6","jiVBPqaofN","6q6L91v5hH","qUJMdW7cTs","QYxC0G1RhS","RkQkeK20wK",
-"rhl0JGv3Fq","vLsmSpT8wu","UmaEvQnJ1S","S77LHdpe1v","OxWIHD6rBy","QYxC0BGaQY","POUYS9eoRc","jtn0XrKDLJ","24ARFYjB9t","CIShGuAWyp",
-"d7vjMRsQUq","aFFssulk41","XflUqtvdkD","48cHL48cHL","I7p2a5iGN5","7fsYMBpYhV","Nxx9VFPfSE","HzZT8Q6hMC","s7Mxk48cHL","LewvMMmsIo",
-"vLsmS580YD","5VZjShUTw7","Chuy3brhlQ","Oz8yZRpBQm","SWfouMmKGJ","VBjhzKr8ys","MGlTFyluBx","Waim6iqv4k","7ku1p8hJdt","he9IALbRTH",
-"Cfgr3nnP8o","U3yw5ZzJHW","Vprf2WMiS3","NOHszatef2","SmGzvEOE1o","lXFOBFjHXR","RACujoGu6x","cL0aEMK07Y","PYBf414FLR","l83Udl83Ud",
-"JXljW8FmFH","jiVBPyEfy9","FnPFBiB08l","WPmlxZzJHW","sqVrfiB08l","9rlg9FFDui","bZLvSKsjRK","FwEJzZJTXH","okgRiQ6Lix","Mkgy85drc6",
-"jiVBPHzZT8","HlUbFCdyBV","WPmlxiB08l","Yw2oU0PktI","gf8rI7ku1p","nnP8om4bxU","IBe8kVLTy6","QworuOUYuF","G1RhSX6Pin","RACujCxVEf",
-"mz8gxLewvM","k85AeNAFuw","yofH3OUqFM","RzaZAKsjRK","tl72Wpv0i7","WmadAmz8gx","hYBCK0BmCy","1j5L8Nxx9V","suY4xMmsIo","SmGzvsqVrf",
-"i3pydjfREu","Cp3mZfcwDa","I7p2aa00b5","hE1QlPb1pa","Yf2EcIn3NS","Y1mC0Q6hMC","tAOsr0Wr5y","zmLYDKsjRK","D6rBy3otm6","xXTI49iGoT",
-"nFqikY1mC0","7Ow5CuZPqg","lj07Qsoy9t","AXpwERmDcr","zz4ZU5ZaEz","G1RhSZv7z0","l83UdhUTw7","soy9tm4bxU","mz8gxcQOnv","Chuy3uLtKs",
-"Yf2EcQChxs","Vprf2sx5Gl","he9IAOHaBz","1v5hHSjskQ","J2mQiK4GS8","ni2v1zHF1q","ReKEWoGu6x","CK5W7L7cGc","Yw2oUzz4ZU","vkCHHpiJSk",
-"dmoS7cmXIX","EOE1oZv7z0","pT8wuKASQ8","2DREs1v5hH","SWfouL7cGc","oVQp6zmLYD","lViBvydG8U","HRxd8rKDLJ","AOgEeZJTXH","K20wKOUqFM",
-"zmLYDVLTy6","rz7UtW3VFH","FwEJzzQt6Q","QssNCU3yw5","i3pydatef2","dmoS7wiHrZ","1j5L8AIYUu","VIlwPnnP8o","JJs5mvkCHH","7fKYURpBQm",
-"pAhR1blLA9","zqH0WVIlwP","J2mQiStlDJ","XflUqkB5nP","uJScXMmKGJ","pFrrllH1kt","qaofNYf2Ec","ReKEWvkCHH","5nmWvTa8f6","D6rByiqv4k",
-"QworuK20wK","Gv3Fqh1zcH","8RCUAjfREu","lH1kt0Wr5y","Ss0ZujiVBP","guMb8zqH0W","uLtKs7hyVv","Gv3FqVNCPd","CqqaDpFrrl","MezSWQbxXc",
-"taOXKFLsph","pAhR1In3NS","HlUbF8xEKz","4dEz6xXTI4","FnPFBY1mC0","aFFssiwzGk","prNT65Mg9r","pWiOsiKqhr","LbRTHECMvU","iKqhrWreyP",
-"fLNg8n1pmO","QbxXc0Wr5y","a00b5FGzgp","SWfouBFkb8","XyPZNM3zXL","Yw2oUblLA9","VjCZqPYBf4","vOqCEn8pJ9","NcICAZ4I1v","29QAzRsQUq",
-"2TRI7xciqp","pvgjShUTw7","D6rByBbwgA","0Kyfso8Uyd","EoToPhYBCK","a00b5ZuDtD","oGu6xjzUqR","xXTI4No0Qb","pT8wui3pyd","ZhwG1rz7Ut",
-"FPfSEBbwgA","1LB1LJJs5m","atef2POUYS","yvOMIMmKGJ","YjB9tFwEJz","RxrsmokgRi","oGu6xAOgEe","5Nammlm0pD","8FmFHv2eC3","FGzgpmz8gx",
-"o8UydpAhR1","jS1ajVjCZq","X6PinyofH3","I7p2aAOgEe","ReKEWgIYvE","JkzUnuupzk","hYBCKVprf2","jfREulj07Q","ksJbyhYBCK","pAhR1FjHXR",
-"QnJ1S55rfB","vkCHHfqypy","PYBf4n1pmO","jzUqRs4786","lm0pDpFrrl","7fsYM8FmFH","v8yFNVIlwP","hUTw7FFDui","UmaEvulk41","6AFT0zQt6Q",
-"jeskSYw2oU","fcJOyIRh48","ni2v1M3zXL","h1zcH0PktI","JIqXimz8gx","VIlwPSbRYy","GXdoH1j5L8","AOgEewDajX","VBjhzbgJAz","uZPqgfcJOy",
-"Uvlv4hYBCK","48cHLQClRL","IBe8kMK07Y","Cfgr3NcICA","WMiS3zQt6Q","ZUnqtChuy3","lweGyfqypy","29QAzdjsrv","JkzUnbrhlQ","cShY2sx5Gl",
-"s7MxkfaHir","Oz8yZzqH0W","uLtKsMezSW","ZUnqt55rfB","MmKGJhYBCK","2hEEUY1mC0","ulk41X6Pin","0Wr5ySs0Zu","tl72WWaWsv","NOHszFhtgl",
-"jzUqRO3iyQ","jeskSBGaQY","Zv7z0618Di","iB08l8RCUA","vkCHHYOfrY","O3iyQCp3mZ","i7WMQBCxeC","uvf7A7lUXZ","okgRiQnJ1S","aez9yyvOMI",
-"Ss0ZuSbRYy","FnPFBjSjS3","SjskQFLsph","4dEz6BGaQY","DLhzM16lHc","Uvlv4iB08l","IRh48CqqaD","5Drn0cmXIX","ulk410Kyfs","hi5X7MezSW",
-"piJSkSbRYy","0MR5Xlj07Q","ZuDtDWaim6","AkKTklXFOB","Yh1hFBGaQY","Waim61j5L8","hUTw7ciuWz","IKxdLe6e4z","S77LHe6e4z","lCMxyv1Hln",
-"ZuDtDix74r","J2mQiSWfou","M6qcGQ6Lix","FnPFBWreyP","OUYuF2Yz7E","CdyBVzqH0W","S77LHzQt6Q","NOHszuZPqg","zmLYDZzJHW","tl72WF6PT2",
-"vkCHHMGlTF","StlDJ4QMc9","tjQxsZv7z0","KASQ8prNT6","lj07Qiqv4k","SWfouCxVEf","tlILtuoStw","i7WMQuQIcz","KASQ8dhSuH","TXQ0ZGv3Fq",
-"blLA9ni2v1","he9IAHlUbF","D6rByzQt6Q","9eoRciKqhr","BCxeC2ZHdk","Mm8sisoy9t","6AFT0xciqp","FxX9qCqqaD","CIShGD6rBy","t98iWCIShG",
-"Dz1R3gjUTu","OxWIHFjHXR","UmaEvVBjhz","6q6L9O3iyQ","SbRYyWaWsv","nnP8oSjskQ","djsrvd7vjM","POUYSh1zcH","WPmlxpT8wu","ogLgco8Uyd",
-"NcICAWMiS3","SWfou29QAz","QnJ1SCxVEf","piJSk7lUXZ","G1RhSd85a9","guMb8FFDui","EoToPzqH0W","No0Qbs4786","fcJOym4bxU","Yf2Ect98iW",
-"WaWsvFxX9q","8FmFH5Namm","4QMc9L7cGc","8hJdtsqVrf","Kr8ysvLsmS","AOgEeO3iyQ","lsQGoWmadA","ix74rLbRTH","Waim6FcWrW","U3yw5pmeCd",
-"BFkb8IjTwP","hYBCKjzUqR","lsQGoDLhzM","EOE1oGWqqX","prNT6LDk6f","0BmCytAOsr","5IhmGFcWrW","o8UydZ4I1v","O3iyQ8TxD7","8cVD3OxWIH",
-"nFqikTCgPp","l83UdU3yw5","Dz1R3lXFOB","RBhp0CdyBV","qQxHPCp3mZ","4QMc9ulk41","4W0TlC2Irc","ix74r5Drn0","ni2v18U2nU","XflUqi3pyd",
-"nlaByFxX9q","he9IAtl72W","9iGoT8TxD7","O3iyQM6qcG","5drc68hJdt","FLsphlsQGo","QnJ1SZhwG1","Y1mC0euZA5","vLsmS0MR5X","DQimpReKEW",
-"s4786HP433","MmsIoa00b5","cShY25IhmG","ydG8UHlUbF","QClRLbgJAz","dmoS7Cp3mZ","BFkb8kZANm","sx5GlxReec","tvdkDtuDyS","prNT6lsQGo",
-"VLTy6SjskQ","9iGoT6AFT0","ZuDtDxciqp","uLtKs618Di","t59lRzQt6Q","DQimpM3zXL","vLsmSVLTy6","rhl0JJkzUn","uZPqgO3iyQ","yvOMIzHF1q",
-"16lHcpv0i7","UmaEvtlILt","8hJdt24ARF","Mkgy82hEEU","mX2GEXflUq","3otm6LDk6f","8RCUAvLsmS","P6bcguTacx","bZLvSzmLYD","JKWYRyluBx",
-"JkzUnK20wK","HP433jfREu","618DinnP8o","jfREus4786","guMb8aL6AJ","GSQwjIBe8k","EOE1opT8wu","cShY2QssNC","TXQ0ZVNCPd","RBhp0dpe1v",
-"zQt6QtaOXK","gdQsSL7cGc","Yf2Ecuupzk","Oz8yZgdQsS","HlUbFSbRYy","dhSuH8hJdt","RACujs7Mxk","piJSkWMiS3","7hyVvulk41","2hEEUfcJOy",
-"Ul4a1FnPFB","P6bcgbgJAz","zz4ZU5Drn0","5nmWv1v5hH","1v5hH3otm6","K20wKNcICA","fFDrJfqypy","NhXdu8FmFH","jzUqRS77LH","FcWrWKZamH",
-"YjB9tzY1GY","IRh48BGaQY","uQIcz8TxD7","FVMxoi3pyd","OUqFMlCMxy","fqypyJkzUn","GrDg724ARF","QYxC0lkMUA","NOHszFLsph","4QMc9ru4UG",
-"FjHXR5Drn0","5iGN5DQimp","x3LDeReKEW","FVMxoni2v1","2NslmL7cGc","5Mg9rZuDtD","zY1GYChuy3","wDajXuvf7A","pmeCd580YD","Ul4a1HRxd8",
-"Ss0Zu9XyT9","1LB1LYw2oU","rhl0JaL6AJ","oQ87rmX2GE","VBjhzzz4ZU","UmaEvWmadA","ZuDtDQWxoT","Nxx9VP6bcg","fFDrJRsQUq","QChxs0Wr5y",
-"zmLYDQChxs","Dz1R3AIYUu","cQOnvqaofN","tuDyS9rlg9","Uvlv4Mkgy8","ru4UGZv7z0","NOHszX6Pin","Y1mC0y94nw","ydG8UStlDJ","YOfrYFwEJz",
-"DcpWBfaHir","9eoRc9eoRc","1LB1LokgRi","uoStwzHF1q","PYBf49iGoT","DcpWBcQOnv","brhlQjiVBP","lj07QbgJAz","iKqhrReKEW","uPX7G7lUXZ",
-"QWxoTuLtKs","blLA9zqH0W","jS1ajCK5W7","lj07Q6AFT0","VerEANxx9V","29QAzDG4sT","lpF6Wx3LDe","uPX7GMmsIo","64s8NuLtKs","Uvlv4uJScX",
-"RACujulk41","C2IrcjeskS","e6e4z580YD","GWqqXU3yw5","CxVEfOz8yZ","U3yw5JXljW","In3NShSSvQ","s7MxkwiHrZ","XyPZNMkgy8","IBe8kjeskS",
-"wiHrZsuY4x","oVQp6LDk6f","v8yFNRmDcr","VBjhzUvlv4","MGlTF9iGoT","y94nw9GXkX","OUqFM16lHc","hSSvQhE1Ql","Ss0ZupvgjS","gjUTutl72W",
-"LDk6fMGlTF","MK07YSWfou","jfREuZUnqt","7lUXZ5Drn0","Cp3mZEOE1o","HlUbFRACuj","MaJQshE1Ql","yvOMIhUTw7","4dEz6yEfy9","he9IAyToGW",
-"LewvMLewvM","GrDg7uAWyp","ThjNnStlDJ","TwanonFqik","ZuDtDK4GS8","rhl0JwDajX","ogLgcyToGW","2DREsVIlwP","RsQUq0PktI","RsQUqksJby",
-"BGaQYCfgr3","55rfBfaHir","h1zcHxReec","MmKGJpFrrl","HfyNQXflUq","aez9yLewvM","RACujuN6r3","FhtglfFDrJ","i7WMQZUnqt","2hEEUatef2",
-"ogLgcs4786","FxX9qydG8U","rKDLJsuY4x","fFDrJ14FLR","IBe8klweGy","lj07Qd7vjM","MmKGJZhwG1","pv0i7uoStw","2ZHdkFPfSE","yEfy9JIqXi",
-"GXdoHPOUYS","sx5Gldpe1v","7Ow5Culk41","lCMxy2Yz7E","a00b5JkzUn","MK07YcL0aE","F6PT2iqv4k","uoStwlpF6W","9iGoTFjHXR","WPmlxYw2oU",
-"5Drn05Namm","ogLgc0Wr5y","zQt6QSWfou","BpYhVLewvM","B3qemiqv4k","lH1ktfcJOy","CIShGgjUTu","Oz8yZ8RCUA","Ta8f6F6PT2","pT8wuDcpWB",
-"yToGWyToGW","suY4x8U2nU","CNHmvuZPqg","vLsmSwiHrZ","POUYSzFgtB","4W0Tl1v5hH","n8pJ9Cfgr3","SbRYyjSjS3","Q6LixbZLvS","I7p2alsQGo",
-"EoToPlj07Q","lj07QGv3Fq","zbIYYCK5W7","G1RhStuDyS","dQ586TXQ0Z","jiVBPdjsrv","RkQkeyToGW","euZA53weIF","lsQGooVQp6","FGzgpatef2",
-"S77LHHzZT8","SjskQRxrsm","FxX9qatef2","suY4xFLsph","gf8rIYjB9t","cQOnvtlILt","U3yw5xXTI4","7Ow5CvkCHH","FLsphzz4ZU","2Nslm6AFT0",
-"prNT655rfB","QWxoToVQp6","RmDcrdhSuH","zqH0WTa8f6","EOE1o0ao3l","TCgPpCqqaD","uZPqgIRh48","jtn0XFPfSE","NAFuwjzUqR","okgRiRsQUq",
-"DcpWBEOE1o","QnJ1SogLgc","iwzGkMm8si","blLA9zQt6Q","5Drn0lpF6W","1j5L8suY4x","pmeCdgtCA5","ni2v1KASQ8","UmaEv8FmFH","SjskQRkQke",
-"ix74rpFrrl","i3pydZv7z0","RkQke0Kyfs","rhl0JNxx9V","iwzGkWPmlx","1j5L8h1zcH","ZJTXHNo0Qb","oGu6x8TxD7","Ta8f6piJSk","iqv4k8FmFH",
-"fcwDalXFOB","K4GS8vOqCE","vOqCERBhp0","lj07QRxrsm","gIYvEZv7z0","m4bxU0Wr5y","FPfSEBCxeC","QClRLK4GS8","blLA9UmaEv","iB08ljSjS3",
-"bgJAzTwano","k85Aev1Hln","s93Ml1j5L8","yluBxyofH3","CNHmvkB5nP","yofH3v2eC3","gjUTut98iW","rhl0J9iGoT","atef28FmFH","JJs5mksJby",
-"AgJHQ2hEEU","14FLRa00b5","MmKGJW7cTs","JXljWhSSvQ","oQ87rIBe8k","tlILthi5X7","zFgtBokgRi","Mm8silsQGo","oGu6xFjHXR","jeskSZJTXH",
-"BFkb8In3NS","i3pyd5iGN5","ZJTXHWMiS3","gjUTumz8gx","JXljW7fsYM","CdyBViKqhr","0h1b1Kr8ys","NcICAAgJHQ","dpe1vRsQUq","fqypyAgJHQ",
-"gtCA5ni2v1","BFkb8lpF6W","MaJQsWreyP","lXFOBiwzGk","P6bcgVLTy6","Dz1R30YAGH","v1HlntuDyS","VjCZqiqv4k","VerEAjeskS","iKqhrnnP8o",
-"zFgtBiB08l","cmXIXJJs5m","lsQGoG1RhS","OUYuFvLsmS","djsrvfFDrJ","kZANmWaWsv","uupzkmX2GE","QYxC0gjUTu","lXFOBgjUTu","7fKYU7lUXZ",
-"xXTI4yofH3","QworuEdBKc","WDVWJogLgc","0Wr5ysoy9t","RsQUquvf7A","3otm6Nxx9V","qQxHPhe9IA","gdQsSjeskS","ReKEWuvf7A","s7Mxkjtn0X",
-"TCgPpJKWYR","pv0i7gIYvE","7fKYU5iGN5","O3iyQd7vjM","K4GS8nlaBy","wDajXFVMxo","9GXkXECMvU","gIYvEyofH3","F6PT2FjHXR","t98iWaL6AJ",
-"1LB1LnlaBy","2DREsZhwG1","dmoS7FGzgp","SmGzv5nmWv","gtCA5JRJQB","zqH0WguMb8","0KyfsMmKGJ","okgRiM6qcG","iB08lIRh48","lCMxyQYxC0",
-"MmsIo0PktI","azIWpcmXIX","tjQxspAhR1","uupzknlaBy","JRJQBI7p2a","7X3uyIjTwP","gf8rI5IhmG","lH1kthYBCK","iqv4k1v5hH","8hJdtIKxdL",
-"QClRLsuY4x","AkKTkHP433","7Ow5CJRJQB","JIqXi4QMc9","VLTy65Mg9r","QssNCRxrsm","BCxeCrhl0J","BCxeCzqH0W","azIWpksJby","8U2nUCNHmv",
-"7X3uy0Kyfs","GWqqXaDGtS","cShY28hJdt","D6rByWaWsv","piJSkuTacx","v8yFNRsQUq","ulk41pvgjS","dpe1vd85a9","KASQ8hi5X7","d85a98RCUA",
-"d85a92TRI7","jzUqRyluBx","9eoRcm4bxU","jSjS39eoRc","29QAzLewvM","JkzUnWDVWJ","lj07QcShY2","yvOMIFjHXR","WaWsv48cHL","euZA5lj07Q",
-"WreyPhSSvQ","0MR5XX6Pin","Zv7z0EdBKc","l83UdYjB9t","xReecpvgjS","I7p2a5ZaEz","iwzGktjQxs","dmoS7guMb8","0ao3lpFrrl","Pb1pa2TRI7",
-"Yf2EciB08l","LbRTHNAFuw","3otm6uLtKs","t98iWCNHmv","gf8rI9rlg9","MaJQsOUqFM","MaJQsblLA9","1LB1LaDGtS","BGaQYW7cTs","ThjNnWDVWJ",
-"580YDnFqik","cShY2CIShG","XflUq7hyVv","aez9y7Ow5C","fcJOyX6Pin","55rfB6AFT0","dpe1vgjUTu","2DREstuDyS","k85AeFnPFB","I7p2ak85Ae",
-"jzUqR0YAGH","QClRLWreyP","HfyNQhE1Ql","tlILtlweGy","ru4UGUmaEv","uZPqgpAhR1","uPX7GtvdkD","dQ586kZANm","POUYStl72W","mX2GEprNT6",
-"lH1ktpiJSk","lsQGoSjskQ","ReKEWB3qem","gtCA5uTacx","jfREuSjskQ","zqH0We6e4z","prNT6gIYvE","Mm8sihi5X7","VBjhzn1pmO","d85a9pv0i7",
-"tuDySLbRTH","yvOMIQYxC0","8FmFHpmeCd","HP433YjB9t","7fKYUhi5X7","IBe8k5IhmG","soy9tDz1R3","QWxoTlweGy","24ARFtaOXK","0BmCyOxWIH",
-"MmKGJDQimp","Chuy3ksJby","lj07QFGzgp","Pb1paCfgr3","XflUqJIqXi","2NslmIjTwP","RmDcrhUTw7","OHaBz8RCUA","5nmWvG1RhS","tl72Wlj07Q",
-"F6PT20ao3l","B3qemQClRL","cL0aE29QAz","7X3uytAOsr","8RCUAciuWz","RpBQmFcWrW","P6bcgru4UG","uTacxK4GS8","wiHrZhYBCK","brhlQSmGzv",
-"pWiOs64s8N","JJs5mvLsmS","MmKGJciuWz","HzZT8Twano","0PktIn8pJ9","v1Hln1LB1L","OUYuF8xEKz","3otm6lCMxy","5nmWvAOgEe","h1zcHfcJOy",
-"7X3uyv1Hln","0YAGHiB08l","RzaZAMm8si","M3zXLGXdoH","BbwgAReKEW","DG4sTuN6r3","24ARF8xEKz","9eoRcFVMxo","ix74rNOHsz","CdyBV7lUXZ",
-"hSSvQru4UG","Q6Lix5iGN5","xReecnlaBy","BpYhV29QAz","JRJQBcmXIX","4QMc9rz7Ut","xciqpL7cGc","RACujcShY2","U3yw5O3iyQ","2Nslmd7vjM",
-"yluBxMmKGJ","F6PT2GWqqX","zHF1qAmdQd","suY4xv1Hln","soy9tCK5W7","Yh1hF24ARF","RzaZAXyPZN","a00b5JIqXi","ZUnqthE1Ql","d85a9rhl0J",
-"5drc6QClRL","S2DfuMkgy8","jzUqR5IhmG","MojnPzHF1q","iB08lUlU3M","b29RJNAFuw","pv0i7yluBx","K20wKjSjS3","UmaEvVIlwP","UlU3M618Di",
-"L7cGcOUqFM","y94nwFFDui","uoStwL7cGc","h1zcHlweGy","QYxC0ZzJHW","d85a9FcWrW","euZA5IBe8k","VIlwPuQIcz","jfREuMK07Y","0KyfsIBe8k",
-"hSSvQCdyBV","TXQ0ZpT8wu","dmoS7Mkgy8","AOgEe9iGoT","8FmFH8cVD3","WmadAh1zcH","prNT6J2mQi","zmLYDogLgc","brhlQMaJQs","Vprf2JJs5m",
-"b29RJYOfrY","oQ87ruTacx","RkQkecShY2","tlILt5Namm","iqv4k8cVD3","BGaQYlm0pD","7fKYUzbIYY","lsQGo2TRI7","FwEJz2Yz7E","TCgPphUTw7",
-"Ul4a1WmadA","MmsIoe6e4z","xciqpjSjS3","In3NSSWfou","Vprf2VNCPd","gtCA5fFDrJ","ni2v19iGoT","5nmWvRzaZA","14FLRVjCZq","RxrsmNxx9V",
-"uLtKsv2eC3","XflUq14FLR","v1HlnI7p2a","CK5W7Q6hMC","Yh1hFXyPZN","gtCA5Pb1pa","HzZT8uvf7A","WMiS3Fhtgl","EOE1o0Kyfs","0MR5XYf2Ec",
-"K20wKFjHXR","0ao3luPX7G","5drc6Nxx9V","RmDcrAmdQd","zQt6QjzUqR","PYBf47ku1p","kB5nPm4bxU","gIYvEWaWsv","UmaEvy94nw","azIWpQ6Lix",
-"Yh1hFa00b5","BCxeCHfyNQ","m4bxUKr8ys","uQIczWmadA","oQ87rEOE1o","3weIFqQxHP","3otm6uTacx","16lHcGrDg7","gjUTuFhtgl","gtCA5hSSvQ",
-"Nxx9Vv1Hln","2hEEUPOUYS","Yh1hF6AFT0","mz8gxrz7Ut","RpBQmTCgPp","pmeCdd7vjM","tl72WRACuj","SWfouDG4sT","ulk41pv0i7","bZLvSdmoS7",
-"L7cGcpAhR1","KsjRKyluBx","48cHLqaofN","YOfrYv2eC3","tlILtlm0pD","uTacxNhXdu","RACuj5IhmG","zY1GYMGlTF","bZLvSKASQ8","AkKTkZuDtD",
-"he9IA5nmWv","NhXduTXQ0Z","W3VFHhE1Ql","SbRYyokgRi","XflUqPb1pa","WMiS3ni2v1","SbRYyCp3mZ","8U2nU6AFT0","EOE1oVerEA","JkzUnDQimp",
-"nnP8oVprf2","kZANmVIlwP","0YAGHIn3NS","2hEEUEdBKc","LewvMwDajX","lpF6W7fsYM","VNCPd9y4lw","45cIHi7WMQ","uoStwfaHir","UmaEvwDajX",
-"cmXIXM6qcG","uZPqgOz8yZ","8TxD7fqypy","prNT6FnPFB","lH1ktFcWrW","qUJMdhUTw7","gdQsSdpe1v","t59lRFnPFB","0MR5X2Nslm","Nxx9V5Namm",
-"tl72WrKDLJ","kB5nPyofH3","AgJHQdmoS7","JKWYRUmaEv","FwEJzuoStw","lXFOBKsjRK","dmoS7yToGW","uLtKs29QAz","2NslmZzJHW","MK07YHP433",
-"QChxs0BmCy","D6rByuAWyp","NAFuw7fKYU","uJScX29QAz","QYxC0cQOnv","MK07Yaez9y","7fKYUBbwgA","iKqhraL6AJ","ksJbygf8rI","Ta8f6zz4ZU",
-"pv0i7FnPFB","VNCPdThjNn","YOfrYhUTw7","RzaZAb29RJ","ECMvURzaZA","DG4sT5Namm","FVMxoaez9y","RxrsmRkQke","o8Uydix74r","9iGoTlXFOB",
-"IjTwPSs0Zu","blLA9Zv7z0","Mm8sixciqp","07n1cCfgr3","WreyPgtCA5","tAOsrRsQUq","lpF6WQnJ1S","Yf2Ec0Wr5y","nlaByRpBQm","DLhzMSmGzv",
-"uoStwfcwDa","ThjNnHRxd8","aez9yIBe8k","t59lRsuY4x","RpBQmh1zcH","4QMc9YjB9t","O3iyQBbwgA","XflUq29QAz","lCMxyazIWp","BpYhVlXFOB",
-"5IhmGtuDyS","bgJAzlkMUA","FFDuih1zcH","dQ586JKWYR","No0QbVLTy6","5Drn0IjTwP","n1pmO45cIH","fFDrJ8FmFH","zFgtBWreyP","s7MxkRzaZA",
-"K4GS8zqH0W","0PktI48cHL","4W0TlgjUTu","HP433ix74r","vLsmSI7p2a","9rlg90BmCy","nFqik4QMc9","AXpwE0Kyfs","7ku1pCqqaD","2ZHdkS2Dfu",
-"IRh48pWiOs","TXQ0ZK20wK","KsjRKFcWrW","zY1GYiqv4k","VerEAAOgEe","b29RJa00b5","Chuy3CIShG","gtCA529QAz","Nxx9VyluBx","m4bxUs4786",
-"CNHmvlm0pD","ydG8UQ6Lix","SjskQdjsrv","e6e4ztl72W","NcICAMmsIo","rKDLJx3LDe","aL6AJsqVrf","JJs5mRACuj","Dz1R3QssNC","fcJOyyofH3",
-"618Digf8rI","zHF1qZv7z0","0YAGHI7p2a","KASQ8M6qcG","FnPFBHlUbF","618DiHfyNQ","5ZaEzni2v1","pv0i7x3LDe","CNHmvPb1pa","FcWrWaDGtS",
-"VIlwPVIlwP","Gv3Fq8FmFH","lkMUA14FLR","bgJAz4dEz6","14FLR8TxD7","HRxd8uQIcz","FFDui0BmCy","tvdkDQ6Lix","6AFT0dQ586","aDGtSiwzGk",
-"uTacx1v5hH","Qworupv0i7","yluBxS77LH","fqypylweGy","6AFT0Cfgr3","2DREsCp3mZ","WMiS39XyT9","uupzkEdBKc","lweGyFnPFB","1j5L8Yw2oU",
-"y94nwbrhlQ","wiHrZVerEA","Gv3FqNhXdu","mz8gxiwzGk","BpYhVxXTI4","cQOnvWmadA","LewvMJKWYR","zbIYYwiHrZ","MojnPUmaEv","Dz1R364s8N",
-"lkMUAqaofN","Qworu5Namm","0Wr5yv1Hln","LewvMcQOnv","aDGtSCp3mZ","uTacxHzZT8","WreyPcQOnv","o8UydbrhlQ","yEfy9Pb1pa","Vprf2gjUTu",
-"CIShGCNHmv","dpe1v5VZjS","jSjS3Fhtgl","i3pydIRh48","hi5X75iGN5","DLhzMguMb8","qUJMdWPmlx","UlU3Mx3LDe","FnPFBzbIYY","FNYIMIBe8k",
-"0YAGH9eoRc","faHirpmeCd","TXQ0ZtvdkD","ru4UGcL0aE","nlaBydjsrv","ZJTXH7ku1p","DLhzMJ2mQi","SjskQVLTy6","lkMUAlpF6W","vLsmSZuDtD",
-"TCgPpWDVWJ","sqVrf6AFT0","1LB1LF6PT2","K4GS8oVQp6","uAWypuPX7G","7X3uyiKqhr","2TRI7gf8rI","8TxD724ARF","CdyBVkZANm","RACujlH1kt",
-"kZANmyluBx","NhXdui7WMQ","prNT6MezSW","Qworui3pyd","OxWIHFPfSE","24ARFCIShG","ZUnqtNOHsz","s7Mxkh1zcH","HzZT82DREs","45cIHAmdQd",
-"uJScXK20wK","5Mg9rdQ586","C2IrcNo0Qb","Vprf2aDGtS","VLTy6qUJMd","l83UdTwano","b29RJuvf7A","o8UydlweGy","mz8gxlpF6W","1v5hHm4bxU",
-"iqv4k2Nslm","yToGWAgJHQ","7fKYUAIYUu","K4GS80Wr5y","GXdoHzY1GY","dQ586Gv3Fq","prNT6hYBCK","29QAzO3iyQ","5Drn0FNYIM","QChxsEOE1o",
-"DLhzMUmaEv","s7MxkOHaBz","KZamHru4UG","4dEz6lXFOB","gtCA5HRxd8","fcwDaqaofN","uoStwwDajX","lj07QuN6r3","CNHmvAkKTk","yEfy9o8Uyd",
-"xXTI4FNYIM","CIShGkZANm","uLtKsuTacx","VerEAI7p2a","RkQke8TxD7","14FLR55rfB","cShY2DLhzM","HRxd8YOfrY","ECMvUfmIK1","uupzkRpBQm",
-"zY1GYOz8yZ","ulk41xReec","RmDcrNxx9V","jeskSni2v1","sx5GlhE1Ql","BbwgAd7vjM","1j5L87hyVv","atef2BpYhV","7lUXZTXQ0Z","VerEAt59lR",
-"zY1GY55rfB","RACuj9eoRc","uAWypydG8U","Q6LixHP433","Yf2EcIRh48","kB5nP0ao3l","FLsphS77LH","faHirXflUq","D6rByM3zXL","blLA9OxWIH",
-"dpe1vhSSvQ","MaJQsDQimp","IRh48zbIYY","RkQke9y4lw","4QMc95IhmG","SWfoudmoS7","DcpWBzHF1q","WaWsvqQxHP","KASQ88RCUA","VNCPdD6rBy",
-"fFDrJ48cHL","FjHXRsx5Gl","yToGWZ4I1v","wDajX24ARF","S2DfuJRJQB","ksJbyVjCZq","ru4UGhe9IA","FxX9qi3pyd","2NslmuTacx","5NammuTacx",
-"t98iWfmIK1","TwanoWreyP","7hyVvzmLYD","07n1clViBv","zqH0WuLtKs","ni2v1Waim6","AIYUuBCxeC","K20wKksJby","0ao3ln8pJ9","lkMUAprNT6",
-"Z4I1vi3pyd","Ta8f6Pb1pa","64s8NKASQ8","UmaEvRzaZA","Kr8ysuN6r3","fmIK1pFrrl","oGu6xM3zXL","lpF6WUmaEv","RACujlkMUA","jzUqRSjskQ",
-"POUYSHfyNQ","9iGoTxXTI4","rhl0J8U2nU","5Drn01LB1L","FLsphUvlv4","OHaBzh1zcH","jeskSS2Dfu","uQIcz3weIF","45cIHU3yw5","5Mg9rI7p2a",
-"5nmWvtvdkD","CK5W7d7vjM","8xEKzNOHsz","MmKGJBpYhV","SbRYybrhlQ","Ul4a1ydG8U","DLhzMiqv4k","5IhmGRBhp0","lViBvv1Hln","zmLYDs4786",
-"IBe8kfLNg8","5ZaEzM6qcG","zz4ZUC2Irc","7fKYUtjQxs","RACujKr8ys","7fsYMAIYUu","cL0aErKDLJ","hi5X7ReKEW","oQ87r2Yz7E","jS1aj0h1b1",
-"7fKYUuupzk","64s8N4dEz6","1LB1Ls93Ml","UmaEvru4UG","29QAzgIYvE","RkQkefcwDa","ZuDtDM6qcG","aez9ytjQxs","VerEAuN6r3","IBe8kdQ586",
-"Ul4a1XyPZN","OUYuFlXFOB","DQimpaFFss","tjQxs3weIF","XyPZNlH1kt","M6qcGoQ87r","FwEJzvkCHH","zz4ZURsQUq","Zv7z0Qworu","m4bxU8RCUA",
-"bgJAzAmdQd","MezSW55rfB","ciuWzru4UG","AOgEeECMvU","t59lR2TRI7","CdyBVI7p2a","DG4sTuoStw","hYBCKiB08l","CK5W7Fhtgl","ni2v15ZaEz",
-"ZzJHWFVMxo","Oz8yZblLA9","7Ow5Cv2eC3","RzaZAGv3Fq","lj07QYh1hF","OUYuFfmIK1","Kr8ys618Di","5Drn06AFT0","wiHrZs93Ml","7lUXZpiJSk",
-"OxWIH16lHc","rz7UtWreyP","ru4UGhSSvQ","lsQGoP6bcg","lViBv9rlg9","zqH0WM3zXL","zY1GYcShY2","RmDcrIKxdL","SbRYy8FmFH","XflUqDQimp",
-"1LB1LtlILt","UmaEvIjTwP","BpYhV0Wr5y","lpF6WyEfy9","GXdoHJKWYR","ZUnqtv8yFN","zFgtBXflUq","HRxd8cShY2","d85a9jSjS3","FFDui16lHc",
-"lweGy48cHL","EoToPdjsrv","tlILtJXljW","WmadAOHaBz","6AFT0Zv7z0","QClRLzmLYD","s93MlRxrsm","vOqCEuN6r3","P6bcgn1pmO","yvOMIIRh48",
-"pAhR1StlDJ","Q6Lix7X3uy","gdQsSHzZT8","2hEEUC2Irc","MaJQsguMb8","64s8NyEfy9","sqVrfrKDLJ","8RCUAlm0pD","tjQxss7Mxk","Mm8si0ao3l",
-"O3iyQ16lHc","d7vjMyofH3","5Drn08xEKz","djsrvru4UG","zz4ZUVLTy6","J2mQigIYvE","fLNg8WMiS3","pvgjSdQ586","M3zXLW7cTs","djsrva00b5",
-"fcwDa55rfB","Zv7z0S2Dfu","SbRYyL7cGc","QnJ1Suvf7A","s4786BCxeC","Chuy3euZA5","ni2v1FGzgp","AOgEe1LB1L","lj07Qsx5Gl","iKqhriqv4k",
-"pT8wunlaBy","XyPZNZv7z0","POUYSCp3mZ","ogLgcVBjhz","MezSW0YAGH","t98iWt98iW","i3pydlH1kt","AmdQd0MR5X","2TRI70BmCy","nFqik64s8N",
-"FcWrW9XyT9","D6rByNcICA","0BmCy9y4lw","y94nwBGaQY","s478664s8N","tuDySjzUqR","jiVBPYh1hF","xciqp9XyT9","lH1ktzmLYD","0Kyfs2TRI7",
-"8TxD7580YD","cmXIXFNYIM","JJs5m7lUXZ","9GXkX4QMc9","Kr8ysxciqp","uTacxqQxHP","pWiOsuPX7G","zHF1q2TRI7","dhSuHy94nw","BFkb8BFkb8",
-"soy9t8U2nU","m4bxUyluBx","Kr8ysTwano","SWfoutAOsr","ogLgcrhl0J","brhlQPb1pa","F6PT2y94nw","ZUnqtGXdoH","QbxXclkMUA","fcJOy5drc6",
-"6AFT0okgRi","AOgEepv0i7","tl72WCdyBV","NOHszhE1Ql","xXTI4JXljW","WDVWJOz8yZ","sx5GllH1kt","NOHszn1pmO","fqypyBbwgA","Nxx9V3otm6",
-"x3LDecmXIX","VIlwPAIYUu","VjCZq4W0Tl","m4bxURACuj","YjB9ttlILt","ni2v1TXQ0Z","lH1kt3otm6","RBhp0DcpWB","piJSkdhSuH","l83UdlkMUA",
-"wDajXlH1kt","nnP8oW7cTs","vLsmSqUJMd","QworuUl4a1","bZLvSfaHir","FcWrWMojnP","QClRLv2eC3","m4bxU2Nslm","uJScXDQimp","cmXIXh1zcH",
-"lweGymX2GE","aez9ybgJAz","uN6r3DcpWB","hi5X72DREs","0Wr5yo8Uyd","2ZHdkK20wK","xciqpjeskS","pv0i7tl72W","hi5X7HRxd8","prNT6yToGW",
-"guMb8Cfgr3","XyPZNy94nw","o8Uyd5ZaEz","uLtKs2DREs","uTacxsx5Gl","S2Dfu0MR5X","d7vjM48cHL","5IhmG29QAz","2NslmAgJHQ","RBhp08RCUA",
-"Nxx9VDz1R3","gf8rIcQOnv","kZANmZuDtD","VerEA8cVD3","sqVrfuJScX","gdQsSGrDg7","FjHXRYf2Ec","qaofN5VZjS","0BmCyZhwG1","azIWpbZLvS",
-"2Yz7ERkQke","Q6Lix0YAGH","oVQp6NcICA","mX2GEVjCZq","brhlQqQxHP","s93MlpiJSk","XflUqh1zcH","5NammTCgPp","HRxd8Zv7z0","2NslmHP433",
-"HzZT8guMb8","7lUXZC2Irc","Ul4a1pFrrl","VNCPdIn3NS","ydG8UVBjhz","cShY2dhSuH","RBhp0CIShG","B3qemQworu","W7cTsD6rBy","WDVWJI7p2a",
-"he9IAVNCPd","nlaBykB5nP","qUJMdjzUqR","pT8wuJ2mQi","ulk41zmLYD","dmoS7QbxXc","M6qcG29QAz","HzZT8i3pyd","LewvMK4GS8","AgJHQogLgc",
-"Yh1hFzbIYY","8FmFHxXTI4","5VZjScShY2","RsQUqgjUTu","blLA98RCUA","0Wr5yazIWp","vkCHHW3VFH","0h1b1VerEA","Vprf2qaofN","RsQUqpT8wu",
-"S2Dfumz8gx","oGu6xblLA9","FNYIMtl72W","jS1ajsqVrf","qQxHPfcJOy","LDk6f1LB1L","FPfSEYw2oU","FLsphLewvM","uvf7As7Mxk","pvgjSPb1pa",
-"nlaByuTacx","Yf2Ec55rfB","RzaZA0ao3l","OHaBzlm0pD","OUYuFXyPZN","lViBvgjUTu","POUYSGv3Fq","Q6LixVjCZq","Fhtgls4786","K20wKatef2",
-"AIYUuBFkb8","45cIH4dEz6","tvdkDdjsrv","IRh48DQimp","OUYuFuvf7A","Oz8yZfcJOy","vkCHHbZLvS","WDVWJoQ87r","Cp3mZQChxs","kB5nP2ZHdk",
-"Nxx9VlCMxy","sx5Glx3LDe","t98iWThjNn","suY4xI7p2a","DLhzMRBhp0","zmLYD0PktI","uvf7AtlILt","S77LHciuWz","4W0TlnnP8o","uAWyp7fKYU",
-"64s8NeuZA5","7Ow5CaFFss","s7MxkSWfou","ogLgcMK07Y","yvOMIJKWYR","pvgjSaL6AJ","O3iyQCNHmv","l83UdfmIK1","uAWyp618Di","GXdoHm4bxU",
-"DLhzMQChxs","dhSuHVLTy6","Chuy3SjskQ","3otm60BmCy","wDajXaDGtS","zqH0WTwano","ECMvUrKDLJ","618Dimz8gx","qaofNx3LDe","RpBQmgdQsS",
-"VIlwP8TxD7","48cHLjSjS3","K4GS8sx5Gl","xXTI4Yh1hF","AIYUumX2GE","VNCPdRxrsm","dpe1vC2Irc","5nmWvU3yw5","oGu6xDQimp","9y4lwx3LDe",
-"n1pmOni2v1","WMiS3ksJby","D6rByyvOMI","2TRI7Ul4a1","JKWYRIRh48","UlU3M9iGoT","S77LH618Di","vkCHHZhwG1","zqH0WChuy3","S2DfulsQGo",
-"JIqXiDG4sT","FGzgpzqH0W","cShY2JXljW","WaWsvGv3Fq","jfREujS1aj","k85Ae8xEKz","uPX7GAIYUu","LbRTHHlUbF","jiVBPVerEA","fqypyKr8ys",
-"gf8rIFwEJz","8xEKzpiJSk","zqH0W2Nslm","VBjhzFhtgl","VerEAMm8si","ECMvU3otm6","FFDui9rlg9","BCxeCDcpWB","uvf7ADcpWB","RzaZAjzUqR",
-"lH1ktix74r","SbRYyi7WMQ","MojnP5drc6","lm0pDksJby","zY1GYAOgEe","lweGy6q6L9","fcJOyYjB9t","XflUqoQ87r","HzZT85Mg9r","Yw2oUoQ87r",
-"v2eC3KsjRK","B3qemDQimp","MezSW0MR5X","i7WMQaez9y","2Nslm5Namm","ulk41RACuj","1v5hHuPX7G","uoStwOxWIH","uTacxQWxoT","h1zcH07n1c",
-"tl72WlpF6W","SmGzvChuy3","yofH3MK07Y","vkCHHhYBCK","CdyBVQworu","StlDJGXdoH","BbwgAh1zcH","L7cGc5iGN5","jtn0XaL6AJ","JIqXiGv3Fq",
-"FnPFB8cVD3","yEfy9RmDcr","ru4UGvkCHH","vOqCE5iGN5","RxrsmtjQxs","OUYuFGrDg7","Zv7z0sx5Gl","CK5W79XyT9","RpBQmzmLYD","iwzGkcL0aE",
-"8hJdtaFFss","fLNg8atef2","fLNg85drc6","1j5L8NcICA","D6rByMGlTF","BGaQYVjCZq","tuDySuJScX","5Drn0guMb8","BCxeCpmeCd","HzZT8ru4UG",
-"QChxsYjB9t","ThjNnBFkb8","tl72W1j5L8","gjUTuCdyBV","lj07QOHaBz","QClRLfaHir","pWiOsSs0Zu","nnP8oRkQke","tuDyS1LB1L","pFrrluvf7A",
-"FwEJz2ZHdk","pvgjSRACuj","rKDLJCNHmv","lj07QlCMxy","uN6r3aDGtS","FLsph3otm6","K20wKAOgEe","gIYvEwDajX","64s8NQnJ1S","9iGoTWaWsv",
-"MGlTFsx5Gl","i7WMQlj07Q","W3VFH29QAz","aL6AJ9rlg9","jiVBPYf2Ec","5Mg9rO3iyQ","h1zcHxciqp","Q6hMCfFDrJ","RsQUqm4bxU","fcwDahUTw7",
-"FxX9qdpe1v","nnP8oqUJMd","AmdQddmoS7","vOqCEfLNg8","QworuIn3NS","v1Hlnn8pJ9","pFrrlWmadA","W3VFH24ARF","pAhR18TxD7","n1pmO580YD",
-"FGzgpIBe8k","DG4sT0ao3l","TXQ0ZjfREu","ksJbyhi5X7","W3VFHVBjhz","RpBQmwiHrZ","cmXIX55rfB","I7p2adQ586","zFgtBZuDtD","blLA9YjB9t",
-"FjHXRb29RJ","zz4ZUgtCA5","pWiOsuupzk","Vprf255rfB","QClRLaFFss","Z4I1vgIYvE","rhl0JHlUbF","580YDyluBx","bZLvS2hEEU","7hyVvGSQwj",
-"ksJbyyvOMI","iqv4kFhtgl","ZzJHWDG4sT","tjQxsgtCA5","he9IAatef2","uZPqgfcwDa","cmXIXs7Mxk","7lUXZ5Namm","hi5X73weIF","Yf2Ec29QAz",
-"45cIHFLsph","9rlg9yluBx","yEfy9aez9y","IjTwPuQIcz","djsrvTwano","QssNCOxWIH","Chuy35nmWv","piJSk0MR5X","HlUbFK4GS8","ru4UGe6e4z",
-"tjQxsatef2","9iGoTS2Dfu","jSjS32DREs","ZJTXH0h1b1","azIWpk85Ae","zQt6QStlDJ","55rfBSs0Zu","e6e4zZJTXH","ThjNnS77LH","pv0i7Yf2Ec",
-"pT8wuYOfrY","RsQUqprNT6","QworuThjNn","mX2GEhYBCK","9XyT9pmeCd","h1zcHnnP8o","I7p2am4bxU","QWxoTjiVBP","taOXK8TxD7","Cp3mZcShY2",
-"Qworu1v5hH","W3VFHv8yFN","HlUbFAgJHQ","pmeCdJRJQB","zQt6QRsQUq","4dEz6ZJTXH","djsrvQworu","GrDg7JRJQB","cL0aEZUnqt","7lUXZ9eoRc",
-"FVMxo55rfB","yvOMIRACuj","ciuWzQnJ1S","ZUnqtOxWIH","jfREuQWxoT","o8UydhYBCK","uTacxUl4a1","RpBQma00b5","iwzGk3weIF","B3qemEoToP",
-"b29RJTwano","7ku1pBGaQY","RkQkehe9IA","55rfB580YD","07n1cMGlTF","gdQsSx3LDe","29QAzmz8gx","OxWIHReKEW","M6qcGqQxHP","Mm8siwDajX",
-"GWqqXkB5nP","Y1mC0m4bxU","taOXKzHF1q","M3zXLgtCA5","uupzke6e4z","45cIHWaWsv","5Mg9rSjskQ","XflUqt98iW","DG4sT48cHL","xReecQ6Lix",
-"OHaBzpvgjS","l83UdAXpwE","v1HlnHRxd8","MmsIoCqqaD","Rxrsm4QMc9","0ao3lNcICA","zFgtBcShY2","Twano3otm6","618DiqQxHP","Oz8yZokgRi",
-"suY4x9eoRc","No0QbFwEJz","aFFssCIShG","gdQsSd85a9","Mkgy8yvOMI","OHaBzYjB9t","5ZaEzpAhR1","QYxC016lHc","cQOnvatef2","SmGzvAkKTk",
-"48cHLtaOXK","Yh1hFFNYIM","jzUqR2DREs","SmGzv6AFT0","zbIYY8cVD3","HlUbFnFqik","jSjS3W7cTs","QbxXcQbxXc","wiHrZoVQp6","PYBf4lj07Q",
-"lXFOBaFFss","FPfSEOUYuF","0Wr5yrKDLJ","2TRI7P6bcg","14FLRnlaBy","DG4sTBFkb8","FGzgpfqypy","7Ow5CFxX9q","y94nw7lUXZ","dQ586B3qem",
-"CdyBV14FLR","6AFT0TXQ0Z","iqv4k1LB1L","VBjhzBGaQY","aDGtSLewvM","uPX7GB3qem","NcICABFkb8","SmGzvvkCHH","vkCHHe6e4z","3otm6pT8wu",
-"MmKGJWmadA","prNT6No0Qb","1LB1LuoStw","SbRYy6AFT0","cL0aEd7vjM","pFrrlWaim6","FxX9qNxx9V","CK5W7Z4I1v","FFDuikB5nP","atef2AIYUu",
-"DcpWB7Ow5C","FLsphWDVWJ","1LB1LY1mC0","RsQUqTa8f6","CNHmvlH1kt","pv0i7Cp3mZ","fmIK107n1c","v1Hln2Nslm","Qworu9XyT9","BCxeC0MR5X",
-"azIWppvgjS","rhl0J7Ow5C","Chuy32Nslm","o8UydUl4a1","uTacx1j5L8","KsjRKa00b5","0Kyfs07n1c","djsrvcShY2","UmaEvgjUTu","fmIK1FFDui",
-"o8UydjzUqR","RpBQm16lHc","AXpwEbZLvS","5VZjSpAhR1","jeskSIjTwP","9eoRcFnPFB","CdyBVtAOsr","aL6AJM6qcG","FLsph7hyVv","fqypyuvf7A",
-"dpe1v07n1c","hE1Ql5IhmG","aez9yUlU3M","C2IrccQOnv","b29RJjeskS","piJSkZuDtD","DcpWBjtn0X","guMb8soy9t","FLsph8hJdt","zFgtBlViBv",
-"lm0pDWDVWJ","qaofNt98iW","K20wK8hJdt","ulk41JXljW","ix74r8RCUA","In3NSCfgr3","5drc6iwzGk","d7vjM5Mg9r","QChxsWDVWJ","YjB9t8TxD7",
-"ogLgc5Drn0","jiVBPwDajX","QYxC0jSjS3","L7cGcAIYUu","9rlg9k85Ae","AXpwEMaJQs","4dEz6nnP8o","s4786WaWsv","lCMxyuvf7A","lpF6WyvOMI",
-"ciuWzl83Ud","GXdoHECMvU","i7WMQQClRL","7fsYMPYBf4","JIqXi0h1b1","CNHmvNxx9V","Mm8sicmXIX","RBhp0oVQp6","t98iWZ4I1v","LewvMbgJAz",
-"fcJOybgJAz","iwzGkBFkb8","8RCUAUmaEv","uN6r3jeskS","zFgtB9y4lw","nnP8oSs0Zu","mz8gxFhtgl","0Kyfs5ZaEz","StlDJiwzGk","Nxx9VSbRYy",
-"k85AeVLTy6","t98iWI7p2a","2ZHdkFwEJz","fmIK1UlU3M","O3iyQbZLvS","EdBKcKsjRK","okgRiRmDcr","WPmlxF6PT2","NOHszvLsmS","lweGyxciqp",
-"Cp3mZC2Irc","SWfoubZLvS","ECMvUpv0i7","lpF6WM3zXL","4W0TlWaim6","SmGzvUlU3M","0PktIhi5X7","SmGzvaFFss","lkMUAlsQGo","FPfSEG1RhS",
-"x3LDejzUqR","iB08lFcWrW","MaJQsHlUbF","jfREuWreyP","7fKYUL7cGc","8FmFH1LB1L","Uvlv44dEz6","618DiThjNn","d7vjMLewvM","0YAGHokgRi",
-"aDGtSNxx9V","4QMc9Qworu","AIYUuQ6Lix","FVMxoQ6Lix","Zv7z0s4786","7Ow5CnlaBy","L7cGclj07Q","pvgjS9rlg9","7X3uyQWxoT","pT8wuGrDg7",
-"VerEACNHmv","rKDLJblLA9","xciqpQClRL","CxVEf2Yz7E","y94nwFLsph","6AFT0HfyNQ","t59lRazIWp","okgRivLsmS","ciuWztAOsr","2ZHdkX6Pin",
-"2TRI7Cfgr3","M3zXLhSSvQ","ZUnqtQ6hMC","9rlg9vOqCE","hYBCKOz8yZ","LbRTHulk41","Uvlv4k85Ae","CqqaDGSQwj","fcJOy16lHc","9y4lwAOgEe",
-"AOgEe0BmCy","RACujFxX9q","KsjRKFPfSE","tlILtFGzgp","UlU3MjSjS3","Z4I1vxReec","d7vjMNhXdu","KsjRKrz7Ut","v8yFNzHF1q","fFDrJtAOsr",
-"1j5L8GWqqX","Qworu4dEz6","nFqikJKWYR","MaJQs4W0Tl","lweGyDQimp","uZPqg3otm6","iqv4kjeskS","64s8N0MR5X","RACujQChxs","2DREsGrDg7",
-"BpYhVAgJHQ","M6qcGCqqaD","bgJAz618Di","JJs5mfFDrJ","Dz1R3FwEJz","tjQxsOUYuF","580YDgdQsS","zqH0W618Di","SmGzvFcWrW","MmsIogdQsS",
-"d7vjMChuy3","M6qcGpAhR1","JJs5mdpe1v","bZLvSpvgjS","VNCPdMm8si","lweGyulk41","2Yz7EbgJAz","W7cTs5Namm","cL0aEOxWIH","t59lRzmLYD",
-"CNHmvMmsIo","d85a9RmDcr","VBjhzI7p2a","iwzGkMmsIo","xXTI4BCxeC","HfyNQuPX7G","lH1ktGv3Fq","BpYhVNhXdu","bZLvSY1mC0","FNYIMtaOXK",
-"jfREurhl0J","In3NSBpYhV","KASQ8taOXK","oVQp6OHaBz","RBhp0uJScX","tvdkDxReec","7fKYUOUqFM","JRJQBsoy9t","x3LDe0YAGH","GrDg7s4786",
-"lXFOBzbIYY","i3pydlCMxy","xReecJJs5m","7fsYMBGaQY","CNHmvlViBv","pWiOsMkgy8","O3iyQPOUYS","FhtgloVQp6","618DiVBjhz","prNT6W7cTs",
-"LbRTHgIYvE","IBe8k48cHL","t59lRBCxeC","KsjRKFnPFB","mz8gxDQimp","QbxXc0ao3l","aFFssMaJQs","M3zXLfcJOy","FcWrWWreyP","Q6Lixy94nw",
-"nlaByGv3Fq","fqypyUvlv4","SWfouCfgr3","7fsYMgjUTu","blLA9tuDyS","9eoRcZzJHW","W3VFHDz1R3","2hEEU8FmFH","IBe8kfcwDa","0BmCy1LB1L",
-"ulk41AmdQd","VerEAVBjhz","9rlg9atef2","uupzkuupzk","ThjNnWPmlx","ksJbyzHF1q","XflUqQClRL","Nxx9VfcwDa","7Ow5C0Wr5y","CNHmv5IhmG",
-"8RCUAbrhlQ","uLtKspmeCd","JJs5mIjTwP","GXdoHZ4I1v","zmLYDix74r","B3qemHlUbF","G1RhS5Drn0","xciqpPYBf4","9eoRcQssNC","yToGWU3yw5",
-"pWiOsnlaBy","ZhwG1Qworu","7Ow5CciuWz","VerEAFGzgp","7fKYUni2v1","B3qemFcWrW","DcpWBHP433","nnP8oYw2oU","SjskQix74r","QYxC00h1b1",
-"kB5nPyvOMI","zHF1qDQimp","zQt6QCNHmv","gIYvEoQ87r","ksJbyHfyNQ","9y4lwksJby","5Drn0S2Dfu","8RCUATwano","L7cGctuDyS","fFDrJix74r",
-"SjskQ4QMc9","Cfgr3OUYuF","CK5W7FcWrW","a00b5OxWIH","7hyVvVNCPd","pAhR164s8N","Ta8f6RACuj","RkQkeguMb8","5IhmGnnP8o","jzUqRlH1kt",
-"okgRiP6bcg","0BmCyfqypy","gf8rISWfou","sx5Glrz7Ut","v8yFNRACuj","SjskQJKWYR","yluBxRBhp0","M3zXLF6PT2","RsQUqydG8U","55rfBoGu6x",
-"lViBvMkgy8","BpYhVlH1kt","QworusqVrf","zY1GYFLsph","8cVD39XyT9","NOHsz8xEKz","S2DfuzY1GY","FLsphSbRYy","0YAGHaL6AJ","rhl0J2TRI7",
-"3weIFO3iyQ","0Wr5yVNCPd","cQOnv29QAz","I7p2aCNHmv","tlILt9y4lw","CxVEfprNT6","Cfgr37hyVv","soy9t7lUXZ","guMb8FwEJz","atef2Yf2Ec",
-"8FmFH2hEEU","fqypyuTacx","ECMvUvLsmS","y94nwVIlwP","tAOsrJJs5m","mX2GESs0Zu","a00b58hJdt","14FLRCxVEf","YjB9tCxVEf","rKDLJLewvM",
-"J2mQiRmDcr","ulk41yvOMI","y94nwsx5Gl","fFDrJQWxoT","OUqFMpiJSk","k85Ae7Ow5C","PYBf4SmGzv","WPmlxlXFOB","fqypy8hJdt","lj07QCdyBV",
-"he9IAprNT6","y94nwix74r","dpe1vtlILt","8TxD7J2mQi","v8yFNdmoS7","n1pmOEoToP","lpF6Wdpe1v","0YAGH7hyVv","8FmFHAmdQd","brhlQ5ZaEz",
-"nFqikUmaEv","QYxC0fcJOy","tjQxsfcwDa","FxX9q580YD","ix74rYw2oU","K20wKTXQ0Z","aDGtSrz7Ut","RpBQm580YD","CdyBVDLhzM","jtn0Xt98iW",
-"J2mQiCxVEf","ksJbyoQ87r","zz4ZU64s8N","i3pydChuy3","yluBxk85Ae","LDk6fBGaQY","9XyT9FVMxo","6q6L9JkzUn","6AFT0FNYIM","FFDuiFnPFB",
-"RkQkeS77LH","2Yz7EfFDrJ","G1RhSi3pyd","cShY2AIYUu","aez9yzz4ZU","lm0pDyEfy9","0Wr5yKZamH","2hEEUIBe8k","5Drn07Ow5C","yToGWSmGzv",
-"fFDrJ9rlg9","QbxXcaL6AJ","d7vjM5nmWv","StlDJPOUYS","iwzGkChuy3","mX2GEvOqCE","1j5L8FPfSE","IRh48XyPZN","G1RhS5IhmG","euZA5WmadA",
-"24ARFmz8gx","yofH3QbxXc","DLhzM4W0Tl","6AFT0RBhp0","DLhzMxXTI4","M3zXLo8Uyd","o8UyddhSuH","NhXdulpF6W","dhSuHuN6r3","BbwgAxReec",
-"pT8wulkMUA","StlDJdQ586","lsQGoJRJQB","l83Ud0YAGH","aL6AJD6rBy","x3LDeMmKGJ","8FmFHiwzGk","VjCZq0Kyfs","WreyPi3pyd","16lHcIRh48",
-"YjB9tjtn0X","8cVD3J2mQi","5drc6Yh1hF","vLsmSt98iW","h1zcHb29RJ","xReecCqqaD","VerEAqaofN","sx5GlKsjRK","NOHszeuZA5","lCMxyStlDJ",
-"5IhmGzbIYY","hYBCK6q6L9","aL6AJi7WMQ","soy9tyluBx","t98iW9eoRc","jeskSyEfy9","K4GS8nnP8o","soy9tNAFuw","5drc6KASQ8","MaJQsReKEW",
-"e6e4ztAOsr","CdyBVlCMxy","QbxXcSmGzv","MezSWpFrrl","lH1ktAXpwE","nnP8oEdBKc","6q6L9HzZT8","BpYhVFPfSE","uLtKszmLYD","I7p2azY1GY",
-"tl72WMmKGJ","BpYhVAOgEe","zY1GYThjNn","8U2nUS77LH","IKxdLAmdQd","BGaQY618Di","0BmCyIn3NS","pWiOswiHrZ","iB08l24ARF","5IhmGxReec",
-"HP433tl72W","OxWIHfcwDa","Ul4a1No0Qb","FjHXRD6rBy","m4bxUSmGzv","ReKEWPOUYS","euZA5tl72W","n1pmOTa8f6","jeskS5VZjS","zY1GYF6PT2",
-"B3qemi3pyd","VerEAQnJ1S","NOHszokgRi","9eoRcK4GS8","jzUqROxWIH","cShY29eoRc","aL6AJYw2oU","8U2nU2ZHdk","xciqpvLsmS","LDk6fCIShG",
-"guMb8M3zXL","4QMc9QYxC0","NcICAi3pyd","55rfBgjUTu","gdQsSiwzGk","y94nwh1zcH","AkKTkdhSuH","fcwDaMaJQs","m4bxUiwzGk","Chuy3PYBf4",
-"FwEJz29QAz","Twanohe9IA","pmeCdJ2mQi","0MR5XCfgr3","55rfBt59lR","fmIK18RCUA","aDGtS3otm6","ciuWzuN6r3","GSQwjAXpwE","gtCA5pv0i7",
-"Oz8yZrhl0J","YjB9tEoToP","zY1GYix74r","dhSuHJRJQB","HzZT8Chuy3","FNYIM7fKYU","7Ow5CxXTI4","M3zXLRpBQm","fcwDazmLYD","S77LHTXQ0Z",
-"nFqikpiJSk","45cIHW3VFH","IjTwPm4bxU","ZzJHWZUnqt","QYxC0KZamH","lm0pDNOHsz","EoToPIjTwP","jeskSTCgPp","9GXkXQChxs","0h1b10h1b1",
-"5iGN5gIYvE","vLsmS7X3uy","yofH38RCUA","tjQxsRBhp0","618DiaFFss","JJs5muupzk","2TRI7EdBKc","Ta8f6M3zXL","gIYvE3weIF","SmGzvbgJAz",
-"gjUTum4bxU","C2IrczFgtB","aL6AJk85Ae","m4bxU6AFT0","2ZHdksqVrf","8RCUAMGlTF","6q6L9AkKTk","ogLgcDLhzM","yvOMIVBjhz","aL6AJs4786",
-"3otm6yToGW","uoStw5Drn0","OxWIHAgJHQ","BpYhVZuDtD","In3NSPYBf4","NhXdu5Mg9r","Pb1pauN6r3","SbRYyWMiS3","FcWrWtvdkD","lsQGoCqqaD",
-"JIqXiFnPFB","uupzk2Nslm","prNT6lCMxy","b29RJQ6Lix","8RCUAHzZT8","2NslmG1RhS","rz7UtFcWrW","GSQwjAmdQd","lXFOBt59lR","NAFuwFcWrW",
-"9rlg9G1RhS","Yw2oUBCxeC","9rlg9zY1GY","uupzkydG8U","b29RJ0YAGH","FLsphv8yFN","IRh48VerEA","rz7Utix74r","7fKYUQYxC0","YjB9tjeskS",
-"lj07Qh1zcH","FGzgpjeskS","WmadAD6rBy","Ta8f6zFgtB","9rlg9jfREu","YjB9t7fKYU","CNHmvuoStw","euZA58TxD7","ThjNnd7vjM","VerEAQWxoT",
-"faHirokgRi","hi5X7lCMxy","48cHLtlILt","pFrrldhSuH","RmDcrlm0pD","lH1kthe9IA","HRxd8CNHmv","8U2nUHzZT8","hYBCK0Kyfs","5Namm7lUXZ",
-"MaJQsQ6Lix","PYBf4RzaZA","ThjNnzQt6Q","brhlQUl4a1","9XyT9lm0pD","UlU3MaDGtS","8FmFH3otm6","XyPZNVprf2","WPmlxuupzk","atef2FPfSE",
-"U3yw5uvf7A","oGu6xS77LH","cShY2lm0pD","Ta8f6fLNg8","FLsphG1RhS","GSQwjmX2GE","vOqCEK4GS8","rhl0JogLgc","K4GS8OUYuF","iqv4kQworu",
-"EoToP24ARF","jiVBPMojnP","mz8gxtjQxs","euZA5v1Hln","Cp3mZBCxeC","6AFT0S77LH","uQIczuQIcz","nFqikuLtKs","9y4lwJXljW","taOXKEOE1o",
-"7fsYMCIShG","MojnPXflUq","h1zcHulk41","Chuy3jS1aj","hSSvQJkzUn","pv0i7ReKEW","64s8NGSQwj","W3VFH7Ow5C","yofH3Kr8ys","Zv7z0FjHXR",
-"NOHszFVMxo","HP433lpF6W","uvf7Adpe1v","CK5W7tlILt","4dEz6uLtKs","zz4ZUvLsmS","d7vjM14FLR","prNT6uZPqg","SjskQmz8gx","M3zXLuJScX",
-"580YDEoToP","tuDySzmLYD","qUJMdsoy9t","JKWYRprNT6","DcpWBPOUYS","Q6hMCFnPFB","2Yz7EVjCZq","fLNg8HRxd8","t98iWaDGtS","QssNCJIqXi",
-"8hJdtzmLYD","0YAGHyluBx","WmadAQYxC0","CK5W7BpYhV","8U2nUF6PT2","VLTy6h1zcH","v1HlnUl4a1","aDGtSlViBv","16lHcuAWyp","zqH0W2hEEU",
-"IBe8kUlU3M","X6PinCdyBV","pT8wu5Mg9r","prNT6zmLYD","vOqCEmz8gx","yluBx618Di","9y4lwlweGy","NAFuwhe9IA","s7MxkFFDui","FxX9qlCMxy",
-"5VZjSIjTwP","guMb8uvf7A","Yh1hFChuy3","2DREs3otm6","LDk6fv2eC3","580YDhi5X7","IjTwP9rlg9","prNT60Kyfs","5Drn0k85Ae","3otm6Y1mC0",
-"QClRLFjHXR","0Wr5yzqH0W","vOqCESs0Zu","BGaQYuvf7A","pvgjS0YAGH","Mkgy8Yh1hF","SmGzvwDajX","lm0pDtlILt","D6rByPOUYS","VjCZqSs0Zu",
-"lm0pD0MR5X","Z4I1v5iGN5","sx5GlOxWIH","55rfBfLNg8","IRh48zHF1q","t59lRdQ586","PYBf4Gv3Fq","DQimpciuWz","LbRTHxciqp","DLhzMFLsph",
-"FGzgp8RCUA","fcJOyCdyBV","GSQwjZv7z0","Cp3mZ45cIH","s93MlW3VFH","ThjNn6AFT0","WmadApv0i7","S2DfuRpBQm","uJScXCfgr3","S77LHuPX7G",
-"55rfB9GXkX","1j5L8VNCPd","zbIYYdhSuH","jtn0XQbxXc","LbRTHCdyBV","uTacxKr8ys","0PktI7X3uy","cQOnvhE1Ql","AmdQdL7cGc","AkKTkh1zcH",
-"zbIYY9XyT9","BGaQY0Wr5y","d85a9DcpWB","wDajXlViBv","DcpWBnnP8o","yvOMI580YD","VNCPdFFDui","W7cTsvOqCE","DcpWBEoToP","0MR5XD6rBy",
-"GXdoHO3iyQ","ix74rNhXdu","n1pmO5nmWv","W7cTsRsQUq","nlaByP6bcg","VIlwPKsjRK","jeskSZUnqt","0ao3loQ87r","S77LHFxX9q","BpYhVFFDui",
-"LDk6fuZPqg","TwanoXflUq","G1RhSQbxXc","ECMvU7fsYM","5VZjSyEfy9","rhl0Jhi5X7","s93MlQnJ1S","ulk41i7WMQ","StlDJU3yw5","jtn0XPOUYS",
-"Yw2oUFjHXR","2ZHdk0h1b1","d7vjMd85a9","iB08luoStw","I7p2al83Ud","IjTwPv2eC3","4W0Tllj07Q","vLsmStvdkD","ReKEW9XyT9","NOHszCxVEf",
-"Waim6he9IA","StlDJlpF6W","gIYvEi3pyd","Yw2oU5Namm","GSQwjuN6r3","IBe8k8FmFH","lXFOBiqv4k","BCxeCAXpwE","VNCPd64s8N","VNCPd5drc6",
-"580YDfmIK1","IRh48ni2v1","9y4lw5Namm","yluBxMkgy8","Kr8ysB3qem","NcICAulk41","2TRI7Yf2Ec","5Mg9rmz8gx","5iGN50ao3l","45cIHLbRTH",
-"MezSWXyPZN","NOHszfFDrJ","8FmFHWreyP","POUYSeuZA5","No0QboGu6x","suY4xhi5X7","SjskQuTacx","prNT6OUYuF","RkQkelXFOB","jS1ajuPX7G",
-"5IhmGoVQp6","U3yw5Waim6","ciuWzIRh48","JRJQB7Ow5C","lm0pD4QMc9","FPfSEUl4a1","7fsYMxReec","ZzJHWQworu","StlDJ5IhmG","uLtKsNOHsz",
-"7fsYM0BmCy","0MR5XFwEJz","MojnPCdyBV","fqypyWDVWJ","FjHXRyvOMI","blLA9VNCPd","tvdkDMkgy8","Z4I1vuvf7A","e6e4zGSQwj","jeskSECMvU",
-"EoToPuoStw","IRh485IhmG","GSQwjtaOXK","1j5L85IhmG","0BmCyRBhp0","CNHmvazIWp","soy9t7ku1p","LbRTHyofH3","sx5Gljtn0X","brhlQuupzk",
-"hE1QlL7cGc","VBjhzpmeCd","No0Qbi3pyd","h1zcHJXljW","AgJHQB3qem","ciuWzlpF6W","jiVBPUl4a1","azIWpNhXdu","HRxd8Dz1R3","XflUqVNCPd",
-"1LB1LECMvU","Yf2EcFwEJz","8TxD7NAFuw","ZhwG1QYxC0","7ku1p2Nslm","aez9ym4bxU","uTacxW7cTs","ulk41PYBf4","8hJdt45cIH","K4GS8m4bxU",
-"BpYhV580YD","MK07YMaJQs","uQIczQ6hMC","Waim6aDGtS","4W0Tl2DREs","14FLRKr8ys","pv0i7faHir","nnP8oyEfy9","5nmWv8cVD3","HRxd8uupzk",
-"fLNg8t98iW","uQIczFNYIM","t59lR2ZHdk","lCMxytjQxs","uupzk618Di","pT8wucmXIX","VLTy6J2mQi","AgJHQGXdoH","FnPFBlsQGo","BCxeCaez9y",
-"Ta8f65Drn0","Ss0ZuRkQke","cmXIXBpYhV","OUqFMiKqhr","ZhwG1blLA9","QnJ1SbZLvS","aDGtSQYxC0","AIYUutAOsr","GSQwjYf2Ec","AmdQdzz4ZU",
-"zmLYDfcJOy","gdQsSlweGy","DG4sTdQ586","nlaByy94nw","fcJOylsQGo","Mkgy8uN6r3","OUqFMSmGzv","blLA9FcWrW","t98iWazIWp","WmadAKsjRK",
-"4QMc9HP433","gIYvEUl4a1","7hyVvUlU3M","wiHrZuupzk","tlILtQworu","HfyNQmX2GE","MmKGJpv0i7","0MR5XWDVWJ","IKxdLFVMxo","oQ87rgdQsS",
-"QnJ1SW3VFH","pWiOsWreyP","5iGN5Fhtgl","lkMUAaez9y","KsjRKyofH3","OHaBzCNHmv","ReKEWaFFss","oGu6xFwEJz","StlDJ0h1b1","tAOsr9GXkX",
-"7ku1pi3pyd","CdyBV7fsYM","2NslmMm8si","nnP8olkMUA","Yw2oU0h1b1","0MR5X7fsYM","djsrvpiJSk","UmaEvuQIcz","oGu6xVprf2","8xEKzulk41",
-"gdQsS8U2nU","a00b5WPmlx","16lHc8FmFH","bgJAzdhSuH","xReecjS1aj","lXFOBYw2oU","Cfgr3KZamH","Kr8yscL0aE","a00b5WmadA","hUTw7KsjRK",
-"CqqaDYjB9t","3otm6SbRYy","55rfBGWqqX","UlU3Ms7Mxk","NAFuwlm0pD","8cVD3DQimp","fqypyoVQp6","MojnP580YD","MmKGJlkMUA","s4786suY4x",
-"07n1c7lUXZ","zHF1qJKWYR","BCxeCeuZA5","9iGoTOxWIH","VBjhzNcICA","S77LHRACuj","uQIczsoy9t","RmDcr7fsYM","K4GS8AOgEe","lkMUAQworu",
-"okgRiF6PT2","s4786t59lR","djsrv8cVD3","QnJ1Si7WMQ","4QMc9IBe8k","Uvlv4uAWyp","uupzkuN6r3","ksJbyG1RhS","8FmFHYw2oU","pvgjShYBCK",
-"TCgPphSSvQ","DQimpsqVrf","hE1QlJIqXi","HzZT8lsQGo","NAFuwCqqaD","PYBf4W7cTs","taOXK580YD","AXpwE1LB1L","Ta8f6prNT6","dpe1vSbRYy",
-"BFkb8O3iyQ","hSSvQHRxd8","hYBCKTXQ0Z","Ta8f616lHc","6q6L9D6rBy","1j5L8okgRi","29QAzM6qcG","Rxrsm8TxD7","DcpWBkB5nP","SWfouJJs5m",
-"Ss0ZuGSQwj","jfREukZANm","uJScXgIYvE","FnPFB2Yz7E","lweGycL0aE","5Namm8FmFH","ix74rsx5Gl","zY1GYFhtgl","FxX9qdmoS7","0ao3l618Di",
-"ogLgckZANm","Gv3FqBbwgA","HlUbFZuDtD","P6bcgxXTI4","BGaQYpT8wu","azIWpDcpWB","5nmWvD6rBy","8TxD7pT8wu","pv0i7WreyP","45cIHAXpwE",
-"cQOnvGrDg7","QClRLzHF1q","NcICAQWxoT","TwanoMkgy8","dhSuHzY1GY","pv0i7RmDcr","Vprf2tuDyS","GrDg7fLNg8","OxWIHVLTy6","tvdkD8RCUA",
-"2hEEUVNCPd","rz7Utulk41","AmdQd64s8N","FcWrW7lUXZ","K4GS814FLR","WDVWJd85a9","ydG8UM6qcG","azIWpJJs5m","No0QbG1RhS","TCgPpv2eC3",
-"IBe8kzY1GY","FwEJz8hJdt","oGu6xWMiS3","QssNCs4786","cL0aEcL0aE","azIWpWMiS3","fcJOyHlUbF","FnPFBDcpWB","ZUnqtFwEJz","SWfoufmIK1",
-"6AFT02Yz7E","iwzGk7lUXZ","ZzJHWFwEJz","7X3uyvkCHH","nlaByNhXdu","dmoS7GXdoH","AkKTks7Mxk","7hyVvWreyP","SbRYyYjB9t","lpF6Wfqypy",
-"0BmCyAkKTk","AOgEeFwEJz","dQ586pAhR1","5IhmGLbRTH","zQt6QvkCHH","zQt6QECMvU","uQIczMmsIo","hE1Qlulk41","ReKEWyofH3","LewvMMkgy8",
-"IjTwPuTacx","2DREs45cIH","9y4lwVLTy6","FFDuicShY2","KsjRKuoStw","x3LDefcJOy","24ARFFGzgp","FPfSEUmaEv","GrDg7AgJHQ","o8UydVNCPd",
-"rz7UtTa8f6","aez9ylCMxy","kZANmBbwgA","X6PinYw2oU","WPmlxDQimp","SjskQ0PktI","pAhR1ZhwG1","QYxC03weIF","2DREsLewvM","8xEKzAgJHQ",
-"3otm6ni2v1","Q6hMCfLNg8","nnP8o0Wr5y","qUJMd5drc6","DQimpb29RJ","XflUq64s8N","piJSkO3iyQ","RmDcri7WMQ","xciqpvOqCE","zY1GYZv7z0",
-"6AFT05IhmG","oQ87rQssNC","oQ87rOUYuF","uZPqgZhwG1","EdBKci7WMQ","RmDcrs93Ml","yToGWeuZA5","LbRTHnFqik","C2Irc0ao3l","uJScXKr8ys",
-"ECMvU8RCUA","9eoRczFgtB","cmXIXIKxdL","euZA5mX2GE","XyPZNlweGy","S2Dfuiqv4k","ZhwG1hUTw7","BFkb8Vprf2","jiVBPEOE1o","mz8gx45cIH",
-"suY4xW3VFH","2TRI7taOXK","Ta8f6GWqqX","7lUXZQnJ1S","uN6r3n8pJ9","OxWIHFVMxo","pWiOsSWfou","zQt6QIRh48","5iGN5WPmlx","pAhR17hyVv",
-"LewvMCdyBV","jzUqRZzJHW","d85a90YAGH","aez9ys4786","gjUTuMkgy8","PYBf4MmKGJ","tjQxsBCxeC","OxWIHLewvM","FFDuiI7p2a","3weIFFwEJz",
-"bZLvSaFFss","hYBCKa00b5","wiHrZFGzgp","brhlQmX2GE","oVQp6WMiS3","Waim6Chuy3","AmdQdW7cTs","Yf2EccShY2","C2IrcKsjRK","JJs5mS2Dfu",
-"uQIczNcICA","vkCHHni2v1","L7cGc2ZHdk","SbRYyzQt6Q","0PktItAOsr","NOHszZzJHW","iqv4kOHaBz","WPmlxS2Dfu","TwanoRpBQm","HlUbFs93Ml",
-"Cp3mZIKxdL","zqH0WNxx9V","8FmFHMezSW","K4GS84W0Tl","yEfy92hEEU","OHaBzUl4a1","zHF1qLbRTH","0h1b1G1RhS","QChxshYBCK","C2Irc5nmWv",
-"uvf7AaL6AJ","7fsYMQbxXc","M6qcGNOHsz","J2mQihe9IA","pmeCdIRh48","FwEJzSs0Zu","gf8rIv1Hln","XflUqQworu","C2IrcMmKGJ","GXdoHzQt6Q",
-"b29RJdmoS7","Oz8yZFjHXR","2hEEUrz7Ut","WMiS3DcpWB","uupzkMmsIo","2NslmVjCZq","iwzGkDG4sT","pFrrlOUqFM","Chuy3IBe8k","e6e4zjzUqR",
-"lCMxyEdBKc","fFDrJmX2GE","X6PinBFkb8","atef2DG4sT","5ZaEz5Namm","0YAGH1LB1L","SjskQ3weIF","Twanosoy9t","tuDySHzZT8","fqypyrz7Ut",
-"MojnPfcwDa","AgJHQuupzk","DQimpBpYhV","djsrvVLTy6","uoStwyofH3","X6PinlViBv","tvdkDFwEJz","ZJTXHAkKTk","a00b5nlaBy","IjTwPQ6hMC",
-"prNT65drc6","uJScX6AFT0","IKxdLs4786","DG4sTiqv4k","Mm8siaL6AJ","Cp3mZgIYvE","uupzkvkCHH","pAhR1KsjRK","vLsmSlXFOB","EOE1oG1RhS",
-"NAFuwJXljW","O3iyQ8hJdt","NhXduy94nw","Gv3Fqs7Mxk","okgRidQ586","vOqCEuvf7A","VNCPdBCxeC","Y1mC0FGzgp","7fKYU8TxD7","RACuj2TRI7",
-"RsQUqazIWp","8TxD7DQimp","pFrrlFPfSE","ThjNnXyPZN","oQ87rFnPFB","Mm8siOz8yZ","ZUnqtWreyP","brhlQ7ku1p","VjCZqxciqp","lj07QZUnqt",
-"n8pJ9dpe1v","NOHszNAFuw","brhlQpT8wu","vkCHHNcICA","WMiS3iwzGk","gjUTuUvlv4","v8yFNFNYIM","ThjNnECMvU","zY1GYogLgc","RkQke14FLR",
-"YjB9tMmsIo","No0Qbuvf7A","jSjS3Rxrsm","9y4lwuoStw","5NammhE1Ql","gtCA5VLTy6","pv0i7gdQsS","suY4xuLtKs","KASQ8JJs5m","9GXkX8FmFH",
-"jfREuThjNn","GrDg79y4lw","29QAz5iGN5","ZJTXHS77LH","BGaQY5VZjS","CqqaDm4bxU","ni2v1lj07Q","jiVBP2ZHdk","oQ87rZ4I1v","5Drn0Oz8yZ",
-"e6e4z9eoRc","0KyfsuAWyp","YjB9ti3pyd","CxVEf0MR5X","hi5X7qUJMd","RpBQmFGzgp","cQOnvFPfSE","azIWpbgJAz","24ARFF6PT2","X6PinjSjS3",
-"tuDySF6PT2","aDGtS7fKYU","KsjRKfaHir","yEfy9piJSk","NOHszPOUYS","YjB9tksJby","M6qcGjeskS","LewvMlCMxy","JKWYRzbIYY","LbRTH9GXkX",
-"6AFT045cIH","4QMc96AFT0","uJScXb29RJ","JRJQBZhwG1","Waim6nFqik","h1zcH5Drn0","In3NSVIlwP","POUYSPb1pa","ogLgcHfyNQ","SWfouXyPZN",
-"FLsphBCxeC","JXljWdhSuH","zz4ZUlj07Q","pmeCdMkgy8","LDk6fQbxXc","24ARF2ZHdk","QClRLX6Pin","Z4I1vNOHsz","IRh48hYBCK","4W0TlECMvU",
-"cQOnvPb1pa","KZamHK4GS8","aez9yOUqFM","FnPFBdhSuH","m4bxUWPmlx","uupzkWmadA","GrDg7MojnP","dmoS72TRI7","HlUbFYjB9t","9y4lwvkCHH",
-"Ss0ZuKr8ys","jtn0X0ao3l","CdyBVOUqFM","TwanoRACuj","t98iWtl72W","uZPqgpvgjS","Kr8ysOxWIH","07n1cZuDtD","Kr8ysMm8si","xReecMK07Y",
-"aez9yjiVBP","AgJHQ5Drn0","t59lRWPmlx","CIShG16lHc","FNYIMqQxHP","uN6r3CqqaD","rhl0JO3iyQ","iwzGkhe9IA","soy9t8TxD7","fFDrJWmadA",
-"k85AeFFDui","lXFOBfLNg8","9GXkXPb1pa","8cVD33weIF","8RCUAaez9y","GrDg7qaofN","FjHXRFhtgl","kZANmlViBv","zFgtBru4UG","RpBQmgf8rI",
-"ni2v15iGN5","VIlwPChuy3","IBe8ksoy9t","RpBQm2ZHdk","Gv3Fqaez9y","8cVD314FLR","y94nwZv7z0","0ao3lUmaEv","QWxoTjeskS","pWiOsFjHXR",
-"JXljWlCMxy","yToGW07n1c","55rfB9XyT9","SbRYyZuDtD","BFkb8YOfrY","gIYvECdyBV","CxVEfM6qcG","brhlQfqypy","i7WMQYh1hF","hUTw75IhmG",
-"s47867ku1p","e6e4zpv0i7","k85AeOUqFM","45cIHfcwDa","yEfy9bgJAz","x3LDeIKxdL","NOHszlXFOB","M3zXLcQOnv","HP433o8Uyd","hE1QlRpBQm",
-"KASQ8gdQsS","kB5nPNOHsz","HP433FNYIM","GXdoHSs0Zu","taOXKGrDg7","iqv4koGu6x","v8yFNPYBf4","OUYuFZzJHW","FFDuiPYBf4","d85a9guMb8",
-"0MR5XQChxs","kZANmt98iW","StlDJiqv4k","guMb8djsrv","D6rByydG8U","NcICAuJScX","ZhwG1zHF1q","iB08lECMvU","MojnPRzaZA","d85a9xciqp",
-"hYBCKQWxoT","5IhmGpmeCd","WreyPMmKGJ","nFqikBbwgA","xXTI4FGzgp","FhtglYf2Ec","Kr8ysVLTy6","FFDuiUmaEv","CxVEfiqv4k","OHaBz4W0Tl",
-"QYxC0Z4I1v","EdBKc4QMc9","lweGyCdyBV","brhlQgjUTu","5VZjSs93Ml","uJScXC2Irc","gf8rI0h1b1","zY1GYWmadA","Cfgr3No0Qb","POUYS5ZaEz",
-"v2eC3uoStw","M3zXLsqVrf","cQOnvyvOMI","FGzgpI7p2a","AOgEeUlU3M","pT8wuwiHrZ","jiVBPa00b5","RsQUqcShY2","5Mg9rDz1R3","qaofN1LB1L",
-"qaofNn8pJ9","y94nwWMiS3","oGu6xAmdQd","CxVEfxciqp","6q6L9QChxs","FNYIMMK07Y","29QAz7Ow5C","TXQ0ZTCgPp","zqH0WgjUTu","zQt6QHlUbF",
-"lpF6WDz1R3","cQOnvIBe8k","Qworul83Ud","DcpWBjeskS","xReecWmadA","cShY264s8N","IBe8k24ARF","IjTwPlsQGo","3otm6POUYS","yEfy91j5L8",
-"dpe1vZ4I1v","HzZT8P6bcg","Cfgr3Mkgy8","faHirjiVBP","FcWrWU3yw5","rKDLJiB08l","zz4ZUjSjS3","zQt6QHfyNQ","taOXKoQ87r","mz8gxd7vjM",
-"he9IAOUYuF","0MR5XAmdQd","rhl0J0ao3l","MmKGJ2Yz7E","pAhR1CxVEf","h1zcHhE1Ql","NAFuwPOUYS","2ZHdkpWiOs","P6bcgi7WMQ","brhlQFhtgl",
-"2hEEUguMb8","2hEEU5IhmG","hSSvQQWxoT","8hJdtd85a9","WPmlxqQxHP","Oz8yZIn3NS","ydG8UpmeCd","sqVrfs4786","FxX9qQYxC0","Fhtgl48cHL",
-"RmDcr618Di","SjskQ14FLR","FNYIM24ARF","Zv7z0d7vjM","lkMUAsoy9t","NhXdugjUTu","rz7UtaL6AJ","tjQxs64s8N","v1HlnfmIK1","JkzUnv8yFN",
-"P6bcgxciqp","8hJdtTXQ0Z","Yf2EcmX2GE","nnP8oQWxoT","nlaByoGu6x","aDGtS1v5hH","GWqqXuN6r3","SmGzv2TRI7","lpF6WlpF6W","gtCA51v5hH",
-"5Drn0tAOsr","nnP8o1LB1L","POUYS5Mg9r","HfyNQHfyNQ","fFDrJgtCA5","FcWrWrz7Ut","yEfy9QssNC","JXljWRmDcr","rKDLJ6q6L9","jfREuQYxC0",
-"OUqFMatef2","jiVBPhYBCK","uJScXyvOMI","tjQxsBpYhV","2Yz7E55rfB","AOgEeQClRL","7X3uyLewvM","ZhwG1QnJ1S","8U2nUAkKTk","uvf7AOz8yZ",
-"KZamHeuZA5","5Namm5nmWv","fqypy2ZHdk","lH1ktRACuj","blLA9qQxHP","a00b5gjUTu","ogLgcfaHir","iKqhrm4bxU","FVMxoWreyP","GXdoHUlU3M",
-"9y4lw0Wr5y","Nxx9VpFrrl","EoToPs93Ml","soy9t6AFT0","Waim6QnJ1S","faHirpv0i7","XyPZNhE1Ql","t59lRsoy9t","07n1cAXpwE","pT8wuuTacx",
-"0MR5XtlILt","uoStwRpBQm","lViBvHP433","hi5X7IKxdL","ZuDtDs4786","iqv4kWreyP","n8pJ9FxX9q","9eoRcn1pmO","1v5hHAIYUu","gf8rIzY1GY",
-"RACujiqv4k","JXljWEoToP","BpYhVaL6AJ","HzZT8x3LDe","cQOnvi7WMQ","xXTI4CxVEf","zbIYYjS1aj","pAhR1rhl0J","ZhwG1yluBx","Cfgr3bgJAz",
-"ogLgclkMUA","Kr8ysvOqCE","dhSuHMmsIo","lj07Qpv0i7","t98iW4dEz6","Zv7z0jfREu","MezSW2DREs","IRh48h1zcH","FNYIMbgJAz","4dEz6CK5W7",
-"P6bcgYf2Ec","07n1caez9y","9XyT9fqypy","8xEKzKASQ8","CK5W7s4786","x3LDeOz8yZ","BCxeC3otm6","cmXIXJRJQB","dhSuHCqqaD","pv0i7wiHrZ",
-"VerEAY1mC0","QnJ1SxXTI4","Y1mC0RzaZA","iB08lMezSW","Ul4a1VLTy6","RpBQm48cHL","VNCPd7fsYM","2Yz7EXyPZN","LbRTHdhSuH","b29RJM3zXL",
-"djsrvBCxeC","zHF1qFjHXR","7lUXZsoy9t","StlDJFjHXR","BCxeC0PktI","P6bcgRzaZA","CxVEfDcpWB","HfyNQQYxC0","euZA5Fhtgl","No0QbVjCZq",
-"pmeCd8TxD7","JKWYRLbRTH","b29RJuoStw","Dz1R3uTacx","yToGWUvlv4","AmdQdokgRi","Gv3FqXflUq","RsQUquTacx","7Ow5C8FmFH","MmKGJMezSW",
-"Cp3mZiB08l","kZANm45cIH","Gv3FqPYBf4","S2DfuJIqXi","iqv4kM6qcG","DQimp0ao3l","lsQGoTXQ0Z","EoToPS2Dfu","9GXkXMkgy8","OxWIH0Kyfs",
-"ulk419eoRc","7fKYUYf2Ec","QssNCwiHrZ","FhtglAOgEe","3otm65VZjS","BCxeCEoToP","ksJbyNhXdu","piJSkYh1hF","VLTy6zz4ZU","LbRTHDz1R3",
-"okgRilViBv","vkCHH5Namm","RBhp0WreyP","gf8rICfgr3","v8yFNMm8si","9y4lw14FLR","lkMUAzmLYD","4dEz6HP433","nlaByzqH0W","8cVD3SWfou",
-"hE1Ql2hEEU","k85Ae0YAGH","y94nwzQt6Q","v1HlnlsQGo","7X3uyFPfSE","gf8rI2hEEU","pv0i79rlg9","okgRi2hEEU","pv0i7IjTwP","wiHrZfqypy",
-"fFDrJ29QAz","kB5nP6q6L9","lweGyMkgy8","cL0aEQWxoT","VBjhzsx5Gl","AOgEesqVrf","9XyT9RkQke","U3yw5EOE1o","ZJTXH5nmWv","lweGysuY4x",
-"RpBQmFFDui","wiHrZQYxC0","In3NSTCgPp","9GXkX618Di","DQimpiqv4k","rKDLJ29QAz","FjHXRiqv4k","JkzUnO3iyQ","07n1cWDVWJ","8FmFHs4786",
-"QssNCsoy9t","14FLRFGzgp","FFDui580YD","IKxdLUl4a1","0PktIOUqFM","uPX7GK4GS8","K20wKbrhlQ","x3LDegjUTu","XflUqMK07Y","fcwDab29RJ",
-"U3yw50ao3l","soy9tkB5nP","CIShGJ2mQi","DG4sT8RCUA","bZLvS0ao3l","PYBf4FFDui","0KyfsSs0Zu","MmsIo1LB1L","5IhmG9rlg9","Fhtglh1zcH",
-"Kr8ysuJScX","t59lRMojnP","v1HlnazIWp","VerEAulk41","618DiMojnP","Zv7z0qUJMd","pT8wupvgjS","azIWpgIYvE","I7p2aSjskQ","KZamHiB08l",
-"DcpWB9GXkX","WaWsvGWqqX","brhlQ7fKYU","M6qcGzHF1q","Gv3FqB3qem","55rfBTa8f6","G1RhSd7vjM","GXdoH3otm6","BpYhV8hJdt","okgRiBCxeC",
-"7ku1pazIWp","gdQsSv1Hln","SjskQlkMUA","QbxXcs7Mxk","VBjhzIKxdL","ciuWzix74r","HzZT8sx5Gl","sx5GlyEfy9","nFqikk85Ae","GSQwjzqH0W",
-"GrDg7zmLYD","rz7UtWaim6","Yh1hFyvOMI","MezSWkB5nP","hSSvQtaOXK","JJs5mQbxXc","FLsphgtCA5","XyPZNECMvU","LbRTHjzUqR","2Yz7EzY1GY",
-"zmLYDX6Pin","uJScXfqypy","uN6r3XyPZN","uZPqgokgRi","48cHLsx5Gl","Yh1hFzHF1q","Vprf26q6L9","zbIYYxXTI4","BbwgAIRh48","fcwDaatef2",
-"s93MltjQxs","VLTy6QnJ1S","dhSuHcShY2","JRJQBYf2Ec","M6qcGJkzUn","gdQsSfqypy","GSQwjQChxs","Ss0ZunnP8o","pv0i7lCMxy","7X3uyMezSW",
-"BpYhVGSQwj","vkCHHJIqXi","YjB9tfcJOy","JXljW55rfB","v1Hlnuvf7A","o8UydRzaZA","gtCA52TRI7","SWfoucL0aE","QnJ1SHlUbF","MmKGJk85Ae",
-"v2eC3XflUq","CdyBVVerEA","5IhmGZv7z0","GWqqX64s8N","U3yw5n1pmO","QChxsPb1pa","Oz8yZogLgc","No0QblXFOB","ZhwG1ulk41","Mm8si9iGoT",
-"jS1ajjzUqR","MojnPIKxdL","mz8gxpvgjS","SWfoum4bxU","RBhp0LDk6f","JXljWl83Ud","IKxdL16lHc","n8pJ9IRh48","EdBKc8TxD7","AgJHQ1v5hH",
-"7Ow5ClkMUA","ECMvUv2eC3","U3yw5VLTy6","9eoRcfFDrJ","QnJ1Sd7vjM","Gv3FqTCgPp","7fsYMFNYIM","WMiS3ciuWz","0ao3lAIYUu","7ku1pjS1aj",
-"uLtKsblLA9","s93MlFhtgl","F6PT20MR5X","hi5X77Ow5C","GXdoHtuDyS","e6e4zdpe1v","5IhmGni2v1","ulk41uN6r3","Mm8siEoToP","1LB1L618Di",
-"MK07YpT8wu","EOE1oiwzGk","yToGW2ZHdk","KZamHnnP8o","Mm8siguMb8","BFkb8FjHXR","SWfouBbwgA","jfREuBGaQY","y94nwYOfrY","vOqCEuLtKs",
-"3otm6Mm8si","OUqFMpFrrl","Waim6lsQGo","Z4I1vCNHmv","rKDLJWPmlx","WaWsvrhl0J","jzUqRpv0i7","U3yw5MGlTF","DQimpMmKGJ","jSjS30Kyfs",
-"kZANmfcJOy","hi5X7F6PT2","pv0i7IKxdL","CNHmvS77LH","lm0pDAgJHQ","rz7UtdmoS7","n1pmOfLNg8","xReecFnPFB","5drc6CK5W7","AIYUuNhXdu",
-"v2eC3v1Hln","BCxeCFnPFB","IRh48Uvlv4","xXTI4zY1GY","pFrrlStlDJ","WPmlxUvlv4","FcWrWQworu","hi5X71v5hH","dpe1vuvf7A","W7cTsVerEA",
-"OHaBzdQ586","hUTw7nlaBy","ECMvUMGlTF","Yw2oUlViBv","ogLgctuDyS","oGu6xv1Hln","SbRYylm0pD","dQ586Rxrsm","5Mg9rfaHir","Waim6lpF6W",
-"tvdkDVerEA","IjTwP45cIH","QssNCYf2Ec","dQ586blLA9","cQOnv0YAGH","OUYuFAgJHQ","QbxXcx3LDe","Ta8f68TxD7","n1pmOaFFss","cShY2AXpwE",
-"3weIFl83Ud","uTacxYOfrY","QClRLs7Mxk","KsjRKuZPqg","45cIHpWiOs","FcWrWRACuj","piJSkMojnP","F6PT2jSjS3","IBe8kfqypy","L7cGcaDGtS",
-"o8UydZUnqt","RkQkelH1kt","8xEKzrKDLJ","J2mQi7lUXZ","DLhzMydG8U","zz4ZUyvOMI","0Kyfs618Di","Y1mC0HzZT8","zbIYYAIYUu","ThjNnMezSW",
-"5nmWvQClRL","zHF1q1v5hH","l83UdB3qem","tlILtt59lR","lXFOB45cIH","Waim6No0Qb","EdBKcFGzgp","jeskSm4bxU","1j5L8zqH0W","k85AeS2Dfu",
-"hE1QlD6rBy","5IhmGFhtgl","0MR5XVIlwP","uQIcz2TRI7","618DipmeCd","KZamHCqqaD","SmGzvqQxHP","9y4lwTa8f6","ZJTXHFLsph","9XyT9uQIcz",
-"O3iyQ55rfB","EoToPtlILt","VjCZqCqqaD","ru4UGAIYUu","YOfrY5Drn0","JKWYRhSSvQ","aez9yYf2Ec","x3LDeuAWyp","uvf7ARpBQm","yvOMIECMvU",
-"fmIK1zHF1q","Zv7z0s93Ml","Vprf2ZuDtD","9eoRcjSjS3","8RCUA9eoRc","3otm6HRxd8","UlU3MCxVEf","EdBKcprNT6","Waim6Rxrsm","ZzJHW9iGoT",
-"t98iWlH1kt","ciuWzm4bxU","l83UdCqqaD","gIYvEyvOMI","L7cGcVBjhz","L7cGcZJTXH","FNYIMlXFOB","07n1cjSjS3","YjB9tVNCPd","5drc6EOE1o",
-"he9IAazIWp","VerEAtjQxs","9XyT9hE1Ql","IBe8ks4786","uQIcz580YD","qaofNDcpWB","NcICADQimp","blLA9cShY2","Kr8ysWMiS3","0BmCyiKqhr",
-"dmoS7qaofN","14FLR2DREs","gtCA5TCgPp","jzUqRuLtKs","aL6AJhYBCK","n8pJ9PYBf4","WaWsvCqqaD","GXdoHRzaZA","fLNg8VBjhz","n8pJ9Nxx9V",
-"2TRI7FcWrW","POUYSvOqCE","uQIczlsQGo","Chuy3Yh1hF","iwzGkFjHXR","wiHrZ5Drn0","iB08lHzZT8","CK5W7J2mQi","JXljWPOUYS","B3qemChuy3",
-"tvdkDVprf2","gtCA5AXpwE","Ss0ZuFcWrW","iqv4kMmsIo","DQimpVerEA","oVQp69eoRc","Q6LixNAFuw","M6qcGfaHir","Dz1R3fcJOy","aFFssWDVWJ",
-"1v5hHtlILt","xciqp8FmFH","zY1GYI7p2a","RsQUqFNYIM","gf8rI5iGN5","U3yw51v5hH","hUTw7uZPqg","MK07YEoToP","dmoS7uPX7G","taOXKn1pmO",
-"yToGWNo0Qb","EdBKcm4bxU","DcpWB29QAz","AIYUuCK5W7","HRxd83otm6","lj07QyluBx","fcwDazQt6Q","QYxC02Nslm","MmKGJ580YD","WreyP580YD",
-"dQ586Nxx9V","9eoRcdmoS7","yvOMIy94nw","lCMxyYf2Ec","Uvlv4CNHmv","ZJTXHVerEA","G1RhS7lUXZ","64s8NfcJOy","0h1b15IhmG","OHaBzsoy9t",
-"oGu6x8RCUA","2TRI7Mm8si","tAOsrvLsmS","VNCPd2Yz7E","RxrsmazIWp","YOfrYEOE1o","QClRLIn3NS","pmeCd0Kyfs","n8pJ9GrDg7","v2eC3hYBCK",
-"ksJbyYjB9t","FGzgpDG4sT","JXljWhE1Ql","faHirfaHir","I7p2a0MR5X","XflUqO3iyQ","4QMc9VBjhz","dpe1vlkMUA","dpe1vVerEA","8U2nUGv3Fq",
-"3weIFEdBKc","580YDU3yw5","ydG8URBhp0","zz4ZU5nmWv","ru4UGU3yw5","zmLYD5nmWv","qUJMdzz4ZU","LDk6fM3zXL","dmoS7djsrv","jtn0XFxX9q",
-"WDVWJxciqp","HfyNQJXljW","RsQUqQ6Lix","ksJbypWiOs","VerEAKr8ys","UlU3MbgJAz","4dEz6EOE1o","FxX9qVerEA","sqVrfaDGtS","fqypyMmKGJ",
-"0KyfsG1RhS","8FmFHyluBx","t98iWfFDrJ","580YDvOqCE","xReecdmoS7","ru4UGuQIcz","qQxHP2hEEU","GXdoH2Yz7E","faHirY1mC0","MmsIodhSuH",
-"FVMxojzUqR","MmKGJYh1hF","RxrsmCIShG","QWxoTzbIYY","yvOMIaDGtS","FVMxo16lHc","m4bxUhYBCK","PYBf4LewvM","0KyfshUTw7","Yw2oUvLsmS",
-"Z4I1vHlUbF","Yw2oUnFqik","Ta8f6yofH3","RACujiB08l","BFkb8HRxd8","9eoRcru4UG","lViBvlsQGo","MmsIoatef2","07n1c2Nslm","FVMxoZhwG1",
-"ksJby55rfB","mX2GEciuWz","oGu6xQssNC","RsQUqHzZT8","xciqpUl4a1","pAhR1Qworu","LDk6fRmDcr","cShY27ku1p","l83UdNhXdu","EOE1oIn3NS",
-"QbxXclViBv","Yw2oU9iGoT","xXTI4s93Ml","0PktIlViBv","Yh1hFMm8si","NhXduzQt6Q","DG4sTblLA9","DQimpxReec","BCxeCv1Hln","P6bcgWmadA",
-"In3NSuPX7G","7Ow5C0YAGH","7ku1p4QMc9","cL0aEVprf2","gjUTublLA9","prNT6HzZT8","gtCA5bZLvS","sx5GlMm8si","i3pyduoStw","ru4UGRACuj",
-"7ku1pVjCZq","QbxXczFgtB","BbwgANAFuw","v2eC3VLTy6","prNT6pWiOs","MK07YO3iyQ","9y4lwIKxdL","VNCPdd7vjM","JRJQBnlaBy","ReKEWyToGW",
-"jeskSQYxC0","F6PT2okgRi","dpe1vdQ586","l83Ud0Wr5y","v2eC3QbxXc","aL6AJcL0aE","AOgEeXflUq","tAOsrtaOXK","DcpWBCdyBV","5drc6S2Dfu",
-"yofH3PYBf4","euZA58U2nU","pvgjSjfREu","brhlQd7vjM","a00b5F6PT2","RxrsmAmdQd","0MR5Xe6e4z","jS1ajzz4ZU","lm0pDlViBv","rz7Ut45cIH",
-"NAFuwn1pmO","xXTI4gf8rI","29QAzHP433","NOHszgjUTu","JKWYRDG4sT","uLtKsTXQ0Z","dmoS7VjCZq","PYBf4GSQwj","4QMc9lViBv","5IhmGaL6AJ",
-"Kr8ys2ZHdk","nnP8oWaim6","lm0pDgf8rI","iwzGkSjskQ","B3qemMmKGJ","CxVEfAXpwE","JXljWuZPqg","EdBKcMm8si","QssNCCK5W7","lH1ktS2Dfu",
-"9XyT9FGzgp","aL6AJNxx9V","MojnPIBe8k","HRxd8Yh1hF","LewvMP6bcg","he9IAcL0aE","9XyT9ZuDtD","C2IrcCIShG","5Drn0RpBQm","jiVBPzqH0W",
-"C2IrcMm8si","WaWsvRzaZA","hUTw7BpYhV","pv0i7bgJAz","VBjhzMkgy8","J2mQiazIWp","G1RhSFxX9q","M6qcGOxWIH","zbIYYXflUq","GXdoHAXpwE",
-"zQt6Qmz8gx","4QMc9yvOMI","JIqXiHRxd8","DG4sTHzZT8","CxVEfFNYIM","DG4sTJKWYR","TCgPpZzJHW","Mm8siYjB9t","kZANmS77LH","LbRTH55rfB",
-"No0Qb24ARF","0ao3l0PktI","bgJAzZ4I1v","0KyfsSjskQ","5IhmGyvOMI","VLTy65VZjS","UmaEv5Mg9r","Ul4a1Z4I1v","OHaBzhi5X7","JJs5myofH3",
-"okgRicQOnv","VjCZqLbRTH","2Nslmrhl0J","WmadAzFgtB","4W0Tlhi5X7","l83Ud07n1c","zmLYDTwano","4QMc98xEKz","GrDg7s7Mxk","wiHrZZUnqt",
-"gtCA5lm0pD","sqVrfK4GS8","Zv7z09rlg9","XflUqrhl0J","Nxx9VfcJOy","7ku1pVerEA","fLNg8lpF6W","pFrrlXflUq","aez9yUmaEv","LewvMVBjhz",
-"oQ87rC2Irc","StlDJJJs5m","bZLvSDcpWB","qaofNThjNn","16lHcvkCHH","xReecpAhR1","ru4UGI7p2a","9eoRcnlaBy","IRh489XyT9","6AFT0RpBQm",
-"ZJTXHNhXdu","Mm8siFGzgp","7X3uyuPX7G","iwzGknlaBy","14FLRZUnqt","bgJAzS2Dfu","5iGN5djsrv","ZuDtDpWiOs","uJScXfaHir","WPmlxOxWIH",
-"FjHXRVjCZq","BpYhVU3yw5","AIYUulViBv","tuDySECMvU","uAWypjiVBP","zQt6QVprf2","YOfrYCxVEf","Kr8ys7Ow5C","In3NSThjNn","8RCUAv1Hln",
-"3otm6IRh48","dhSuHzFgtB","P6bcgUmaEv","taOXKCxVEf","GWqqXI7p2a","yluBxwiHrZ","MaJQsHzZT8","xReectjQxs","oGu6x9rlg9","5iGN5Rxrsm",
-"9GXkX16lHc","QworudhSuH","AXpwE6q6L9","gIYvEuTacx","29QAzXyPZN","JRJQBNo0Qb","I7p2auN6r3","cmXIXxciqp","SWfou7fsYM","dQ5867hyVv",
-"nlaByOz8yZ","9eoRclkMUA","s4786WPmlx","t98iWaez9y","zqH0W3weIF","rhl0JCfgr3","EoToPydG8U","Chuy3lweGy","0YAGHdQ586","RxrsmhUTw7",
-"lkMUADG4sT","9XyT9uoStw","NcICANxx9V","o8Uyd4dEz6","WMiS3vLsmS","taOXKBbwgA","Nxx9ViwzGk","hYBCK8RCUA","rhl0JFxX9q","OxWIHHzZT8",
-"ulk41mz8gx","jfREuK20wK","9iGoTVjCZq","UmaEvdpe1v","ReKEWkZANm","iKqhrJ2mQi","gf8rIZv7z0","iwzGks4786","RACujwiHrZ","uvf7A8FmFH",
-"ydG8UtuDyS","0MR5XuLtKs","hSSvQm4bxU","OUYuFyofH3","EOE1oIKxdL","WaWsvogLgc","pWiOsM3zXL","rhl0JtaOXK","lpF6WdhSuH","GXdoHlCMxy",
-"jSjS3GSQwj","TCgPpe6e4z","EOE1odQ586","7fsYM7hyVv","gjUTuNhXdu","wDajXbgJAz","618DiCfgr3","i7WMQo8Uyd","HzZT8BCxeC","BCxeC7fsYM",
-"QworuiKqhr","M6qcGuupzk","Q6hMC5nmWv","8TxD7ZUnqt","DQimphYBCK","a00b5blLA9","24ARFvkCHH","SmGzvnlaBy","Q6hMClpF6W","Cp3mZprNT6",
-"s4786pv0i7","uTacxVBjhz","HP433mX2GE","yvOMIYh1hF","wiHrZi7WMQ","XflUq1j5L8","i3pydMezSW","hi5X77lUXZ","CNHmvZv7z0","pmeCdjzUqR",
-"QworuCIShG","bZLvSVprf2","dhSuHG1RhS","UlU3MIKxdL","C2IrczbIYY","Yw2oUjSjS3","AIYUulH1kt","euZA5n8pJ9","O3iyQQYxC0","L7cGcDcpWB",
-"In3NSjiVBP","EdBKculk41","he9IAUlU3M","F6PT2AkKTk","Vprf27lUXZ","Ss0Zulj07Q","IRh48Yw2oU","nFqikP6bcg","QnJ1SRkQke","In3NSZUnqt",
-"0KyfsK4GS8","uQIczoGu6x","pv0i7SjskQ","FVMxoEOE1o","In3NS5Namm","1j5L8kZANm","Y1mC01LB1L","KASQ8IRh48","6q6L9ksJby","l83UdSjskQ",
-"s93MlguMb8","QworuMojnP","cShY2uPX7G","JRJQBoGu6x","fFDrJ5Mg9r","QChxsZv7z0","BpYhVwiHrZ","SmGzvpFrrl","ru4UGoQ87r","RsQUq55rfB",
-"jeskS5Mg9r","RACujVIlwP","Yh1hFcQOnv","DQimpYw2oU","iKqhrazIWp","pFrrl4QMc9","ZhwG1dpe1v","kZANmJkzUn","zHF1q8TxD7","rhl0JFnPFB",
-"StlDJ7lUXZ","blLA9n8pJ9","yToGWuupzk","S77LHECMvU","lsQGoaDGtS","Yw2oU0Kyfs","zqH0WzmLYD","AXpwEtlILt","qaofNfLNg8","dmoS7Cfgr3",
-"G1RhSFnPFB","ThjNn0Kyfs","a00b50YAGH","jzUqRs93Ml","iB08lm4bxU","AXpwE7fKYU","MojnP45cIH","djsrvfaHir","1LB1L4dEz6","aFFssfLNg8",
-"29QAz7hyVv","bgJAzZv7z0","SbRYyrz7Ut","M3zXL07n1c","LbRTH2ZHdk","QssNCdQ586","oVQp6NAFuw","CqqaDChuy3","n1pmOC2Irc","s4786fqypy",
-"wDajXhYBCK","8FmFHTCgPp","zbIYYBFkb8","ulk41Kr8ys","Nxx9V55rfB","580YDsx5Gl","G1RhS8FmFH","0KyfsFNYIM","9eoRcbgJAz","zbIYYRzaZA",
-"Dz1R31j5L8","Yf2EcBbwgA","qUJMd7fKYU","faHir0h1b1","AIYUuVLTy6","Ss0Zu8hJdt","Yf2EcWreyP","fLNg80BmCy","LbRTHzmLYD","OUqFMKsjRK",
-"ksJbyBCxeC","s7Mxk29QAz","UlU3M7fKYU","G1RhS7ku1p","tvdkDQ6hMC","GWqqXCIShG","AOgEeRzaZA","C2IrcOz8yZ","4dEz6HlUbF","BCxeCMezSW",
-"vLsmSdpe1v","YjB9t4QMc9","9y4lwyofH3","ulk41jeskS","XflUqWMiS3","pT8wuECMvU","Mkgy8uLtKs","NOHszIn3NS","dQ586GrDg7","wiHrZM3zXL",
-"xciqpEdBKc","RBhp0pvgjS","X6PinPYBf4","0Wr5yGv3Fq","Ul4a1hYBCK","W7cTs0PktI","taOXKMmsIo","Cp3mZlweGy","b29RJNxx9V","NcICAhe9IA",
-"5Mg9rBCxeC","ReKEWIjTwP","Mkgy8iwzGk","IKxdL0MR5X","UmaEvxReec","Chuy3kZANm","Z4I1vGXdoH","YOfrYrKDLJ","NOHszBCxeC","uupzkThjNn",
-"okgRiprNT6","v2eC3blLA9","RACuj8xEKz","ZzJHW9XyT9","24ARFNhXdu","XyPZNPYBf4","Fhtgluvf7A","AXpwEyluBx","qaofNP6bcg","AIYUukZANm",
-"M6qcGO3iyQ","9eoRcB3qem","jfREuVBjhz","SmGzvhUTw7","MezSWix74r","QssNCVerEA","2TRI7tvdkD","24ARFZhwG1","blLA9vkCHH","Yw2oUPb1pa",
-"y94nw5Drn0","bZLvSrz7Ut","OHaBz2TRI7","07n1cDQimp","IRh48Cfgr3","G1RhSJIqXi","KASQ8O3iyQ","KASQ8W7cTs","pmeCdQworu","Nxx9VIn3NS",
-"fLNg87Ow5C","CIShGSjskQ","zY1GYUvlv4","Nxx9Vru4UG","ZuDtDwiHrZ","TCgPpi3pyd","29QAzI7p2a","0Wr5ygtCA5","zQt6QSbRYy","k85AenFqik",
-"cmXIXWPmlx","bZLvSPYBf4","Gv3Fq8cVD3","IjTwPS77LH","9iGoTsuY4x","8RCUAWPmlx","Uvlv4ReKEW","FnPFBWPmlx","GSQwj8FmFH","AmdQdjfREu",
-"b29RJs93Ml","ZzJHWIn3NS","3otm6DQimp","uLtKsNAFuw","lm0pDPb1pa","D6rByulk41","sqVrfCdyBV","POUYSrKDLJ","0h1b1WDVWJ","MaJQs9rlg9",
-"yToGWsuY4x","yofH3fqypy","zqH0Wb29RJ","s4786jSjS3","ciuWzQYxC0","yToGWMezSW","GXdoHvkCHH","pAhR1IRh48","OHaBz5Mg9r","RmDcrxciqp",
-"lm0pDuQIcz","48cHLqUJMd","oQ87rThjNn","MaJQsh1zcH","rz7UtfmIK1","TXQ0Z45cIH","OxWIHWDVWJ","IjTwPZJTXH","RxrsmKsjRK","FjHXR0h1b1",
-"Yf2EcMojnP","Q6LixokgRi","t98iWX6Pin","pT8wuDQimp","MojnPlViBv","7X3uy0BmCy","jzUqRlXFOB","t59lRuAWyp","O3iyQiKqhr","ydG8UWDVWJ",
-"SbRYy7hyVv","lj07QK20wK","5ZaEzGrDg7","lj07QZ4I1v","AmdQdjS1aj","NhXdu0BmCy","Nxx9VWmadA","8U2nUYf2Ec","MezSWS2Dfu","l83Ud9iGoT",
-"xciqpZv7z0","lkMUAt98iW","dQ5868hJdt","AmdQdix74r","rhl0JRkQke","BpYhVGWqqX","S77LHMmKGJ","iqv4kCfgr3","y94nwK4GS8","FnPFBTwano",
-"zz4ZUQbxXc","Ss0ZuJKWYR","4W0Tl8FmFH","0YAGHMezSW","he9IA6q6L9","soy9tNhXdu","FGzgpxXTI4","gdQsSlpF6W","5IhmG0BmCy","G1RhSCp3mZ",
-"tAOsryluBx","zmLYDJKWYR","MmKGJFcWrW","Mm8siCqqaD","J2mQiW7cTs","BpYhV14FLR","tAOsrguMb8","nnP8on8pJ9","NcICAThjNn","oQ87rGWqqX",
-"FGzgpqQxHP","3weIFzHF1q","K4GS8S2Dfu","Gv3Fqmz8gx","lweGyzqH0W","0KyfsStlDJ","8U2nUgf8rI","gtCA5hi5X7","nFqikQWxoT","7fKYU14FLR",
-"yEfy9uoStw","8U2nUPOUYS","pWiOsFxX9q","5drc6FjHXR","djsrvS2Dfu","No0QbFFDui","RmDcrVprf2","lXFOB2Nslm","In3NS580YD","AkKTkAmdQd",
-"WreyPtaOXK","SjskQ0BmCy","Ul4a19GXkX","uvf7A9rlg9","hYBCKlsQGo","hSSvQOxWIH","soy9tJkzUn","HP433XflUq","lH1kt55rfB","ZhwG1JKWYR",
-"5nmWvjtn0X","cL0aEzbIYY","ksJbyUmaEv","dpe1v0h1b1","ZJTXHs7Mxk","NOHszyEfy9","VBjhznnP8o","1v5hH7fsYM","Uvlv48U2nU","G1RhSh1zcH",
-"CK5W72hEEU","blLA9n1pmO","faHirCIShG","JKWYRReKEW","lweGyNcICA","VIlwPQ6hMC","FwEJzs93Ml","J2mQiDcpWB","Dz1R3cL0aE","QYxC05nmWv",
-"oQ87rbZLvS","FcWrWkB5nP","8FmFHuupzk","GSQwjlm0pD","OHaBzl83Ud","CxVEfP6bcg","NhXdudhSuH","ogLgcjiVBP","ciuWz16lHc","Chuy3ZJTXH",
-"aez9yTwano","uvf7A7Ow5C","UlU3MfcJOy","O3iyQfmIK1","n8pJ93weIF","DQimpChuy3","gjUTuzFgtB","iKqhrTCgPp","i3pydAkKTk","In3NS7hyVv",
-"kB5nPfFDrJ","MezSWOHaBz","uN6r3qUJMd","AXpwEVNCPd","jiVBPfFDrJ","s47863weIF","xciqp9y4lw","MGlTFjSjS3","EoToPpiJSk","mz8gxjzUqR",
-"cQOnvIKxdL","K20wKQClRL","0MR5XEdBKc","zmLYD7lUXZ","D6rByxXTI4","7X3uyP6bcg","lH1ktwiHrZ","FwEJzqUJMd","Vprf2prNT6","JXljWJKWYR",
-"ReKEW7ku1p","atef214FLR","Y1mC0QnJ1S","Yh1hFy94nw","618DiGrDg7","9eoRcs7Mxk","7lUXZ64s8N","PYBf4L7cGc","Z4I1vOz8yZ","YOfrYsuY4x",
-"uN6r3U3yw5","6q6L9tl72W","ECMvUtvdkD","SjskQtvdkD","lViBvCp3mZ","FwEJztjQxs","8xEKzlkMUA","JRJQBuZPqg","5VZjSiB08l","9XyT9RACuj",
-"azIWpPb1pa","NcICAdjsrv","9XyT9FxX9q","DLhzMG1RhS","jzUqRZuDtD","BCxeCiqv4k","nlaBy5Drn0","RmDcrhe9IA","GSQwjjS1aj","tuDySWDVWJ",
-"suY4xFjHXR","DQimp6AFT0","oQ87rix74r","v1Hlnhe9IA","Ul4a1NcICA","29QAzWDVWJ","In3NSaL6AJ","ZzJHWrKDLJ","qUJMd5IhmG","8xEKzDz1R3",
-"lViBvuupzk","M3zXLkZANm","S2DfuIBe8k","64s8NXflUq","8FmFHzY1GY","djsrvfLNg8","No0QbjSjS3","Oz8yZYjB9t","he9IA29QAz","GWqqXZhwG1",
-"0MR5XHlUbF","ix74rTXQ0Z","rz7UtgIYvE","BpYhVCp3mZ","pv0i7yofH3","P6bcgLewvM","ulk41zz4ZU","ru4UG29QAz","0YAGHJRJQB","0PktIIRh48",
-"IKxdL45cIH","ciuWzM6qcG","5VZjSa00b5","0Wr5ykZANm","jzUqRuupzk","HRxd8MGlTF","iwzGkuQIcz","uZPqgFcWrW","NcICA6AFT0","CqqaDcQOnv",
-"MGlTFNo0Qb","vOqCEmX2GE","uJScXOHaBz","CIShGtaOXK","iKqhr1LB1L","uQIcznFqik","jeskSuupzk","DQimpVNCPd","7fKYUulk41","t59lRRpBQm",
-"UmaEvUvlv4","8hJdtJJs5m","yEfy9nFqik","7X3uyWPmlx","0KyfsciuWz","pmeCd2hEEU","jeskSQnJ1S","yofH3zQt6Q","zqH0WFcWrW","pT8wuuN6r3",
-"WMiS329QAz","IRh48pvgjS","hSSvQCqqaD","uN6r3VLTy6","07n1cwiHrZ","5nmWvVLTy6","b29RJ5drc6","LewvMVprf2","mX2GEIn3NS","ni2v1O3iyQ",
-"RkQkexciqp","DQimp5IhmG","kB5nPuJScX","X6PinMaJQs","zHF1qThjNn","7fsYM14FLR","4dEz6yofH3","VNCPdzqH0W","uLtKsFxX9q","M3zXLyvOMI",
-"QbxXcWreyP","nnP8odjsrv","FNYIMMkgy8","jeskSvLsmS","SjskQXyPZN","K4GS85Mg9r","fqypyo8Uyd","FLsphuPX7G","9eoRcU3yw5","uN6r3HlUbF",
-"24ARFFnPFB","tl72W45cIH","0Wr5yXyPZN","n8pJ9i3pyd","Waim6iB08l","0h1b1RkQke","WPmlxAXpwE","lkMUA2DREs","XflUqCfgr3","VIlwPzz4ZU",
-"BFkb8kB5nP","gdQsSS77LH","ZuDtDaFFss","yEfy9F6PT2","Mkgy8KZamH","9XyT9ulk41","W3VFHPOUYS","07n1catef2","iqv4khUTw7","WDVWJn8pJ9",
-"HlUbF3weIF","FFDui5drc6","soy9t7fsYM","WreyPaDGtS","B3qemUlU3M","uvf7AFnPFB","RxrsmgjUTu","DcpWBlweGy","7lUXZlCMxy","WDVWJtlILt",
-"XyPZNCfgr3","FxX9qDcpWB","b29RJqUJMd","M3zXLuupzk","t98iW2hEEU","lj07QUvlv4","Ta8f6580YD","ZzJHWLewvM","48cHLlweGy","FPfSEJRJQB",
-"cL0aEaez9y","pAhR1CK5W7","TXQ0ZprNT6","8RCUAJJs5m","RBhp0x3LDe","BbwgADLhzM","VerEAjSjS3","suY4xpiJSk","EoToPulk41","jeskS1v5hH",
-"AIYUux3LDe","LDk6fBbwgA","RACuj1LB1L","s4786djsrv","8U2nUcmXIX","0h1b1M3zXL","2ZHdkix74r","MojnPdhSuH","Y1mC0s93Ml","soy9tyofH3",
-"OUYuFjSjS3","8cVD3zbIYY","djsrv5Namm","uJScX7fsYM","NOHszprNT6","RzaZAMmsIo","AXpwEvkCHH","WmadA4W0Tl","QnJ1SnFqik","IRh48Mm8si",
-"rz7Utjtn0X","uTacxNo0Qb","JkzUn618Di","UmaEvJXljW","t59lRtaOXK","o8UyddmoS7","brhlQ5Drn0","5iGN5LbRTH","fcJOy9eoRc","ZhwG1v1Hln",
-"QssNCWDVWJ","cQOnvYjB9t","euZA57X3uy","taOXKs7Mxk","7fsYMYf2Ec","iKqhrvkCHH","RzaZA5drc6","ni2v1FxX9q","AOgEeFPfSE","s93MlOz8yZ",
-"M6qcGRxrsm","F6PT20PktI","wDajXChuy3","Dz1R3I7p2a","5Mg9rk85Ae","wiHrZWMiS3","MmsIo9y4lw","CdyBV6q6L9","BpYhVM3zXL","AXpwE9y4lw",
-"16lHcvLsmS","Waim6tuDyS","Nxx9VgdQsS","lj07QjfREu","l83UdkZANm","1j5L8dhSuH","RxrsmVerEA","IBe8k9iGoT","QnJ1SQssNC","FcWrW5nmWv",
-"YjB9tOUqFM","FwEJzZUnqt","a00b5pT8wu","zY1GYuZPqg","O3iyQF6PT2","9iGoTblLA9","JkzUnL7cGc","ydG8UfmIK1","P6bcgNOHsz","SbRYyIBe8k",
-"lsQGoVjCZq","FNYIMRsQUq","5ZaEz8RCUA","he9IAHP433","pv0i7y94nw","JIqXix3LDe","0h1b1JIqXi","VerEAkZANm","gf8rIprNT6","RACujQWxoT",
-"MojnPfFDrJ","taOXKFxX9q","xXTI4JKWYR","taOXK9iGoT","RACujD6rBy","4dEz6dmoS7","FVMxolH1kt","wiHrZBGaQY","LbRTHUvlv4","WMiS3580YD",
-"M3zXLW3VFH","v1HlnAIYUu","7lUXZCqqaD","ThjNnW7cTs","xciqp0Wr5y","jeskS9rlg9","tvdkDUl4a1","uvf7A1j5L8","euZA5Waim6","uTacxa00b5",
-"MaJQsFjHXR","CdyBVY1mC0","8xEKzQbxXc","1v5hHNOHsz","24ARFdjsrv","n8pJ9SjskQ","cQOnv5VZjS","EOE1oguMb8","AOgEeJXljW","QbxXchE1Ql",
-"jeskSpFrrl","uvf7Al83Ud","Nxx9V3weIF","cQOnvM6qcG","uPX7G7fKYU","SmGzvQnJ1S","AkKTkcL0aE","5NammKsjRK","7Ow5CVLTy6","uTacxEoToP",
-"rz7UtWDVWJ","uJScXdmoS7","VIlwPru4UG","NhXdutvdkD","K20wKZ4I1v","8U2nUvkCHH","zbIYYK4GS8","W7cTsJJs5m","BFkb8iKqhr","WMiS33otm6",
-"JkzUnbZLvS","1v5hH5Drn0","ReKEW8hJdt","zz4ZUjiVBP","C2IrcDQimp","t59lRmz8gx","9eoRcrKDLJ","lweGy8TxD7","fcJOy7X3uy","suY4xC2Irc",
-"yluBxxXTI4","JkzUnFGzgp","fLNg8FFDui","aDGtSlCMxy","Chuy3JJs5m","UlU3MZzJHW","uQIczJkzUn","7lUXZGv3Fq","55rfBEoToP","MojnP5nmWv",
-"guMb8MaJQs","9XyT9ix74r","aDGtSMmsIo","pT8wuLewvM","JKWYRCxVEf","v1HlnhYBCK","FcWrWZv7z0","ni2v1Rxrsm","FVMxoI7p2a","DQimpd7vjM",
-"euZA5iwzGk","rhl0JUvlv4","AOgEeXyPZN","guMb8jSjS3","RmDcrQnJ1S","580YDTCgPp","0MR5Xd85a9","aL6AJ6q6L9","s4786yEfy9","ZzJHWnnP8o",
-"LbRTHiB08l","v2eC3uvf7A","yToGWFcWrW","IKxdLgtCA5","v2eC3pFrrl","cQOnvSmGzv","gtCA5MojnP","Z4I1vpiJSk","07n1chSSvQ","YjB9tdpe1v",
-"iwzGkMaJQs","uZPqgd85a9","s93Ml9eoRc","QChxsNo0Qb","X6Pin8hJdt","kB5nPRsQUq","YOfrY9iGoT","580YDwiHrZ","bgJAzChuy3","soy9tvLsmS",
-"CdyBVfmIK1","ReKEWDcpWB","sx5GlY1mC0","ZuDtDqaofN","0PktIbZLvS","1j5L8guMb8","lweGyFGzgp","FLsph3weIF","NhXduSjskQ","RxrsmF6PT2",
-"AXpwEVLTy6","Yh1hF1LB1L","HlUbFOxWIH","qUJMdzqH0W","SjskQGXdoH","fqypyfcwDa","GrDg7pmeCd","Yh1hF9GXkX","XflUqzY1GY","n8pJ95IhmG",
-"brhlQF6PT2","QWxoTVerEA","lViBvIKxdL","tl72WXyPZN","FnPFBGWqqX","OUqFMZzJHW","lweGyNOHsz","1j5L8EOE1o","prNT6uLtKs","24ARFYf2Ec",
-"9eoRcb29RJ","1LB1LNxx9V","fmIK1sx5Gl","OxWIHNo0Qb","NhXduF6PT2","YOfrYaez9y","580YDy94nw","aez9yaL6AJ","D6rBy8xEKz","3otm6jS1aj",
-"6q6L9AgJHQ","iB08lFjHXR","LewvMbrhlQ","XyPZN6AFT0","lCMxy1LB1L","9y4lw7fsYM","2TRI7HRxd8","HlUbF618Di","TCgPpulk41","aDGtSAgJHQ",
-"aDGtSHfyNQ","W3VFHKASQ8","1v5hHt98iW","Y1mC03weIF","4QMc9TCgPp","Cfgr3fcwDa","vkCHH5Drn0","IjTwPAXpwE","Twano4QMc9","BbwgAiwzGk",
-"dpe1vfqypy","uJScXuZPqg","2hEEU9iGoT","L7cGctAOsr","Ul4a1zHF1q","WaWsvM6qcG","cQOnvWaWsv","0YAGHKZamH","3otm6Waim6","AIYUud7vjM",
-"Yh1hFwiHrZ","lm0pDyofH3","y94nwuTacx","QnJ1SXflUq","tAOsrNxx9V","Z4I1vWreyP","No0Qb580YD","EOE1oMGlTF","okgRi8U2nU","64s8Nulk41",
-"FwEJz7lUXZ","D6rBy64s8N","XflUqv1Hln","jfREuOUYuF","guMb8aFFss","In3NSzz4ZU","FLsph5Mg9r","zqH0WjzUqR","580YDbrhlQ","8xEKz7X3uy",
-"zbIYYgjUTu","QChxsC2Irc","RBhp0d85a9","Q6LixuZPqg","SbRYyG1RhS","DQimprhl0J","gjUTuCfgr3","a00b5Vprf2","soy9tuTacx","2Yz7E45cIH",
-"MmKGJzz4ZU","tuDySmX2GE","8TxD7AmdQd","aFFssyvOMI","3otm6taOXK","BbwgAVjCZq","o8Uydxciqp","Vprf2uN6r3","WmadAyluBx","WPmlxprNT6",
-"cQOnvQssNC","RBhp0Chuy3","3otm6mz8gx","brhlQjtn0X","0MR5X16lHc","8hJdtU3yw5","U3yw5yToGW","AXpwEHzZT8","S2DfulpF6W","6q6L97lUXZ",
-"HP4337ku1p","5Mg9rStlDJ","qaofN0Wr5y","Dz1R3QChxs","uZPqgQbxXc","8FmFH45cIH","0MR5X5iGN5","Y1mC0SWfou","tuDySW3VFH","AmdQdI7p2a",
-"tlILtDz1R3","1LB1LYf2Ec","2DREs7Ow5C","ECMvUAOgEe","0BmCy8FmFH","JKWYRlH1kt","ogLgcC2Irc","pvgjSCNHmv","uLtKsS2Dfu","y94nwtlILt",
-"RACujP6bcg","oVQp65ZaEz","OxWIH7lUXZ","AmdQdfcJOy","s93MlpFrrl","55rfBJKWYR","Yf2EcvLsmS","CK5W7n8pJ9","0PktIuoStw","cmXIXCK5W7",
-"IBe8kTa8f6","bgJAzmz8gx","dpe1veuZA5","CNHmviwzGk","bZLvSatef2","i3pyd9XyT9","Y1mC0BCxeC","DLhzMQworu","WPmlxNhXdu","RkQkeUmaEv",
-"hSSvQtlILt","S2DfurKDLJ","tuDyS0BmCy","Yf2EcS77LH","CNHmv0Wr5y","kB5nPiwzGk","Kr8ysZzJHW","3weIFuupzk","okgRi5Drn0","OUYuFgjUTu",
-"P6bcg3otm6","MezSWK20wK","POUYSHlUbF","2DREs6q6L9","HP433X6Pin","5drc6v1Hln","JIqXinlaBy","5iGN5tl72W","CqqaDZv7z0","uvf7AciuWz",
-"bgJAzYh1hF","hYBCKlj07Q","euZA5Zv7z0","S2Dfu4dEz6","FxX9quQIcz","gIYvEFjHXR","e6e4zEoToP","ix74rm4bxU","P6bcg5Drn0","3otm6e6e4z",
-"lXFOBEOE1o","8FmFHksJby","WDVWJPOUYS","RsQUq8cVD3","MaJQsazIWp","48cHLVerEA","TXQ0Z5iGN5","ZUnqt8TxD7","aL6AJfcJOy","AkKTkMaJQs",
-"lkMUAaL6AJ","lCMxyY1mC0","B3qemcL0aE","ogLgcOUqFM","9GXkXFNYIM","lweGyhUTw7","uJScXAOgEe","W3VFHvLsmS","gdQsSy94nw","bgJAzG1RhS",
-"QssNClXFOB","Yf2EcjzUqR","Vprf25Namm","soy9t7fKYU","gtCA5In3NS","ZUnqtM6qcG","ZuDtDB3qem","sx5Gl0ao3l","fcwDaaDGtS","lsQGoCfgr3",
-"suY4xWreyP","G1RhS2DREs","NhXdu3otm6","euZA5KsjRK","RzaZAYOfrY","8cVD3m4bxU","hi5X7uupzk","lweGylm0pD","0YAGH1v5hH","gIYvEXflUq",
-"cQOnvPYBf4","ru4UGIjTwP","lm0pDcL0aE","5drc6uLtKs","9eoRcDLhzM","8TxD7rhl0J","1j5L82Nslm","aFFssCxVEf","M3zXLuLtKs","cmXIX7Ow5C",
-"t98iWzbIYY","jtn0XFcWrW","pAhR1XflUq","fmIK1RmDcr","8U2nUulk41","IjTwPbZLvS","7lUXZx3LDe","2ZHdkU3yw5","Ul4a1WaWsv","RsQUqlkMUA",
-"jzUqRXflUq","Ss0Zuni2v1","v2eC3WDVWJ","pvgjSblLA9","RxrsmNo0Qb","uZPqg8RCUA","gjUTubZLvS","DcpWBCp3mZ","ni2v1jtn0X","uTacxnFqik",
-"YOfrYlkMUA","UlU3MEdBKc","CIShGlCMxy","Ss0ZuW7cTs","cShY2OxWIH","bgJAz8cVD3","KASQ8QChxs","Vprf224ARF","Nxx9V29QAz","s4786iKqhr",
-"Z4I1vuQIcz","Nxx9VwiHrZ","pAhR1580YD","JkzUn6q6L9","0Wr5y4dEz6","WreyPhe9IA","W3VFHAmdQd","iKqhr2ZHdk","DLhzMfFDrJ","O3iyQlm0pD",
-"h1zcHgdQsS","ThjNnFVMxo","0BmCyFFDui","FVMxoD6rBy","Ta8f6Twano","faHirBpYhV","X6PinBCxeC","F6PT2EoToP","zbIYYQ6hMC","tl72W5Drn0",
-"zY1GYt98iW","KASQ8FVMxo","uLtKsEdBKc","dmoS7uAWyp","RBhp0mz8gx","mX2GEd85a9","RkQkeZzJHW","FNYIMs93Ml","ZUnqt4dEz6","x3LDezY1GY",
-"jtn0XvkCHH","07n1cStlDJ","pAhR155rfB","POUYSX6Pin","Ul4a1O3iyQ","zmLYDLDk6f","l83UdzHF1q","8U2nUsx5Gl","ix74r5VZjS","pvgjSuN6r3",
-"QChxsCK5W7","S77LHMojnP","zbIYYMGlTF","EOE1oRmDcr","HzZT8IjTwP","RmDcrMK07Y","yofH3ydG8U","taOXKfcwDa","QChxsWMiS3","pmeCdFcWrW",
-"OxWIHuoStw","gdQsSMaJQs","3otm6cL0aE","h1zcHlj07Q","S2DfupiJSk","ZhwG1rhl0J","hUTw7lm0pD","HzZT8FVMxo","C2IrcjSjS3","WmadACK5W7",
-"guMb8NAFuw","StlDJqQxHP","ciuWzgIYvE","NcICAW3VFH","L7cGcwiHrZ","oQ87rfcJOy","FxX9qn1pmO","Yh1hFNOHsz","aez9yi3pyd","VjCZqAmdQd",
-"5drc6iqv4k","vOqCE8hJdt","2DREsjSjS3","CK5W7G1RhS","AXpwEt59lR","yEfy9YjB9t","4dEz6FjHXR","uLtKsdmoS7","b29RJZzJHW","yofH3d7vjM",
-"t98iWUvlv4","tlILt29QAz","h1zcH7lUXZ","s93MlGrDg7","5Mg9raez9y","pvgjSvOqCE","55rfBgdQsS","rKDLJMGlTF","G1RhSpmeCd","NcICA9XyT9",
-"TCgPpwDajX","0h1b1Nxx9V","1v5hHG1RhS","zqH0WDcpWB","DQimpoGu6x","SjskQgtCA5","7hyVvCK5W7","oGu6x0YAGH","cShY2FcWrW","I7p2atjQxs",
-"ReKEWhSSvQ","BGaQYnnP8o","NcICAVLTy6","Ss0Zus4786","tvdkDAIYUu","yToGWUl4a1","HP433BGaQY","lH1ktcShY2","StlDJzFgtB","ogLgcW3VFH",
-"atef2prNT6","4QMc9s7Mxk","45cIH4W0Tl","FnPFB0YAGH","ZUnqtIjTwP","45cIHMezSW","8cVD3WMiS3","MGlTF2Yz7E","faHirMojnP","0MR5XHfyNQ",
-"K20wKPb1pa","oQ87rk85Ae","s47860MR5X","IKxdL5nmWv","FxX9qpv0i7","e6e4ziB08l","gf8rInFqik","vOqCEB3qem","MK07YIBe8k","rhl0JVjCZq",
-"O3iyQaFFss","CdyBVuQIcz","QWxoTdjsrv","YjB9trKDLJ","iqv4knFqik","he9IA4W0Tl","VerEASbRYy","lweGyQ6hMC","lj07QpFrrl","gjUTu3otm6",
-"Pb1pani2v1","ZhwG1KZamH","ZUnqthYBCK","U3yw5uTacx","hi5X7BCxeC","jSjS3AXpwE","v8yFNzz4ZU","tjQxstvdkD","GSQwjHlUbF","pWiOs55rfB",
-"WDVWJulk41","X6PintjQxs","ni2v1MmsIo","zqH0WK20wK","aez9yo8Uyd","lCMxyix74r","XflUqqUJMd","v1HlnIBe8k","oVQp6JXljW","pv0i7fcJOy",
-"s7Mxkl83Ud","zHF1qpWiOs","dhSuHeuZA5","W3VFHYw2oU","uvf7AlH1kt","OUYuFxciqp","fLNg8xciqp","8FmFHY1mC0","jzUqRQnJ1S","BpYhVKZamH",
-"HRxd8v1Hln","zHF1qRsQUq","lViBvxciqp","5ZaEzs4786","mz8gxuQIcz","U3yw5X6Pin","fqypyLbRTH","jzUqR16lHc","rhl0JMK07Y","iKqhroQ87r",
-"S77LHyofH3","ZzJHWW3VFH","RBhp0lXFOB","UlU3MUvlv4","vOqCEnFqik","yvOMIdhSuH","uJScXs4786","7hyVvyvOMI","aez9y2TRI7","16lHck85Ae",
-"sqVrfoVQp6","k85AeUl4a1","dmoS7AmdQd","ksJby1LB1L","XflUq0h1b1","lH1ktNAFuw","y94nwjSjS3","In3NSzmLYD","FLsphQ6Lix","dmoS7CIShG",
-"tlILtfqypy","DQimpyofH3","QbxXcCNHmv","55rfBGXdoH","XflUqlweGy","soy9tokgRi","uPX7GG1RhS","W7cTsbgJAz","fFDrJ6q6L9","mX2GEsqVrf",
-"Gv3Fq24ARF","ReKEWK20wK","dhSuHSs0Zu","8hJdt0MR5X","3otm6ThjNn","fFDrJhi5X7","cL0aEFPfSE","LewvM64s8N","MmsIoQbxXc","jfREu7X3uy",
-"0Wr5yMGlTF","WreyPRxrsm","vLsmS7Ow5C","MmsIoazIWp","Y1mC0D6rBy","tvdkDblLA9","48cHLGXdoH","mz8gxuoStw","FLsphAgJHQ","I7p2amz8gx",
-"64s8NcL0aE","QssNCDG4sT","uZPqgprNT6","MGlTFYw2oU","StlDJKsjRK","rhl0JzmLYD","yvOMIzz4ZU","9eoRcMm8si","WreyPdpe1v","CqqaDYOfrY",
-"W7cTsgf8rI","QChxs7hyVv","dmoS77ku1p","m4bxUFVMxo","KASQ85iGN5","2ZHdkdpe1v","v1HlnCqqaD","VNCPdVjCZq","soy9tOz8yZ","KASQ8XflUq",
-"7hyVvLewvM","NhXdukB5nP","zz4ZUUmaEv","n1pmOuN6r3","AOgEeCxVEf","GXdoHAkKTk","bgJAzi7WMQ","8hJdtRpBQm","MK07Y4QMc9","h1zcHQYxC0",
-"uvf7AUmaEv","yToGWChuy3","QnJ1SdmoS7","WDVWJJKWYR","uoStwl83Ud","lweGyx3LDe","WMiS3Ss0Zu","LewvM5IhmG","7Ow5C7fKYU","e6e4zlm0pD",
-"dmoS71j5L8","vOqCEStlDJ","ECMvUZ4I1v","TCgPp5nmWv","EdBKclkMUA","4QMc9RACuj","0YAGHazIWp","jtn0XyvOMI","SWfourKDLJ","5ZaEztaOXK",
-"ZJTXHlweGy","nnP8o8cVD3","blLA9yToGW","gIYvEAOgEe","oVQp6SbRYy","1j5L829QAz","atef229QAz","14FLRtl72W","xReecECMvU","fmIK1kZANm",
-"gtCA5QbxXc","s93Ml29QAz","8U2nU5nmWv","5nmWvW7cTs","HfyNQTXQ0Z","OxWIHdpe1v","ulk41Zv7z0","2TRI7MojnP","JJs5mZ4I1v","5nmWvdpe1v",
-"5iGN5FFDui","FcWrWazIWp","ydG8Uni2v1","Cfgr3djsrv","K4GS8LewvM","SWfou3weIF","Oz8yZAIYUu","xReecHRxd8","jzUqRdjsrv","jeskSs7Mxk",
-"ZhwG10Kyfs","AgJHQtvdkD","DG4sTpv0i7","xXTI4xXTI4","0YAGHPb1pa","gf8rIECMvU","DG4sTs93Ml","t98iW1j5L8","i3pydMGlTF","taOXKbgJAz",
-"C2Irc5drc6","aL6AJFGzgp","45cIHcL0aE","8xEKzW3VFH","Vprf2d85a9","iwzGkIRh48","bZLvSMK07Y","tjQxsy94nw","RxrsmnFqik","0PktIatef2",
-"S77LHSWfou","Yf2EcVerEA","pmeCdx3LDe","lkMUAjSjS3","JRJQBM6qcG","9XyT9TCgPp","jfREu8FmFH","5Mg9r9XyT9","Oz8yZulk41","hSSvQyEfy9",
-"VerEAnnP8o","AOgEeI7p2a","K4GS8FNYIM","YOfrYKASQ8","AmdQdRzaZA","TXQ0ZLDk6f","Ta8f6uLtKs","Z4I1vQssNC","F6PT2Dz1R3","OxWIHa00b5",
-"yofH3VIlwP","wDajXwiHrZ","ulk41Chuy3","S2DfuRkQke","atef2faHir","Gv3FqMmKGJ","MezSWQChxs","uoStwSmGzv","2DREskZANm","t98iWRBhp0",
-"JJs5meuZA5","K20wKTCgPp","uvf7AF6PT2","pAhR1FwEJz","6AFT07fKYU","9rlg9ECMvU","brhlQuQIcz","CxVEftl72W","Mm8sivLsmS","QWxoTjtn0X",
-"FFDui3otm6","WmadAOUqFM","prNT6S77LH","Cp3mZrhl0J","SbRYyVprf2","NAFuwzbIYY","gtCA5d85a9","pWiOs8RCUA","guMb8zY1GY","5iGN5WMiS3",
-"IKxdLfmIK1","WMiS3BbwgA","lm0pD0ao3l","SbRYyIn3NS","okgRizHF1q","0MR5X5Mg9r","yluBxAOgEe","uQIczIRh48","55rfB7ku1p","lpF6WfcJOy",
-"VerEAprNT6","e6e4zPOUYS","G1RhSvOqCE","FFDuiUlU3M","8FmFHa00b5","k85AeReKEW","RBhp0MmKGJ","9rlg9pWiOs","HfyNQsuY4x","gdQsSD6rBy",
-"W3VFH0h1b1","8RCUABGaQY","lsQGoCp3mZ","aL6AJlweGy","zHF1qxReec","HfyNQP6bcg","azIWpC2Irc","MmsIolCMxy","vLsmSsqVrf","lkMUAVLTy6",
-"tjQxsyToGW","JXljWJ2mQi","O3iyQl83Ud","C2Ircs7Mxk","IBe8kX6Pin","fFDrJJXljW","QbxXcZ4I1v","Q6hMCOz8yZ","RACuj0YAGH","StlDJJRJQB",
-"ydG8US77LH","JRJQBlXFOB","29QAziKqhr","lweGyuQIcz","Cp3mZAkKTk","faHirQWxoT","ZJTXHD6rBy","0Wr5yCdyBV","ZuDtDM3zXL","5IhmGpWiOs",
-"PYBf4ksJby","BCxeCdpe1v","AOgEeZuDtD","24ARFrhl0J","9XyT9l83Ud","yEfy9DcpWB","zFgtBcL0aE","uAWyp1v5hH","5nmWvt98iW","mX2GEpvgjS",
-"HzZT8pFrrl","L7cGcaFFss","ix74rni2v1","aDGtSk85Ae","blLA9NAFuw","LDk6f5IhmG","Yh1hFRxrsm","Q6hMCatef2","5VZjS3otm6","wiHrZjzUqR",
-"ZJTXHulk41","Chuy3jeskS","JJs5mGSQwj","cL0aEZzJHW","iB08l1v5hH","55rfBCp3mZ","XyPZNlm0pD","wiHrZUl4a1","CdyBVpiJSk","ZuDtDEOE1o",
-"8FmFHgdQsS","JKWYRQ6Lix","uvf7AyluBx","07n1cIRh48","BbwgAGSQwj","FhtglWDVWJ","n8pJ9JXljW","5Mg9rgdQsS","IKxdLEoToP","Uvlv4pvgjS",
-"zbIYYAmdQd","29QAzpWiOs","x3LDeSjskQ","DG4sT7ku1p","nnP8obZLvS","2hEEU9y4lw","GSQwj6q6L9","WMiS3nnP8o","yluBxVerEA","JXljWVerEA",
-"lpF6WpT8wu","ZzJHWVNCPd","NhXduaDGtS","Yh1hF8RCUA","I7p2a0BmCy","I7p2aDz1R3","JXljWuLtKs","Pb1pa3otm6","lViBvjS1aj","BGaQYHRxd8",
-"JJs5m55rfB","VerEAZuDtD","580YDBCxeC","No0QbW3VFH","Zv7z0lkMUA","FhtglQworu","tvdkDQClRL","Yh1hFlCMxy","0MR5XtuDyS","5ZaEzBpYhV",
-"4QMc9CK5W7","580YDDLhzM","sqVrf1v5hH","BFkb8dmoS7","RpBQmaL6AJ","CqqaDs93Ml","wDajXs4786","QssNCNxx9V","FGzgpFwEJz","M6qcGCK5W7",
-"1v5hHpAhR1","ulk41HRxd8","tAOsrAXpwE","AXpwEv1Hln","xReec55rfB","hi5X7zQt6Q","e6e4zh1zcH","DcpWBK20wK","Pb1paQ6hMC","soy9tAmdQd",
-"xXTI4azIWp","VIlwPaL6AJ","soy9tKr8ys","brhlQlCMxy","0PktIMezSW","J2mQix3LDe","9iGoTDz1R3","zz4ZUFcWrW","5VZjSzQt6Q","Q6hMCazIWp",
-"v1HlnhSSvQ","BbwgALewvM","0PktItlILt","P6bcg5IhmG","kB5nPjSjS3","KsjRKoVQp6","OHaBz16lHc","lsQGoVIlwP","Cfgr3Z4I1v","YjB9t7lUXZ",
-"hSSvQydG8U","aFFssRACuj","hUTw764s8N","JkzUn0Wr5y","XflUq3weIF","i3pydhUTw7","d85a9k85Ae","gIYvEuLtKs","64s8N7fsYM","dhSuHtl72W",
-"7X3uyDQimp","8U2nUpiJSk","yvOMI5iGN5","IBe8k5VZjS","7ku1p6q6L9","prNT6QClRL","uvf7A14FLR","JRJQB5Drn0","RkQkeW7cTs","580YDLewvM",
-"Gv3Fqdjsrv","W7cTsk85Ae","2TRI7zQt6Q","U3yw5B3qem","7Ow5CHlUbF","lm0pDd85a9","1v5hH0Kyfs","cShY27Ow5C","SWfou5drc6","Kr8ys7hyVv",
-"bgJAzVprf2","ksJbyJIqXi","RsQUqaFFss","RzaZAoGu6x","ydG8UD6rBy","qaofNM6qcG","jzUqRW7cTs","XyPZN55rfB","JIqXikZANm","ZUnqt1v5hH",
-"aFFssb29RJ","iwzGkPb1pa","8cVD3zQt6Q","m4bxU2Yz7E","zY1GYFnPFB","lXFOBlj07Q","kB5nPuN6r3","Q6LixoGu6x","dpe1vFNYIM","VLTy6dhSuH",
-"LbRTH5VZjS","29QAzaFFss","cShY2ECMvU","O3iyQprNT6","lViBvAmdQd","guMb8JXljW","S77LH0MR5X","OUYuFRkQke","KASQ8fqypy","pv0i78cVD3",
-"aFFsseuZA5","0BmCygjUTu","JKWYRQnJ1S","QbxXcuQIcz","uPX7GVNCPd","xXTI4Gv3Fq","cShY2RsQUq","vkCHHcQOnv","ECMvUVIlwP","FxX9q14FLR",
-"jiVBPv1Hln","sx5GlAmdQd","ogLgct59lR","4QMc9618Di","vkCHHBCxeC","o8UydgIYvE","XyPZNxciqp","m4bxUOUYuF","uJScXfmIK1","zqH0Wd85a9",
-"X6PinpvgjS","xXTI4lCMxy","l83UdVNCPd","HRxd8Mkgy8","YOfrY5VZjS","jfREujtn0X","y94nwVerEA","ZhwG1Oz8yZ","zY1GYHzZT8","Waim60Wr5y",
-"uN6r3JJs5m","ogLgcRpBQm","5nmWvfcwDa","OUYuF07n1c","lViBvDcpWB","FhtglyluBx","OHaBzydG8U","YOfrY8cVD3","Y1mC0HfyNQ","FVMxod85a9",
-"iKqhrzFgtB","8xEKz0h1b1","jeskSRxrsm","rhl0J64s8N","Cp3mZJXljW","EdBKcNhXdu","blLA99XyT9","IjTwPwDajX","7ku1pdQ586","vOqCEFNYIM",
-"NAFuwUl4a1","AIYUuGSQwj","MmKGJHzZT8","uQIczeuZA5","Kr8ysfFDrJ","s7MxkMmsIo","TwanoCdyBV","uAWypK20wK","AIYUuyofH3","jiVBPuAWyp",
-"CIShGiB08l","zHF1qMezSW","K4GS864s8N","IjTwPQworu","1v5hHFxX9q","FcWrWVprf2","GWqqXtjQxs","zbIYYDLhzM","wiHrZHfyNQ","4QMc9In3NS",
-"ogLgcfmIK1","U3yw5Mm8si","0MR5X5IhmG","JXljW9XyT9","CK5W77fsYM","qUJMdPYBf4","NcICAZv7z0","9iGoT8xEKz","BCxeCe6e4z","JJs5mciuWz",
-"FnPFB8xEKz","jtn0X4dEz6","sqVrfnFqik","n1pmOZJTXH","zz4ZUJJs5m","2NslmcL0aE","fLNg8WDVWJ","pmeCdZhwG1","PYBf4lXFOB","CK5W7FwEJz",
-"No0QbgdQsS","8cVD3In3NS","TwanoTwano","JkzUnQClRL","4QMc9Nxx9V","lXFOBnlaBy","ZJTXHRxrsm","s4786uTacx","QbxXcYw2oU","Q6hMCuQIcz",
-"Zv7z0cShY2","kB5nPFxX9q","ZUnqtM3zXL","FNYIMJXljW","ksJbyLbRTH","MmKGJI7p2a","RmDcrjS1aj","uoStwjiVBP","6AFT007n1c","BFkb8n8pJ9",
-"J2mQiSmGzv","I7p2av8yFN","nlaByhSSvQ","GWqqXKsjRK","tvdkDJJs5m","BpYhVdmoS7","5iGN5n1pmO","uvf7Ae6e4z","StlDJ5drc6","xXTI4wiHrZ",
-"TwanoFxX9q","ix74rLDk6f","rhl0JCK5W7","9GXkXOUYuF","hE1QlI7p2a","NAFuwyofH3","i3pydGXdoH","7hyVvgIYvE","pv0i7MmsIo","9rlg9TCgPp",
-"BGaQYMGlTF","Dz1R3fLNg8","ulk41HfyNQ","5NammYh1hF","gIYvEDcpWB","wiHrZOUqFM","KASQ8ulk41","2ZHdksx5Gl","rz7UtLewvM","Z4I1vgjUTu",
-"5Mg9rzY1GY","uPX7GpmeCd","fcJOyB3qem","MojnPuAWyp","W7cTstaOXK","sqVrfTXQ0Z","7Ow5CMaJQs","guMb8EoToP","5NammbrhlQ","uvf7Aulk41",
-"PYBf4v1Hln","uAWypM3zXL","brhlQCIShG","hUTw7DcpWB","9rlg99y4lw","TXQ0ZFxX9q","Cfgr3K4GS8","HP433OxWIH","0YAGHQChxs","AXpwEWmadA",
-"lViBvEdBKc","yofH3S2Dfu","iKqhrFGzgp","pmeCdFFDui","MojnPQ6Lix","5NammpmeCd","2TRI7IjTwP","fqypyzFgtB","QbxXcWPmlx","64s8NvOqCE",
-"NOHszo8Uyd","vOqCEPOUYS","pFrrlYf2Ec","5Drn0Vprf2","FVMxoYw2oU","2Nslmdpe1v","FVMxok85Ae","5IhmGpT8wu","cmXIX45cIH","Oz8yZLDk6f",
-"L7cGcpT8wu","Chuy3zbIYY","a00b50ao3l","7hyVv8FmFH","a00b5zFgtB","7fKYUQWxoT","MmKGJydG8U","tl72Wdjsrv","618Di6q6L9","JKWYR8U2nU",
-"qUJMdMojnP","yluBx5Mg9r","UmaEvQssNC","pT8wuBGaQY","IKxdLd7vjM","fcJOy0BmCy","Nxx9VMojnP","aFFss64s8N","8TxD7UmaEv","ZJTXHh1zcH",
-"C2Irclm0pD","fLNg8o8Uyd","oGu6xKsjRK","qaofNo8Uyd","6q6L9fLNg8","UmaEvS77LH","SmGzvo8Uyd","zqH0WQWxoT","7lUXZ5VZjS","Q6hMC5Drn0",
-"5iGN5AXpwE","RmDcrkZANm","618DioGu6x","W3VFH0BmCy","JIqXiAgJHQ","Ul4a1ThjNn","vLsmSCNHmv","5nmWv55rfB","lkMUAgdQsS","CqqaD0Wr5y",
-"tjQxs9GXkX","9XyT9pAhR1","PYBf4l83Ud","JJs5mZJTXH","FhtglfmIK1","Gv3FqgjUTu","ix74r6q6L9","3otm67X3uy","5NammUmaEv","lweGy618Di",
-"VBjhz7ku1p","618DiHlUbF","d85a9uTacx","7fKYUUlU3M","0PktITa8f6","AgJHQjiVBP","UlU3MJXljW","euZA5VjCZq","wiHrZguMb8","Twano9iGoT",
-"HzZT8pAhR1","7hyVvjfREu","QWxoTdQ586","tAOsrpvgjS","VjCZqZzJHW","K4GS8SjskQ","pT8wuWPmlx","UlU3MQWxoT","XflUqXflUq","AmdQdogLgc",
-"VjCZqFcWrW","KASQ8AmdQd","8U2nUyvOMI","Q6hMCjeskS","9rlg9CK5W7","aFFsshUTw7","l83UdTCgPp","2NslmZ4I1v","FhtgllweGy","uN6r3BCxeC",
-"Oz8yZ8xEKz","k85AeaL6AJ","MGlTFBGaQY","uPX7GCfgr3","tlILtqQxHP","Yh1hF6q6L9","lj07QhE1Ql","AmdQdReKEW","2DREsAkKTk","DcpWBVLTy6",
-"soy9tJ2mQi","Ss0ZucQOnv","64s8Ntl72W","fcwDatvdkD","dpe1v1LB1L","jtn0XDz1R3","brhlQHlUbF","7fKYU6q6L9","RkQkelweGy","AgJHQxXTI4",
-"5iGN5EoToP","VIlwPwiHrZ","D6rBya00b5","S2DfuDcpWB","8hJdtVLTy6","8cVD3rKDLJ","CK5W7yofH3","oVQp6jzUqR","n8pJ9k85Ae","VjCZqe6e4z",
-"o8UydlCMxy","MGlTF2ZHdk","qaofNZhwG1","uLtKsHfyNQ","i3pydgdQsS","mz8gxMojnP","atef2DcpWB","1LB1Lulk41","FjHXRCfgr3","VNCPdlViBv",
-"zHF1qEdBKc","k85AeiB08l","s93MlJKWYR","cQOnvVIlwP","vLsmSD6rBy","prNT6FNYIM","8hJdt7lUXZ","QClRL8FmFH","HRxd8gIYvE","MaJQsQClRL",
-"1j5L8Q6Lix","9iGoTuvf7A","wDajX5Drn0","jS1ajuvf7A","HzZT8uTacx","pvgjSfcJOy","hSSvQuoStw","9y4lwv2eC3","y94nwBpYhV","guMb80Kyfs",
-"zz4ZUCNHmv","64s8NIKxdL","WPmlxRxrsm","7X3uyjiVBP","KASQ8FwEJz","jSjS3HzZT8","24ARFzbIYY","x3LDe0MR5X","HfyNQ7X3uy","v2eC3uAWyp",
-"h1zcHBpYhV","3weIFtAOsr","WPmlxG1RhS","lViBvRmDcr","bgJAz1LB1L","3otm6MGlTF","FVMxoVerEA","soy9tEOE1o","No0QbuJScX","RxrsmAkKTk",
-"SjskQuoStw","hE1Qliqv4k","lXFOBaL6AJ","Waim6bZLvS","OHaBzhYBCK","piJSk0ao3l","aL6AJQ6hMC","djsrv580YD","QnJ1SFPfSE","1j5L8jSjS3",
-"AOgEeuAWyp","Q6LixzbIYY","5drc6yEfy9","VLTy60BmCy","nFqik8cVD3","29QAzD6rBy","MmsIob29RJ","AXpwEfcJOy","dpe1vMmKGJ","dmoS7t98iW",
-"14FLRVerEA","5nmWvIKxdL","nFqik16lHc","ksJbyyToGW","5drc6TXQ0Z","soy9tuvf7A","FGzgplm0pD","Vprf2faHir","NhXduzFgtB","GrDg7FFDui",
-"AIYUuFVMxo","KsjRKZUnqt","Q6LixcmXIX","7fKYUtaOXK","I7p2a29QAz","lCMxyt59lR","aDGtSaFFss","aFFssgIYvE","WDVWJe6e4z","8U2nUuoStw",
-"AOgEe9eoRc","StlDJWDVWJ","o8UydcQOnv","ix74r8U2nU","MezSWLbRTH","1LB1LAIYUu","rhl0JmX2GE","ECMvUFVMxo","0PktIVprf2","7fKYUDQimp",
-"hYBCKNxx9V","euZA5tvdkD","WaWsvHzZT8","Nxx9V0Wr5y","5nmWvDz1R3","6AFT0jSjS3","LewvMNxx9V","QChxs6q6L9","SmGzvOUYuF","QbxXc2hEEU",
-"VIlwPJkzUn","uoStwpiJSk","RmDcr1j5L8","fLNg8CK5W7","qUJMdhSSvQ","jtn0XuAWyp","rKDLJix74r","TXQ0ZuLtKs","9rlg9HP433","Cfgr3M6qcG",
-"QssNCTCgPp","uupzky94nw","iqv4k8TxD7","suY4xVNCPd","aez9y0YAGH","ulk41aFFss","jiVBP1v5hH","dmoS7tl72W","RBhp0fLNg8","QWxoTnlaBy",
-"I7p2aqaofN","rz7UtxReec","d7vjMzmLYD","jS1ajprNT6","WreyPvOqCE","0YAGH5nmWv","29QAzL7cGc","5NammRmDcr","1j5L8DLhzM","vOqCEtuDyS",
-"MmKGJQ6hMC","qQxHP0YAGH","oVQp6IKxdL","fFDrJblLA9","fcwDa16lHc","TXQ0ZqaofN","fmIK1VjCZq","BbwgA55rfB","EOE1ovkCHH","K20wKzz4ZU",
-"VjCZqM3zXL","qQxHPDLhzM","iwzGkKASQ8","s93MljS1aj","Yf2EcoGu6x","oQ87rv2eC3","yvOMIKsjRK","FnPFBciuWz","ciuWzlkMUA","uLtKsCdyBV",
-"1v5hHxReec","MmKGJX6Pin","soy9tJRJQB","29QAzTXQ0Z","BbwgAsuY4x","ZhwG1iB08l","WmadAECMvU","cmXIX1LB1L","P6bcgwDajX","8U2nUkZANm",
-"oQ87rulk41","X6PinuZPqg","a00b5TCgPp","atef2aDGtS","zmLYDaFFss","Uvlv4i3pyd","KZamHbrhlQ","SWfouChuy3","CIShGFhtgl","ksJbyTwano",
-"fLNg824ARF","iqv4kTXQ0Z","FFDuiMkgy8","rz7UtK4GS8","PYBf4o8Uyd","lViBvl83Ud","aL6AJTCgPp","b29RJ2Yz7E","24ARFTXQ0Z","RzaZAVLTy6",
-"k85AeJKWYR","brhlQksJby","RBhp0pWiOs","lkMUAl83Ud","ZzJHWyvOMI","qaofN2Yz7E","GSQwjyluBx","fqypyZUnqt","2DREstl72W","cQOnvlm0pD",
-"lCMxywDajX","JkzUnazIWp","pvgjS9iGoT","ZJTXHQYxC0","NAFuwdpe1v","TCgPp1v5hH","Yf2EcAmdQd","n1pmOJXljW","dpe1vm4bxU","okgRijSjS3",
-"DQimp3otm6","kZANmEdBKc","he9IA5iGN5","HzZT8Z4I1v","2DREs7fKYU","blLA9Vprf2","G1RhSWaim6","hSSvQKZamH","tvdkDYh1hF","nFqik2Nslm",
-"D6rByfFDrJ","K4GS8LbRTH","GSQwjRBhp0","Ss0Zuiqv4k","HRxd8pT8wu","tl72WazIWp","IKxdLUvlv4","QworuOUqFM","HfyNQAgJHQ","RzaZAt59lR",
-"fLNg8zbIYY","8hJdtO3iyQ","WmadAVBjhz","2Nslm3otm6","LbRTHKZamH","yEfy95VZjS","CqqaDOz8yZ","9iGoTRsQUq","jeskStlILt","HfyNQzqH0W",
-"FxX9qIn3NS","Z4I1vuoStw","IjTwPrz7Ut","JJs5mJJs5m","RpBQm1v5hH","suY4xNhXdu","blLA9RkQke","Kr8ysjzUqR","pAhR1ZuDtD","DcpWBpAhR1",
-"2DREsMojnP","Nxx9VECMvU","Kr8yss7Mxk","FwEJzHRxd8","B3qem7Ow5C","HfyNQRpBQm","zz4ZUt98iW","L7cGcxReec","5iGN5i3pyd","2DREsKASQ8",
-"0MR5Xl83Ud","blLA9v2eC3","oGu6xD6rBy","fcwDai7WMQ","TXQ0ZQ6hMC","uLtKsnFqik","QWxoTzHF1q","0PktIiKqhr","OUYuF55rfB","K4GS8PYBf4",
-"AXpwEQnJ1S","fcJOy2TRI7","suY4xgtCA5","U3yw5C2Irc","0BmCyuZPqg","hSSvQYf2Ec","Ss0ZuhUTw7","FjHXRAkKTk","Q6hMCQYxC0","Vprf2v1Hln",
-"m4bxUn1pmO","7hyVvzz4ZU","gIYvESbRYy","brhlQpv0i7","CK5W7AIYUu","RBhp0W7cTs","9y4lwCxVEf","4dEz6uQIcz","7lUXZFhtgl","WmadAJXljW",
-"uupzkprNT6","55rfB2hEEU","ogLgciB08l","djsrvuoStw","D6rByqQxHP","EdBKctjQxs","sqVrfPYBf4","JJs5miB08l","QYxC0JKWYR","NAFuwhUTw7",
-"tvdkDFNYIM","rKDLJ0BmCy","5Namm5Mg9r","gjUTuksJby","6AFT0taOXK","SWfou9y4lw","xciqpvkCHH","EoToP0MR5X","9GXkXVerEA","5nmWvVjCZq",
-"uPX7G5VZjS","45cIHGv3Fq","jiVBPpmeCd","F6PT2Cfgr3","oQ87r8cVD3","QYxC0UlU3M","7Ow5Cn1pmO","m4bxUbZLvS","OHaBzY1mC0","sx5GlWMiS3",
-"9XyT9aL6AJ","Oz8yZqQxHP","jS1aj8xEKz","rhl0Jaez9y","Kr8ysIjTwP","jiVBP7fKYU","lweGylXFOB","jiVBPuPX7G","yEfy9MezSW","7fsYM07n1c",
-"hUTw7uupzk","jeskShE1Ql","NhXdufcwDa","FxX9qcL0aE","Dz1R3dmoS7","WreyPzqH0W","suY4x2Nslm","48cHLStlDJ","n1pmOl83Ud","WaWsvnlaBy",
-"Ta8f6aez9y","uZPqgIBe8k","rz7UtTwano","x3LDeRsQUq","Gv3FqMGlTF","djsrvbgJAz","brhlQi7WMQ","B3qemlweGy","Rxrsm7fsYM","KASQ8lpF6W",
-"0h1b1AmdQd","4W0TlfLNg8","OUqFMSWfou","yEfy97X3uy","QYxC00Kyfs","RsQUqlViBv","0ao3laL6AJ","LDk6fJKWYR","2NslmCK5W7","suY4xix74r",
-"lpF6WpiJSk","e6e4zNo0Qb","oQ87rW3VFH","D6rByWPmlx","piJSkQClRL","sqVrfF6PT2","dQ586iKqhr","NOHsz7lUXZ","ThjNnlsQGo","TwanoQssNC",
-"0Kyfs1LB1L","pWiOs1v5hH","8hJdtGv3Fq","lweGyoQ87r","Gv3FqQChxs","6q6L95drc6","0BmCyuTacx","In3NS5iGN5","MezSW9XyT9","fcJOyCK5W7",
-"x3LDelViBv","8U2nUM3zXL","9GXkXtl72W","zbIYYBbwgA","W3VFHS77LH","MmsIoWaWsv","Ta8f6JkzUn","8U2nUNhXdu","kB5nPs4786","NhXdupiJSk",
-"WMiS3RpBQm","t59lRMmsIo","y94nwe6e4z","cmXIXcL0aE","8xEKzTa8f6","tl72Ws4786","FNYIMpmeCd","MmKGJlsQGo","No0Qbv2eC3","S2Dfu5Mg9r",
-"EOE1oM3zXL","7hyVvNxx9V","yofH3StlDJ","oVQp6WreyP","8U2nUhYBCK","hE1QlWDVWJ","S2Dfuru4UG","vLsmSUl4a1","MGlTFoVQp6","QnJ1SIRh48",
-"uupzkogLgc","blLA9rhl0J","2ZHdk5nmWv","v2eC3uLtKs","ulk41Uvlv4","EdBKcQ6Lix","3otm62DREs","pWiOsHzZT8","IjTwPnlaBy","2Yz7E16lHc",
-"euZA5Yh1hF","oVQp6fqypy","a00b5POUYS","ReKEWO3iyQ","pmeCddQ586","iKqhrnFqik","0BmCyfcJOy","FNYIMgf8rI","0ao3lOxWIH","blLA9Chuy3",
-"v8yFN618Di","Yw2oUt59lR","PYBf4ZJTXH","FFDuiJkzUn","ZuDtDtuDyS","yluBxtl72W","9y4lwS2Dfu","TCgPp0Wr5y","nFqikIRh48","pWiOs8TxD7",
-"L7cGcAOgEe","lm0pD2TRI7","jfREuRzaZA","BFkb8Fhtgl","DLhzMuAWyp","LbRTHS2Dfu","YjB9tbZLvS","rhl0JCxVEf","vLsmSMezSW","l83UdmX2GE",
-"euZA54dEz6","8RCUAK20wK","Yw2oUHlUbF","Waim6FwEJz","G1RhSlj07Q","CqqaDVNCPd","aL6AJCqqaD","dpe1vMmsIo","ni2v1nFqik","UlU3MCK5W7",
-"8RCUA29QAz","OxWIHBbwgA","3otm6KZamH","3otm645cIH","WmadAYw2oU","aFFsspT8wu","l83Ud64s8N","Kr8ysUvlv4","tvdkDBbwgA","Kr8ysmX2GE",
-"FFDuiXyPZN","X6PinwiHrZ","vkCHHfmIK1","I7p2an1pmO","djsrv5iGN5","mX2GEIKxdL","K4GS84dEz6","0h1b1X6Pin","yofH35nmWv","5nmWv0Kyfs",
-"h1zcHpAhR1","gjUTuiwzGk","Mkgy87X3uy","AOgEehSSvQ","b29RJZUnqt","MmsIo8RCUA","FVMxooQ87r","8U2nUECMvU","uvf7AKZamH","aL6AJv1Hln",
-"BbwgAmz8gx","h1zcHjiVBP","nnP8ot98iW","48cHLJXljW","VBjhzQssNC","v8yFNsqVrf","tjQxsgdQsS","ix74r1LB1L","CqqaDMmsIo","8U2nU7lUXZ",
-"oVQp6pvgjS","YOfrY580YD","P6bcgaez9y","1j5L8CIShG","WMiS3lj07Q","SmGzva00b5","OUYuFnFqik","YOfrYSWfou","4QMc9aez9y","lH1ktECMvU",
-"fLNg8RzaZA","WaWsvwiHrZ","5Drn0mz8gx","Y1mC0pAhR1","5IhmGXflUq","iqv4kUlU3M","uLtKsk85Ae","iB08ly94nw","taOXKAkKTk","Chuy35drc6",
-"faHirWmadA","OxWIH0h1b1","cmXIX7ku1p","VLTy61v5hH","BFkb85VZjS","fLNg8uN6r3","JXljW8xEKz","8xEKzTwano","EoToPMaJQs","GWqqXsoy9t",
-"MmKGJZzJHW","2hEEUaDGtS","DG4sT0Wr5y","pAhR1Nxx9V","5iGN5jfREu","2TRI7Ss0Zu","suY4xtaOXK","lweGyqQxHP","7hyVv0Wr5y","pvgjS0Kyfs",
-"a00b5LDk6f","faHirjSjS3","Yh1hFqUJMd","wiHrZYOfrY","rhl0JgIYvE","QssNCokgRi","8U2nUh1zcH","pmeCdi7WMQ","XflUqVerEA","xciqpl83Ud",
-"JIqXii7WMQ","tvdkDzY1GY","I7p2aWDVWJ","gf8rIVBjhz","tAOsrFjHXR","G1RhSv8yFN","0BmCyMmsIo","7fsYMQ6Lix","okgRiW7cTs","EOE1oy94nw",
-"brhlQyofH3","lsQGoQ6Lix","CqqaDAOgEe","9rlg9kZANm","uTacxlViBv","SjskQiqv4k","ix74rhUTw7","JXljWbgJAz","FLsphatef2","8xEKz7ku1p",
-"Mm8sitvdkD","ThjNnWmadA","16lHctuDyS","jzUqRuZPqg","v8yFNG1RhS","MaJQsVIlwP","WDVWJdjsrv","piJSkgf8rI","2TRI7Vprf2","MojnPThjNn",
-"uAWypt59lR","uN6r3CNHmv","jiVBPoGu6x","Mkgy8BbwgA","No0Qb5Namm","zQt6Qv2eC3","hUTw7StlDJ","zmLYDAgJHQ","3otm6WreyP","azIWphE1Ql",
-"s93MldQ586","euZA5618Di","W3VFHzqH0W","F6PT2a00b5","QbxXcfaHir","jSjS3In3NS","Gv3FqW3VFH","MojnP7fKYU","xciqpFLsph","prNT6gjUTu",
-"RxrsmprNT6","IBe8kjzUqR","ciuWzi7WMQ","y94nwKsjRK","vOqCElViBv","aL6AJt98iW","nlaByksJby","Vprf2wiHrZ","RmDcrHfyNQ","OUYuFlkMUA",
-"Oz8yZECMvU","iqv4ks93Ml","ZuDtDdpe1v","RACujWPmlx","jSjS32Nslm","t98iW7fsYM","FLsphKASQ8","he9IAWreyP","jSjS3TCgPp","ogLgcPYBf4",
-"GSQwj580YD","iqv4keuZA5","aL6AJlm0pD","FxX9qKZamH","DLhzMUvlv4","L7cGcs4786","WreyP8TxD7","nlaByVBjhz","uN6r38cVD3","1v5hH0BmCy",
-"JJs5mMmKGJ","azIWp3otm6","Ul4a1tuDyS","ReKEWqQxHP","Waim6fFDrJ","CIShGFcWrW","iwzGkaFFss","HRxd82Nslm","K4GS8cL0aE","K4GS8MmsIo",
-"IRh48BCxeC","QWxoTbrhlQ","FcWrWRkQke","nlaByLDk6f","IRh48StlDJ","b29RJVjCZq","1LB1L8U2nU","RBhp0618Di","RzaZApFrrl","oGu6xmX2GE",
-"DLhzMeuZA5","AkKTkpT8wu","KASQ8tjQxs","W3VFHbgJAz","ZhwG1IRh48","lm0pDF6PT2","d85a9618Di","tuDySTwano","ix74roGu6x","iKqhr9XyT9",
-"l83UdpFrrl","CdyBVblLA9","CdyBVRsQUq","iKqhrM3zXL","TCgPpdQ586","aFFsss7Mxk","d7vjMNcICA","dpe1vDG4sT","CIShGeuZA5","aDGtSQworu",
-"ulk41Y1mC0","8RCUARpBQm","KsjRKB3qem","HlUbFDG4sT","s47865iGN5","7X3uyi3pyd","7hyVvlCMxy","aL6AJ0ao3l","FhtglOz8yZ","4dEz6tlILt",
-"lweGys4786","9XyT9cQOnv","lCMxycQOnv","ECMvUMK07Y","v2eC3fFDrJ","W3VFHCK5W7","v1Hln0PktI","bZLvShYBCK","lkMUA29QAz","yofH35VZjS",
-"W3VFHWaim6","618DiIRh48","HRxd8faHir","uQIczcQOnv","EdBKcgdQsS","W7cTs7lUXZ","h1zcHVNCPd","lXFOBy94nw","BGaQY2TRI7","k85Aeaez9y",
-"GrDg7NAFuw","StlDJQChxs","mz8gxpiJSk","ZUnqtK20wK","2ZHdkgtCA5","aFFssLbRTH","Waim6nlaBy","azIWpAkKTk","WMiS3a00b5","uLtKshYBCK",
-"JIqXiuN6r3","aez9y0PktI","MmsIo0Kyfs","1j5L8Yh1hF","RsQUqWreyP","iKqhrlm0pD","7Ow5CxReec","QWxoTVIlwP","zY1GYOUYuF","ZhwG1MK07Y",
-"ulk41Yf2Ec","bZLvSpT8wu","fmIK1gIYvE","UmaEv0ao3l","B3qemJXljW","QbxXchYBCK","ZuDtDvLsmS","MK07Y2hEEU","nlaBymX2GE","Q6hMCfaHir",
-"DG4sT9rlg9","MmsIoMkgy8","3weIF8TxD7","GXdoHtAOsr","ZhwG1Ta8f6","fmIK1taOXK","QClRLqUJMd","U3yw5CIShG","qQxHPlsQGo","BCxeCReKEW",
-"Cp3mZIjTwP","bgJAzW7cTs","jtn0XMGlTF","a00b5pAhR1","L7cGcQ6hMC","lViBvMm8si","RzaZA3weIF","AOgEev8yFN","pWiOsFLsph","zHF1qFnPFB",
-"1v5hHStlDJ","QnJ1SL7cGc","guMb8VjCZq","a00b5HP433","GXdoHaDGtS","LewvMdQ586","IRh488cVD3","v2eC3GXdoH","QnJ1SqaofN","Vprf2HzZT8",
-"hUTw7dpe1v","I7p2a2TRI7","nFqiky94nw","MmKGJAIYUu","ru4UGcmXIX","IRh48QClRL","dpe1vbrhlQ","9XyT9zmLYD","s7Mxk24ARF","2NslmOz8yZ",
-"BpYhVQChxs","wDajXS2Dfu","HzZT88hJdt","QnJ1SVNCPd","v1Hln0ao3l","Gv3Fqs4786","Cfgr355rfB","45cIHrKDLJ","EOE1o64s8N","Dz1R31LB1L",
-"HlUbFBGaQY","EdBKchE1Ql","2DREsfaHir","0YAGHBbwgA","7fsYMVIlwP","s4786i7WMQ","nFqikPYBf4","CxVEfMaJQs","d7vjMtuDyS","DG4sTRxrsm",
-"aFFsszY1GY","MmsIoNOHsz","ksJbypAhR1","5VZjSgIYvE","BGaQYQClRL","JKWYRuTacx","lXFOBKZamH","xciqp5iGN5","LewvMv8yFN","tvdkDGXdoH",
-"yToGW0ao3l","0YAGHwDajX","No0Qb6q6L9","i7WMQUmaEv","IRh480Wr5y","sx5GlOz8yZ","rz7Ut7lUXZ","fcwDaJIqXi","l83UdFGzgp","8hJdtQChxs",
-"iB08lCxVEf","8FmFHazIWp","uJScXhUTw7","jtn0X3weIF","SjskQuupzk","ni2v1UmaEv","cmXIX1j5L8","fcJOyCqqaD","ZzJHWhSSvQ","jeskSpv0i7",
-"iwzGkM6qcG","dpe1vtvdkD","zQt6QAmdQd","t98iWUl4a1","Rxrsm8FmFH","FNYIMn1pmO","tAOsr5drc6","guMb8bZLvS","8cVD3FGzgp","uvf7AlXFOB",
-"WMiS3EoToP","VBjhzMmKGJ","IRh48WmadA","faHirQworu","pmeCdtaOXK","8U2nU9GXkX","xciqpFjHXR","v1HlnfcwDa","suY4xPYBf4","ix74rfLNg8",
-"wiHrZuvf7A","8TxD7uPX7G","sqVrfpAhR1","tlILtMK07Y","0h1b1iKqhr","S77LHjiVBP","5nmWvsuY4x","nnP8o1j5L8","hSSvQ7X3uy","TXQ0ZdhSuH",
-"Mkgy8lsQGo","5drc62DREs","i7WMQFGzgp","WPmlxIBe8k","Yh1hFQ6Lix","EdBKcWmadA","FVMxoDQimp","ZUnqtFVMxo","HP433oQ87r","MK07Ypv0i7",
-"Waim6WmadA","kZANmdhSuH","lkMUAy94nw","i3pyduLtKs","fqypylCMxy","ksJbyHlUbF","uLtKs3weIF","Yw2oUIBe8k","nnP8oZv7z0","SbRYyAgJHQ",
-"ru4UG1j5L8","Zv7z00Wr5y","l83UdNAFuw","IjTwPs93Ml","v1Hlnru4UG","GXdoH9GXkX","CdyBV1LB1L","Uvlv4zQt6Q","kZANmBGaQY","jeskSFnPFB",
-"NOHszAgJHQ","nnP8o8U2nU","9y4lwrhl0J","cL0aEogLgc","ix74rvkCHH","zQt6QguMb8","HP4335iGN5","AXpwEFVMxo","0MR5XuZPqg","uQIcz7hyVv",
-"qQxHPazIWp","VNCPdNxx9V","fqypyFFDui","DLhzMEOE1o","I7p2azmLYD","VerEAlm0pD","gdQsSCxVEf","7hyVvK20wK","sx5GliB08l","uoStw6q6L9",
-"CdyBVvkCHH","RBhp09GXkX","VLTy6b29RJ","AgJHQI7p2a","2hEEUFVMxo","gf8rIVjCZq","pmeCdn1pmO","VjCZqpFrrl","gtCA55VZjS","C2Irc0PktI",
-"Uvlv40MR5X","AmdQdGSQwj","F6PT2GXdoH","JJs5mChuy3","Yf2EcSs0Zu","Ul4a1t98iW","FNYIMZuDtD","3weIFD6rBy","JIqXijiVBP","lkMUAOxWIH",
-"gtCA5fqypy","pWiOs8hJdt","qUJMdjiVBP","OUqFMJ2mQi","In3NSFPfSE","MezSWs7Mxk","fLNg8fcwDa","BpYhVgIYvE","dhSuHdhSuH","yvOMIMm8si",
-"blLA9iwzGk","a00b5bgJAz","oGu6xWaim6","oVQp648cHL","55rfBlj07Q","MmsIogjUTu","aL6AJpAhR1","16lHcHlUbF","EOE1oMK07Y","Fhtgln1pmO",
-"JXljWJJs5m","AkKTk7fKYU","M6qcGJRJQB","FcWrWIBe8k","CqqaDhSSvQ","jS1ajsoy9t","64s8NP6bcg","WaWsvWDVWJ","9rlg9pvgjS","HfyNQYw2oU",
-"okgRifqypy","W7cTsPb1pa","qaofNy94nw","Nxx9V580YD","pmeCd1LB1L","atef2IBe8k","FwEJzzHF1q","Ta8f6Yh1hF","zqH0WgtCA5","DcpWB618Di",
-"KASQ8S2Dfu","xciqpECMvU","SbRYyaL6AJ","QClRLWPmlx","dQ586cQOnv","lweGyRBhp0","UmaEvMojnP","BpYhVazIWp","euZA5FLsph","WreyPFPfSE",
-"WmadAsqVrf","Gv3FqhSSvQ","In3NSB3qem","55rfBzqH0W","prNT6MmKGJ","2Nslm2Nslm","pvgjSuQIcz","lweGyHP433","45cIH7fKYU","TCgPpSWfou",
-"7lUXZFPfSE","iKqhr2DREs","vkCHH5drc6","zmLYDTa8f6","brhlQwiHrZ","oQ87r7ku1p","5ZaEz0MR5X","W3VFHJkzUn","5VZjSD6rBy","8RCUAogLgc",
-"M3zXLI7p2a","16lHcpAhR1","lViBvlm0pD","pFrrlM6qcG","zz4ZUx3LDe","LDk6fW7cTs","7fsYMGv3Fq","RBhp0rKDLJ","blLA9Fhtgl","AXpwEFNYIM",
-"2Nslm24ARF","O3iyQ5Mg9r","5IhmGydG8U","d7vjMuupzk","Cfgr3QYxC0","580YDoGu6x","RACujFVMxo","zbIYYzz4ZU","Nxx9VX6Pin","zQt6QnnP8o",
-"zqH0WPb1pa","nFqikx3LDe","580YD6q6L9","jSjS3580YD","AkKTkTa8f6","FGzgpCxVEf","v8yFNh1zcH","aez9y45cIH","kZANm2Nslm","MmsIod85a9",
-"FGzgppiJSk","taOXK5Mg9r","Ss0ZulweGy","BCxeCazIWp","RzaZAnnP8o","Waim6oVQp6","FwEJzi3pyd","cShY29XyT9","dQ586rKDLJ","iqv4kU3yw5",
-"dhSuHUl4a1","fqypyVprf2","m4bxU5nmWv","dpe1v5Namm","MezSWGWqqX","5VZjSXflUq","vkCHHCfgr3","2DREsAmdQd","KsjRKL7cGc","iqv4kdpe1v",
-"jiVBPSjskQ","e6e4zsuY4x","tuDySzz4ZU","n1pmOPOUYS","qUJMdsx5Gl","bZLvSZ4I1v","i3pydt59lR","LewvMi3pyd","OUqFMyvOMI","jS1ajeuZA5",
-"Ta8f6sx5Gl","FVMxoPb1pa","2hEEUFPfSE","kB5nPaL6AJ","rz7UtSWfou","pAhR1ni2v1","pT8wudjsrv","UmaEvWaWsv","AIYUuIKxdL","taOXKpv0i7",
-"U3yw5t98iW","Yw2oUHzZT8","4QMc9jzUqR","bgJAzTa8f6","nFqikOUYuF","tl72WzHF1q","Uvlv4NAFuw","vOqCE16lHc","J2mQiF6PT2","GrDg7nFqik",
-"WDVWJ14FLR","aL6AJazIWp","IBe8kzmLYD","IBe8kpFrrl","07n1cDG4sT","CdyBVm4bxU","KsjRK6q6L9","L7cGc0Kyfs","WMiS3fmIK1","14FLRi3pyd",
-"8xEKzGrDg7","atef2Rxrsm","oVQp6kZANm","WDVWJMojnP","vLsmSIKxdL","v1HlnRBhp0","d85a90h1b1","OUqFMS77LH","s7MxkG1RhS","lH1ktSbRYy",
-"5ZaEzcL0aE","2ZHdkydG8U","Zv7z07lUXZ","0KyfsQssNC","djsrv24ARF","lsQGofcwDa","djsrvNhXdu","2TRI7brhlQ","6q6L94QMc9","RsQUq9y4lw",
-"jzUqRM6qcG","F6PT2BpYhV","Chuy34dEz6","JXljWokgRi","Z4I1v4W0Tl","jzUqR1LB1L","SWfoubgJAz","tl72WJkzUn","aDGtS6AFT0","SWfouQChxs",
-"v8yFNCp3mZ","CNHmvm4bxU","F6PT2l83Ud","ciuWztuDyS","Vprf2ydG8U","0h1b1DcpWB","Waim6tlILt","07n1cP6bcg","cQOnvoQ87r","L7cGcjiVBP",
-"ru4UGzz4ZU","zQt6QX6Pin","dQ586zQt6Q","ksJbyZ4I1v","hi5X7AIYUu","he9IAgIYvE","IRh48BbwgA","t98iWsx5Gl","gjUTurhl0J","lweGyatef2",
-"FxX9qeuZA5","XyPZNNxx9V","WaWsvRpBQm","MojnPaDGtS","TCgPpD6rBy","NhXduJKWYR","580YDAgJHQ","IKxdLI7p2a","h1zcHS77LH","No0QbOUYuF",
-"i7WMQl83Ud","rz7Uts7Mxk","D6rByFcWrW","64s8NMGlTF","fLNg8wiHrZ","EOE1oQClRL","ulk41dhSuH","24ARF6AFT0","9eoRcAgJHQ","blLA9oVQp6",
-"GWqqXaez9y","PYBf4Fhtgl","5VZjSlm0pD","FjHXRW7cTs","uvf7A0MR5X","zqH0Ws93Ml","WPmlxtl72W","IjTwPVLTy6","k85AeDLhzM","7lUXZP6bcg",
-"VLTy6AXpwE","580YDMkgy8","KASQ8lCMxy","W3VFHFnPFB","45cIHFjHXR","7fsYMzHF1q","iqv4kFPfSE","mX2GEPYBf4","MezSWDz1R3","AmdQdfaHir",
-"SmGzvTXQ0Z","v2eC3zz4ZU","zz4ZUh1zcH","ZhwG1uTacx","zY1GYLewvM","0ao3l7hyVv","14FLRHzZT8","Cp3mZFPfSE","sx5GlKASQ8","euZA55nmWv",
-"Yh1hFpv0i7","C2IrcMaJQs","ECMvUzQt6Q","16lHcAmdQd","NAFuwl83Ud","FcWrWjS1aj","zz4ZUtaOXK","UmaEvkZANm","FxX9qBFkb8","45cIHkB5nP",
-"MaJQsfcJOy","ydG8Ud7vjM","GXdoH8cVD3","CIShGjeskS","hSSvQpiJSk","lViBvZv7z0","JXljWQ6hMC","2Yz7EjzUqR","BbwgAUmaEv","HlUbFnnP8o",
-"2TRI7Dz1R3","VBjhzUmaEv","8FmFHK4GS8","GWqqXiKqhr","uQIczCxVEf","0ao3luoStw","MezSWtjQxs","cmXIXQChxs","iKqhrZuDtD","i3pyd5IhmG",
-"dpe1vuPX7G","zmLYDvkCHH","t98iW7hyVv","lH1ktlXFOB","Zv7z09GXkX","qaofNCp3mZ","iKqhrbZLvS","Dz1R3y94nw","DG4sTD6rBy","64s8Ngf8rI",
-"uAWyp0ao3l","YOfrYPb1pa","tvdkD0YAGH","7lUXZgjUTu","ydG8U2Yz7E","AmdQdhUTw7","vkCHHa00b5","AOgEeo8Uyd","rz7UtQClRL","uJScXVBjhz",
-"1v5hH5Mg9r","Gv3Fqv2eC3","lViBvuLtKs","D6rByhSSvQ","RsQUqpFrrl","dmoS7gjUTu","WreyPfcJOy","VjCZqGv3Fq","ru4UGXyPZN","jfREu4W0Tl",
-"jeskSVLTy6","Cp3mZyofH3","lCMxylViBv","pvgjSrhl0J","MojnPm4bxU","WDVWJyToGW","euZA57hyVv","GWqqXsqVrf","hYBCKQ6Lix","RpBQmjtn0X",
-"s4786CxVEf","AIYUuMkgy8","NcICAni2v1","tAOsrU3yw5","gdQsSX6Pin","hE1Ql0YAGH","xciqpMK07Y","nFqikjzUqR","BpYhVFcWrW","Dz1R3M6qcG",
-"7lUXZ0BmCy","Z4I1v1LB1L","KsjRKogLgc","2Yz7ES2Dfu","fcwDa5iGN5","xReecRsQUq","8RCUA0YAGH","JkzUnfqypy","IBe8kK4GS8","k85AeChuy3",
-"zbIYY618Di","BCxeCcL0aE","IRh48D6rBy","Cfgr3HRxd8","FcWrW2Nslm","FwEJzjtn0X","OUYuFprNT6","AkKTkjfREu","vkCHHgf8rI","zQt6QqQxHP",
-"oGu6xO3iyQ","wDajXgjUTu","fFDrJ7Ow5C","FjHXRC2Irc","1j5L8s4786","uLtKszFgtB","guMb84QMc9","EdBKcpmeCd","IKxdLWMiS3","kB5nPQClRL",
-"mX2GElweGy","s93MlTCgPp","hYBCKXflUq","2NslmuAWyp","6AFT0OxWIH","ciuWzRACuj","xciqpMaJQs","bZLvSlXFOB","aFFssgdQsS","In3NSIRh48",
-"No0QbVNCPd","ydG8UKsjRK","GWqqXYjB9t","QClRLjeskS","piJSkazIWp","Gv3FqcmXIX","BGaQYUvlv4","FNYIM0BmCy","FGzgpv1Hln","HfyNQIn3NS",
-"Yh1hFRmDcr","0YAGHs7Mxk","I7p2ajS1aj","qaofNJJs5m","MK07Yi7WMQ","2DREs1j5L8","i3pydZzJHW","0KyfsFnPFB","lsQGoLbRTH","JJs5mVNCPd",
-"RmDcrECMvU","yEfy9kB5nP","3otm6Uvlv4","29QAznFqik","M3zXLDz1R3","VjCZqydG8U","OxWIHogLgc","mX2GEAOgEe","QYxC0xciqp","soy9tzbIYY",
-"VjCZqNxx9V","v2eC3S2Dfu","WMiS3qaofN","24ARFAXpwE","2Nslmdjsrv","4dEz6OHaBz","okgRiaFFss","M3zXLaFFss","BFkb8ReKEW","rKDLJMkgy8",
-"pvgjS5VZjS","Oz8yZtjQxs","FFDuiOz8yZ","SWfoupmeCd","KsjRKZJTXH","jtn0XWaim6","9eoRcmz8gx","uN6r3tuDyS","blLA9xReec","gjUTuCNHmv",
-"PYBf4pAhR1","lkMUAk85Ae","uPX7GpWiOs","lsQGoIn3NS","Y1mC0TCgPp","uPX7Gt59lR","oQ87rUl4a1","RxrsmoGu6x","Kr8ys0PktI","v1Hln4QMc9",
-"oGu6xtl72W","Vprf2i7WMQ","iKqhr8FmFH","7fsYMYOfrY","GSQwj1j5L8","lCMxyHlUbF","4QMc9AXpwE","45cIHyofH3","qaofNix74r","euZA5BbwgA",
-"ThjNne6e4z","MK07Yv2eC3","Cfgr3Chuy3","PYBf4Yw2oU","RBhp0gtCA5","TwanoMmsIo","618DiVprf2","CNHmvRmDcr","blLA9RmDcr","Y1mC0cL0aE",
-"580YDvkCHH","5VZjS4dEz6","e6e4zNcICA","OUqFMfFDrJ","zz4ZUnFqik","qaofNiqv4k","4W0Tlm4bxU","M6qcGWaim6","JXljWi7WMQ","RmDcroVQp6",
-"RACujWDVWJ","9GXkXLewvM","EdBKcCp3mZ","sqVrfU3yw5","pT8wuVBjhz","G1RhSRxrsm","X6Pin1LB1L","VNCPdzHF1q","Mkgy8RmDcr","1j5L8TXQ0Z",
-"jS1ajpFrrl","ThjNn16lHc","cQOnvGWqqX","dhSuHJkzUn","StlDJ6AFT0","Pb1palViBv","AgJHQzFgtB","s7MxkQnJ1S","9iGoTJkzUn","BFkb8No0Qb",
-"AXpwEkB5nP","ogLgcfqypy","0YAGHe6e4z","pvgjS580YD","dmoS7vOqCE","BFkb8MmsIo","2hEEUni2v1","MaJQsgdQsS","v8yFNyToGW","WaWsvMezSW",
-"5IhmGogLgc","yToGWtaOXK","Yw2oUXflUq","cL0aEMmKGJ","zmLYDHP433","POUYS1LB1L","yvOMICfgr3","Chuy3DLhzM","Ss0Zu9eoRc","BFkb8NcICA",
-"BbwgAo8Uyd","aL6AJGXdoH","OUqFMiB08l","6AFT09XyT9","FnPFBSbRYy","ZhwG12TRI7","IjTwP8cVD3","45cIHzmLYD","rKDLJ8TxD7","QssNCHlUbF",
-"ulk41Q6hMC","8TxD7gjUTu","Dz1R3RpBQm","fcwDaIRh48","9iGoT8FmFH","48cHLe6e4z","JJs5m8FmFH","fcwDaVerEA","brhlQzz4ZU","pvgjScQOnv",
-"uoStwm4bxU","bgJAzVIlwP","AgJHQHP433","AIYUuDcpWB","cmXIXLbRTH","jzUqRlm0pD","aFFssNcICA","9XyT9Mm8si","4QMc9XyPZN","AmdQdX6Pin",
-"pvgjSFNYIM","FcWrW7Ow5C","pWiOs45cIH","RzaZAHRxd8","lXFOBVLTy6","jtn0X0h1b1","lj07QWaim6","0BmCyyToGW","aez9yC2Irc","ciuWzLewvM",
-"xciqpY1mC0","nlaByuoStw","wDajX5nmWv","kZANmQworu","FxX9q8FmFH","VBjhzCNHmv","yEfy9tvdkD","5NammmX2GE","QnJ1SRmDcr","tjQxsRpBQm",
-"Cp3mZ0ao3l","uvf7AhUTw7","DQimpCp3mZ","5drc67fKYU","Uvlv4UmaEv","b29RJix74r","MaJQsuQIcz","ciuWzSbRYy","StlDJRACuj","CIShGAmdQd",
-"yvOMIh1zcH","m4bxUEoToP","gIYvEFwEJz","t59lR5IhmG","zQt6QUl4a1","Ul4a1dQ586","5drc69XyT9","FhtglWmadA","WMiS3o8Uyd","KZamHPOUYS",
-"vLsmSb29RJ","9XyT9kZANm","gtCA5uoStw","rz7Ut8U2nU","uTacxCxVEf","8xEKzDcpWB","uLtKsFhtgl","nFqik7hyVv","prNT6azIWp","wiHrZv8yFN",
-"xXTI4RmDcr","xReecIjTwP","RACujWaWsv","ZuDtDe6e4z","K20wK2ZHdk","b29RJVBjhz","4W0TlVNCPd","cQOnvKZamH","14FLRQssNC","4W0Tld7vjM",
-"DQimph1zcH","sx5Gl1j5L8","jzUqRNxx9V","AkKTkCxVEf","zz4ZUlsQGo","v1Hlni3pyd","aL6AJxXTI4","lCMxy24ARF","Ss0Zuk85Ae","SmGzv4dEz6",
-"CxVEfD6rBy","Cfgr3aDGtS","n1pmO8FmFH","1LB1L16lHc","FLsphtAOsr","ix74rPb1pa","dhSuHOxWIH","5Namm3otm6","2ZHdk2hEEU","piJSkMm8si",
-"OHaBzL7cGc","qaofN0MR5X","BGaQYfqypy","YOfrYlH1kt","fFDrJpT8wu","HP433FxX9q","QssNCZv7z0","Chuy31j5L8","9GXkXTa8f6","bgJAzO3iyQ",
-"HfyNQogLgc","CK5W7vLsmS","FhtglpT8wu","GWqqXzmLYD","5iGN5v1Hln","RACujfqypy","IjTwP7lUXZ","U3yw5uLtKs","7lUXZuoStw","fLNg84QMc9",
-"LDk6f5Drn0","U3yw5qQxHP","sx5GlciuWz","i3pydIKxdL","pvgjSZ4I1v","2TRI7ZuDtD","s7MxkzFgtB","VjCZq7Ow5C","Gv3FqECMvU","nFqikRzaZA",
-"YOfrYcShY2","2Nslmix74r","5IhmGgIYvE","FNYIM4W0Tl","mz8gxjiVBP","RxrsmQClRL","AmdQdUl4a1","Uvlv4TXQ0Z","MGlTFEOE1o","StlDJiKqhr",
-"0PktIAIYUu","nFqikCqqaD","8U2nUChuy3","YjB9tRxrsm","StlDJnlaBy","FNYIMG1RhS","07n1ciKqhr","0h1b1k85Ae","Mkgy8RpBQm","JRJQBAOgEe",
-"MK07YzbIYY","Yw2oUReKEW","I7p2at59lR","n8pJ9AOgEe","FVMxouLtKs","UmaEv5IhmG","8RCUASWfou","dpe1vxXTI4","hE1QlVprf2","8cVD3guMb8",
-"Qworumz8gx","dQ586VerEA","D6rByGSQwj","hUTw7AIYUu","wiHrZxciqp","qUJMd5Drn0","FnPFBVLTy6","9y4lw29QAz","tuDySJ2mQi","X6PinY1mC0",
-"rz7Utfqypy","7ku1pZhwG1","VLTy6XyPZN","uZPqgeuZA5","9GXkXC2Irc","tlILtMezSW","bgJAzyofH3","0KyfsguMb8","fcJOyCIShG","Ss0ZuvOqCE",
-"xReecwDajX","d7vjMuoStw","W3VFHCdyBV","DG4sTY1mC0","lsQGoa00b5","J2mQimz8gx","KsjRKJXljW","yluBx6q6L9","NhXduIKxdL","bZLvSReKEW",
-"DcpWBiqv4k","kB5nPSjskQ","1v5hHlm0pD","FjHXRLDk6f","HlUbFJJs5m","hE1QluN6r3","Q6hMCZuDtD","Ul4a1F6PT2","VIlwPzqH0W","Dz1R3guMb8",
-"C2IrcSWfou","AOgEeatef2","ni2v15nmWv","MaJQssuY4x","Ta8f6CxVEf","OUYuFbZLvS","YjB9tVBjhz","KZamHJXljW","tuDySt98iW","W7cTsjeskS",
-"VBjhzDG4sT","djsrvzz4ZU","Vprf25ZaEz","i3pydSs0Zu","LDk6fuQIcz","ThjNnFFDui","v8yFNOxWIH","0MR5XlH1kt","he9IAmz8gx","SbRYyFxX9q",
-"yofH3jzUqR","sqVrfOHaBz","QnJ1S3otm6","IBe8k5ZaEz","qQxHPuAWyp","iwzGkWMiS3","6AFT0Ss0Zu","uoStwxciqp","2DREsVBjhz","0KyfssuY4x",
-"cQOnvZUnqt","7lUXZqaofN","5VZjSk85Ae","Mm8si4W0Tl","BbwgAeuZA5","oGu6xeuZA5","KZamH2Nslm","hSSvQSs0Zu","aez9yFGzgp","e6e4zL7cGc",
-"48cHLTwano","No0QbQworu","xciqpWDVWJ","uJScXTa8f6","BpYhVhSSvQ","zHF1qKZamH","HlUbFGSQwj","FwEJz6q6L9","SWfou24ARF","ThjNnblLA9",
-"TXQ0ZFGzgp","lm0pD7ku1p","Q6Lix5Mg9r","vkCHHWmadA","Mkgy8prNT6","9XyT9S77LH","5NammVjCZq","jSjS3RzaZA","vOqCE2ZHdk","v8yFNK20wK",
-"07n1cjeskS","ulk41bZLvS","hUTw7dmoS7","Zv7z0aez9y","ZuDtDdQ586","JIqXikB5nP","RkQkeuZPqg","WPmlxtjQxs","JXljWmz8gx","pWiOsn8pJ9",
-"xciqpNxx9V","48cHLRsQUq","ru4UGZJTXH","aez9yzbIYY","hE1Ql7ku1p","8cVD3s93Ml","pFrrlMezSW","ReKEWEdBKc","FVMxoBFkb8","QnJ1SCK5W7",
-"W7cTsBFkb8","e6e4zni2v1","QbxXcpmeCd","Gv3FqcL0aE","EdBKcokgRi","MojnP2hEEU","guMb8blLA9","8cVD3tl72W","BFkb8BGaQY","UlU3MFjHXR",
-"BGaQYLDk6f","FLsphjtn0X","G1RhS5nmWv","8cVD3CK5W7","NhXduLewvM","aDGtSuTacx","FhtglRBhp0","iB08luLtKs","lViBv8TxD7","VjCZqPOUYS",
-"lm0pD0Wr5y","FPfSE8cVD3","Waim6Uvlv4","In3NScShY2","YjB9tOxWIH","iwzGkCfgr3","ydG8UpiJSk","prNT6IBe8k","x3LDe5drc6","wDajXv1Hln",
-"xciqpqaofN","LbRTHNcICA","NcICAyofH3","MojnPpvgjS","kB5nPlViBv","ksJbyUl4a1","SWfouuvf7A","ZJTXHlsQGo","ogLgcSjskQ","jiVBPCdyBV",
-"v1HlnpiJSk","gdQsSbgJAz","tuDySy94nw","yToGWBbwgA","ECMvUguMb8","HfyNQokgRi","lweGyFFDui","dhSuHtAOsr","ThjNnFPfSE","FGzgpRpBQm",
-"FPfSEWreyP","nlaByiB08l","NhXduhUTw7","piJSkS2Dfu","M3zXLiqv4k","OUYuFM6qcG","vLsmS2Nslm","nnP8ovkCHH","LbRTH9XyT9","FcWrWnFqik",
-"sqVrfe6e4z","0BmCykB5nP","Gv3FqjfREu","BGaQY2Nslm","0YAGHB3qem","KZamHZhwG1","euZA5tAOsr","d85a9YOfrY","IRh48yvOMI","Z4I1vwiHrZ",
-"dQ586zFgtB","uN6r3VerEA","Zv7z0KZamH","9y4lw4W0Tl","Yw2oU0BmCy","U3yw5OUqFM","RmDcr5Drn0","CNHmvSjskQ","HlUbFmz8gx","ogLgcJRJQB",
-"5drc6djsrv","FnPFBMmsIo","vkCHHjzUqR","RzaZAZ4I1v","DQimpl83Ud","D6rBy5ZaEz","KsjRKxXTI4","OUqFM1j5L8","e6e4zRBhp0","zQt6Q5drc6",
-"zqH0Wiqv4k","FFDuiJIqXi","7lUXZAgJHQ","Dz1R3aDGtS","GWqqXwDajX","CNHmvjzUqR","o8Uyd7X3uy","dpe1vY1mC0","5Drn0uZPqg","QworumX2GE",
-"sx5GlfcwDa","0YAGHG1RhS","euZA5Ul4a1","zmLYDQ6hMC","xReecuvf7A","uN6r3Uvlv4","dmoS7hYBCK","tvdkDuLtKs","mz8gxL7cGc","vkCHHt98iW",
-"QnJ1SAkKTk","2hEEUChuy3","RkQkeQChxs","GSQwjAgJHQ","iwzGkh1zcH","Dz1R3CqqaD","29QAzqUJMd","lm0pD4dEz6","UlU3MMezSW","JIqXi7lUXZ",
-"SjskQS2Dfu","aez9y8hJdt","JKWYR2Yz7E","5IhmGpvgjS","hE1QlNxx9V","v1HlnuJScX","Yf2EcKr8ys","Cfgr3EoToP","pWiOsxciqp","O3iyQrKDLJ",
-"zbIYYZUnqt","gtCA5cQOnv","7ku1pKr8ys","dpe1vQChxs","MmsIoWPmlx","GrDg7RsQUq","J2mQiQ6Lix","4dEz6fmIK1","fcJOyPYBf4","HP433piJSk",
-"i3pyd7Ow5C","QYxC0aL6AJ","AmdQdEoToP","EdBKcwiHrZ","IjTwPSjskQ","dpe1vSmGzv","QChxstAOsr","ZUnqtMmKGJ","48cHLhYBCK","Pb1paFxX9q",
-"9rlg9s4786","Qworuv2eC3","Ul4a1lj07Q","W3VFHBFkb8","l83UdG1RhS","nFqikrz7Ut","JXljWMGlTF","TCgPpHP433","FFDuiYjB9t","oVQp6ulk41",
-"QworuuZPqg","e6e4z5iGN5","QClRL8U2nU","8cVD3FFDui","IRh48EoToP","QnJ1S8U2nU","QnJ1SOUqFM","AIYUuXflUq","3otm6SWfou","7hyVvuPX7G",
-"zFgtBwiHrZ","prNT69rlg9","QYxC0ciuWz","2NslmbgJAz","8FmFHVNCPd","0PktIVBjhz","Cfgr3uQIcz","uupzkn8pJ9","rKDLJKr8ys","fFDrJzz4ZU",
-"Yw2oUaFFss","Qworuru4UG","Cp3mZVIlwP","MaJQs5drc6","5ZaEzZhwG1","MojnPQnJ1S","9eoRcpAhR1","TCgPp5iGN5","QWxoTLewvM","5IhmGsoy9t",
-"ogLgc1j5L8","FjHXRGXdoH","5nmWvRsQUq","U3yw50BmCy","h1zcHMmKGJ","lkMUAfcwDa","5drc6oVQp6","pvgjSNcICA","BCxeCQClRL","jfREu24ARF",
-"ZJTXH5ZaEz","IRh48oGu6x","Kr8ysO3iyQ","s7MxkhUTw7","G1RhSFjHXR","HP433OHaBz","5nmWvZJTXH","Q6LixBpYhV","hi5X7Ul4a1","TXQ0ZVLTy6",
-"JKWYRtvdkD","NOHszQ6hMC","qUJMdRBhp0","bZLvSs93Ml","yvOMIQbxXc","aez9yDQimp","LbRTHprNT6","K4GS8MmKGJ","ZJTXHCK5W7","NhXduGXdoH",
-"Oz8yZlCMxy","CdyBVRkQke","hE1QlW7cTs","d85a9Waim6","Nxx9VYOfrY","X6PinSWfou","jSjS3ZJTXH","YjB9tYf2Ec","MaJQsKASQ8","zQt6QKASQ8",
-"cShY2FGzgp","oGu6xbrhlQ","GXdoHKsjRK","GXdoHtl72W","D6rByVNCPd","POUYSDG4sT","kB5nPdhSuH","lpF6WK4GS8","soy9tdhSuH","9iGoTuN6r3",
-"qUJMdhe9IA","HRxd87lUXZ","5NammD6rBy","uPX7GcQOnv","wDajXhi5X7","BbwgAd85a9","uN6r3HfyNQ","atef28U2nU","PYBf4FGzgp","EdBKcFjHXR",
-"yvOMIpAhR1","5nmWvYjB9t","RmDcrDLhzM","RsQUqRxrsm","n8pJ9lH1kt","uLtKsGv3Fq","xXTI4ZzJHW","1LB1LwiHrZ","29QAzpv0i7","Mm8silViBv",
-"QChxsBbwgA","Yf2EcRACuj","Nxx9VbZLvS","cQOnvL7cGc","uPX7GSWfou","LbRTHbgJAz","zHF1qpAhR1","5iGN5MK07Y","euZA5CIShG","2hEEUzqH0W",
-"cL0aEYOfrY","2TRI7pAhR1","Pb1pajS1aj","W3VFHSjskQ","uupzkTCgPp","lpF6WP6bcg","5nmWvhYBCK","kZANmgjUTu","sqVrfs93Ml","oGu6xo8Uyd",
-"i3pydX6Pin","OHaBzlj07Q","hUTw7MojnP","soy9t9iGoT","O3iyQW7cTs","QYxC0Fhtgl","tl72WzY1GY","07n1c7Ow5C","VLTy6jSjS3","48cHLfFDrJ",
-"wDajXI7p2a","Kr8ysIKxdL","WreyPQChxs","W3VFH48cHL","rhl0JFLsph","okgRi580YD","tuDySnlaBy","hE1QlpT8wu","TwanoDcpWB","AkKTklweGy",
-"jzUqRVBjhz","n1pmOyofH3","d85a9mX2GE","bgJAzFFDui","F6PT2ZUnqt","DQimpJ2mQi","45cIHO3iyQ","NhXdugdQsS","cmXIXFLsph","HfyNQVIlwP",
-"AgJHQUl4a1","dQ586Ta8f6","ReKEWZv7z0","aez9ysx5Gl","Zv7z0nnP8o","Y1mC0atef2","iqv4kAkKTk","K20wKCIShG","KASQ80BmCy","2DREswDajX",
-"LbRTHZzJHW","HzZT8lweGy","cL0aEFwEJz","nFqik45cIH","StlDJHzZT8","VLTy6VBjhz","v2eC38cVD3","0ao3lt98iW","uN6r3Q6Lix","atef2zmLYD",
-"guMb88TxD7","580YDaDGtS","2ZHdkvOqCE","14FLRlpF6W","5VZjSQworu","UlU3MCp3mZ","jzUqR14FLR","MmsIo3otm6","NcICAd7vjM","Oz8yZMK07Y",
-"14FLRlkMUA","45cIHix74r","SmGzvQssNC","tlILtRACuj","LbRTHjeskS","0Wr5y29QAz","FjHXR7Ow5C","atef2M6qcG","HRxd814FLR","v2eC3ciuWz",
-"1j5L8D6rBy","ThjNnL7cGc","5Drn09rlg9","8cVD3K4GS8","vOqCE9GXkX","prNT6lViBv","U3yw5vLsmS","JRJQBReKEW","oVQp6jS1aj","ulk41lsQGo",
-"FVMxoCdyBV","8FmFHpiJSk","SbRYyaez9y","ZUnqt7fKYU","WreyP5iGN5","pT8wuFVMxo","FxX9qS2Dfu","ydG8UnFqik","Mm8siDz1R3","zY1GYBFkb8",
-"HzZT8MojnP","ZhwG1atef2","7fsYMdpe1v","StlDJECMvU","QWxoT9iGoT","tuDyS9y4lw","qaofNgIYvE","djsrvn1pmO","P6bcgTXQ0Z","B3qemJ2mQi",
-"xciqpW3VFH","DLhzMjiVBP","K20wK16lHc","Pb1paChuy3","O3iyQeuZA5","FcWrW5ZaEz","JKWYRRBhp0","gjUTujfREu","soy9tlCMxy","gtCA5wiHrZ",
-"yofH3No0Qb","14FLR9XyT9","zY1GYprNT6","VNCPdWaim6","TXQ0ZXyPZN","LewvMksJby","8TxD7lViBv","MojnPqQxHP","HP4334W0Tl","aDGtSCNHmv",
-"Cfgr3QssNC","hYBCKn1pmO","L7cGccShY2","dpe1vBGaQY","tl72WuPX7G","0PktI1v5hH","Dz1R3In3NS","Vprf2azIWp","AOgEeuPX7G","zz4ZU8cVD3",
-"580YDcL0aE","lkMUAQssNC","NhXduW7cTs","xciqpMmsIo","VjCZq9XyT9","7lUXZ0Kyfs","zY1GY7fKYU","O3iyQqQxHP","v1Hlnmz8gx","yluBxCNHmv",
-"tjQxslH1kt","Oz8yZHlUbF","bZLvS5Drn0","K20wKK20wK","I7p2a4dEz6","5iGN5brhlQ","IBe8khYBCK","MGlTF7fsYM","uJScXuTacx","gdQsS2DREs",
-"Y1mC0JJs5m","8cVD3O3iyQ","5drc6jS1aj","bgJAzWDVWJ","DG4sTi7WMQ","8FmFHVLTy6","2ZHdklm0pD","fFDrJksJby","RzaZAOHaBz","4W0TlW3VFH",
-"Mm8siW7cTs","KASQ8OxWIH","lXFOBix74r","ciuWzVprf2","J2mQiNo0Qb","0BmCyxReec","MaJQsZhwG1","dpe1vEdBKc","6q6L9lweGy","QbxXcDG4sT",
-"EOE1oQYxC0","JJs5mqUJMd","QWxoTfaHir","0MR5X7X3uy","Pb1pafmIK1","OUYuFqQxHP","aL6AJWmadA","MmKGJnlaBy","Kr8ysprNT6","zbIYY0Kyfs",
-"TXQ0ZVjCZq","HRxd8iKqhr","DQimpix74r","EOE1oI7p2a","16lHcoQ87r","oVQp6tuDyS","vLsmSHzZT8","Nxx9VpmeCd","lpF6W8U2nU","AkKTk5ZaEz",
-"zbIYY6AFT0","RACujChuy3","dQ586XflUq","lXFOBUlU3M","atef2jtn0X","n8pJ9Ss0Zu","UmaEvJKWYR","lViBvM6qcG","uupzks7Mxk","Yw2oUVLTy6",
-"e6e4zDQimp","lViBv7lUXZ","taOXKb29RJ","tjQxs0h1b1","Ss0ZukZANm","lm0pDi7WMQ","pT8wuTXQ0Z","lkMUAWMiS3","fqypynlaBy","In3NShe9IA",
-"kZANmdjsrv","45cIHS2Dfu","UlU3MSs0Zu","AkKTkwDajX","4QMc9Cfgr3","t98iWQnJ1S","Mm8siQYxC0","9iGoTK20wK","wiHrZsx5Gl","0PktIpiJSk",
-"o8Uyds93Ml","gdQsSuPX7G","LbRTHnnP8o","0PktIZv7z0","XyPZN4QMc9","2Nslmn1pmO","9eoRc16lHc","7fsYMqaofN","UmaEvoGu6x","iB08lydG8U",
-"MK07YguMb8","guMb8BFkb8","oVQp6jSjS3","AmdQdbZLvS","hE1QlQClRL","tl72W7hyVv","h1zcHYOfrY","kB5nPSWfou","Cfgr3pvgjS","XflUqRxrsm",
-"soy9tnFqik","iKqhriB08l","G1RhSMkgy8","Ss0Zudpe1v","ni2v1he9IA","B3qem9iGoT","uZPqgtaOXK","NOHszVBjhz","dQ586Yw2oU","16lHcW7cTs",
-"k85Ae7fsYM","0ao3l0Wr5y","ulk41lm0pD","UlU3MzHF1q","FNYIM8TxD7","MK07YpiJSk","uQIczXyPZN","9rlg924ARF","uvf7AM6qcG","GXdoHFwEJz",
-"m4bxUuupzk","VLTy6Q6hMC","lweGydpe1v","h1zcHhUTw7","MmsIoJ2mQi","dQ586nFqik","jSjS3FGzgp","m4bxUM3zXL","jtn0X0MR5X","Dz1R3tAOsr",
-"No0Qbsoy9t","J2mQin1pmO","uTacx07n1c","BGaQYxciqp","8hJdtb29RJ","FLsphfmIK1","a00b5IBe8k","uPX7GuJScX","zz4ZUt59lR","fqypyAmdQd",
-"X6Pin16lHc","U3yw5d85a9","fFDrJzY1GY","tuDySRBhp0","ZuDtDZUnqt","StlDJ1j5L8","DQimp2Nslm","AkKTk07n1c","jtn0X7fKYU","nFqikgtCA5",
-"o8UydPOUYS","azIWpfLNg8","uQIczsqVrf","lpF6WXyPZN","kZANmpiJSk","rKDLJe6e4z","wiHrZJIqXi","HfyNQ8hJdt","FFDuiuN6r3","Kr8ysm4bxU",
-"4W0TlFLsph","2Yz7E7ku1p","07n1c8cVD3","W7cTscmXIX","wDajXrz7Ut","5ZaEzCIShG","JJs5mM3zXL","FjHXRh1zcH","YOfrYzz4ZU","2ZHdk580YD",
-"aez9yY1mC0","FVMxo0h1b1","29QAzn8pJ9","48cHLQssNC","Ss0ZuazIWp","gdQsSDz1R3","16lHcEdBKc","RmDcr580YD","xciqpuvf7A","ni2v1EdBKc",
-"piJSkNOHsz","ZJTXH618Di","xciqpHRxd8","i7WMQn1pmO","ECMvUmX2GE","s4786uN6r3","JIqXiLDk6f","X6PinIBe8k","JJs5mQClRL","K20wKnFqik",
-"O3iyQjzUqR","taOXKhYBCK","FnPFBy94nw","U3yw5W7cTs","QWxoTcL0aE","uAWypUlU3M","WPmlx0Wr5y","WMiS3tAOsr","RkQkeFGzgp","O3iyQNAFuw",
-"W3VFHsoy9t","9eoRcqaofN","uoStwvkCHH","Y1mC08cVD3","lweGyAgJHQ","ZUnqtQ6Lix","ydG8UYjB9t","2ZHdkv8yFN","TXQ0Z4QMc9","uAWypRmDcr",
-"AmdQd7fsYM","s93Mlgf8rI","3weIF24ARF","XflUqJXljW","ZhwG17fKYU","5drc65IhmG","gf8rIlXFOB","QworuJkzUn","Cfgr3DQimp","uvf7AIjTwP",
-"AmdQdKASQ8","9iGoTuupzk","nlaByvOqCE","Yh1hFokgRi","RpBQmt98iW","hYBCK5nmWv","m4bxUlCMxy","lCMxyS77LH","XyPZNzqH0W","uTacxlCMxy",
-"zmLYDWDVWJ","SmGzvJKWYR","3weIFv2eC3","v8yFNVprf2","IKxdLdQ586","yToGWQ6hMC","AkKTk1LB1L","SWfouMK07Y","L7cGcDG4sT","l83UdlH1kt",
-"NhXdu45cIH","rz7Ut1LB1L","In3NS14FLR","Oz8yZPb1pa","uAWyplH1kt","dmoS7IKxdL","guMb8OHaBz","aez9yoVQp6","zHF1qKASQ8","24ARFm4bxU",
-"HRxd8UlU3M","14FLRUl4a1","HRxd8GXdoH","lXFOBQworu","5drc6okgRi","AgJHQ0ao3l","mX2GEU3yw5","jSjS3Yh1hF","tjQxsVIlwP","suY4x6AFT0",
-"HzZT8tl72W","jtn0XWMiS3","6q6L9OUYuF","x3LDelCMxy","8cVD3D6rBy","Oz8yZl83Ud","QWxoTSjskQ","JXljW4W0Tl","7ku1pxReec","VjCZqFjHXR",
-"m4bxUv1Hln","qQxHPb29RJ","y94nwCK5W7","5iGN55nmWv","3weIFW3VFH","Cfgr3Q6hMC","Rxrsm45cIH","6q6L9QssNC","2TRI7nnP8o","OHaBzMmKGJ",
-"FxX9q5iGN5","v2eC3rz7Ut","Yw2oU55rfB","BCxeCPYBf4","5iGN5GXdoH","SmGzvdhSuH","d85a9EdBKc","MaJQsMmsIo","Ul4a1gtCA5","yToGW3otm6",
-"uPX7Glj07Q","L7cGc5drc6","IBe8kYjB9t","lweGyAXpwE","uAWypYw2oU","VIlwPiqv4k","Dz1R3ru4UG","faHirDz1R3","CNHmv1LB1L","zz4ZUyluBx",
-"CK5W7Y1mC0","v2eC3yluBx","29QAzDz1R3","zqH0WCqqaD","FFDuiNOHsz","Z4I1vtaOXK","RzaZAIjTwP","9eoRcsqVrf","nFqikzY1GY","iqv4kvOqCE",
-"Ss0ZuJ2mQi","tjQxsOz8yZ","RmDcrgdQsS","0Wr5yFLsph","AXpwEt98iW","x3LDefcwDa","Q6Lix07n1c","jtn0XGrDg7","0Kyfs9iGoT","C2IrcG1RhS",
-"kB5nPtvdkD","zY1GYS2Dfu","n1pmOtl72W","KZamHlCMxy","pvgjSgdQsS","POUYShi5X7","5nmWvSWfou","Q6Lix9eoRc","ni2v1Ss0Zu","O3iyQWmadA",
-"cL0aE9rlg9","2DREsjfREu","n1pmO9y4lw","1j5L8uoStw","ZuDtDnFqik","jfREuzmLYD","gIYvEOHaBz","s93MlXflUq","D6rByYOfrY","9eoRcpT8wu",
-"5Drn0Nxx9V","5drc6IKxdL","D6rByDG4sT","2hEEUQssNC","Ul4a1JXljW","iB08lBGaQY","Oz8yZEoToP","Nxx9VK20wK","ulk41RpBQm","1v5hHIRh48",
-"FVMxoatef2","VerEAU3yw5","VerEAC2Irc","F6PT2t98iW","JIqXiSbRYy","brhlQfcJOy","0MR5XsuY4x","BFkb8qaofN","TwanouN6r3","FnPFBfFDrJ",
-"xciqpRzaZA","VerEAjfREu","6AFT0MK07Y","0Wr5y0YAGH","zHF1qIBe8k","1LB1LvkCHH","KASQ84QMc9","tuDySfcwDa","t98iWeuZA5","OxWIHpiJSk",
-"WmadAEdBKc","0Wr5yDG4sT","ydG8U0YAGH","pT8wuCdyBV","Uvlv4fcJOy","RACujsqVrf","ReKEWuLtKs","ZuDtDcmXIX","QnJ1SOxWIH","y94nwHzZT8",
-"b29RJn1pmO","fqypyW3VFH","pvgjSUvlv4","fcwDaNcICA","MmKGJdmoS7","iB08lfLNg8","QChxsCdyBV","aL6AJW7cTs","Pb1padpe1v","h1zcHdmoS7",
-"gjUTuCxVEf","pv0i7iwzGk","lkMUAyofH3","8FmFHlViBv","BGaQYciuWz","vOqCE1j5L8","Waim6sx5Gl","jtn0XksJby","7hyVvfaHir","kB5nP9iGoT",
-"RACujDG4sT","4W0Tl9GXkX","qaofNFcWrW","GWqqXfmIK1","mz8gxBbwgA","M6qcGMkgy8","zHF1qtlILt","Kr8ysOz8yZ","TwanoOxWIH","BFkb8ZUnqt",
-"VIlwPWreyP","uLtKsZzJHW","VjCZquoStw","uTacxsoy9t","5Mg9r4W0Tl","7X3uymX2GE","dhSuHhYBCK","Q6hMCpiJSk","FwEJzdhSuH","lkMUACIShG",
-"ni2v1AOgEe","rKDLJNhXdu","0YAGHUvlv4","7fKYUaez9y","Cp3mZn8pJ9","LewvMDQimp","G1RhSAIYUu","WMiS3ix74r","KsjRK0BmCy","29QAzVerEA",
-"LbRTHatef2","wDajXZhwG1","QClRLt59lR","2NslmQWxoT","RzaZACxVEf","uLtKsBbwgA","GXdoHlj07Q","Y1mC0IKxdL","hYBCK9iGoT","1LB1LuAWyp",
-"1LB1LRxrsm","GrDg7piJSk","lViBvlpF6W","zHF1qiqv4k","YjB9td7vjM","CdyBV9GXkX","pFrrl0MR5X","qUJMdtl72W","tuDyStAOsr","U3yw507n1c",
-"Q6hMCvOqCE","7fKYUgdQsS","XflUqRsQUq","9XyT9Y1mC0","iwzGk2hEEU","pmeCdsuY4x","jtn0XtuDyS","Nxx9VFhtgl","uZPqg0BmCy","JKWYRAOgEe",
-"6q6L91j5L8","lm0pDFcWrW","i3pydjiVBP","yofH3ZzJHW","S2Dfu9iGoT","i3pydZUnqt","Yf2EcUl4a1","uJScXsuY4x","qaofN0YAGH","QnJ1SQ6Lix",
-"YjB9tJJs5m","Mm8sipAhR1","OUqFM29QAz","t59lR1LB1L","LewvMfcwDa","29QAzs7Mxk","W3VFHgjUTu","jzUqRQClRL","pT8wuqaofN","CxVEfNcICA",
-"hE1QlWaWsv","Cfgr3OUqFM","ZhwG1gjUTu","9GXkX5ZaEz","oVQp65nmWv","lCMxy5VZjS","gjUTuZJTXH","618DiOz8yZ","QWxoTSWfou","Z4I1vs93Ml",
-"RACujmz8gx","fLNg8PYBf4","gdQsSfmIK1","LewvMJRJQB","jSjS3Z4I1v","YjB9tW3VFH","pAhR1e6e4z","DLhzM2hEEU","W7cTslm0pD","JRJQB5Mg9r",
-"WreyPK4GS8","QnJ1S5VZjS","KASQ8xciqp","9iGoTVBjhz","Yf2Ecs93Ml","Yw2oUx3LDe","580YDuJScX","I7p2ayluBx","BFkb8FPfSE","lm0pDa00b5",
-"jtn0XmX2GE","BCxeCsqVrf","AXpwEfLNg8","FhtglQYxC0","LewvMOxWIH","cL0aEIjTwP","s7MxkoGu6x","hYBCKogLgc","blLA9In3NS","POUYSHzZT8",
-"pv0i7ZhwG1","J2mQiFxX9q","0ao3lt59lR","lj07QQYxC0","O3iyQX6Pin","5drc6gdQsS","s7MxkcQOnv","guMb855rfB","tAOsrChuy3","8cVD3DcpWB",
-"rhl0JJIqXi","X6PinpWiOs","G1RhSMK07Y","tjQxsFGzgp","VNCPdGSQwj","lCMxyFGzgp","Mkgy8MK07Y","vkCHH8hJdt","Uvlv4hSSvQ","azIWp5Mg9r",
-"HfyNQYjB9t","6q6L9v1Hln","OUYuFciuWz","pv0i77Ow5C","oVQp6IRh48","QWxoTgdQsS","UlU3M9y4lw","FxX9qFxX9q","Yf2EcyToGW","OHaBz8cVD3",
-"hi5X7Q6hMC","zFgtBk85Ae","iKqhrcShY2","In3NSWDVWJ","cmXIXS77LH","In3NSAXpwE","3otm6zmLYD","AkKTk9GXkX","F6PT2blLA9","zHF1qlj07Q",
-"StlDJfcwDa","lsQGot98iW","gdQsSJXljW","G1RhSlweGy","bgJAzGv3Fq","k85Aeiqv4k","5Drn0ogLgc","VIlwPzQt6Q","IBe8kv2eC3","AgJHQnFqik",
-"L7cGcFcWrW","AkKTktjQxs","OUYuFGWqqX","qQxHPfaHir","DQimpBbwgA","tjQxsuJScX","WaWsvsqVrf","zmLYDpAhR1","GWqqXWDVWJ","MmKGJbrhlQ",
-"AXpwEtvdkD","7hyVv1LB1L","VIlwPciuWz","oVQp6yEfy9","O3iyQMaJQs","TwanoNhXdu","RpBQmHRxd8","8U2nUCdyBV","brhlQiB08l","Cfgr3CdyBV",
-"lViBvNhXdu","JJs5m6q6L9","2ZHdkiqv4k","NhXdupFrrl","GrDg7oGu6x","FwEJzyToGW","WmadA580YD","Dz1R3ksJby","d7vjMoGu6x","ogLgcNcICA",
-"he9IAFwEJz","EdBKcvLsmS","FVMxouTacx","FcWrW0Wr5y","zqH0Wa00b5","YOfrYRxrsm","lsQGoPb1pa","D6rByMojnP","FNYIMWDVWJ","uLtKs2ZHdk",
-"0h1b1Uvlv4","EOE1oGv3Fq","cmXIXDLhzM","In3NS3weIF","3weIF4QMc9","JJs5mOxWIH","lViBvdmoS7","DcpWB8RCUA","VBjhzksJby","Oz8yZJKWYR",
-"BpYhVOxWIH","l83UdzmLYD","O3iyQFVMxo","dhSuH7hyVv","8RCUAl83Ud","fqypyP6bcg","3otm60ao3l","GrDg77lUXZ","7fKYUZJTXH","ciuWzG1RhS",
-"FnPFB9iGoT","tuDySlkMUA","suY4xPb1pa","bZLvSQYxC0","XflUqFjHXR","C2IrcGXdoH","taOXKzQt6Q","MezSWcL0aE","rKDLJ0YAGH","MojnP7X3uy",
-"CqqaD8RCUA","dhSuHDQimp","lsQGo5drc6","gf8rIkB5nP","5Drn0yluBx","sqVrfSWfou","G1RhSKsjRK","SmGzvCK5W7","4dEz6FNYIM","jfREui7WMQ",
-"GSQwjQbxXc","cQOnvuQIcz","WPmlxkB5nP","gdQsSOHaBz","AXpwEpFrrl","QbxXc24ARF","POUYSVerEA","jfREuRkQke","l83Udt98iW","fLNg8I7p2a",
-"RsQUq2ZHdk","LDk6flXFOB","pFrrlnlaBy","580YD9XyT9","Zv7z0tvdkD","AOgEeRmDcr","0Wr5yFwEJz","QWxoTaFFss","l83Ud8U2nU","8TxD7Nxx9V",
-"2NslmMmsIo","3weIF48cHL","o8UydHfyNQ","1j5L80ao3l","xReecOz8yZ","F6PT2wiHrZ","No0QbcShY2","uAWypeuZA5","FLsphGv3Fq","oQ87rjeskS",
-"9rlg9iKqhr","KsjRKi7WMQ","sx5GlrKDLJ","faHiraez9y","guMb8JRJQB","l83UdIn3NS","lm0pDMGlTF","qaofN8hJdt","5VZjSGXdoH","14FLRWMiS3",
-"7ku1p0PktI","Vprf2LbRTH","he9IA5IhmG","fqypyjzUqR","iKqhrMK07Y","POUYS2ZHdk","HP433ru4UG","ZhwG1W3VFH","zQt6QcL0aE","lsQGofcJOy",
-"l83UdAIYUu","Z4I1vsoy9t","fFDrJCIShG","5Mg9rlj07Q","CIShGuZPqg","VBjhzMmsIo","ZuDtDChuy3","blLA9AOgEe","fcwDaoQ87r","jiVBP5Namm",
-"wDajXtuDyS","O3iyQ2ZHdk","NcICAGv3Fq","KZamHSbRYy","F6PT2JkzUn","rKDLJh1zcH","VLTy6EdBKc","Chuy3h1zcH","suY4xLDk6f","nlaBy8FmFH",
-"UlU3MlpF6W","fcwDaAOgEe","HP433ogLgc","xXTI4guMb8","dhSuHOz8yZ","aL6AJ2DREs","gf8rIt98iW","2DREsJkzUn","d85a97ku1p","FLsph55rfB",
-"cL0aEM3zXL","Mkgy89GXkX","zbIYYChuy3","FVMxo0Kyfs","v2eC3U3yw5","tjQxsCfgr3","pvgjS14FLR","dpe1vjfREu","aL6AJlH1kt","aL6AJlCMxy",
-"y94nw0PktI","48cHLOHaBz","i7WMQ29QAz","NAFuwvOqCE","tl72WIKxdL","aDGtSNo0Qb","48cHLMezSW","48cHL6q6L9","HRxd8JIqXi","B3qemyluBx",
-"14FLRNOHsz","oVQp6a00b5","FFDuipAhR1","8cVD3ni2v1","Cfgr3oVQp6","aez9yuZPqg","IjTwPYf2Ec","kZANmNhXdu","AOgEeLDk6f","POUYScShY2",
-"In3NSUlU3M","7lUXZtAOsr","dmoS7lpF6W","29QAzQworu","CqqaDgf8rI","9XyT9pFrrl","QYxC0jS1aj","5Drn0fmIK1","kZANmaez9y","cQOnv9eoRc",
-"hSSvQjzUqR","RpBQmZUnqt","kB5nPwiHrZ","Q6hMCUlU3M","pmeCdjS1aj","MK07YSjskQ","0YAGHuQIcz","s93MlRpBQm","ogLgcTa8f6","K20wKD6rBy",
-"uupzkuQIcz","cShY2Ta8f6","fLNg8a00b5","ZuDtDfmIK1","uoStw9iGoT","pv0i7aFFss","KASQ8ReKEW","ciuWzfaHir","ZzJHWS2Dfu","mX2GEyEfy9",
-"m4bxUNxx9V","WDVWJWmadA","TwanoWDVWJ","cmXIXd85a9","FjHXRuvf7A","CNHmvrKDLJ","uupzkSjskQ","XflUqUvlv4","8cVD3XyPZN","5ZaEz9GXkX",
-"M3zXLpmeCd","tjQxsgf8rI","2DREslweGy","QWxoTYf2Ec","uvf7Apv0i7","TXQ0ZTa8f6","P6bcgyToGW","XyPZNBGaQY","EoToPzQt6Q","SjskQ7Ow5C",
-"5iGN5DG4sT","POUYSSmGzv","GrDg7jS1aj","tjQxsgjUTu","t59lRuLtKs","JKWYRyEfy9","9XyT9L7cGc","prNT6l83Ud","24ARFWreyP","HlUbFn8pJ9",
-"EoToPNhXdu","AkKTkQbxXc","ix74rcmXIX","Oz8yZX6Pin","SjskQ0MR5X","uN6r37fsYM","FGzgpOUYuF","M6qcGF6PT2","rhl0JGXdoH","HP433jiVBP",
-"HlUbFzbIYY","FLsphpFrrl","yluBxzmLYD","yvOMIi7WMQ","BGaQYQworu","D6rByRACuj","Vprf2FcWrW","Oz8yZGXdoH","zbIYYHlUbF","FhtglpWiOs",
-"AOgEeaL6AJ","vkCHHfFDrJ","Kr8ysi7WMQ","RBhp0QWxoT","VerEARmDcr","fLNg8MmKGJ","48cHLIn3NS","55rfBHRxd8","NOHszIjTwP","S77LHO3iyQ",
-"nnP8oGWqqX","jeskSogLgc","VNCPd0Wr5y","29QAzbgJAz","7ku1p7Ow5C","rhl0J8hJdt","W7cTs8xEKz","ZhwG1Ss0Zu","GWqqXLbRTH","uoStwo8Uyd",
-"rhl0JU3yw5","s7MxkJKWYR","0Wr5ygf8rI","DcpWBru4UG","uvf7ApmeCd","tjQxsU3yw5","Q6hMCXflUq","NAFuwUvlv4","ix74rJIqXi","lpF6Wi3pyd",
-"lsQGoJkzUn","n8pJ9Ul4a1","ZuDtDulk41","Kr8ysiKqhr","U3yw5StlDJ","HfyNQtvdkD","kZANmzqH0W","v8yFNhSSvQ","s93MlKsjRK","qUJMdJJs5m",
-"HzZT8lpF6W","6q6L9zHF1q","FLsphJXljW","CqqaD2DREs","vkCHHStlDJ","l83UdQ6Lix","bZLvSbgJAz","AXpwEOxWIH","zmLYDRpBQm","qQxHPaez9y",
-"y94nwAIYUu","PYBf4Cfgr3","ECMvUWreyP","FGzgp0ao3l","i3pydtuDyS","gf8rI0PktI","Chuy3dQ586","WreyP14FLR","FwEJzRkQke","DQimpFFDui",
-"1j5L8dpe1v","FcWrWxXTI4","RsQUqcL0aE","HP433D6rBy","djsrvO3iyQ","CNHmv9XyT9","tjQxsaez9y","8TxD7XflUq","iqv4kJ2mQi","HfyNQFNYIM",
-"zQt6QpvgjS","FGzgpjzUqR","uJScXuupzk","KZamHprNT6","QChxsiB08l","4W0TlSjskQ","7Ow5CzbIYY","8hJdtFxX9q","aL6AJtuDyS","fmIK1o8Uyd",
-"F6PT2uQIcz","hi5X7yEfy9","ZhwG1SjskQ","LDk6fRACuj","jS1ajbrhlQ","jtn0X5nmWv","SmGzvrKDLJ","5VZjSMmKGJ","uN6r37X3uy","Cfgr3RzaZA",
-"Waim69eoRc","QworuB3qem","8U2nUJKWYR","S77LHW7cTs","YjB9t7Ow5C","3otm6JKWYR","lweGyM3zXL","2Yz7EAIYUu","Cfgr3LDk6f","BCxeCL7cGc",
-"pv0i7L7cGc","BFkb8HlUbF","L7cGcrz7Ut","dpe1vMkgy8","qaofNMGlTF","Vprf2n8pJ9","WDVWJWaim6","QYxC08cVD3","ogLgcnFqik","4W0TlAIYUu",
-"8TxD7ZuDtD","24ARFzFgtB","1j5L8wiHrZ","GrDg70MR5X","vkCHHRmDcr","aez9yjeskS","bZLvSOUqFM","VNCPdhe9IA","RxrsmRpBQm","tjQxsECMvU",
-"mz8gxS77LH","Ul4a1POUYS","euZA5VerEA","s7Mxkix74r","s7MxkChuy3","Ul4a17ku1p","Chuy3kB5nP","S77LHVjCZq","Z4I1vfLNg8","hYBCKvLsmS",
-"7lUXZfaHir","YjB9t0MR5X","pAhR1Y1mC0","uPX7G0ao3l","gIYvEX6Pin","lpF6Wy94nw","RzaZAtAOsr","B3qemprNT6","No0QbKsjRK","n1pmOFGzgp",
-"JJs5mO3iyQ","b29RJb29RJ","WPmlxtAOsr","RsQUqs93Ml","fcwDani2v1","UlU3MQChxs","WaWsvTXQ0Z","pv0i7oGu6x","bgJAzNcICA","M6qcGMmKGJ",
-"Yh1hFb29RJ","S77LHCp3mZ","IRh48bgJAz","M3zXLguMb8","a00b5Ul4a1","55rfBF6PT2","0BmCyqQxHP","NcICAFcWrW","5nmWv580YD","rKDLJUmaEv",
-"kB5nPIRh48","Nxx9VuTacx","UmaEvRBhp0","KASQ8bZLvS","64s8NuQIcz","pFrrlZzJHW","RzaZAo8Uyd","CdyBVk85Ae","AOgEezY1GY","jSjS3yofH3",
-"JKWYREOE1o","TXQ0Z8hJdt","8RCUAuAWyp","tAOsrQnJ1S","618DiU3yw5","h1zcHP6bcg","lm0pDtjQxs","MezSWRsQUq","6AFT03weIF","hUTw7iwzGk",
-"RmDcrgIYvE","oGu6xvOqCE","2Yz7Ehe9IA","AOgEeZUnqt","8U2nU8RCUA","k85AeO3iyQ","x3LDee6e4z","Uvlv4C2Irc","I7p2acL0aE","UmaEvFLsph",
-"Pb1panlaBy","1v5hHi7WMQ","QClRLrKDLJ","nlaByaL6AJ","rz7UtAOgEe","pT8wu8TxD7","7X3uyzQt6Q","pvgjS2ZHdk","jeskSdpe1v","ix74rCfgr3",
-"FLsphFjHXR","lXFOBoGu6x","K20wKiB08l","jiVBPLbRTH","pmeCdIBe8k","QClRL0PktI","lweGyRACuj","M6qcGyofH3","ix74rX6Pin","zQt6QZzJHW",
-"JRJQBzQt6Q","4dEz6pWiOs","55rfBv1Hln","xciqpYh1hF","AkKTkJ2mQi","DQimpi7WMQ","h1zcHzz4ZU","gdQsSsx5Gl","CdyBVdhSuH","jtn0Xmz8gx",
-"4dEz62ZHdk","Mkgy8Gv3Fq","HfyNQsqVrf","fcwDaGWqqX","Kr8ysNcICA","HRxd8DG4sT","0BmCy5nmWv","zQt6QlH1kt","aDGtSaez9y","mz8gxCxVEf",
-"lweGySjskQ","7fsYMAXpwE","IBe8kvOqCE","ksJbyAkKTk","Q6LixFVMxo","lm0pDSs0Zu","rz7UtpvgjS","7lUXZ7fKYU","dpe1vru4UG","a00b5W3VFH",
-"fmIK1aL6AJ","CqqaDwDajX","2ZHdkksJby","2hEEUyluBx","JJs5muvf7A","zz4ZUwiHrZ","HP433MojnP","Q6LixZJTXH","9y4lwW3VFH","pFrrlfcJOy",
-"FnPFBFLsph","BCxeCdmoS7","2Yz7EuAWyp","dmoS7G1RhS","RmDcrQ6hMC","6AFT0pmeCd","Oz8yZ580YD","fFDrJaFFss","AgJHQkZANm","zbIYYRpBQm",
-"jzUqRThjNn","RzaZA8U2nU","FLsphHRxd8","QssNCJRJQB","55rfBFwEJz","taOXKTa8f6","1v5hHGSQwj","QChxsfqypy","aFFssWMiS3","4W0TljfREu",
-"0KyfsrKDLJ","zY1GYaL6AJ","Zv7z0AXpwE","KZamHHRxd8","U3yw5fLNg8","vLsmSFVMxo","euZA5y94nw","zY1GYLDk6f","Ul4a1ZhwG1","HRxd8ReKEW",
-"BbwgAnnP8o","mz8gxyofH3","QbxXcksJby","uTacxtAOsr","5Namm1LB1L","lm0pDMezSW","ix74r5drc6","CIShGzY1GY","fcJOyK20wK","BpYhVTXQ0Z",
-"IKxdLfFDrJ","KZamHWDVWJ","8U2nUEdBKc","brhlQpvgjS","SjskQgdQsS","POUYSuN6r3","EoToPsoy9t","8U2nUs7Mxk","d85a9TXQ0Z","JJs5mVjCZq",
-"MaJQsIjTwP","9eoRcgtCA5","8U2nUtAOsr","jSjS3BpYhV","oQ87r2TRI7","RBhp0k85Ae","7hyVvogLgc","guMb8MezSW","uoStwVprf2","iB08lGWqqX",
-"sqVrfbZLvS","kZANmpv0i7","WmadAjzUqR","VjCZq2Nslm","tvdkD5Drn0","mX2GEo8Uyd","fcwDaHRxd8","gIYvEHlUbF","i3pydBFkb8","d85a9aL6AJ",
-"fcJOy5Drn0","4W0TluJScX","Dz1R3NhXdu","OxWIH2hEEU","MmKGJ0YAGH","kB5nP29QAz","DLhzMqaofN","fcJOy8cVD3","he9IA5Drn0","0Wr5yx3LDe",
-"rKDLJ2TRI7","0h1b17lUXZ","vOqCEbZLvS","tl72WpmeCd","RmDcr5drc6","guMb8NhXdu","5iGN51j5L8","P6bcgoQ87r","WreyP0h1b1","VLTy6Yf2Ec",
-"0MR5XBbwgA","MGlTFoGu6x","aez9yuQIcz","a00b5uupzk","MGlTFyofH3","5nmWvkZANm","v8yFNuJScX","Twanos7Mxk","MmsIo0BmCy","WPmlxRsQUq",
-"K4GS88U2nU","SmGzv3otm6","Z4I1vLbRTH","s4786Vprf2","VLTy6tAOsr","FGzgptl72W","AXpwEn8pJ9","Gv3FquN6r3","7fsYMuQIcz","2Nslm16lHc",
-"Kr8ysjS1aj","07n1cm4bxU","uvf7AzbIYY","Waim6QYxC0","QWxoT4QMc9","JkzUnGv3Fq","G1RhSG1RhS","uAWyp8cVD3","lH1ktRxrsm","3weIFC2Irc",
-"6AFT0uZPqg","bZLvSzqH0W","pmeCdHP433","rz7Utni2v1","d7vjMydG8U","0KyfsazIWp","n8pJ9CNHmv","sx5GleuZA5","cQOnvmX2GE","atef2MGlTF",
-"tAOsr6AFT0","I7p2at98iW","gtCA58hJdt","euZA5VNCPd","pv0i7Qworu","t98iWru4UG","zFgtB24ARF","jS1aj7fsYM","kZANmrhl0J","h1zcHv2eC3",
-"0KyfsRACuj","FcWrWFPfSE","RsQUq7X3uy","VLTy6kB5nP","hYBCKCK5W7","uZPqgi3pyd","azIWpDQimp","mz8gxjeskS","Kr8ys8RCUA","0Kyfshe9IA",
-"vLsmSF6PT2","SmGzvB3qem","Twano4W0Tl","ThjNn0ao3l","ydG8Urz7Ut","faHiro8Uyd","ZzJHWlweGy","PYBf4gdQsS","QbxXcPOUYS","B3qemfFDrJ",
-"0ao3lVprf2","gjUTuQnJ1S","fFDrJaDGtS","l83UdEoToP","24ARFOUqFM","580YDRsQUq","t59lRFPfSE","yEfy9Nxx9V","VerEAhe9IA","FcWrWkZANm",
-"aL6AJvkCHH","yvOMIDcpWB","Zv7z0Mm8si","fFDrJkZANm","7ku1pyluBx","iB08lJKWYR","6AFT0gf8rI","GWqqXFjHXR","rz7UtlXFOB","GXdoHUvlv4",
-"oQ87rvLsmS","dmoS7DG4sT","VIlwP9rlg9","guMb80ao3l","0YAGHjzUqR","7fKYUoQ87r","HP433ZzJHW","ECMvUnnP8o","WDVWJ7Ow5C","Oz8yZCfgr3",
-"6q6L99XyT9","9y4lwguMb8","tuDySJIqXi","6AFT00BmCy","ni2v1zY1GY","In3NSzqH0W","WmadA1LB1L","iwzGkpvgjS","y94nw0YAGH","3weIFP6bcg",
-"WMiS3piJSk","Uvlv4h1zcH","No0QbciuWz","oVQp62Nslm","ksJbyqUJMd","t98iWECMvU","lweGyFhtgl","Mkgy82Nslm","uAWypMm8si","he9IAQnJ1S",
-"jzUqRWMiS3","Zv7z0O3iyQ","zHF1qVjCZq","VerEADQimp","iqv4kW3VFH","Ul4a1lsQGo","Mkgy8P6bcg","RzaZAiB08l","SjskQbgJAz","cL0aEiwzGk",
-"aL6AJOUqFM","NAFuwm4bxU","uZPqguAWyp","rhl0JTCgPp","5drc6LewvM","aFFssuupzk","6AFT0azIWp","Kr8ysLDk6f","NOHszCdyBV","EOE1ofqypy",
-"cmXIXYw2oU","fcwDaFjHXR","0h1b1HRxd8","NcICAprNT6","hi5X7dmoS7","s4786QnJ1S","0h1b1qUJMd","55rfBcmXIX","IKxdLJkzUn","VNCPdGXdoH",
-"kZANm7ku1p","K20wKSbRYy","3weIFlj07Q","YOfrYK4GS8","soy9t8hJdt","uupzkpWiOs","0h1b1Ul4a1","FPfSEkB5nP","Nxx9V9iGoT","FjHXR5Namm",
-"pAhR148cHL","qUJMdIjTwP","9GXkX5iGN5","jiVBPsx5Gl","VNCPdpAhR1","4QMc9BCxeC","Uvlv4zY1GY","TXQ0ZQChxs","2hEEUbZLvS","tjQxsTa8f6",
-"Oz8yZgjUTu","h1zcHRxrsm","he9IANhXdu","BbwgAhi5X7","24ARFC2Irc","oQ87rpFrrl","wDajXtvdkD","FhtglVBjhz","AXpwEZJTXH","8U2nUXyPZN",
-"QworuJRJQB","JkzUnW3VFH","5nmWvMmKGJ","jzUqRzz4ZU","SbRYyJIqXi","0MR5X2hEEU","uPX7Grz7Ut","d7vjMOUYuF","8cVD3P6bcg","sqVrf9GXkX",
-"mX2GEQClRL","uJScXMm8si","BFkb8I7p2a","No0QbYf2Ec","Yw2oU0ao3l","he9IAUl4a1","G1RhSTCgPp","WaWsvZuDtD","i3pydtlILt","8U2nUpFrrl",
-"GrDg7atef2","v1HlnCdyBV","55rfBpAhR1","In3NSRpBQm","iB08liwzGk","AXpwEL7cGc","8TxD7oVQp6","3weIFuAWyp","GrDg7lCMxy","cQOnvciuWz",
-"lH1ktNcICA","VIlwP7hyVv","oVQp6KASQ8","hE1Qlatef2","l83UdZuDtD","2Yz7EnFqik","aFFss7Ow5C","aDGtS1LB1L","xReecHzZT8","fcJOy8hJdt",
-"okgRi48cHL","Gv3FqBFkb8","CdyBVQWxoT","VNCPd6AFT0","QClRLi3pyd","NhXduVNCPd","7hyVvjeskS","cL0aE7X3uy","QWxoT2DREs","zmLYD8xEKz",
-"VerEAlCMxy","SWfousqVrf","gIYvEKr8ys","lj07QGrDg7","h1zcHReKEW","uQIcz48cHL","rz7UtfLNg8","pWiOsOHaBz","CIShGNxx9V","fcwDaMK07Y",
-"soy9tThjNn","VLTy6tuDyS","D6rBydpe1v","CIShGEOE1o","bgJAzThjNn","prNT6MaJQs","ZUnqtciuWz","fFDrJzbIYY","W7cTsPOUYS","1j5L8MezSW",
-"zFgtBm4bxU","cL0aEuLtKs","S77LHfcJOy","lH1ktx3LDe","9iGoTtuDyS","jSjS3NcICA","3otm6FNYIM","nlaByk85Ae","S77LHix74r","EOE1oJJs5m",
-"M6qcGxReec","jeskSZuDtD","zFgtBMmKGJ","6AFT00h1b1","zY1GYksJby","QWxoTuoStw","BCxeCdhSuH","uTacxKASQ8","CdyBVuupzk","LDk6fQ6Lix",
-"aez9ySmGzv","9y4lwtuDyS","2ZHdkd7vjM","MojnPEOE1o","TXQ0Z2hEEU","VerEA5nmWv","kZANm9rlg9","5nmWvVBjhz","dQ586FPfSE","0h1b1VNCPd",
-"I7p2a2DREs","ZzJHWo8Uyd","48cHLuLtKs","JRJQB2Nslm","hUTw7gdQsS","a00b5VBjhz","sx5GlMaJQs","b29RJ2DREs","EOE1oWMiS3","Chuy39rlg9",
-"IRh48In3NS","aDGtSl83Ud","KsjRKjS1aj","OHaBzuPX7G","SbRYyVerEA","IKxdLAXpwE","ulk41WaWsv","lkMUAh1zcH","ReKEWMezSW","6q6L9xXTI4",
-"B3qemlsQGo","CqqaD8cVD3","5IhmGW7cTs","3otm6EOE1o","KASQ8tlILt","07n1c2hEEU","yEfy9MGlTF","S2Dfuo8Uyd","VerEAUl4a1","Mm8sihE1Ql",
-"AXpwECfgr3","SWfouQ6hMC","bgJAz5Namm","Pb1paJkzUn","GrDg7dhSuH","AOgEelm0pD","uJScXStlDJ","HP433jSjS3","Zv7z0m4bxU","NhXdu5iGN5",
-"NOHszpWiOs","8TxD7Cp3mZ","bgJAzOUqFM","aL6AJ29QAz","Kr8ysZv7z0","Nxx9VLbRTH","VjCZq4QMc9","YOfrYuN6r3","AgJHQpFrrl","TCgPp2ZHdk",
-"jtn0Xo8Uyd","vLsmSjeskS","9rlg9uZPqg","7fKYU0Kyfs","16lHcGSQwj","ZUnqtMkgy8","QnJ1SKZamH","WmadAVerEA","sqVrf5Namm","uLtKsFwEJz",
-"GrDg7F6PT2","ThjNnkB5nP","FxX9qSWfou","Y1mC0VLTy6","WreyPHP433","SmGzvOxWIH","s93MluAWyp","ReKEW29QAz","lpF6WaDGtS","uN6r3OUYuF",
-"GXdoHb29RJ","UlU3MeuZA5","LewvMtaOXK","8U2nU64s8N","zY1GYhE1Ql","piJSklkMUA","bgJAzRBhp0","guMb8GXdoH","1LB1LFnPFB","StlDJjSjS3",
-"WmadAL7cGc","suY4xhE1Ql","8cVD3Ul4a1","ZuDtDW7cTs","tAOsrqUJMd","iKqhrzmLYD","v8yFNlm0pD","Mkgy8e6e4z","xReecGSQwj","iwzGk7X3uy",
-"0YAGHYw2oU","lm0pDcmXIX","uJScXuAWyp","SjskQmX2GE","8RCUAcL0aE","GrDg7n1pmO","Q6LixazIWp","m4bxUFwEJz","a00b507n1c","QbxXcd7vjM",
-"FPfSE5IhmG","8cVD3fcwDa","Zv7z0e6e4z","uAWypdhSuH","t98iW7Ow5C","e6e4zJ2mQi","tAOsrYf2Ec","AOgEepmeCd","1v5hHiKqhr","IKxdLRBhp0",
-"QChxsKr8ys","VIlwPThjNn","AkKTkQ6Lix","Kr8ys1v5hH","M3zXLJIqXi","uN6r3pT8wu","8hJdtaDGtS","RmDcrFNYIM","5Nammsoy9t","Y1mC04W0Tl",
-"zz4ZUNcICA","Mkgy8lCMxy","TCgPpfaHir","9eoRcO3iyQ","K20wKDcpWB","2ZHdkl83Ud","QbxXc4W0Tl","7Ow5CVNCPd","qUJMdv2eC3","16lHcB3qem",
-"RkQkekB5nP","VNCPdy94nw","i3pydIn3NS","ZUnqtEdBKc","oQ87rdpe1v","Uvlv4aDGtS","8xEKzTCgPp","gIYvEfLNg8","7lUXZoQ87r","iKqhreuZA5",
-"d85a9ulk41","8FmFHhe9IA","MmsIoIn3NS","8cVD3hSSvQ","EoToP5Namm","POUYSaDGtS","8TxD7Waim6","uZPqgMkgy8","lViBvFjHXR","mz8gxyEfy9",
-"t59lRbZLvS","5ZaEzmz8gx","Rxrsm5Namm","ZhwG1rKDLJ","xReecjeskS","gtCA55nmWv","YOfrYBCxeC","FcWrWxciqp","lpF6WFLsph","AOgEeMkgy8",
-"KsjRK5IhmG","55rfBLDk6f","gjUTuFxX9q","piJSk9eoRc","taOXKd7vjM","Mm8siF6PT2","7Ow5CkZANm","jfREujeskS","7ku1ptvdkD","uupzkni2v1",
-"faHir24ARF","fmIK1soy9t","uupzkQChxs","YjB9tDG4sT","FwEJz7Ow5C","zmLYD48cHL","9eoRcVprf2","5Mg9rtl72W","vLsmSBbwgA","zY1GYUlU3M",
-"nnP8o8TxD7","FNYIMt59lR","JIqXiYw2oU","uTacxRzaZA","IjTwPsoy9t","prNT6fFDrJ","5VZjS16lHc","h1zcHMkgy8","WMiS30YAGH","FLsphyEfy9",
-"Yw2oUGrDg7","cQOnv5Mg9r","Gv3Fqm4bxU","s93MlCIShG","RBhp0s4786","pFrrlYOfrY","aez9yWMiS3","GWqqXVIlwP","9GXkXwDajX","dhSuHn1pmO",
-"Chuy3ReKEW","55rfBhSSvQ","ECMvU8xEKz","yToGWAIYUu","pFrrlqaofN","vLsmSyToGW","WDVWJ9iGoT","he9IAW7cTs","Yf2Ec4W0Tl","BbwgAWMiS3",
-"6q6L9y94nw","KZamHb29RJ","NOHszMkgy8","ulk41EdBKc","Uvlv4LewvM","VLTy62DREs","ZuDtDlViBv","DQimppmeCd","1j5L8HzZT8","Q6LixJ2mQi",
-"ydG8UogLgc","IRh485Mg9r","v8yFNtaOXK","BGaQYazIWp","cQOnvrz7Ut","UlU3MlCMxy","v2eC3hSSvQ","ZUnqtsuY4x","xXTI49y4lw","azIWpuZPqg",
-"tAOsrxXTI4","v1HlnuLtKs","hUTw7CNHmv","IRh485VZjS","55rfBsqVrf","uN6r3xciqp","UmaEvtaOXK","45cIHuQIcz","5Drn0X6Pin","ZJTXHbrhlQ",
-"aFFssMGlTF","RsQUqblLA9","pWiOsdjsrv","CNHmvYw2oU","FxX9qWDVWJ","8hJdthi5X7","2Yz7E0ao3l","yluBxRpBQm","QChxs7ku1p","oGu6xuQIcz",
-"xciqpMm8si","euZA52TRI7","QnJ1S0MR5X","7ku1puAWyp","7X3uyhUTw7","NOHszi3pyd","uTacxHRxd8","he9IAx3LDe","mX2GEtuDyS","gjUTu2Nslm",
-"OHaBzi3pyd","AkKTkt59lR","NhXdutuDyS","2TRI7MmKGJ","07n1cAOgEe","QClRL2hEEU","zHF1qBCxeC","lH1ktydG8U","fLNg8s4786","MK07YuZPqg",
-"7ku1ppFrrl","45cIHrhl0J","uQIczFxX9q","nlaByBpYhV","14FLRmX2GE","pvgjS0h1b1","MojnPd85a9","lXFOBAmdQd","ni2v1Yw2oU","m4bxUaFFss",
-"azIWpSbRYy","zmLYDAOgEe","8TxD7AkKTk","1LB1LoVQp6","jzUqRUlU3M","HlUbF9XyT9","BbwgAtaOXK","jSjS37ku1p","Zv7z07fKYU","hYBCKfaHir",
-"d85a9GSQwj","FcWrWeuZA5","jfREuVNCPd","jtn0XAmdQd","MK07YzY1GY","DcpWBuAWyp","FnPFBpWiOs","t98iWZv7z0","d7vjMix74r","euZA59y4lw",
-"Zv7z0P6bcg","XflUqaL6AJ","cShY27fKYU","kZANmKr8ys","GXdoHEdBKc","CxVEfv8yFN","s93Ml4QMc9","5drc6MaJQs","DQimpEdBKc","lj07QNcICA",
-"YOfrY24ARF","jfREuh1zcH","uTacx7lUXZ","cQOnvWaim6","618Di1LB1L","RpBQmjzUqR","aDGtSYOfrY","Yh1hFjzUqR","ydG8UF6PT2","kZANmL7cGc",
-"VLTy6FcWrW","J2mQi9GXkX","tAOsrAkKTk","MezSWxXTI4","qaofNtAOsr","EdBKcJRJQB","ThjNnCNHmv","ZzJHWrz7Ut","No0QbCdyBV","uvf7ADG4sT",
-"Cp3mZfmIK1","8hJdt7fsYM","TCgPpAkKTk","RzaZAiwzGk","TXQ0ZqUJMd","tlILtDcpWB","qaofNcQOnv","VNCPd29QAz","v2eC3IBe8k","0KyfsaDGtS",
-"AXpwEGXdoH","CK5W7ni2v1","0KyfsMK07Y","ni2v107n1c","pAhR10h1b1","taOXKVjCZq","FxX9qZJTXH","Qworujtn0X","AgJHQM6qcG","wiHrZDLhzM",
-"brhlQzQt6Q","ogLgcMmKGJ","FcWrWblLA9","FhtglzY1GY","StlDJGSQwj","Yf2EcFNYIM","jSjS3G1RhS","lweGyNxx9V","WmadAVLTy6","DcpWB5iGN5",
-"XflUqGSQwj","mX2GEYjB9t","ReKEWGv3Fq","dpe1vCIShG","JKWYRIBe8k","m4bxUStlDJ","suY4xJ2mQi","yToGWHlUbF","4dEz64QMc9","hYBCKydG8U",
-"CIShGAkKTk","lXFOBFNYIM","taOXK64s8N","8U2nUI7p2a","Y1mC064s8N","16lHclViBv","9GXkXAXpwE","TCgPpix74r","P6bcgOHaBz","1j5L84QMc9",
-"SWfouFnPFB","s93MlEoToP","RpBQmprNT6","Yf2Ec5iGN5","fcJOygjUTu","5VZjSWDVWJ","cQOnviKqhr","dQ586JXljW","9iGoTd85a9","qQxHPulk41",
-"uZPqggtCA5","FLsphtaOXK","pAhR1Mm8si","uupzkbgJAz","64s8NlpF6W","Yh1hFIRh48","piJSkdpe1v","jiVBPfcwDa","0YAGH5drc6","RsQUqPb1pa",
-"xReecGXdoH","7lUXZe6e4z","07n1cZJTXH","t59lRaFFss","EOE1oJIqXi","zbIYYgdQsS","NAFuwChuy3","vkCHHCNHmv","dhSuH48cHL","Waim6rKDLJ",
-"5ZaEzQworu","5Mg9rIRh48","IBe8kFNYIM","Q6Lixzz4ZU","5Nammtl72W","ZUnqtDG4sT","Mm8siPYBf4","I7p2afcwDa","K4GS8n8pJ9","h1zcHkB5nP",
-"DLhzMS77LH","QChxssqVrf","QssNC64s8N","7lUXZgIYvE","9y4lw9rlg9","fLNg80Wr5y","RsQUqFPfSE","1v5hHGXdoH","TXQ0ZWaWsv","cQOnvTa8f6",
-"7fsYMVjCZq","vOqCELDk6f","SWfouVjCZq","Yf2Eco8Uyd","hi5X75drc6","FPfSEVerEA","taOXKm4bxU","Pb1paeuZA5","RBhp0uPX7G","WaWsv14FLR",
-"lkMUAVerEA","ZUnqt7Ow5C","2DREsS77LH","LbRTHKsjRK","uvf7A8TxD7","1j5L8gdQsS","o8UydjS1aj","7fKYUYh1hF","tlILtoQ87r","zQt6QfFDrJ",
-"ogLgcYh1hF","9GXkXRpBQm","fcJOyYOfrY","pAhR1uQIcz","9XyT9MezSW","fqypyQChxs","LbRTHzQt6Q","he9IAyofH3","GrDg7DQimp","xReecYw2oU",
-"d7vjMAOgEe","NAFuwaFFss","a00b5v8yFN","B3qemjfREu","8hJdt8hJdt","aez9yiB08l","WPmlxMK07Y","Z4I1vK4GS8","Cp3mZjtn0X","uQIczdmoS7",
-"qQxHP2ZHdk","QClRLfFDrJ","GWqqXqaofN","dmoS7gtCA5","MGlTFkB5nP","TXQ0ZQ6Lix","zHF1qHlUbF","faHirv1Hln","L7cGcZUnqt","J2mQibgJAz",
-"NcICAyEfy9","wDajXv8yFN","VerEAS77LH","VBjhziB08l","Gv3Fqulk41","Y1mC0Pb1pa","G1RhSrKDLJ","F6PT2ZhwG1","9rlg9zmLYD","uTacxMaJQs",
-"lCMxyVjCZq","AkKTkDcpWB","QYxC0t59lR","AgJHQgIYvE","IjTwPqQxHP","Kr8ysGXdoH","zmLYDW3VFH","CxVEfazIWp","F6PT29rlg9","W7cTsni2v1",
-"RkQkeBbwgA","2TRI7GrDg7","4dEz6WmadA","9XyT9vkCHH","14FLRIn3NS","FGzgpy94nw","mX2GENAFuw","yvOMIix74r","n8pJ95Drn0","Cp3mZEoToP",
-"uTacxVprf2","jS1ajgdQsS","0PktIs93Ml","EOE1ohE1Ql","Gv3FqFcWrW","jeskSUmaEv","4dEz6gf8rI","nFqikM3zXL","OUYuFhUTw7","XflUq0Kyfs",
-"ix74ri7WMQ","DcpWBzmLYD","JRJQBNOHsz","mz8gxzFgtB","ECMvUSs0Zu","suY4xYjB9t","HfyNQCIShG","b29RJ48cHL","WreyPFwEJz","lCMxyVNCPd",
-"uLtKsuvf7A","2Yz7EuLtKs","RkQkerKDLJ","7fKYUsx5Gl","zz4ZUDQimp","YjB9tBGaQY","Mkgy8d7vjM","gjUTuyofH3","Oz8yZReKEW","5IhmGpAhR1",
-"29QAzRxrsm","X6PinlsQGo","ydG8UHP433","iB08lC2Irc","Rxrsm9rlg9","qQxHP2Nslm","i3pydVNCPd","FxX9qulk41","RpBQmC2Irc","ZJTXHjfREu",
-"Zv7z0DcpWB","bZLvSfmIK1","VLTy6M6qcG","cShY2jSjS3","Uvlv4gIYvE","TwanoZv7z0","Ss0Zui7WMQ","CNHmvxciqp","In3NSNhXdu","No0QbWDVWJ",
-"FPfSEAmdQd","vOqCEx3LDe","ReKEWVBjhz","hSSvQAIYUu","x3LDeBFkb8","hE1QlUl4a1","MaJQs3weIF","v1HlnZv7z0","G1RhSyofH3","No0Qb3weIF",
-"Pb1paCK5W7","Twano55rfB","QClRL6q6L9","7fsYMJXljW","StlDJyofH3","D6rByQssNC","CIShGK4GS8","2hEEUm4bxU","VIlwPe6e4z","C2Ircl83Ud",
-"Cp3mZ5Drn0","dQ586FwEJz","OUYuFlm0pD","5VZjSnlaBy","guMb8lH1kt","StlDJ3otm6","gtCA58RCUA","vkCHHI7p2a","YjB9te6e4z","1v5hHd85a9",
-"OxWIHrz7Ut","WaWsvblLA9","cShY2t98iW","Uvlv4IRh48","1v5hHX6Pin","2hEEUs7Mxk","lCMxyDQimp","Ss0ZuoQ87r","rKDLJt98iW","AOgEeWMiS3",
-"ZUnqtlViBv","nlaByNxx9V","WPmlxFGzgp","EoToPUlU3M","RsQUq7fsYM","vkCHHPOUYS","d7vjM9GXkX","Nxx9VtlILt","v1Hlndpe1v","lj07Qtl72W",
-"hE1Qldjsrv","X6PinRACuj","blLA90MR5X","9y4lwVjCZq","0MR5XSs0Zu","JKWYR9XyT9","qaofNjSjS3","oQ87rSs0Zu","8TxD7JJs5m","L7cGc48cHL",
-"5Nammxciqp","uJScXl83Ud","0YAGHulk41","MmsIo45cIH","7lUXZuvf7A","tjQxstl72W","Dz1R3WPmlx","MaJQs8cVD3","Pb1pacQOnv","OUYuFBpYhV",
-"n1pmO2ZHdk","2ZHdkaDGtS","HlUbFuZPqg","AIYUuB3qem","5drc6rKDLJ","8RCUAulk41","XyPZNuLtKs","8xEKzzmLYD","xReecChuy3","AXpwEb29RJ",
-"QYxC0tjQxs","X6PinRsQUq","In3NSlCMxy","pmeCduPX7G","MmsIoKr8ys","Ta8f6I7p2a","580YDMmsIo","EoToPuLtKs","VNCPdyluBx","sx5GlB3qem",
-"qQxHPQbxXc","ECMvUSbRYy","FxX9qyEfy9","yofH3AXpwE","GWqqXmX2GE","d85a9dhSuH","J2mQiuQIcz","he9IAgtCA5","zmLYDyToGW","9y4lw8TxD7",
-"GXdoH0YAGH","QWxoTWMiS3","MmsIosx5Gl","9iGoTzqH0W","55rfBDLhzM","HzZT82Yz7E","SjskQU3yw5","dmoS7m4bxU","RACujBpYhV","uTacx14FLR",
-"SjskQAmdQd","AkKTkWreyP","QClRLIKxdL","Q6LixmX2GE","ulk415Namm","LDk6fFVMxo","hE1QluQIcz","vLsmSv8yFN","JRJQBZzJHW","GWqqX8RCUA",
-"Zv7z0G1RhS","s4786qaofN","uoStwQYxC0","uPX7G9XyT9","Oz8yZhi5X7","v2eC3d85a9","JJs5mQworu","rhl0JqaofN","ZhwG1AIYUu","VerEAuZPqg",
-"0MR5XvkCHH","Gv3FqGSQwj","cQOnvQ6hMC","ydG8UkZANm","FNYIM0ao3l","xciqpGXdoH","zqH0W1j5L8","WmadAzqH0W","16lHcyluBx","jS1ajOUYuF",
-"zFgtB9iGoT","Yh1hFRzaZA","lH1ktM3zXL","Mm8siECMvU","VerEAaL6AJ","TCgPpPb1pa","QworuAOgEe","t98iWciuWz","n1pmOm4bxU","pAhR1I7p2a",
-"7ku1pzY1GY","tuDySSWfou","JJs5mBFkb8","ydG8UFcWrW","5Mg9rQWxoT","fqypyZuDtD","gf8rItlILt","FGzgppAhR1","hYBCKcmXIX","FLsph16lHc",
-"M3zXL9iGoT","EoToPHzZT8","ZzJHWuoStw","FnPFBIRh48","Pb1paStlDJ","jtn0XbZLvS","he9IAZUnqt","tlILtM3zXL","QssNChi5X7","8RCUAFNYIM",
-"AOgEeuoStw","2ZHdkqaofN","zFgtBMmsIo","ksJbypvgjS","x3LDeMojnP","l83Ud1v5hH","ydG8USs0Zu","S2DfuRxrsm","5IhmGLDk6f","gdQsSWDVWJ",
-"tl72WRBhp0","VLTy6CNHmv","KASQ845cIH","7hyVv9rlg9","fcJOyXyPZN","Cp3mZd7vjM","NcICAh1zcH","HRxd80BmCy","nFqikOHaBz","o8UydAgJHQ",
-"In3NS2hEEU","dpe1vtjQxs","oVQp6s7Mxk","rKDLJzY1GY","RACujrKDLJ","qaofNh1zcH","ZzJHWdpe1v","5Drn0wDajX","IBe8kIn3NS","P6bcg618Di",
-"ogLgcYf2Ec","d7vjMI7p2a","fFDrJn1pmO","MK07YQworu","3otm6DcpWB","Waim6Ss0Zu","BbwgAiqv4k","uLtKsSjskQ","cQOnvBCxeC","BpYhVSs0Zu",
-"TCgPpUmaEv","IKxdLXflUq","lViBvJIqXi","2ZHdk07n1c","fcJOyrz7Ut","blLA9azIWp","Dz1R3IRh48","uJScXUvlv4","BCxeC5IhmG","8FmFHFGzgp",
-"Pb1paWPmlx","KZamHlkMUA","07n1cpT8wu","Zv7z0lpF6W","yluBxuQIcz","3weIFaDGtS","faHirOHaBz","iwzGkCK5W7","2DREs64s8N","l83UdaL6AJ",
-"SbRYylsQGo","RBhp0iKqhr","aez9yfcwDa","FjHXRFnPFB","v2eC3LbRTH","JKWYRxciqp","lsQGoAXpwE","mX2GEhSSvQ","pAhR15iGN5","tl72Wuupzk",
-"FFDui9y4lw","0KyfsQYxC0","CK5W7ulk41","ydG8UJ2mQi","fcJOyi3pyd","pT8wuIKxdL","s7MxkcmXIX","djsrv0Wr5y","SmGzvs4786","l83Ud3otm6",
-"djsrv45cIH","5iGN5OUqFM","SjskQMkgy8","ni2v13otm6","JkzUnAgJHQ","BFkb8OUqFM","NOHszM6qcG","lpF6W5ZaEz","VLTy6cQOnv","JRJQBDLhzM",
-"oGu6xFFDui","i3pyd9rlg9","XyPZNkB5nP","0YAGHpmeCd","MmKGJ0BmCy","zqH0WLbRTH","5VZjS29QAz","LbRTH16lHc","7fsYMLbRTH","X6PinBbwgA",
-"iKqhrWDVWJ","RBhp0zbIYY","FjHXRogLgc","EoToP7X3uy","WreyPJXljW","DLhzMh1zcH","jSjS3dQ586","7lUXZ45cIH","5VZjSUmaEv","rKDLJ7hyVv",
-"SbRYyzqH0W","5ZaEzzz4ZU","VerEAJJs5m","16lHc0Wr5y","ZuDtDjtn0X","brhlQZzJHW","BFkb8lViBv","tl72WQChxs","vkCHHwiHrZ","RzaZAUmaEv",
-"HzZT8QYxC0","8RCUAYf2Ec","WMiS3Dz1R3","Ta8f6FFDui","Y1mC0v8yFN","aFFsswDajX","sqVrflViBv","6q6L9Ss0Zu","0h1b1djsrv","64s8N8TxD7",
-"fqypyWmadA","MaJQs0PktI","jfREu3weIF","azIWp3weIF","JRJQBJ2mQi","pFrrlLbRTH","lkMUAhSSvQ","9eoRctAOsr","cShY2Qworu","LDk6flweGy",
-"RkQkeqQxHP","rz7UtBCxeC","K20wK9iGoT","14FLRcmXIX","Yh1hFXflUq","QssNCZhwG1","zmLYDhYBCK","Mkgy8VIlwP","Ul4a1JKWYR","zmLYDtvdkD",
-"5Mg9rsoy9t","8cVD3ksJby","d85a9fLNg8","ECMvUX6Pin","yEfy9No0Qb","WMiS38FmFH","8U2nUvOqCE","RkQkeZUnqt","NhXduMm8si","5Drn0h1zcH",
-"fFDrJFPfSE","Yh1hFEOE1o","vOqCEjfREu","dmoS7aFFss","vOqCEsx5Gl","ru4UGlCMxy","pT8wuHP433","9rlg9h1zcH","ZJTXHMezSW","xXTI4qQxHP",
-"gtCA5Cfgr3","JXljWFGzgp","ECMvUfLNg8","yvOMIzQt6Q","VIlwPPYBf4","pmeCd5VZjS","lCMxysoy9t","U3yw5U3yw5","tuDySpiJSk","VLTy6JJs5m",
-"DcpWBlCMxy","45cIHbgJAz","NOHszQYxC0","HRxd8dmoS7","lpF6WCK5W7","s4786prNT6","pAhR1Gv3Fq","rhl0JRpBQm","UmaEvciuWz","gtCA5fcwDa",
-"Z4I1vNcICA","9GXkX7ku1p","5Drn0RsQUq","zbIYYyluBx","W7cTs9XyT9","GrDg7prNT6","FPfSEtuDyS","wiHrZgdQsS","cShY2sqVrf","B3qemmz8gx",
-"ydG8UM3zXL","PYBf4tvdkD","jeskSK20wK","5Drn0x3LDe","TCgPp7X3uy","K20wK24ARF","SbRYyGv3Fq","I7p2aPYBf4","VerEAuoStw","gIYvE0MR5X",
-"lkMUAsuY4x","okgRilCMxy","WDVWJi7WMQ","ix74rfaHir","hUTw7fcJOy","Y1mC0hi5X7","aez9yJKWYR","OHaBzuN6r3","WPmlxzFgtB","lCMxypT8wu",
-"kZANmksJby","soy9tXflUq","WPmlxblLA9","pAhR1zHF1q","Q6hMCyluBx","euZA5JIqXi","NhXdubZLvS","Zv7z0WaWsv","n1pmOy94nw","WPmlxv2eC3",
-"WPmlxfaHir","5Drn0atef2","ZzJHWaez9y","lpF6WFhtgl","6q6L9NcICA","45cIHtvdkD","tjQxsAIYUu","yToGWwiHrZ","fFDrJFwEJz","Uvlv4nFqik",
-"yEfy9ZzJHW","WMiS3ydG8U","lm0pD8hJdt","lCMxyaDGtS","In3NSv1Hln","nlaBy2TRI7","vLsmSXflUq","M6qcG2ZHdk","vOqCEZhwG1","mz8gxJRJQB",
-"RxrsmlpF6W","8TxD7uLtKs","uJScXzbIYY","EOE1orz7Ut","Dz1R37hyVv","2Yz7EuPX7G","No0QbuQIcz","gtCA5aFFss","8cVD3vOqCE","lsQGoMGlTF",
-"O3iyQxReec","iqv4kpmeCd","tAOsrksJby","EoToPCK5W7","VNCPdWreyP","sqVrfgf8rI","Vprf2G1RhS","n1pmORzaZA","VLTy6aL6AJ","lsQGoZ4I1v",
-"Q6hMCFGzgp","WMiS3xXTI4","Oz8yZVLTy6","VIlwPb29RJ","i7WMQWPmlx","TCgPp0YAGH","lm0pD2ZHdk","lpF6WuAWyp","L7cGcFjHXR","zmLYDL7cGc",
-"0MR5Xjtn0X","s7MxkrKDLJ","hi5X7lpF6W","LbRTHfaHir","No0Qb0Kyfs","618DiFPfSE","Ta8f6qaofN","KZamHtl72W","2Yz7E0h1b1","07n1ctvdkD",
-"FLsphWaim6","NcICAfFDrJ","2NslmWDVWJ","AgJHQ9eoRc","Yf2EcK20wK","K20wKFhtgl","JRJQBAkKTk","yEfy9IjTwP","U3yw5SbRYy","QnJ1Sk85Ae",
-"D6rByvkCHH","UlU3MZJTXH","vLsmSZJTXH","BCxeCQ6hMC","tuDySStlDJ","4dEz6b29RJ","CK5W7ReKEW","CqqaDCK5W7","KsjRK4QMc9","8hJdtZ4I1v",
-"gtCA5Twano","PYBf4uN6r3","oGu6xgtCA5","MmsIoZuDtD","MaJQsgf8rI","DQimplm0pD","QnJ1Sdjsrv","euZA5Cfgr3","Oz8yZydG8U","Chuy3UlU3M",
-"2TRI748cHL","oGu6xlweGy","Waim6Cfgr3","HlUbFdQ586","n8pJ9SbRYy","hSSvQZv7z0","QChxsvkCHH","tl72WWDVWJ","azIWpRpBQm","RpBQmcL0aE",
-"nFqikVLTy6","h1zcH8cVD3","OHaBzblLA9","euZA5JKWYR","UmaEvnlaBy","o8UydpmeCd","5nmWv2DREs","pAhR1wiHrZ","v2eC3NOHsz","3otm6iwzGk",
-"RkQkeyofH3","48cHLHlUbF","7hyVvaFFss","t59lRfaHir","BbwgAguMb8","X6PinK20wK","FVMxoQChxs","nFqikjfREu","4QMc9CNHmv","rz7UtVprf2",
-"Ss0Zuv1Hln","1LB1Lk85Ae","Yf2Ecgf8rI","zY1GYhSSvQ","Uvlv4POUYS","YOfrY7Ow5C","fLNg8UmaEv","iKqhrjzUqR","5Mg9rGSQwj","lViBv0MR5X",
-"Dz1R37fsYM","2TRI7k85Ae","VIlwPSmGzv","LewvMTCgPp","VLTy6FwEJz","Z4I1vHP433","hUTw7Kr8ys","yluBxuJScX","pmeCdBGaQY","d7vjMyluBx",
-"suY4xyToGW","pT8wuMmKGJ","IRh48aFFss","JJs5mn1pmO","BpYhV4W0Tl","ECMvUMojnP","s93MlAkKTk","yofH3kZANm","cL0aE8cVD3","5ZaEz0PktI",
-"RBhp0qUJMd","xXTI44W0Tl","S77LHJJs5m","sx5GlJXljW","6q6L95Drn0","BpYhVgf8rI","2Yz7Et98iW","wiHrZNOHsz","FjHXR3otm6","J2mQifcwDa",
-"lH1ktBpYhV","XflUqBCxeC","NAFuw0PktI","Ss0ZuuTacx","VLTy6CK5W7","qUJMdMmsIo","s4786Ta8f6","0h1b1soy9t","SbRYyBpYhV","0Wr5yM3zXL",
-"U3yw555rfB","5Drn0DcpWB","9rlg9gIYvE","Waim67ku1p","FxX9qd7vjM","5Mg9rFFDui","NcICAFwEJz","jiVBPNo0Qb","7X3uylCMxy","MmsIo9GXkX",
-"5NammXyPZN","TCgPppmeCd","nnP8oRsQUq","uupzkChuy3","ZJTXHVBjhz","2DREslm0pD","ZJTXHsuY4x","1j5L82Yz7E","nFqik48cHL","HRxd8QbxXc",
-"ksJbyyofH3","yEfy9J2mQi","tuDySAXpwE","Q6LixQbxXc","580YDK20wK","uN6r3jSjS3","MmsIozqH0W","DcpWB9eoRc","zz4ZUcShY2","n1pmOpAhR1",
-"DLhzMqQxHP","CIShGMm8si","580YDJKWYR","dpe1v3weIF","bgJAzcL0aE","piJSkrz7Ut","OxWIHrhl0J","pT8wubrhlQ","blLA9fcwDa","taOXKSs0Zu",
-"In3NSChuy3","8xEKzlCMxy","iB08lzY1GY","TCgPpNhXdu","v2eC3Ss0Zu","Cfgr39XyT9","yofH3IjTwP","2DREsDz1R3","S77LHXyPZN","v2eC3FFDui",
-"Ta8f64W0Tl","0ao3lFLsph","9eoRcZUnqt","lH1ktk85Ae","14FLRk85Ae","9XyT9mX2GE","Yh1hFuAWyp","fmIK1RACuj","8TxD7kZANm","gf8rIrz7Ut",
-"vkCHHzmLYD","QWxoT29QAz","JRJQBWreyP","14FLRkZANm","AgJHQ3otm6","CIShGUvlv4","zQt6QJkzUn","ZuDtDfaHir","YOfrYC2Irc","WmadAi7WMQ",
-"CNHmvjeskS","9XyT9SjskQ","2Yz7EQChxs","QYxC0pvgjS","Uvlv42DREs","UmaEvfaHir","lj07QNhXdu","xciqpatef2","QnJ1SoGu6x","euZA5lXFOB",
-"Oz8yZcQOnv","uN6r3S77LH","RBhp0EoToP","Gv3Fqx3LDe","HRxd8iB08l","VBjhzQChxs","qQxHP4dEz6","LbRTHpiJSk","RsQUqNo0Qb","9rlg9Vprf2",
-"v1HlnWmadA","EdBKcogLgc","EOE1on8pJ9","Gv3FqyofH3","fLNg8WreyP","gf8rICdyBV","taOXKSbRYy","qUJMdHlUbF","fqypyqaofN","1j5L8lH1kt",
-"NOHszkB5nP","atef2ru4UG","0MR5XtvdkD","hE1QlXyPZN","uN6r3FNYIM","cL0aE4dEz6","MGlTFyToGW","SWfouiB08l","FjHXRMezSW","mz8gxFPfSE",
-"s4786K4GS8","cShY2s4786","ciuWzt59lR","y94nw8RCUA","uupzk4W0Tl","QChxsRpBQm","cmXIXPYBf4","3otm6x3LDe","4W0Tl618Di","24ARFcShY2",
-"B3qemuJScX","n1pmOd85a9","WPmlxRmDcr","i3pydFnPFB","FLsphTwano","0PktI0YAGH","8FmFHKZamH","24ARFn1pmO","uAWyptAOsr","l83Ud580YD",
-"fqypy1j5L8","24ARFwiHrZ","WDVWJXyPZN","blLA9okgRi","7ku1pKASQ8","G1RhS0Wr5y","s7MxkVerEA","uvf7ABbwgA","W7cTssqVrf","SbRYyhSSvQ",
-"AOgEeiKqhr","JKWYRQworu","XflUqZzJHW","uAWypG1RhS","tjQxsjiVBP","JkzUnvkCHH","B3qemRxrsm","mX2GEUlU3M","FLsphStlDJ","pAhR15Namm",
-"euZA5qQxHP","9eoRccShY2","s4786KZamH","kZANmRsQUq","AXpwE2ZHdk","G1RhSYh1hF","rKDLJAOgEe","QbxXczY1GY","1LB1LAXpwE","M3zXLB3qem",
-"v1HlnOUqFM","WMiS3x3LDe","lm0pDkZANm","OUqFMzY1GY","SWfouyEfy9","tAOsrWaWsv","J2mQisqVrf","VjCZq1j5L8","CdyBVuLtKs","uoStwYjB9t",
-"ogLgch1zcH","hYBCKRsQUq","OxWIHzmLYD","4dEz6Z4I1v","Gv3Fq0MR5X","pFrrlQ6hMC","lViBvzQt6Q","uoStwpT8wu","oGu6xPYBf4","HP433nnP8o",
-"taOXKEoToP","7X3uy618Di","FhtglWPmlx","iwzGkFVMxo","JXljW9rlg9","OxWIHsuY4x","2TRI7gtCA5","iB08lVBjhz","Ta8f6lViBv","lViBvW7cTs",
-"piJSkaFFss","5NammMaJQs","vkCHHix74r","s7MxkQbxXc","l83UdMezSW","AkKTkXyPZN","SmGzvtl72W","blLA93weIF","Mkgy8zQt6Q","KZamHuoStw",
-"2hEEUvOqCE","dhSuHYh1hF","U3yw5DQimp","WreyPyvOMI","pT8wu5VZjS","JkzUndpe1v","QssNCK20wK","soy9tKZamH","oQ87r6AFT0","Ss0Zusoy9t",
-"FhtglCp3mZ","i7WMQ8TxD7","ix74rcShY2","8RCUARBhp0","SjskQwDajX","azIWpNcICA","o8Uyd8FmFH","dpe1vWreyP","wiHrZQWxoT","2NslmoGu6x",
-"BCxeCHlUbF","SbRYyAmdQd","3weIFMaJQs","guMb8FcWrW","FhtglZv7z0","8RCUAgdQsS","MojnPmz8gx","cShY2FVMxo","FLsphPb1pa","VNCPdbZLvS",
-"QbxXcOUqFM","Ul4a1ru4UG","0ao3lyofH3","yluBxKsjRK","ECMvU3weIF","QnJ1SlpF6W","GrDg7jeskS","RzaZAAOgEe","uvf7AP6bcg","suY4xfmIK1",
-"0h1b1aFFss","5iGN5ThjNn","Q6LixeuZA5","P6bcgVprf2","7Ow5CD6rBy","o8UydCp3mZ","AmdQd8U2nU","o8UydWPmlx","prNT6nnP8o","zY1GYuLtKs",
-"OHaBzI7p2a","CdyBVlH1kt","I7p2aEoToP","s7Mxk5drc6","Kr8ys29QAz","QClRLVLTy6","v2eC37fKYU","NhXduZv7z0","CdyBVVjCZq","uJScXuvf7A",
-"QChxsgf8rI","Yw2oUTwano","zHF1qMaJQs","Yw2oURBhp0","1LB1LUlU3M","DG4sTn8pJ9","BFkb8v8yFN","yEfy9EdBKc","okgRiYOfrY","suY4xQ6hMC",
-"8U2nUFjHXR","ciuWzlm0pD","5ZaEziwzGk","iqv4kHzZT8","yluBx1v5hH","uAWyplkMUA","rhl0JIjTwP","0ao3lulk41","XyPZNBpYhV","NhXduBpYhV",
-"7X3uyqQxHP","Mkgy8S77LH","qUJMdxciqp","8hJdtoGu6x","2TRI7RACuj","ydG8UO3iyQ","atef2JKWYR","1v5hHnFqik","0PktI9XyT9","taOXKVerEA",
-"suY4xOUqFM","l83UdzY1GY","FNYIMl83Ud","5ZaEzMkgy8","QssNCXflUq","tl72W8TxD7","uQIczhUTw7","0MR5XwDajX","ThjNnnFqik","WreyPciuWz",
-"BbwgA8cVD3","n8pJ9WMiS3","MK07YOUYuF","CIShGSbRYy","Rxrsmo8Uyd","RzaZANAFuw","2TRI7lH1kt","5nmWvSmGzv","PYBf4kZANm","Q6Lix0h1b1",
-"tjQxsZhwG1","jfREuWaim6","s7Mxkrz7Ut","PYBf4suY4x","cQOnvkZANm","okgRi0PktI","9rlg9rz7Ut","lpF6WYf2Ec","lViBv8xEKz","1j5L8uJScX",
-"9y4lwYh1hF","tjQxsFFDui","cmXIXe6e4z","2NslmeuZA5","jSjS3aL6AJ","OUqFMjfREu","cQOnvLbRTH","AmdQd5Namm","5nmWvNhXdu","lj07Qv8yFN",
-"RsQUqzmLYD","2Nslmb29RJ","hi5X7suY4x","Mkgy8vkCHH","DQimpXyPZN","HP433uPX7G","faHirM6qcG","kZANm5drc6","gf8rIpWiOs","QworuK4GS8",
-"xReecYh1hF","FxX9qpvgjS","5drc62TRI7","0YAGHStlDJ","D6rBy4W0Tl","blLA9HfyNQ","v2eC3qaofN","d7vjM1LB1L","UmaEvtl72W","yvOMI0MR5X",
-"G1RhSOUqFM","Nxx9VgjUTu","MGlTFYOfrY","UmaEvzmLYD","pFrrlcmXIX","e6e4zMojnP","FnPFB9XyT9","GSQwjM3zXL","7lUXZmz8gx","ZzJHW7hyVv",
-"OHaBz0ao3l","sqVrfiKqhr","FhtglJ2mQi","G1RhSCIShG","x3LDeEOE1o","FxX9qlm0pD","aL6AJpmeCd","Dz1R3yToGW","qaofNMkgy8","TXQ0ZLewvM",
-"WaWsvYf2Ec","CIShG7X3uy","mz8gxoGu6x","J2mQiaL6AJ","lm0pDU3yw5","VLTy6tvdkD","WPmlxUl4a1","FVMxoOUqFM","k85AeazIWp","6q6L9M6qcG",
-"FcWrWAgJHQ","bZLvSJkzUn","e6e4zZhwG1","QbxXcBGaQY","EoToPvLsmS","v2eC3taOXK","he9IA5drc6","zY1GYtaOXK","TwanolpF6W","XyPZNksJby",
-"zFgtBqaofN","UlU3MtAOsr","QworuGXdoH","tjQxsSs0Zu","i3pydzz4ZU","oVQp6P6bcg","a00b5JXljW","S2DfuWMiS3","DcpWBY1mC0","jS1ajru4UG",
-"bZLvSkZANm","5IhmGUlU3M","dQ586yEfy9","y94nwyToGW","7hyVvpT8wu","FNYIM1LB1L","BbwgAyToGW","DLhzMK20wK","CdyBV8RCUA","Q6hMCzqH0W",
-"zbIYY0MR5X","S77LHQnJ1S","faHir5nmWv","VIlwPJRJQB","IRh48NhXdu","DcpWB55rfB","BbwgAokgRi","blLA9uupzk","kB5nPx3LDe","QYxC05ZaEz",
-"i3pydhe9IA","mX2GEWaWsv","HzZT8Rxrsm","ulk41ThjNn","oQ87rdjsrv","uZPqgcShY2","y94nwMojnP","SjskQsx5Gl","RzaZAtvdkD","xXTI4hE1Ql",
-"8TxD729QAz","RxrsmIn3NS","gf8rIlCMxy","OUYuFMmsIo","5nmWv5ZaEz","0Wr5yoVQp6","pWiOs2Yz7E","9eoRcKr8ys","EoToPd7vjM","2hEEUGSQwj",
-"QssNCyvOMI","9iGoTpiJSk","5nmWvVerEA","jfREu8hJdt","0MR5Xxciqp","8U2nUpvgjS","5nmWv7fKYU","QWxoThe9IA","Ta8f68U2nU","Mkgy80MR5X",
-"7fsYMMm8si","i7WMQSWfou","HzZT85IhmG","7fKYUtAOsr","L7cGc9rlg9","blLA9LDk6f","wDajX7lUXZ","LbRTHzbIYY","mX2GEyvOMI","MGlTFIn3NS",
-"4W0TlZ4I1v","NcICADG4sT","yvOMIiwzGk","t98iWbZLvS","brhlQ0BmCy","qUJMdJ2mQi","FnPFBW3VFH","VIlwPDcpWB","MmsIoDG4sT","VBjhzAIYUu",
-"C2IrcWmadA","Vprf2NOHsz","gjUTu7lUXZ","GXdoHDG4sT","Cp3mZ580YD","In3NSAkKTk","Ta8f6Gv3Fq","i7WMQM6qcG","IRh487fsYM","tjQxsP6bcg",
-"BbwgAHP433","JkzUnl83Ud","UlU3MYjB9t","uPX7GJKWYR","yofH3cShY2","pFrrlWDVWJ","FFDuiksJby","0PktIU3yw5","cmXIXd7vjM","S77LHazIWp",
-"EoToPzHF1q","x3LDeY1mC0","RBhp0I7p2a","5IhmG1v5hH","bZLvS5drc6","aez9yRkQke","iKqhruvf7A","qQxHP2DREs","GrDg76AFT0","45cIH2hEEU",
-"Kr8ysMGlTF","DG4sTWPmlx","7fsYMOHaBz","Vprf2FPfSE","v2eC34W0Tl","zz4ZUDcpWB","dpe1vTCgPp","QYxC0Twano","he9IAStlDJ","PYBf4IKxdL",
-"PYBf4JXljW","tvdkD48cHL","zFgtBciuWz","GSQwjTXQ0Z","fcwDaTXQ0Z","2ZHdkQworu","6q6L9iKqhr","tuDySQssNC","MmKGJXflUq","MmKGJuLtKs",
-"X6Pinb29RJ","v2eC3yvOMI","euZA5zHF1q","GWqqXaL6AJ","uvf7A45cIH","B3qemVLTy6","IBe8k9eoRc","VerEA0MR5X","FxX9qMGlTF","zHF1qpiJSk",
-"hE1QlGSQwj","ni2v18xEKz","8FmFHgIYvE","POUYSkB5nP","iB08lrz7Ut","okgRiNAFuw","OHaBzrKDLJ","P6bcgjeskS","uTacxFhtgl","gf8rIK4GS8",
-"7fKYUK4GS8","VerEAdmoS7","uJScXBCxeC","2DREsXyPZN","EOE1oHlUbF","B3qemWreyP","FjHXRaFFss","RACujJ2mQi","ogLgcCNHmv","3otm6RACuj",
-"uQIczoVQp6","FhtglokgRi","7lUXZ1j5L8","7fKYUF6PT2","euZA5Oz8yZ","zqH0WGSQwj","Cp3mZ8TxD7","yToGWcL0aE","h1zcHIjTwP","B3qemIBe8k",
-"vLsmSi7WMQ","Q6LixgjUTu","ru4UGgf8rI","C2Ircm4bxU","pv0i7Yw2oU","7fKYUhe9IA","9y4lwhE1Ql","D6rBydjsrv","StlDJQ6hMC","9eoRcCIShG",
-"YjB9tQbxXc","1j5L8Fhtgl","jSjS39y4lw","qaofNQWxoT","zQt6QGv3Fq","euZA5t98iW","soy9tOUYuF","6AFT01j5L8","iB08ljS1aj","qaofNSbRYy",
-"VLTy6AIYUu","J2mQiQnJ1S","hSSvQiwzGk","5iGN56q6L9","gf8rIGv3Fq","MmKGJ7fsYM","i3pydru4UG","iKqhrNo0Qb","5Drn0vkCHH","FhtglFGzgp",
-"faHirs4786","jeskSvOqCE","EdBKcB3qem","fFDrJlkMUA","Ul4a1MmKGJ","AOgEeWaWsv","IjTwPsuY4x","2hEEUydG8U","JJs5mpiJSk","GXdoHQworu",
-"DG4sTzz4ZU","GWqqXlXFOB","Yh1hFS2Dfu","bgJAzxciqp","Vprf2CxVEf","Ul4a1JJs5m","aDGtSsoy9t","lH1ktJKWYR","tAOsrulk41","DcpWBNxx9V",
-"KsjRKhE1Ql","VNCPdcmXIX","jfREuYf2Ec","9XyT9d85a9","iB08lHP433","RmDcrTCgPp","uN6r3pv0i7","QworuRkQke","8TxD72Yz7E","FcWrWHfyNQ",
-"soy9tVjCZq","zY1GYiB08l","JXljW5VZjS","M3zXL9y4lw","v1HlnTXQ0Z","8FmFHHfyNQ","okgRi9rlg9","hE1QlzFgtB","atef2RACuj","e6e4zJKWYR",
-"RBhp02Nslm","1LB1Lv2eC3","Y1mC0Fhtgl","FjHXRzqH0W","JIqXigdQsS","v8yFNF6PT2","JRJQBO3iyQ","7X3uypv0i7","pAhR19rlg9","XyPZNk85Ae",
-"ECMvUmz8gx","uZPqg9XyT9","IRh480ao3l","K20wKogLgc","VIlwPFGzgp","hYBCKfLNg8","Yh1hFAOgEe","2ZHdkb29RJ","0MR5XMojnP","6AFT0DG4sT",
-"pvgjSTXQ0Z","FhtglDz1R3","JXljWsoy9t","iB08lsx5Gl","jzUqRuvf7A","HlUbFAkKTk","uJScXzmLYD","y94nw8U2nU","lXFOBB3qem","J2mQiKsjRK",
-"0KyfscL0aE","rhl0JEOE1o","Ss0ZuPb1pa","jiVBP1j5L8","zz4ZUEoToP","jS1aj48cHL","uoStw9GXkX","QnJ1STa8f6","BbwgAdhSuH","hE1QlUmaEv",
-"lpF6WcL0aE","QClRLv1Hln","Uvlv4x3LDe","DG4sTgtCA5","MmsIooQ87r","QClRLBCxeC","a00b50h1b1","IjTwPJJs5m","atef2VjCZq","s7MxkOxWIH",
-"oVQp6RmDcr","brhlQ5drc6","okgRicShY2","zmLYDlpF6W","CNHmvFLsph","zbIYYblLA9","14FLRzmLYD","Nxx9V8TxD7","WaWsvt59lR","dQ586QWxoT",
-"bgJAzIjTwP","0MR5XOUqFM","QbxXcMaJQs","cmXIXhSSvQ","Vprf2ru4UG","Oz8yZqUJMd","tvdkDi3pyd","aFFssZ4I1v","BpYhV0BmCy","QnJ1SD6rBy",
-"zQt6QfLNg8","tAOsrCp3mZ","iqv4kaFFss","yEfy9Qworu","yluBx0BmCy","SmGzv580YD","zqH0WfmIK1","Q6hMCGWqqX","Q6Lix7hyVv","AOgEeNhXdu",
-"qUJMdi3pyd","Pb1pa5VZjS","Qworuh1zcH","pT8wuK20wK","ReKEWs93Ml","VIlwP48cHL","MojnPGv3Fq","i3pydQYxC0","2TRI71LB1L","FVMxodhSuH",
-"jiVBPtlILt","FNYIMi3pyd","NAFuwbZLvS","bgJAz2ZHdk","48cHLzFgtB","9GXkXLDk6f","wiHrZ2ZHdk","5VZjSC2Irc","bgJAzxXTI4","iwzGk24ARF",
-"1v5hHfaHir","TCgPpHRxd8","X6PinHlUbF","5Namm7Ow5C","BbwgARpBQm","taOXKuvf7A","J2mQiM6qcG","mz8gxVjCZq","WPmlxSjskQ","Chuy3Y1mC0",
-"3otm6vkCHH","v8yFNTCgPp","h1zcHzQt6Q","jeskSzQt6Q","tAOsrBCxeC","M6qcGIKxdL","No0QbHP433","VjCZqKASQ8","RzaZAogLgc","iB08lTwano",
-"4dEz6fcwDa","yofH3Yw2oU","cL0aE618Di","n8pJ9rz7Ut","IBe8kprNT6","QWxoTl83Ud","8RCUAhi5X7","wDajXNhXdu","WMiS3dpe1v","48cHLdpe1v",
-"NOHszxciqp","lm0pDhSSvQ","soy9toQ87r","AIYUucmXIX","hi5X7zbIYY","ReKEWAmdQd","FwEJzdjsrv","K20wKY1mC0","0MR5XECMvU","JJs5mtl72W",
-"bgJAzwDajX","48cHLI7p2a","2ZHdkuPX7G","wiHrZ0YAGH","i7WMQzmLYD","O3iyQI7p2a","OxWIHd7vjM","o8UydMaJQs","CdyBVgdQsS","tlILtWmadA",
-"d7vjMQnJ1S","ulk41K20wK","hi5X7wiHrZ","sqVrf2TRI7","Vprf2pFrrl","dQ5868TxD7","AOgEeYjB9t","MezSWCfgr3","AgJHQv1Hln","1LB1LrKDLJ",
-"Chuy3LDk6f","F6PT2EdBKc","QnJ1S9eoRc","lweGyECMvU","14FLR9iGoT","gIYvEe6e4z","Rxrsmpv0i7","29QAzKASQ8","HfyNQAXpwE","StlDJs4786",
-"StlDJ8FmFH","580YDazIWp","jeskSjtn0X","euZA5k85Ae","rKDLJlweGy","t98iWzFgtB","9GXkXm4bxU","I7p2aZUnqt","ru4UGfLNg8","7ku1pKZamH",
-"07n1c24ARF","tuDySReKEW","RkQkeOz8yZ","aez9yuJScX","RmDcrRpBQm","uoStwfFDrJ","UlU3MIn3NS","YjB9tsoy9t","YjB9tQworu","CxVEfWaWsv",
-"MezSWlweGy","pWiOsprNT6","GSQwjQ6hMC","QssNC2Nslm","NcICACfgr3","uoStwqQxHP","ZzJHWv8yFN","y94nwlpF6W","aez9yB3qem","Cfgr3uN6r3",
-"Waim6jzUqR","uLtKs8TxD7","k85AeZ4I1v","azIWp0Wr5y","SWfouru4UG","pmeCd7hyVv","nFqiki7WMQ","CdyBVUvlv4","FPfSEuAWyp","ogLgcZJTXH",
-"FGzgpzmLYD","a00b58U2nU","QChxsDcpWB","pmeCd9XyT9","HlUbFDQimp","fcJOyThjNn","0YAGHMkgy8","QnJ1SCNHmv","FjHXRlsQGo","piJSkyvOMI",
-"WPmlxs4786","AIYUu5IhmG","M3zXL0MR5X","FxX9quAWyp","CNHmvvOqCE","v1HlnRzaZA","WDVWJZ4I1v","lsQGon8pJ9","U3yw50MR5X","rz7UtLDk6f",
-"VIlwP0Wr5y","d85a9M3zXL","EOE1o29QAz","1LB1Laez9y","ulk41zFgtB","Oz8yZ5Namm","rz7Utk85Ae","uvf7AO3iyQ","lpF6Wtl72W","uupzkaFFss",
-"Vprf2soy9t","okgRiFGzgp","WDVWJPYBf4","MojnPqUJMd","qUJMdC2Irc","AkKTki3pyd","a00b5QnJ1S","CxVEfAmdQd","RBhp0uTacx","dpe1vAOgEe",
-"cShY24QMc9","bZLvSRACuj","BCxeClweGy","5IhmG6AFT0","ydG8UJkzUn","14FLRWaWsv","RsQUqDz1R3","WaWsvTa8f6","I7p2aVjCZq","QChxs580YD",
-"1v5hHuQIcz","yofH3RzaZA","FnPFBaDGtS","2Yz7Ehi5X7","x3LDeh1zcH","fcJOyfFDrJ","iwzGk8TxD7","tl72WQ6hMC","2NslmazIWp","qaofN8FmFH",
-"mz8gx2DREs","ni2v1ECMvU","lH1ktyofH3","LbRTHQbxXc","OUqFMOz8yZ","FLsphhUTw7","QbxXc4QMc9","y94nwC2Irc","RBhp0Waim6","RzaZAfcwDa",
-"dhSuHa00b5","ECMvU1v5hH","zQt6Q8RCUA","k85AeYf2Ec","ZhwG1oQ87r","W7cTs0MR5X","FwEJzIBe8k","lViBvAkKTk","hYBCKD6rBy","QssNClweGy",
-"jS1ajgf8rI","0YAGHLbRTH","gjUTu16lHc","lsQGoOHaBz","rhl0JTa8f6","TXQ0Zn8pJ9","zQt6QzQt6Q","XflUqRBhp0","AmdQdoGu6x","nFqik6AFT0",
-"Ss0Zu8FmFH","hSSvQHfyNQ","t59lRGrDg7","ogLgc2TRI7","3weIFM6qcG","XyPZNbgJAz","OHaBzQ6Lix","lViBvAXpwE","hi5X7DLhzM","S77LHRxrsm",
-"zmLYDqQxHP","ZhwG1Cp3mZ","fLNg8jzUqR","hYBCKWaim6","0PktIcL0aE","prNT64W0Tl","BCxeClkMUA","MezSW5iGN5","gIYvEMm8si","7hyVvDQimp",
-"RsQUqB3qem","zQt6QuAWyp","pAhR145cIH","cQOnvZhwG1","8FmFH2DREs","Q6Lixiqv4k","KASQ8Vprf2","XflUquZPqg","DcpWBX6Pin","CxVEfaL6AJ",
-"pFrrlqUJMd","29QAzlm0pD","yvOMIVprf2","jeskSSjskQ","ZuDtDCfgr3","zQt6QlCMxy","AOgEeGv3Fq","iqv4ktlILt","wDajXVerEA","In3NS55rfB",
-"uAWyp6q6L9","OUYuFQ6Lix","ksJbyJXljW","gIYvE5nmWv","bgJAzQbxXc","G1RhSAOgEe","Waim6VjCZq","GrDg7IjTwP","FxX9q24ARF","he9IATXQ0Z",
-"ydG8U7fsYM","Mm8sid7vjM","JkzUnLbRTH","WDVWJWDVWJ","xciqps4786","QClRLcmXIX","14FLRuPX7G","fcwDaFNYIM","iqv4kX6Pin","euZA55Namm",
-"VLTy6MojnP","wiHrZgf8rI","aez9yhUTw7","U3yw5NcICA","GrDg7o8Uyd","YOfrY8xEKz","FVMxopvgjS","pT8wu2DREs","hE1QlOHaBz","9XyT90h1b1",
-"Cp3mZjfREu","v1HlnpAhR1","0KyfsiB08l","jiVBPMaJQs","lweGy9eoRc","WmadA2Nslm","QssNCtlILt","dpe1vK4GS8","jiVBPd7vjM","YjB9tzz4ZU",
-"jzUqRjtn0X","Fhtgliqv4k","2ZHdkLbRTH","AmdQdyluBx","5Nammo8Uyd","QworukB5nP","2NslmRsQUq","KZamHFjHXR","X6Piniqv4k","GXdoHM3zXL",
-"Oz8yZP6bcg","UlU3Maez9y","iwzGkPYBf4","soy9thi5X7","EdBKcjiVBP","d7vjMWPmlx","CxVEf8xEKz","qaofN29QAz","DG4sTogLgc","lj07QiB08l",
-"OUqFMEoToP","55rfBU3yw5","2hEEUgf8rI","OxWIHlkMUA","lXFOBFPfSE","FwEJzFjHXR","lViBvbrhlQ","TXQ0Zx3LDe","JKWYRMGlTF","RsQUqyofH3",
-"gjUTuW3VFH","8RCUACqqaD","LDk6foGu6x","FjHXRd85a9","29QAzAOgEe","yvOMILDk6f","Ta8f6ThjNn","LewvMjfREu","5ZaEzDLhzM","yluBx0PktI",
-"uZPqgwDajX","AXpwERzaZA","ZhwG1KsjRK","d7vjMFwEJz","9XyT9MK07Y","dpe1vciuWz","9eoRcOUYuF","NAFuwiwzGk","yofH3nlaBy","jiVBPix74r",
-"F6PT2aDGtS","suY4xuoStw","YOfrYMK07Y","v8yFNoGu6x","Ss0Zu16lHc","prNT6iwzGk","QbxXcD6rBy","FVMxox3LDe","Mkgy8LewvM","7fsYMyToGW",
-"RACujguMb8","4dEz6Rxrsm","n8pJ9POUYS","pmeCdS77LH","dQ586gf8rI","JRJQB8RCUA","FFDuiGSQwj","Ul4a1s93Ml","Kr8ysv2eC3","JIqXi9XyT9",
-"9eoRcfqypy","MK07YReKEW","CdyBV8TxD7","BCxeC7lUXZ","kZANmRxrsm","JJs5mRpBQm","oGu6xC2Irc","s93MlJ2mQi","ZJTXHnnP8o","Q6LixWmadA",
-"JJs5moGu6x","StlDJzz4ZU","zbIYYpAhR1","2Yz7ED6rBy","4QMc9nFqik","uAWypjfREu","hE1Ql48cHL","4QMc90Kyfs","cShY22DREs","3otm6L7cGc",
-"16lHctjQxs","0Wr5yzmLYD","dpe1viwzGk","VjCZqmX2GE","OHaBzHfyNQ","euZA5prNT6","JIqXi5iGN5","ogLgcM3zXL","0BmCy4dEz6","euZA5BFkb8",
-"Nxx9VlweGy","fcwDaguMb8","n8pJ9nnP8o","OxWIHKr8ys","SbRYyaFFss","dhSuHlViBv","dQ5861LB1L","zY1GYStlDJ","6AFT0NAFuw","pv0i7xReec",
-"n1pmOhe9IA","ni2v148cHL","bZLvSuupzk","RzaZAOUYuF","pvgjSQ6Lix","29QAzxReec","t59lR9y4lw","pvgjSjiVBP","xReecdhSuH","ZhwG1xciqp",
-"guMb8s7Mxk","HzZT814FLR","xReecs93Ml","lj07Q16lHc","jS1ajGv3Fq","pFrrlHlUbF","Rxrsmlm0pD","bZLvS4W0Tl","VLTy6guMb8","uJScXRmDcr",
-"oQ87rMm8si","QClRLZzJHW","EOE1oS2Dfu","TCgPppT8wu","Gv3FqOz8yZ","fFDrJs4786","prNT65ZaEz","WPmlxtlILt","uLtKsZ4I1v","QClRLCK5W7",
-"bZLvS16lHc","vkCHHuJScX","fLNg8DLhzM","G1RhSlXFOB","0Kyfs0ao3l","8FmFHF6PT2","lXFOBD6rBy","zQt6QsuY4x","zHF1q9eoRc","WreyPd85a9",
-"cmXIXWDVWJ","iwzGkBCxeC","0KyfsX6Pin","618DiYw2oU","U3yw5IBe8k","LDk6fpvgjS","Kr8ysrz7Ut","7hyVviKqhr","WreyPZhwG1","9GXkXWPmlx",
-"5Drn0PYBf4","dQ586HP433","KZamH4dEz6","WmadAQ6Lix","ThjNnYf2Ec","tAOsrvOqCE","CK5W78RCUA","ulk41ogLgc","F6PT2gf8rI","zqH0WHzZT8",
-"ulk41brhlQ","WmadAsuY4x","55rfBRkQke","Waim6zY1GY","uJScXguMb8","dpe1vwiHrZ","0Kyfs0Wr5y","Z4I1vdpe1v","dpe1vCK5W7","jtn0Xd7vjM",
-"qaofNQworu","Uvlv445cIH","BGaQYaDGtS","Zv7z0xXTI4","Mm8sihUTw7","W7cTsaez9y","5iGN5nnP8o","RkQkeL7cGc","WPmlxpv0i7","h1zcHFNYIM",
-"SWfouRzaZA","AmdQdM6qcG","VjCZqXflUq","zQt6QYjB9t","0PktIi3pyd","qUJMd0Kyfs","k85AeKZamH","oQ87rSmGzv","5nmWvoQ87r","ThjNnYh1hF",
-"K20wKpT8wu","tl72WZzJHW","he9IARmDcr","9rlg9e6e4z","7Ow5C16lHc","0MR5XlCMxy","FxX9qyluBx","rz7Ut618Di","XyPZNcQOnv","O3iyQm4bxU",
-"P6bcgokgRi","vkCHHSWfou","XflUqHP433","5NammTXQ0Z","dpe1vcShY2","nnP8opT8wu","2ZHdkDLhzM","0ao3lvLsmS","J2mQitlILt","Q6hMCNo0Qb",
-"gIYvE64s8N","hUTw7AXpwE","5VZjSGrDg7","Z4I1vSjskQ","BpYhVnnP8o","TwanoZzJHW","5IhmGECMvU","fqypyRACuj","d7vjMVjCZq","y94nwXflUq",
-"4QMc9Vprf2","W7cTsThjNn","0Wr5yjS1aj","I7p2aiqv4k","vLsmSfLNg8","XflUqzbIYY","Z4I1vS2Dfu","8U2nUEOE1o","VIlwPatef2","0BmCyFnPFB",
-"kB5nPh1zcH","ZhwG1okgRi","BFkb8Ss0Zu","ydG8UzY1GY","0YAGHcShY2","lViBv1j5L8","pvgjS9eoRc","qQxHPMGlTF","SmGzvblLA9","WaWsvyofH3",
-"FxX9qFPfSE","pAhR17lUXZ","LbRTH24ARF","29QAzeuZA5","48cHLdQ586","FnPFB48cHL","29QAzY1mC0","PYBf4iKqhr","tuDySpv0i7","FhtglFNYIM",
-"cmXIXD6rBy","yofH3HP433","FnPFBMK07Y","W3VFHCxVEf","Mm8siFnPFB","JIqXijtn0X","QssNCaDGtS","5Mg9r0Wr5y","X6PinOUYuF","jfREuqaofN",
-"soy9tpWiOs","AmdQdiqv4k","KASQ8lm0pD","6AFT0oQ87r","lCMxyBpYhV","0YAGHCqqaD","CK5W7kZANm","kB5nPZJTXH","S77LHFhtgl","qUJMdBbwgA",
-"7Ow5C2Yz7E","pAhR16q6L9","No0Qb5IhmG","azIWpyToGW","DQimpFjHXR","Kr8ysW7cTs","MojnPbrhlQ","k85AepmeCd","fcJOyGWqqX","BbwgAi7WMQ",
-"zHF1qG1RhS","RBhp0GXdoH","Mm8siUl4a1","o8UydM6qcG","brhlQa00b5","pWiOszQt6Q","5NammrKDLJ","uJScXHfyNQ","ReKEW618Di","OxWIHzQt6Q",
-"kB5nP7hyVv","QClRLXyPZN","B3qemOz8yZ","rz7UtPb1pa","8hJdtSWfou","DQimpnnP8o","bgJAzFwEJz","he9IAK20wK","rhl0JMaJQs","45cIHYOfrY",
-"AXpwEuvf7A","0h1b15ZaEz","xReeczY1GY","KZamHxXTI4","piJSkKsjRK","HzZT8dpe1v","Yh1hFfqypy","nnP8oiKqhr","oGu6xK20wK","K4GS8BpYhV",
-"QssNChE1Ql","vkCHHwDajX","k85AeFGzgp","1LB1La00b5","faHirhSSvQ","FcWrWFLsph","W7cTsh1zcH","v2eC3lkMUA","l83UdlweGy","JkzUnt98iW",
-"pmeCdFwEJz","RkQkenlaBy","hYBCKChuy3","ZhwG15Namm","zHF1qgf8rI","Ss0ZujfREu","ZzJHWMezSW","n8pJ9ECMvU","F6PT2i3pyd","EoToPWPmlx",
-"gjUTu0ao3l","WmadAGv3Fq","rhl0Js93Ml","s4786uZPqg","48cHLGWqqX","VjCZq29QAz","2Yz7Efqypy","yvOMIt59lR","Q6hMCJXljW","7lUXZfcwDa",
-"VLTy60h1b1","XflUqCxVEf","No0Qb8FmFH","jiVBPogLgc","FVMxoIRh48","HRxd8Yw2oU","kB5nPbrhlQ","HRxd88cVD3","FPfSE7lUXZ","WreyPqUJMd",
-"vLsmSqQxHP","gIYvEdhSuH","S2DfuAXpwE","LbRTHCfgr3","JIqXiCqqaD","45cIHLewvM","iqv4kOUqFM","Ss0ZuM3zXL","0KyfsYOfrY","jiVBPUmaEv",
-"piJSkprNT6","blLA9M3zXL","cL0aEa00b5","BpYhVt98iW","2Yz7EVprf2","W7cTsW7cTs","2DREs9iGoT","IBe8kpv0i7","v2eC3n1pmO","W3VFHpAhR1",
-"piJSkuupzk","aFFssjzUqR","9y4lwReKEW","bZLvS3weIF","HlUbFBFkb8","No0Qb9iGoT","bgJAzCdyBV","zqH0W1v5hH","jiVBPSbRYy","1LB1LPb1pa",
-"AOgEe48cHL","aDGtS2TRI7","yEfy9Rxrsm","fmIK1FcWrW","HlUbFl83Ud","Kr8ys5ZaEz","pT8wuyToGW","uvf7AqQxHP","tuDySfmIK1","5nmWvMm8si",
-"jfREusoy9t","atef2lCMxy","AIYUuRsQUq","pvgjSMmsIo","rKDLJxXTI4","ZUnqt5iGN5","2DREsOUqFM","VjCZqFhtgl","kZANmJRJQB","mX2GElViBv",
-"lm0pDRACuj","okgRi64s8N","FnPFBtjQxs","O3iyQ7lUXZ","7fKYUgjUTu","v2eC3HP433","Cfgr3FPfSE","Fhtgl45cIH","Fhtglv2eC3","NOHszogLgc",
-"b29RJgtCA5","HzZT8jiVBP","tlILtKASQ8","zFgtBt59lR","HP433azIWp","yluBxgIYvE","1j5L8ydG8U","yToGWIjTwP","mz8gxQbxXc","RACujS2Dfu",
-"RzaZAGXdoH","5iGN5h1zcH","dmoS7WaWsv","9y4lwC2Irc","FcWrWVLTy6","FxX9quvf7A","yvOMIjtn0X","8xEKzazIWp","JRJQB0ao3l","cShY2RzaZA",
-"pT8wu1v5hH","8xEKz5iGN5","IKxdLrhl0J","LDk6fVprf2","VLTy6RkQke","0BmCy8hJdt","x3LDeKsjRK","MaJQs0MR5X","wDajXlm0pD","JKWYR0h1b1",
-"5Drn0a00b5","Mm8si8cVD3","BGaQYuN6r3","fFDrJ8U2nU","ZJTXHhYBCK","AXpwEazIWp","ydG8UuPX7G","guMb8iqv4k","dhSuHEoToP","tAOsrUlU3M",
-"KASQ8WmadA","pv0i7zqH0W","J2mQiEOE1o","ZzJHW5VZjS","jtn0XAIYUu","EoToPQ6Lix","cShY2U3yw5","CdyBVTCgPp","IKxdLk85Ae","Chuy3HfyNQ",
-"uZPqgJ2mQi","Zv7z00BmCy","XyPZNYh1hF","5ZaEzt98iW","LDk6fd7vjM","P6bcg5nmWv","9iGoTMm8si","16lHcCK5W7","TXQ0Zix74r","hSSvQQworu",
-"Oz8yZrz7Ut","ulk410h1b1","uAWypBCxeC","MGlTF45cIH","IKxdL9XyT9","FwEJzK20wK","dhSuHRkQke","zmLYDJRJQB","J2mQiHRxd8","IjTwP48cHL",
-"y94nwJJs5m","K4GS8Z4I1v","lpF6WU3yw5","G1RhSQ6Lix","tl72WEdBKc","lpF6WTa8f6","kB5nPFPfSE","UmaEvHzZT8","VerEA2DREs","7lUXZfqypy",
-"SbRYyuQIcz","S77LHlXFOB","v2eC3PYBf4","AkKTk8hJdt","t59lRQworu","0Wr5yXflUq","GSQwjdmoS7","TXQ0ZSmGzv","WPmlxWaim6","In3NS6q6L9",
-"MaJQsZzJHW","vLsmS07n1c","prNT6PYBf4","iKqhrDG4sT","Gv3Fq5Namm","7fKYUiKqhr","QbxXcX6Pin","FLsphMojnP","P6bcgKASQ8","9GXkX0MR5X",
-"Waim6azIWp","hi5X7s7Mxk","cShY2e6e4z","Vprf2EoToP","v8yFN0MR5X","EoToPMkgy8","7fKYUMm8si","oGu6xuPX7G","rKDLJnnP8o","ulk41GWqqX",
-"fcwDa2DREs","aL6AJzmLYD","SWfou64s8N","WaWsvdmoS7","QbxXcLbRTH","SWfouZuDtD","oQ87rEdBKc","2TRI7cShY2","k85Aerhl0J","4dEz6CdyBV",
-"IRh48v1Hln","VBjhzm4bxU","Yw2oUi7WMQ","cQOnv2hEEU","5drc6fcwDa","3weIF0BmCy","s7MxkYw2oU","CxVEfOxWIH","vkCHHFnPFB","euZA564s8N",
-"QssNCTwano","uPX7GD6rBy","QYxC014FLR","07n1cRkQke","zz4ZUnlaBy","Gv3Fq5drc6","wDajXOz8yZ","J2mQiGWqqX","tuDySWreyP","QChxsuoStw",
-"l83Ud5ZaEz","BCxeCLDk6f","zz4ZUblLA9","S77LHYw2oU","7hyVvPYBf4","l83Ud14FLR","No0QbhSSvQ","jzUqRQ6Lix","9iGoTSmGzv","pWiOshUTw7",
-"WaWsvyvOMI","L7cGcLewvM","ZzJHWTa8f6","GWqqXAOgEe","yEfy9hE1Ql","pmeCdcShY2","14FLRhe9IA","YOfrYMaJQs","iKqhrs93Ml","hYBCKWDVWJ",
-"Nxx9VdhSuH","sqVrfs7Mxk","HfyNQ4dEz6","24ARFksJby","Uvlv4FcWrW","FNYIM0YAGH","bZLvSciuWz","zqH0W4W0Tl","n8pJ9ZUnqt","I7p2ay94nw",
-"AmdQd0Wr5y","RACujzz4ZU","d7vjMe6e4z","7Ow5C1LB1L","hi5X7pFrrl","LDk6fF6PT2","bgJAztvdkD","zQt6QChuy3","yEfy9yEfy9","hSSvQ8U2nU",
-"vLsmSru4UG","nnP8ogjUTu","NcICAVerEA","G1RhSP6bcg","uLtKsnlaBy","NOHszvkCHH","64s8NgjUTu","RpBQmAgJHQ","3weIFxXTI4","8U2nUFFDui",
-"7fKYURxrsm","aL6AJ55rfB","7Ow5CQbxXc","ru4UGOUqFM","2Yz7EuTacx","3weIFQYxC0","KsjRK2Nslm","K4GS8tl72W","5VZjSyToGW","Mkgy8HfyNQ",
-"RBhp0ni2v1","YOfrY7hyVv","YOfrYVIlwP","5VZjSQWxoT","FGzgpyluBx","9iGoTJKWYR","piJSk0Wr5y","zz4ZUdQ586","7fsYMru4UG","7fsYM4QMc9",
-"5IhmGlH1kt","ydG8Udpe1v","iqv4ksx5Gl","Cp3mZzY1GY","NOHszECMvU","oGu6xxReec","cShY2lpF6W","0KyfsoGu6x","55rfBAIYUu","lweGyZ4I1v",
-"StlDJ0PktI","cL0aEGWqqX","sqVrfydG8U","jeskSiqv4k","tjQxsMm8si","lH1kti7WMQ","hUTw7XyPZN","AXpwERpBQm","VNCPduTacx","n1pmOyToGW",
-"1LB1LMGlTF","fmIK1suY4x","VerEAJRJQB","taOXKCK5W7","ZuDtDni2v1","16lHcQWxoT","dmoS79eoRc","FcWrWNAFuw","5iGN5tlILt","FcWrWix74r",
-"FNYIMcShY2","QbxXcEOE1o","zHF1qQClRL","lCMxy5Namm","SbRYy7X3uy","vkCHHFhtgl","Cfgr3F6PT2","ni2v13weIF","t59lR618Di","48cHLlXFOB",
-"14FLRFLsph","VerEAThjNn","aDGtSQnJ1S","blLA9xXTI4","uQIcztl72W","t59lR0MR5X","o8UydgjUTu","jzUqRBpYhV","mz8gxtl72W","JKWYRt59lR",
-"a00b5cShY2","MmKGJfcwDa","B3qemJKWYR","P6bcgDLhzM","MK07YtAOsr","I7p2alweGy","Yh1hFG1RhS","XflUqY1mC0","24ARFS2Dfu","kB5nPgIYvE",
-"s7MxkD6rBy","QssNCRACuj","AgJHQTCgPp","MaJQsZv7z0","LDk6f8TxD7","tuDySQ6Lix","D6rByJKWYR","jSjS3FLsph","Vprf2v8yFN","iwzGkGv3Fq",
-"K4GS8guMb8","ZJTXHMojnP","JJs5mhE1Ql","VjCZqbrhlQ","MmsIon8pJ9","5nmWvvOqCE","JKWYR5Drn0","F6PT2MmsIo","uupzk7hyVv","RxrsmCdyBV",
-"B3qemx3LDe","OUqFMtl72W","NAFuwMezSW","v2eC3Waim6","tl72WlXFOB","RkQkeksJby","pv0i7aL6AJ","hSSvQzqH0W","zHF1q48cHL","MezSWFVMxo",
-"lpF6WSbRYy","MGlTFHfyNQ","FwEJztvdkD","bZLvSWaWsv","9XyT9QssNC","guMb8i7WMQ","VBjhz2TRI7","lkMUAmz8gx","3otm66AFT0","Vprf2aL6AJ",
-"K20wKyluBx","9XyT9CK5W7","GWqqXQYxC0","7fsYMzFgtB","tjQxsQworu","ksJbyL7cGc","pWiOsReKEW","U3yw5lsQGo","IKxdLzHF1q","QworuhYBCK",
-"wDajXCxVEf","RpBQmJJs5m","BCxeCulk41","hSSvQNcICA","7hyVvSbRYy","zz4ZUFNYIM","0PktIMkgy8","dhSuHL7cGc","No0QbcL0aE","M3zXLfaHir",
-"K4GS8KASQ8","xciqpYf2Ec","yluBxlm0pD","0PktIzbIYY","iB08ldQ586","v1HlnCNHmv","5iGN57fKYU","zFgtBazIWp","HzZT8DcpWB","s7MxkkZANm",
-"45cIHECMvU","bZLvSl83Ud","blLA9G1RhS","n1pmOlpF6W","JIqXiYjB9t","9eoRc48cHL","tjQxshSSvQ","bgJAzSjskQ","prNT6gf8rI","aez9yMGlTF",
-"2TRI7Mkgy8","IRh48VIlwP","QbxXco8Uyd","WreyPFLsph","mz8gx9iGoT","0ao3lGXdoH","m4bxUAkKTk","FFDuivOqCE","M3zXLM3zXL","pmeCdL7cGc",
-"0YAGHlCMxy","cmXIX5Namm","W7cTsOHaBz","XflUqWmadA","ThjNn4dEz6","BCxeCCxVEf","Yh1hF0h1b1","TwanowDajX","U3yw5Q6hMC","SmGzv8RCUA",
-"HzZT8prNT6","Nxx9V2ZHdk","EoToPazIWp","CqqaDDz1R3","VNCPdpWiOs","JJs5mReKEW","lH1ktCdyBV","P6bcgS2Dfu","Yf2EcbgJAz","FFDuiVjCZq",
-"sqVrftl72W","euZA5K20wK","O3iyQLDk6f","FFDuizFgtB","pFrrljSjS3","FxX9qFjHXR","DQimpWaim6","zQt6Qtl72W","L7cGcy94nw","v2eC3x3LDe",
-"jzUqR8TxD7","MaJQsMm8si","lsQGoqaofN","Z4I1vHRxd8","RxrsmEoToP","FcWrWFjHXR","aDGtSAmdQd","FLsphuJScX","JIqXiVNCPd","QClRLZJTXH",
-"J2mQiIn3NS","AOgEebZLvS","Yw2oUFwEJz","Kr8ysjiVBP","U3yw5HlUbF","GXdoHMK07Y","jtn0XVIlwP","FxX9qJKWYR","W3VFHatef2","hYBCKUmaEv",
-"o8UydqUJMd","euZA5OHaBz","prNT6X6Pin","hSSvQ7fsYM","uN6r38RCUA","Q6LixYf2Ec","M6qcGYh1hF","HRxd8qUJMd","55rfBYOfrY","MezSWCxVEf",
-"29QAzt59lR","qUJMd4QMc9","OHaBzVerEA","cL0aEDQimp","jSjS39XyT9","QClRLvLsmS","0MR5X55rfB","3weIF618Di","YOfrYbZLvS","m4bxUVIlwP",
-"VjCZqnnP8o","1LB1LWMiS3","iwzGknnP8o","uTacxChuy3","zz4ZURzaZA","MGlTFIKxdL","taOXKpT8wu","Cfgr3guMb8","EdBKcRxrsm","5drc6yToGW",
-"0ao3lzbIYY","BpYhVEOE1o","uAWypSWfou","gjUTu580YD","hE1QlOxWIH","0ao3l3weIF","XflUq7fKYU","v1HlnIRh48","ogLgcY1mC0","Pb1pae6e4z",
-"QClRLOUqFM","MojnPyofH3","pv0i7mX2GE","uQIczaDGtS","o8UydYw2oU","ReKEWuPX7G","8TxD7HP433","NhXduuQIcz","24ARFkB5nP","Oz8yZjfREu",
-"WmadA7hyVv","Yh1hF7Ow5C","64s8NHfyNQ","B3qem48cHL","AXpwEgIYvE","JkzUnblLA9","hE1Qllj07Q","pFrrloVQp6","hSSvQzbIYY","SmGzvjeskS",
-"lpF6WWaWsv","gIYvEo8Uyd","pv0i7uLtKs","4QMc9DcpWB","v2eC38TxD7","0KyfsXflUq","lm0pDlH1kt","v8yFNdQ586","9GXkXKASQ8","pAhR1UlU3M",
-"0KyfsdhSuH","2DREsiwzGk","UmaEvGv3Fq","DLhzMlkMUA","xReecjiVBP","JXljWWDVWJ","HP433h1zcH","kB5nPpiJSk","MmKGJ9y4lw","CNHmvM3zXL",
-"xciqp9eoRc","FFDui3weIF","5Mg9rM6qcG","Pb1paS2Dfu","W7cTsUvlv4","yofH3FPfSE","GXdoH8RCUA","5iGN5jtn0X","uQIczhi5X7","580YDm4bxU",
-"VIlwPix74r","rKDLJqaofN","9GXkXydG8U","xciqpbZLvS","BGaQYRmDcr","Ss0ZujSjS3","zHF1q07n1c","MezSWa00b5","jeskSv2eC3","RsQUqbrhlQ",
-"QYxC0QYxC0","JXljWUmaEv","Mm8siMojnP","fLNg8Chuy3","M6qcG6AFT0","FhtglDcpWB","kZANmZzJHW","hUTw7oQ87r","AIYUuni2v1","RBhp0lkMUA",
-"HP4338TxD7","zQt6QzHF1q","DG4sTThjNn","NAFuwQworu","OHaBzAkKTk","WreyPxReec","s93MlgdQsS","ix74r16lHc","faHir3weIF","d7vjMUmaEv",
-"v2eC3CK5W7","IRh481j5L8","d7vjMuZPqg","FjHXRZJTXH","8hJdtv2eC3","ciuWzTXQ0Z","hSSvQoVQp6","ni2v1rKDLJ","Mm8siWPmlx","SbRYyjtn0X",
-"DG4sTDG4sT","DcpWBqaofN","ZUnqtyToGW","cmXIXnFqik","MK07YYw2oU","jzUqRvLsmS","vOqCEhUTw7","Kr8ysKASQ8","ydG8Ufqypy","Uvlv4X6Pin",
-"yEfy9gf8rI","6AFT0brhlQ","MaJQsTXQ0Z","5ZaEzs93Ml","YOfrYs4786","ksJbyPOUYS","uQIczSWfou","RsQUq5Mg9r","VLTy6AgJHQ","7fKYU5ZaEz",
-"kB5nPJJs5m","fLNg8POUYS","5nmWvuPX7G","0h1b1FLsph","Yf2Ec7Ow5C","xciqp24ARF","RBhp0RkQke","HP433wiHrZ","0Wr5yokgRi","RsQUqCIShG",
-"C2IrcVBjhz","8cVD3i7WMQ","WMiS3v2eC3","GXdoHGv3Fq","48cHLm4bxU","n1pmO0Kyfs","qUJMdYjB9t","fcwDaXyPZN","y94nwS77LH","4QMc9iB08l",
-"S2Dfut59lR","l83UdJIqXi","ciuWzn8pJ9","nFqikzHF1q","ZJTXHkB5nP","aez9yWPmlx","Nxx9VKASQ8","HfyNQLewvM","sx5GlAkKTk","nlaByI7p2a",
-"k85AexReec","AkKTk8xEKz","0Wr5yQ6Lix","b29RJ3otm6","WaWsvcQOnv","MaJQsqQxHP","0MR5XQbxXc","2ZHdki3pyd","ogLgcEdBKc","580YDOxWIH",
-"ECMvUSjskQ","WmadAcQOnv","ZuDtDUvlv4","MmKGJWaim6","Cp3mZ5nmWv","vLsmSfmIK1","Uvlv414FLR","VerEABpYhV","pWiOsRsQUq","t98iWIRh48",
-"S77LHRzaZA","QYxC0DQimp","Kr8ys7lUXZ","7fsYM0PktI","Oz8yZZv7z0","16lHcDz1R3","HzZT8NOHsz","07n1che9IA","2DREspWiOs","Z4I1v2DREs",
-"uAWyp9eoRc","Chuy3taOXK","4W0TlKsjRK","LewvM4dEz6","lm0pDlCMxy","Chuy3MK07Y","soy9tDG4sT","b29RJI7p2a","QClRLSs0Zu","JXljWYh1hF",
-"FPfSEyluBx","RzaZAtuDyS","v1Hln9XyT9","07n1c5iGN5","Cp3mZBbwgA","he9IAFhtgl","UlU3Mdpe1v","HP433FnPFB","64s8NDQimp","qQxHPF6PT2",
-"RxrsmGXdoH","M3zXL5IhmG","45cIHCNHmv","NOHszZhwG1","K20wKru4UG","azIWpy94nw","zbIYYM6qcG","2NslmO3iyQ","aez9yx3LDe","SmGzvK4GS8",
-"AIYUuOUqFM","IKxdLK4GS8","bZLvSxciqp","uLtKsfcwDa","W7cTsiKqhr","14FLRZhwG1","mX2GEs4786","pFrrldjsrv","MmsIojtn0X","VLTy6pFrrl",
-"QssNCAIYUu","uvf7AVIlwP","QYxC0m4bxU","UlU3Mru4UG","NOHszix74r","jS1ajZuDtD","pT8wuTwano","lpF6WnFqik","iKqhrfqypy","ZUnqtBCxeC",
-"nnP8oa00b5","HlUbFoQ87r","BpYhVsuY4x","P6bcgMGlTF","aDGtStaOXK","Zv7z08cVD3","ogLgc3otm6","9eoRcvkCHH","2DREsZv7z0","zY1GYHP433",
-"gdQsSuLtKs","QbxXcJXljW","uupzkFnPFB","2ZHdk5Drn0","SmGzvx3LDe","vLsmSeuZA5","Yf2Ec6AFT0","Uvlv4OHaBz","HfyNQRkQke","Ta8f6tuDyS",
-"X6PinECMvU","Cfgr3vLsmS","9eoRcOxWIH","oVQp6VIlwP","VjCZqEOE1o","IjTwP618Di","iwzGkyEfy9","vkCHH580YD","KASQ8ZJTXH","ulk41ru4UG",
-"SbRYy9XyT9","d7vjMYOfrY","RmDcrBCxeC","HP433dQ586","EOE1oQ6hMC","fqypyqUJMd","n8pJ9QYxC0","guMb8pvgjS","mX2GEa00b5","jzUqRTwano",
-"FhtgliB08l","Z4I1vCp3mZ","aL6AJaDGtS","W3VFH9iGoT","oGu6xni2v1","NcICADz1R3","8xEKzuPX7G","FjHXRYjB9t","I7p2aFNYIM","FxX9qqQxHP",
-"Cp3mZGXdoH","gf8rIzQt6Q","Pb1paCIShG","jS1ajpT8wu","aL6AJ5VZjS","Ul4a1tvdkD","mX2GEcShY2","t98iWdjsrv","OHaBzuupzk","yvOMIru4UG",
-"M6qcG0BmCy","zHF1qRkQke","dhSuH5drc6","i7WMQRzaZA","taOXK1LB1L","K20wKYOfrY","S2DfuSmGzv","Uvlv4zbIYY","iB08lCp3mZ","GrDg7pAhR1",
-"Ul4a1oVQp6","taOXKZv7z0","XflUqWaim6","FnPFBgf8rI","GSQwj1v5hH","FGzgpdhSuH","QClRLFGzgp","QYxC0n8pJ9","suY4xRBhp0","16lHcStlDJ",
-"RsQUqC2Irc","he9IAy94nw","zHF1q8xEKz","4W0TlUmaEv","EoToPTCgPp","Kr8ys0ao3l","2ZHdkYw2oU","FnPFBtaOXK","fFDrJguMb8","45cIHBGaQY",
-"iB08l0Wr5y","vLsmSBpYhV","EdBKcgIYvE","RxrsmC2Irc","Chuy355rfB","nnP8opWiOs","pWiOsW3VFH","CIShGRmDcr","S77LHzFgtB","v2eC355rfB",
-"Kr8ysYjB9t","FjHXR9iGoT","v2eC3EdBKc","gtCA57ku1p","uAWypn8pJ9","P6bcgMm8si","wiHrZM6qcG","AXpwEiKqhr","jfREuGrDg7","gf8rINOHsz",
-"M3zXLQChxs","7fsYMpFrrl","qQxHPKASQ8","RzaZA0Kyfs","Nxx9VHzZT8","9iGoTZ4I1v","1v5hHZhwG1","VjCZqjSjS3","8cVD3gjUTu","EdBKcM6qcG",
-"Nxx9VfmIK1","4dEz6JXljW","7X3uyatef2","uTacxJ2mQi","uPX7GS2Dfu","QWxoTazIWp","Kr8ysCp3mZ","ZzJHW1LB1L","Cfgr3NAFuw","LewvM24ARF",
-"MmKGJVIlwP","0Wr5yzbIYY","lweGy8cVD3","euZA5Uvlv4","8hJdtRmDcr","KZamHs4786","IKxdLjeskS","sx5Gl2Yz7E","k85Aet59lR","Cfgr3HfyNQ",
-"FFDuifaHir","mX2GEVLTy6","CK5W7POUYS","2hEEUcQOnv","QnJ1Sm4bxU","BGaQYWDVWJ","5IhmGAOgEe","5nmWvoVQp6","xReectuDyS","5VZjSuQIcz",
-"JKWYR8hJdt","5Drn0HRxd8","yofH3Ss0Zu","I7p2aHzZT8","9iGoTMmsIo","lweGyjeskS","hE1QlECMvU","3weIFdmoS7","lj07QgIYvE","48cHLlpF6W",
-"x3LDeCK5W7","W7cTso8Uyd","MmsIoQworu","K4GS82TRI7","RzaZAix74r","zHF1qpmeCd","VLTy6WPmlx","VerEAfcJOy","ReKEWNcICA","8FmFH8FmFH",
-"LbRTHQChxs","gIYvEPb1pa","8xEKzFxX9q","Yw2oUn1pmO","IRh48nFqik","CK5W7C2Irc","FFDuiIn3NS","5ZaEzL7cGc","HlUbFTwano","WmadAkB5nP",
-"POUYStlILt","W3VFHdmoS7","bZLvSNhXdu","5Drn0ni2v1","uQIczWDVWJ","Zv7z0CdyBV","Mm8siv8yFN","CxVEfCNHmv","hi5X70h1b1","MaJQsK4GS8",
-"t98iWtjQxs","cShY2Rxrsm","ciuWzNAFuw","WDVWJWaWsv","pWiOsQWxoT","taOXKSjskQ","tuDySEdBKc","SjskQMm8si","Zv7z024ARF","yEfy9rhl0J",
-"FVMxoFGzgp","GrDg7fFDrJ","gIYvEy94nw","RACuj29QAz","hUTw70ao3l","Uvlv4jiVBP","t98iW9XyT9","JKWYRlweGy","uoStwrhl0J","jzUqRxReec",
-"QYxC024ARF","HP433n1pmO","BFkb8LewvM","d85a9pvgjS","9iGoTkB5nP","618DiSbRYy","zbIYYdQ586","i3pydk85Ae","S77LHWaWsv","h1zcHwiHrZ",
-"8hJdtGSQwj","brhlQJ2mQi","gjUTu5IhmG","6AFT0EdBKc","0ao3l7fKYU","OUYuFfcJOy","LewvMaL6AJ","iwzGkuPX7G","lkMUAiqv4k","MGlTFzY1GY",
-"8RCUA5iGN5","AIYUuHP433","0Wr5yuZPqg","piJSkCdyBV","FhtglxXTI4","JXljWyluBx","AgJHQNcICA","ogLgc29QAz","y94nwfLNg8","DG4sTuTacx",
-"Pb1pauvf7A","MmsIopAhR1","ru4UGulk41","Ul4a1zbIYY","1v5hHa00b5","RsQUqhYBCK","dQ586GSQwj","WPmlxVprf2","JkzUnDLhzM","IBe8ktjQxs",
-"zbIYYhe9IA","LbRTHv1Hln","tvdkDtl72W","yToGWHzZT8","5nmWvQworu","ulk41uQIcz","gtCA58FmFH","kZANmNcICA","v1Hlnulk41","4W0TlWDVWJ",
-"2Yz7EMkgy8","SjskQBGaQY","9y4lwVBjhz","tAOsrOz8yZ","jSjS35IhmG","tl72WRmDcr","AXpwEAmdQd","FjHXRmX2GE","KZamHtAOsr","xXTI4i3pyd",
-"lViBvt59lR","GXdoHuLtKs","HlUbF0MR5X","lweGyuoStw","P6bcgZv7z0","7Ow5CTCgPp","IKxdLnlaBy","QssNCaFFss","64s8N9eoRc","fcwDak85Ae",
-"Ta8f6D6rBy","5IhmGhUTw7","EdBKcaL6AJ","HfyNQGXdoH","KASQ824ARF","azIWp16lHc","8U2nUaFFss","Ul4a1KZamH","JJs5miqv4k","FFDuiK4GS8",
-"CNHmvjfREu","RxrsmQ6hMC","VIlwPsqVrf","CNHmvfFDrJ","WDVWJlm0pD","M6qcG64s8N","W3VFHWaWsv","qUJMde6e4z","EdBKc0Kyfs","Ss0Zul83Ud",
-"yToGWNcICA","jSjS348cHL","QnJ1SyofH3","UlU3M580YD","fFDrJ2TRI7","M3zXLqQxHP","0Wr5yHP433","uJScXyEfy9","djsrvyofH3","ciuWzuoStw",
-"kZANm0Kyfs","FVMxoqaofN","64s8Nsoy9t","n1pmOuvf7A","hUTw7K4GS8","dpe1v9rlg9","LewvM7ku1p","16lHcTXQ0Z","nnP8onnP8o","14FLRaFFss",
-"JKWYRNxx9V","FPfSEK4GS8","5IhmGKASQ8","Vprf2n1pmO","sqVrftAOsr","Yf2EcLbRTH","zbIYYNxx9V","5IhmGuvf7A","FNYIMJRJQB","WmadAJJs5m",
-"dhSuHQ6hMC","0ao3lqaofN","6q6L9tuDyS","RpBQmtjQxs","pWiOs7X3uy","FGzgp5nmWv","5Drn0GXdoH","wDajXJkzUn","2Yz7E14FLR","piJSkM3zXL",
-"lweGyTa8f6","pT8wuPYBf4","lj07Q7fKYU","TXQ0ZWaim6","EdBKcRsQUq","y94nwksJby","Cp3mZDQimp","Mkgy8hUTw7","S2DfuFNYIM","cShY2ReKEW",
-"jzUqRSmGzv","QClRLiKqhr","MmKGJCp3mZ","MmKGJ0MR5X","M3zXLXyPZN","UmaEvB3qem","Y1mC0o8Uyd","Gv3FqF6PT2","BpYhVMaJQs","9iGoTtvdkD",
-"jiVBPzY1GY","FwEJzFNYIM","ulk418xEKz","M3zXLPYBf4","QbxXc5iGN5","pvgjS0MR5X","AIYUuYw2oU","6q6L9uQIcz","guMb8IBe8k","HRxd8zQt6Q",
-"4W0TlOHaBz","fcwDa7lUXZ","UlU3M29QAz","pvgjSyEfy9","HzZT8s4786","Dz1R35iGN5","14FLRZuDtD","UmaEvReKEW","SWfouVprf2","djsrvCdyBV",
-"OUqFMFFDui","SbRYySbRYy","SmGzvC2Irc","oVQp6AgJHQ","uoStwDLhzM","CqqaDv1Hln","AOgEeru4UG","lXFOBtAOsr","QYxC0Zv7z0","W3VFHvkCHH",
-"9eoRcBpYhV","i7WMQuN6r3","WmadAs93Ml","iKqhrt98iW","pT8wuSs0Zu","2NslmtvdkD","fmIK1xXTI4","hUTw70MR5X","NOHszuoStw","W3VFHPYBf4",
-"azIWpjfREu","nlaByVIlwP","MezSWFjHXR","QbxXc0YAGH","5ZaEzYjB9t","618Di55rfB","W7cTsjSjS3","7lUXZ7Ow5C","Waim6iwzGk","SjskQ64s8N",
-"ECMvUksJby","tjQxsxReec","Q6hMCbgJAz","OxWIH2ZHdk","G1RhSnnP8o","oQ87rzHF1q","TCgPpkB5nP","Q6hMC5Mg9r","jtn0X5Mg9r","uoStw5drc6",
-"NAFuwfFDrJ","e6e4z9GXkX","aL6AJNAFuw","8hJdtMmsIo","nlaByMezSW","v8yFNcL0aE","8xEKzcShY2","Y1mC0HRxd8","KsjRK0Kyfs","0MR5X2TRI7",
-"3otm62ZHdk","v2eC3L7cGc","jSjS3v8yFN","d7vjMBbwgA","BpYhVCfgr3","zmLYDRsQUq","jS1ajYOfrY","i7WMQvkCHH","VjCZquLtKs","RxrsmOUqFM",
-"uZPqguJScX","2DREsMm8si","0Kyfsjtn0X","NhXdupvgjS","UmaEvX6Pin","OUYuFIRh48","DLhzMSbRYy","7ku1pvOqCE","55rfBThjNn","ru4UGcQOnv",
-"CqqaDZhwG1","M6qcGgjUTu","faHirqaofN","pFrrlG1RhS","jiVBP4QMc9","tAOsrnFqik","uLtKs0h1b1","G1RhSdmoS7","M3zXLMezSW","ciuWz0h1b1",
-"7hyVvdjsrv","2Yz7EBFkb8","lH1ktyEfy9","fLNg8No0Qb","pWiOs7Ow5C","tAOsrDcpWB","hSSvQVerEA","AIYUuCp3mZ","W7cTsyluBx","dQ58629QAz",
-"FnPFBECMvU","K4GS8kZANm","b29RJnlaBy","kB5nPP6bcg","faHir7hyVv","m4bxUyEfy9","MmKGJK4GS8","tlILthUTw7","LewvMtuDyS","nFqikhYBCK",
-"LDk6fMm8si","qQxHPEOE1o","45cIHFFDui","In3NSfcJOy","fFDrJs93Ml","Q6Lix3weIF","y94nwzFgtB","POUYSVjCZq","8cVD34W0Tl","14FLRDLhzM",
-"zY1GYOUqFM","Z4I1vsx5Gl","iwzGk4dEz6","OUqFMHlUbF","d85a9BCxeC","JJs5mKr8ys","mX2GEfmIK1","uTacxGWqqX","pFrrl9XyT9","Ss0ZuAXpwE",
-"RBhp0gIYvE","n1pmOpWiOs","BGaQYSbRYy","JXljWnnP8o","uZPqgMm8si","uvf7AWDVWJ","lpF6WuLtKs","lweGyChuy3","lpF6W9iGoT","uupzkJIqXi",
-"ECMvUd7vjM","s93MlyofH3","WMiS3ThjNn","SmGzvdQ586","dQ586FjHXR","Cp3mZSmGzv","qQxHP9iGoT","sx5GlBpYhV","fcwDaprNT6","F6PT2AmdQd",
-"StlDJatef2","AmdQdJKWYR","FxX9qB3qem","0Wr5yuJScX","5Drn0Cfgr3","WmadAF6PT2","TXQ0Z9XyT9","GWqqXhE1Ql","QChxsAIYUu","2Yz7E9y4lw",
-"No0QbbrhlQ","EdBKc7lUXZ","AOgEekB5nP","BpYhV7lUXZ","8FmFHtjQxs","QClRLtaOXK","M6qcGSmGzv","m4bxUpT8wu","5Mg9riwzGk","MGlTF0MR5X",
-"1j5L8Yf2Ec","blLA9MezSW","ReKEWNOHsz","uLtKsuZPqg","FhtglJJs5m","MK07YUlU3M","t98iWFhtgl","a00b50BmCy","hYBCKReKEW","PYBf46AFT0",
-"jzUqRnlaBy","O3iyQpWiOs","s7MxklpF6W","brhlQlpF6W","mz8gx2hEEU","Pb1paDQimp","CNHmvMkgy8","Waim68xEKz","MK07YMkgy8","faHirsoy9t",
-"7X3uyB3qem","Z4I1vfqypy","7Ow5CtlILt","VerEAgf8rI","P6bcgStlDJ","Vprf2gf8rI","AmdQdyvOMI","B3qemSbRYy","suY4xWaWsv","JJs5mtaOXK",
-"soy9tFFDui","aL6AJKr8ys","0ao3lsx5Gl","CNHmvgtCA5","7fsYM8RCUA","Mm8siv2eC3","dQ586lm0pD","zFgtBjeskS","IKxdLulk41","4W0TlTXQ0Z",
-"sx5GlgjUTu","soy9t0ao3l","1LB1LM3zXL","QbxXcgIYvE","xciqp5nmWv","a00b5OUqFM","KASQ8zbIYY","uJScXNcICA","FGzgprz7Ut","bgJAzfcJOy",
-"24ARFCp3mZ","VLTy6Mm8si","hYBCKBCxeC","aez9yJJs5m","GrDg7LbRTH","9XyT9bgJAz","Waim6uvf7A","8hJdtQWxoT","dmoS7aez9y","5IhmG64s8N",
-"uvf7AhYBCK","fcwDaAmdQd","OHaBzhE1Ql","zqH0WHlUbF","soy9taez9y","8TxD7sqVrf","Y1mC02ZHdk","5IhmGPYBf4","sqVrfQssNC","jtn0XKr8ys",
-"guMb8QClRL","2hEEU45cIH","CxVEfh1zcH","n8pJ9EoToP","FcWrWBbwgA","Rxrsm4W0Tl","ni2v1FPfSE","QYxC0oGu6x","Y1mC0iB08l","G1RhSFPfSE",
-"gf8rIni2v1","NOHszDLhzM","uJScXaDGtS","YOfrY07n1c","mX2GEh1zcH","8FmFH5VZjS","b29RJFnPFB","G1RhS7X3uy","dQ586zHF1q","hi5X7l83Ud",
-"MK07YPOUYS","CdyBVIjTwP","Gv3FqyToGW","M3zXLblLA9","nnP8olXFOB","CqqaDNOHsz","5VZjSzbIYY","lweGyGv3Fq","yvOMI4dEz6","m4bxU1j5L8",
-"t98iWbgJAz","EoToPdmoS7","MaJQsdpe1v","cmXIXo8Uyd","azIWpBbwgA","RmDcrxReec","gdQsSi7WMQ","6AFT0s4786","YjB9twDajX","3otm6n1pmO",
-"Mkgy8jiVBP","fFDrJQbxXc","ThjNnHfyNQ","zFgtBJXljW","s93Ml45cIH","DG4sTguMb8","WPmlxiKqhr","Vprf216lHc","7lUXZfcJOy","2DREsQssNC",
-"cmXIX29QAz","Q6hMChUTw7","IBe8kXyPZN","QworulCMxy","HfyNQpWiOs","VIlwPIn3NS","Yf2EcVjCZq","nlaByW3VFH","0Wr5yAmdQd","WDVWJ0Kyfs",
-"lm0pDPYBf4","IBe8ksx5Gl","tuDySsuY4x","pAhR1Z4I1v","QbxXcBpYhV","zbIYYX6Pin","0YAGHMojnP","taOXKgtCA5","lsQGoQWxoT","UlU3MGWqqX",
-"HfyNQ1LB1L","XyPZNv1Hln","vOqCE07n1c","BpYhV9y4lw","7Ow5CgdQsS","QnJ1SzQt6Q","JXljWP6bcg","QChxsatef2","WDVWJG1RhS","y94nw7fsYM",
-"GrDg7e6e4z","Mm8siciuWz","bgJAzgjUTu","JIqXiQ6Lix","s4786ru4UG","yluBxvkCHH","FGzgpaez9y","s93MlZuDtD","29QAzaez9y","GrDg7uN6r3",
-"jiVBPQssNC","lj07QbrhlQ","yEfy9M6qcG","pAhR1CqqaD","QssNCM6qcG","Vprf22hEEU","ZhwG1qUJMd","FhtglO3iyQ","e6e4zuupzk","JkzUnVprf2",
-"rz7UthSSvQ","VLTy6KASQ8","UmaEv16lHc","9XyT9SmGzv","nnP8oFVMxo","Cp3mZVBjhz","FjHXR8hJdt","SmGzv7Ow5C","prNT6B3qem","VerEAVjCZq",
-"618Di7lUXZ","lpF6WWmadA","2NslmprNT6","OUqFMyluBx","bgJAzulk41","jfREuFwEJz","QssNCuTacx","HfyNQxReec","64s8NfcwDa","YOfrYQClRL",
-"OUqFMW7cTs","DQimpjS1aj","Mm8siNOHsz","gdQsSM3zXL","atef2FGzgp","yluBxD6rBy","VIlwP29QAz","d7vjM2Yz7E","NOHszm4bxU","9y4lw5drc6",
-"NOHsz580YD","ZuDtDAkKTk","fmIK1Q6hMC","ogLgcd85a9","IBe8k580YD","jfREuUvlv4","1j5L8ZJTXH","AmdQdpv0i7","0KyfsuQIcz","wiHrZyluBx",
-"5nmWvtuDyS","KsjRKxciqp","9iGoTydG8U","yvOMIWreyP","HlUbF29QAz","EoToPGWqqX","KASQ80ao3l","FVMxoRsQUq","zmLYD7Ow5C","RACujsuY4x",
-"s4786MaJQs","ECMvUuTacx","tl72WaDGtS","Q6hMCjzUqR","fcwDaTa8f6","t59lROUqFM","CK5W7CNHmv","AmdQdzQt6Q","CNHmvLDk6f","3weIFAXpwE",
-"FjHXRO3iyQ","he9IAGv3Fq","9XyT9EOE1o","t98iWNhXdu","kB5nPv2eC3","Yw2oUbZLvS","Yf2Ec3weIF","azIWpogLgc","Yf2EcZzJHW","ogLgcNxx9V",
-"b29RJnFqik","FjHXRyluBx","iKqhrMaJQs","ZzJHWuvf7A","djsrvtlILt","Twanov8yFN","QnJ1SZJTXH","ru4UGdmoS7","pvgjSuLtKs","jSjS3lViBv",
-"jSjS3v1Hln","Mm8si5Mg9r","MGlTFuQIcz","pT8wuGSQwj","k85AeFLsph","dmoS7ZhwG1","uLtKsPb1pa","W3VFHuN6r3","t98iWmz8gx","Waim6lCMxy",
-"v2eC35nmWv","jS1ajdjsrv","tlILtJRJQB","5IhmGhe9IA","qQxHPJXljW","lj07QrKDLJ","NAFuwGXdoH","8TxD7ZzJHW","vOqCElXFOB","gjUTuvLsmS",
-"SWfou5Namm","OUYuFG1RhS","ReKEWxciqp","Cp3mZWPmlx","GXdoHOz8yZ","LewvMUlU3M","dmoS7yofH3","s93Mlzz4ZU","MK07YVBjhz","BbwgA8TxD7",
-"48cHLJkzUn","Cp3mZ4W0Tl","oVQp6MaJQs","FNYIMWaWsv","brhlQ3otm6","pmeCd5iGN5","jSjS3b29RJ","zHF1q8cVD3","jiVBPtl72W","LbRTHMGlTF",
-"BpYhVxReec","8xEKzPb1pa","U3yw56q6L9","rKDLJjeskS","n1pmOWMiS3","n1pmOprNT6","OUYuFK4GS8","Oz8yZNxx9V","M3zXLhUTw7","WmadAFwEJz",
-"7hyVvksJby","Gv3Fq48cHL","Vprf2lH1kt","lpF6Wsx5Gl","BFkb8OUYuF","qUJMdfaHir","qaofNrhl0J","FFDuiRxrsm","9iGoTgdQsS","TCgPpsqVrf",
-"U3yw5IjTwP","uoStwFPfSE","HRxd8QnJ1S","oQ87rPOUYS","StlDJJ2mQi","DLhzMOUYuF","TXQ0ZChuy3","6q6L9DLhzM","s93Ml8TxD7","GSQwjzY1GY",
-"tuDySlj07Q","MaJQsG1RhS","Mkgy8HzZT8","v2eC3OxWIH","guMb8lpF6W","IjTwPM3zXL","2ZHdki7WMQ","0h1b1uPX7G","hUTw7SWfou","L7cGcvLsmS",
-"tvdkDguMb8","MezSWRBhp0","fLNg8uQIcz","4QMc9MmKGJ","gdQsS9eoRc","dQ586gjUTu","QWxoT2Yz7E","C2Irct59lR","fqypyhYBCK","uZPqgECMvU",
-"2hEEU5Mg9r","ZJTXHciuWz","SjskQY1mC0","O3iyQ9XyT9","zHF1qo8Uyd","QWxoTo8Uyd","faHirMmKGJ","jiVBPmz8gx","iKqhrzQt6Q","djsrvThjNn",
-"bgJAzD6rBy","48cHL5drc6","gjUTu7ku1p","YOfrYn8pJ9","S2Dfu9XyT9","iB08lnlaBy","FPfSERmDcr","euZA53otm6","W7cTsFLsph","ECMvUYf2Ec",
-"ksJbyEOE1o","jfREuVprf2","iwzGktvdkD","Ul4a1m4bxU","zHF1qI7p2a","uTacxhYBCK","0KyfsIRh48","JkzUnFcWrW","wDajXWDVWJ","LewvMI7p2a",
-"8U2nU9y4lw","Ul4a1lkMUA","FjHXRGSQwj","prNT6zHF1q","yEfy9iwzGk","8hJdtSmGzv","t59lRWmadA","n8pJ9Fhtgl","618DiRsQUq","zqH0WkZANm",
-"HlUbFKsjRK","cShY2S77LH","dQ586fFDrJ","7ku1p3weIF","e6e4zrz7Ut","yToGWJXljW","L7cGclH1kt","AgJHQ5ZaEz","W3VFH2Yz7E","FFDuiDLhzM",
-"5VZjSCp3mZ","ni2v1Mkgy8","fqypyECMvU","IKxdLlweGy","dhSuHMojnP","NAFuw7X3uy","Yh1hFW7cTs","d85a9lCMxy","Chuy3e6e4z","MmsIo0Wr5y",
-"IKxdLX6Pin","hE1QlZuDtD","M6qcGyvOMI","55rfB4dEz6","uQIczqUJMd","UmaEvxciqp","uQIczBpYhV","C2IrcJXljW","3otm6QYxC0","i7WMQprNT6",
-"4QMc9MK07Y","LDk6fpiJSk","aL6AJlXFOB","JIqXiqUJMd","s4786TCgPp","Mm8silpF6W","FFDuiLbRTH","QWxoTb29RJ","QChxsQClRL","RACujn1pmO",
-"IBe8k5Drn0","ZuDtD8TxD7","CdyBVQ6Lix","8xEKzW7cTs","t98iWzqH0W","Z4I1v5Drn0","FnPFB9eoRc","guMb8qaofN","Dz1R3Rxrsm","nnP8ox3LDe",
-"3otm6nlaBy","x3LDefqypy","U3yw5cShY2","brhlQOUqFM","zz4ZUmX2GE","OUYuFSs0Zu","LbRTHHfyNQ","BpYhVciuWz","JKWYRpmeCd","FwEJzTa8f6",
-"h1zcHvOqCE","Z4I1vAkKTk","qUJMdcQOnv","sx5GlfFDrJ","TwanoQ6Lix","5NammIBe8k","pv0i7aez9y","BbwgAWreyP","gf8rIBbwgA","IjTwPAkKTk",
-"fcJOyfaHir","5IhmG5IhmG","uLtKs45cIH","d85a9BFkb8","s93MlZUnqt","U3yw5ciuWz","G1RhSQ6hMC","a00b5lm0pD","MK07Yh1zcH","dpe1vVIlwP",
-"suY4xWmadA","VNCPdaFFss","0YAGH5Namm","e6e4zNOHsz","NAFuw5drc6","Y1mC0tuDyS","gf8rIWPmlx","14FLRrhl0J","0PktIMGlTF","NOHsz8RCUA",
-"FwEJz0MR5X","aL6AJzY1GY","uupzkwiHrZ","gjUTuKZamH","X6Pin9y4lw","xXTI4OUqFM","vOqCEbrhlQ","lm0pDqUJMd","9iGoTnnP8o","v1HlnDG4sT",
-"WreyPFnPFB","yToGWThjNn","FLsphCxVEf","FjHXRIBe8k","4dEz6DcpWB","d85a95IhmG","OHaBzMmsIo","0h1b1KASQ8","k85Ae7hyVv","B3qemW3VFH",
-"wiHrZKASQ8","dmoS79y4lw","s7MxkJRJQB","2Yz7EHfyNQ","ThjNnNcICA","2Yz7EFnPFB","vkCHHW7cTs","AgJHQFGzgp","NhXdupv0i7","d7vjMv1Hln",
-"jtn0XgjUTu","XflUquJScX","OUqFMmX2GE","YOfrYKsjRK","0Wr5ywDajX","CNHmvMGlTF","okgRi8xEKz","t59lRHzZT8","EOE1oh1zcH","pmeCdiB08l",
-"x3LDecQOnv","k85AeUvlv4","uN6r3nnP8o","gIYvEGSQwj","4QMc94W0Tl","ZzJHW9rlg9","ZhwG1ZuDtD","yToGW7Ow5C","Kr8yssx5Gl","Q6LixguMb8",
-"ulk41okgRi","cL0aEbgJAz","blLA98hJdt","RzaZAlXFOB","QbxXcChuy3","uPX7GNAFuw","NOHszIKxdL","DLhzMoQ87r","iqv4ki7WMQ","qaofNSmGzv",
-"Dz1R3nlaBy","QbxXc0BmCy","xReecKASQ8","aL6AJXflUq","bgJAzBGaQY","ru4UG9iGoT","VNCPd2Nslm","iqv4kThjNn","G1RhSCdyBV","xXTI4ZJTXH",
-"xReecStlDJ","1v5hHFhtgl","8TxD7AgJHQ","dpe1vx3LDe","POUYSSbRYy","KASQ8FNYIM","TwanoWaim6","DQimpQnJ1S","m4bxUlj07Q","5nmWvFhtgl",
-"FFDuiZUnqt","vkCHH16lHc","rhl0JFVMxo","lj07QiwzGk","BCxeC9iGoT","EdBKct98iW","CK5W7cmXIX","aDGtSgIYvE","FGzgpsoy9t","7fsYMAkKTk",
-"yEfy9BpYhV","MGlTF8U2nU","FPfSEuLtKs","OxWIHW3VFH","64s8NY1mC0","0ao3ln1pmO","UlU3MWPmlx","rKDLJuQIcz","uQIczS2Dfu","S2DfuM6qcG",
-"hE1QleuZA5","pFrrl8RCUA","SmGzvnFqik","7X3uyi7WMQ","Y1mC0CxVEf","5NammQWxoT","X6PinfcJOy","VLTy64QMc9","qUJMdAOgEe","JXljWB3qem",
-"14FLRPb1pa","1j5L89eoRc","QWxoTMaJQs","SWfouY1mC0","MezSWsx5Gl","iwzGkxciqp","xReec9rlg9","k85AevLsmS","i3pydyluBx","sqVrfHlUbF",
-"QYxC0azIWp","5NammuLtKs","0h1b1vOqCE","rz7UtyluBx","s7MxkxXTI4","0h1b1StlDJ","PYBf4mX2GE","FGzgphi5X7","5Drn0rhl0J","ni2v17X3uy",
-"xXTI4kZANm","d7vjMKsjRK","NAFuwHfyNQ","FjHXRCxVEf","pmeCd4QMc9","JkzUnKr8ys","lkMUASjskQ","FwEJz5Namm","Y1mC0dpe1v","Uvlv4FxX9q",
-"7Ow5CgIYvE","d85a9Q6hMC","IKxdL580YD","dhSuHZv7z0","6AFT0XyPZN","9iGoT580YD","AXpwEZ4I1v","QYxC0W7cTs","X6PinUmaEv","EoToP9eoRc",
-"wiHrZLewvM","Ul4a1QWxoT","AgJHQFwEJz","b29RJCfgr3","ZuDtDWaWsv","7X3uyLbRTH","0YAGHJJs5m","CdyBVjtn0X","lweGy7lUXZ","EoToPiKqhr",
-"580YDZUnqt","WreyPECMvU","QssNCfcwDa","s93Mluvf7A","FNYIMlsQGo","YjB9tQ6hMC","Yh1hF0Wr5y","Waim6RBhp0","tvdkDS77LH","8hJdtCdyBV",
-"e6e4zsqVrf","ogLgcsuY4x","ix74rS77LH","JKWYRSWfou","1LB1LWaim6","fFDrJlweGy","Rxrsm618Di","FFDuioGu6x","Cfgr3S77LH","s93MlFLsph",
-"aL6AJjSjS3","TCgPpoQ87r","EOE1ofaHir","zY1GY0ao3l","zHF1q5Mg9r","7Ow5CtjQxs","FLsphlCMxy","CIShGvkCHH","qUJMd9GXkX","KsjRKVprf2",
-"azIWpM6qcG","F6PT2YjB9t","taOXKgIYvE","lXFOBmz8gx","I7p2aDLhzM","M6qcGjS1aj","5VZjS0PktI","v8yFNFwEJz","O3iyQDLhzM","lpF6WHfyNQ",
-"VerEAK4GS8","9eoRclXFOB","Yw2oUsoy9t","0Wr5ydhSuH","BpYhVuPX7G","Chuy3Waim6","d85a9prNT6","wiHrZSbRYy","Pb1pajeskS","FGzgpF6PT2",
-"PYBf4FwEJz","t59lREdBKc","rKDLJ8U2nU","StlDJOUYuF","UlU3Mrhl0J","pAhR1t59lR","zqH0WsuY4x","Cfgr3zY1GY","5Drn0oGu6x","4dEz6zQt6Q",
-"LewvM8U2nU","CK5W70Kyfs","RmDcriB08l","2ZHdk1LB1L","U3yw5Ss0Zu","iqv4kv2eC3","kB5nPCIShG","dhSuHuvf7A","ulk41CK5W7","KsjRKThjNn",
-"RmDcrOHaBz","FPfSEKr8ys","MGlTFRzaZA","lCMxyW7cTs","AXpwEmX2GE","lpF6Wru4UG","U3yw5S2Dfu","fqypySWfou","BpYhVRBhp0","RmDcraDGtS",
-"RBhp0Mkgy8","VNCPdix74r","FhtglCqqaD","sqVrfKZamH","yvOMIv2eC3","2ZHdkEoToP","0BmCyL7cGc","lH1ktpv0i7","0h1b10Kyfs","L7cGcsuY4x",
-"oQ87rQnJ1S","faHirVprf2","yluBx7fsYM","JKWYR0BmCy","v1HlnfcJOy","sx5GlzqH0W","yToGWguMb8","gjUTuBbwgA","cQOnvG1RhS","oVQp6RACuj",
-"7ku1pMK07Y","64s8NFFDui","QClRLbZLvS","OUYuF580YD","ulk41MK07Y","MK07YFjHXR","2DREsnlaBy","jzUqRzY1GY","UmaEvRmDcr","azIWpfaHir",
-"wDajXhSSvQ","S77LHxciqp","gf8rIBpYhV","NAFuwrKDLJ","BGaQYM6qcG","l83UduTacx","zQt6Q2ZHdk","k85Aeh1zcH","v8yFNyEfy9","BGaQY7fsYM",
-"zY1GYUmaEv","blLA9ZUnqt","LDk6f0h1b1","MaJQsuN6r3","pvgjSYf2Ec","KZamHjSjS3","SbRYyyvOMI","jzUqRK20wK","5drc6jfREu","5Namm2Nslm",
-"atef2ulk41","bgJAz8TxD7","2hEEUlweGy","lm0pDuLtKs","7hyVvix74r","CIShGoVQp6","jzUqRRmDcr","Mkgy80YAGH","oVQp614FLR","PYBf4JIqXi",
-"CIShGTa8f6","yofH3yluBx","MmKGJtuDyS","2DREs618Di","5iGN5Yf2Ec","uQIczJKWYR","CNHmvMezSW","gdQsSh1zcH","2TRI76q6L9","OxWIHciuWz",
-"d7vjMCfgr3","RACuj5Namm","Kr8ysWreyP","VBjhzhe9IA","tlILtfFDrJ","FwEJz2DREs","EdBKcaFFss","WPmlx6AFT0","bZLvSYw2oU","FVMxo2Yz7E",
-"RpBQmzFgtB","fqypypvgjS","HfyNQguMb8","FPfSEgtCA5","jtn0XAkKTk","jeskSUl4a1","07n1clweGy","okgRi55rfB","RzaZAmz8gx","FLsphnFqik",
-"HlUbFgjUTu","tAOsr8cVD3","uoStwRACuj","ThjNnoQ87r","64s8NjfREu","fLNg82Yz7E","ksJbyBFkb8","LDk6f2hEEU","XyPZNiKqhr","aez9y2Yz7E",
-"WaWsvjzUqR","SmGzvfmIK1","Gv3FqiwzGk","ulk41JIqXi","hi5X7fcJOy","aez9yCfgr3","GSQwj9eoRc","07n1cAgJHQ","MojnPo8Uyd","iqv4kOxWIH",
-"PYBf4qUJMd","618DipAhR1","uZPqgMezSW","ni2v1RsQUq","Waim6hYBCK","CxVEfhi5X7","zQt6QPYBf4","hSSvQDLhzM","sqVrfcmXIX","Uvlv47fsYM",
-"dQ586hYBCK","fcJOypFrrl","Y1mC0XyPZN","ZzJHWCdyBV","0h1b1QChxs","ogLgcni2v1","CIShGfmIK1","QworuxReec","TCgPpiB08l","In3NSNOHsz",
-"StlDJcmXIX","dmoS7pv0i7","WaWsvcL0aE","8TxD7EoToP","b29RJBCxeC","Cp3mZTa8f6","Chuy3rz7Ut","ksJbyoVQp6","OUqFMxXTI4","bgJAzPb1pa",
-"yvOMIiB08l","5VZjSiKqhr","VBjhzWmadA","VjCZqgf8rI","DQimpQChxs","wDajXJIqXi","HzZT8ThjNn","QnJ1Ss7Mxk","oGu6xzY1GY","xXTI4M3zXL",
-"he9IAHzZT8","pFrrlv8yFN","I7p2a7X3uy","lweGynnP8o","GXdoHpiJSk","Gv3Fqv8yFN","WMiS3jS1aj","qQxHPvkCHH","v8yFNdjsrv","RmDcr9eoRc",
-"7Ow5Cn8pJ9","29QAzSmGzv","zz4ZUb29RJ","jfREuRsQUq","QssNCFGzgp","qQxHPfFDrJ","45cIHG1RhS","xciqpAmdQd","5Drn0VIlwP","uTacx0YAGH",
-"0h1b1zHF1q","Oz8yZ14FLR","7fsYM2Nslm","KZamH6q6L9","gtCA5fcJOy","MmKGJL7cGc","zFgtBOz8yZ","1v5hHblLA9","sx5Gl7lUXZ","9XyT9LDk6f",
-"POUYSuPX7G","RACuj8hJdt","ZzJHWhe9IA","Yw2oUeuZA5","9rlg9XflUq","piJSk29QAz","xReecVNCPd","iKqhrRkQke","DcpWB7fKYU","24ARFK4GS8",
-"cShY2pv0i7","qaofNG1RhS","2hEEU7ku1p","e6e4zSmGzv","yToGWRzaZA","jSjS3JIqXi","VjCZqaDGtS","UlU3MCNHmv","d85a9SjskQ","TXQ0Z3weIF",
-"48cHLpT8wu","F6PT2dQ586","POUYSksJby","Ta8f6FwEJz","iB08lLDk6f","uQIczfqypy","sx5Gl2ZHdk","8cVD3taOXK","b29RJy94nw","In3NSrKDLJ",
-"qUJMds4786","rhl0Jo8Uyd","cL0aEi7WMQ","Dz1R3lH1kt","JJs5mIRh48","RsQUqPYBf4","JkzUnPb1pa","piJSk6q6L9","bgJAzyluBx","SWfou0ao3l",
-"Kr8ysbgJAz","EdBKc07n1c","5VZjSAmdQd","JJs5mOHaBz","rz7UtBpYhV","ThjNn9iGoT","ThjNnAkKTk","uN6r37Ow5C","jfREuCxVEf","FGzgpRzaZA",
-"BbwgAsqVrf","nFqikLewvM","48cHLW7cTs","oGu6xuN6r3","lH1ktTXQ0Z","jfREuFxX9q","dhSuHUvlv4","MezSWFnPFB","QChxst59lR","0PktIcShY2",
-"i7WMQVBjhz","hUTw7ksJby","b29RJaDGtS","SWfouBCxeC","VNCPdiB08l","iqv4k16lHc","W3VFHW3VFH","WaWsvDcpWB","cmXIXmX2GE","fcwDabZLvS",
-"uPX7GtlILt","ECMvU5drc6","JJs5m8xEKz","zHF1qcShY2","pvgjS7hyVv","x3LDeW3VFH","5iGN5lkMUA","t59lRdpe1v","ix74rs4786","azIWpfFDrJ",
-"Gv3FqvOqCE","n8pJ9618Di","e6e4zFjHXR","e6e4zBCxeC","Zv7z0gdQsS","55rfBiKqhr","zFgtB7fKYU","WaWsvVIlwP","7Ow5Cix74r","iB08lZuDtD",
-"yEfy9FwEJz","taOXK8hJdt","Q6hMCVBjhz","v2eC3ydG8U","ydG8UKr8ys","taOXK7ku1p","Gv3Fqt59lR","gdQsSYf2Ec","ydG8UNhXdu","9rlg9GrDg7",
-"JJs5mThjNn","2Nslm48cHL","4W0Tly94nw","jSjS3GrDg7","K4GS8YjB9t","GWqqX7lUXZ","piJSkuPX7G","618DiKr8ys","ZzJHWRBhp0","QChxs07n1c",
-"brhlQ2Yz7E","AmdQdFjHXR","NOHszI7p2a","brhlQcShY2","Ss0ZuiwzGk","FGzgpdQ586","Cfgr3HP433","RpBQmuoStw","ZzJHWmX2GE","55rfBhYBCK",
-"tAOsroVQp6","pv0i7VBjhz","GXdoHAgJHQ","gf8rIB3qem","pWiOslpF6W","WaWsvgIYvE","lViBvzY1GY","ZUnqtY1mC0","k85AeFNYIM","Ss0ZufFDrJ",
-"DLhzMDz1R3","OxWIHyEfy9","ciuWzSmGzv","hi5X7MGlTF","NcICA48cHL","qUJMd580YD","0BmCyvOqCE","azIWp1j5L8","dmoS7JkzUn","hYBCKxciqp",
-"Ta8f6uN6r3","zHF1qD6rBy","guMb8tuDyS","XflUqlpF6W","uoStw7fsYM","Mkgy8pvgjS","J2mQiAOgEe","LewvMFcWrW","CK5W7uJScX","W7cTsuoStw",
-"CqqaDyofH3","64s8N8hJdt","DLhzMlViBv","jfREuTa8f6","lViBvBpYhV","W7cTs4QMc9","16lHcs7Mxk","5iGN5IjTwP","kZANmFVMxo","W7cTsFnPFB",
-"580YDfcwDa","LDk6ftjQxs","xciqpNOHsz","8RCUA2TRI7","VerEAzz4ZU","FnPFBK4GS8","dQ5865IhmG","MojnPUvlv4","XyPZNpWiOs","9y4lwDQimp",
-"4W0TlDLhzM","Ss0ZuAIYUu","guMb8aez9y","fLNg8hE1Ql","29QAzVNCPd","8cVD3VIlwP","Cfgr3D6rBy","oVQp60MR5X","mz8gx0BmCy","8U2nU7ku1p",
-"Fhtgl7Ow5C","tlILtv2eC3","qaofNTa8f6","gf8rIFnPFB","UmaEviwzGk","QYxC0K4GS8","D6rByhe9IA","kB5nPHzZT8","BbwgADcpWB","yToGWWPmlx",
-"FxX9qkZANm","lweGyKr8ys","lpF6Wv1Hln","zFgtBv1Hln","fmIK18U2nU","5VZjSHP433","v1HlnPYBf4","tuDySQYxC0","B3qemvOqCE","soy9t0Wr5y",
-"lViBvDQimp","hE1QlfFDrJ","S2DfuuLtKs","48cHL9iGoT","OUqFMd7vjM","uTacxcL0aE","P6bcg24ARF","7ku1pNOHsz","D6rByFhtgl","soy9tYh1hF",
-"Oz8yZjeskS","OUYuFLewvM","suY4x2ZHdk","Waim6oQ87r","pmeCddmoS7","DG4sTKASQ8","Q6Lixh1zcH","BFkb8gdQsS","taOXKHlUbF","WPmlxt98iW",
-"brhlQYf2Ec","FNYIMru4UG","XflUqECMvU","55rfBazIWp","KsjRKiKqhr","B3qemQnJ1S","pFrrlZhwG1","JJs5m7ku1p","qQxHPsuY4x","48cHLo8Uyd",
-"VLTy67fKYU","xReecCxVEf","MK07Y24ARF","zbIYYVBjhz","CdyBV8U2nU","ulk41In3NS","zbIYYuQIcz","0BmCyn1pmO","tuDyS580YD","Yw2oUsx5Gl",
-"s7MxkEOE1o","oGu6x6q6L9","kB5nPbZLvS","GXdoHhYBCK","J2mQi2TRI7","dQ586DLhzM","QssNCJXljW","VIlwPO3iyQ","7X3uysuY4x","D6rBylViBv",
-"KZamHtvdkD","Oz8yZMaJQs","16lHcVLTy6","JKWYRMezSW","aL6AJYOfrY","K4GS8gjUTu","tl72W2Yz7E","m4bxUFGzgp","ZJTXH8TxD7","5Nammlj07Q",
-"he9IAaez9y","BCxeCRsQUq","MK07Y5VZjS","jSjS364s8N","Kr8ysqQxHP","s7MxkCNHmv","kZANmCp3mZ","X6PinOxWIH","M6qcG4QMc9","fmIK1ZzJHW",
-"5drc6Pb1pa","JXljWZuDtD","WreyPrhl0J","Vprf2S77LH","ZuDtDCIShG","In3NS8U2nU","POUYSprNT6","JRJQBOxWIH","iKqhrMmKGJ","D6rByBFkb8",
-"ulk41zHF1q","NcICAe6e4z","n8pJ9vLsmS","Ss0ZuxReec","hYBCKiKqhr","RkQke5IhmG","QbxXcLewvM","fLNg8pWiOs","WPmlxuZPqg","RpBQm5Mg9r",
-"lCMxybrhlQ","a00b5KASQ8","RsQUq8xEKz","lj07Q6q6L9","8cVD3MmKGJ","RzaZAJ2mQi","MojnPStlDJ","6AFT0kB5nP","Gv3Fq0PktI","ydG8UwDajX",
-"djsrvJkzUn","euZA5O3iyQ","nlaBydhSuH","atef2618Di","oGu6xguMb8","kB5nPMmsIo","jfREutAOsr","lsQGo9GXkX","ReKEWeuZA5","HP433GrDg7",
-"2Yz7E2DREs","5nmWvBbwgA","24ARF55rfB","blLA9JJs5m","GrDg7k85Ae","FhtglDG4sT","7X3uyQssNC","uJScXBGaQY","RsQUqLbRTH","dhSuHAkKTk",
-"lXFOBBpYhV","7Ow5C4dEz6","DG4sT16lHc","UmaEv14FLR","azIWpDz1R3","xciqpMkgy8","uQIczgtCA5","fmIK1MezSW","P6bcgM3zXL","8RCUAM3zXL",
-"07n1cRsQUq","Nxx9Vn1pmO","i3pydMaJQs","t98iWQssNC","ix74raDGtS","fLNg8aFFss","RzaZAd7vjM","jeskSMezSW","8RCUAmX2GE","1j5L8AmdQd",
-"16lHc45cIH","lCMxyUl4a1","MK07YQ6Lix","brhlQHP433","MaJQsZuDtD","EoToPuvf7A","BpYhVkZANm","OUYuFcShY2","ydG8UuQIcz","ciuWzDcpWB",
-"uN6r3Gv3Fq","dhSuHGv3Fq","4QMc9JRJQB","0MR5X8FmFH","ECMvUqQxHP","3weIFbZLvS","FGzgpCp3mZ","6q6L9GrDg7","vLsmSSbRYy","X6Pin7ku1p",
-"brhlQaFFss","oQ87ri7WMQ","aez9y0MR5X","MojnPMm8si","CNHmvjtn0X","8TxD74W0Tl","l83Udgf8rI","Y1mC0xXTI4","Pb1paiKqhr","KZamHNxx9V",
-"45cIH16lHc","Yw2oUZuDtD","GWqqXOHaBz","KASQ8ru4UG","FnPFBeuZA5","EOE1oxciqp","jiVBPIn3NS","AIYUu24ARF","RkQkeJXljW","yofH3DLhzM",
-"TXQ0ZKZamH","2NslmCfgr3","uPX7GydG8U","taOXKuAWyp","2DREsgtCA5","G1RhSQnJ1S","a00b5v1Hln","9y4lwUlU3M","ReKEWMGlTF","aDGtSv8yFN",
-"J2mQiQssNC","DG4sTBpYhV","s7MxkO3iyQ","WPmlx9XyT9","StlDJni2v1","piJSk5Namm","S77LHEdBKc","WPmlxHRxd8","AkKTkFLsph","8xEKzaez9y",
-"2DREsYw2oU","lm0pDsx5Gl","ulk41VIlwP","AgJHQ24ARF","JKWYRe6e4z","ZzJHWQbxXc","hE1QlFFDui","4dEz6WaWsv","zHF1qoQ87r","GXdoHTCgPp",
-"lm0pDoQ87r","ogLgcMojnP","yToGWRpBQm","0YAGHksJby","7hyVvLDk6f","CxVEflCMxy","oGu6xgIYvE","qaofNJRJQB","JRJQBFPfSE","t98iW5iGN5",
-"uN6r3yluBx","POUYSy94nw","3otm69eoRc","5nmWv07n1c","FxX9qDLhzM","yToGWP6bcg","rz7UtFPfSE","ogLgcl83Ud","nnP8oVBjhz","ZJTXHnlaBy",
-"EdBKcWMiS3","WDVWJM3zXL","RpBQmciuWz","fFDrJdQ586","x3LDeL7cGc","zHF1qX6Pin","X6PintlILt","zHF1qWPmlx","ni2v1jSjS3","HzZT8ogLgc",
-"HfyNQpv0i7","QWxoT5VZjS","n8pJ9azIWp","Ss0ZusuY4x","PYBf4NOHsz","pT8wutlILt","0BmCy6AFT0","9iGoTRkQke","L7cGcFwEJz","dhSuHmX2GE",
-"WaWsv8xEKz","5Drn0In3NS","8FmFHAgJHQ","BpYhVDG4sT","zFgtBAkKTk","29QAz9XyT9","zFgtBs7Mxk","CIShGNAFuw","8xEKz1j5L8","AIYUuuTacx",
-"Oz8yZzbIYY","CK5W7soy9t","mX2GECdyBV","X6Pin4W0Tl","BpYhVKASQ8","prNT6fLNg8","nlaByUl4a1","DQimptjQxs","BpYhVi7WMQ","i7WMQYOfrY",
-"X6Pin2Nslm","MezSWLDk6f","blLA98U2nU","WPmlxjfREu","n1pmO7X3uy","pmeCdoQ87r","Mm8siChuy3","LewvM0h1b1","IRh48n1pmO","RBhp02DREs",
-"IRh484W0Tl","lpF6WFNYIM","AkKTkCp3mZ","VerEAmX2GE","F6PT2jS1aj","XyPZNfLNg8","cL0aE7fsYM","xXTI4RzaZA","HzZT80PktI","zqH0WhYBCK",
-"9rlg9O3iyQ","hSSvQhe9IA","9y4lwlXFOB","ZuDtDRBhp0","Y1mC0KsjRK","2ZHdkdhSuH","TCgPpBGaQY","AkKTk5nmWv","IRh48Y1mC0","zY1GYmX2GE",
-"In3NSlH1kt","SmGzvzY1GY","AmdQdJXljW","gdQsStjQxs","Ss0Zun8pJ9","580YDdpe1v","QworuNOHsz","ZhwG1yToGW","jtn0XtAOsr","oVQp6lpF6W",
-"8hJdt8U2nU","dQ586RzaZA","9XyT9pv0i7","JXljWFwEJz","AXpwEzY1GY","jS1ajSbRYy","2DREsgIYvE","0YAGHWDVWJ","WreyP8U2nU","5Mg9rjzUqR",
-"StlDJk85Ae","7lUXZSs0Zu","FVMxotvdkD","BCxeCS77LH","WaWsv9rlg9","a00b5ksJby","L7cGc580YD","nFqikKsjRK","VBjhzpFrrl","TwanoGWqqX",
-"lCMxyuupzk","guMb8Gv3Fq","1v5hHdjsrv","yEfy9JKWYR","CIShGRsQUq","S2DfuSbRYy","gIYvEZzJHW","W7cTsGrDg7","Yw2oUXyPZN","KZamH8RCUA",
-"v1HlnNhXdu","Q6hMCuLtKs","x3LDeHRxd8","0Kyfss7Mxk","I7p2a7lUXZ","CIShGbgJAz","s7MxkuJScX","Uvlv45IhmG","FxX9qtl72W","ru4UGVNCPd",
-"pT8wuNcICA","uPX7GZJTXH","prNT6FLsph","n8pJ924ARF","VjCZqGXdoH","48cHLzmLYD","AgJHQEdBKc","Cp3mZUmaEv","2TRI7LDk6f","iB08lQnJ1S",
-"LbRTHUmaEv","I7p2aSbRYy","WPmlxM3zXL","tvdkD0Kyfs","jiVBP8hJdt","4W0Tl48cHL","d7vjMpiJSk","xReecQ6hMC","cShY2jiVBP","55rfB0ao3l",
-"W3VFHiqv4k","Ta8f61j5L8","EoToP14FLR","RBhp0IKxdL","FnPFBQChxs","guMb8iB08l","WreyPyToGW","jzUqRuoStw","n1pmOuTacx","VLTy6W3VFH",
-"Oz8yZtlILt","8U2nUb29RJ","jiVBPyvOMI","hSSvQl83Ud","cL0aECK5W7","hE1QlF6PT2","In3NSOUqFM","lpF6Wh1zcH","POUYSWaWsv","StlDJ24ARF",
-"aDGtSnnP8o","xXTI4dpe1v","tjQxsXyPZN","IRh48lweGy","FGzgplXFOB","I7p2annP8o","7fKYUaDGtS","fqypyTXQ0Z","AXpwEv2eC3","iB08lMkgy8",
-"WPmlxWaWsv","t98iWWMiS3","zmLYDPYBf4","rhl0J0PktI","FjHXRaDGtS","5Mg9ruupzk","Ta8f6Cfgr3","sqVrfv1Hln","FjHXRlm0pD","djsrvfcwDa",
-"zY1GYMm8si","cmXIXTwano","dhSuHbrhlQ","mX2GECNHmv","tl72WbgJAz","Chuy30ao3l","fcwDasoy9t","zbIYYI7p2a","okgRiVLTy6","ulk41JkzUn",
-"rhl0JksJby","FxX9q3weIF","cShY27lUXZ","lj07QWPmlx","6AFT0POUYS","sqVrfZuDtD","CqqaDWDVWJ","0ao3lSs0Zu","4dEz6i3pyd","RsQUqYOfrY",
-"RxrsmblLA9","he9IAxXTI4","pvgjSK4GS8","3weIFpvgjS","m4bxUiB08l","dhSuH0YAGH","JXljWciuWz","9GXkXUvlv4","JkzUnhE1Ql","O3iyQKsjRK",
-"uJScXYf2Ec","dpe1vs7Mxk","CxVEfzHF1q","SbRYy5VZjS","0YAGHNhXdu","NcICAqQxHP","tl72WcL0aE","W7cTsAOgEe","vkCHHCK5W7","O3iyQdmoS7",
-"k85AeFcWrW","PYBf4WDVWJ","2ZHdksoy9t","y94nw1j5L8","yEfy9fFDrJ","2DREszFgtB","zmLYDAIYUu","zbIYYHRxd8","SmGzv7ku1p","AkKTkAIYUu",
-"FnPFBHfyNQ","CNHmvFnPFB","djsrvuPX7G","0BmCy5iGN5","Chuy3jzUqR","FGzgpn1pmO","fLNg8hi5X7","7fsYMKZamH","TXQ0ZEdBKc","aFFss0ao3l",
-"0KyfsVBjhz","t98iWZuDtD","taOXKDLhzM","7hyVvcQOnv","cL0aEwiHrZ","fFDrJRkQke","HlUbFm4bxU","Yh1hFVLTy6","pvgjSzY1GY","jfREulCMxy",
-"cShY2K4GS8","C2IrckZANm","45cIHxciqp","oGu6xulk41","9iGoTFcWrW","JkzUnAOgEe","AXpwEni2v1","hUTw7gtCA5","2hEEU8TxD7","PYBf49GXkX",
-"5nmWvlj07Q","yToGWuvf7A","yvOMIVNCPd","CxVEfQssNC","dmoS7hSSvQ","s7MxkJIqXi","ogLgcAgJHQ","EoToPVLTy6","24ARFiB08l","wiHrZKsjRK",
-"sx5Glulk41","cL0aEStlDJ","suY4xmz8gx","GXdoHWmadA","QClRLD6rBy","5VZjS07n1c","WPmlxzHF1q","nFqiklXFOB","gf8rIJJs5m","mz8gxQ6Lix",
-"580YDThjNn","Z4I1vGWqqX","QYxC0CxVEf","uZPqg8xEKz","RkQke4dEz6","n8pJ9WaWsv","jfREuI7p2a","jtn0XQssNC","Nxx9VGSQwj","cShY2FnPFB",
-"Oz8yZIKxdL","jeskSsx5Gl","zz4ZU5Namm","WreyPMkgy8","uvf7Asoy9t","VBjhzQbxXc","9XyT9vOqCE","tlILt9GXkX","0MR5Xt59lR","hSSvQDz1R3",
-"wiHrZnlaBy","5Drn08TxD7","WreyPv2eC3","VNCPdjfREu","fmIK1OUYuF","AmdQd55rfB","7X3uydmoS7","ni2v1SjskQ","14FLRfqypy","7X3uyGWqqX",
-"SmGzvZzJHW","RACujuJScX","Ul4a1s4786","UmaEvQWxoT","RmDcrUlU3M","b29RJhYBCK","NOHszGSQwj","Cp3mZFLsph","PYBf4uupzk","FNYIMEOE1o",
-"mX2GEMezSW","1j5L8LDk6f","k85Ae580YD","vOqCED6rBy","F6PT2jtn0X","EdBKcMmsIo","JRJQBvkCHH","5nmWvWmadA","lsQGoulk41","8TxD7RBhp0",
-"v1Hlnix74r","uLtKslm0pD","zFgtBTwano","CdyBVuTacx","JkzUn7lUXZ","7hyVv07n1c","OUqFMKASQ8","he9IAWaWsv","9eoRcQworu","Oz8yZK20wK",
-"EOE1ozmLYD","9XyT9zz4ZU","8cVD3Q6hMC","hi5X7cQOnv","K20wKS77LH","pWiOsNOHsz","pv0i7WPmlx","07n1cTwano","qaofNtlILt","FFDuiiqv4k",
-"lViBvsoy9t","tjQxsoVQp6","aDGtSVerEA","RBhp0CNHmv","lXFOBvLsmS","RmDcrFwEJz","jtn0X29QAz","7lUXZdjsrv","Rxrsmn1pmO","yluBxs7Mxk",
-"QClRLt98iW","zY1GYmz8gx","aL6AJWaWsv","xReecF6PT2","FjHXRXflUq","nFqikOxWIH","t98iWS77LH","6q6L9VerEA","5iGN5GSQwj","HfyNQ5Drn0",
-"RzaZAMaJQs","HlUbF8FmFH","xXTI4qUJMd","QClRLQssNC","nlaByF6PT2","ru4UGNcICA","F6PT27hyVv","nnP8oIKxdL","BbwgAuupzk","XyPZNHfyNQ",
-"pFrrl580YD","CK5W7wDajX","0PktICxVEf","8TxD7DLhzM","FnPFBb29RJ","mz8gxa00b5","e6e4zRACuj","tjQxsDG4sT","sqVrfZ4I1v","8RCUAFcWrW",
-"0YAGHQbxXc","NcICAJkzUn","P6bcg7hyVv","QssNC3otm6","0PktI8FmFH","VLTy6aDGtS","4QMc91j5L8","JJs5mFwEJz","pAhR1P6bcg","VBjhzjfREu",
-"FnPFBYOfrY","uAWypIKxdL","ReKEWpv0i7","LbRTHReKEW","IBe8kU3yw5","uN6r3lCMxy","ix74rNcICA","QYxC0BpYhV","tlILtDLhzM","9eoRcMezSW",
-"618Dil83Ud","9XyT90MR5X","a00b5o8Uyd","D6rByQ6hMC","07n1cv2eC3","cShY255rfB","t98iWhSSvQ","fmIK1LewvM","QssNCzbIYY","lsQGo5iGN5",
-"BpYhVwDajX","KZamHM6qcG","3otm6WDVWJ","ulk419rlg9","4W0TlpmeCd","LDk6fn1pmO","d85a9O3iyQ","tlILtoVQp6","EoToPgtCA5","Kr8ysVprf2",
-"G1RhSjS1aj","ni2v1JJs5m","rKDLJQbxXc","zqH0WW3VFH","sx5GlGrDg7","wDajXbZLvS","07n1cYf2Ec","RmDcrv1Hln","xciqphE1Ql","16lHcCNHmv",
-"HfyNQn8pJ9","DG4sTyluBx","h1zcH2DREs","GrDg7pFrrl","FjHXRDG4sT","KZamHFxX9q","F6PT2ThjNn","Z4I1vBpYhV","VIlwPlViBv","uPX7GazIWp",
-"hYBCKfFDrJ","a00b5brhlQ","tAOsr0Kyfs","wDajXyluBx","tuDySmz8gx","KsjRKAOgEe","AgJHQ5Mg9r","dpe1vlCMxy","gdQsSBbwgA","oVQp6W7cTs",
-"F6PT25iGN5","uN6r39y4lw","NhXduuPX7G","WMiS3MaJQs","euZA5M6qcG","gIYvEjzUqR","SWfou1v5hH","guMb8o8Uyd","yvOMI9XyT9","tlILtNo0Qb",
-"0h1b10ao3l","No0QbwiHrZ","CNHmvpT8wu","n8pJ9tvdkD","uvf7AFjHXR","Kr8ysfcwDa","2TRI7580YD","TwanoJKWYR","IKxdLksJby","n1pmOciuWz",
-"9XyT9qQxHP","B3qemi7WMQ","pvgjSDLhzM","FjHXRzmLYD","2ZHdkwiHrZ","QChxsuZPqg","iKqhrtjQxs","b29RJpFrrl","azIWpMGlTF","uvf7AJXljW",
-"h1zcHKsjRK","8RCUAAXpwE","8TxD7G1RhS","fqypy7hyVv","580YD9rlg9","9y4lwAXpwE","QworucmXIX","JKWYRS77LH","OUYuFTXQ0Z","8cVD307n1c",
-"tAOsrxciqp","s7MxkWreyP","gtCA5dmoS7","9y4lwsoy9t","Ul4a1yofH3","e6e4zGXdoH","JRJQBBFkb8","aFFssYf2Ec","jeskSM6qcG","1j5L8NhXdu",
-"2TRI7WMiS3","AXpwEUlU3M","ZUnqtThjNn","RACujl83Ud","GWqqXRmDcr","RpBQmUlU3M","i3pydnnP8o","qQxHPe6e4z","FVMxoyToGW","tjQxsYjB9t",
-"JkzUnPYBf4","azIWpdpe1v","Q6hMC5IhmG","GXdoHQYxC0","9GXkX9y4lw","suY4xUlU3M","WMiS3uJScX","7fKYUJKWYR","BGaQYfLNg8","HlUbF7ku1p",
-"d85a924ARF","okgRirKDLJ","zHF1qUvlv4","MGlTFd85a9","jS1aj2ZHdk","Z4I1vh1zcH","StlDJkZANm","lViBvKr8ys","n8pJ9VIlwP","5nmWv9GXkX",
-"8hJdtJ2mQi","k85Aeuvf7A","9rlg9Rxrsm","Z4I1vRBhp0","S2Dfu8xEKz","GrDg7mz8gx","dmoS7tAOsr","MezSWMm8si","CqqaD4QMc9","G1RhSzY1GY",
-"TwanoRzaZA","M3zXL1j5L8","uTacxCNHmv","yluBxZJTXH","Vprf23weIF","7hyVvyToGW","Yw2oUAgJHQ","djsrvgtCA5","EdBKcZhwG1","9iGoTgf8rI",
-"Pb1pajSjS3","C2IrcHP433","yvOMId85a9","OxWIHv2eC3","FcWrWQYxC0","rhl0J4QMc9","yvOMIFxX9q","Q6hMC7Ow5C","0MR5X0PktI","0ao3l5IhmG",
-"8FmFHaez9y","yvOMIUlU3M","lViBvgIYvE","oVQp6suY4x","GWqqXPb1pa","P6bcgBCxeC","8RCUAlH1kt","pFrrlFhtgl","0ao3lC2Irc","he9IAQ6Lix",
-"AkKTkzbIYY","taOXKBCxeC","jiVBP2DREs","PYBf4xciqp","4dEz6k85Ae","suY4xwiHrZ","QYxC0VerEA","5VZjSwDajX","BFkb82TRI7","ZuDtDS77LH",
-"rKDLJFNYIM","BCxeC8RCUA","oQ87rFhtgl","IBe8keuZA5","aL6AJYh1hF","v1Hln0h1b1","Kr8ysfmIK1","2hEEU0PktI","Cp3mZS2Dfu","Cfgr3h1zcH",
-"ydG8UpAhR1","Cp3mZAgJHQ","EoToP7ku1p","F6PT2k85Ae","DcpWBDcpWB","P6bcgPOUYS","5drc6DLhzM","dmoS7iwzGk","ksJbyWmadA","No0QbDG4sT",
-"MezSWhe9IA","8cVD3tAOsr","J2mQiCqqaD","9eoRc2DREs","JKWYRTa8f6","7fsYMP6bcg","QssNC9XyT9","ZUnqtPOUYS","2NslmyEfy9","0BmCyZJTXH",
-"Gv3FqHRxd8","atef2JkzUn","RsQUqiKqhr","soy9tG1RhS","MezSWdjsrv","ix74r7hyVv","2TRI7xXTI4","s7MxkZUnqt","8TxD7xciqp","G1RhS4dEz6",
-"yToGWCdyBV","StlDJFnPFB","iqv4kHfyNQ","EdBKcVprf2","DG4sTUvlv4","dhSuHCIShG","9eoRcVerEA","AXpwEe6e4z","ogLgcdjsrv","Chuy3618Di",
-"S2Dfu4QMc9","HzZT8aez9y","DQimpW7cTs","FnPFBFGzgp","QWxoTYh1hF","taOXK0ao3l","CxVEftjQxs","kZANmjSjS3","WMiS3aL6AJ","RzaZAzY1GY",
-"6q6L9lCMxy","cQOnvo8Uyd","EdBKcuPX7G","JkzUnCfgr3","YOfrY9y4lw","GXdoHbgJAz","YOfrY618Di","9rlg9jtn0X","GWqqXtAOsr","YOfrYAmdQd",
-"HfyNQa00b5","pAhR1gf8rI","EdBKcK4GS8","1v5hHt59lR","uTacxMGlTF","XyPZNSbRYy","Chuy3NAFuw","tlILt2DREs","07n1c0PktI","Chuy3he9IA",
-"GSQwjPb1pa","MezSWAmdQd","Gv3Fqb29RJ","6q6L9iB08l","b29RJVLTy6","14FLRpv0i7","Cp3mZFhtgl","y94nwtjQxs","618DiUvlv4","24ARFDLhzM",
-"2TRI70MR5X","cmXIXJ2mQi","JIqXi8hJdt","4dEz6FLsph","VNCPdUvlv4","2TRI7SmGzv","PYBf4QWxoT","lCMxyVprf2","s93Ml5nmWv","aFFssOHaBz",
-"ni2v1MezSW","QWxoTVLTy6","ZuDtDOHaBz","vOqCEjtn0X","0Wr5yuPX7G","4W0TlHlUbF","pvgjSx3LDe","SmGzvZUnqt","FwEJzhYBCK","h1zcH2TRI7",
-"LDk6fIRh48","45cIHBpYhV","GrDg7faHir","EdBKc6q6L9","xXTI4bgJAz","2TRI7lXFOB","LbRTHogLgc","Nxx9VFcWrW","Mkgy8VBjhz","0PktIL7cGc",
-"Zv7z0x3LDe","0ao3l2hEEU","soy9t4W0Tl","4dEz6lm0pD","6q6L9Yf2Ec","B3qemNAFuw","lj07Q9XyT9","WMiS3pvgjS","h1zcHHfyNQ","29QAzS77LH",
-"kZANmK4GS8","2ZHdkMmsIo","48cHLFxX9q","pv0i7M3zXL","K4GS8QssNC","JKWYRqaofN","hE1Ql55rfB","piJSkMezSW","cQOnvUlU3M","gf8rIBGaQY",
-"2Yz7EXflUq","hYBCKGXdoH","v8yFNMezSW","G1RhSPOUYS","jSjS3euZA5","5ZaEzprNT6","Uvlv4zHF1q","BFkb8yofH3","fFDrJru4UG","he9IASjskQ",
-"azIWpU3yw5","aL6AJtlILt","CdyBVrKDLJ","RzaZAuQIcz","RzaZAlm0pD","lj07QZzJHW","aFFss7fKYU","0KyfsHfyNQ","Ta8f6mX2GE","bgJAzWmadA",
-"EdBKcatef2","BCxeCpT8wu","8cVD3KsjRK","oQ87rYh1hF","b29RJTCgPp","zqH0WlH1kt","KsjRKiwzGk","BGaQYRACuj","9rlg9faHir","WmadApmeCd",
-"fqypyS2Dfu","yvOMIlCMxy","b29RJAXpwE","MmKGJ2DREs","pT8wu5Namm","Gv3FqQYxC0","9rlg91v5hH","kB5nPtl72W","kB5nPs7Mxk","DLhzMgjUTu",
-"StlDJS2Dfu","tvdkDVjCZq","Pb1paBpYhV","D6rBy8U2nU","8xEKzzFgtB","QYxC0i3pyd","rKDLJlsQGo","RACujCfgr3","zmLYDpv0i7","RkQkeaez9y",
-"NOHszazIWp","pmeCdCNHmv","16lHcKr8ys","uAWypYOfrY","8FmFHS2Dfu","5NammSjskQ","Nxx9VTCgPp","hUTw7nnP8o","45cIHY1mC0","lj07QfcwDa",
-"FGzgplpF6W","rz7UtRsQUq","5IhmGWaim6","9y4lwi7WMQ","IKxdLciuWz","0MR5XRsQUq","ydG8UQworu","nnP8oQssNC","JXljWZhwG1","gf8rIpiJSk",
-"ksJbytlILt","pFrrlSmGzv","CK5W7KsjRK","RmDcr2TRI7","FFDuiW3VFH","ulk418hJdt","PYBf48hJdt","5ZaEzRmDcr","XyPZNFFDui","hSSvQd7vjM",
-"2hEEUn1pmO","XyPZNIn3NS","WmadAK4GS8","Nxx9VIjTwP","RACujFFDui","07n1cQClRL","uJScXCp3mZ","iKqhrZv7z0","1v5hHWmadA","JIqXiLbRTH",
-"B3qem8FmFH","YOfrYVNCPd","5Drn04dEz6","NAFuwWaim6","2TRI7ogLgc","StlDJRzaZA","0YAGHiKqhr","MaJQsWPmlx","55rfBuTacx","v2eC3m4bxU",
-"s4786zqH0W","B3qemkZANm","Ta8f6QClRL","MezSWB3qem","7Ow5CTa8f6","6AFT0vkCHH","TXQ0Z14FLR","WmadANcICA","5Drn0618Di","h1zcHpT8wu",
-"suY4xDG4sT","JkzUnzFgtB","pAhR1O3iyQ","JJs5m9eoRc","yToGWn8pJ9","jeskSgdQsS","ZUnqt1j5L8","m4bxUUvlv4","Vprf2Ul4a1","QWxoTKsjRK",
-"FnPFBdQ586","y94nw16lHc","tuDySokgRi","JXljWuAWyp","i3pyd55rfB","wiHrZFxX9q","ni2v1Y1mC0","F6PT2FPfSE","d7vjMTwano","NhXdu8xEKz",
-"Ss0ZuYh1hF","y94nwuoStw","NcICAxciqp","CdyBVhSSvQ","mz8gxAgJHQ","JXljWKsjRK","n1pmOThjNn","8FmFHNhXdu","QYxC0tAOsr","tAOsrX6Pin",
-"XflUqOUYuF","ulk41gIYvE","RBhp00h1b1","QWxoTNOHsz","bZLvStuDyS","jtn0XdmoS7","8cVD3l83Ud","xXTI4IBe8k","JXljWFnPFB","ciuWzK20wK",
-"rhl0J7fsYM","Uvlv4RmDcr","s4786zmLYD","K20wK48cHL","lm0pDGv3Fq","VBjhzsuY4x","kB5nPUlU3M","aFFssYjB9t","QYxC0Chuy3","8U2nUJkzUn",
-"GSQwjsuY4x","9eoRcuZPqg","KsjRKru4UG","RkQkepWiOs","M6qcGaL6AJ","yvOMIQssNC","X6Pin3weIF","gjUTulH1kt","7fKYUhE1Ql","Ta8f6RkQke",
-"hUTw7ulk41","07n1c3otm6","64s8NUmaEv","0BmCyGrDg7","0YAGHs4786","5ZaEzCfgr3","RsQUqNAFuw","k85AeiwzGk","NOHszIBe8k","RpBQmZv7z0",
-"Rxrsm0h1b1","iwzGk5VZjS","XyPZNcmXIX","rz7UtDLhzM","FhtglogLgc","3weIFQWxoT","uPX7GjSjS3","RsQUqJIqXi","POUYSwDajX","cQOnvguMb8",
-"5drc6taOXK","5NammStlDJ","ZUnqtMezSW","EoToPEoToP","KsjRK5Drn0","oGu6x8xEKz","dhSuHP6bcg","Mkgy81LB1L","6q6L9zz4ZU","iB08lUl4a1",
-"64s8N45cIH","618DiIn3NS","JIqXiD6rBy","uQIczDcpWB","jeskSIRh48","64s8N9y4lw","ZUnqtVBjhz","nnP8o45cIH","gf8rIL7cGc","IKxdLMkgy8",
-"WDVWJydG8U","5nmWvfmIK1","uvf7ALewvM","lpF6WSmGzv","t59lR5iGN5","0ao3luTacx","aez9yTXQ0Z","3weIF5Mg9r","IBe8kzHF1q","7ku1pWaWsv",
-"MojnPpv0i7","Gv3FqblLA9","zFgtBBFkb8","FFDuiBCxeC","uJScXsoy9t","brhlQo8Uyd","aDGtSs93Ml","ogLgcUl4a1","lViBvS2Dfu","bZLvSHfyNQ",
-"piJSkd7vjM","618DioQ87r","5Drn0lCMxy","jtn0XoVQp6","9eoRc24ARF","Yf2EcECMvU","nnP8oqaofN","RpBQm0h1b1","euZA5jeskS","4QMc9FGzgp",
-"KASQ8vOqCE","ZhwG1Mm8si","IRh48uTacx","07n1cJRJQB","8hJdtlpF6W","fqypyQ6Lix","zmLYD2ZHdk","GrDg7U3yw5","X6PinCIShG","K20wK5Drn0",
-"ReKEWMmsIo","FxX9q8xEKz","e6e4zAkKTk","qUJMd0BmCy","nnP8o2Nslm","RkQkeRACuj","VjCZqQYxC0","uQIczlH1kt","8RCUAk85Ae","rhl0Jni2v1",
-"8xEKzwiHrZ","hUTw7KASQ8","Z4I1v7fKYU","yvOMI5VZjS","v2eC3MaJQs","gf8rIKsjRK","M3zXLGv3Fq","gdQsSMkgy8","v8yFNMmsIo","L7cGcQ6Lix",
-"dhSuHBpYhV","OUqFM5drc6","xReecKr8ys","Dz1R3RmDcr","AkKTkNcICA","uN6r3dQ586","lViBv4dEz6","d85a9SmGzv","fFDrJSmGzv","SmGzvZuDtD",
-"Ul4a124ARF","I7p2apWiOs","sqVrfru4UG","6AFT0BpYhV","2ZHdkZUnqt","GrDg7In3NS","fqypyCIShG","CIShGrz7Ut","zbIYY9iGoT","IKxdLSs0Zu",
-"45cIHIn3NS","BbwgAZJTXH","xReec2TRI7","faHirChuy3","Nxx9Vi3pyd","JXljWW3VFH","tlILtlH1kt","yluBxYh1hF","gtCA5gf8rI","VjCZqIn3NS",
-"6AFT0FjHXR","uLtKsyofH3","NcICAlXFOB","7ku1pAkKTk","SWfouGWqqX","OUqFMOxWIH","gtCA5IKxdL","AmdQddpe1v","OUqFMLDk6f","M6qcGTCgPp",
-"yofH3iKqhr","VLTy67hyVv","vLsmSTXQ0Z","QWxoTSbRYy","oGu6xKASQ8","D6rBy1j5L8","WMiS37X3uy","FjHXRt98iW","b29RJpmeCd","8RCUA0Kyfs",
-"Zv7z05drc6","euZA5W3VFH","B3qemCxVEf","h1zcHMK07Y","Kr8ysxXTI4","oQ87rogLgc","Uvlv4dpe1v","RmDcrNcICA","9GXkX4W0Tl","qaofNpAhR1",
-"2hEEUru4UG","XflUqlkMUA","P6bcgyofH3","zQt6QQnJ1S","Ss0Zuy94nw","VBjhz5VZjS","CK5W714FLR","MaJQsqaofN","IjTwPQClRL","lkMUAC2Irc",
-"AgJHQdjsrv","7fKYUBGaQY","lCMxyVIlwP","VIlwPMojnP","nFqik8U2nU","NhXdul83Ud","d85a94QMc9","6AFT0JRJQB","x3LDeFxX9q","s93MlWaim6",
-"DLhzMC2Irc","OHaBzHRxd8","uupzkJJs5m","S2DfuqUJMd","M3zXLydG8U","5ZaEzpmeCd","7Ow5CPYBf4","9y4lwJKWYR","JXljWgf8rI","U3yw5LewvM",
-"aDGtSRxrsm","atef2bZLvS","Yf2Ec580YD","cShY2dmoS7","QnJ1SGWqqX","pv0i7JkzUn","YOfrYfqypy","48cHL8xEKz","uTacxgdQsS","iB08l2Nslm",
-"Kr8ysG1RhS","djsrvX6Pin","D6rByaL6AJ","14FLRJJs5m","i3pydlm0pD","NAFuwjfREu","v8yFNnnP8o","cQOnvMmsIo","CxVEfHP433","aez9yM6qcG",
-"QworuO3iyQ","7hyVvbZLvS","6q6L9BbwgA","sqVrfzQt6Q","WMiS37Ow5C","bZLvSEoToP","DcpWBd85a9","Mkgy89eoRc","CxVEfAIYUu","NOHszOUqFM",
-"aL6AJmz8gx","n1pmOZ4I1v","4dEz6MGlTF","GXdoHSmGzv","RBhp0VBjhz","sqVrf2hEEU","NhXdu0Kyfs","Kr8ys9XyT9","cmXIXcShY2","5Mg9rRkQke",
-"4QMc9lpF6W","FhtglWaWsv","lweGyMaJQs","n8pJ9ZJTXH","fLNg8580YD","mz8gxFwEJz","xXTI4Cfgr3","5ZaEzM3zXL","EdBKcv2eC3","NhXduvkCHH",
-"Cp3mZx3LDe","fcJOyFFDui","FxX9q5ZaEz","s4786nnP8o","gdQsSStlDJ","d85a9MmsIo","LewvMulk41","0PktI24ARF","Mm8siNAFuw","aez9yChuy3",
-"Chuy3v1Hln","C2IrcgdQsS","3weIFyEfy9","UmaEvCNHmv","t59lRSWfou","GSQwjatef2","NAFuwcmXIX","iqv4k9GXkX","fcwDan8pJ9","S77LHUvlv4",
-"OUqFMfcwDa","5NammjfREu","zbIYYW3VFH","2hEEUUmaEv","WmadAFnPFB","blLA9cL0aE","45cIHh1zcH","lXFOBhSSvQ","lCMxypFrrl","oGu6x8FmFH",
-"xciqp0YAGH","24ARF48cHL","ydG8UaDGtS","QChxsuLtKs","Vprf2pmeCd","3otm6OUqFM","SbRYyoGu6x","VIlwPNhXdu","Qworuni2v1","CqqaDi7WMQ",
-"BpYhVCK5W7","guMb8lsQGo","jiVBPM6qcG","uZPqgMmsIo","KASQ89y4lw","soy9t5Namm","HRxd8jS1aj","9GXkX7fsYM","JKWYRG1RhS","hE1QlBFkb8",
-"RkQkelm0pD","ciuWznnP8o","2NslmGSQwj","KASQ8IjTwP","29QAzix74r","2NslmCxVEf","fLNg8IBe8k","Dz1R3CdyBV","FhtgltjQxs","7X3uyy94nw",
-"QWxoTRmDcr","LbRTHgtCA5","aFFsslj07Q","i7WMQVIlwP","7fKYUWmadA","0MR5XaL6AJ","uN6r3D6rBy","W7cTstAOsr","bgJAzydG8U","zmLYDLewvM",
-"qUJMdIKxdL","2hEEUpiJSk","QnJ1SpmeCd","nFqikuZPqg","dmoS7Waim6","okgRiHzZT8","Cfgr3Qworu","1j5L8Oz8yZ","0YAGHOz8yZ","8U2nUO3iyQ",
-"7hyVvwDajX","iqv4khi5X7","WmadA5VZjS","IBe8kIjTwP","AgJHQsx5Gl","8xEKzYh1hF","XflUqhYBCK","Ta8f6FxX9q","zbIYYt98iW","7fKYUuJScX",
-"aez9ypT8wu","jS1aj5drc6","NAFuwyEfy9","Cfgr35Mg9r","5Drn0Fhtgl","HfyNQUvlv4","zFgtBv8yFN","tvdkDokgRi","5VZjSTXQ0Z","5Mg9rpvgjS",
-"VjCZqFFDui","IRh48VjCZq","StlDJ618Di","uLtKsQWxoT","h1zcHtaOXK","prNT60MR5X","s4786YjB9t","JJs5m1v5hH","Cp3mZqUJMd","WaWsvmz8gx",
-"s93MlIBe8k","B3qemVNCPd","dpe1vcL0aE","FGzgpU3yw5","OUYuFOxWIH","OUqFMZ4I1v","1v5hH6q6L9","RzaZATCgPp","xXTI4TXQ0Z","jfREuvLsmS",
-"lH1kt7ku1p","X6PinJ2mQi","GrDg7FjHXR","J2mQiQWxoT","tjQxs3otm6","zz4ZUd7vjM","BCxeCU3yw5","uN6r3wDajX","FGzgpRxrsm","Pb1paprNT6",
-"BbwgAydG8U","FGzgpCIShG","yEfy9kZANm","2hEEUG1RhS","5IhmGZ4I1v","kB5nPCfgr3","ZUnqtix74r","Y1mC0JXljW","dmoS7DcpWB","Gv3FqIBe8k",
-"NAFuwMkgy8","zqH0WFPfSE","QClRLQClRL","KASQ8POUYS","d7vjMpAhR1","cmXIXRBhp0","bZLvShUTw7","MmKGJHP433","uvf7AuZPqg","9eoRcRsQUq",
-"G1RhSyvOMI","YjB9tlCMxy","uQIczMojnP","lkMUAzQt6Q","uLtKseuZA5","ksJbyo8Uyd","Z4I1vuN6r3","v8yFNJKWYR","brhlQThjNn","vkCHHRsQUq",
-"ix74rjS1aj","azIWpVIlwP","KASQ8lXFOB","Z4I1viqv4k","SjskQpmeCd","NcICAlsQGo","DG4sTpFrrl","AkKTkM3zXL","b29RJCNHmv","580YDHP433",
-"fcwDaDcpWB","8RCUA1j5L8","RBhp0ReKEW","VjCZqQChxs","WPmlx24ARF","rz7UtB3qem","6q6L9Kr8ys","ciuWzHlUbF","IBe8kcShY2","LewvMl83Ud",
-"S2DfuGWqqX","8cVD3IRh48","EdBKcYf2Ec","AkKTkzY1GY","guMb8D6rBy","0KyfsfmIK1","SbRYyFwEJz","JXljWlViBv","lsQGoS77LH","euZA5a00b5",
-"yluBxiKqhr","ydG8UrKDLJ","oVQp6vLsmS","blLA9ix74r","HRxd8AXpwE","J2mQi0PktI","IKxdLFjHXR","rhl0JzY1GY","sqVrfokgRi","fqypykZANm",
-"t59lRS2Dfu","CK5W7RmDcr","lH1ktXflUq","In3NSAIYUu","8RCUAdhSuH","ru4UGpAhR1","gIYvEbgJAz","s4786M3zXL","2Yz7EksJby","8RCUAfFDrJ",
-"fcwDaHP433","yToGW0YAGH","2Nslm0h1b1","Kr8ys3otm6","zHF1q5drc6","ni2v1m4bxU","5VZjSgdQsS","IRh48n8pJ9","RpBQmP6bcg","zY1GYQssNC",
-"uoStwxXTI4","2ZHdkIn3NS","7hyVvpmeCd","0h1b1S77LH","8FmFHbgJAz","RzaZAX6Pin","FPfSE4W0Tl","rKDLJFPfSE","bZLvSoQ87r","JIqXih1zcH",
-"cmXIX7fsYM","hE1QlbgJAz","Mkgy88RCUA","zFgtB5Mg9r","M3zXL8hJdt","CNHmv618Di","JkzUnMaJQs","AgJHQQClRL","iqv4kJXljW","uJScXbgJAz",
-"2hEEUQnJ1S","cmXIXs93Ml","BGaQYaez9y","6q6L9d85a9","tuDySsoy9t","blLA9KASQ8","ni2v19XyT9","CIShGHlUbF","7ku1pSjskQ","v2eC33otm6",
-"3weIFM3zXL","hUTw7tuDyS","lXFOBSjskQ","piJSkuZPqg","ix74r55rfB","hYBCKpFrrl","Nxx9VMezSW","5iGN5W3VFH","24ARFOHaBz","oGu6xdQ586",
-"BGaQYRBhp0","lsQGoqQxHP","Nxx9VYf2Ec","zz4ZUzFgtB","n8pJ9nFqik","pAhR1JRJQB","QworuHfyNQ","i3pydmX2GE","LDk6fgf8rI","zQt6Q5Mg9r",
-"StlDJgjUTu","C2IrcAmdQd","G1RhS2hEEU","FjHXRPb1pa","Q6hMCIKxdL","fFDrJwDajX","1j5L8hYBCK","JRJQBazIWp","hi5X7rKDLJ","In3NSgtCA5",
-"ni2v1Dz1R3","IBe8kO3iyQ","4QMc91v5hH","jeskSWreyP","tlILt5Drn0","CqqaDJRJQB","hSSvQ4W0Tl","0YAGH7Ow5C","OxWIHS77LH","U3yw5ogLgc",
-"NAFuwVIlwP","taOXKjtn0X","W7cTsNOHsz","blLA92DREs","W3VFHyvOMI","dhSuHaDGtS","Ss0ZutuDyS","8cVD3fLNg8","MojnPDz1R3","CxVEfMkgy8",
-"jSjS38FmFH","Yh1hFCfgr3","7Ow5CK20wK","HzZT8GXdoH","B3qemAIYUu","uLtKshE1Ql","EoToPkB5nP","6AFT0jtn0X","8U2nUlm0pD","48cHLNAFuw",
-"7lUXZReKEW","zqH0WFhtgl","HP433uN6r3","prNT67Ow5C","hSSvQlj07Q","zmLYDD6rBy","DG4sTTCgPp","wiHrZQssNC","8hJdteuZA5","Chuy3uupzk",
-"lCMxyblLA9","14FLRCIShG","VLTy6AkKTk","P6bcga00b5","gtCA5GWqqX","M3zXLVLTy6","Cfgr3kB5nP","ulk41VNCPd","5IhmGCIShG","ReKEWhE1Ql",
-"xciqp7X3uy","zHF1qn1pmO","xXTI4VerEA","AkKTkThjNn","bZLvSX6Pin","XflUq9eoRc","lsQGodhSuH","XyPZN7ku1p","HRxd8xReec","FhtglJkzUn",
-"v8yFNs4786","IBe8kazIWp","bgJAzUmaEv","ogLgcBbwgA","AIYUuTXQ0Z","5Mg9rgIYvE","FxX9q2Yz7E","BpYhVeuZA5","DQimpuAWyp","n8pJ99rlg9",
-"0PktIVLTy6","pv0i7mz8gx","5iGN5fLNg8","8cVD3Nxx9V","Waim6SWfou","580YD5iGN5","s7MxkvOqCE","618DiAgJHQ","soy9tJKWYR","9iGoTm4bxU",
-"uTacxIRh48","OUYuFuZPqg","qUJMdaL6AJ","3weIFfcwDa","3otm6Cfgr3","Zv7z0IKxdL","uQIczJXljW","AmdQd0YAGH","VIlwPJKWYR","cQOnvhYBCK",
-"oVQp6hSSvQ","FnPFBLbRTH","6q6L9faHir","zFgtBgjUTu","h1zcHWreyP","7hyVvYf2Ec","uJScXWmadA","h1zcHni2v1","piJSktl72W","tjQxs7fsYM",
-"l83UddQ586","djsrvVIlwP","ReKEWpT8wu","07n1cQYxC0","M3zXLgdQsS","XyPZNsoy9t","d85a9zY1GY","lXFOBMGlTF","atef25drc6","AOgEeFnPFB",
-"pT8wuqQxHP","hSSvQgjUTu","14FLRdjsrv","uJScXzQt6Q","SjskQfmIK1","kB5nPB3qem","P6bcgbrhlQ","xXTI4uvf7A","i3pydd7vjM","Mm8sia00b5",
-"lViBvtjQxs","v8yFN5Namm","guMb8Uvlv4","1LB1L2Nslm","S2DfuOxWIH","fcJOyKASQ8","yvOMIqQxHP","CNHmvWmadA","8cVD3GSQwj","aL6AJQbxXc",
-"5iGN5qaofN","5nmWvMkgy8","WaWsvgtCA5","nnP8ouAWyp","EoToPMm8si","oVQp64QMc9","TXQ0ZyvOMI","AXpwEwiHrZ","8cVD3fFDrJ","uoStwCIShG",
-"NhXduxXTI4","OxWIH55rfB","7fKYUW7cTs","ydG8UHfyNQ","suY4xQssNC","XyPZN2Yz7E","FwEJzl83Ud","lm0pDv8yFN","0PktIRACuj","o8UydwDajX",
-"uTacx48cHL","okgRiMm8si","W7cTskZANm","zmLYDNAFuw","lsQGopvgjS","AgJHQAmdQd","lH1ktPYBf4","FLsphFhtgl","C2IrcprNT6","aL6AJAgJHQ",
-"0MR5X64s8N","CxVEfK4GS8","mz8gxaL6AJ","hSSvQVNCPd","AmdQd5Drn0","iqv4kNo0Qb","azIWplweGy","WreyPWaim6","i3pydReKEW","tl72Wrhl0J",
-"RmDcrogLgc","IRh4816lHc","nFqikFjHXR","lpF6Wpv0i7","ni2v1hE1Ql","uPX7GZzJHW","KsjRKtuDyS","4W0TlOz8yZ","W7cTsnlaBy","lH1ktjzUqR",
-"IjTwPVIlwP","Waim61v5hH","MGlTFi7WMQ","2TRI714FLR","NcICAMmKGJ","QWxoTS77LH","uTacxUvlv4","QnJ1Sl83Ud","IBe8k8TxD7","CIShGhYBCK",
-"pv0i7BGaQY","nFqik24ARF","EoToPl83Ud","48cHLjfREu","Yf2EcuoStw","ciuWzYOfrY","uTacxWreyP","djsrvMGlTF","5drc6Y1mC0","WPmlxGWqqX",
-"yluBxZUnqt","vLsmSfcwDa","zY1GYrKDLJ","1LB1LCNHmv","qaofNciuWz","tuDySYOfrY","atef23weIF","XyPZNFxX9q","0BmCyHzZT8","he9IAxciqp",
-"9iGoTuPX7G","v8yFNzmLYD","618DiJRJQB","ni2v1AXpwE","G1RhS1j5L8","HP433VNCPd","S77LHAmdQd","BFkb88cVD3","1LB1Lix74r","Qworu9y4lw",
-"W3VFHI7p2a","blLA9J2mQi","taOXK7lUXZ","v2eC3KZamH","n8pJ9xReec","CxVEf8cVD3","W3VFHDQimp","EdBKc9iGoT","F6PT2tuDyS","Q6Lixjtn0X",
-"Waim6GWqqX","0PktI45cIH","5IhmGl83Ud","fqypy4W0Tl","0Wr5y7ku1p","FGzgpGWqqX","pFrrlYw2oU","WmadARBhp0","PYBf4AgJHQ","5ZaEzyvOMI",
-"uQIczIBe8k","DQimpFxX9q","FwEJzru4UG","CqqaD7fKYU","lkMUAxciqp","VNCPdM3zXL","tlILtzY1GY","FLsphb29RJ","vOqCEQClRL","v2eC3e6e4z",
-"LbRTHjtn0X","48cHLMK07Y","ru4UGPOUYS","7hyVvtjQxs","5ZaEzjtn0X","t98iWJIqXi","Yw2oUF6PT2","POUYSOxWIH","9iGoTzz4ZU","okgRifaHir",
-"HlUbFSWfou","JRJQBYjB9t","kB5nPtuDyS","StlDJQworu","29QAzCdyBV","s4786M6qcG","zY1GYRkQke","FwEJzCK5W7","BpYhVMGlTF","zHF1qRBhp0",
-"BFkb8hi5X7","WDVWJzbIYY","Yw2oUuZPqg","QnJ1ScmXIX","zz4ZU45cIH","Z4I1vblLA9","JJs5mGv3Fq","WPmlxzY1GY","CqqaDRkQke","ZJTXHSWfou",
-"No0QbzmLYD","OxWIHDLhzM","OHaBziKqhr","SmGzvQClRL","G1RhS8xEKz","ogLgcP6bcg","tl72W4QMc9","lm0pD5Namm","618Dihe9IA","Yh1hFFjHXR",
-"AkKTkW3VFH","MezSWydG8U","VBjhzpvgjS","HRxd8LDk6f","jtn0XGSQwj","6q6L9gdQsS","Q6Lix5Drn0","ZJTXHaez9y","mX2GEdpe1v","hYBCKnnP8o",
-"ZzJHWfFDrJ","MGlTFTwano","L7cGcMkgy8","jzUqRcmXIX","gtCA5VIlwP","DQimpY1mC0","o8UydB3qem","cL0aEWaim6","8U2nU4dEz6","lweGyy94nw",
-"tjQxs7fKYU","ciuWzGrDg7","MaJQsix74r","2ZHdkcShY2","5IhmGqQxHP","yofH3gIYvE","5iGN5pT8wu","24ARFuTacx","ogLgcFxX9q","gdQsSPOUYS",
-"8RCUARsQUq","9GXkXn1pmO","G1RhSuAWyp","fcJOyoVQp6","cL0aEOUYuF","pT8wuiKqhr","ogLgctvdkD","7lUXZG1RhS","RmDcrMmKGJ","aez9ymz8gx",
-"4QMc9RkQke","5IhmGuN6r3","618Dih1zcH","TXQ0ZXflUq","Twanozz4ZU","o8UydfFDrJ","VNCPdAOgEe","bZLvSS2Dfu","0Wr5y9iGoT","dpe1vjeskS",
-"vOqCE8cVD3","CxVEfNOHsz","IBe8kgtCA5","euZA5W7cTs","fcwDazbIYY","QbxXche9IA","hSSvQUlU3M","8RCUAQ6hMC","ru4UGOHaBz","45cIH07n1c",
-"BbwgAP6bcg","KASQ8brhlQ","KASQ85nmWv","WPmlxpWiOs","1v5hHY1mC0","2Yz7EJXljW","ZzJHWqUJMd","MK07YZzJHW","StlDJBCxeC","hUTw7Cp3mZ",
-"KASQ8xXTI4","mX2GEDcpWB","1j5L8blLA9","EoToP580YD","nFqikZhwG1","0YAGH55rfB","ulk412ZHdk","iB08lcL0aE","4W0TlsuY4x","StlDJuAWyp",
-"CK5W7QYxC0","IRh48WPmlx","yToGW8RCUA","J2mQiZUnqt","RBhp0lH1kt","BbwgAhUTw7","1v5hHzFgtB","xXTI46AFT0","W3VFHiwzGk","hSSvQWPmlx",
-"14FLR45cIH","KASQ8580YD","GrDg7yToGW","580YD6AFT0","2DREsKr8ys","HP433qQxHP","QworuUmaEv","cL0aE7ku1p","DG4sTFcWrW","azIWp7fsYM",
-"JRJQBzqH0W","IjTwP8xEKz","lXFOBZuDtD","JJs5mn8pJ9","FVMxotAOsr","0PktIIjTwP","Mkgy8uPX7G","1j5L8QnJ1S","G1RhSn8pJ9","lkMUAnnP8o",
-"0BmCyUl4a1","1j5L8hi5X7","O3iyQpmeCd","Dz1R3OUqFM","FcWrWjiVBP","5ZaEzJkzUn","WaWsvIKxdL","618Dilj07Q","cL0aEFFDui","FwEJzlpF6W",
-"FLsph7X3uy","uQIczcL0aE","0Wr5y07n1c","5nmWvs7Mxk","WDVWJlXFOB","hi5X7SjskQ","FVMxoiwzGk","SWfouP6bcg","Yf2EcRsQUq","QWxoTStlDJ",
-"CNHmvpAhR1","ZJTXHazIWp","uPX7GHzZT8","9rlg9s93Ml","64s8NiwzGk","TwanoMm8si","dpe1v9XyT9","yEfy9m4bxU","NhXduFNYIM","9eoRcKASQ8",
-"JRJQBWaim6","NAFuwJIqXi","zz4ZUiB08l","Waim6MmsIo","s4786BGaQY","TCgPpAOgEe","NAFuwK4GS8","Cfgr3nFqik","fqypyksJby","FNYIMThjNn",
-"MK07YI7p2a","SjskQVNCPd","Ta8f6UlU3M","HlUbFs7Mxk","pv0i7lXFOB","i7WMQ8hJdt","vOqCEUlU3M","Yf2EcFxX9q","vOqCENOHsz","aDGtSpWiOs",
-"FVMxosqVrf","iB08lt98iW","FjHXRix74r","Vprf2lweGy","iKqhr16lHc","29QAzpFrrl","WreyP5IhmG","Mm8siokgRi","JRJQBFLsph","jzUqRfqypy",
-"cShY2Yh1hF","NOHszBpYhV","DQimpQ6Lix","iqv4k8xEKz","aFFssKZamH","TwanoL7cGc","piJSklweGy","bZLvSv8yFN","blLA9pmeCd","QbxXcxXTI4",
-"y94nwlm0pD","5IhmGB3qem","FFDuiO3iyQ","vOqCEQChxs","W3VFHeuZA5","RpBQmzHF1q","ECMvUe6e4z","e6e4zxReec","x3LDe4dEz6","2ZHdkRmDcr",
-"oGu6xBbwgA","Waim6UmaEv","dhSuHO3iyQ","i7WMQHlUbF","QYxC05drc6","NAFuwzFgtB","s7MxkDz1R3","dmoS745cIH","J2mQiBCxeC","OHaBzTXQ0Z",
-"GXdoHzHF1q","QnJ1SdhSuH","RmDcrNOHsz","k85AeK4GS8","v2eC3BFkb8","6q6L9yEfy9","MaJQss4786","8FmFHOHaBz","B3qemjeskS","JKWYRECMvU",
-"i7WMQmz8gx","BFkb88hJdt","BpYhVSjskQ","ix74r2ZHdk","prNT6BpYhV","RsQUqlweGy","guMb8AIYUu","WDVWJP6bcg","0Wr5yRmDcr","oGu6xQChxs",
-"YOfrYgjUTu","fLNg8bZLvS","djsrv64s8N","7X3uy7hyVv","QWxoT9rlg9","yofH3rhl0J","iB08lJIqXi","ni2v1brhlQ","HRxd85IhmG","WPmlx1v5hH",
-"8hJdtCK5W7","uZPqga00b5","lsQGocL0aE","lsQGotaOXK","yluBxiB08l","VNCPdtl72W","pvgjSuPX7G","TwanohYBCK","vkCHHv8yFN","uJScXtaOXK",
-"JJs5m2TRI7","zbIYYlweGy","9iGoTlm0pD","S2DfuzbIYY","580YD0YAGH","uQIcz7fsYM","FNYIMSbRYy","djsrv0PktI","jSjS3hYBCK","DLhzMYw2oU",
-"UmaEvjeskS","tvdkDgIYvE","pmeCdQbxXc","OUqFMRmDcr","SbRYyTXQ0Z","brhlQiqv4k","a00b5aL6AJ","lsQGoIBe8k","uN6r3bgJAz","iKqhrs7Mxk",
-"S77LHJXljW","NhXduRACuj","WmadAB3qem","45cIHs4786","HlUbFIRh48","yToGWDLhzM","tvdkDMGlTF","WmadACqqaD","OUYuFGSQwj","FcWrWy94nw",
-"5IhmGOxWIH","YOfrYUl4a1","rhl0JFwEJz","Chuy3FFDui","5Mg9rs4786","LDk6fy94nw","F6PT2ni2v1","5NammBGaQY","0Wr5yDQimp","48cHLVjCZq",
-"IRh48JJs5m","O3iyQcQOnv","CqqaDQ6Lix","aL6AJRmDcr","WreyPUl4a1","iqv4kVLTy6","Pb1paJ2mQi","OxWIHJRJQB","taOXKlm0pD","Cp3mZ4QMc9",
-"hUTw7gf8rI","W3VFHdhSuH","brhlQUlU3M","tjQxsOHaBz","qaofNZuDtD","YjB9toVQp6","K20wKtvdkD","zFgtBRzaZA","VerEAsuY4x","U3yw53otm6",
-"zbIYYlCMxy","XflUqHRxd8","EoToPCfgr3","DG4sTiKqhr","YjB9tNo0Qb","y94nwvkCHH","EdBKcEdBKc","uN6r3okgRi","Twano5IhmG","zmLYDjzUqR",
-"hi5X7t59lR","BpYhVO3iyQ","Pb1paIjTwP","GSQwjpv0i7","ksJbyh1zcH","YOfrYjzUqR","3weIFogLgc","24ARFlCMxy","NAFuwZuDtD","BbwgAgdQsS",
-"1v5hHGrDg7","oVQp6piJSk","uvf7A2ZHdk","fqypyHfyNQ","O3iyQCxVEf","hE1Qlm4bxU","qaofNbrhlQ","piJSkx3LDe","TXQ0ZU3yw5","pWiOsdQ586",
-"s4786ni2v1","uLtKsG1RhS","RkQke8xEKz","lXFOBDG4sT","MaJQsnnP8o","jtn0XQ6Lix","0MR5XRkQke","1j5L8prNT6","MezSWVLTy6","hUTw7QssNC",
-"taOXKIRh48","tl72WIn3NS","qaofN4W0Tl","nFqikKr8ys","wiHrZMmsIo","dQ586ru4UG","Zv7z0cmXIX","KZamH9y4lw","BGaQY8TxD7","WmadANo0Qb",
-"9eoRcazIWp","DLhzMJIqXi","G1RhSK4GS8","2hEEU2hEEU","Q6hMCaDGtS","AIYUuW7cTs","qUJMdCNHmv","d7vjM618Di","EdBKcYw2oU","zz4ZUXflUq",
-"6AFT0ReKEW","EOE1ocL0aE","Kr8ysMojnP","nFqikSbRYy","BpYhVgjUTu","QbxXc48cHL","8cVD37Ow5C","Pb1paHfyNQ","uQIczChuy3","CxVEf64s8N",
-"14FLRatef2","HlUbF0h1b1","tvdkD5VZjS","lCMxyLbRTH","Z4I1vaFFss","5Drn0I7p2a","VBjhzUlU3M","rKDLJQ6Lix","nnP8otaOXK","9GXkXDLhzM",
-"vOqCE7X3uy","FVMxoAgJHQ","ZzJHWokgRi","MmsIouvf7A","v1HlnJXljW","2DREsuupzk","618Di0BmCy","TCgPpmz8gx","pFrrl2ZHdk","euZA5NAFuw",
-"QworuTwano","xReecZJTXH","NOHszRBhp0","CxVEfcL0aE","6q6L9lViBv","1LB1L1LB1L","MojnPP6bcg","5Drn0hUTw7","GXdoHQnJ1S","X6PinpAhR1",
-"lpF6WiKqhr","16lHcX6Pin","KsjRKv2eC3","DQimp48cHL","7hyVvs4786","y94nwDz1R3","JRJQBG1RhS","jeskSNhXdu","pvgjSlpF6W","suY4xlsQGo",
-"t98iW14FLR","1j5L85drc6","FPfSE0YAGH","s4786CK5W7","fqypytvdkD","QssNC29QAz","9iGoTP6bcg","zz4ZUMK07Y","0h1b1EdBKc","ru4UGThjNn",
-"t59lRRACuj","RkQkeBCxeC","pmeCdoGu6x","W7cTsgIYvE","CNHmvFhtgl","yvOMIX6Pin","GSQwjn1pmO","RACujEOE1o","Yh1hF5Mg9r","5IhmGFxX9q",
-"hSSvQVprf2","16lHcVprf2","hE1Ql24ARF","oVQp6lsQGo","W3VFHYOfrY","HRxd8wiHrZ","5iGN5ix74r","WreyPXflUq","d7vjMcmXIX","ogLgcqaofN",
-"16lHcGv3Fq","I7p2aMaJQs","Oz8yZ8TxD7","K20wKSWfou","FcWrWMmsIo","OHaBzv1Hln","yvOMIVLTy6","5Mg9rRpBQm","GSQwjNcICA","D6rBynlaBy",
-"In3NS7X3uy","sqVrfNo0Qb","K20wKGrDg7","NcICARsQUq","5iGN5SbRYy","QssNCkB5nP","FNYIMYf2Ec","DQimpIRh48","JJs5mbZLvS","aez9yBpYhV",
-"bZLvSFxX9q","Ul4a1uAWyp","FVMxoxReec","bgJAzFNYIM","XflUqFcWrW","cL0aEAXpwE","yToGWcShY2","U3yw59eoRc","JkzUnYOfrY","pT8wu3otm6",
-"RACujEoToP","9iGoTfcwDa","JKWYRFjHXR","M6qcGCfgr3","MK07YYOfrY","lH1ktSjskQ","jzUqR55rfB","4W0TlLewvM","DG4sT9eoRc","Dz1R3Yh1hF",
-"xXTI4m4bxU","iqv4kSs0Zu","lweGypvgjS","VNCPdjSjS3","ydG8U9rlg9","x3LDeWDVWJ","zbIYYl83Ud","hUTw7yofH3","FcWrW5Drn0","iwzGkdQ586",
-"oGu6xuAWyp","OUqFMyofH3","FFDuitAOsr","D6rBy8hJdt","YjB9tzqH0W","vOqCEeuZA5","CK5W7FxX9q","ydG8UqQxHP","Zv7z0CIShG","atef20Kyfs",
-"uupzkblLA9","iwzGkuTacx","aFFss4QMc9","9iGoTciuWz","9rlg9JIqXi","FGzgpIjTwP","uoStwPYBf4","WMiS3zmLYD","rKDLJsx5Gl","5IhmGtjQxs",
-"0h1b1YjB9t","5IhmGGrDg7","0ao3ls4786","aDGtSzz4ZU","yluBxuLtKs","0YAGH8hJdt","vLsmSWPmlx","618Didpe1v","taOXKFhtgl","WaWsvgdQsS",
-"EdBKcY1mC0","Yf2EckZANm","uvf7A8RCUA","hYBCKO3iyQ","HRxd855rfB","WPmlxlm0pD","oVQp65VZjS","e6e4zWaWsv","aez9yEdBKc","K20wKuoStw",
-"9iGoTWaim6","Dz1R3zz4ZU","580YDdQ586","ThjNnPOUYS","0h1b1yluBx","NOHszFFDui","s93Ml24ARF","s4786TXQ0Z","WMiS324ARF","d85a9SbRYy",
-"5Namm9XyT9","cL0aEYf2Ec","7Ow5CiB08l","pT8wuuvf7A","BCxeCK20wK","1LB1LS77LH","FFDuijtn0X","fmIK1oGu6x","9XyT9S2Dfu","ECMvUzHF1q",
-"Chuy32DREs","vOqCEvOqCE","Nxx9VjeskS","dmoS7NhXdu","vOqCEiqv4k","7hyVve6e4z","lCMxy0PktI","zz4ZU5iGN5","AXpwEJKWYR","dQ5869iGoT",
-"FGzgplCMxy","fLNg8UlU3M","AIYUuQ6hMC","BGaQY9XyT9","X6PinJXljW","P6bcg5ZaEz","XflUqJKWYR","8U2nUNo0Qb","No0Qb7fsYM","CdyBV5Mg9r",
-"Waim6wDajX","MezSWvLsmS","07n1cdmoS7","lj07QMkgy8","7fKYUXyPZN","SWfouuJScX","xReecTa8f6","VBjhzOUYuF","GXdoHQWxoT","HzZT8CNHmv",
-"MezSWNOHsz","MaJQsCqqaD","k85Ae0h1b1","Q6LixpAhR1","zqH0WzY1GY","8U2nUqaofN","KsjRKcmXIX","16lHcTwano","ni2v1n1pmO","WPmlxHfyNQ",
-"aL6AJOUYuF","5iGN55VZjS","qQxHP55rfB","pFrrlQChxs","gjUTuk85Ae","9iGoTtlILt","hi5X7fmIK1","tlILtpAhR1","IRh48ECMvU","fcwDaiKqhr",
-"fcJOywiHrZ","qUJMdVNCPd","gf8rI0ao3l","QWxoTJXljW","7fKYUW3VFH","FwEJzQworu","Kr8ysdhSuH","9eoRcVjCZq","uJScXjtn0X","tl72WnFqik",
-"nnP8ociuWz","k85AezFgtB","0MR5XciuWz","HlUbFzY1GY","Oz8yZLewvM","KASQ8jiVBP","mz8gxLDk6f","M6qcGBCxeC","JKWYRRmDcr","djsrv2TRI7",
-"Nxx9VpvgjS","RzaZAh1zcH","lViBvzmLYD","1LB1LFFDui","iwzGkJXljW","i7WMQuoStw","0Wr5yd85a9","J2mQi5drc6","618DiX6Pin","o8UydRBhp0",
-"zmLYDkZANm","mz8gxfaHir","AgJHQOxWIH","5Mg9rFLsph","hYBCK0ao3l","DG4sTVprf2","MGlTFQssNC","iB08lCIShG","SWfouKASQ8","HfyNQuJScX",
-"0YAGHdhSuH","tAOsrWaim6","SWfouv2eC3","nFqikkZANm","CdyBVJXljW","VIlwPCqqaD","4dEz6GWqqX","aFFss4dEz6","lsQGokB5nP","LbRTHiKqhr",
-"yofH3VerEA","JkzUn45cIH","pv0i7rhl0J","7X3uyVNCPd","D6rByNxx9V","FNYIMMmsIo","jiVBPW3VFH","soy9tjSjS3","pmeCdxReec","jfREuiKqhr",
-"POUYSM6qcG","oQ87rYjB9t","cmXIXlsQGo","o8Uyd24ARF","8RCUA7fsYM","CNHmvgjUTu","vkCHHZJTXH","RsQUqwDajX","7Ow5CHP433","ydG8U5nmWv",
-"580YDfcJOy","FnPFBGXdoH","aez9y5iGN5","uN6r35Namm","VBjhzTwano","U3yw5UmaEv","SmGzvIKxdL","VjCZqSWfou","FFDuiEdBKc","brhlQRxrsm",
-"BCxeCMGlTF","BFkb8QWxoT","CxVEfi7WMQ","pWiOsokgRi","VLTy6dpe1v","IRh48lViBv","3otm60PktI","cmXIXv8yFN","Uvlv4ZUnqt","FxX9q48cHL",
-"cQOnv2DREs","RpBQmmz8gx","hYBCKsuY4x","VBjhzl83Ud","JJs5mSmGzv","4W0Tl0YAGH","qQxHP0PktI","nFqikzz4ZU","hi5X7Pb1pa","Kr8ysDcpWB",
-"BFkb84dEz6","lCMxyhYBCK","3weIFCIShG","Yh1hFhYBCK","x3LDeRACuj","yluBx5IhmG","b29RJzqH0W","bgJAzpFrrl","2hEEU6q6L9","StlDJVLTy6",
-"Cp3mZix74r","2TRI73otm6","ZJTXHtaOXK","Y1mC08hJdt","Pb1pajtn0X","JJs5m9rlg9","nlaByReKEW","4W0TlX6Pin","5Mg9ratef2","FGzgpgtCA5",
-"zY1GYDLhzM","e6e4ztaOXK","9y4lw7hyVv","jeskSJJs5m","n1pmOix74r","pT8wuMmsIo","0MR5XuTacx","WMiS3MmsIo","tlILt7hyVv","24ARFvOqCE",
-"7ku1pFhtgl","Chuy3nFqik","RsQUqWaim6","he9IAhUTw7","2TRI7uoStw","JRJQBjzUqR","7hyVvFLsph","NOHsztl72W","piJSk0h1b1","tl72W2DREs",
-"K20wKyEfy9","fqypyBCxeC","TCgPp5Namm","euZA5GWqqX","LbRTHtAOsr","G1RhSzHF1q","tAOsrlm0pD","Dz1R3W3VFH","VBjhzhSSvQ","Mm8si580YD",
-"VIlwPGrDg7","guMb8v8yFN","RpBQmWmadA","29QAz0BmCy","FjHXRlj07Q","2DREs14FLR","DQimp8hJdt","Dz1R3U3yw5","Pb1paRzaZA","VNCPdazIWp",
-"Q6LixAXpwE","ReKEWuZPqg","s93Ml8cVD3","y94nwReKEW","Yw2oUFxX9q","QYxC0i7WMQ","S77LHhSSvQ","Qworu2Nslm","QYxC0FxX9q","QChxsrKDLJ",
-"i7WMQPOUYS","TwanoFwEJz","OUYuFHfyNQ","0h1b1VjCZq","rz7Utgf8rI","OHaBznFqik","Ul4a1qaofN","k85AelXFOB","suY4x0h1b1","Waim6cmXIX",
-"Kr8yspFrrl","d7vjMciuWz","7fsYMRACuj","yluBxFcWrW","Yw2oUFcWrW","hSSvQG1RhS","CNHmvGrDg7","i7WMQksJby","16lHcfaHir","J2mQiHP433",
-"NcICA29QAz","v8yFNcQOnv","t59lRO3iyQ","i3pydAmdQd","oQ87ruvf7A","QClRLsx5Gl","LewvMOHaBz","gtCA5he9IA","2DREshYBCK","7X3uycQOnv",
-"jeskShSSvQ","OHaBzhSSvQ","Kr8yslsQGo","EOE1ogtCA5","tvdkDkB5nP","aFFssCK5W7","tjQxsQ6Lix","GWqqXpvgjS","lViBvOUqFM","4W0TlO3iyQ",
-"zmLYD0h1b1","zmLYDuAWyp","rKDLJLbRTH","8cVD37X3uy","7hyVvL7cGc","I7p2aiKqhr","QbxXc8U2nU","zHF1q0MR5X","bgJAzNxx9V","RpBQmCfgr3",
-"RACujM3zXL","NcICAIKxdL","pFrrldpe1v","hSSvQk85Ae","LbRTHrz7Ut","s93Ml9rlg9","24ARF6q6L9","d85a9QssNC","o8UydF6PT2","In3NSaez9y",
-"HRxd807n1c","n1pmOCp3mZ","0ao3lQworu","gdQsSiKqhr","Fhtgl7fKYU","ksJbyfLNg8","CNHmv7hyVv","0YAGHJKWYR","ydG8UUlU3M","rKDLJZhwG1",
-"NOHszCIShG","tl72WiB08l","piJSkciuWz","RACujksJby","NhXduWaWsv","y94nwVBjhz","tjQxsiqv4k","kZANmnnP8o","jS1ajWPmlx","lCMxyECMvU",
-"uPX7GpvgjS","lm0pDnFqik","xXTI4qaofN","faHirwiHrZ","Qworudjsrv","29QAzOxWIH","i7WMQyEfy9","soy9t580YD","NOHszWreyP","JJs5mtvdkD",
-"d85a9aDGtS","iwzGk1v5hH","AkKTkvkCHH","M6qcG8cVD3","ECMvUfcwDa","RkQkecL0aE","JKWYRS2Dfu","lpF6WGv3Fq","uTacxuJScX","sqVrfmz8gx",
-"7fsYMSjskQ","WMiS3BFkb8","pT8wuuQIcz","hSSvQoGu6x","JIqXibgJAz","0MR5XMaJQs","WreyPMezSW","zqH0W8xEKz","i7WMQ7Ow5C","hE1Ql7fsYM",
-"yofH3cL0aE","yEfy9lH1kt","9XyT99rlg9","ulk41iqv4k","GWqqX24ARF","uJScXfLNg8","FhtglqUJMd","iqv4ktAOsr","l83UdnnP8o","S77LHU3yw5",
-"uN6r3vLsmS","K20wKFxX9q","6q6L92hEEU","e6e4zLbRTH","QWxoTpv0i7","FLsphgdQsS","Nxx9V6q6L9","brhlQ8hJdt","kB5nPb29RJ","zY1GYsx5Gl",
-"vkCHHuLtKs","VLTy624ARF","D6rByxReec","fqypyYjB9t","3otm6fFDrJ","Yh1hFgtCA5","a00b5ThjNn","lm0pDuupzk","IRh482ZHdk","AmdQdVerEA",
-"JkzUnAkKTk","Mm8siAIYUu","8FmFHmz8gx","Cp3mZTXQ0Z","iwzGkYh1hF","yofH34dEz6","YOfrYJRJQB","s7MxkGWqqX","D6rByvOqCE","dQ586ulk41",
-"lH1kt64s8N","YOfrY48cHL","OUYuFdpe1v","ECMvUlCMxy","jiVBPY1mC0","FPfSES77LH","tl72WJRJQB","LewvMzY1GY","QWxoTuPX7G","AgJHQzbIYY",
-"yluBxqUJMd","a00b57ku1p","Z4I1v29QAz","XyPZNiB08l","lkMUA9rlg9","sx5GljfREu","lH1ktCp3mZ","AkKTkZJTXH","FjHXRjfREu","Chuy3wDajX",
-"FVMxo3weIF","G1RhSMmsIo","hSSvQSbRYy","9eoRcTXQ0Z","DcpWBCxVEf","hUTw7Gv3Fq","uoStwzbIYY","lViBvNxx9V","HlUbFVjCZq","K4GS8Mkgy8",
-"yvOMIsx5Gl","GSQwjQworu","fcJOyzmLYD","45cIHni2v1","24ARFdmoS7","Nxx9VciuWz","yvOMILewvM","gf8rINo0Qb","KASQ8JKWYR","CdyBVuoStw",
-"Y1mC0nFqik","zbIYYtjQxs","dQ586OxWIH","XflUqQ6Lix","6q6L9CIShG","sx5GltlILt","Yh1hFlpF6W","pWiOshYBCK","k85Ae7lUXZ","DcpWBM6qcG",
-"BpYhVUmaEv","zHF1qF6PT2","FjHXRciuWz","YOfrYFcWrW","8cVD324ARF","NOHszqaofN","v1HlnSs0Zu","zmLYDlH1kt","IjTwP24ARF","s7Mxkhi5X7",
-"JKWYR9GXkX","ReKEWjzUqR","guMb8uZPqg","Z4I1vCqqaD","Kr8ysXyPZN","Cfgr3FnPFB","lm0pDhi5X7","ni2v1hi5X7","jiVBPJXljW","h1zcHDz1R3",
-"Y1mC0G1RhS","NcICAJ2mQi","sqVrf0YAGH","iqv4kYw2oU","prNT6VjCZq","RmDcrcQOnv","qaofNjS1aj","Gv3FqfLNg8","VNCPdRpBQm","5NammjS1aj",
-"cL0aEFnPFB","HlUbFi3pyd","29QAzcmXIX","5ZaEzxciqp","hYBCK9rlg9","LDk6fI7p2a","No0QbuTacx","FcWrWlXFOB","Y1mC0h1zcH","kZANmAXpwE",
-"POUYSdpe1v","ZUnqtStlDJ","L7cGc7hyVv","kZANmblLA9","ZzJHWjfREu","Chuy3uAWyp","F6PT2DcpWB","64s8NZuDtD","zqH0WFwEJz","cQOnvDz1R3",
-"2ZHdkhYBCK","VIlwPZUnqt","7Ow5CRmDcr","8cVD3FPfSE","uZPqgWreyP","AgJHQ8hJdt","VjCZqXyPZN","FhtglkB5nP","TXQ0Z0ao3l","l83Ud8xEKz",
-"BbwgAlCMxy","lm0pDNo0Qb","AmdQdazIWp","fFDrJJIqXi","GSQwj0MR5X","zz4ZUOz8yZ","VLTy6Kr8ys","2TRI7uN6r3","X6Pin0PktI","zqH0WRBhp0",
-"7lUXZulk41","WaWsv64s8N","QYxC0mX2GE","OUYuFQssNC","8RCUAMezSW","CqqaDiwzGk","v1HlnVLTy6","wDajXJRJQB","aFFssru4UG","dhSuHbgJAz",
-"Nxx9VL7cGc","SbRYy2Nslm","BpYhVqaofN","rhl0J7hyVv","FNYIMpWiOs","cL0aERsQUq","J2mQiyEfy9","jzUqRcL0aE","i7WMQzbIYY","OUYuFzz4ZU",
-"JRJQBlViBv","dQ586fqypy","IKxdL0h1b1","ThjNnxReec","8U2nUt98iW","mz8gxKZamH","M3zXLrhl0J","qaofNwiHrZ","TCgPp9eoRc","HzZT8gf8rI",
-"Q6hMCgdQsS","5nmWvzFgtB","45cIHguMb8","9eoRclj07Q","CdyBVYh1hF","StlDJcQOnv","CK5W7LewvM","5Drn0pvgjS","hUTw7ECMvU","tvdkDCfgr3",
-"QYxC0PYBf4","lCMxySmGzv","hE1QlCqqaD","JJs5mVerEA","XyPZNQChxs","yluBxTwano","jfREuxReec","hSSvQWmadA","Twano0BmCy","Mkgy8Ss0Zu",
-"EOE1oFPfSE","aDGtSSs0Zu","FnPFBoVQp6","okgRiuvf7A","BpYhVhE1Ql","7X3uypiJSk","AmdQd7Ow5C","QWxoT0BmCy","RzaZAfaHir","l83UdGWqqX",
-"1j5L8OUYuF","CK5W7QssNC","5VZjS5Drn0","M3zXLL7cGc","WreyPpT8wu","NhXdulkMUA","FVMxobrhlQ","S2DfuhYBCK","OUqFM1LB1L","VBjhz0ao3l",
-"FhtglsqVrf","7fsYMpv0i7","pAhR1AIYUu","45cIHSjskQ","0PktISs0Zu","I7p2acmXIX","JRJQBdpe1v","DcpWBSs0Zu","VerEAydG8U","hYBCKgIYvE",
-"MezSW8FmFH","lCMxyHRxd8","PYBf4U3yw5","48cHLGrDg7","kB5nP8hJdt","bZLvSn1pmO","IBe8kChuy3","pAhR1jeskS","7ku1pCNHmv","J2mQiguMb8",
-"vLsmS3otm6","64s8NnnP8o","Mm8siDG4sT","m4bxUfLNg8","ThjNnVerEA","wiHrZjeskS","JIqXi0Kyfs","v1Hlnrz7Ut","1LB1LM6qcG","2TRI7v1Hln",
-"0h1b1gjUTu","iKqhrjSjS3","7ku1p7ku1p","uPX7GFVMxo","Kr8ysFcWrW","5VZjSRkQke","Q6hMCJJs5m","h1zcHjSjS3","Rxrsm5drc6","fmIK1ciuWz",
-"P6bcgtvdkD","kZANmnlaBy","ZJTXH64s8N","4QMc9No0Qb","Yf2EcJJs5m","POUYSi7WMQ","QClRLokgRi","oQ87rIn3NS","ksJbykB5nP","pmeCdyluBx",
-"NhXduQbxXc","HfyNQaL6AJ","tAOsrix74r","Yf2EctAOsr","o8UydiB08l","TXQ0Z8RCUA","iwzGkzFgtB","WmadAlkMUA","8RCUAhE1Ql","iqv4kogLgc",
-"EOE1otuDyS","XyPZNuPX7G","oQ87rCp3mZ","lH1ktQssNC","tuDySMaJQs","7X3uyjfREu","NOHsz7ku1p","FnPFBpvgjS","7lUXZv2eC3","1LB1LhYBCK",
-"vOqCEVIlwP","P6bcgzFgtB","0Wr5ynFqik","Zv7z0ru4UG","zY1GYVLTy6","ydG8UIn3NS","bgJAzhE1Ql","atef2tjQxs","cmXIXaez9y","Y1mC0QssNC",
-"brhlQs93Ml","GSQwjfcwDa","FhtgljiVBP","7X3uyCfgr3","DcpWBgtCA5","tAOsrZUnqt","Cp3mZOxWIH","Uvlv4KZamH","M3zXLWreyP","Y1mC0MojnP",
-"YOfrY0PktI","IRh488TxD7","4W0Tlfqypy","pAhR1o8Uyd","F6PT2vkCHH","WMiS3StlDJ","cL0aEMojnP","gtCA5FFDui","DG4sTIjTwP","G1RhShUTw7",
-"NAFuwaL6AJ","jtn0XwiHrZ","lViBv8U2nU","sx5Gl3otm6","QnJ1S7lUXZ","2Yz7Es4786","KsjRKuJScX","AgJHQVBjhz","JKWYRguMb8","ogLgci3pyd",
-"yofH3IKxdL","iB08l5Mg9r","BCxeC7Ow5C","aez9y0Kyfs","In3NSgf8rI","ZUnqt9eoRc","ReKEWyEfy9","ThjNnYw2oU","JXljWuTacx","dQ586tuDyS",
-"FGzgpogLgc","5nmWvLewvM","faHirpAhR1","nFqikulk41","FGzgpSjskQ","HlUbF9GXkX","Ss0ZuZJTXH","AmdQdlViBv","8RCUArhl0J","aL6AJhUTw7",
-"KASQ8B3qem","618DiJXljW","MK07Yuvf7A","MGlTFjS1aj","BbwgA07n1c","ZUnqt14FLR","yEfy90Wr5y","QnJ1SuZPqg","tvdkDMmsIo","NOHszaez9y",
-"M3zXLTa8f6","xciqpyEfy9","s93MltaOXK","MGlTFFjHXR","CIShGHP433","suY4xLewvM","iqv4kWDVWJ","m4bxU0YAGH","hYBCKyofH3","BpYhVuJScX",
-"OUqFMWDVWJ","GrDg7pv0i7","0Wr5yBbwgA","RpBQmOUYuF","I7p2aReKEW","he9IAEOE1o","XflUqrz7Ut","3otm6a00b5","8hJdtOHaBz","NcICAF6PT2",
-"Ss0ZuF6PT2","RpBQmThjNn","Ta8f60YAGH","0YAGHtAOsr","oVQp6VNCPd","FnPFBJXljW","WDVWJrKDLJ","BGaQYe6e4z","uPX7GUlU3M","taOXKWaWsv",
-"EOE1oAgJHQ","lj07QJkzUn","RACujhi5X7","aFFsshE1Ql","Dz1R3FNYIM","mz8gxQ6hMC","fFDrJlsQGo","o8UydCIShG","Vprf2iqv4k","QWxoTrz7Ut",
-"FwEJzWaim6","uN6r3IBe8k","fqypySbRYy","5iGN52DREs","ZuDtDX6Pin","Q6hMC0Kyfs","blLA9o8Uyd","t98iWfaHir","MmsIouZPqg","nlaBygIYvE",
-"uTacxMmKGJ","5IhmGTXQ0Z","iqv4kVBjhz","8RCUAKsjRK","IRh48SWfou","uTacxpT8wu","aez9ye6e4z","ulk41d85a9","uLtKs5Namm","64s8NpmeCd",
-"TwanoAXpwE","YOfrYuQIcz","pAhR1jS1aj","Waim6ThjNn","kB5nPGWqqX","gf8rI5Namm","ogLgcThjNn","ReKEW2DREs","GrDg73otm6","FjHXR7ku1p",
-"faHirNAFuw","I7p2alCMxy","9eoRcZJTXH","i3pydxXTI4","jtn0XhUTw7","1v5hHxciqp","BFkb8yEfy9","MmsIopvgjS","9XyT9jzUqR","I7p2aEOE1o",
-"1v5hH5VZjS","4dEz6BbwgA","lCMxyxXTI4","Gv3FqaDGtS","qaofNqUJMd","v1HlnTwano","BbwgAfLNg8","kB5nP9y4lw","yToGWt98iW","yToGWOHaBz",
-"dhSuHRxrsm","MK07Ysx5Gl","CIShGStlDJ","55rfBm4bxU","ksJbyCIShG","CqqaD3otm6","oQ87rQbxXc","v2eC3RkQke","PYBf4CNHmv","QbxXcprNT6",
-"uPX7GNOHsz","ZzJHW7ku1p","yToGWTCgPp","BGaQYOHaBz","QnJ1SHRxd8","VBjhz8FmFH","LewvMNAFuw","ZUnqt9y4lw","ulk41MojnP","HlUbFEoToP",
-"djsrvaFFss","SjskQFnPFB","mz8gxOz8yZ","2TRI7aL6AJ","KZamHQbxXc","7hyVvtvdkD","a00b5B3qem","MGlTFiKqhr","I7p2a580YD","YjB9t2hEEU",
-"yvOMIO3iyQ","yToGW618Di","5VZjSnFqik","hSSvQe6e4z","dhSuHv8yFN","HzZT8CK5W7","s7MxkcL0aE","DLhzMCdyBV","HlUbFzmLYD","TCgPpIjTwP",
-"7Ow5CVprf2","K20wKJKWYR","VIlwPDLhzM","aez9y64s8N","vLsmSGWqqX","QYxC0Cp3mZ","8hJdtgtCA5","h1zcHAmdQd","uoStwlweGy","8cVD3IBe8k",
-"48cHLWaim6","2Yz7EtlILt","CdyBVNAFuw","EoToPgjUTu","jtn0XlkMUA","nnP8oPYBf4","uLtKsbrhlQ","fFDrJfcwDa","YOfrYbgJAz","NhXduECMvU",
-"ZzJHWMmKGJ","55rfBIBe8k","yEfy9FcWrW","okgRidpe1v","okgRiQbxXc","nFqikCxVEf","LDk6f9eoRc","h1zcHPb1pa","fcwDajeskS","2ZHdk5Mg9r",
-"GSQwjciuWz","LDk6ft98iW","d85a9tlILt","0BmCyBFkb8","DG4sTMK07Y","dQ5865Drn0","WPmlxni2v1","uTacxLbRTH","e6e4zgf8rI","oQ87rVBjhz",
-"J2mQiAXpwE","fFDrJMK07Y","aFFssbrhlQ","8cVD3yToGW","k85AeTCgPp","uLtKsYjB9t","SjskQIBe8k","RsQUqTXQ0Z","xXTI4lViBv","GSQwj2Nslm",
-"MaJQsAkKTk","StlDJ9XyT9","Yw2oUQChxs","ReKEWReKEW","v2eC35IhmG","2Nslmi3pyd","nnP8oguMb8","oQ87rlCMxy","G1RhSJ2mQi","pv0i78RCUA",
-"zz4ZUqUJMd","i3pydpiJSk","cShY2YOfrY","ZJTXHWDVWJ","rKDLJJIqXi","DcpWBtlILt","aL6AJOHaBz","uAWypiKqhr","0ao3ly94nw","FVMxoJIqXi",
-"2hEEUMojnP","vLsmSbrhlQ","1v5hHFcWrW","guMb8pAhR1","oGu6xIKxdL","618Din8pJ9","lCMxya00b5","Waim6s7Mxk","QbxXcO3iyQ","RACujqaofN",
-"fqypyFnPFB","yluBxEOE1o","FFDuiVBjhz","i7WMQJkzUn","0YAGH16lHc","RmDcr8FmFH","bZLvSuLtKs","gIYvEaDGtS","K20wKLbRTH","1j5L80YAGH",
-"kZANmhYBCK","CK5W7guMb8","DG4sTMaJQs","Ul4a1MK07Y","2Yz7ElweGy","iqv4kIRh48","JkzUnpFrrl","0Wr5yQbxXc","cQOnvIjTwP","2hEEUKASQ8",
-"ni2v1zbIYY","4W0TlM3zXL","GrDg7QssNC","FVMxolpF6W","O3iyQzqH0W","fcwDaLewvM","8RCUAMmsIo","No0QbnFqik","RBhp0G1RhS","NAFuwSs0Zu",
-"ydG8UqaofN","14FLR0PktI","n1pmO7fsYM","JkzUnJXljW","5nmWvGWqqX","uJScX9GXkX","cL0aEsuY4x","v2eC3FGzgp","iqv4kK4GS8","lm0pDwiHrZ",
-"ydG8U0Kyfs","7hyVvC2Irc","X6PinFFDui","B3qemOUYuF","FjHXRZhwG1","uTacxLewvM","X6PinYjB9t","8RCUAWaim6","TXQ0ZRxrsm","n1pmO1j5L8",
-"7ku1pQ6hMC","7hyVvo8Uyd","qUJMdFLsph","xReecxciqp","MaJQsrz7Ut","HP433lm0pD","C2Ircmz8gx","yofH39rlg9","X6Pin8cVD3","KZamHLDk6f",
-"5VZjS8RCUA","n8pJ9aFFss","jS1ajW3VFH","FxX9qfLNg8","FVMxoqQxHP","UmaEvgtCA5","dhSuH9iGoT","FcWrWGSQwj","RACujfcJOy","nnP8oCIShG",
-"Nxx9VCfgr3","8RCUApWiOs","t98iW24ARF","2hEEUaL6AJ","F6PT2SWfou","pT8wuHRxd8","OUqFMdmoS7","Pb1paWDVWJ","POUYSBbwgA","gIYvE4dEz6",
-"nnP8oazIWp","QWxoTix74r","d7vjMkB5nP","ReKEW0MR5X","FGzgpguMb8","8xEKzIjTwP","bZLvSJKWYR","sx5GlWreyP","tvdkDHRxd8","RBhp0tAOsr",
-"fcwDaSWfou","4dEz6BpYhV","FNYIMHP433","FnPFBSWfou","fcwDaoGu6x","FnPFBYh1hF","M6qcGjfREu","0MR5X5drc6","s7MxkTwano","GXdoHeuZA5",
-"0PktIhe9IA","WreyPpWiOs","IKxdLO3iyQ","yvOMIWDVWJ","lpF6WUlU3M","5ZaEzzqH0W","i3pydLewvM","4QMc9vkCHH","x3LDeVjCZq","lkMUAWaWsv",
-"ZzJHWUvlv4","wiHrZEOE1o","VerEAyToGW","zbIYYJRJQB","LDk6fZzJHW","piJSkVprf2","mz8gxfcwDa","i7WMQvLsmS","9GXkXP6bcg","VLTy6Twano",
-"DLhzMZJTXH","xciqpy94nw","lViBvrKDLJ","tjQxsdjsrv","oGu6xQbxXc","n1pmOi7WMQ","atef22DREs","55rfBzHF1q","JJs5mK20wK","2ZHdkHfyNQ",
-"RBhp0DQimp","d85a9StlDJ","qaofNNxx9V","dpe1vnnP8o","QssNCzY1GY","TwanobgJAz","HP433SmGzv","G1RhSgdQsS","tjQxsPb1pa","pT8wue6e4z",
-"5Mg9r7Ow5C","IjTwPMm8si","NOHsz8hJdt","d85a9zmLYD","m4bxUX6Pin","2Yz7EtuDyS","24ARFogLgc","zbIYYhi5X7","0MR5X9eoRc","QssNCiKqhr",
-"atef2rKDLJ","RACujix74r","azIWpuAWyp","UmaEvLDk6f","lH1kteuZA5","hSSvQLDk6f","Cfgr38FmFH","lweGyBpYhV","zz4ZUGv3Fq","X6PinnlaBy",
-"lCMxyWaWsv","POUYSStlDJ","No0Qb55rfB","pv0i79eoRc","9eoRcVBjhz","VerEArhl0J","rhl0J2ZHdk","nFqikIjTwP","07n1clpF6W","YjB9tDcpWB",
-"a00b5W7cTs","CxVEfOHaBz","NOHszNxx9V","9rlg95VZjS","faHirblLA9","ReKEW0BmCy","DG4sTW3VFH","FVMxo0Wr5y","WPmlxix74r","lpF6WVjCZq",
-"zqH0WvkCHH","JXljWTCgPp","nlaBy8xEKz","x3LDeJKWYR","29QAzCNHmv","5drc6FNYIM","aez9yuoStw","S2DfuSWfou","29QAzjtn0X","fqypypiJSk",
-"0Wr5yzz4ZU","yofH3KASQ8","MmsIoYh1hF","Ss0ZuzqH0W","t59lROxWIH","Mm8si8U2nU","JXljWKZamH","ulk416AFT0","a00b5YOfrY","IKxdLv1Hln",
-"2hEEUjtn0X","MaJQsy94nw","uZPqgfLNg8","0KyfsvOqCE","LewvMFVMxo","G1RhSQClRL","8hJdtVNCPd","m4bxUDLhzM","fmIK155rfB","YjB9t1j5L8",
-"v8yFNDcpWB","Yw2oURsQUq","AkKTkMK07Y","Vprf2atef2","zFgtB55rfB","7fKYU8xEKz","jzUqRl83Ud","jzUqROHaBz","ReKEWvLsmS","oQ87r5nmWv",
-"ZUnqt580YD","SjskQQ6Lix","J2mQiU3yw5","YjB9tgtCA5","tvdkDtjQxs","NAFuwpmeCd","djsrvcmXIX","ZuDtD7lUXZ","ThjNn0h1b1","ZUnqtuZPqg",
-"lweGyFPfSE","FjHXRdjsrv","VLTy65Drn0","fqypyRmDcr","he9IAAmdQd","ru4UGd85a9","G1RhSGv3Fq","uupzktaOXK","ciuWzv1Hln","yEfy95Namm",
-"ogLgcVprf2","XflUqVLTy6","fLNg80Kyfs","OUYuF5iGN5","tAOsrtlILt","8U2nUFwEJz","fFDrJPb1pa","P6bcgjS1aj","m4bxUni2v1","a00b5HfyNQ",
-"UlU3Mv8yFN","pWiOsvOqCE","yvOMIQ6Lix","fmIK1a00b5","EdBKcfaHir","bZLvStlILt","sqVrfAgJHQ","F6PT2nFqik","Oz8yZ3otm6","pAhR1i7WMQ",
-"ix74rdhSuH","mz8gxqUJMd","cL0aEix74r","MaJQsciuWz","Pb1pazqH0W","lH1kt8cVD3","RpBQmYjB9t","DQimpQYxC0","dpe1vzFgtB","nlaByQnJ1S",
-"7X3uy64s8N","zbIYYxciqp","ReKEWKr8ys","uPX7GtjQxs","Nxx9VsqVrf","gdQsSLDk6f","48cHLFjHXR","0PktIQClRL","DcpWB7hyVv","lXFOBCIShG",
-"dpe1vJJs5m","fcJOycL0aE","VLTy6QssNC","djsrv7hyVv","1v5hHpv0i7","Nxx9V7hyVv","d85a9lj07Q","IRh48580YD","BCxeCRmDcr","FLsph2DREs",
-"W3VFHwiHrZ","LewvMsuY4x","jfREuyToGW","NhXdu5IhmG","W7cTsRzaZA","xXTI47lUXZ","ZhwG1Q6Lix","Yw2oUfLNg8","ThjNn2ZHdk","QworufFDrJ",
-"xciqpsuY4x","fcwDadmoS7","ZhwG1VjCZq","1LB1Lmz8gx","hYBCK7ku1p","AkKTk0BmCy","1v5hHRxrsm","suY4xuAWyp","5IhmGRsQUq","EoToPZhwG1",
-"ZJTXHaFFss","16lHchUTw7","7fKYUGrDg7","JXljWlsQGo","WreyPtl72W","Q6LixsuY4x","5VZjScL0aE","MGlTFSmGzv","BbwgAQYxC0","CNHmvulk41",
-"dpe1vThjNn","W3VFHfmIK1","55rfBqUJMd","8hJdttuDyS","MGlTFiB08l","7lUXZEdBKc","RpBQmZJTXH","W3VFHfFDrJ","jiVBPfLNg8","8TxD7n1pmO",
-"7fKYUb29RJ","7fsYMZhwG1","W7cTsgdQsS","16lHcn1pmO","o8UydJRJQB","ReKEWRBhp0","C2IrckB5nP","i3pyda00b5","CIShGqQxHP","Fhtgln8pJ9",
-"vkCHHdjsrv","tlILtzHF1q","lH1ktKZamH","JRJQBb29RJ","FLsph7fsYM","VjCZqU3yw5","lpF6W8cVD3","RzaZAQworu","QYxC08U2nU","7fsYMO3iyQ",
-"vOqCENAFuw","SjskQgf8rI","IKxdLSmGzv","FFDuifqypy","qaofNjiVBP","9XyT95nmWv","RACujXyPZN","5iGN5NhXdu","HP433hSSvQ","lH1ktrKDLJ",
-"iKqhrB3qem","blLA9zz4ZU","blLA9oGu6x","ksJbyuLtKs","7ku1pjSjS3","jfREuHP433","VjCZqS2Dfu","7fKYU3weIF","WDVWJjzUqR","fqypy7fKYU",
-"2NslmSs0Zu","ni2v1lViBv","WDVWJX6Pin","aL6AJDQimp","nlaBy0MR5X","StlDJ7Ow5C","iwzGkFxX9q","RkQkelkMUA","FwEJzUlU3M","OUYuFFFDui",
-"s4786O3iyQ","FxX9qLDk6f","gf8rIi7WMQ","uAWypcShY2","oQ87rQ6hMC","JKWYRHRxd8","pFrrlHzZT8","pvgjSqUJMd","ksJby8RCUA","zHF1qQssNC",
-"J2mQiRzaZA","zY1GY14FLR","QssNCru4UG","S2Dfu2TRI7","C2Irc8TxD7","VerEAtuDyS","5Namma00b5","ksJbyjtn0X","vLsmSnlaBy","t59lR7fsYM",
-"bZLvS0Kyfs","Cfgr32DREs","UlU3MWaWsv","9GXkXuN6r3","Ss0Zuuupzk","UlU3MB3qem","tjQxshUTw7","VIlwP9iGoT","tuDyScQOnv","aDGtSpvgjS",
-"lkMUA7lUXZ","pvgjSFFDui","SjskQIjTwP","AXpwE45cIH","PYBf4Chuy3","QnJ1SI7p2a","55rfBnFqik","Mm8sibrhlQ","uAWypJJs5m","he9IArz7Ut",
-"YjB9tWDVWJ","djsrvn8pJ9","SjskQzbIYY","AIYUutjQxs","S2Dfuh1zcH","5Drn0brhlQ","e6e4zStlDJ","HRxd8F6PT2","HfyNQ6AFT0","U3yw5brhlQ",
-"uTacxJRJQB","EOE1oW3VFH","yToGWMkgy8","FNYIMsx5Gl","Pb1paJJs5m","BbwgAzY1GY","o8UydJIqXi","faHirCxVEf","cmXIXThjNn","WDVWJQChxs",
-"gtCA5uvf7A","0MR5XDQimp","lH1ktlCMxy","k85AekZANm","7hyVv5Drn0","XyPZNSjskQ","SjskQQClRL","QworunFqik","oQ87rXflUq","NOHszRpBQm",
-"okgRiBGaQY","uLtKszz4ZU","jiVBPKr8ys","tjQxszqH0W","P6bcg0ao3l","CqqaD0MR5X","dhSuHokgRi","prNT6uupzk","VerEAlXFOB","fFDrJEdBKc",
-"2DREsW7cTs","WPmlxo8Uyd","VerEAGXdoH","vOqCE9iGoT","uZPqgWPmlx","cShY2atef2","suY4xNOHsz","iB08lRBhp0","JJs5mKZamH","F6PT2VIlwP",
-"pmeCdnlaBy","GrDg7BpYhV","tjQxs8xEKz","WDVWJKr8ys","AkKTkK4GS8","BCxeCWaim6","brhlQrz7Ut","8U2nUTXQ0Z","G1RhSeuZA5","jSjS3FcWrW",
-"zqH0W2Yz7E","hYBCK45cIH","Gv3FqFnPFB","KZamHOHaBz","HRxd8pFrrl","fmIK1Kr8ys","FjHXR9eoRc","0BmCydjsrv","DG4sThi5X7","JKWYRJJs5m",
-"55rfBfcwDa","Gv3FqGWqqX","tlILtnFqik","ZhwG1CK5W7","iwzGkni2v1","AIYUuIRh48","v1Hlnjtn0X","lm0pDB3qem","oGu6x24ARF","8hJdts93Ml",
-"yToGWuTacx","JJs5mWmadA","uAWypMaJQs","7ku1pBpYhV","Q6hMCNcICA","Z4I1vCK5W7","atef25VZjS","JXljW5drc6","SWfouDz1R3","lH1ktyluBx",
-"YOfrY0YAGH","fcwDaFwEJz","MaJQs7ku1p","24ARFb29RJ","VerEARsQUq","lpF6WLewvM","580YDWreyP","uLtKsjiVBP","gtCA507n1c","nnP8ovLsmS",
-"U3yw57ku1p","Gv3FqNxx9V","0Wr5yCIShG","aFFssJIqXi","U3yw5VBjhz","ciuWzy94nw","ulk41rz7Ut","YjB9togLgc","OUYuFXflUq","QChxsWaim6",
-"No0Qbe6e4z","EoToPFPfSE","djsrvRsQUq","mz8gxWDVWJ","tvdkDCNHmv","VNCPdGv3Fq","J2mQi5VZjS","tlILtHP433","2ZHdk0MR5X","atef2No0Qb",
-"ThjNnFjHXR","F6PT2iwzGk","29QAzW7cTs","Yw2oU5ZaEz","uupzk7Ow5C","QWxoTYw2oU","NcICAt98iW","cQOnvyluBx","Q6LixMGlTF","TXQ0ZfcwDa",
-"IBe8kWDVWJ","NOHszJ2mQi","SbRYyru4UG","14FLRO3iyQ","1LB1Lxciqp","1j5L8wDajX","lpF6WWreyP","qQxHPMK07Y","jS1ajqQxHP","zz4ZUfFDrJ",
-"gdQsS618Di","uLtKsU3yw5","s93MlpmeCd","JXljWazIWp","W7cTszqH0W","NhXduNxx9V","JXljW5iGN5","AkKTkUvlv4","CK5W7gjUTu","L7cGct59lR",
-"KsjRKlH1kt","zqH0WNo0Qb","XyPZNxXTI4","FVMxo8FmFH","MGlTFcL0aE","hi5X77fKYU","lm0pDzbIYY","8TxD73weIF","RzaZAFcWrW","1LB1LD6rBy",
-"Yf2Ecdjsrv","CIShGlpF6W","iB08lVprf2","POUYSAIYUu","EdBKcEOE1o","pAhR1FPfSE","cL0aEdjsrv","IBe8kFnPFB","L7cGc16lHc","Uvlv4Cfgr3",
-"ZUnqtPYBf4","faHirWDVWJ","5drc6LbRTH","AkKTkRxrsm","dQ586HzZT8","D6rBytAOsr","uTacxi7WMQ","faHirMm8si","JRJQBKsjRK","9y4lwv8yFN",
-"7fsYMZuDtD","faHirGXdoH","k85AeNxx9V","uAWypRpBQm","5Drn0o8Uyd","Yw2oUIn3NS","CdyBVcL0aE","kZANmlCMxy","9rlg9vLsmS","rhl0JBpYhV",
-"J2mQizQt6Q","TCgPp3weIF","nlaByPb1pa","MmKGJ2hEEU","YOfrYTXQ0Z","okgRitAOsr","YOfrYEoToP","5ZaEzD6rBy","AOgEe0MR5X","CxVEfNxx9V",
-"0KyfsJRJQB","lj07QJKWYR","DQimp7ku1p","U3yw5BFkb8","uAWyp24ARF","GXdoHCK5W7","QworulXFOB","uTacxgIYvE","2TRI7iqv4k","JJs5mWaWsv",
-"Yf2EcuLtKs","dmoS7JJs5m","0MR5XChuy3","XyPZNRzaZA","uZPqgcQOnv","ZUnqtQYxC0","Q6hMCWDVWJ","L7cGczFgtB","faHircQOnv","SjskQfaHir",
-"WreyPuoStw","W7cTsfFDrJ","0BmCy64s8N","PYBf4uTacx","0MR5XAXpwE","fcwDaKASQ8","suY4x5nmWv","JkzUn5ZaEz","JkzUnKsjRK","ni2v1580YD",
-"tlILtuLtKs","gf8rIuAWyp","uN6r33otm6","tlILt1j5L8","LbRTHeuZA5","nFqikjtn0X","EOE1ozY1GY","WreyPYf2Ec","kB5nPGrDg7","tl72WOxWIH",
-"0KyfsGv3Fq","5Drn0IKxdL","tAOsrjiVBP","FPfSECIShG","uTacxhi5X7","faHirYOfrY","LbRTHdpe1v","OHaBzrz7Ut","No0QbyEfy9","DG4sThe9IA",
-"W3VFHtaOXK","9iGoThE1Ql","gdQsSHP433","J2mQifFDrJ","FGzgpe6e4z","NAFuwe6e4z","QYxC0djsrv","9iGoTC2Irc","Y1mC0b29RJ","CK5W7WDVWJ",
-"h1zcHbZLvS","hSSvQMK07Y","hE1QlKZamH","tAOsrQWxoT","AgJHQCK5W7","uPX7GF6PT2","QbxXcS77LH","LewvMmX2GE","Z4I1vhSSvQ","aL6AJgdQsS",
-"oQ87ra00b5","7lUXZni2v1","YOfrYNOHsz","qUJMdJXljW","brhlQOz8yZ","pv0i7dQ586","0h1b1tl72W","0Wr5yFcWrW","lm0pDEoToP","AkKTkv8yFN",
-"RkQkeOHaBz","5ZaEzRBhp0","m4bxUNAFuw","VNCPdMmsIo","JRJQBzFgtB","WreyP4dEz6","VIlwPFhtgl","CIShGfFDrJ","FPfSEqUJMd","48cHLPb1pa",
-"suY4x9GXkX","ECMvUWaim6","VBjhzmz8gx","jtn0XChuy3","0Wr5yQClRL","FVMxotaOXK","6q6L9VLTy6","uvf7Ahe9IA","zmLYDNxx9V","hSSvQHzZT8",
-"HfyNQMm8si","2ZHdkDz1R3","7fsYMWDVWJ","tAOsrpT8wu","o8UydJKWYR","FcWrWJ2mQi","tl72WRsQUq","lViBvMmKGJ","8hJdt0BmCy","8U2nUX6Pin",
-"zbIYYTCgPp","B3qemY1mC0","HzZT8G1RhS","VIlwP8cVD3","5NammpFrrl","QChxsWaWsv","ZzJHWWmadA","5Mg9rciuWz","ZJTXHd7vjM","aFFssjfREu",
-"LDk6f8xEKz","5Drn0pWiOs","7lUXZMmsIo","v1HlnSjskQ","RkQkeprNT6","Cp3mZwiHrZ","hUTw7RzaZA","Ul4a10MR5X","O3iyQOz8yZ","gjUTuLewvM",
-"s93MlOUYuF","lsQGoWaim6","tl72WguMb8","QssNCnFqik","WreyPsx5Gl","ECMvU4W0Tl","DQimpIKxdL","B3qembgJAz","zHF1qydG8U","WMiS3gtCA5",
-"QnJ1SjeskS","cL0aEVLTy6","lCMxyG1RhS","GrDg7NcICA","NcICAEoToP","zz4ZUuAWyp","rKDLJO3iyQ","7Ow5Cpv0i7","xReeccmXIX","gtCA5L7cGc",
-"Oz8yZ0ao3l","vkCHHtlILt","9eoRciB08l","lH1kt45cIH","a00b57X3uy","qaofNUmaEv","0ao3luAWyp","LbRTHzFgtB","Gv3FqydG8U","ZJTXHpv0i7",
-"OUqFM8TxD7","TwanoBCxeC","uAWypzFgtB","QClRLyofH3","7hyVvn1pmO","kB5nPyToGW","24ARFzmLYD","y94nwoVQp6","QssNCtuDyS","aez9yRBhp0",
-"uAWyp0h1b1","jSjS3ZuDtD","QWxoT8U2nU","hE1Ql2DREs","WMiS3zqH0W","hi5X7jiVBP","AIYUuChuy3","zY1GYOHaBz","aDGtSVjCZq","gdQsSVerEA",
-"Yh1hFhE1Ql","XyPZNWPmlx","W7cTsprNT6","RxrsmX6Pin","pFrrlUmaEv","HfyNQ9XyT9","X6PinGrDg7","v2eC3oQ87r","DLhzMogLgc","uoStwWaim6",
-"uAWypi3pyd","9rlg9DLhzM","29QAz5VZjS","AkKTkrhl0J","okgRiVBjhz","16lHcDcpWB","S2Dfum4bxU","jzUqRGv3Fq","i7WMQ9XyT9","WDVWJLewvM",
-"5drc6k85Ae","Uvlv4vkCHH","B3qemUmaEv","FwEJz7ku1p","RmDcrhE1Ql","kZANmv2eC3","MojnP0PktI","2hEEUuPX7G","aFFssoQ87r","StlDJMaJQs",
-"9rlg9zqH0W","iB08lru4UG","9iGoTI7p2a","n8pJ9cQOnv","JIqXiIjTwP","6q6L9VBjhz","0h1b1m4bxU","HlUbFaL6AJ","0YAGHCNHmv","nFqikMkgy8",
-"Y1mC0zY1GY","QnJ1S7Ow5C","yvOMI29QAz","bgJAzRACuj","pvgjSy94nw","rKDLJQ6hMC","0h1b1MojnP","5ZaEzHfyNQ","4dEz6Y1mC0","v8yFN9GXkX",
-"DcpWBbrhlQ","HfyNQazIWp","LewvMtvdkD","he9IAS2Dfu","suY4xFwEJz","ThjNnpv0i7","sqVrfVNCPd","StlDJEoToP","lViBvfFDrJ","6AFT0RkQke",
-"0MR5X1LB1L","pvgjSMK07Y","O3iyQAkKTk","aDGtSgjUTu","WPmlxguMb8","yToGWiwzGk","D6rByCp3mZ","v8yFNkB5nP","Rxrsm2DREs","uvf7ATCgPp",
-"b29RJFLsph","HlUbFuTacx","s7MxknlaBy","i7WMQZv7z0","S2Dfu7ku1p","2hEEUbgJAz","0PktIFPfSE","WmadAQClRL","y94nwCdyBV","n8pJ94W0Tl",
-"GXdoH8FmFH","Q6hMCe6e4z","lXFOBd85a9","TCgPpGXdoH","RzaZA8hJdt","OUYuFs93Ml","O3iyQnlaBy","nFqik5iGN5","uAWypkZANm","FLsphS2Dfu",
-"h1zcHwDajX","BbwgA4dEz6","hE1QlIBe8k","uupzk8RCUA","BbwgAJkzUn","Z4I1v8U2nU","bgJAzrz7Ut","fcJOyhYBCK","atef2vOqCE","hSSvQnnP8o",
-"POUYSl83Ud","OxWIHFcWrW","RkQkeP6bcg","8cVD3FnPFB","xciqpUvlv4","iB08lv1Hln","16lHc7fKYU","y94nw07n1c","pv0i716lHc","LDk6fKZamH",
-"mX2GEbrhlQ","29QAzG1RhS","8hJdt0YAGH","SjskQ2Nslm","JJs5muAWyp","NhXduHfyNQ","7ku1p9y4lw","LDk6fZhwG1","Ta8f66AFT0","Mm8siogLgc",
-"7Ow5CFcWrW","MezSWRACuj","K20wK5ZaEz","yluBxHzZT8","GSQwjyToGW","RpBQm2Nslm","Ta8f6WPmlx","QChxsfaHir","QnJ1ShUTw7","55rfB14FLR",
-"RACujydG8U","QworuRACuj","hi5X7MmsIo","lj07QcQOnv","UlU3MWmadA","HP433Rxrsm","G1RhSzz4ZU","7Ow5CLbRTH","NOHsz5Mg9r","kB5nPsx5Gl",
-"LewvMqUJMd","ru4UGs4786","1j5L8zHF1q","o8Uyd3otm6","ZzJHWJRJQB","XflUqStlDJ","dmoS77hyVv","ix74rlViBv","xciqpJRJQB","NOHszYf2Ec",
-"pT8wu7fKYU","iqv4ka00b5","8U2nUG1RhS","8hJdtYOfrY","pmeCdQYxC0","LbRTHWmadA","jzUqRrKDLJ","SbRYyFFDui","BpYhVECMvU","Yf2EcDLhzM",
-"5ZaEz6q6L9","K4GS8FGzgp","M6qcGru4UG","uoStwUvlv4","oGu6xMojnP","BCxeCXyPZN","uJScXlweGy","OUqFMQWxoT","VjCZqfaHir","9eoRcpv0i7",
-"QbxXcdhSuH","RACujThjNn","qaofNCdyBV","CK5W7MaJQs","gf8rIlkMUA","7lUXZECMvU","soy9tAgJHQ","Vprf2SbRYy","atef2FFDui","AIYUurKDLJ",
-"EOE1onFqik","IjTwP5iGN5","hUTw7NAFuw","d7vjMMmsIo","yvOMIkB5nP","bgJAzEdBKc","ogLgc2DREs","pmeCdK4GS8","YOfrY5Namm","lH1ktdpe1v",
-"zbIYYU3yw5","euZA5aez9y","dmoS7HfyNQ","MaJQsM6qcG","KZamHd7vjM","djsrvsoy9t","MK07YAXpwE","OxWIHRACuj","xciqpZ4I1v","SWfou5ZaEz",
-"GWqqXpAhR1","Ul4a1GXdoH","gf8rIuupzk","8cVD3LewvM","GrDg7EoToP","8xEKzfmIK1","07n1csx5Gl","8hJdt3otm6","8U2nUJ2mQi","GrDg7K20wK",
-"SjskQv1Hln","lCMxymX2GE","BCxeCtaOXK","Rxrsm0Wr5y","ZzJHWtuDyS","Dz1R3Y1mC0","ulk41Nxx9V","dmoS7JRJQB","pWiOsy94nw","lweGyUvlv4",
-"QnJ1SIn3NS","ReKEWXyPZN","ReKEWd7vjM","6AFT0DQimp","lj07QlXFOB","prNT6F6PT2","9eoRcYw2oU","618DiS77LH","AmdQdjeskS","jfREut98iW",
-"OUYuFYf2Ec","MezSWKr8ys","oQ87r45cIH","K4GS8ksJby","SbRYylCMxy","GXdoHIRh48","oQ87rBGaQY","0MR5XNOHsz","F6PT24W0Tl","ru4UGZUnqt",
-"Nxx9VuLtKs","OHaBzvkCHH","U3yw5HzZT8","UlU3MciuWz","gIYvEFxX9q","DQimpyluBx","ZhwG1G1RhS","0KyfsQworu","DcpWBKZamH","zQt6QBCxeC",
-"FnPFBC2Irc","YOfrYGSQwj","xciqphUTw7","gdQsSP6bcg","YOfrYydG8U","sqVrfn1pmO","gtCA5rhl0J","S2DfuuZPqg","6q6L9ru4UG","UmaEv0MR5X",
-"BpYhVG1RhS","dpe1vgIYvE","tAOsrMmsIo","7ku1pYf2Ec","s93MliwzGk","5Drn0AgJHQ","FnPFB8U2nU","0h1b1oGu6x","lH1ktksJby","n1pmOQYxC0",
-"HlUbFQbxXc","9rlg9HzZT8","8TxD7iKqhr","ciuWz1LB1L","ZuDtDZJTXH","In3NSLbRTH","SmGzvAXpwE","6q6L9pFrrl","4dEz6uZPqg","FGzgp3weIF",
-"Waim6HlUbF","dpe1vCNHmv","Z4I1vdhSuH","ciuWzHzZT8","XyPZNjzUqR","n8pJ9ciuWz","RxrsmuPX7G","JXljWsuY4x","1LB1LKsjRK","9rlg9QChxs",
-"mX2GEOHaBz","JkzUnMGlTF","bZLvSbZLvS","e6e4zfcwDa","QbxXcW3VFH","jS1ajZJTXH","o8UydHlUbF","KZamHpFrrl","7lUXZRmDcr","s4786atef2",
-"xReecqQxHP","fmIK12Nslm","i3pydjzUqR","gdQsS0Kyfs","No0Qbb29RJ","oGu6xSWfou","TwanoprNT6","okgRiPYBf4","uZPqggf8rI","guMb8d85a9",
-"2hEEUOxWIH","bZLvSlpF6W","aez9yFhtgl","uTacx5IhmG","dpe1v8FmFH","v8yFNUmaEv","fmIK1JJs5m","Zv7z0jzUqR","vOqCEy94nw","gdQsSvkCHH",
-"a00b52TRI7","lj07QuQIcz","QbxXc580YD","faHirRkQke","EOE1o5VZjS","Pb1pahSSvQ","9y4lw64s8N","Q6hMCcQOnv","618DihUTw7","9y4lw2ZHdk",
-"FjHXRRzaZA","ZuDtDQworu","KZamH7ku1p","i3pydhE1Ql","SjskQEOE1o","BbwgAMm8si","gjUTuhSSvQ","ZJTXHFxX9q","Q6LixPb1pa","WaWsvW7cTs",
-"FcWrWAIYUu","blLA9MmKGJ","POUYSRkQke","07n1cSmGzv","9XyT97fKYU","POUYStaOXK","1j5L8QClRL","v1Hlns4786","aFFssYOfrY","WreyPsuY4x",
-"RsQUq0MR5X","GrDg7okgRi","tjQxsLbRTH","soy9tSjskQ","FNYIMOUqFM","7Ow5CO3iyQ","h1zcHlsQGo","W7cTszFgtB","Gv3FqwiHrZ","VNCPds93Ml",
-"s7Mxk7ku1p","GXdoHC2Irc","2DREsfmIK1","JIqXiFwEJz","jzUqR5Mg9r","fcwDaWreyP","L7cGc0h1b1","iwzGkzz4ZU","16lHcKsjRK","qUJMdqUJMd",
-"CK5W7yvOMI","2NslmsuY4x","TXQ0ZpiJSk","BpYhVuTacx","bZLvSZJTXH","lpF6WVIlwP","lweGyuTacx","ZuDtD0Wr5y","TXQ0Z9y4lw","5Mg9rYOfrY",
-"l83UdtvdkD","KZamHVNCPd","s4786MGlTF","pvgjSPOUYS","9iGoTaez9y","45cIHgdQsS","RzaZAazIWp","vkCHHhi5X7","7hyVv9y4lw","ksJbyZJTXH",
-"Yf2Ec1LB1L","WreyPnlaBy","Yh1hFYf2Ec","djsrviB08l","2Yz7EM3zXL","azIWpBFkb8","Fhtgl2ZHdk","m4bxUQssNC","pv0i7HlUbF","5Mg9rVIlwP",
-"qaofNJXljW","x3LDerz7Ut","WmadAHlUbF","uvf7ACK5W7","DLhzMHRxd8","bgJAzLDk6f","5NammTwano","8cVD3HlUbF","pAhR1VNCPd","uJScX1j5L8",
-"cShY2xciqp","2NslmJ2mQi","9XyT90BmCy","5Mg9r0MR5X","5drc6WaWsv","suY4xqUJMd","Mm8sirz7Ut","BbwgARsQUq","fmIK1HzZT8","VBjhzpv0i7",
-"JXljWIn3NS","dhSuHatef2","ReKEWDLhzM","MojnPRxrsm","9XyT9JJs5m","C2IrcLDk6f","atef2W3VFH","JRJQBFcWrW","uupzkFPfSE","9GXkXCp3mZ",
-"QChxsI7p2a","dQ5862DREs","4QMc9M3zXL","J2mQiHlUbF","yvOMIHlUbF","5nmWvVprf2","qaofNfaHir","MmsIocShY2","nlaByKASQ8","Zv7z0J2mQi",
-"hE1Ql8hJdt","7Ow5C8cVD3","JKWYR5ZaEz","yToGWFVMxo","s93MlZhwG1","VIlwPiKqhr","d7vjMrKDLJ","s93MlBbwgA","piJSkdQ586","55rfBZhwG1",
-"ulk41gjUTu","QClRLFhtgl","TXQ0Z2Yz7E","0MR5XMGlTF","Y1mC0hE1Ql","vLsmSIRh48","aL6AJiwzGk","jtn0XvLsmS","tl72W1v5hH","dhSuHNcICA",
-"OUYuFCNHmv","Y1mC0qaofN","4dEz6S2Dfu","hE1QlP6bcg","45cIHaDGtS","MmKGJMK07Y","mz8gxAkKTk","Y1mC0xciqp","4dEz6AOgEe","CqqaDECMvU",
-"45cIHZuDtD","Fhtgl5IhmG","suY4xJIqXi","piJSkyToGW","0PktIKASQ8","CIShGWreyP","TCgPp0ao3l","fFDrJF6PT2","RBhp0FPfSE","S77LHs4786",
-"lj07QMojnP","8hJdtEdBKc","QYxC0JJs5m","VNCPdCNHmv","HzZT8DLhzM","ECMvUtlILt","5ZaEzxReec","QssNCtjQxs","hYBCKzQt6Q","DcpWBWPmlx",
-"lH1kt5ZaEz","b29RJhUTw7","sx5Gl2Nslm","BbwgAqaofN","0BmCyReKEW","tvdkDmX2GE","FxX9qVLTy6","DcpWB4dEz6","FxX9qFcWrW","8FmFHbZLvS",
-"JRJQBQssNC","oVQp6HlUbF","4W0Tl16lHc","5drc6zHF1q","TwanozbIYY","3weIFfcJOy","Qworu2DREs","wDajXMkgy8","WPmlxHzZT8","AgJHQDcpWB",
-"DLhzMo8Uyd","C2Irc5VZjS","5IhmGCxVEf","5drc6SbRYy","7hyVvVprf2","ZzJHWqaofN","tl72Wm4bxU","29QAzVjCZq","2TRI7pmeCd","guMb8FVMxo",
-"8xEKzSWfou","zmLYDMK07Y","PYBf4dpe1v","zmLYDSmGzv","Vprf2e6e4z","MmKGJtaOXK","he9IANOHsz","VNCPdqaofN","GWqqXSmGzv","RkQkeFFDui",
-"xReecHfyNQ","Yh1hFHP433","uoStwEoToP","a00b5mz8gx","J2mQiMmsIo","JIqXifmIK1","BGaQYlCMxy","9y4lwK20wK","CIShG8RCUA","yToGW16lHc",
-"azIWpOxWIH","8TxD7618Di","fLNg8lCMxy","Gv3FqSjskQ","uupzktuDyS","ru4UGAmdQd","OxWIH6AFT0","HRxd8No0Qb","7hyVvlViBv","OUqFMVerEA",
-"RpBQm4W0Tl","tvdkDW3VFH","ZuDtDAOgEe","TXQ0ZBFkb8","wiHrZ8xEKz","5NammyluBx","NcICAMm8si","ThjNnJ2mQi","CK5W7t98iW","2hEEUiB08l",
-"AXpwE4QMc9","pv0i7iqv4k","JJs5mYjB9t","fmIK1KZamH","K4GS8k85Ae","cL0aEF6PT2","vLsmSRkQke","MezSW2ZHdk","RmDcrgtCA5","CK5W79eoRc",
-"BpYhVmX2GE","HlUbFcShY2","atef20Wr5y","cmXIXuAWyp","yofH3XflUq","KsjRK5iGN5","5ZaEzjfREu","RkQkeHlUbF","WMiS3Mm8si","UlU3Mh1zcH",
-"QYxC0v1Hln","FxX9qM6qcG","8hJdtjeskS","5NammTa8f6","FjHXRNOHsz","5Mg9rBbwgA","TwanosuY4x","ThjNnni2v1","ZhwG1gf8rI","iKqhrydG8U",
-"m4bxUHP433","ZuDtDlweGy","zmLYDlweGy","580YD24ARF","NcICAcL0aE","RACujogLgc","7fKYUzz4ZU","0MR5XuQIcz","ksJbyI7p2a","pv0i7FNYIM",
-"24ARFciuWz","ThjNnC2Irc","piJSkn1pmO","uN6r37lUXZ","EOE1oFGzgp","Kr8ysgf8rI","oGu6xLewvM","v2eC35VZjS","lweGyDG4sT","7ku1pIn3NS",
-"MK07Ysoy9t","G1RhSatef2","nlaByoVQp6","Nxx9VQChxs","HlUbFyvOMI","9XyT9uZPqg","zz4ZUzqH0W","tl72WpFrrl","ThjNnh1zcH","FLsphdQ586",
-"hYBCKTCgPp","ru4UGSWfou","CdyBVAkKTk","7fsYMk85Ae","OxWIHv1Hln","7lUXZSWfou","ECMvUQChxs","ru4UGJJs5m","Y1mC0gtCA5","NAFuwD6rBy",
-"aFFssksJby","2DREsEOE1o","VjCZqy94nw","Mm8siix74r","Kr8ysfLNg8","rKDLJC2Irc","fqypyQ6hMC","W7cTsAXpwE","Oz8yZuLtKs","IjTwPBFkb8",
-"UmaEvix74r","0Wr5ymz8gx","cShY2X6Pin","uTacxIn3NS","7ku1p55rfB","VLTy60PktI","K20wKXyPZN","8cVD3hE1Ql","M3zXLa00b5","pFrrlKASQ8",
-"No0QbVprf2","uLtKs7ku1p","tlILt2TRI7","hi5X7mz8gx","yEfy9SWfou","uoStw48cHL","4W0Tl5nmWv","16lHc0YAGH","9rlg9vkCHH","ni2v1NcICA",
-"8FmFHQnJ1S","0Wr5yRsQUq","CIShGyofH3","8hJdtVIlwP","gf8rI4W0Tl","S77LHQ6hMC","DQimpZzJHW","FPfSE9GXkX","FxX9qJRJQB","BFkb80MR5X",
-"pmeCdBbwgA","9GXkXFLsph","qaofN0BmCy","jeskSCK5W7","IjTwPW3VFH","0h1b1VIlwP","tlILtGv3Fq","wiHrZCp3mZ","lH1ktPb1pa","ogLgcVNCPd",
-"NcICACNHmv","okgRiuZPqg","hYBCKpAhR1","7fsYMJIqXi","Yh1hF580YD","7fsYMgf8rI","2DREsdQ586","MmsIoEOE1o","B3qem2DREs","07n1cEdBKc",
-"i3pydMmKGJ","7fKYU9iGoT","NAFuwtl72W","XyPZNi7WMQ","xXTI4s7Mxk","Zv7z0t59lR","MaJQsOHaBz","YOfrY0Wr5y","ulk41DQimp","Q6Lix2hEEU",
-"WMiS3sx5Gl","FjHXRMGlTF","hUTw7zmLYD","sx5Gl0h1b1","OxWIHaDGtS","tjQxsi7WMQ","hYBCKAgJHQ","azIWp7X3uy","580YDYjB9t","M3zXLMGlTF",
-"5ZaEzix74r","StlDJv1Hln","fFDrJTCgPp","uQIczMaJQs","IRh48L7cGc","48cHLBFkb8","v2eC3RsQUq","JRJQBv8yFN","AmdQdIBe8k","djsrvWPmlx",
-"yvOMIrKDLJ","G1RhScQOnv","RACujhSSvQ","yluBxYOfrY","taOXKThjNn","rhl0JaFFss","618DiFxX9q","Ss0ZuStlDJ","CK5W7GXdoH","5drc6yluBx",
-"zFgtBIn3NS","JKWYRuLtKs","VLTy6UlU3M","CNHmvuupzk","QbxXcvOqCE","fqypyYOfrY","0MR5X2ZHdk","JkzUnQ6hMC","a00b5O3iyQ","CxVEf7ku1p",
-"okgRiTXQ0Z","GXdoHQ6hMC","FPfSENOHsz","Kr8yslCMxy","5ZaEzcShY2","8TxD7FcWrW","RxrsmQssNC","S2Dfu5drc6","t98iWfcwDa","FhtglJXljW",
-"P6bcgZuDtD","JIqXiJXljW","fcJOyJXljW","nlaBy3otm6","8TxD7suY4x","DcpWBydG8U","WaWsvb29RJ","OHaBzJJs5m","fFDrJfFDrJ","zQt6Q9rlg9",
-"ni2v1aez9y","RBhp029QAz","NcICARBhp0","Z4I1vuAWyp","SmGzvuN6r3","FcWrWd85a9","Cfgr3taOXK","QClRLa00b5","jzUqRIRh48","8cVD3MezSW",
-"n1pmOb29RJ","580YDFwEJz","jS1ajAgJHQ","2Nslm9rlg9","fcJOyzbIYY","yluBx9eoRc","8U2nUzFgtB","VBjhzMezSW","rKDLJIn3NS","guMb8oGu6x",
-"CIShGYOfrY","zQt6Qhe9IA","MojnPn8pJ9","fcwDaFxX9q","lViBvBbwgA","MmKGJyvOMI","blLA94W0Tl","NOHszpv0i7","0Wr5yX6Pin","h1zcHtl72W",
-"rz7UtfaHir","bZLvStAOsr","suY4x8cVD3","Q6hMClXFOB","atef2Ul4a1","tAOsrsqVrf","v2eC35Namm","7hyVvxXTI4","2DREsru4UG","VBjhz29QAz",
-"5Drn0BCxeC","xReec8hJdt","yofH3xReec","y94nwqUJMd","mX2GEFnPFB","WPmlxv8yFN","zQt6QrKDLJ","ThjNnQ6Lix","FNYIMZUnqt","pFrrl55rfB",
-"Yh1hFVprf2","aL6AJVjCZq","D6rByIRh48","FFDuifmIK1","BbwgAFPfSE","tAOsrd7vjM","9XyT9QbxXc","5ZaEzuJScX","CNHmvXyPZN","EOE1ocShY2",
-"dmoS7s7Mxk","AOgEeY1mC0","s7Mxk4W0Tl","Waim6soy9t","0Wr5yBFkb8","QbxXcPYBf4","cShY2M3zXL","SWfouSs0Zu","s7MxkBpYhV","WPmlxnlaBy",
-"JkzUnVBjhz","vLsmSSWfou","OUqFMNcICA","VerEAguMb8","5iGN5DLhzM","v8yFNZzJHW","JRJQB1j5L8","jfREuiqv4k","W3VFHjiVBP","9iGoTnFqik",
-"fcwDaAgJHQ","fcwDaK4GS8","WmadACxVEf","BCxeCAmdQd","ciuWzVBjhz","l83Uds4786","aL6AJ45cIH","9eoRc2hEEU","aez9y29QAz","GSQwjydG8U",
-"iB08l4dEz6","dpe1vJRJQB","HfyNQlsQGo","C2Ircrz7Ut","oVQp6azIWp","CNHmv64s8N","oQ87rNcICA","7fKYUyofH3","jS1ajnlaBy","QworuG1RhS",
-"AOgEeiB08l","MaJQs1v5hH","9XyT9rhl0J","brhlQ2Nslm","vkCHHqUJMd","sx5GlwiHrZ","ogLgcvOqCE","piJSkfmIK1","ZhwG1yvOMI","VNCPdHRxd8",
-"55rfBD6rBy","HzZT8Vprf2","jfREuNhXdu","zFgtBAIYUu","MezSWO3iyQ","HP433FVMxo","GWqqXtvdkD","brhlQMojnP","hYBCKpT8wu","MojnPhE1Ql",
-"7ku1pprNT6","jS1aj6q6L9","IjTwPGXdoH","Pb1pa8FmFH","WaWsv8U2nU","PYBf4FnPFB","5Drn0DQimp","KASQ8BCxeC","ru4UGFcWrW","8TxD7tl72W",
-"QworuIRh48","0KyfsWDVWJ","ZJTXHhi5X7","yvOMIfcJOy","d7vjMfLNg8","Gv3FqpAhR1","WMiS3hE1Ql","IBe8kyEfy9","atef2jS1aj","24ARFHlUbF",
-"JXljWpiJSk","aDGtS8U2nU","1j5L8lXFOB","VLTy6rKDLJ","NhXduZzJHW","WreyPRmDcr","0Wr5yStlDJ","brhlQgf8rI","BFkb8aL6AJ","HRxd8l83Ud",
-"fqypyWaim6","WaWsvuoStw","qQxHPWPmlx","RBhp0WDVWJ","uPX7GPOUYS","mz8gxZ4I1v","fmIK1JXljW","1j5L8HP433","pvgjSxXTI4","fcwDa9GXkX",
-"2DREsh1zcH","xReecbZLvS","XyPZNEoToP","HRxd8FNYIM","MojnPtjQxs","J2mQiO3iyQ","FcWrWdhSuH","oVQp6uoStw","FNYIMCK5W7","29QAz0Wr5y",
-"2hEEUrhl0J","HfyNQqaofN","n1pmOuQIcz","TXQ0ZblLA9","tl72WuZPqg","oVQp6UlU3M","VerEAZzJHW","BGaQYgf8rI","euZA5DG4sT","Chuy3Chuy3",
-"i7WMQqQxHP","ZhwG1cShY2","HzZT8FnPFB","CdyBVVNCPd","9iGoT7fKYU","yEfy964s8N","OxWIHHP433","KsjRKRpBQm","RzaZABbwgA","sqVrf29QAz",
-"BFkb8guMb8","aez9yt98iW","uAWypuupzk","GXdoH1v5hH","5drc6Vprf2","0PktINxx9V","nnP8oiB08l","YjB9tRzaZA","d85a9AIYUu","8FmFHW3VFH",
-"LbRTHWDVWJ","MK07YzmLYD","AIYUupAhR1","gIYvExXTI4","HP433CxVEf","pmeCdQ6hMC","UlU3MksJby","3otm6RBhp0","mz8gxaez9y","tlILtWaim6",
-"zz4ZUyofH3","VNCPdIRh48","y94nwChuy3","WDVWJzFgtB","QworuVBjhz","jtn0Xhi5X7","ulk415VZjS","GWqqXMaJQs","14FLRHfyNQ","FVMxoUmaEv",
-"IRh480YAGH","AgJHQBpYhV","b29RJUl4a1","BpYhVQWxoT","a00b5dhSuH","gtCA5d7vjM","FcWrW07n1c","uN6r3TCgPp","7fKYUnlaBy","5ZaEzJRJQB",
-"ciuWzydG8U","iKqhr5drc6","SjskQWmadA","1LB1LhSSvQ","7lUXZprNT6","aL6AJlsQGo","vOqCEtaOXK","Cfgr37X3uy","v1HlnLewvM","mz8gxO3iyQ",
-"WreyPNhXdu","fqypyMkgy8","2hEEUpv0i7","5Drn0lXFOB","M6qcGgIYvE","pWiOsBGaQY","FwEJztAOsr","CqqaDqQxHP","MmKGJF6PT2","i3pydix74r",
-"lj07QtjQxs","hSSvQTwano","ReKEWFjHXR","Waim69iGoT","MmKGJMkgy8","aL6AJBGaQY","UlU3MS2Dfu","7ku1p580YD","RkQkexReec","9GXkXPOUYS",
-"brhlQzmLYD","2ZHdkY1mC0","QworuBFkb8","Nxx9VoVQp6","xReec4W0Tl","8cVD3IKxdL","a00b5fLNg8","h1zcHFVMxo","t98iW8RCUA","uLtKsVerEA",
-"cQOnv8RCUA","Ss0Zu7X3uy","F6PT20YAGH","Gv3FqeuZA5","BCxeC55rfB","CK5W7PYBf4","4W0Tl5IhmG","Y1mC00h1b1","QClRLtjQxs","1LB1LoQ87r",
-"xciqp5drc6","ni2v1vkCHH","9y4lwMkgy8","yToGWDcpWB","0MR5XlXFOB","Nxx9V8hJdt","5ZaEzlkMUA","n1pmOUl4a1","O3iyQHlUbF","l83UdpWiOs",
-"9rlg9xXTI4","wiHrZLDk6f","s7MxkgIYvE","0YAGHhE1Ql","RkQkeJRJQB","3weIFh1zcH","UmaEvjfREu","LDk6fuLtKs","Mm8siY1mC0","gtCA5lXFOB",
-"YOfrYhE1Ql","ulk41S77LH","64s8NFxX9q","pmeCd8cVD3","NOHszFPfSE","FnPFBatef2","VerEA6AFT0","7Ow5CQChxs","0Kyfsi3pyd","lViBvMmsIo",
-"cShY28U2nU","2ZHdk2TRI7","W3VFHzQt6Q","M6qcGChuy3","P6bcghYBCK","Ta8f6mz8gx","64s8NzQt6Q","m4bxUOxWIH","48cHLUl4a1","ThjNn3otm6",
-"e6e4zx3LDe","yluBxpvgjS","RxrsmRmDcr","6AFT0pT8wu","VerEAF6PT2","soy9tgjUTu","m4bxUrKDLJ","VIlwPcQOnv","VerEAX6Pin","GSQwjQ6Lix",
-"EOE1ohYBCK","IRh48tuDyS","uoStwCp3mZ","4QMc9W7cTs","SWfouYOfrY","IBe8kQChxs","gf8rI1v5hH","pWiOsThjNn","iKqhri3pyd","v2eC3lsQGo",
-"8U2nUUl4a1","piJSk1j5L8","9GXkXZzJHW","lweGyU3yw5","pWiOssqVrf","Mm8siydG8U","h1zcHGXdoH","G1RhSdjsrv","S77LHNcICA","Kr8ysCdyBV",
-"piJSkzHF1q","prNT6GSQwj","4W0TlGv3Fq","64s8NEOE1o","lm0pD7Ow5C","Q6LixtlILt","PYBf4Waim6","suY4xQYxC0","YjB9tlpF6W","24ARFQClRL",
-"djsrvuvf7A","FjHXRFVMxo","W3VFHbZLvS","BbwgAQWxoT","CK5W7AmdQd","aDGtSThjNn","DLhzMwDajX","okgRiWreyP","HzZT8atef2","wiHrZmX2GE",
-"tjQxsblLA9","NAFuwlkMUA","CxVEfl83Ud","blLA9K20wK","CK5W75drc6","gIYvElViBv","Rxrsm8U2nU","dQ586RACuj","JIqXiGWqqX","yvOMIt98iW",
-"VerEAlweGy","iqv4kStlDJ","Pb1paEdBKc","ciuWzAgJHQ","bgJAzgIYvE","pv0i7cShY2","cShY2UmaEv","Pb1paRmDcr","YjB9tWreyP","aez9ypvgjS",
-"2Yz7EciuWz","ydG8UOUqFM","MezSWfqypy","2DREsFGzgp","Pb1pasx5Gl","jfREuRBhp0","DLhzMRACuj","MmKGJRzaZA","prNT65Namm","HzZT8jzUqR",
-"s93MlzQt6Q","VjCZqpvgjS","Chuy3b29RJ","prNT6M6qcG","NAFuwjeskS","PYBf4pvgjS","atef2In3NS","WDVWJcQOnv","dmoS7pmeCd","oVQp6Kr8ys",
-"Ss0ZujS1aj","d85a9Qworu","QClRLMK07Y","AgJHQWMiS3","DLhzMtAOsr","qaofNQbxXc","TwanoY1mC0","QworuBGaQY","hSSvQWMiS3","s7Mxk6AFT0",
-"Q6hMC4QMc9","QWxoT55rfB","AmdQdIKxdL","oGu6xDG4sT","Vprf2Rxrsm","S77LHZzJHW","WreyPuAWyp","jSjS3FVMxo","e6e4ziKqhr","VLTy6piJSk",
-"fcJOyuLtKs","fLNg80h1b1","ThjNnRmDcr","BpYhVMkgy8","9iGoTcmXIX","DcpWBIRh48","a00b5lCMxy","pFrrlGSQwj","Ul4a1yEfy9","Yf2EcQWxoT",
-"DQimpUvlv4","hi5X7WMiS3","SmGzvazIWp","Q6LixfcJOy","gIYvED6rBy","7lUXZzbIYY","AmdQdCIShG","RmDcrW7cTs","I7p2a1j5L8","bZLvSFLsph",
-"yToGW9GXkX","0Wr5y6AFT0","xXTI4uJScX","O3iyQdQ586","D6rBy0ao3l","suY4x8TxD7","B3qem7fKYU","7fKYUWPmlx","Yw2oURxrsm","W3VFH7X3uy",
-"zbIYYB3qem","1v5hHciuWz","SWfoupWiOs","8TxD7LewvM","BGaQYDz1R3","K20wKlkMUA","lCMxyLewvM","IKxdLzqH0W","cL0aEWDVWJ","x3LDe7fKYU",
-"UlU3M7ku1p","29QAzblLA9","RBhp0PYBf4","618DiFnPFB","JXljW9y4lw","5ZaEzsoy9t","n1pmO9eoRc","Z4I1vnnP8o","blLA9fcJOy","FwEJzFVMxo",
-"MaJQszqH0W","tuDySuTacx","t59lRoVQp6","oVQp6ZzJHW","bZLvSs4786","b29RJsoy9t","tl72WvOqCE","PYBf40PktI","JKWYRgjUTu","JkzUnJRJQB",
-"aFFssFwEJz","hUTw7yluBx","1v5hHzz4ZU","Ss0Zu2Nslm","5IhmG9iGoT","C2IrczHF1q","dQ586NOHsz","zz4ZUYf2Ec","0MR5XUmaEv","ZJTXHzY1GY",
-"AkKTkFFDui","Ss0ZuBFkb8","ogLgcYw2oU","JXljWuvf7A","BCxeCAIYUu","aFFssbZLvS","uLtKsMm8si","oVQp6VjCZq","jSjS345cIH","iqv4k0ao3l",
-"CdyBVCNHmv","3weIF8FmFH","4W0TlpT8wu","cShY2CxVEf","5Mg9rMGlTF","soy9tcQOnv","8TxD7Mm8si","U3yw5yofH3","PYBf4O3iyQ","uLtKsaL6AJ",
-"6q6L9vLsmS","cL0aEqUJMd","zY1GY5IhmG","Q6hMCAkKTk","2ZHdkG1RhS","VjCZquupzk","jzUqRlsQGo","UmaEvuAWyp","Ta8f6TXQ0Z","lH1kt8TxD7",
-"n1pmOBFkb8","vkCHHCp3mZ","jfREuksJby","VLTy6JXljW","1j5L8jiVBP","y94nwv1Hln","qUJMdRzaZA","7ku1pOUYuF","2DREsRmDcr","24ARF5Mg9r",
-"uN6r3JIqXi","zbIYYBGaQY","zz4ZUpmeCd","AXpwENcICA","QYxC0ZJTXH","ZhwG1tjQxs","hUTw7pv0i7","Mkgy8lXFOB","yluBxmz8gx","Chuy3K20wK",
-"55rfBgtCA5","0PktIt98iW","aDGtSpAhR1","tjQxsIn3NS","hE1QlkZANm","fmIK10MR5X","zQt6QMmKGJ","azIWpNAFuw","29QAzoQ87r","gtCA5RzaZA",
-"StlDJIRh48","soy9trhl0J","jS1ajLDk6f","MezSWQssNC","l83UdOUYuF","jeskSaez9y","tjQxstuDyS","uJScXtl72W","lCMxyQssNC","5Mg9rZJTXH",
-"Q6LixzFgtB","s93MllH1kt","I7p2aEdBKc","piJSkStlDJ","nlaBylj07Q","vLsmSNo0Qb","pFrrlDcpWB","O3iyQazIWp","WDVWJzz4ZU","K20wKWDVWJ",
-"jfREuNcICA","BCxeCMmsIo","HP433K20wK","AmdQdFhtgl","0ao3lAgJHQ","dmoS7uN6r3","HRxd8Vprf2","tAOsrdpe1v","FGzgpMezSW","5Namm2ZHdk",
-"7Ow5C5drc6","4QMc9cQOnv","HP433WaWsv","vOqCEsuY4x","JXljWt98iW","uAWypsqVrf","uZPqgBCxeC","IjTwP0ao3l","BGaQYzbIYY","7ku1pbgJAz",
-"DG4sTksJby","uoStwKr8ys","oVQp6FNYIM","tuDySQChxs","pT8wujzUqR","7fKYUuAWyp","07n1cokgRi","zqH0WAIYUu","Fhtgl5drc6","xReecpWiOs",
-"zFgtB0ao3l","iwzGke6e4z","hi5X7bgJAz","lj07QKASQ8","qQxHPGrDg7","8U2nULDk6f","y94nwjtn0X","pv0i7XflUq","FFDuirz7Ut","pmeCdFVMxo",
-"zFgtBlsQGo","Pb1paZhwG1","gIYvEciuWz","hUTw7HlUbF","ulk41nFqik","cShY2uvf7A","QWxoTRBhp0","SbRYy8xEKz","uAWypAmdQd","IKxdLRpBQm",
-"7fKYUZ4I1v","FFDuiuJScX","ru4UGOxWIH","2Yz7EfaHir","HlUbFpFrrl","FFDui5VZjS","kB5nPzFgtB","EdBKcMkgy8","Qworu0BmCy","DLhzMjS1aj",
-"lViBvJXljW","Vprf2GrDg7","gtCA5Zv7z0","Nxx9VHRxd8","Cfgr3Yf2Ec","MmKGJi3pyd","s4786ZhwG1","BFkb8mz8gx","4QMc9fqypy","2DREsQYxC0",
-"8xEKzrz7Ut","pv0i7ZJTXH","MezSWDLhzM","JkzUn7Ow5C","RsQUqBbwgA","Ss0ZuCdyBV","JXljWs4786","Zv7z0S77LH","zbIYYxReec","1LB1LazIWp",
-"sx5Gl9XyT9","fLNg8AIYUu","2Yz7E3weIF","pv0i70Wr5y","IKxdLDcpWB","9iGoT7hyVv","gjUTuFPfSE","tl72WYf2Ec","euZA55Mg9r","I7p2aOxWIH",
-"5Mg9rxciqp","Rxrsmd7vjM","e6e4zFNYIM","K4GS8I7p2a","s93MlvOqCE","RBhp0S77LH","LDk6fFhtgl","Ta8f6uoStw","FwEJzMm8si","kB5nPPYBf4",
-"0Wr5ylsQGo","Yh1hF2TRI7","HRxd8Rxrsm","okgRilpF6W","fLNg81j5L8","fcJOyECMvU","uAWypD6rBy","K4GS8Rxrsm","VNCPd0BmCy","C2IrcAIYUu",
-"OxWIHPYBf4","M6qcGcQOnv","euZA5lweGy","B3qemZ4I1v","kB5nPL7cGc","gIYvE1v5hH","jzUqRmz8gx","9XyT97lUXZ","DG4sTMmKGJ","ECMvUd85a9",
-"ECMvUEOE1o","aFFss3weIF","KsjRKzqH0W","fcwDaCfgr3","prNT6s7Mxk","QWxoT5iGN5","S77LHWDVWJ","W7cTseuZA5","tl72WJJs5m","zbIYYS2Dfu",
-"pFrrlzY1GY","jiVBP5nmWv","jSjS3JkzUn","lj07Qni2v1","fqypy9XyT9","OUYuFpT8wu","lweGyAOgEe","taOXKmX2GE","64s8NBFkb8","LDk6fMojnP",
-"9GXkXAOgEe","1j5L8ZuDtD","L7cGcF6PT2","B3qem0BmCy","3weIFLewvM","brhlQpFrrl","DQimp1v5hH","Mm8siVjCZq","ksJby7lUXZ","yluBxQbxXc",
-"M6qcGMaJQs","0BmCy8cVD3","JRJQB9y4lw","FFDuiaDGtS","qQxHPvLsmS","piJSklXFOB","BCxeCa00b5","RxrsmbZLvS","9rlg90MR5X","5nmWvFLsph",
-"uZPqg7hyVv","lsQGovOqCE","9y4lwAmdQd","vLsmSiqv4k","FcWrWvkCHH","8hJdtmz8gx","RzaZA8xEKz","NhXduQworu","VerEAM6qcG","W7cTsksJby",
-"zFgtBL7cGc","Zv7z0F6PT2","gjUTuD6rBy","2TRI7ni2v1","8hJdtpiJSk","5IhmGiqv4k","piJSkQworu","soy9tFnPFB","1LB1L7fKYU","BCxeCxciqp",
-"dpe1vuQIcz","aez9yBFkb8","o8UydlsQGo","jtn0X8xEKz","RACujFGzgp","rz7UtguMb8","FnPFBtAOsr","0ao3ltuDyS","W7cTsI7p2a","VjCZqni2v1",
-"5ZaEzTwano","m4bxUMojnP","Ul4a18FmFH","2Yz7E9eoRc","jS1ajvOqCE","FjHXRNAFuw","VNCPdblLA9","pT8wuCp3mZ","Yh1hFYw2oU","uQIczvLsmS",
-"IRh48MezSW","uN6r3h1zcH","2DREsJXljW","M6qcG8xEKz","zY1GYRsQUq","Cp3mZ9GXkX","nFqikd85a9","WreyPhi5X7","zHF1qChuy3","QYxC0QWxoT",
-"UlU3MCfgr3","NhXducShY2","cShY2Y1mC0","OUYuFjS1aj","aDGtSDLhzM","i3pydfmIK1","2DREsOz8yZ","Uvlv4zz4ZU","0Wr5yaL6AJ","0ao3lrz7Ut",
-"DcpWBFGzgp","hSSvQ0ao3l","Mm8sipiJSk","580YD64s8N","cL0aEokgRi","AmdQdaDGtS","D6rByBCxeC","o8UydAXpwE","0h1b1Zv7z0","8cVD3pv0i7",
-"lXFOBLewvM","NAFuwU3yw5","5nmWvMmsIo","DcpWBoGu6x","iKqhrEoToP","Kr8ysAkKTk","9iGoTECMvU","lCMxyHP433","k85Aey94nw","lH1ktBCxeC",
-"YjB9t9XyT9","FnPFB4QMc9","okgRizqH0W","QssNCs93Ml","UmaEvydG8U","yToGWFLsph","v1Hlnd85a9","he9IAtjQxs","tAOsr24ARF","rhl0JNOHsz",
-"gIYvESmGzv","DcpWB5VZjS","StlDJ7X3uy","rKDLJ8FmFH","16lHcThjNn","dhSuHW3VFH","55rfBpmeCd","JkzUn5iGN5","bZLvSm4bxU","C2Irc24ARF",
-"MaJQs6AFT0","NAFuwRACuj","1LB1LFxX9q","0MR5Xgf8rI","1LB1LaFFss","4QMc9Q6hMC","MmsIotjQxs","aDGtSgtCA5","7Ow5CEdBKc","NhXduogLgc",
-"zbIYYi3pyd","s7Mxk64s8N","M6qcGtuDyS","0BmCyHP433","6q6L9Twano","Ta8f6x3LDe","1v5hHazIWp","tvdkDCdyBV","XyPZNaDGtS","FxX9qGWqqX",
-"FLsphDG4sT","5iGN5TCgPp","mz8gxgIYvE","5IhmGY1mC0","iKqhrQChxs","kZANm5IhmG","jfREu16lHc","Yh1hFAIYUu","CxVEfQbxXc","xciqpNAFuw",
-"ksJbyKsjRK","0YAGHDG4sT","jeskSO3iyQ","uoStwAIYUu","64s8N5Namm","aL6AJ0Wr5y","MmsIo1v5hH","16lHcFcWrW","m4bxUGrDg7","9XyT9FnPFB",
-"9iGoT618Di","1LB1LcQOnv","zz4ZUy94nw","GWqqXuPX7G","DcpWBTCgPp","Oz8yZCqqaD","e6e4z9iGoT","okgRiRkQke","zqH0WAmdQd","8U2nUpWiOs",
-"ciuWzoGu6x","EdBKcQYxC0","wiHrZReKEW","oGu6xaDGtS","zbIYYi7WMQ","azIWplXFOB","6AFT0SWfou","gdQsSazIWp","FFDuiuTacx","lXFOBqQxHP",
-"CxVEfix74r","2TRI71v5hH","uJScX7lUXZ","AOgEe0Wr5y","16lHc2ZHdk","x3LDelkMUA","zY1GY45cIH","o8UydQYxC0","lkMUAPOUYS","v1HlnyluBx",
-"WaWsvL7cGc","7fKYUlsQGo","dpe1vFFDui","MGlTFIBe8k","2TRI7MmsIo","oVQp6Ss0Zu","TCgPpzHF1q","MmsIoBpYhV","RsQUqVjCZq","oQ87rPYBf4",
-"48cHLgtCA5","0ao3lhE1Ql","RxrsmHRxd8","ydG8UhUTw7","dQ586Mm8si","cmXIXvOqCE","ZUnqtiKqhr","ulk41Rxrsm","m4bxU2ZHdk","VIlwPHlUbF",
-"pT8wuFLsph","lpF6WyofH3","HlUbFWaWsv","fcJOyWaWsv","gdQsSNhXdu","MK07YxXTI4","2ZHdkStlDJ","cmXIXQ6hMC","In3NSZuDtD","v8yFN9y4lw",
-"M3zXLQ6Lix","0MR5XHP433","tlILt4dEz6","tlILtMojnP","zbIYYzbIYY","atef2fcwDa","LbRTHQClRL","mz8gxMaJQs","Q6hMCFcWrW","lweGyDLhzM",
-"580YDuvf7A","CdyBV5nmWv","vOqCEO3iyQ","1j5L8In3NS","GSQwj7Ow5C","FFDuiMmsIo","SbRYyOz8yZ","cQOnvSjskQ","lpF6WprNT6","okgRi8FmFH",
-"ix74rwiHrZ","AkKTk7X3uy","t98iW9iGoT","h1zcHU3yw5","i7WMQKZamH","tAOsrtuDyS","QClRLDLhzM","zz4ZURpBQm","t59lRDQimp","wDajXwDajX",
-"QnJ1SFVMxo","AgJHQv8yFN","guMb8SbRYy","cQOnvBbwgA","zz4ZUbrhlQ","uPX7GfFDrJ","lViBvdQ586","ru4UGMK07Y","jfREuFcWrW","pFrrlQYxC0",
-"K20wKkZANm","FGzgpBGaQY","14FLRSmGzv","8xEKz7lUXZ","S2Dfu7fKYU","Ta8f6Mkgy8","2hEEUFnPFB","2DREsDG4sT","rz7UtpAhR1","YjB9tQClRL",
-"cQOnvcShY2","FNYIMcL0aE","euZA5Cp3mZ","9rlg9gtCA5","2DREsYjB9t","ru4UG7Ow5C","MmKGJIBe8k","t98iWix74r","suY4xqaofN","jfREu29QAz",
-"6AFT0jzUqR","Chuy3WPmlx","In3NSl83Ud","y94nwRBhp0","S2Dfu7X3uy","tjQxssoy9t","DcpWBRkQke","tjQxsNcICA","FLsphTXQ0Z","x3LDeUlU3M",
-"VerEAlH1kt","s93MlFGzgp","VjCZqs4786","2DREsP6bcg","8hJdtblLA9","Pb1paiqv4k","blLA9Nxx9V","Q6hMCZ4I1v","I7p2aCxVEf","tlILtJkzUn",
-"rhl0JFFDui","FGzgp3otm6","C2Irc5Drn0","BGaQYrhl0J","580YDtjQxs","uLtKsHP433","Ss0ZuQ6Lix","tl72WKr8ys","rKDLJzbIYY","ZhwG1lkMUA",
-"nnP8oJIqXi","n1pmOi3pyd","d7vjMZhwG1","B3qemxReec","FNYIMSs0Zu","EdBKc0MR5X","fcJOyWMiS3","pv0i7jeskS","K4GS8Ul4a1","lm0pDVNCPd",
-"iwzGkWaWsv","Waim6W7cTs","gdQsShi5X7","9eoRchYBCK","KZamH5VZjS","Q6Lix0BmCy","VNCPd5nmWv","t59lRl83Ud","bgJAzni2v1","0YAGHjfREu",
-"VBjhztuDyS","s4786Oz8yZ","TXQ0ZAkKTk","tuDySBGaQY","uPX7GuN6r3","29QAzDQimp","aL6AJs7Mxk","QworuKZamH","FNYIMpT8wu","pmeCddjsrv",
-"8cVD38xEKz","MojnPatef2","U3yw5fFDrJ","x3LDeCfgr3","U3yw5iqv4k","gdQsS0Wr5y","yofH3aDGtS","M3zXLJRJQB","AXpwESWfou","MmKGJJJs5m",
-"v2eC3FjHXR","b29RJrhl0J","pWiOsgIYvE","HRxd8WDVWJ","uZPqgHlUbF","NAFuwMm8si","FFDuil83Ud","ZzJHWRsQUq","Ul4a1SWfou","soy9tCIShG",
-"0KyfsYw2oU","CIShG0Kyfs","WMiS3FFDui","suY4x7ku1p","o8UydciuWz","In3NSKr8ys","v1HlnK20wK","LewvMYh1hF","tuDySd7vjM","Nxx9VXflUq",
-"In3NSd7vjM","0YAGH5ZaEz","hE1QlsuY4x","qUJMdSWfou","MmKGJYjB9t","jiVBPv8yFN","hE1QlprNT6","aez9yQ6hMC","pFrrlkB5nP","7X3uye6e4z",
-"rz7UtpFrrl","QnJ1S9y4lw","TwanoRmDcr","Vprf2Uvlv4","lViBv0Wr5y","uoStwQWxoT","zmLYDIBe8k","bZLvSFFDui","wDajX5iGN5","ZzJHWnFqik",
-"B3qemhYBCK","GrDg7YjB9t","uPX7G9eoRc","JJs5mVLTy6","LbRTHOxWIH","blLA9e6e4z","S2DfuRmDcr","nlaBylViBv","ZhwG1C2Irc","0ao3lsuY4x",
-"FwEJz8TxD7","cmXIXhE1Ql","MK07YB3qem","kZANm5nmWv","W3VFHwDajX","uN6r3bZLvS","14FLRIBe8k","M6qcGK4GS8","lpF6WdQ586","uoStwMmsIo",
-"W3VFHsuY4x","QChxspvgjS","d7vjM5Drn0","RACujiKqhr","DLhzMzFgtB","iKqhrZJTXH","IBe8ktAOsr","pFrrl0PktI","o8Uydv2eC3","J2mQiQ6hMC",
-"blLA9zY1GY","55rfB4QMc9","taOXKguMb8","qaofNFxX9q","djsrviwzGk","IBe8k6AFT0","9rlg9VerEA","OHaBz24ARF","YjB9tYjB9t","ogLgc580YD",
-"Ss0ZuLewvM","SjskQnnP8o","OxWIHJIqXi","lH1ktyToGW","Kr8ysChuy3","7X3uyUmaEv","mX2GEB3qem","6q6L97Ow5C","Gv3FqFFDui","uN6r3gjUTu",
-"MK07Yy94nw","ciuWzMmsIo","WaWsvSs0Zu","s93Mlx3LDe","tvdkDECMvU","8FmFHBGaQY","yvOMIjS1aj","lsQGoZuDtD","qQxHP3otm6","VIlwPLbRTH",
-"7fsYMFhtgl","s93MluQIcz","sx5GlwDajX","fqypymz8gx","NcICAOxWIH","zHF1qcL0aE","yluBxkB5nP","djsrvrz7Ut","jS1ajs7Mxk","uN6r30PktI",
-"t98iWQWxoT","sx5Glfqypy","rz7Uto8Uyd","CK5W7suY4x","dQ586Z4I1v","JIqXijzUqR","45cIHTCgPp","FcWrW0MR5X","v2eC3hUTw7","pAhR1Yw2oU",
-"HRxd8QClRL","QChxslweGy","BFkb8MK07Y","o8UydsqVrf","55rfB2DREs","X6Pin8TxD7","JJs5mWreyP","48cHLIKxdL","RACujqQxHP","s93MlTa8f6",
-"FxX9qksJby","WmadAhSSvQ","fcwDadQ586","brhlQ07n1c","YOfrYtuDyS","SjskQl83Ud","lm0pD618Di","ksJbyDQimp","SWfouZUnqt","fmIK1ZUnqt",
-"hYBCKzHF1q","Chuy3pmeCd","hSSvQiqv4k","WaWsvmX2GE","4W0TlJIqXi","ZzJHWcQOnv","9GXkXWaim6","9iGoT1v5hH","Q6Lix3otm6","G1RhSDQimp",
-"7lUXZVIlwP","iB08lThjNn","VjCZq9iGoT","Cfgr3lViBv","MojnPv2eC3","SbRYyFGzgp","WreyP8cVD3","DQimpfcJOy","ZuDtDOUYuF","Fhtglxciqp",
-"pmeCdcmXIX","3otm6k85Ae","uAWypXflUq","2ZHdkyToGW","PYBf4sx5Gl","C2IrcTCgPp","nFqikydG8U","lsQGohi5X7","K4GS8JIqXi","In3NSuTacx",
-"7fKYUAgJHQ","lCMxyFPfSE","S2DfunnP8o","S77LHFNYIM","KASQ8WDVWJ","5drc6AgJHQ","JIqXipAhR1","CIShGjtn0X","0h1b1uN6r3","580YDrz7Ut",
-"45cIHsoy9t","14FLRRkQke","tvdkDGWqqX","16lHcM3zXL","VNCPdPYBf4","VBjhzFLsph","d85a9WmadA","2Nslm1j5L8","i3pydECMvU","prNT6KsjRK",
-"NAFuwFVMxo","HP433SjskQ","BFkb8euZA5","9rlg9ru4UG","9rlg9gjUTu","RkQken8pJ9","dpe1vSWfou","MmsIoy94nw","s93MlBCxeC","FNYIMDQimp",
-"ZUnqt3weIF","2hEEUlpF6W","QYxC0BCxeC","SmGzvDz1R3","F6PT2hi5X7","9y4lwTwano","64s8NNxx9V","3weIFpAhR1","RxrsmCqqaD","X6PinL7cGc",
-"4W0TlIn3NS","XyPZNrhl0J","0BmCypvgjS","14FLR5ZaEz","aL6AJpFrrl","blLA9uZPqg","FhtgloQ87r","bgJAzuupzk","S2DfuEoToP","yvOMIQWxoT",
-"hSSvQv8yFN","WaWsvv1Hln","NhXdu9y4lw","fFDrJXyPZN","Q6LixC2Irc","pWiOsdmoS7","ix74rFhtgl","DcpWBuJScX","lViBvVIlwP","b29RJIjTwP",
-"HRxd80h1b1","TCgPpuJScX","rhl0JHP433","JXljWQnJ1S","OxWIH45cIH","AOgEeLbRTH","lH1kttlILt","2Yz7EBCxeC","NhXdu07n1c","vOqCEyluBx",
-"azIWpECMvU","GrDg7X6Pin","d85a9uoStw","StlDJUlU3M","VIlwPMK07Y","24ARFpT8wu","5Mg9ryToGW","8RCUAVNCPd","JKWYR0YAGH","zY1GYkZANm",
-"QnJ1S7hyVv","VerEAksJby","QChxsIRh48","NhXduo8Uyd","RmDcrtuDyS","0h1b1FVMxo","FFDuidmoS7","Qworu8TxD7","jS1ajaez9y","mz8gxs4786",
-"4W0TluLtKs","n1pmOPb1pa","WMiS3SbRYy","GWqqXRsQUq","SWfoub29RJ","i3pydulk41","5drc65Namm","AIYUuzz4ZU","gIYvETa8f6","jiVBPCp3mZ",
-"G1RhSRBhp0","OHaBz2DREs","VIlwPdQ586","WMiS3tjQxs","5NammtAOsr","NcICAru4UG","QbxXcd85a9","tlILtRxrsm","iB08lsuY4x","1v5hHF6PT2",
-"RmDcrY1mC0","zz4ZUTa8f6","0PktIlj07Q","HP433HzZT8","yvOMI7lUXZ","EdBKcgjUTu","FLsphMGlTF","FNYIMC2Irc","h1zcHRzaZA","l83UdFVMxo",
-"t98iWiqv4k","pv0i7s7Mxk","0BmCyNhXdu","lj07QAOgEe","8xEKzCIShG","BGaQYjSjS3","G1RhS7Ow5C","5VZjSl83Ud","zHF1qNxx9V","AgJHQ0Kyfs",
-"GWqqXxXTI4","lXFOBNo0Qb","K4GS8i7WMQ","S2DfuOz8yZ","pvgjSk85Ae","uQIcz0BmCy","29QAzbZLvS","GSQwjOUYuF","FFDuiRkQke","ni2v1D6rBy",
-"OUYuFJkzUn","1j5L8ix74r","hE1QlMmsIo","QClRL9iGoT","hSSvQUl4a1","zmLYD2hEEU","vLsmSLbRTH","uN6r3aez9y","Fhtgllj07Q","IjTwPZzJHW",
-"wiHrZlViBv","JKWYRfaHir","S77LH5Mg9r","xXTI4gjUTu","tlILt4QMc9","DcpWBZUnqt","rhl0JpiJSk","AkKTkrKDLJ","brhlQfaHir","CxVEffqypy",
-"azIWph1zcH","I7p2aVLTy6","VLTy6v2eC3","SbRYyhe9IA","atef2NcICA","hUTw7ni2v1","h1zcHokgRi","SbRYyNo0Qb","cmXIX3weIF","DLhzM5Mg9r",
-"0Kyfss93Ml","07n1cxciqp","Cfgr3AIYUu","IjTwPTwano","AmdQdQWxoT","djsrvk85Ae","uLtKspWiOs","Q6Lix4dEz6","UmaEvMGlTF","lH1ktD6rBy",
-"HlUbFOHaBz","QYxC0faHir","5drc60Wr5y","o8UydqaofN","jiVBP0ao3l","580YDJkzUn","S2Dfu0YAGH","KsjRKsuY4x","BGaQYfaHir","JkzUn0ao3l",
-"NcICA9iGoT","JkzUnYh1hF","zFgtBlweGy","14FLRazIWp","FhtglI7p2a","nnP8oRACuj","SWfou0BmCy","AgJHQlsQGo","BpYhVd85a9","JkzUnOUqFM",
-"ydG8UzFgtB","QnJ1S4W0Tl","UlU3MgdQsS","oGu6xFPfSE","mX2GEIBe8k","JkzUnpv0i7","Uvlv4Y1mC0","BFkb8WMiS3","9eoRcWMiS3","5Mg9rsuY4x",
-"atef2IKxdL","EoToPDcpWB","AIYUuGXdoH","s93MlO3iyQ","HfyNQMkgy8","t98iW5nmWv","LewvMgIYvE","uPX7GVjCZq","Yh1hFU3yw5","nlaByOHaBz",
-"ix74r9XyT9","iB08ld7vjM","9GXkXzY1GY","s93MlyvOMI","RsQUqRpBQm","gIYvEGrDg7","nFqikNo0Qb","LbRTHYf2Ec","0ao3lUl4a1","CxVEfs4786",
-"8U2nUix74r","29QAzgdQsS","AmdQdkB5nP","5VZjSjtn0X","AOgEesoy9t","5nmWvlCMxy","fFDrJhSSvQ","Z4I1vmX2GE","TwanojS1aj","cShY2TCgPp",
-"ni2v1FnPFB","In3NSpmeCd","prNT6Q6Lix","16lHc48cHL","suY4xs4786","kZANmuN6r3","v8yFNksJby","TCgPp618Di","In3NSi3pyd","StlDJ2DREs",
-"2NslmBGaQY","ulk41vOqCE","jzUqRgdQsS","RBhp0XyPZN","OHaBz45cIH","jiVBP8RCUA","aDGtSx3LDe","07n1c5drc6","tl72Wzz4ZU","rz7UtsqVrf",
-"iB08lOz8yZ","7hyVv0BmCy","SWfou48cHL","vkCHHNo0Qb","FVMxoVBjhz","cmXIX16lHc","JXljWFPfSE","C2Ircy94nw","UmaEv8hJdt","pmeCdCqqaD",
-"2TRI78FmFH","Mm8siCfgr3","0ao3llm0pD","5VZjSzz4ZU","ix74rQ6hMC","l83UdqaofN","FFDuihSSvQ","9GXkXciuWz","tvdkDzbIYY","lsQGoFNYIM",
-"DLhzM5IhmG","dmoS7uLtKs","k85AeBbwgA","n8pJ9WDVWJ","lCMxyuPX7G","7X3uySjskQ","s7Mxk8U2nU","sx5Glgf8rI","fcwDaazIWp","1LB1LG1RhS",
-"lm0pDFnPFB","5Nammm4bxU","VIlwPbZLvS","2TRI7CIShG","5Namm16lHc","zz4ZU7Ow5C","fFDrJFxX9q","FFDuiECMvU","aDGtSI7p2a","3otm6VLTy6",
-"ThjNnChuy3","aL6AJ14FLR","lkMUApmeCd","uTacxvLsmS","Ul4a1DLhzM","0ao3lP6bcg","Ss0Zu55rfB","Q6hMC7fKYU","pT8wucShY2","n8pJ9StlDJ",
-"GXdoHyEfy9","0KyfsjSjS3","oVQp6YjB9t","xXTI4EOE1o","vkCHHuN6r3","uTacxkB5nP","s7MxkzmLYD","GWqqXS77LH","VNCPdECMvU","QnJ1SBCxeC",
-"9iGoTW7cTs","GSQwjs93Ml","iwzGkQ6hMC","RzaZAyvOMI","0Kyfse6e4z","DG4sTWmadA","uPX7GRkQke","FFDuiHRxd8","vLsmSiwzGk","vOqCEv8yFN",
-"nlaByQChxs","gtCA5Gv3Fq","vLsmSdQ586","VIlwPRxrsm","2NslmM6qcG","QssNCd7vjM","ZJTXHcQOnv","7ku1pQssNC","45cIHRBhp0","bZLvSJXljW",
-"JKWYRXyPZN","oVQp6FVMxo","FVMxoYh1hF","NAFuwECMvU","VerEAgdQsS","v1HlniB08l","BCxeCoVQp6","vkCHHv2eC3","cShY2VIlwP","RACuj8TxD7",
-"xXTI4XflUq","lCMxyvkCHH","EOE1oru4UG","tAOsr9y4lw","XyPZNru4UG","yToGWX6Pin","WMiS3yluBx","Uvlv4vOqCE","vLsmSix74r","AXpwEhe9IA",
-"7hyVv0Kyfs","IjTwPK4GS8","JIqXit59lR","In3NS4dEz6","WDVWJ5nmWv","lm0pDNxx9V","ix74rFFDui","iwzGktAOsr","0h1b1nFqik","LDk6fgdQsS",
-"Cfgr3prNT6","QWxoT0PktI","dQ5868xEKz","FnPFBWDVWJ","07n1cuoStw","JkzUnkZANm","2Yz7EvkCHH","WPmlxFhtgl","yofH3aez9y","iqv4kksJby",
-"AgJHQCNHmv","bZLvS9iGoT","gIYvEru4UG","IjTwPRzaZA","AIYUucL0aE","KsjRKCxVEf","JXljWY1mC0","BGaQYECMvU","0YAGH48cHL","nnP8ov8yFN",
-"WmadAlCMxy","D6rByUmaEv","OUqFMO3iyQ","MK07YDLhzM","WDVWJ8U2nU","WreyPUvlv4","Vprf2lpF6W","UmaEvBbwgA","gdQsSIjTwP","CNHmvyToGW",
-"s4786uvf7A","fmIK1d85a9","ydG8U0h1b1","F6PT2CxVEf","RkQkeCNHmv","ECMvUFnPFB","Nxx9Vxciqp","618DitaOXK","RkQkeaDGtS","4dEz6uN6r3",
-"0BmCyRpBQm","gjUTuuN6r3","i7WMQcShY2","J2mQiSjskQ","hYBCKJkzUn","lpF6WlXFOB","6AFT064s8N","Vprf2qQxHP","5Drn0VjCZq","16lHcCfgr3",
-"fmIK1iB08l","0PktIfcJOy","lXFOBuTacx","Pb1paOxWIH","d85a9cShY2","16lHcSs0Zu","DcpWBBFkb8","7X3uy3weIF","e6e4zM6qcG","jfREuaez9y",
-"DG4sTjSjS3","5Drn0EdBKc","9eoRcQ6Lix","ksJbyGSQwj","s93Ml07n1c","45cIH6AFT0","lXFOBMm8si","dhSuHRpBQm","rhl0JGrDg7","MGlTFn8pJ9",
-"8RCUA0ao3l","cShY23weIF","CdyBVFNYIM","FhtglYh1hF","lweGyydG8U","s93MlHzZT8","lkMUAs4786","M3zXLcmXIX","1j5L8U3yw5","piJSkWDVWJ",
-"K4GS8d7vjM","HzZT8mX2GE","G1RhSrz7Ut","zY1GYIRh48","FPfSERxrsm","S77LHK4GS8","AgJHQbrhlQ","7ku1pmX2GE","5ZaEzpT8wu","LbRTHhYBCK",
-"fLNg8ECMvU","FwEJzokgRi","MGlTFblLA9","Q6hMCnlaBy","ydG8UnnP8o","GXdoHn8pJ9","OHaBzMm8si","FPfSE7fsYM","pAhR1B3qem","d7vjMhSSvQ",
-"oVQp60YAGH","cL0aEgf8rI","VjCZqRpBQm","48cHLyToGW","Vprf2FGzgp","ni2v1WDVWJ","5Nammaez9y","AXpwECp3mZ","rKDLJdQ586","9rlg98xEKz",
-"FwEJzTwano","POUYS3weIF","MmKGJFPfSE","zbIYYFjHXR","MK07YtaOXK","suY4xS77LH","WPmlxkZANm","Ss0ZuRpBQm","JXljWX6Pin","ECMvU2DREs",
-"9XyT9s4786","gtCA5FNYIM","dmoS755rfB","yToGWCfgr3","QClRLThjNn","OHaBzlpF6W","NAFuwgtCA5","CK5W7iqv4k","QChxszmLYD","zFgtBtjQxs",
-"FVMxoAkKTk","M3zXLx3LDe","DLhzMyvOMI","uvf7AD6rBy","Uvlv4nlaBy","L7cGcuLtKs","rz7Uttl72W","ogLgcaFFss","WPmlxaez9y","cQOnv0MR5X",
-"NOHszoQ87r","ReKEWX6Pin","XyPZN1j5L8","n1pmOqQxHP","v2eC3gjUTu","7Ow5CBpYhV","24ARFQ6Lix","Gv3Fq8RCUA","zQt6QRBhp0","s7MxkgjUTu",
-"i3pyd7X3uy","16lHcsx5Gl","oGu6xbZLvS","uoStwMkgy8","BFkb8BpYhV","DG4sTBCxeC","8FmFHv8yFN","0Kyfsk85Ae","euZA5zFgtB","fLNg8uvf7A",
-"Q6LixlkMUA","RmDcrzHF1q","NAFuwqQxHP","n1pmOiqv4k","FjHXRReKEW","W7cTsyEfy9","NhXduXflUq","qUJMdcL0aE","nlaByGXdoH","rz7UtgtCA5",
-"d7vjMYw2oU","lpF6WhSSvQ","sx5GlRkQke","a00b5zbIYY","y94nwMm8si","v1HlnfLNg8","0YAGHW7cTs","ni2v1S77LH","taOXKuLtKs","I7p2aTXQ0Z",
-"UmaEvuZPqg","WDVWJlH1kt","aez9yNcICA","pAhR1HP433","fmIK1yluBx","Cp3mZvkCHH","S2DfuSjskQ","uLtKsNxx9V","lViBvCNHmv","hYBCK5Namm",
-"iwzGkSs0Zu","VBjhzyvOMI","X6PinSbRYy","v8yFNYh1hF","fcJOy5nmWv","BCxeCD6rBy","lCMxyrz7Ut","rhl0JdmoS7","b29RJlpF6W","29QAzXflUq",
-"TXQ0Z6AFT0","55rfBfmIK1","8cVD316lHc","In3NStl72W","s93Mls93Ml","MojnPcShY2","sx5Gl4QMc9","5IhmGWDVWJ","K20wKvLsmS","K4GS8n1pmO",
-"FGzgpVNCPd","oGu6xWmadA","lH1ktuLtKs","Y1mC05ZaEz","v8yFNCNHmv","YjB9tQnJ1S","2Nslm0Kyfs","uPX7GJJs5m","uTacxNAFuw","7Ow5CX6Pin",
-"xciqpnlaBy","AXpwEW3VFH","0Wr5yGSQwj","618Di5IhmG","gjUTue6e4z","29QAzQ6Lix","v2eC3RACuj","Dz1R3SbRYy","WmadAiB08l","45cIHt59lR",
-"2NslmBbwgA","dQ586zbIYY","e6e4zFPfSE","Mm8sidmoS7","FcWrWBpYhV","lweGys7Mxk","s4786hYBCK","45cIH9iGoT","a00b5VLTy6","YOfrYzFgtB",
-"5drc6sx5Gl","aez9y2hEEU","8U2nUOxWIH","KsjRKQChxs","580YDgtCA5","lXFOBCNHmv","Ul4a1zQt6Q","QChxsIKxdL","7lUXZi3pyd","oQ87rtAOsr",
-"v2eC36q6L9","yofH3Mkgy8","suY4x07n1c","OUqFMt59lR","3weIFSs0Zu","cQOnvQYxC0","0BmCytuDyS","D6rBytuDyS","uLtKsKsjRK","aDGtSYjB9t",
-"RkQkegdQsS","he9IA5ZaEz","RBhp0cQOnv","Pb1paNcICA","HfyNQHlUbF","v8yFNFGzgp","GWqqXgtCA5","8TxD7FPfSE","faHirzbIYY","0Wr5yiwzGk",
-"0h1b1PYBf4","07n1csqVrf","5iGN5t98iW","hE1Ql2ZHdk","2Yz7EZJTXH","FNYIMhi5X7","zFgtBksJby","QYxC0QssNC","2DREs7lUXZ","pT8wuYh1hF",
-"7ku1pd85a9","0MR5XyvOMI","IBe8k07n1c","580YDGXdoH","qQxHPY1mC0","FVMxoQ6hMC","blLA9Yw2oU","QChxsGWqqX","BGaQYnFqik","euZA5NcICA",
-"VerEAtAOsr","fqypyPYBf4","uupzkWMiS3","s93Ml9iGoT","brhlQhE1Ql","6AFT0LbRTH","pT8wu8xEKz","aez9ycL0aE","GrDg7iB08l","cQOnvRsQUq",
-"s4786NAFuw","fFDrJfaHir","8xEKzQssNC","GWqqXHzZT8","Pb1parz7Ut","WreyPRpBQm","MojnPi7WMQ","NcICAW7cTs","ksJbyOUqFM","h1zcHVLTy6",
-"StlDJ45cIH","cQOnvi3pyd","MezSWjzUqR","2DREsRsQUq","atef2G1RhS","DQimpLewvM","lweGyFjHXR","Cfgr3dmoS7","8RCUAQYxC0","gjUTuFnPFB",
-"WreyP9iGoT","lj07QTa8f6","VNCPdVprf2","DG4sTtvdkD","iqv4kni2v1","v2eC30h1b1","UlU3MuN6r3","BGaQY14FLR","tvdkD1v5hH","Qworu6q6L9",
-"BFkb8pWiOs","K4GS8gIYvE","KZamHiwzGk","tjQxsFLsph","wDajX7fKYU","euZA5QChxs","gIYvEAIYUu","y94nwjS1aj","JJs5mlm0pD","5IhmGFjHXR",
-"HRxd89XyT9","FLsphHzZT8","WaWsv9eoRc","ZJTXHFhtgl","GrDg7Ul4a1","S2DfuBpYhV","tjQxs618Di","prNT6fmIK1","euZA5zmLYD","MojnPdQ586",
-"MK07YKr8ys","MmsIopmeCd","OxWIHpvgjS","i3pydFFDui","I7p2aLDk6f","s93MlUl4a1","2hEEUkB5nP","DLhzM8cVD3","CNHmvuLtKs","EOE1oaDGtS",
-"faHirSs0Zu","jSjS3Q6Lix","OxWIHpT8wu","lkMUAUmaEv","UlU3MxReec","prNT6s4786","fLNg87fsYM","LDk6fdQ586","FVMxoXyPZN","i7WMQgjUTu",
-"FnPFBZ4I1v","0h1b1bgJAz","djsrvGWqqX","9eoRcoQ87r","Zv7z0X6Pin","RACujIRh48","Kr8ysAIYUu","uvf7A4dEz6","CxVEfsx5Gl","cShY2zHF1q",
-"BCxeCfcJOy","FjHXRFFDui","AXpwEPb1pa","Y1mC0ECMvU","W7cTshUTw7","StlDJ5Drn0","tvdkD5iGN5","kZANmuZPqg","TCgPpUvlv4","9GXkX48cHL",
-"0Kyfsulk41","NOHsz2Nslm","QworuMmKGJ","BbwgAAIYUu","ZzJHWMmsIo","7X3uylViBv","cQOnv64s8N","DG4sTd7vjM","b29RJOz8yZ","OUqFMIBe8k",
-"F6PT2WPmlx","s4786UmaEv","QClRLSmGzv","t59lRAkKTk","QssNCWaWsv","tlILtuTacx","LewvM3otm6","O3iyQx3LDe","dQ586O3iyQ","i7WMQsx5Gl",
-"0KyfsS77LH","FNYIMFNYIM","ZzJHWVprf2","pFrrlTwano","d7vjMpT8wu","uAWyps93Ml","uQIczlpF6W","ru4UGogLgc","Ta8f6xXTI4","i3pydtl72W",
-"lkMUABbwgA","MmKGJ8RCUA","rKDLJrz7Ut","NAFuwKZamH","No0QbblLA9","WDVWJru4UG","2hEEUIn3NS","fmIK1Zv7z0","StlDJBbwgA","pv0i7DQimp",
-"ZuDtDGWqqX","VerEAZUnqt","zmLYDNcICA","uupzkiKqhr","pAhR1UmaEv","RBhp0dmoS7","gf8rIVerEA","7Ow5CVBjhz","8RCUAoGu6x","Ss0Zuaez9y",
-"X6PinThjNn","WMiS31v5hH","7Ow5CFjHXR","M6qcG3otm6","NhXduGWqqX","FFDui2DREs","SWfouVLTy6","AOgEe14FLR","RzaZAMkgy8","No0QblkMUA",
-"atef2rz7Ut","W7cTs1j5L8","gf8rI2Yz7E","8TxD7VerEA","Dz1R3Ta8f6","3weIFzqH0W","DLhzMuupzk","dhSuHKZamH","AXpwEWaWsv","618DiSWfou",
-"0Wr5yMK07Y","29QAzrhl0J","Zv7z0uoStw","7Ow5CsqVrf","uAWyplsQGo","soy9tFVMxo","AgJHQtaOXK","okgRipv0i7","WMiS3X6Pin","IjTwPgf8rI",
-"oVQp6uAWyp","rhl0JpmeCd","9GXkXgjUTu","FLsphxReec","jeskSgtCA5","UlU3MFwEJz","ReKEWNxx9V","CIShG2TRI7","ulk41l83Ud","RACujlsQGo",
-"gf8rIS2Dfu","LDk6f9XyT9","i7WMQv2eC3","i3pydy94nw","M6qcGHfyNQ","Rxrsmgf8rI","TXQ0Zatef2","9y4lwiwzGk","48cHLuoStw","55rfBt98iW",
-"hi5X7YOfrY","9iGoTYjB9t","t98iWzz4ZU","nlaBye6e4z","xciqpHP433","EdBKcsx5Gl","9eoRc1LB1L","Q6hMCF6PT2","CxVEfZhwG1","QChxsChuy3",
-"iwzGkOz8yZ","OHaBzUvlv4","GWqqX5nmWv","JkzUnXyPZN","9XyT9FFDui","hUTw7Twano","wiHrZEoToP","618DiECMvU","0ao3lD6rBy","jtn0XGv3Fq",
-"t98iW9GXkX","HzZT8uAWyp","580YDZJTXH","fqypyiqv4k","Oz8yZsoy9t","yofH3t98iW","MGlTFpFrrl","5Namms4786","ksJbyuJScX","v2eC3lj07Q",
-"BCxeCUlU3M","KZamHfcJOy","SmGzvnnP8o","t98iW2Yz7E","uN6r3ni2v1","WMiS3W7cTs","7ku1p9iGoT","pmeCdECMvU","OHaBzMGlTF","29QAzcQOnv",
-"v2eC3jtn0X","ydG8U45cIH","d7vjMSmGzv","M6qcGydG8U","Kr8ys6q6L9","WMiS3lCMxy","ru4UG4dEz6","8FmFHQWxoT","POUYSlm0pD","Yh1hFQ6hMC",
-"x3LDeyofH3","P6bcgQssNC","3otm68cVD3","JRJQBdmoS7","45cIHZ4I1v","KZamH07n1c","5iGN59XyT9","ni2v1CqqaD","HlUbFTa8f6","n1pmOFnPFB",
-"Yh1hF0YAGH","AgJHQvkCHH","5iGN5gtCA5","B3qempvgjS","Zv7z0CK5W7","0MR5X4dEz6","fqypyFhtgl","xciqp8TxD7","WDVWJJXljW","v8yFNuN6r3",
-"AOgEeAmdQd","AkKTkiKqhr","s7MxkRBhp0","WmadABGaQY","TCgPpZJTXH","m4bxU8FmFH","azIWppAhR1","yluBxa00b5","lpF6WuZPqg","OUYuFHlUbF",
-"ECMvUFwEJz","uZPqggIYvE","Gv3FqK20wK","FjHXRZv7z0","6AFT0lkMUA","07n1c8hJdt","lXFOB4QMc9","djsrvHlUbF","atef2y94nw","FNYIM1v5hH",
-"O3iyQni2v1","9y4lwuPX7G","jtn0XRACuj","uTacxsqVrf","W3VFHcL0aE","l83UdVIlwP","y94nwBFkb8","lkMUAn1pmO","FLsphNAFuw","x3LDe0Wr5y",
-"hi5X7uTacx","y94nwt98iW","kB5nPt59lR","9eoRcdpe1v","jSjS3JRJQB","8U2nURzaZA","JJs5mRzaZA","lsQGoMmKGJ","2TRI7gIYvE","ZuDtDCNHmv",
-"0BmCyWaWsv","RBhp09rlg9","2DREs5nmWv","nFqikrhl0J","S2DfuciuWz","fqypyVNCPd","Ul4a1fcwDa","zHF1qzY1GY","ReKEWgdQsS","hUTw7S2Dfu",
-"G1RhSXflUq","14FLRlsQGo","atef2wiHrZ","MezSWjiVBP","euZA5o8Uyd","8RCUAAIYUu","7ku1pRACuj","VBjhz2DREs","lj07QX6Pin","dhSuH5Mg9r",
-"gf8rITXQ0Z","NcICAt59lR","dQ58616lHc","Gv3FqUmaEv","HzZT8pT8wu","Y1mC0sqVrf","hSSvQNhXdu","Mkgy8t59lR","sqVrfzz4ZU","1v5hH580YD",
-"gdQsS1j5L8","iKqhrhSSvQ","AXpwEP6bcg","2NslmWPmlx","piJSk0PktI","WaWsvAgJHQ","iKqhrO3iyQ","QYxC0ix74r","WDVWJ9y4lw","Zv7z0bgJAz",
-"Yw2oUlCMxy","9XyT9jSjS3","No0QbXyPZN","lCMxyhSSvQ","zY1GYIjTwP","prNT6he9IA","48cHLv2eC3","aez9yAXpwE","P6bcgDz1R3","FFDuimz8gx",
-"8cVD3F6PT2","AmdQdatef2","ZJTXHPYBf4","aL6AJpWiOs","QbxXcUvlv4","NOHszs4786","KsjRK8hJdt","0h1b18U2nU","HlUbFAOgEe","okgRiFhtgl",
-"t98iWHlUbF","SjskQaez9y","zbIYYpmeCd","JKWYR5Namm","faHirW3VFH","tlILtTCgPp","0YAGHhSSvQ","azIWpQ6hMC","o8UydaL6AJ","iB08ljfREu",
-"s93MlWmadA","FFDuiTXQ0Z","uupzkIRh48","2ZHdkYjB9t","64s8NQ6hMC","zHF1qSbRYy","14FLRKsjRK","B3qemF6PT2","NAFuw29QAz","POUYSPYBf4",
-"lXFOBlkMUA","Dz1R34W0Tl","RzaZAvkCHH","fFDrJyluBx","bZLvSIBe8k","HRxd85Mg9r","8U2nUlpF6W","suY4xl83Ud","CxVEfHlUbF","0KyfsAIYUu",
-"0PktIjeskS","0MR5XVerEA","o8UydfaHir","ulk41ni2v1","2NslmlViBv","Nxx9VpWiOs","16lHcGXdoH","Dz1R3e6e4z","lViBvaez9y","lkMUAuAWyp",
-"sqVrfMGlTF","k85Ae1v5hH","U3yw5Ta8f6","DG4sTJJs5m","In3NSzbIYY","pv0i7iB08l","LDk6fokgRi","IRh48RACuj","LbRTHlViBv","CIShGbrhlQ",
-"48cHL8hJdt","BbwgAQnJ1S","ix74rJJs5m","07n1ctAOsr","S77LHvkCHH","OHaBzBCxeC","M3zXLKZamH","ix74ruQIcz","ZhwG1BCxeC","QbxXcWDVWJ",
-"FxX9qAIYUu","Q6LixDG4sT","UlU3MNhXdu","nlaBy3weIF","LbRTH8cVD3","S77LHWPmlx","JXljWZzJHW","fcJOyuQIcz","uN6r3oQ87r","ZhwG1In3NS",
-"iqv4kS77LH","hYBCKtl72W","S77LHpWiOs","o8Uyd8hJdt","8xEKzblLA9","sqVrfhe9IA","uLtKss4786","yToGWdjsrv","rz7UtCp3mZ","zY1GY9y4lw",
-"MojnPpT8wu","I7p2agdQsS","IKxdLprNT6","7fKYU64s8N","zz4ZUtl72W","zbIYYnFqik","8FmFHChuy3","7fsYMv8yFN","gdQsSAOgEe","Mm8siIRh48",
-"5Mg9rCqqaD","MK07Y1LB1L","5iGN5BbwgA","IKxdLC2Irc","lH1ktNxx9V","JIqXiy94nw","B3qems93Ml","RACujQClRL","gIYvEQworu","o8Uyd0Wr5y",
-"Chuy32Yz7E","v8yFNBFkb8","uAWypFhtgl","JJs5mwiHrZ","8RCUAtuDyS","M6qcGBpYhV","k85Ae4W0Tl","8hJdtD6rBy","v2eC3Chuy3","ru4UGUlU3M",
-"HlUbFhUTw7","9GXkXRxrsm","fLNg8Yh1hF","VerEAlj07Q","GWqqXIKxdL","v1HlnFcWrW","Ta8f6Kr8ys","y94nw7fKYU","HP433lsQGo","Chuy39GXkX",
-"hUTw7TXQ0Z","euZA5cQOnv","soy9tZJTXH","lXFOBzqH0W","7hyVvpiJSk","D6rBy2ZHdk","oQ87rJIqXi","QClRLn8pJ9","aDGtSLDk6f","nnP8oDQimp",
-"HlUbFxciqp","VNCPdFwEJz","8hJdtFGzgp","zqH0Wzz4ZU","hi5X7EOE1o","he9IAgdQsS","qaofNPb1pa","Yw2oUfFDrJ","pv0i7uPX7G","Ss0ZuKASQ8",
-"Cp3mZb29RJ","VBjhzMojnP","MmsIoWaim6","0BmCyG1RhS","soy9tW7cTs","8FmFHNcICA","JXljWQClRL","FhtglaL6AJ","POUYS6q6L9","ZJTXHrKDLJ",
-"POUYSnFqik","IBe8kAgJHQ","W3VFHlm0pD","RkQkeWmadA","WPmlxCdyBV","KASQ8n1pmO","CdyBVXflUq","lj07QCK5W7","Cp3mZaez9y","7fsYMjiVBP",
-"ZuDtDRpBQm","14FLR3otm6","KZamH6AFT0","Mkgy8Mm8si","MmsIoGSQwj","Q6hMCv2eC3","LewvMQ6hMC","uQIcz2Nslm","fcJOyJJs5m","blLA9kB5nP",
-"piJSkv8yFN","tl72WQssNC","fqypyzY1GY","uvf7AAmdQd","NAFuwKr8ys","tvdkDrKDLJ","vkCHH14FLR","QworuFjHXR","lweGy29QAz","JJs5mCxVEf",
-"zFgtBb29RJ","TCgPppFrrl","uQIczX6Pin","QChxsAgJHQ","faHiruPX7G","WPmlxGrDg7","mX2GEcmXIX","2TRI7lweGy","FPfSEtvdkD","9XyT9VerEA",
-"jS1ajTXQ0Z","0ao3lVjCZq","faHira00b5","ZJTXHSjskQ","lH1ktnlaBy","MaJQs2DREs","OHaBzW7cTs","5drc6n8pJ9","JJs5mFVMxo","wiHrZRkQke",
-"XflUqJkzUn","9GXkXQbxXc","7fKYUcShY2","In3NShUTw7","Q6LixyvOMI","MezSWfLNg8","pT8wufmIK1","uJScXiqv4k","lH1ktQnJ1S","d85a9zqH0W",
-"aDGtSNcICA","fLNg8FwEJz","MojnPFLsph","5Drn0EoToP","FnPFB0MR5X","FNYIMK20wK","NhXduzY1GY","9rlg95nmWv","5IhmGvkCHH","uZPqgTCgPp",
-"618DiY1mC0","y94nwIn3NS","L7cGclpF6W","aL6AJ2hEEU","In3NSCp3mZ","2TRI7euZA5","M6qcGGSQwj","qQxHPP6bcg","OHaBzFjHXR","o8Uydtl72W",
-"BFkb8tuDyS","a00b5FNYIM","K20wKTwano","QbxXclH1kt","QChxsW7cTs","RmDcrFPfSE","MaJQspv0i7","jtn0Xlj07Q","MmsIoAkKTk","4W0TlCK5W7",
-"AIYUuRmDcr","RsQUqBGaQY","K4GS8uAWyp","Dz1R3pv0i7","QClRLLewvM","0Wr5yEdBKc","KZamH7X3uy","S2Dfu2DREs","xXTI4fLNg8","DLhzMNhXdu",
-"WreyPxXTI4","TCgPpv1Hln","Uvlv42ZHdk","yvOMIWmadA","ciuWzRmDcr","IKxdLU3yw5","FhtglNcICA","No0QbOHaBz","2TRI7uQIcz","djsrvJKWYR",
-"QssNCBCxeC","faHir7fKYU","d7vjMn1pmO","Oz8yZ2Nslm","7fKYUStlDJ","7ku1ppWiOs","i3pydvkCHH","ZJTXHCqqaD","2hEEU0BmCy","MezSWiwzGk",
-"AIYUu5iGN5","rhl0Jx3LDe","a00b5StlDJ","W7cTsnFqik","uupzk55rfB","t59lRuupzk","kB5nP48cHL","s93MlWDVWJ","0BmCy48cHL","djsrvhYBCK",
-"uZPqgdpe1v","NcICA5IhmG","gf8rIQssNC","QworuVjCZq","vOqCEZv7z0","iqv4kjiVBP","4dEz6Q6hMC","8hJdt1j5L8","rhl0JDG4sT","jzUqRdpe1v",
-"uoStw5VZjS","2hEEULDk6f","Z4I1v0h1b1","aL6AJReKEW","EOE1oeuZA5","BGaQYpWiOs","fcJOylCMxy","5NammgtCA5","AOgEeQChxs","o8UydlXFOB",
-"WreyPiwzGk","hYBCKS77LH","KASQ8rhl0J","aFFss9y4lw","14FLRjfREu","7hyVvVLTy6","gjUTulViBv","uTacxyEfy9","JJs5m64s8N","HfyNQEdBKc",
-"FxX9qx3LDe","Twano9rlg9","h1zcHaez9y","nFqikqQxHP","SWfouPb1pa","l83UdIjTwP","zqH0Wuvf7A","MaJQs45cIH","5Mg9rqUJMd","CIShGaL6AJ",
-"29QAzJRJQB","QYxC00MR5X","rKDLJ4dEz6","ni2v1Gv3Fq","SmGzvwiHrZ","Yh1hFM3zXL","2ZHdkuoStw","TCgPphE1Ql","lViBv9XyT9","ogLgcmX2GE",
-"QworuF6PT2","0PktIfLNg8","XflUqW3VFH","CIShG618Di","HP433EoToP","CK5W7d85a9","zmLYDQWxoT","tuDySEOE1o","QnJ1SlsQGo","zY1GY7ku1p",
-"lkMUAReKEW","FLsphfaHir","hi5X7fFDrJ","piJSkM6qcG","yEfy9NOHsz","n1pmOhUTw7","suY4xuJScX","Pb1paMK07Y","gdQsSzQt6Q","YjB9tdQ586",
-"7X3uygIYvE","5iGN5LDk6f","MezSW1j5L8","n8pJ9FnPFB","uvf7Azz4ZU","vOqCESbRYy","G1RhSSs0Zu","Z4I1vW7cTs","WDVWJqUJMd","XyPZNtlILt",
-"DQimpBCxeC","WPmlxfLNg8","qaofNJkzUn","t59lRjeskS","oQ87r8RCUA","IjTwP1v5hH","YjB9tTCgPp","Dz1R3prNT6","2TRI7azIWp","gdQsScQOnv",
-"0MR5XW7cTs","0Wr5yfaHir","OHaBzJ2mQi","Z4I1vEoToP","FxX9qFGzgp","hUTw7pT8wu","aFFssQ6Lix","wDajXKr8ys","brhlQJKWYR","JRJQBPYBf4",
-"gjUTuLbRTH","taOXKRmDcr","NOHszNcICA","9rlg9Ul4a1","FwEJzY1mC0","zFgtBi3pyd","l83Udtl72W","FhtglBCxeC","k85AeiKqhr","ydG8UVprf2",
-"5NammaDGtS","atef2SjskQ","2ZHdkQChxs","RkQkeReKEW","ZUnqtd85a9","xXTI4F6PT2","lCMxyaez9y","k85Ae5iGN5","QbxXczQt6Q","y94nwiB08l",
-"uupzkyEfy9","fcJOydhSuH","VBjhzWreyP","Ul4a1Pb1pa","BbwgAVerEA","FFDuihe9IA","0Wr5yQssNC","IKxdLQ6hMC","lViBvyToGW","y94nwKr8ys",
-"4QMc964s8N","Gv3Fq4dEz6","pAhR12Yz7E","BGaQYa00b5","55rfBIRh48","7X3uyAmdQd","lViBv5Drn0","tvdkD5ZaEz","fcwDaRsQUq","qaofNCNHmv",
-"uZPqglpF6W","X6PinSs0Zu","VLTy6KsjRK","LDk6fe6e4z","rz7Utl83Ud","9XyT90Kyfs","djsrvgIYvE","cShY2QbxXc","AIYUu16lHc","gIYvEFLsph",
-"jtn0XvOqCE","6AFT0iqv4k","fcJOygdQsS","aDGtSzY1GY","O3iyQBGaQY","uPX7GMkgy8","d85a9d85a9","x3LDeZv7z0","nlaByhUTw7","FhtgliwzGk",
-"1j5L8EoToP","2Yz7E2TRI7","UlU3MbZLvS","faHirG1RhS","vLsmSv1Hln","MK07Yhe9IA","gjUTupmeCd","ThjNnpvgjS","ThjNnMmKGJ","uTacx9eoRc",
-"QYxC0MaJQs","pvgjSpT8wu","ogLgcpWiOs","VLTy6VerEA","faHirI7p2a","prNT63weIF","wDajXCp3mZ","OUqFMGSQwj","YOfrYzHF1q","AXpwEyofH3",
-"fcJOyjfREu","5drc6hUTw7","IRh488hJdt","0KyfspvgjS","dmoS7RmDcr","ZhwG18RCUA","suY4xIn3NS","29QAzlj07Q","d85a96q6L9","h1zcHs93Ml",
-"BGaQYogLgc","xXTI4Y1mC0","LDk6fNAFuw","AgJHQGv3Fq","7fKYUtl72W","AIYUujiVBP","B3qemt98iW","gjUTuEoToP","pFrrlmz8gx","iKqhrBbwgA",
-"OHaBzkZANm","Ta8f6s4786","oQ87rjS1aj","aFFssLDk6f","OUqFMDcpWB","55rfBlweGy","AkKTkiqv4k","FcWrWciuWz","4W0TlNxx9V","tvdkDAkKTk",
-"hi5X7QClRL","W3VFHlpF6W","BCxeCuJScX","nFqikv8yFN","EOE1ozFgtB","Zv7z0IBe8k","zFgtBAmdQd","QYxC0ReKEW","o8UydWDVWJ","HzZT8ZzJHW",
-"0h1b1xXTI4","aFFssOxWIH","UlU3MyofH3","ZzJHWWPmlx","hSSvQ0PktI","jSjS3djsrv","G1RhS55rfB","4QMc9mX2GE","KZamHzz4ZU","tl72WaL6AJ",
-"x3LDe7Ow5C","29QAzYw2oU","s93Ml9y4lw","mz8gxyluBx","fLNg8MGlTF","EoToPvkCHH","MezSWUlU3M","6q6L95Mg9r","taOXKM6qcG","i7WMQ1v5hH",
-"Nxx9VtuDyS","AOgEeBpYhV","atef255rfB","2Nslmni2v1","xciqp1LB1L","9GXkXX6Pin","kZANmyToGW","lj07Qlj07Q","FxX9qMm8si","lj07QKr8ys",
-"d85a9FLsph","RsQUqChuy3","faHir45cIH","Yw2oULDk6f","MaJQsqUJMd","ix74rNxx9V","IjTwPFVMxo","jtn0XU3yw5","piJSkfLNg8","bgJAzAOgEe",
-"yvOMIzqH0W","MK07Ys4786","MmKGJ6q6L9","okgRigjUTu","lH1kt6q6L9","Cfgr3qQxHP","WaWsviwzGk","MGlTF8cVD3","xciqpcL0aE","blLA9tlILt",
-"MGlTFdpe1v","5ZaEzzbIYY","NOHsztjQxs","pT8wuiB08l","Dz1R3JkzUn","RmDcrYh1hF","dhSuH618Di","cmXIXzmLYD","hi5X7aFFss","BCxeCjtn0X",
-"0MR5XrKDLJ","hUTw7XflUq","CqqaDatef2","LbRTHQYxC0","K4GS8FjHXR","pvgjSQbxXc","jSjS3EOE1o","jSjS3ZzJHW","qUJMd1v5hH","zz4ZU1v5hH",
-"iwzGkU3yw5","pmeCd1j5L8","RpBQmFhtgl","lkMUAjiVBP","W3VFHVerEA","FNYIMsoy9t","SmGzvKr8ys","rz7Utm4bxU","CNHmvblLA9","JKWYROHaBz",
-"2Nslmlm0pD","l83Ud29QAz","AkKTkvOqCE","gf8rIyToGW","CdyBVNhXdu","ksJbyTXQ0Z","cShY2FwEJz","ydG8Uv8yFN","7hyVvt59lR","uoStwJkzUn",
-"s93MlsuY4x","gjUTuRACuj","K20wKaL6AJ","aez9yfcJOy","HlUbF7Ow5C","fmIK1v2eC3","QnJ1SFFDui","9iGoTGv3Fq","CdyBVNcICA","uupzktlILt",
-"Gv3FqPOUYS","tl72W9GXkX","0ao3lJkzUn","OUqFMs4786","i3pydqUJMd","KASQ855rfB","sqVrfRkQke","XflUqWaWsv","RACujMojnP","Q6hMCzY1GY",
-"uQIczzbIYY","djsrvWMiS3","P6bcghUTw7","pv0i7VLTy6","NOHszAIYUu","VNCPd0h1b1","Vprf2fcwDa","VBjhzzFgtB","W7cTsulk41","fcwDaaFFss",
-"AXpwEydG8U","XflUq6AFT0","oQ87rn1pmO","JKWYRXflUq","ydG8UoQ87r","1v5hHmX2GE","hYBCKfcJOy","QssNC9GXkX","L7cGcIKxdL","8hJdtZUnqt",
-"NOHszyofH3","Mm8sifcJOy","WreyPCxVEf","ciuWzoVQp6","YjB9tciuWz","No0QbL7cGc","faHir9GXkX","POUYSBpYhV","POUYSIjTwP","45cIHDcpWB",
-"aFFssciuWz","Kr8ys8TxD7","1v5hH2hEEU","zQt6QqaofN","rhl0JtuDyS","JKWYRGv3Fq","WMiS3I7p2a","4QMc9t59lR","UlU3MQClRL","SmGzvQ6Lix",
-"0h1b129QAz","faHirjfREu","aL6AJ7Ow5C","TXQ0ZCxVEf","xXTI4618Di","P6bcg2Yz7E","pFrrlb29RJ","Dz1R3Ul4a1","BCxeC8TxD7","NhXduK20wK",
-"uQIczGXdoH","ZhwG1OUqFM","PYBf4BFkb8","9GXkXt98iW","IjTwPprNT6","a00b57fKYU","qUJMdguMb8","RxrsmyvOMI","yofH3n8pJ9","Pb1paQ6Lix",
-"Yf2EcQ6hMC","14FLRQ6hMC","lkMUAEOE1o","KsjRKiqv4k","CxVEfThjNn","9XyT9M6qcG","suY4xRkQke","lViBvKZamH","RsQUqsx5Gl","fmIK1X6Pin",
-"a00b5djsrv","KsjRKOUYuF","uoStwlj07Q","a00b57fsYM","0PktI7ku1p","djsrv8FmFH","b29RJTa8f6","0ao3lwiHrZ","MGlTFYh1hF","d85a9o8Uyd",
-"nFqikt59lR","prNT6Cp3mZ","DLhzMMmsIo","FVMxoU3yw5","uN6r3oVQp6","RmDcrBbwgA","EoToP5Mg9r","piJSklj07Q","XyPZNdhSuH","zbIYY5VZjS",
-"NAFuw1LB1L","taOXK0YAGH","Ul4a1uQIcz","SjskQLDk6f","0ao3lkB5nP","NhXduPOUYS","HP4335IhmG","2TRI7uLtKs","Y1mC0580YD","WaWsvy94nw",
-"hSSvQ3weIF","zbIYYEoToP","ThjNnlm0pD","soy9tdQ586","Dz1R3RBhp0","brhlQyluBx","LDk6f2Nslm","YOfrYoVQp6","wDajXuPX7G","CdyBV29QAz",
-"5iGN5lweGy","gtCA5RpBQm","iwzGkX6Pin","PYBf4ThjNn","taOXKdjsrv","nnP8oru4UG","S2DfuCIShG","Ta8f6iqv4k","hi5X70PktI","7fsYMFjHXR",
-"14FLR1j5L8","VBjhz1j5L8","FwEJzDQimp","okgRiThjNn","AkKTk9rlg9","RmDcrBGaQY","i3pyd5Drn0","atef2Q6hMC","J2mQiRkQke","jSjS3CdyBV",
-"tjQxsprNT6","tjQxsJKWYR","8TxD7RACuj","B3qem45cIH","0h1b17hyVv","QssNCYw2oU","faHirqUJMd","l83UdbrhlQ","BFkb8zFgtB","DG4sTUmaEv",
-"hUTw7QChxs","ZuDtDhYBCK","pAhR1ReKEW","DcpWBt59lR","JIqXiL7cGc","9eoRc7fKYU","NOHszpmeCd","BGaQYGrDg7","RkQke1LB1L","jzUqRgf8rI",
-"24ARFFLsph","lj07Qe6e4z","RmDcrMmsIo","1v5hHWaWsv","aDGtSyofH3","HP433ydG8U","Yf2Ecrz7Ut","X6PinMkgy8","Chuy3iqv4k","gIYvEqUJMd",
-"WaWsvuPX7G","uJScXOz8yZ","y94nwQbxXc","5drc6K4GS8","7fsYMRzaZA","bZLvS4QMc9","Rxrsmix74r","X6PinU3yw5","NcICA5drc6","RsQUq5VZjS",
-"lH1kt29QAz","07n1cMmsIo","QWxoTXyPZN","FjHXRlkMUA","ZuDtDHzZT8","sx5GlThjNn","LDk6fazIWp","m4bxUx3LDe","QWxoTQworu","YjB9tGrDg7",
-"iwzGkOHaBz","HlUbFvkCHH","I7p2azFgtB","bZLvSgIYvE","Twanojtn0X","Gv3FqzbIYY","MmKGJuvf7A","5Mg9rWMiS3","aL6AJdQ586","VLTy6fcJOy",
-"7hyVv8RCUA","KsjRKJkzUn","BpYhV7fsYM","LbRTHXyPZN","8cVD3NcICA","gjUTupWiOs","qQxHPFcWrW","hE1QlBpYhV","LewvM0Wr5y","G1RhSFhtgl",
-"IBe8k9rlg9","zmLYDfqypy","IBe8kMm8si","45cIHWPmlx","HP433NcICA","xReecP6bcg","580YDZ4I1v","lweGyQssNC","i3pydtjQxs","J2mQiQYxC0",
-"MojnPwiHrZ","CxVEfuPX7G","UlU3MoVQp6","zmLYDYf2Ec","dpe1vlj07Q","HfyNQBCxeC","uLtKsfLNg8","LDk6foVQp6","NcICA580YD","aL6AJZUnqt",
-"l83Ud4W0Tl","jzUqRm4bxU","uTacxe6e4z","VIlwP7Ow5C","uPX7G14FLR","xReeczmLYD","8cVD3tvdkD","WaWsvni2v1","Q6Lixgf8rI","DcpWBlm0pD",
-"n1pmOpiJSk","pT8wuzqH0W","nlaByTwano","AOgEeyEfy9","zQt6Q29QAz","wDajX0ao3l","guMb8hSSvQ","pT8wu0Wr5y","yEfy9v1Hln","t98iWGWqqX",
-"zHF1quupzk","VerEAGWqqX","JRJQBKASQ8","GXdoHzmLYD","v1HlnuoStw","DG4sTuJScX","GWqqXydG8U","07n1ccmXIX","VerEAQworu","AgJHQuvf7A",
-"WDVWJK20wK","1LB1LHzZT8","IBe8kuoStw","Cp3mZDG4sT","FcWrWGXdoH","zFgtBl83Ud","5ZaEz16lHc","7fsYMJJs5m","5iGN5aez9y","ogLgcAmdQd",
-"7ku1plj07Q","9XyT9DQimp","JIqXi9eoRc","XyPZNyvOMI","RkQke7fKYU","hE1QlMkgy8","DcpWBIjTwP","m4bxUCfgr3","9XyT9m4bxU","HzZT8ulk41",
-"5ZaEzQ6Lix","uAWypjS1aj","jtn0XQClRL","pvgjSHP433","5nmWvAkKTk","MK07YFnPFB","YjB9tpvgjS","fcwDaiqv4k","Kr8ysUl4a1","aDGtSFnPFB",
-"VBjhzMm8si","blLA9uTacx","0BmCyW7cTs","ksJbyS2Dfu","0MR5XB3qem","I7p2amX2GE","9iGoT8cVD3","pAhR18hJdt","Vprf2J2mQi","djsrvQbxXc",
-"fmIK1s7Mxk","Zv7z02Yz7E","BbwgAVNCPd","W3VFHSWfou","2ZHdkOUYuF","m4bxULDk6f","d7vjMlweGy","Cfgr3YOfrY","9y4lwKr8ys","tjQxsuvf7A",
-"StlDJs93Ml","Cfgr307n1c","y94nwRzaZA","AXpwE2hEEU","LewvMRkQke","s4786pWiOs","Ul4a1FjHXR","M3zXLtaOXK","2ZHdkZ4I1v","1LB1LpWiOs",
-"9iGoTWPmlx","ReKEWi3pyd","Fhtgl2DREs","piJSkxReec","PYBf4NhXdu","i3pyd6q6L9","uTacxC2Irc","618Dii7WMQ","qQxHPZ4I1v","fmIK1ZJTXH",
-"0MR5XNxx9V","gIYvECqqaD","v8yFN4QMc9","soy9t8cVD3","JXljWxXTI4","QssNCuN6r3","2DREsIn3NS","lm0pDFwEJz","tAOsrMm8si","W7cTs5drc6",
-"X6PinlpF6W","yluBx48cHL","FcWrW6AFT0","suY4xqQxHP","gIYvEgf8rI","CxVEfSjskQ","MojnPvOqCE","Yf2EcZ4I1v","L7cGcX6Pin","k85Aetl72W",
-"SWfouaFFss","qQxHPeuZA5","uTacxVjCZq","7ku1pC2Irc","9GXkXx3LDe","fFDrJv1Hln","xReecWaWsv","5nmWvzHF1q","qaofNv2eC3","uJScXJkzUn",
-"mX2GERzaZA","0Wr5yDz1R3","hYBCK3otm6","5NammS77LH","S77LH7lUXZ","euZA5RACuj","Chuy3AkKTk","t59lRHlUbF","vkCHHhUTw7","l83UdMkgy8",
-"d7vjMuJScX","8FmFH2TRI7","FNYIMIjTwP","4dEz6EoToP","Oz8yZIRh48","xReecUl4a1","DLhzMCNHmv","lj07Q14FLR","yluBxuTacx","FVMxoogLgc",
-"uQIcz5Namm","a00b5faHir","48cHLWmadA","QnJ1SwiHrZ","8xEKzLewvM","pv0i7zbIYY","VIlwPn8pJ9","5drc65ZaEz","b29RJGv3Fq","0Wr5yG1RhS",
-"7X3uyrhl0J","5Mg9r7ku1p","VerEAVNCPd","KASQ80PktI","1j5L81j5L8","iB08lP6bcg","ECMvUlpF6W","NhXduBCxeC","CqqaDx3LDe","JJs5md85a9",
-"dQ586AgJHQ","StlDJKr8ys","yofH32Yz7E","5IhmGIn3NS","FNYIMLewvM","iKqhrOz8yZ","07n1cWaWsv","BbwgAn1pmO","F6PT20h1b1","soy9tcShY2",
-"SbRYyZv7z0","I7p2ae6e4z","d7vjM9iGoT","FcWrWHP433","618DieuZA5","uN6r3zQt6Q","M6qcGv2eC3","CNHmvMmKGJ","JXljWL7cGc","VLTy6Ul4a1",
-"VIlwP9y4lw","Mkgy8X6Pin","WmadAhUTw7","cShY2lCMxy","aez9yuvf7A","JIqXi1j5L8","a00b5ZJTXH","atef2NhXdu","yofH3X6Pin","gjUTu5nmWv",
-"W3VFHtl72W","jzUqRKASQ8","cmXIXciuWz","7X3uyBCxeC","d85a9NcICA","euZA5lkMUA","uJScXxXTI4","lkMUAxXTI4","EdBKccL0aE","JIqXiFGzgp",
-"pAhR1MezSW","QChxsfLNg8","tl72WuJScX","HP433Cp3mZ","uLtKsFLsph","guMb8m4bxU","AXpwEIRh48","taOXKCp3mZ","ZzJHWzY1GY","lXFOBzmLYD",
-"Nxx9VJIqXi","OUqFMCdyBV","wDajX5Namm","gdQsS7Ow5C","9rlg9qQxHP","WreyP8FmFH","D6rBypv0i7","JkzUnFxX9q","gIYvEsoy9t","s7MxkBbwgA",
-"n8pJ9JkzUn","Uvlv4Fhtgl","D6rByt59lR","2Yz7EZv7z0","5Mg9r5ZaEz","fqypypT8wu","5iGN5atef2","MK07Y0Kyfs","dmoS7nlaBy","Ss0ZuWaWsv",
-"Chuy3HzZT8","PYBf4Yh1hF","JIqXiIn3NS","U3yw5I7p2a","hi5X7djsrv","CK5W7lm0pD","k85AeIn3NS","iKqhrDQimp","DLhzMRmDcr","CIShGuvf7A",
-"lkMUAOHaBz","b29RJHP433","yvOMIQ6hMC","Pb1pa9eoRc","d85a9Z4I1v","zqH0WbZLvS","O3iyQhYBCK","ksJbyv1Hln","yEfy9i7WMQ","BpYhVQworu",
-"Yh1hFAmdQd","L7cGc5IhmG","d85a9tAOsr","oVQp6FwEJz","JIqXiWaim6","iwzGkix74r","pAhR1VjCZq","ksJbyM3zXL","45cIHydG8U","PYBf4FPfSE",
-"AmdQdGrDg7","55rfBAXpwE","b29RJRmDcr","OUYuFlpF6W","vkCHHgdQsS","AIYUuK20wK","fLNg88FmFH","tAOsrkB5nP","EdBKcK20wK","S77LHtl72W",
-"pmeCdCK5W7","jfREuAmdQd","5ZaEzlj07Q","pAhR1uPX7G","uvf7ApWiOs","S77LHuAWyp","xXTI4HRxd8","hSSvQFFDui","nlaByOxWIH","mX2GEF6PT2",
-"lViBvuJScX","CdyBVv1Hln","taOXKNxx9V","MojnPpAhR1","pvgjSMmKGJ","uupzkgf8rI","Mm8siO3iyQ","6AFT0O3iyQ","gf8rIjfREu","AOgEeMmKGJ",
-"1j5L8Mkgy8","UlU3MjzUqR","Twano8RCUA","yofH3l83Ud","WMiS35Namm","5iGN52Nslm","WreyPJKWYR","8U2nU0ao3l","3weIF0YAGH","UlU3MIjTwP",
-"UmaEvqQxHP","ydG8Ui3pyd","xXTI4kB5nP","HP433PYBf4","Dz1R3HlUbF","jtn0XcL0aE","NhXdu6AFT0","L7cGcogLgc","WmadA24ARF","fLNg8k85Ae",
-"WaWsvs7Mxk","Ul4a1lweGy","FPfSEFVMxo","1v5hHni2v1","7X3uybgJAz","yofH39y4lw","zY1GYgjUTu","iqv4kpiJSk","tAOsrSbRYy","IKxdLqaofN",
-"dpe1vpmeCd","zmLYDIjTwP","MaJQs9GXkX","3weIFQ6Lix","okgRioVQp6","Cfgr3uupzk","AkKTk9y4lw","pWiOsrz7Ut","lm0pDW7cTs","dhSuH7lUXZ",
-"ulk41piJSk","ZUnqtzz4ZU","blLA9L7cGc","7fKYUcQOnv","WDVWJ0h1b1","uPX7G55rfB","FLsph07n1c","FLsphqUJMd","AOgEeVNCPd","gf8rIpmeCd",
-"Cfgr3jiVBP","n8pJ9i7WMQ","ZJTXHI7p2a","5IhmGhE1Ql","6AFT0AgJHQ","oQ87rOz8yZ","pWiOsRpBQm","yluBxazIWp","YOfrYxXTI4","HzZT8BGaQY",
-"fqypy4dEz6","1LB1LSs0Zu","PYBf4W3VFH","n8pJ9uQIcz","OHaBzTCgPp","y94nwd7vjM","sx5GlFjHXR","CK5W77Ow5C","OUYuFAOgEe","KZamHThjNn",
-"JIqXihe9IA","qUJMdQWxoT","JIqXiAOgEe","ix74rguMb8","ni2v1GXdoH","GXdoHJRJQB","aez9ySbRYy","AXpwEcShY2","yToGWs93Ml","fLNg86q6L9",
-"GXdoHoQ87r","OxWIHix74r","he9IAlsQGo","QssNCguMb8","HfyNQS2Dfu","y94nwJXljW","DLhzMQYxC0","d7vjMbgJAz","tlILtbrhlQ","1j5L8v8yFN",
-"FjHXRQ6Lix","AkKTkL7cGc","M6qcGJJs5m","aL6AJ580YD","HP433JIqXi","dmoS7jfREu","GWqqXv2eC3","2hEEUiKqhr","v8yFNyvOMI","HzZT87Ow5C",
-"DG4sTQ6hMC","i3pydQ6Lix","Yf2EcW7cTs","I7p2ayofH3","Dz1R3TCgPp","XflUqOz8yZ","rz7UtkZANm","Yf2EcazIWp","ZuDtDydG8U","QYxC0nlaBy",
-"PYBf4vOqCE","GrDg7CqqaD","iqv4kP6bcg","faHirYjB9t","YjB9tpWiOs","BbwgACxVEf","oQ87rBFkb8","TCgPph1zcH","dpe1vi3pyd","x3LDeBGaQY",
-"CK5W7yluBx","oGu6xokgRi","ECMvUOz8yZ","NAFuwLDk6f","HzZT8WMiS3","45cIHVIlwP","m4bxU5Drn0","AXpwEm4bxU","tlILtFxX9q","Ss0Zu7lUXZ",
-"ogLgc5iGN5","hYBCKX6Pin","t98iWLewvM","JkzUnzY1GY","ydG8UECMvU","WMiS35ZaEz","lpF6WRkQke","1j5L8lCMxy","FGzgpn8pJ9","WPmlxEoToP",
-"mX2GEzQt6Q","xReecVjCZq","MaJQsSWfou","JJs5mXyPZN","FjHXRv1Hln","pT8wueuZA5","GSQwj7ku1p","zbIYYuTacx","HfyNQReKEW","Chuy3i3pyd",
-"ECMvUuupzk","jeskSx3LDe","aL6AJFcWrW","jzUqRYOfrY","pT8wuuPX7G","tvdkDDG4sT","aFFssEdBKc","9y4lwGXdoH","ix74rxXTI4","RzaZA2TRI7",
-"DcpWBdpe1v","2Yz7ESWfou","CK5W7x3LDe","lsQGo0ao3l","DG4sT8hJdt","zz4ZU9y4lw","hUTw7Cfgr3","5ZaEzCp3mZ","taOXKRBhp0","MmsIoAOgEe",
-"QssNCzz4ZU","jeskSoQ87r","vLsmSzFgtB","6AFT05ZaEz","okgRiReKEW","7X3uySWfou","hUTw7Q6hMC","DG4sTo8Uyd","1j5L8k85Ae","s93MlnnP8o",
-"MmKGJuQIcz","kB5nPFwEJz","v8yFNVerEA","fmIK1hUTw7","v8yFNZuDtD","fcwDauQIcz","RBhp0ThjNn","7fsYMNAFuw","MmsIogtCA5","v1HlnDQimp",
-"LbRTHrKDLJ","QWxoTaL6AJ","K20wKUl4a1","C2IrcDcpWB","JRJQBLbRTH","v2eC3BpYhV","1v5hH5Namm","0h1b1d7vjM","fqypyjfREu","aFFss0YAGH",
-"tl72WX6Pin","Ss0Zu2ZHdk","0MR5XydG8U","ulk41ECMvU","lCMxyZuDtD","8TxD7QWxoT","pmeCdAgJHQ","9iGoTNcICA","I7p2aMm8si","AOgEeB3qem",
-"BCxeCQYxC0","PYBf4I7p2a","P6bcg9XyT9","Zv7z02Nslm","No0QbzY1GY","lweGyaFFss","0ao3l8U2nU","xXTI4DQimp","cmXIXWMiS3","6AFT0t59lR",
-"MezSWM6qcG","DG4sTlXFOB","cmXIXgjUTu","VLTy6WaWsv","5IhmGOUqFM","sqVrffcwDa","MmKGJFFDui","WreyP5ZaEz","ru4UGd7vjM","AkKTkRACuj",
-"prNT6JIqXi","uZPqgh1zcH","RmDcrFhtgl","gjUTuECMvU","0MR5XAkKTk","14FLRiqv4k","oQ87rIjTwP","kB5nPd7vjM","W3VFHWmadA","GSQwjpFrrl",
-"RpBQm5IhmG","kZANmAgJHQ","L7cGcgIYvE","pmeCd55rfB","64s8NQChxs","uvf7AAOgEe","RBhp0hYBCK","QWxoTlpF6W","FNYIMEdBKc","n1pmOeuZA5",
-"WDVWJRkQke","zz4ZUfcwDa","n8pJ9jeskS","jtn0XJXljW","KASQ8zz4ZU","DG4sTn1pmO","tAOsrL7cGc","FVMxoZUnqt","x3LDeFFDui","JRJQBYOfrY",
-"8hJdtlsQGo","faHirs93Ml","StlDJK20wK","RsQUqFnPFB","SWfou2hEEU","9XyT9MGlTF","s93MlOHaBz","aez9yWaim6","CIShGRACuj","7hyVvZhwG1",
-"Pb1pazmLYD","WDVWJVBjhz","blLA9Kr8ys","QClRLvkCHH","hUTw7wiHrZ","zQt6Q8xEKz","jSjS3prNT6","y94nwWaWsv","zbIYYbgJAz","VBjhz9XyT9",
-"lj07QdhSuH","B3qemgtCA5","k85AeTXQ0Z","5nmWv3weIF","AXpwECdyBV","uZPqgx3LDe","Yw2oU5VZjS","MezSWpmeCd","k85AeAXpwE","0h1b1Y1mC0",
-"FVMxooVQp6","m4bxU618Di","Mkgy8Pb1pa","gtCA55Mg9r","M3zXLZv7z0","he9IAzHF1q","W3VFHQWxoT","ydG8UkB5nP","fcJOylH1kt","8xEKz3weIF",
-"cQOnvuoStw","1v5hHlkMUA","tAOsr4QMc9","qaofNFGzgp","iB08lxciqp","OxWIHP6bcg","0PktIAgJHQ","8U2nU5iGN5","BGaQYzHF1q","aez9yru4UG",
-"WaWsvvkCHH","Chuy3ZUnqt","6q6L9qaofN","gIYvEpiJSk","Pb1pa5Drn0","Mm8si0MR5X","dhSuH0Wr5y","VerEAEoToP","dmoS7v2eC3","2TRI72TRI7",
-"AmdQdGv3Fq","AgJHQoGu6x","IRh48OHaBz","WMiS3rz7Ut","lCMxys93Ml","7fsYMWaWsv","HfyNQpiJSk","lpF6WtvdkD","t98iWJXljW","bZLvS8xEKz",
-"ReKEW7lUXZ","yEfy9sx5Gl","Cfgr3WaWsv","0YAGHK4GS8","9XyT9IjTwP","QClRLSjskQ","zz4ZU4QMc9","lXFOBRkQke","pvgjSRzaZA","5IhmGgf8rI",
-"fLNg8J2mQi","lpF6WIKxdL","D6rByzz4ZU","7Ow5Cx3LDe","5IhmGAgJHQ","AOgEeEoToP","lkMUAUvlv4","RzaZAdpe1v","iqv4k48cHL","16lHc1LB1L",
-"lsQGozY1GY","m4bxUCK5W7","oVQp6d7vjM","U3yw5GXdoH","ni2v1MojnP","FwEJzZ4I1v","L7cGcIn3NS","lH1ktUmaEv","SmGzvAmdQd","aL6AJyofH3",
-"Oz8yZCIShG","24ARFRzaZA","FLsphFFDui","ReKEW8xEKz","fFDrJMmKGJ","s93Ml64s8N","d85a9VjCZq","pAhR1Twano","bgJAzbZLvS","atef21j5L8",
-"ix74rStlDJ","ogLgcvLsmS","lViBvAIYUu","2TRI7BbwgA","9eoRcpmeCd","OxWIHuAWyp","4dEz6cL0aE","gdQsSgjUTu","x3LDeNOHsz","HfyNQ5nmWv",
-"SbRYyVjCZq","HfyNQWaWsv","tAOsrhYBCK","Dz1R3okgRi","dmoS7zQt6Q","CK5W7GSQwj","14FLR8xEKz","jiVBPCK5W7","WreyP5nmWv","zmLYDyEfy9",
-"rz7Ut3weIF","yluBxKZamH","n1pmO7ku1p","zbIYYzmLYD","AOgEelH1kt","h1zcHVprf2","jiVBPZJTXH","YjB9tM6qcG","a00b5Y1mC0","uZPqgt59lR",
-"48cHLs93Ml","Yf2EceuZA5","LewvMpWiOs","8U2nU1LB1L","8cVD3QYxC0","3weIFxReec","vOqCEoGu6x","lCMxyKsjRK","v8yFNP6bcg","VIlwPFLsph",
-"3weIF4W0Tl","XyPZN5ZaEz","ZhwG1pv0i7","ThjNnGrDg7","VIlwPEOE1o","hE1Qlv1Hln","L7cGcNxx9V","CK5W7pvgjS","RACuje6e4z","8cVD3sqVrf",
-"DQimpSWfou","ZuDtDZuDtD","l83UdSWfou","DQimplCMxy","xciqpSmGzv","FLsphlkMUA","pFrrlNxx9V","nFqikkB5nP","Yw2oUGSQwj","IjTwPMkgy8",
-"yofH3djsrv","ThjNnlkMUA","OUqFMTCgPp","9XyT9rz7Ut","hYBCKQClRL","cL0aENAFuw","7hyVvKr8ys","aDGtScQOnv","2NslmjzUqR","n8pJ9QChxs",
-"9XyT9b29RJ","EOE1oIRh48","LDk6fStlDJ","ciuWzYjB9t","dmoS78TxD7","ZhwG1VIlwP","RACuj0Wr5y","fcwDaMmKGJ","lXFOB7fKYU","9XyT9XyPZN",
-"AmdQdMm8si","YjB9t618Di","5NammFnPFB","ni2v1azIWp","580YDRBhp0","hUTw7sx5Gl","QnJ1SfFDrJ","TXQ0ZpvgjS","580YDxReec","5drc6Yf2Ec",
-"nnP8oPOUYS","SWfouW7cTs","X6PinNxx9V","rz7UtWMiS3","yToGWyEfy9","jeskSFLsph","DQimpsx5Gl","v2eC3Fhtgl","RkQkeRpBQm","wDajXQworu",
-"lCMxyjeskS","5IhmGzQt6Q","Yf2EcAkKTk","CK5W7Cfgr3","Fhtgl7hyVv","jeskS0Kyfs","guMb87hyVv","IRh484QMc9","qUJMdMezSW","9GXkXtjQxs",
-"ReKEWzY1GY","7fKYUs4786","uZPqgFhtgl","O3iyQ9eoRc","ciuWzKr8ys","FnPFB9GXkX","dpe1vuJScX","2TRI7QYxC0","CdyBVOUYuF","lkMUA7hyVv",
-"AkKTkRsQUq","jS1ajWaWsv","1LB1L5nmWv","taOXKzqH0W","7Ow5CCxVEf","O3iyQYw2oU","618DiJkzUn","G1RhS7fsYM","7fKYUhYBCK","5Mg9r2Yz7E",
-"Vprf2In3NS","QbxXc3weIF","TwanoHP433","pv0i7lm0pD","iB08lrKDLJ","iqv4k24ARF","LDk6fjfREu","vkCHH64s8N","s93Mlk85Ae","ZUnqtuvf7A",
-"HRxd8VNCPd","No0QbFnPFB","0Wr5y8cVD3","BbwgAuN6r3","xReecVLTy6","gf8rI5Mg9r","9y4lw48cHL","tjQxs0BmCy","lsQGozbIYY","hUTw7tvdkD",
-"3weIF0PktI","rKDLJIjTwP","ogLgc7X3uy","ni2v1l83Ud","oQ87rpAhR1","0ao3ld85a9","zY1GYdpe1v","6q6L9brhlQ","5NammciuWz","tAOsrK4GS8",
-"Q6hMCMGlTF","JRJQBZuDtD","Mkgy88xEKz","yEfy9tlILt","ni2v17Ow5C","uN6r3i3pyd","uZPqgRzaZA","kZANmCqqaD","pmeCdCxVEf","jfREuNo0Qb",
-"uQIczZ4I1v","24ARFPb1pa","b29RJfLNg8","QnJ1SQWxoT","OxWIHjiVBP","S2Dfusoy9t","euZA5OxWIH","IBe8kSjskQ","FVMxoeuZA5","MojnP24ARF",
-"xXTI4x3LDe","iqv4ksoy9t","TCgPp9rlg9","0PktILewvM","2DREsiKqhr","yToGWGrDg7","No0Qb8RCUA","fqypyOz8yZ","MezSWlj07Q","kZANm16lHc",
-"lXFOBZUnqt","lCMxyX6Pin","OUYuF2ZHdk","LbRTHtaOXK","v8yFNpmeCd","4dEz64dEz6","ReKEWCfgr3","uN6r3iB08l","64s8N1v5hH","iB08lBCxeC",
-"Uvlv4UlU3M","6AFT0Oz8yZ","ix74rlsQGo","LbRTHlpF6W","yEfy9iB08l","4dEz6Uvlv4","IjTwPNo0Qb","Cfgr3RsQUq","uoStwDcpWB","v1HlnuTacx",
-"tjQxszFgtB","cmXIXUvlv4","618DiNhXdu","L7cGcGSQwj","l83UdaFFss","0ao3lZUnqt","ZhwG1uZPqg","AgJHQuPX7G","ydG8UCNHmv","aL6AJ2Yz7E",
-"v8yFNuQIcz","fmIK1euZA5","DQimp8TxD7","QChxs24ARF","t59lRFNYIM","xXTI4ksJby","Mm8siblLA9","HP4330Kyfs","VLTy6qQxHP","gtCA545cIH",
-"7X3uy9eoRc","CdyBV9y4lw","AOgEe5iGN5","Ss0ZuJJs5m","cShY2AgJHQ","prNT69XyT9","0KyfsFjHXR","n8pJ9iqv4k","xciqpFGzgp","CK5W7BbwgA",
-"aL6AJQ6Lix","iwzGkJIqXi","BbwgAlpF6W","yvOMIcmXIX","CdyBVHzZT8","FLsphFnPFB","he9IADLhzM","VBjhzYOfrY","oQ87rdhSuH","D6rBylkMUA",
-"FVMxokZANm","brhlQwDajX","blLA9soy9t","WMiS3BCxeC","RxrsmQbxXc","lCMxyyofH3","Oz8yZzQt6Q","wiHrZGXdoH","580YDIn3NS","tvdkDRmDcr",
-"uAWypv8yFN","JKWYRdjsrv","h1zcHDLhzM","tvdkDrhl0J","8RCUAIRh48","SjskQ8xEKz","5VZjS5IhmG","S77LHBFkb8","2hEEUuJScX","0Wr5yRxrsm",
-"U3yw5zFgtB","s7Mxk07n1c","VNCPduLtKs","In3NSazIWp","LbRTHYh1hF","AgJHQAXpwE","blLA9X6Pin","8U2nUni2v1","TXQ0ZmX2GE","y94nwMGlTF",
-"NhXdux3LDe","ZzJHWZ4I1v","cQOnvzHF1q","DcpWBCfgr3","ulk41uupzk","qaofNCK5W7","piJSkqaofN","jzUqRFVMxo","i7WMQNxx9V","CdyBVECMvU",
-"CxVEfGWqqX","piJSkHRxd8","n1pmOd7vjM","K20wKDG4sT","jtn0XnlaBy","ReKEWVNCPd","Z4I1vZzJHW","cQOnvQnJ1S","MojnPix74r","0PktItvdkD",
-"4QMc9ciuWz","CxVEf7fKYU","soy9twDajX","QChxsksJby","0MR5XjeskS","djsrvv1Hln","FGzgpNxx9V","k85AeEOE1o","Ul4a1QYxC0","uLtKsrhl0J",
-"i3pydUlU3M","U3yw5cQOnv","hE1QloQ87r","0BmCy0ao3l","C2IrcHRxd8","4QMc9ydG8U","yvOMIF6PT2","OUqFMDG4sT","Pb1paFcWrW","okgRi8TxD7",
-"jtn0X48cHL","AkKTkm4bxU","oQ87rpv0i7","FwEJzFFDui","lj07QZv7z0","Fhtglm4bxU","DLhzM8hJdt","W3VFHd85a9","ru4UGK20wK","FnPFB7lUXZ",
-"Fhtgl1LB1L","580YD7fKYU","RBhp0SmGzv","HRxd8nnP8o","9eoRc5VZjS","618DiFLsph","b29RJ2TRI7","lweGyv1Hln","0Wr5yIKxdL","M6qcGUlU3M",
-"7fKYUZuDtD","KsjRK9eoRc","ZhwG1RzaZA","9eoRcksJby","Q6Lix7fsYM","ZJTXHyEfy9","s7MxkC2Irc","zbIYY2Yz7E","hUTw77hyVv","tjQxs1j5L8",
-"MojnPIjTwP","cQOnvix74r","FcWrW2ZHdk","QnJ1SJkzUn","t59lRGSQwj","ni2v1pT8wu","QWxoT5ZaEz","lpF6WbrhlQ","uoStwjS1aj","S77LHyvOMI",
-"KZamHblLA9","oGu6xKZamH","aFFssMkgy8","pmeCdmz8gx","AOgEezmLYD","fLNg8AXpwE","8RCUAMK07Y","AmdQdsuY4x","XyPZNzbIYY","ZUnqtRACuj",
-"8RCUA16lHc","Gv3FqRpBQm","pmeCdJJs5m","6q6L9ulk41","sx5GlZhwG1","mz8gxv1Hln","xReecRzaZA","tjQxsx3LDe","WmadA9rlg9","lCMxykB5nP",
-"IKxdLvOqCE","EdBKc7Ow5C","Uvlv4Pb1pa","VerEAYjB9t","Nxx9VSs0Zu","K20wK5Namm","QWxoTZuDtD","m4bxUBbwgA","PYBf43weIF","7lUXZVprf2",
-"AOgEe0YAGH","pvgjSlViBv","uJScXM6qcG","fFDrJMGlTF","5iGN5lH1kt","tl72W16lHc","rhl0JCqqaD","U3yw5K20wK","xciqpYOfrY","ru4UGAXpwE",
-"4QMc9b29RJ","BFkb89eoRc","5VZjS0YAGH","YOfrYYOfrY","lXFOBzQt6Q","jiVBPy94nw","VerEAxReec","MGlTF5Namm","OHaBzGXdoH","7Ow5CpAhR1",
-"0Kyfsh1zcH","FxX9qtAOsr","lkMUAIRh48","5drc6RzaZA","5nmWvuZPqg","7hyVvfmIK1","fLNg8ydG8U","YOfrYiKqhr","dQ586AkKTk","cShY2brhlQ",
-"hSSvQS2Dfu","jzUqRCxVEf","Oz8yZlkMUA","jtn0XazIWp","sqVrfBCxeC","ix74rHlUbF","4dEz6NAFuw","FcWrW7fsYM","tAOsryEfy9","CIShGReKEW",
-"45cIHQYxC0","7lUXZWreyP","lkMUAQbxXc","FnPFBQnJ1S","AOgEedjsrv","MojnP6AFT0","MGlTFHlUbF","TwanotjQxs","ciuWz0BmCy","EOE1oBpYhV",
-"TwanoTXQ0Z","14FLRTwano","gjUTu0BmCy","EdBKcNAFuw","fcJOyxReec","8xEKz4dEz6","RzaZAFNYIM","prNT6fcJOy","DG4sTtjQxs","BFkb8Yw2oU",
-"WaWsvuJScX","xXTI45Mg9r","tl72WUvlv4","lViBvoQ87r","dmoS7LbRTH","sx5GlsuY4x","pmeCdYf2Ec","AIYUu5nmWv","oQ87rxciqp","xReecAkKTk",
-"s4786zHF1q","2Yz7EChuy3","uLtKsMK07Y","uupzkDG4sT","jSjS3sqVrf","iKqhrlj07Q","QYxC0iqv4k","RkQkeLbRTH","uTacxciuWz","ni2v1W3VFH",
-"fcJOyAgJHQ","s93MlMK07Y","zz4ZURACuj","lm0pDeuZA5","d7vjMfmIK1","fcJOyBCxeC","HP433ulk41","pvgjSvLsmS","uAWypWmadA","DG4sTsuY4x",
-"tuDySP6bcg","8xEKz5Namm","9y4lwpT8wu","BFkb8Qworu","t59lRKsjRK","NOHsz1v5hH","jtn0Xxciqp","qUJMd6AFT0","jeskSpT8wu","azIWp8TxD7",
-"24ARF7ku1p","sqVrfLbRTH","zY1GY24ARF","9XyT9rKDLJ","9y4lw9GXkX","gf8rIiqv4k","Yw2oUD6rBy","5Mg9rhi5X7","DcpWBMezSW","pv0i7Uvlv4",
-"i7WMQSbRYy","i7WMQIjTwP","aez9yGv3Fq","Ul4a1NOHsz","ogLgcWmadA","uAWypnFqik","i3pydDLhzM","uJScXFNYIM","kZANma00b5","M3zXLqaofN",
-"Ta8f6O3iyQ","M6qcGmX2GE","7hyVvpvgjS","Yf2EcZv7z0","faHirAkKTk","rKDLJuPX7G","9eoRcni2v1","qQxHPHzZT8","5VZjSTwano","zY1GYyEfy9",
-"ydG8UyvOMI","LDk6fv8yFN","GXdoHiKqhr","qUJMd618Di","zFgtBy94nw","NhXduiwzGk","29QAzdQ586","6q6L96q6L9","fFDrJMkgy8","5IhmGi7WMQ",
-"aez9yM3zXL","hSSvQlH1kt","ReKEWZJTXH","KZamHoGu6x","0KyfsIKxdL","0Wr5yCfgr3","5IhmGtaOXK","cQOnvNo0Qb","Ss0ZuTCgPp","G1RhSfmIK1",
-"yEfy9euZA5","wDajX0h1b1","l83Udxciqp","AOgEeOxWIH","qUJMdvLsmS","M3zXLvLsmS","n1pmOzqH0W","iqv4kPb1pa","hUTw7JKWYR","xXTI45nmWv",
-"RkQke7hyVv","AOgEeNOHsz","ZUnqtvLsmS","sx5Gl1v5hH","NcICAQ6Lix","zqH0WTXQ0Z","TCgPpW3VFH","ZJTXHdQ586","lViBvbZLvS","ZuDtD0h1b1",
-"7fKYUGSQwj","55rfBwiHrZ","tlILtMm8si","NcICAEOE1o","uvf7Ax3LDe","e6e4zv8yFN","vkCHH5VZjS","Cp3mZpv0i7","ZzJHWciuWz","MojnPaL6AJ",
-"lCMxy07n1c","CqqaDWreyP","45cIHoQ87r","lj07QHRxd8","PYBf42Nslm","HP43329QAz","vLsmS45cIH","ydG8URpBQm","0YAGHqQxHP","G1RhSm4bxU",
-"D6rBypmeCd","FFDuilViBv","wiHrZl83Ud","JRJQBpAhR1","45cIHC2Irc","FxX9qgf8rI","WPmlxtvdkD","GrDg764s8N","HRxd87hyVv","jSjS3oGu6x",
-"5iGN5x3LDe","BbwgANxx9V","9iGoTaL6AJ","gf8rICIShG","VNCPdAXpwE","FcWrWoGu6x","No0Qbrz7Ut","VerEAFhtgl","ulk41qaofN","jiVBPBFkb8",
-"VLTy6YOfrY","5Mg9r2TRI7","oGu6xdpe1v","I7p2adjsrv","pv0i7M6qcG","HP433xXTI4","KsjRKl83Ud","9rlg9618Di","IBe8kEdBKc","aDGtSFGzgp",
-"5NammlpF6W","LewvMy94nw","Q6hMCqQxHP","l83UdAmdQd","hi5X7b29RJ","Uvlv4cmXIX","uLtKsCxVEf","ECMvUcmXIX","S2Dfu0BmCy","FxX9q07n1c",
-"1j5L8YjB9t","i7WMQbrhlQ","s4786hUTw7","YjB9t2ZHdk","Uvlv4iqv4k","FxX9qqUJMd","uPX7GFNYIM","S2Dfu0Kyfs","tAOsrQworu","v2eC3lpF6W",
-"vLsmSZhwG1","dmoS7AXpwE","FnPFBhE1Ql","DG4sTJkzUn","0KyfsGXdoH","pT8wuMojnP","NAFuwuupzk","ix74rlj07Q","WPmlxazIWp","Q6LixNo0Qb",
-"VIlwPksJby","s93MlwDajX","NAFuwFFDui","guMb8ulk41","4QMc9tjQxs","ECMvUTa8f6","5VZjSmX2GE","jzUqRNo0Qb","jzUqRQ6hMC","OUYuF1v5hH",
-"29QAzCK5W7","xReecFGzgp","d7vjMVLTy6","euZA55drc6","JRJQB580YD","WreyPS2Dfu","LbRTHOUqFM","S77LHThjNn","faHirW7cTs","aFFsslH1kt",
-"jtn0XB3qem","FVMxoIBe8k","zz4ZU5VZjS","sqVrfaL6AJ","RpBQmk85Ae","m4bxU0h1b1","euZA5ru4UG","XyPZNFcWrW","hE1QlzHF1q","v2eC3vLsmS",
-"FxX9qpAhR1","Cfgr3Q6Lix","16lHcgIYvE","UlU3MjfREu","0YAGHix74r","BbwgACK5W7","uAWyp5VZjS","G1RhS580YD","ZJTXHbgJAz","NAFuw7ku1p",
-"fFDrJEoToP","L7cGcBCxeC","kZANmxXTI4","5Mg9rAgJHQ","WmadAfFDrJ","MK07YPb1pa","Waim6y94nw","618DitjQxs","8TxD7ReKEW","mX2GEk85Ae",
-"618DisqVrf","n8pJ9ThjNn","nFqikDG4sT","14FLRkB5nP","MaJQs0Wr5y","RsQUq0h1b1","RpBQm5Namm","fcwDauAWyp","8cVD3pmeCd","Cp3mZoGu6x",
-"WreyPpv0i7","DcpWBAIYUu","lkMUAuJScX","fFDrJl83Ud","HlUbFrz7Ut","Oz8yZKr8ys","GWqqXuTacx","VIlwPfqypy","HfyNQcmXIX","GrDg7MK07Y",
-"yluBxIn3NS","pFrrl8cVD3","JKWYRM3zXL","EOE1o6q6L9","OUYuF8cVD3","5NammCqqaD","uAWypVerEA","SbRYyix74r","kB5nPI7p2a","MezSWlm0pD",
-"rhl0JuTacx","AOgEe64s8N","M6qcG7hyVv","48cHLd85a9","uZPqgAIYUu","8RCUAlkMUA","TXQ0Zy94nw","QnJ1SrKDLJ","pv0i72hEEU","5Mg9rpFrrl",
-"Dz1R3Mkgy8","rz7UtogLgc","QworuAmdQd","AmdQdgtCA5","v2eC3bZLvS","hYBCKni2v1","ECMvUUvlv4","DG4sTG1RhS","ni2v1tuDyS","uPX7GjS1aj",
-"FPfSEuZPqg","tlILtazIWp","l83UdUmaEv","lH1kthSSvQ","jS1ajFjHXR","euZA5dpe1v","uPX7GW3VFH","FPfSEokgRi","n1pmOs7Mxk","n1pmOEdBKc",
-"No0QbtlILt","nlaByEoToP","rz7Uthe9IA","2DREsBGaQY","QChxsHRxd8","zmLYDMojnP","l83UdyluBx","AmdQdAOgEe","MK07YJIqXi","MaJQsdQ586",
-"QbxXcv8yFN","ThjNnMGlTF","FxX9qDQimp","CxVEfCfgr3","TCgPpNOHsz","uAWyp7X3uy","RBhp0Q6hMC","9eoRc7lUXZ","ciuWztl72W","ru4UGAgJHQ",
-"7fsYM2TRI7","jtn0Xn1pmO","WMiS30MR5X","n8pJ9v1Hln","ReKEWAXpwE","guMb8qQxHP","0BmCyKZamH","DG4sTRBhp0","0BmCy2Yz7E","HRxd8s4786",
-"uTacxU3yw5","gjUTuguMb8","HfyNQL7cGc","iwzGk0Kyfs","VLTy6uN6r3","CNHmvgf8rI","48cHL5IhmG","sx5Gly94nw","ZUnqtMojnP","CqqaD0Kyfs",
-"lH1ktxXTI4","GWqqX5VZjS","ReKEWOxWIH","Oz8yZZUnqt","ECMvUGrDg7","W3VFHNOHsz","oQ87rlweGy","zbIYYSmGzv","uZPqgFLsph","CNHmvk85Ae",
-"8xEKzgdQsS","07n1c45cIH","uJScX618Di","0ao3lDz1R3","TXQ0ZD6rBy","lpF6WzY1GY","mX2GE5drc6","2DREs2ZHdk","uJScXMaJQs","BGaQYuJScX",
-"ciuWzOxWIH","ECMvUHP433","Cp3mZk85Ae","TwanoyToGW","J2mQituDyS","uoStwlViBv","SbRYyM3zXL","aL6AJQWxoT","K4GS87lUXZ","d7vjM5IhmG",
-"Yf2EcQnJ1S","jtn0XRkQke","MK07YNOHsz","RmDcrKr8ys","pT8wuuoStw","NOHszbrhlQ","WMiS3ZuDtD","5iGN5qUJMd","No0QbtAOsr","2hEEUPYBf4",
-"d85a9FPfSE","e6e4zCqqaD","VLTy6lm0pD","JIqXi7X3uy","uAWyptlILt","D6rByX6Pin","GrDg7OHaBz","euZA5euZA5","d7vjMReKEW","No0Qbix74r",
-"ydG8UBCxeC","aL6AJaFFss","ZzJHWv1Hln","Oz8yZRzaZA","l83Ud2DREs","yvOMICdyBV","pvgjS7fsYM","lsQGouTacx","GSQwjfcJOy","qQxHPlXFOB",
-"WMiS38hJdt","FNYIMLbRTH","zmLYDVIlwP","IRh480BmCy","HRxd8RzaZA","3weIFs93Ml","WaWsvo8Uyd","I7p2ab29RJ","JJs5mrhl0J","qaofN5iGN5",
-"8hJdtlweGy","xciqphe9IA","618Di64s8N","t98iWcL0aE","aDGtSuQIcz","yvOMIDLhzM","MezSWOz8yZ","tjQxsGXdoH","tAOsrwiHrZ","ZzJHW0BmCy",
-"45cIH29QAz","ydG8U6q6L9","gtCA5BFkb8","rhl0Jv2eC3","k85Ae0PktI","5nmWvIn3NS","hi5X7d85a9","BpYhV0ao3l","HlUbFMK07Y","XyPZN0ao3l",
-"5Mg9r8TxD7","i3pydcmXIX","QChxsWreyP","xciqpyvOMI","lViBv4W0Tl","v8yFN7X3uy","qQxHPRxrsm","RmDcrb29RJ","zbIYYjiVBP","fcJOy29QAz",
-"lH1ktQYxC0","0MR5XGWqqX","djsrv2Nslm","VerEAn1pmO","KZamHIKxdL","XyPZNbZLvS","16lHcVIlwP","M6qcGStlDJ","MezSWuvf7A","J2mQiHzZT8",
-"ulk417hyVv","Waim60BmCy","Gv3FqGrDg7","CqqaDxXTI4","GXdoHW7cTs","Nxx9VC2Irc","RmDcrUl4a1","HzZT8FwEJz","W7cTsHRxd8","WPmlxdQ586",
-"cQOnvOxWIH","16lHcblLA9","qUJMdQClRL","EoToPtuDyS","618DiyofH3","BCxeClXFOB","GWqqXMmsIo","5drc6cQOnv","X6PinRBhp0","h1zcHCfgr3",
-"euZA5NOHsz","dpe1vAIYUu","5iGN5fFDrJ","JXljWy94nw","brhlQ9iGoT","pAhR116lHc","5IhmG8cVD3","45cIHuN6r3","SbRYydjsrv","Nxx9VVprf2",
-"aFFssD6rBy","FVMxoJRJQB","0MR5X8RCUA","yvOMISjskQ","uvf7ARBhp0","RzaZA2ZHdk","MmKGJWMiS3","qQxHPYjB9t","RzaZANxx9V","i7WMQ8RCUA",
-"zQt6QGXdoH","9iGoTaDGtS","X6Pin0h1b1","pAhR1OxWIH","3weIFFhtgl","pWiOs4dEz6","gdQsS2Nslm","lH1ktWMiS3","QnJ1SoVQp6","W3VFHfaHir",
-"1v5hH4dEz6","QYxC0MezSW","YOfrYzqH0W","MK07YFPfSE","zqH0W64s8N","prNT6ZUnqt","h1zcHiwzGk","lsQGoReKEW","aDGtSVNCPd","SmGzvRACuj",
-"6AFT0yofH3","RmDcrfFDrJ","zbIYYQ6Lix","7fKYUZUnqt","JRJQBRzaZA","CqqaDxReec","Y1mC0uZPqg","uoStwv8yFN","fFDrJsqVrf","580YDeuZA5",
-"3weIFlpF6W","WDVWJl83Ud","AIYUuiKqhr","FjHXR8U2nU","y94nwlsQGo","ZzJHWCNHmv","ZUnqtLbRTH","SbRYyO3iyQ","hSSvQJRJQB","RzaZAlViBv",
-"SjskQtlILt","2ZHdk1v5hH","2DREspvgjS","Yw2oUVerEA","jSjS3vkCHH","NAFuwKsjRK","WPmlxoQ87r","2ZHdkFhtgl","FGzgpni2v1","m4bxUFxX9q",
-"pFrrlydG8U","J2mQiJIqXi","6AFT0QYxC0","HfyNQkZANm","ZJTXHwiHrZ","0PktIzFgtB","7Ow5CMkgy8","GSQwjxciqp","QnJ1SyToGW","hE1QlPOUYS",
-"HlUbFnlaBy","SmGzvIn3NS","7fsYMtlILt","1LB1LpiJSk","gtCA5o8Uyd","jeskSksJby","JJs5m5IhmG","Z4I1vCxVEf","OUqFMRxrsm","K4GS85ZaEz",
-"hYBCKzFgtB","07n1cECMvU","9GXkXQ6hMC","FGzgpQYxC0","0MR5XZhwG1","faHirTCgPp","CK5W7Twano","AgJHQoQ87r","AkKTkNAFuw","Cp3mZxXTI4",
-"I7p2aCIShG","9eoRcEoToP","O3iyQpFrrl","ZhwG1WmadA","5ZaEzfFDrJ","t98iWDQimp","MmsIod7vjM","iB08lOUqFM","lpF6WFFDui","BCxeCSmGzv",
-"O3iyQAOgEe","TwanoQworu","UmaEvfcwDa","FnPFBa00b5","hYBCKeuZA5","rhl0Jy94nw","5drc6K20wK","cmXIXAOgEe","K4GS8ciuWz","zbIYYMkgy8",
-"ECMvUCfgr3","faHiraL6AJ","fFDrJHP433","EOE1oaL6AJ","Uvlv4s93Ml","Ta8f64QMc9","7X3uyVerEA","Waim65iGN5","MGlTF8xEKz","HfyNQ8TxD7",
-"uupzk8cVD3","hi5X7Oz8yZ","3weIFcShY2","xciqpcShY2","t59lRfqypy","8RCUAuLtKs","GrDg7zFgtB","FFDuiiwzGk","UlU3MjeskS","Ta8f6Qworu",
-"uTacxD6rBy","NhXduhYBCK","5Drn0FFDui","9y4lwvLsmS","AgJHQBGaQY","WMiS3PYBf4","yEfy9GWqqX","DQimpO3iyQ","EoToPThjNn","nnP8oOUqFM",
-"rz7Ut9eoRc","5VZjSNAFuw","0MR5XIBe8k","ru4UGTwano","zQt6QzbIYY","P6bcgAOgEe","FNYIMP6bcg","i7WMQe6e4z","MK07YNhXdu","J2mQiI7p2a",
-"gf8rI0Kyfs","mX2GENcICA","VjCZqtlILt","8U2nUWPmlx","uN6r38U2nU","VerEAbZLvS","rKDLJ55rfB","BCxeCQ6Lix","vkCHHfaHir","0KyfszY1GY",
-"CK5W7SbRYy","OxWIHCfgr3","aFFssjiVBP","Z4I1vtlILt","lXFOBcmXIX","JIqXidmoS7","fmIK17fKYU","WDVWJoVQp6","K4GS85Namm","Dz1R35nmWv",
-"J2mQii7WMQ","n1pmOzFgtB","sqVrft59lR","t59lRi3pyd","Oz8yZCp3mZ","5VZjSJJs5m","nFqik2Yz7E","xReeculk41","NcICAWmadA","d7vjMVBjhz",
-"dmoS7HzZT8","2Yz7EmX2GE","5nmWvsoy9t","5Drn0MmKGJ","uPX7GChuy3","MK07YlkMUA","5Drn0ReKEW","7ku1pZv7z0","RBhp0uQIcz","2Yz7ESbRYy",
-"DG4sTZzJHW","iKqhrDcpWB","yToGWlsQGo","KZamHcL0aE","EOE1ob29RJ","AgJHQAkKTk","s7MxkIBe8k","oQ87rECMvU","lpF6Wgf8rI","QChxs16lHc",
-"S2DfulViBv","uLtKs9GXkX","uvf7Asx5Gl","GSQwjBbwgA","jiVBPRpBQm","KZamHni2v1","0MR5XZuDtD","OUqFMaDGtS","AOgEeQnJ1S","gf8rIWaWsv",
-"uvf7A9GXkX","fqypyFxX9q","MmsIov8yFN","pmeCdxciqp","dQ586NAFuw","DLhzM8U2nU","5drc6azIWp","8FmFHAIYUu","ZUnqtpAhR1","ZzJHWIjTwP",
-"i7WMQUlU3M","m4bxUxciqp","HzZT8FLsph","3weIFS77LH","DG4sTcL0aE","0PktINo0Qb","9eoRc2Yz7E","RpBQmvOqCE","EOE1olCMxy","azIWpatef2",
-"8TxD70MR5X","he9IA7X3uy","RkQkezY1GY","mX2GEChuy3","64s8Nd85a9","NcICAOz8yZ","7ku1pfcwDa","Yw2oUcShY2","7hyVvX6Pin","Yh1hFni2v1",
-"AIYUuKASQ8","ulk41tAOsr","jzUqRMmsIo","O3iyQZJTXH","U3yw5YOfrY","aFFssBbwgA","VNCPdHzZT8","0h1b1UlU3M","8U2nU7fKYU","pAhR1AkKTk",
-"VjCZq5nmWv","fFDrJJKWYR","cQOnvhi5X7","lm0pDjeskS","jfREuXflUq","AmdQdCNHmv","ix74rIn3NS","soy9tBFkb8","zFgtBiqv4k","NOHszXflUq",
-"fcJOyKsjRK","5IhmGDG4sT","dmoS70MR5X","yToGWlm0pD","9XyT95VZjS","8xEKztuDyS","U3yw55ZaEz","nFqikvkCHH","pv0i79XyT9","cShY2fcJOy",
-"vLsmS6q6L9","7lUXZiB08l","QChxsjtn0X","AOgEeRBhp0","FFDuiQClRL","EdBKcXyPZN","3otm6Gv3Fq","dQ58648cHL","BGaQYRpBQm","WmadAY1mC0",
-"07n1cRpBQm","FLsphPYBf4","LbRTH2Yz7E","CdyBVzbIYY","OUqFM0ao3l","oQ87rVprf2","mz8gx0MR5X","7hyVvTa8f6","0YAGHzFgtB","8xEKzvOqCE",
-"KZamHhe9IA","RsQUqKsjRK","WreyPF6PT2","Z4I1vWaWsv","pT8wuM6qcG","uTacxTa8f6","uupzkaDGtS","Cfgr3QnJ1S","SWfouokgRi","WmadAuZPqg",
-"FNYIMjeskS","QChxsThjNn","cShY2NOHsz","uTacx8TxD7","WreyPBCxeC","QWxoTD6rBy","Qworu16lHc","XyPZNS77LH","0BmCyQssNC","FPfSEBGaQY",
-"ReKEW24ARF","9XyT9JRJQB","Rxrsm4dEz6","mz8gx9XyT9","9rlg9uoStw","v1HlnHzZT8","9iGoTazIWp","FnPFBzHF1q","sx5GlVprf2","fLNg8zz4ZU",
-"AIYUuJKWYR","UlU3MtjQxs","QnJ1SMm8si","JRJQBWPmlx","Dz1R3pAhR1","RACujLewvM","Q6Lixuupzk","SbRYyCdyBV","VerEARBhp0","iwzGk8xEKz",
-"QYxC0ni2v1","bZLvSSs0Zu","hUTw7DLhzM","i3pyd4W0Tl","v1HlnzqH0W","iwzGkRpBQm","5nmWv2Nslm","8U2nUwDajX","iKqhrWPmlx","lCMxy4QMc9",
-"K20wK4W0Tl","Ta8f6wDajX","WaWsvZJTXH","4dEz63otm6","i3pydvOqCE","i7WMQcmXIX","hUTw7hUTw7","C2IrcVIlwP","ZhwG1he9IA","sx5GlVjCZq",
-"BpYhVFGzgp","FLsphGXdoH","KsjRKNhXdu","EoToPaDGtS","IBe8kxXTI4","soy9tdjsrv","Mm8siFcWrW","zmLYD9eoRc","MezSWtlILt","C2IrclH1kt",
-"cmXIXCxVEf","SmGzvbrhlQ","WMiS3hUTw7","WPmlxs93Ml","OUYuFzHF1q","gjUTuuTacx","Ss0Zu7fsYM","9iGoTJJs5m","QbxXc8cVD3","xXTI4pvgjS",
-"CIShGQWxoT","iB08l5ZaEz","zQt6QTa8f6","Mkgy8mz8gx","FLsphU3yw5","X6Pinsx5Gl","Chuy3oGu6x","hUTw7yvOMI","prNT6K4GS8","yToGWni2v1",
-"xXTI42Nslm","wiHrZv1Hln","oVQp6LewvM","GSQwj0YAGH","0Wr5yHlUbF","ru4UG8xEKz","JRJQB618Di","tvdkDvkCHH","55rfBCK5W7","JXljWjiVBP",
-"HlUbFqUJMd","RACujAkKTk","ZUnqtzqH0W","QssNChSSvQ","dQ586Yf2Ec","NcICAMezSW","BpYhVokgRi","Mm8siJXljW","YjB9tGWqqX","VIlwP1j5L8",
-"aL6AJNcICA","nFqikChuy3","AgJHQBCxeC","I7p2a9iGoT","v2eC3IjTwP","gf8rIVNCPd","bgJAzfcwDa","Ss0ZuVNCPd","Gv3FqAIYUu","NhXduhE1Ql",
-"i7WMQGv3Fq","n1pmOYf2Ec","vkCHHcShY2","24ARFNcICA","S77LHMmsIo","QworuS2Dfu","6q6L9pmeCd","DLhzMcmXIX","guMb8AkKTk","KsjRK48cHL",
-"ulk41XyPZN","l83Ud9XyT9","5VZjSPb1pa","pv0i7RACuj","X6PinHP433","B3qemni2v1","rKDLJQWxoT","tAOsr5Namm","a00b5GWqqX","NAFuwlViBv",
-"tl72WKsjRK","i3pydd85a9","xciqpciuWz","oGu6x7ku1p","0h1b1ni2v1","azIWpzQt6Q","vLsmSMK07Y","ReKEWLbRTH","POUYS4W0Tl","dmoS78hJdt",
-"hSSvQxXTI4","oGu6xfFDrJ","fcJOyoGu6x","sqVrfnnP8o","Q6hMCn8pJ9","AkKTk7Ow5C","s4786lsQGo","5Mg9rHfyNQ","TXQ0Z618Di","qUJMdXflUq",
-"Ul4a1uupzk","FFDuiRACuj","uLtKstuDyS","FVMxohYBCK","5NammuN6r3","KsjRKYOfrY","uLtKsNcICA","WaWsvLbRTH","4dEz60BmCy","ogLgcdQ586",
-"hUTw7suY4x","pT8wuHfyNQ","ksJbys93Ml","zmLYDMm8si","VNCPd1v5hH","qaofN7lUXZ","zQt6Q1v5hH","SWfoubrhlQ","azIWpK20wK","djsrvjfREu",
-"fLNg8b29RJ","IRh48ix74r","MK07YDG4sT","xXTI4jSjS3","e6e4z7X3uy","9XyT9zQt6Q","J2mQiDz1R3","OUYuFjtn0X","5drc61LB1L","blLA9s93Ml",
-"16lHcM6qcG","FNYIMAmdQd","IRh48qaofN","pvgjSAgJHQ","tAOsrKr8ys","gjUTuNOHsz","aFFssHfyNQ","8xEKzDLhzM","AkKTkydG8U","8TxD7dhSuH",
-"lkMUARpBQm","v2eC3prNT6","ogLgcjS1aj","64s8N8FmFH","aDGtSG1RhS","AkKTkk85Ae","wDajXM3zXL","tAOsrxReec","Yh1hFZhwG1","KsjRK0Wr5y",
-"EoToP7fsYM","uPX7G4W0Tl","Gv3FqmX2GE","wDajXNOHsz","cQOnvhe9IA","SmGzvxReec","DQimpHlUbF","dmoS7RsQUq","ZhwG1QChxs","WDVWJ7hyVv",
-"yluBxYjB9t","rhl0Ja00b5","Oz8yZix74r","xXTI4Dz1R3","Pb1paoGu6x","ogLgcQChxs","7X3uyZzJHW","FwEJzW7cTs","uZPqghE1Ql","bgJAzMezSW",
-"Mm8si618Di","5iGN5tjQxs","MGlTFuPX7G","he9IAAkKTk","EOE1o2TRI7","IKxdL0BmCy","FjHXREoToP","Vprf22Yz7E","CNHmvDz1R3","yToGWsx5Gl",
-"WmadAFFDui","BbwgAKsjRK","l83UdogLgc","CqqaDRsQUq","IKxdLRmDcr","RBhp0vLsmS","6AFT0Mm8si","IjTwPChuy3","XyPZN14FLR","YOfrYTa8f6",
-"Cfgr3cL0aE","5ZaEzOHaBz","QbxXcZUnqt","K4GS8s4786","SmGzvS2Dfu","B3qemlj07Q","0PktIRBhp0","OUqFMv1Hln","rhl0JQWxoT","mz8gxb29RJ",
-"oGu6xzqH0W","uPX7G0Wr5y","C2IrchSSvQ","6AFT0aFFss","hSSvQFnPFB","OxWIHlj07Q","J2mQisx5Gl","ru4UG0MR5X","UlU3MqUJMd","uJScXsx5Gl",
-"K20wKvkCHH","8RCUAgtCA5","2DREsUvlv4","5Mg9rvLsmS","3otm6Chuy3","fcJOyt59lR","IBe8k3otm6","Chuy3pAhR1","xReecC2Irc","45cIHzqH0W",
-"HzZT816lHc","ksJbyuvf7A","JKWYRQssNC","jiVBPZhwG1","FVMxo9XyT9","fFDrJ64s8N","zqH0W0h1b1","zmLYDuQIcz","l83Ud9GXkX","lj07QpiJSk",
-"WaWsvTCgPp","prNT6b29RJ","0YAGH8U2nU","zqH0WdmoS7","SbRYy3otm6","cQOnvokgRi","HlUbFgIYvE","oGu6xuZPqg","pFrrlpiJSk","M6qcGUl4a1",
-"RmDcrK20wK","lkMUAwDajX","GXdoHJXljW","OxWIHnnP8o","JKWYRWMiS3","5nmWvvkCHH","bgJAzgdQsS","rhl0JThjNn","F6PT2F6PT2","h1zcH6AFT0",
-"yofH38U2nU","0Wr5yLbRTH","Mm8siuLtKs","AkKTkjeskS","CdyBVcShY2","oGu6xiKqhr","Chuy3fcJOy","AXpwEFnPFB","lm0pDatef2","0KyfsdQ586",
-"Yw2oUQ6hMC","IKxdLjzUqR","sqVrfHzZT8","zQt6QTCgPp","HP433Z4I1v","tvdkD618Di","5NammKASQ8","FwEJzO3iyQ","zz4ZUWreyP","tAOsrfFDrJ",
-"iqv4kEoToP","AkKTkEdBKc","5Mg9r07n1c","QworurKDLJ","VBjhzyToGW","9rlg9VLTy6","qUJMdSmGzv","KZamHZzJHW","8RCUAhUTw7","C2IrcuQIcz",
-"TwanoWaWsv","AIYUuzqH0W","WreyPMK07Y","IBe8kAXpwE","M6qcGfcwDa","NcICA45cIH","qQxHPCK5W7","ZzJHWuQIcz","ReKEW6AFT0","wDajXC2Irc",
-"5Mg9r0ao3l","8FmFHlXFOB","xXTI4EdBKc","QworuciuWz","1LB1LzbIYY","0PktIReKEW","yvOMIQnJ1S","ksJbySbRYy","uLtKs2TRI7","IjTwPtAOsr",
-"fFDrJyvOMI","9XyT9taOXK","Ta8f6IjTwP","kB5nPWMiS3","s7Mxkulk41","uAWypI7p2a","v8yFN0YAGH","ogLgcK20wK","CqqaD8xEKz","e6e4z5Drn0",
-"OUqFMGv3Fq","7fsYMlpF6W","JXljWuN6r3","VjCZqFNYIM","qUJMduTacx","OUYuFt98iW","ZzJHWCIShG","gtCA5lH1kt","jzUqRCNHmv","6q6L99GXkX",
-"i7WMQBFkb8","lXFOB5IhmG","580YDpFrrl","n1pmOlViBv","W3VFH9GXkX","pT8wuIRh48","QworuW7cTs","NOHszQbxXc","pFrrlHP433","kZANm7fKYU",
-"HfyNQYOfrY","K4GS8O3iyQ","dmoS7rz7Ut","24ARFzHF1q","cL0aEQYxC0","AIYUu2Nslm","W7cTsQWxoT","iwzGkjiVBP","zmLYDyvOMI","uZPqgUvlv4",
-"fFDrJUmaEv","xReecBGaQY","IjTwPrhl0J","kB5nPe6e4z","2Yz7EfmIK1","uTacxn8pJ9","DcpWBt98iW","AgJHQ4QMc9","gjUTuYjB9t","IRh48LewvM",
-"jS1ajLewvM","JIqXiJJs5m","OUYuFhSSvQ","pAhR1JJs5m","IRh48xXTI4","7hyVvQssNC","C2IrcpT8wu","9eoRcJRJQB","yluBxuPX7G","jfREuYjB9t",
-"M3zXL2hEEU","jeskSFxX9q","oVQp6prNT6","6AFT0zqH0W","S2DfuAmdQd","zz4ZUP6bcg","zbIYYdjsrv","iKqhrTXQ0Z","euZA5soy9t","jtn0XpiJSk",
-"LewvM1LB1L","uLtKsRBhp0","lsQGo3otm6","v8yFN29QAz","29QAzNxx9V","MojnPSjskQ","mz8gxJKWYR","MaJQsQYxC0","0PktIW7cTs","uLtKsGrDg7",
-"uAWyp5Mg9r","djsrvZzJHW","wDajXjtn0X","cL0aESs0Zu","xReecQWxoT","M3zXL8TxD7","iqv4k5iGN5","EdBKc8cVD3","07n1cIn3NS","DG4sTTXQ0Z",
-"v8yFNNo0Qb","JIqXiU3yw5","y94nwuupzk","yEfy9tuDyS","Mm8silCMxy","b29RJt98iW","B3qemO3iyQ","dpe1v5ZaEz","CdyBVprNT6","8cVD35iGN5",
-"aL6AJokgRi","0MR5XTa8f6","3weIFZzJHW","pvgjSe6e4z","AgJHQqQxHP","7hyVvpWiOs","HlUbFECMvU","TwanojiVBP","y94nw0h1b1","AXpwEO3iyQ",
-"2hEEUCNHmv","J2mQiJXljW","Yf2EcJ2mQi","jzUqRzQt6Q","mz8gxRsQUq","pv0i75drc6","MGlTFAmdQd","mX2GE5IhmG","qQxHPlH1kt","4QMc9QClRL",
-"9XyT9hi5X7","vkCHHSbRYy","FGzgpHP433","NOHszFjHXR","mX2GECqqaD","VerEAsoy9t","RBhp04W0Tl","POUYSZzJHW","WaWsvUlU3M","iKqhr8xEKz",
-"0h1b1ThjNn","Zv7z0tlILt","FxX9qzz4ZU","4QMc90Wr5y","X6Pinv1Hln","sqVrfBFkb8","OUqFMReKEW","7X3uyWMiS3","QChxs1v5hH","cQOnv1LB1L",
-"hUTw7uJScX","AkKTkn8pJ9","AgJHQGWqqX","ru4UGY1mC0","WreyPrKDLJ","SWfou9rlg9","iwzGkQClRL","WaWsvuTacx","ydG8UKZamH","1j5L8UmaEv",
-"iB08lhe9IA","HP4335Mg9r","RmDcr8xEKz","Ul4a1JkzUn","F6PT2WmadA","qaofNuTacx","lpF6WS77LH","d85a95drc6","1LB1LQ6hMC","d85a9KASQ8",
-"sx5GlHP433","AOgEeX6Pin","9iGoT0YAGH","pAhR1dpe1v","d85a9L7cGc","3weIFUl4a1","nlaByM3zXL","Dz1R35Namm","RmDcrkB5nP","bZLvSMezSW",
-"n8pJ9Pb1pa","2ZHdkMaJQs","16lHcFGzgp","BGaQYBGaQY","zY1GYazIWp","cmXIXix74r","ECMvUciuWz","IKxdLzY1GY","djsrvRzaZA","ZJTXHJkzUn",
-"7Ow5CIRh48","FLsphlXFOB","nnP8o3otm6","RzaZAksJby","9GXkXpmeCd","s7MxkQClRL","uLtKs07n1c","wDajXLDk6f","JXljWCK5W7","Cp3mZWDVWJ",
-"POUYSjiVBP","0h1b1aDGtS","MezSWIBe8k","FFDuiCp3mZ","EdBKc1j5L8","0PktIHfyNQ","mz8gx7fKYU","JIqXiUl4a1","4dEz6Chuy3","1v5hHn1pmO",
-"9rlg9ZuDtD","EdBKcbgJAz","Mm8si6AFT0","FGzgpazIWp","dQ586jS1aj","gdQsS2TRI7","8hJdt7X3uy","AXpwEPYBf4","yluBxNo0Qb","4dEz6kZANm",
-"tAOsrtl72W","oQ87rSWfou","pv0i7dmoS7","k85Ae3otm6","07n1c6AFT0","m4bxUlpF6W","d85a9HRxd8","ZuDtDzHF1q","0Wr5yh1zcH","Ss0ZuDQimp",
-"ReKEWBbwgA","POUYSThjNn","DcpWBWaWsv","ZUnqtfaHir","BbwgABbwgA","ksJbyatef2","MaJQsChuy3","okgRiMGlTF","GWqqXt59lR","F6PT2aez9y",
-"9rlg9NAFuw","xXTI4tAOsr","O3iyQuoStw","K4GS8prNT6","YOfrYZJTXH","In3NS7lUXZ","v2eC3n8pJ9","qaofN1j5L8","9GXkX7hyVv","suY4xSbRYy",
-"rhl0JOz8yZ","kZANm8xEKz","ksJbyRBhp0","ni2v11v5hH","MGlTF07n1c","n1pmOmX2GE","KASQ8Cp3mZ","5Mg9r45cIH","DLhzMGSQwj","2NslmFFDui",
-"2ZHdkt59lR","gtCA5CIShG","9rlg99rlg9","RpBQmdjsrv","uZPqg14FLR","gf8rI3otm6","fcJOyC2Irc","uoStwdmoS7","ThjNn2hEEU","x3LDejS1aj",
-"0h1b1J2mQi","IjTwPDcpWB","d85a9Cp3mZ","xReecXyPZN","SWfou8xEKz","WDVWJpv0i7","cL0aEAIYUu","zqH0Wi3pyd","W3VFHs7Mxk","QChxsjzUqR",
-"hSSvQP6bcg","JXljW9iGoT","FnPFBIBe8k","Mm8siUlU3M","CxVEfo8Uyd","ksJbyOUYuF","VerEAFPfSE","taOXKAOgEe","Pb1pak85Ae","M6qcGvkCHH",
-"ciuWzLbRTH","LDk6fJRJQB","No0QbJXljW","OUYuFbgJAz","8U2nUIRh48","uPX7GNcICA","xXTI4LDk6f","pFrrl5drc6","1j5L8RkQke","zz4ZUNAFuw",
-"pAhR1uTacx","QChxsOz8yZ","2ZHdkbrhlQ","v8yFNNAFuw","5iGN5Q6Lix","IjTwPpv0i7","64s8Ns93Ml","gIYvEM6qcG","QClRLpT8wu","n1pmOatef2",
-"S77LHZ4I1v","9iGoTlpF6W","7X3uyQChxs","AOgEevOqCE","B3qemaDGtS","iqv4kuQIcz","AkKTkl83Ud","0Wr5yydG8U","9eoRceuZA5","blLA9QClRL",
-"0Wr5yO3iyQ","IKxdL8TxD7","SjskQ1j5L8","MezSWzY1GY","AkKTkWPmlx","AOgEeydG8U","QbxXc2Nslm","9eoRcFLsph","kB5nP1LB1L","JXljWVprf2",
-"7fKYURsQUq","ru4UGRpBQm","0MR5XI7p2a","9rlg9ThjNn","gjUTuQ6hMC","e6e4zWPmlx","K20wKDQimp","t59lRPOUYS","AkKTk618Di","cShY2gtCA5",
-"BCxeCZuDtD","Vprf2blLA9","SmGzv8U2nU","7hyVvdpe1v","RpBQmlj07Q","lsQGoNhXdu","5nmWvlXFOB","uLtKs8U2nU","MezSWJkzUn","ZJTXHlCMxy",
-"2hEEUL7cGc","07n1czHF1q","FnPFBYjB9t","n8pJ9Q6Lix","NhXducL0aE","4W0TlFwEJz","FhtglazIWp","VBjhzs93Ml","Mm8siiB08l","pv0i7AgJHQ",
-"Z4I1vtuDyS","0ao3lgIYvE","IRh48bZLvS","5ZaEzFPfSE","EdBKcaDGtS","F6PT2ksJby","Vprf2M3zXL","tuDySVBjhz","5Drn0Pb1pa","IjTwPBbwgA",
-"blLA9h1zcH","jeskStAOsr","RsQUql83Ud","a00b5yofH3","1LB1LqUJMd","AmdQdMmKGJ","wiHrZdQ586","VjCZq5drc6","djsrvaL6AJ","Uvlv4gdQsS",
-"AXpwEuLtKs","lj07QMGlTF","64s8NbgJAz","9GXkXBpYhV","CK5W7oVQp6","prNT6i3pyd","Fhtgl7X3uy","a00b5EOE1o","BbwgAJIqXi","7lUXZAkKTk",
-"K4GS8yvOMI","0YAGHSmGzv","55rfBlXFOB","lXFOBW3VFH","hUTw7LewvM","Uvlv424ARF","lCMxyPOUYS","RmDcrrz7Ut","tlILtsqVrf","HlUbFNhXdu",
-"AOgEe16lHc","Ul4a15iGN5","Yh1hFO3iyQ","M3zXLK20wK","CdyBVS77LH","KASQ8aFFss","UlU3MOxWIH","zY1GYa00b5","KsjRKDLhzM","NAFuwNcICA",
-"FGzgpCfgr3","7X3uySbRYy","pFrrltjQxs","8cVD3SmGzv","FNYIMlweGy","3otm6WmadA","pv0i70h1b1","2ZHdk0ao3l","m4bxUaL6AJ","GrDg7CIShG",
-"RsQUqqaofN","7lUXZDQimp","NOHszjtn0X","b29RJ3weIF","uJScXQnJ1S","G1RhSPYBf4","8TxD7OxWIH","VerEAciuWz","lpF6WuPX7G","yToGWGSQwj",
-"FcWrWZ4I1v","gdQsSru4UG","W7cTs4dEz6","Ta8f6lweGy","v2eC3vOqCE","0MR5XZv7z0","TXQ0ZzQt6Q","OxWIHzqH0W","tjQxsn8pJ9","2NslmVIlwP",
-"Cp3mZRACuj","2DREszHF1q","14FLRRzaZA","m4bxUyvOMI","bZLvSTa8f6","In3NSCIShG","x3LDegdQsS","K4GS8RpBQm","0ao3ldpe1v","MojnPQssNC",
-"8xEKzLDk6f","KASQ8yluBx","oVQp67hyVv","07n1cnFqik","zbIYYZzJHW","he9IASWfou","CK5W7dpe1v","YOfrYZzJHW","dpe1vqaofN","DcpWBFcWrW",
-"piJSkjiVBP","x3LDevkCHH","lkMUAdmoS7","oGu6xcmXIX","BGaQYulk41","7hyVvokgRi","iKqhrgIYvE","ogLgcPOUYS","ni2v1IBe8k","1LB1L55rfB",
-"ni2v1GrDg7","iKqhrgdQsS","suY4xjS1aj","S2DfuWDVWJ","6q6L9jfREu","lsQGoF6PT2","xXTI4cmXIX","gIYvEsx5Gl","sx5GlCqqaD","v2eC3No0Qb",
-"SWfouIKxdL","FGzgpgjUTu","1v5hHP6bcg","Cfgr3a00b5","Ss0Zu48cHL","7lUXZjS1aj","tAOsrW3VFH","0h1b1ZJTXH","pT8wu7fsYM","VjCZqpWiOs",
-"uTacxuoStw","CqqaDKZamH","Ta8f69GXkX","qaofNWreyP","jfREuyofH3","gdQsSoQ87r","HzZT8Y1mC0","iwzGkFPfSE","b29RJbrhlQ","14FLRuJScX",
-"ciuWzfFDrJ","lpF6WZJTXH","RACujvkCHH","n1pmOVBjhz","zbIYYMm8si","ogLgcSmGzv","FxX9q7Ow5C","ZhwG1FcWrW","8TxD7zbIYY","RkQkeWaWsv",
-"lViBvlj07Q","7Ow5CQYxC0","RmDcr8hJdt","oQ87rFLsph","uvf7ATwano","580YDNxx9V","MmsIom4bxU","S77LHaDGtS","1LB1LiKqhr","FxX9qtaOXK",
-"QWxoT45cIH","Mm8siFFDui","WDVWJSWfou","vLsmSGrDg7","FcWrWDcpWB","uQIczJJs5m","HzZT8QChxs","suY4xjiVBP","IKxdLfaHir","2hEEUnnP8o",
-"580YDuPX7G","jzUqRUvlv4","h1zcHRACuj","dhSuHNo0Qb","YjB9tlkMUA","WmadAJ2mQi","KsjRK1LB1L","3weIFZJTXH","sx5GlYh1hF","9GXkX1j5L8",
-"aez9yzFgtB","lCMxyXflUq","SjskQ5Mg9r","16lHcatef2","zHF1qQnJ1S","atef2aL6AJ","OHaBzWPmlx","yluBxIBe8k","ksJbyFxX9q","DG4sT4dEz6",
-"lsQGoO3iyQ","lweGyMojnP","QworuM6qcG","BbwgARACuj","2NslmQYxC0","07n1cQ6hMC","uTacxM3zXL","Chuy3Mm8si","TXQ0ZsqVrf","QssNCxciqp",
-"Yf2Ec9iGoT","iqv4kyToGW","tlILta00b5","jS1ajl83Ud","nFqikNxx9V","ulk41wDajX","WreyPgdQsS","qQxHPaDGtS","IKxdLMaJQs","BpYhVkB5nP",
-"C2IrcqUJMd","fcwDa8cVD3","16lHcazIWp","9GXkXZv7z0","9XyT98TxD7","BpYhVtl72W","FwEJzsuY4x","L7cGcb29RJ","YOfrY2hEEU","S77LHlj07Q",
-"Q6LixGWqqX","RBhp0HzZT8","jeskSbZLvS","oGu6xZUnqt","IBe8kRACuj","ru4UGpT8wu","TCgPpcmXIX","GSQwjECMvU","n8pJ9KZamH","VIlwPCNHmv",
-"aez9yy94nw","xXTI43weIF","uZPqgzQt6Q","0BmCyNcICA","QClRLlpF6W","7ku1pUlU3M","I7p2a9eoRc","uupzktvdkD","uupzkG1RhS","yofH3sx5Gl",
-"SbRYyIjTwP","uJScXGSQwj","Yf2EcCqqaD","Waim6lXFOB","FnPFBSmGzv","ZJTXH6AFT0","VIlwPCdyBV","ZJTXHWmadA","b29RJcQOnv","F6PT2yEfy9",
-"B3qem5drc6","AIYUuZhwG1","MmsIo1j5L8","SjskQ07n1c","0Wr5yEOE1o","MmKGJsuY4x","fcwDaQworu","Vprf2hE1Ql","7Ow5CzqH0W","zmLYDIn3NS",
-"0BmCyjS1aj","0KyfsBFkb8","0Wr5yFnPFB","2ZHdkReKEW","YOfrY4QMc9","YOfrY9GXkX","cL0aEgjUTu","hi5X7MmKGJ","jiVBPe6e4z","ogLgcn8pJ9",
-"gtCA5HP433","m4bxUK20wK","FxX9qhe9IA","5iGN5t59lR","BGaQYWaWsv","GrDg7azIWp","7X3uyAOgEe","BCxeCuupzk","9iGoTn1pmO","FGzgp5VZjS",
-"1LB1LuQIcz","KsjRKQnJ1S","Qworuatef2","0ao3lPOUYS","jzUqR0h1b1","IKxdL1v5hH","GWqqXgjUTu","CK5W7tAOsr","zqH0Wn8pJ9","5iGN5suY4x",
-"BFkb8oGu6x","1j5L8uAWyp","TCgPpnlaBy","HzZT8DG4sT","iB08lqUJMd","OxWIH0BmCy","gtCA5JKWYR","tlILtHfyNQ","IKxdLi3pyd","qQxHPgjUTu",
-"qQxHP1v5hH","iKqhrSjskQ","m4bxU1v5hH","uLtKsiB08l","dQ586aFFss","QYxC0Kr8ys","FwEJz0PktI","8hJdt16lHc","RmDcrL7cGc","9rlg9RBhp0",
-"qaofNYjB9t","iqv4kNxx9V","FnPFBI7p2a","cmXIX5drc6","8FmFHVBjhz","QClRLaL6AJ","HP433t59lR","yToGWZuDtD","xXTI48U2nU","mz8gxIRh48",
-"a00b5atef2","OUYuFGXdoH","QChxspAhR1","GXdoHgdQsS","3otm6F6PT2","Ta8f6QssNC","v1HlnEdBKc","ulk41gf8rI","yofH3WDVWJ","9GXkXxciqp",
-"HP433LDk6f","wDajXMojnP","29QAzYjB9t","mz8gxuJScX","ZuDtDDG4sT","cL0aEvLsmS","hUTw7lj07Q","RsQUqFLsph","KASQ8MGlTF","9eoRcsuY4x",
-"uPX7GogLgc","cL0aExReec","MGlTF9y4lw","qUJMdRkQke","07n1cW3VFH","Chuy3tvdkD","8FmFHfaHir","6AFT0ZzJHW","oQ87re6e4z","bgJAzSWfou",
-"X6PintvdkD","UmaEvzY1GY","bZLvSjS1aj","24ARFI7p2a","SjskQVIlwP","8RCUApiJSk","MojnPAmdQd","Q6hMCMkgy8","L7cGc8U2nU","qUJMd3weIF",
-"qQxHPyvOMI","gdQsSKsjRK","5IhmGiKqhr","y94nwNAFuw","2DREsgdQsS","I7p2aZ4I1v","CK5W7xciqp","0KyfstAOsr","nnP8o64s8N","CxVEfYf2Ec",
-"tjQxsydG8U","vkCHH0PktI","he9IAWmadA","JJs5mCp3mZ","AmdQdhE1Ql","ZJTXHyofH3","CIShGo8Uyd","cShY2SjskQ","VBjhzMaJQs","guMb8QnJ1S",
-"jiVBPtuDyS","LDk6fjSjS3","yofH3t59lR","ciuWztjQxs","rhl0JzbIYY","IKxdLvLsmS","zFgtBsqVrf","tAOsrIBe8k","0Wr5y8xEKz","XyPZNuQIcz",
-"brhlQFwEJz","s7MxkDQimp","lweGyNo0Qb","aFFssvLsmS","5nmWv1LB1L","FNYIMGWqqX","gjUTuoVQp6","QChxsciuWz","zFgtBrKDLJ","gjUTutvdkD",
-"SWfouKsjRK","9iGoTsqVrf","oVQp6618Di","OHaBztuDyS","hUTw7lsQGo","5Drn0YjB9t","dpe1vQnJ1S","uupzkZhwG1","zqH0WoVQp6","Q6hMCQChxs",
-"B3qemTwano","5Drn0W3VFH","okgRivOqCE","nFqikKZamH","618DiPYBf4","s4786aL6AJ","C2IrcciuWz","6AFT0Rxrsm","PYBf4DQimp","U3yw5zbIYY",
-"a00b5JRJQB","QYxC07ku1p","LDk6f14FLR","jtn0XTCgPp","Chuy3BGaQY","pAhR1s7Mxk","CNHmv6q6L9","0ao3lydG8U","Gv3FqsuY4x","NAFuwSWfou",
-"rz7UtjeskS","EoToP2TRI7","tjQxsd7vjM","9XyT9lCMxy","pT8wu5nmWv","CIShGGXdoH","M3zXL5drc6","dQ586nnP8o","bgJAzpmeCd","Gv3FqI7p2a",
-"No0QblpF6W","ReKEWFcWrW","L7cGcHlUbF","MezSWJXljW","QYxC0d85a9","JJs5mpWiOs","kZANmsoy9t","Ss0ZuyluBx","JXljWC2Irc","1v5hHIBe8k",
-"lViBv9eoRc","Uvlv4sqVrf","lsQGod7vjM","hSSvQPb1pa","2TRI7pFrrl","7Ow5CQWxoT","9GXkXkZANm","UlU3MAgJHQ","7fsYM2DREs","EOE1oni2v1",
-"hSSvQFLsph","d85a95Drn0","5Drn0sx5Gl","PYBf4OxWIH","StlDJhSSvQ","x3LDeJ2mQi","suY4xJJs5m","jS1ajFxX9q","aDGtSWreyP","FxX9qoGu6x",
-"zHF1q9XyT9","suY4xzQt6Q","jS1ajxXTI4","Yw2oUjiVBP","G1RhS16lHc","Gv3Fqni2v1","yluBxzz4ZU","StlDJwDajX","DLhzMv2eC3","Vprf2RmDcr",
-"WMiS3djsrv","lj07Qgf8rI","JXljWFNYIM","ECMvUokgRi","dmoS7hE1Ql","G1RhS9rlg9","yofH3G1RhS","OHaBz5drc6","EoToP0h1b1","jiVBPuN6r3",
-"GXdoHlViBv","EdBKcru4UG","ciuWzogLgc","iKqhrVprf2","2TRI7zFgtB","Waim62TRI7","gjUTuHP433","5drc6Waim6","Gv3Fq8hJdt","9eoRcM6qcG",
-"POUYSgIYvE","cL0aE5Mg9r","cShY2blLA9","wiHrZCfgr3","brhlQsqVrf","dpe1vpvgjS","SWfou3otm6","lsQGodmoS7","Vprf2lViBv","JkzUnzqH0W",
-"yvOMIZ4I1v","Cfgr3Twano","0YAGHfqypy","t59lR0ao3l","7Ow5Cxciqp","jzUqRMmKGJ","hi5X7mX2GE","UlU3M5ZaEz","Yw2oUYf2Ec","Nxx9V2Nslm",
-"QbxXci3pyd","tvdkDfFDrJ","blLA9FGzgp","gtCA5W3VFH","dQ586CdyBV","lm0pDQWxoT","y94nwAgJHQ","b29RJRzaZA","lViBvfcwDa","07n1cx3LDe",
-"PYBf4B3qem","tvdkDLDk6f","Mkgy8zbIYY","prNT6IRh48","GSQwjDLhzM","zHF1qrhl0J","Chuy3Twano","SjskQ9XyT9","uQIcz5ZaEz","he9IA9iGoT",
-"2Yz7Erhl0J","xciqpsx5Gl","ZJTXHqaofN","CK5W7b29RJ","QWxoTm4bxU","oQ87rQworu","Pb1paM6qcG","QYxC09y4lw","zbIYYUvlv4","Pb1paK20wK",
-"MmKGJ7lUXZ","MezSWnFqik","S77LHKASQ8","2Yz7ERxrsm","Kr8ysLewvM","zQt6QKsjRK","HfyNQzbIYY","nnP8o55rfB","0ao3lYOfrY","pmeCdWDVWJ",
-"zqH0WWPmlx","Zv7z045cIH","0YAGHMaJQs","jSjS34dEz6","FjHXRDLhzM","GrDg7LDk6f","Yf2EcWMiS3","HlUbFpiJSk","5drc62ZHdk","CNHmvv2eC3",
-"SmGzvVNCPd","l83Ud7lUXZ","nlaBy45cIH","WPmlxpvgjS","0ao3lZ4I1v","GrDg7Cfgr3","MaJQsQ6hMC","ZzJHW5ZaEz","uN6r3MaJQs","zHF1qFLsph",
-"1LB1LGrDg7","5Mg9r9eoRc","yofH3Mm8si","K4GS8xXTI4","blLA9gf8rI","7ku1pMezSW","fFDrJM6qcG","ulk41rhl0J","pWiOs0YAGH","Yf2EcBFkb8",
-"CIShGdjsrv","2hEEUM3zXL","ogLgcWMiS3","xReecnFqik","Mm8siiwzGk","Mm8sixXTI4","5iGN5yofH3","B3qempT8wu","TCgPpvkCHH","iB08luvf7A",
-"pAhR1s4786","JkzUn1j5L8","iwzGkfqypy","AkKTkVNCPd","NOHszbgJAz","ydG8UUmaEv","HzZT8djsrv","9GXkXnnP8o","3otm6gIYvE","0ao3lY1mC0",
-"16lHcK4GS8","AmdQdlpF6W","hUTw7GXdoH","ni2v19eoRc","ZhwG1QssNC","EOE1oCqqaD","v8yFNWMiS3","618Di4QMc9","fFDrJuupzk","RpBQmfLNg8",
-"zqH0WNcICA","gIYvE1j5L8","jeskSjeskS","9rlg9Yw2oU","t59lRDG4sT","lm0pDix74r","AOgEegf8rI","2NslmtuDyS","pWiOsRACuj","lsQGo8xEKz",
-"pvgjS0BmCy","MmsIoLDk6f","G1RhS24ARF","D6rByuoStw","kZANmkZANm","v1Hlnlm0pD","POUYS24ARF","Vprf2U3yw5","n8pJ98xEKz","M3zXLiKqhr",
-"45cIHmz8gx","FVMxoFnPFB","fqypydjsrv","Ul4a1rhl0J","Yh1hFs4786","VjCZq2Yz7E","AOgEeReKEW","EoToPS77LH","yofH3I7p2a","fFDrJnnP8o",
-"aez9yD6rBy","cL0aEm4bxU","TXQ0ZjS1aj","Gv3FqM3zXL","BpYhVtaOXK","SbRYyzHF1q","MK07YDcpWB","v8yFNUvlv4","lkMUAZzJHW","cL0aEK4GS8",
-"0ao3lh1zcH","Oz8yZAOgEe","RACujatef2","0h1b1azIWp","oVQp6yToGW","8hJdt5drc6","YjB9tRpBQm","RmDcrRkQke","Q6hMC24ARF","ni2v1FcWrW",
-"s7MxkReKEW","aez9y8FmFH","F6PT28xEKz","Mkgy8WreyP","ksJbytaOXK","5VZjSlH1kt","lj07Q5Drn0","5Drn0lViBv","O3iyQYf2Ec","XflUqKZamH",
-"s4786zQt6Q","M3zXLStlDJ","Nxx9VBpYhV","okgRituDyS","v2eC3Z4I1v","fFDrJMmsIo","FjHXRqUJMd","YjB9tLbRTH","IKxdL7lUXZ","t59lRPb1pa",
-"IBe8kiwzGk","WaWsvWMiS3","xXTI4TCgPp","WreyPVprf2","BpYhVWaWsv","64s8Ni3pyd","zFgtB6AFT0","prNT6Yh1hF","Uvlv4AmdQd","prNT6SWfou",
-"ulk41AIYUu","l83UdCfgr3","cmXIXni2v1","1LB1LtjQxs","djsrvPOUYS","1j5L87lUXZ","MK07YnFqik","t59lRC2Irc","azIWp1v5hH","aez9yZJTXH",
-"JJs5mTa8f6","aDGtSJkzUn","FwEJz9rlg9","Chuy3M3zXL","RxrsmHzZT8","HP433lkMUA","6AFT0s7Mxk","MezSW7ku1p","Dz1R3v1Hln","yToGW5IhmG",
-"QWxoTiB08l","3weIF3otm6","aDGtS5Namm","AIYUuh1zcH","2NslmfmIK1","ciuWz5drc6","lXFOBFLsph","9eoRctlILt","fLNg855rfB","FLsphtl72W",
-"5VZjSb29RJ","07n1c5nmWv","RmDcr0YAGH","5iGN5RsQUq","FLsphOz8yZ","LewvMlkMUA","tl72WVNCPd","UmaEvLbRTH","xciqpuQIcz","5VZjSFnPFB",
-"oVQp6RkQke","lViBvhe9IA","o8UydI7p2a","AIYUuDG4sT","M6qcG9GXkX","OUYuFNo0Qb","hUTw7jiVBP","618DiD6rBy","K4GS8VerEA","NcICAdhSuH",
-"RkQke1v5hH","RxrsmzFgtB","ZzJHW0ao3l","48cHLHRxd8","aFFssJ2mQi","0YAGHYh1hF","s4786oVQp6","tlILtYh1hF","5Drn0pFrrl","QssNCuoStw",
-"e6e4z5Mg9r","0ao3l5nmWv","7fKYUeuZA5","HlUbFCNHmv","1j5L8ZzJHW","k85AeuN6r3","ru4UGjiVBP","I7p2ataOXK","1LB1LlViBv","cmXIXlm0pD",
-"guMb8jeskS","FnPFBokgRi","FNYIMiKqhr","Mkgy8aL6AJ","8TxD7AXpwE","pv0i7qUJMd","QbxXcblLA9","0MR5XM3zXL","0KyfsUmaEv","I7p2aFPfSE",
-"U3yw5FGzgp","SjskQ2Yz7E","QbxXcJ2mQi","TXQ0ZjeskS","3weIFChuy3","djsrvi7WMQ","ZzJHWJKWYR","yToGW8cVD3","2TRI7soy9t","uN6r3WmadA",
-"VIlwPGXdoH","ulk41sx5Gl","JKWYRaFFss","wDajX4W0Tl","rKDLJsoy9t","Pb1paxciqp","24ARFh1zcH","7lUXZM3zXL","M3zXLKr8ys","8U2nU8cVD3",
-"s4786OxWIH","LDk6f2TRI7","0YAGHv1Hln","lViBvYw2oU","9GXkXi7WMQ","ZzJHWVerEA","b29RJFcWrW","pvgjSTwano","qQxHP8FmFH","KsjRKb29RJ",
-"S77LHHP433","M6qcGdhSuH","Q6Lix5ZaEz","lXFOBNhXdu","euZA5iqv4k","lm0pDYOfrY","soy9ti7WMQ","Yw2oU1LB1L","5Drn0Z4I1v","QnJ1SBFkb8",
-"djsrvGSQwj","uPX7G9GXkX","Cfgr3JXljW","JRJQBIjTwP","FnPFBIjTwP","DcpWBMm8si","24ARFSmGzv","tjQxss4786","VjCZqMGlTF","29QAz48cHL",
-"FcWrWK4GS8","8U2nU5Mg9r","jiVBPDG4sT","uN6r3WMiS3","NOHszsoy9t","Waim66AFT0","ZUnqtUvlv4","0PktISjskQ","CNHmvIRh48","1j5L8Mm8si",
-"2ZHdk2ZHdk","jeskSPOUYS","tl72Wb29RJ","jeskSyluBx","U3yw5azIWp","K20wKX6Pin","cShY2guMb8","QssNCVprf2","xReecgf8rI","Pb1padQ586",
-"580YD4W0Tl","uLtKsrKDLJ","uoStwHfyNQ","sx5GlNAFuw","uupzkU3yw5","aFFssQChxs","hUTw7dQ586","djsrvzmLYD","Mkgy8v2eC3","oGu6x2Nslm",
-"dmoS7Vprf2","SjskQrz7Ut","DcpWB24ARF","t98iWNxx9V","ReKEWfcwDa","uoStwuupzk","4dEz60MR5X","ulk4107n1c","lH1kttAOsr","ReKEWiKqhr",
-"JIqXiuoStw","gIYvENOHsz","fcwDaC2Irc","Cfgr3MmKGJ","2Yz7EIBe8k","GrDg7FnPFB","VNCPdM6qcG","D6rBy2DREs","9rlg9JkzUn","4dEz6C2Irc",
-"h1zcHTCgPp","Yw2oUlsQGo","M3zXLni2v1","7fsYM5drc6","2DREsVjCZq","zFgtBPOUYS","oQ87raL6AJ","4W0TlNAFuw","1v5hHC2Irc","i3pydl83Ud",
-"e6e4zD6rBy","MojnPBCxeC","8FmFHFPfSE","RmDcrReKEW","vkCHH55rfB","jtn0XZzJHW","Twano8hJdt","t98iWMK07Y","RxrsmRsQUq","JRJQB7hyVv",
-"uvf7A4W0Tl","HP433vkCHH","pAhR17ku1p","MezSWBFkb8","uJScX8hJdt","s4786W7cTs","CqqaD8U2nU","zQt6QM3zXL","vkCHHoGu6x","Chuy3suY4x",
-"ix74r6AFT0","YOfrYzQt6Q","nlaBy48cHL","tlILtbgJAz","QWxoT9GXkX","azIWpo8Uyd","o8Uydk85Ae","MezSWiB08l","jS1ajdQ586","pFrrlguMb8",
-"B3qemxXTI4","pFrrlYh1hF","qUJMdrKDLJ","pvgjSZJTXH","618DitlILt","OxWIHwiHrZ","vLsmSiB08l","gtCA5LbRTH","48cHLzQt6Q","lCMxyEOE1o",
-"nlaBy5Namm","ulk41cQOnv","pT8wu64s8N","d7vjMaFFss","ydG8Uatef2","KZamH5iGN5","yToGWlViBv","uoStw3otm6","FhtglFxX9q","cQOnv07n1c",
-"8xEKzhYBCK","t59lRYf2Ec","JJs5mFLsph","sqVrfQChxs","oGu6x7fKYU","U3yw5OHaBz","v8yFNYjB9t","DQimpCNHmv","dhSuHm4bxU","h1zcHlViBv",
-"7lUXZzY1GY","MezSWuoStw","WMiS3gdQsS","k85Ae9y4lw","taOXKfmIK1","FnPFBNxx9V","JIqXiuAWyp","lj07QciuWz","gIYvEI7p2a","jeskSL7cGc",
-"oVQp6LbRTH","ZJTXHIn3NS","CNHmvZJTXH","24ARFIRh48","CdyBVLewvM","brhlQD6rBy","QClRLReKEW","FxX9qHRxd8","5ZaEznnP8o","GWqqXZuDtD",
-"qUJMdhi5X7","uvf7AFPfSE","FNYIMjtn0X","FnPFBxReec","NOHszVjCZq","8xEKzRsQUq","mz8gxi7WMQ","djsrvsuY4x","aL6AJK4GS8","aFFsshYBCK",
-"qUJMds7Mxk","hi5X7brhlQ","X6Pinm4bxU","e6e4zazIWp","zQt6Qlj07Q","y94nwU3yw5","aL6AJn1pmO","J2mQiZzJHW","Yh1hF8cVD3","9XyT90ao3l",
-"rz7UteuZA5","SWfouLDk6f","uQIczAkKTk","Qworu55rfB","hUTw7IKxdL","XflUqMojnP","aDGtScShY2","MGlTFMmKGJ","o8UydzFgtB","Ss0Zu6q6L9",
-"4W0TldQ586","FVMxoix74r","ix74rWreyP","x3LDejeskS","5nmWvpvgjS","Vprf2RsQUq","BCxeCgjUTu","TCgPp9XyT9","oGu6xazIWp","n1pmOv2eC3",
-"vLsmSQYxC0","QnJ1SW7cTs","nFqikVNCPd","prNT6aFFss","OHaBzix74r","RkQkeY1mC0","VNCPdOz8yZ","cL0aExXTI4","Nxx9V5ZaEz","aL6AJuQIcz",
-"QbxXcix74r","Pb1paSWfou","7Ow5Cdpe1v","wDajX8cVD3","uQIczuN6r3","cShY2RBhp0","JKWYR07n1c","OHaBz5Drn0","8hJdtpAhR1","7lUXZMGlTF",
-"8TxD7wDajX","blLA9Qworu","9y4lwWDVWJ","vkCHHXflUq","QChxsVIlwP","ydG8UfFDrJ","FPfSEOHaBz","AXpwESmGzv","h1zcHAOgEe","uoStwlXFOB",
-"FwEJz7hyVv","qUJMduQIcz","ZhwG1M3zXL","0PktIGWqqX","Yf2Ecmz8gx","7lUXZ4W0Tl","jzUqRlkMUA","AXpwEzbIYY","1v5hHMGlTF","lCMxy9rlg9",
-"ZzJHWgIYvE","Nxx9V1v5hH","MaJQsuvf7A","ni2v1lXFOB","8TxD7Y1mC0","QClRLQbxXc","hi5X7HzZT8","lj07QpWiOs","M6qcGUvlv4","7lUXZXflUq",
-"MmKGJd7vjM","WDVWJv1Hln","CK5W7zQt6Q","iB08l5nmWv","1j5L8hE1Ql","RxrsmYh1hF","he9IAn8pJ9","wDajXnlaBy","ulk41QssNC","uQIczuTacx",
-"tAOsrGv3Fq","Uvlv49eoRc","MojnPOUYuF","U3yw5tAOsr","nlaBy2ZHdk","t59lRK20wK","8TxD7B3qem","jtn0X0PktI","4dEz6IKxdL","v2eC3FwEJz",
-"djsrvFNYIM","1LB1LlXFOB","9y4lwX6Pin","piJSkZzJHW","D6rByXyPZN","bZLvSt98iW","QssNCP6bcg","AgJHQpvgjS","J2mQioGu6x","0BmCyO3iyQ",
-"Yh1hFfaHir","t59lRRkQke","9rlg9prNT6","xciqpjfREu","CdyBVlkMUA","3otm63otm6","7lUXZydG8U","QYxC0MK07Y","RmDcrQworu","1v5hHFPfSE",
-"cmXIXQssNC","pWiOsIn3NS","ZzJHW1v5hH","uLtKsStlDJ","he9IAFLsph","MmKGJXyPZN","n8pJ92ZHdk","piJSk0BmCy","618DiWaWsv","fcwDaKr8ys",
-"kZANmHfyNQ","3weIFzQt6Q","5IhmGzHF1q","yToGWjfREu","pvgjSmz8gx","LbRTHlkMUA","euZA5CqqaD","fcwDaZv7z0","8FmFHDG4sT","M3zXLFFDui",
-"pWiOsUlU3M","StlDJYjB9t","CxVEfzqH0W","jSjS3EdBKc","lweGyW7cTs","jfREu9GXkX","29QAzS2Dfu","XflUqFGzgp","d85a9MGlTF","ZuDtDVjCZq",
-"9rlg9RpBQm","UmaEvO3iyQ","0MR5Xs93Ml","5drc6Q6Lix","AIYUulsQGo","8FmFHHP433","1j5L8soy9t","SbRYye6e4z","v8yFNiKqhr","suY4xIjTwP",
-"tjQxs5iGN5","JKWYRVLTy6","fLNg8oGu6x","LbRTHgf8rI","o8UyduJScX","TCgPpNo0Qb","o8UydlViBv","Fhtgl9eoRc","s7Mxk2ZHdk","jfREuReKEW",
-"7hyVv9iGoT","Q6LixkZANm","YjB9tlm0pD","XyPZN5drc6","K4GS8i3pyd","l83UdMmsIo","yEfy9AOgEe","ciuWzS2Dfu","djsrvEOE1o","jSjS3CxVEf",
-"d85a98FmFH","K4GS8xReec","DG4sTsx5Gl","mz8gx9eoRc","3otm6gtCA5","kZANmoQ87r","9rlg9IjTwP","guMb80MR5X","JJs5mjSjS3","uTacxNxx9V",
-"QnJ1SMojnP","6AFT0ZhwG1","C2IrcEOE1o","nFqikuN6r3","ogLgcOHaBz","uJScX2ZHdk","fFDrJ8TxD7","n1pmOJ2mQi","7fKYUjSjS3","MmKGJQ6Lix",
-"zQt6QBbwgA","Ul4a1DQimp","Yw2oUIKxdL","lH1ktciuWz","a00b5pv0i7","X6Pin2DREs","MaJQsHP433","prNT6tlILt","lXFOBblLA9","Yh1hF7X3uy",
-"dmoS7rhl0J","Vprf20Kyfs","iqv4k5Mg9r","aez9ywiHrZ","AOgEeiqv4k","VNCPdgjUTu","RxrsmUlU3M","0BmCy3weIF","pv0i7Gv3Fq","CK5W7IRh48",
-"Vprf2cL0aE","2NslmQssNC","he9IAh1zcH","S2DfuOHaBz","JXljWMmsIo","VIlwPv8yFN","RzaZA7hyVv","7X3uy0MR5X","s4786ogLgc","5ZaEzcmXIX",
-"lweGyn8pJ9","3otm6S2Dfu","JkzUnnFqik","FPfSEt59lR","cL0aE0ao3l","618DiQbxXc","nnP8oOHaBz","ogLgcNAFuw","qaofNguMb8","0MR5XRpBQm",
-"0PktIOxWIH","xReecMGlTF","uAWyprz7Ut","qQxHPYh1hF","pFrrl7fKYU","G1RhS48cHL","WMiS3CNHmv","CdyBV55rfB","DLhzMP6bcg","No0Qbt98iW",
-"JJs5ml83Ud","AkKTkaDGtS","lweGyF6PT2","Ul4a1L7cGc","WaWsvtl72W","yvOMIZUnqt","y94nwlH1kt","zbIYYMezSW","UlU3MgjUTu","J2mQiNOHsz",
-"vLsmSCIShG","lViBvZhwG1","FGzgpqaofN","9y4lwTCgPp","aez9y4W0Tl","s4786CqqaD","NhXduQWxoT","Vprf25Drn0","AIYUufqypy","Ul4a1blLA9",
-"SmGzvUl4a1","9iGoTU3yw5","Ul4a1618Di","Dz1R3ogLgc","kB5nPQ6hMC","0PktILDk6f","hi5X7Dz1R3","1v5hHQssNC","RmDcrRzaZA","zmLYDcL0aE",
-"QWxoTJIqXi","jeskStl72W","lH1ktFxX9q","Chuy3hYBCK","oVQp6aDGtS","Zv7z0l83Ud","MGlTFAOgEe","mX2GE618Di","QssNCoGu6x","lH1ktK4GS8",
-"5VZjSsoy9t","DQimpNcICA","m4bxUSs0Zu","OUYuF2Nslm","atef28RCUA","3otm6QChxs","8cVD3RsQUq","WmadAHRxd8","EoToPQ6hMC","VIlwPJIqXi",
-"BGaQYYh1hF","wiHrZIRh48","IBe8kMGlTF","ThjNn5ZaEz","Yh1hFJJs5m","RACujUvlv4","Ta8f6kZANm","VjCZqTCgPp","MaJQsNo0Qb","BFkb83otm6",
-"x3LDeqaofN","xReecuZPqg","AgJHQTwano","CxVEfpiJSk","uQIczwDajX","rhl0J9eoRc","AmdQdBCxeC","ZzJHWlViBv","AIYUujtn0X","IBe8kPOUYS",
-"HP433e6e4z","QChxs6AFT0","BGaQYYOfrY","xReect59lR","XyPZNgtCA5","K4GS8uvf7A","7ku1pyToGW","yofH3NAFuw","Gv3FqpvgjS","0YAGHAIYUu",
-"9iGoT5ZaEz","Z4I1vNxx9V","2DREsNAFuw","RBhp0ZhwG1","F6PT25VZjS","LbRTHpvgjS","VLTy6RmDcr","5Mg9rvOqCE","D6rByzHF1q","ni2v1L7cGc",
-"BCxeCxXTI4","3weIFaFFss","ECMvUG1RhS","brhlQXflUq","pT8wuAXpwE","8xEKzaL6AJ","TwanoFcWrW","8U2nURsQUq","nnP8oQworu","HzZT8d85a9",
-"pFrrlJRJQB","uPX7Glm0pD","tuDySm4bxU","s4786CIShG","0Wr5y5nmWv","CIShGWmadA","0ao3lJRJQB","2ZHdk9iGoT","oGu6xNOHsz","2ZHdkpmeCd",
-"o8Uydpv0i7","5NammqUJMd","sx5Glsx5Gl","0YAGHRzaZA","cmXIXtvdkD","rz7UtyToGW","uLtKsCK5W7","AXpwEKr8ys","gjUTuY1mC0","Ss0ZuRBhp0",
-"7ku1p5ZaEz","WMiS3NAFuw","ksJbyMK07Y","QssNCv8yFN","Yf2EczFgtB","0KyfszFgtB","x3LDeM3zXL","yEfy9ni2v1","jeskSdhSuH","HP433iqv4k",
-"pvgjS24ARF","t59lRBGaQY","OHaBzIBe8k","FxX9qTCgPp","zmLYDbrhlQ","ksJbyLDk6f","RzaZAni2v1","jzUqRVLTy6","gdQsSblLA9","Yf2EcBCxeC",
-"7fKYUCdyBV","RxrsmGSQwj","zFgtBxReec","RACujY1mC0","SbRYyMK07Y","uJScX5Mg9r","x3LDeaez9y","tl72WGrDg7","suY4x0YAGH","fcJOyUmaEv",
-"TXQ0ZuPX7G","QChxsZzJHW","SWfouPYBf4","s7MxkxReec","iB08lMojnP","jzUqRyofH3","8RCUAFjHXR","S77LHt98iW","suY4xTXQ0Z","C2Irc8hJdt",
-"dpe1vFVMxo","QnJ1SZ4I1v","8U2nURxrsm","S77LHRkQke","5NammDG4sT","QworuyluBx","lkMUARzaZA","RzaZAW3VFH","Kr8ysX6Pin","Twanov2eC3",
-"0MR5XbgJAz","CdyBVaFFss","MaJQsMojnP","Oz8yZFcWrW","nlaByY1mC0","LbRTH5nmWv","StlDJfaHir","pT8wus93Ml","b29RJS77LH","s4786lkMUA",
-"EoToPcQOnv","nnP8otl72W","tl72Wsoy9t","U3yw5Dz1R3","D6rBy16lHc","4QMc9WmadA","8cVD30Kyfs","G1RhSCK5W7","vLsmSNOHsz","7Ow5CSs0Zu",
-"9GXkXUlU3M","HlUbFpv0i7","Kr8ysuoStw","0BmCy9GXkX","ZJTXHyvOMI","gjUTu8cVD3","pWiOsuZPqg","tl72Watef2","FjHXRuTacx","t98iWHzZT8",
-"I7p2asuY4x","48cHLnlaBy","prNT6zFgtB","HP433Waim6","JJs5mNo0Qb","FhtglStlDJ","7fKYUM3zXL","GSQwjk85Ae","Q6LixUmaEv","d7vjM07n1c",
-"ECMvUF6PT2","dhSuHTa8f6","29QAzAkKTk","RzaZAZJTXH","gf8rIiB08l","Yw2oU29QAz","FPfSEyofH3","YOfrYQbxXc","2Yz7E29QAz","Waim6Y1mC0",
-"bgJAz4QMc9","I7p2auoStw","ZhwG17ku1p","NOHsz24ARF","pWiOsXflUq","oQ87rlpF6W","qaofNX6Pin","UlU3MWDVWJ","k85AeWreyP","VIlwP16lHc",
-"JXljW7X3uy","TCgPppAhR1","tvdkDzHF1q","MojnPfLNg8","Chuy38TxD7","Vprf21v5hH","uupzkSWfou","8RCUALDk6f","4dEz61j5L8","Mkgy8K20wK",
-"iB08lhSSvQ","ZJTXHZJTXH","2TRI7OUYuF","ZzJHWGrDg7","xciqplCMxy","fcJOyv2eC3","WMiS3G1RhS","TXQ0ZS2Dfu","EOE1oogLgc","cShY2euZA5",
-"OHaBzuoStw","euZA5tuDyS","FcWrW8cVD3","lViBvFNYIM","fqypyt59lR","jSjS3zHF1q","2NslmVNCPd","bgJAzuN6r3","fcwDaaL6AJ","XyPZN07n1c",
-"OHaBzyvOMI","QworuSjskQ","vOqCEHP433","FNYIMuTacx","5NammFjHXR","ni2v1iB08l","SWfoui3pyd","nFqiksqVrf","v8yFNOUqFM","djsrv7X3uy",
-"yluBx2DREs","HP433zFgtB","FnPFB8hJdt","3otm6BbwgA","7fsYMjtn0X","Waim6yofH3","4W0TlGrDg7","yToGWStlDJ","BFkb8oQ87r","n8pJ99iGoT",
-"jS1ajC2Irc","RBhp0In3NS","DG4sTwiHrZ","pT8wu0Kyfs","vOqCEBpYhV","cmXIXaDGtS","nlaByJXljW","lkMUAMmKGJ","CIShGsqVrf","JXljWWreyP",
-"dpe1v7fsYM","fqypyJKWYR","cQOnvQ6Lix","LDk6fJXljW","brhlQaL6AJ","faHiruoStw","ZzJHWWMiS3","AmdQduAWyp","lCMxyD6rBy","0YAGH2TRI7",
-"ZJTXH2Yz7E","uPX7GgtCA5","lsQGoFFDui","d7vjMqUJMd","pAhR1W7cTs","0PktIkB5nP","KZamHOUYuF","n1pmOzY1GY","soy9tF6PT2","NAFuwydG8U",
-"ksJbyzQt6Q","FcWrWsuY4x","lCMxyZJTXH","VjCZq5Namm","XflUqU3yw5","QClRLpv0i7","zFgtBGrDg7","7X3uyHfyNQ","v8yFNsuY4x","hE1QlStlDJ",
-"EoToPC2Irc","OxWIHl83Ud","0Wr5ygjUTu","U3yw5DcpWB","mz8gxhUTw7","QbxXc6AFT0","Waim6fmIK1","45cIHa00b5","wDajXblLA9","yToGWksJby",
-"Ul4a1Gv3Fq","vOqCERpBQm","Yh1hFJ2mQi","VLTy6n1pmO","HzZT8FFDui","ksJbyaL6AJ","lViBvWreyP","s93MlzHF1q","dQ586Qworu","RkQkeaFFss",
-"XflUqfcJOy","Kr8yswDajX","uoStw7hyVv","zHF1qaDGtS","fFDrJNxx9V","RsQUqRzaZA","GWqqXs4786","t59lRuZPqg","azIWpaDGtS","8RCUAyofH3",
-"FcWrWHlUbF","uQIczCK5W7","uTacxPYBf4","zz4ZUs7Mxk","4QMc9dQ586","MezSWv1Hln","8hJdtzHF1q","StlDJfFDrJ","mX2GE16lHc","VIlwPxXTI4",
-"7hyVvv2eC3","IRh48cL0aE","iwzGkRACuj","WPmlxCfgr3","64s8Ndjsrv","9rlg9oVQp6","kB5nPEdBKc","RzaZAMojnP","oQ87r5Drn0","MojnPAIYUu",
-"iKqhr5nmWv","KsjRKCqqaD","Kr8ys9iGoT","FnPFB5nmWv","uvf7AYh1hF","HP4337fKYU","5ZaEzF6PT2","tjQxsulk41","rhl0JiKqhr","rz7UtuZPqg",
-"rKDLJyToGW","MmsIotl72W","RBhp0AOgEe","9XyT9fFDrJ","FcWrWogLgc","y94nwY1mC0","gjUTuAIYUu","uQIczm4bxU","QChxsJJs5m","KASQ8FFDui",
-"qaofNt59lR","UmaEvGWqqX","t98iWD6rBy","zHF1qqUJMd","7lUXZs4786","ECMvUBFkb8","t59lRvkCHH","ReKEWsx5Gl","vLsmSQClRL","0ao3lXflUq",
-"atef2a00b5","MmKGJG1RhS","oVQp6ksJby","VIlwPtl72W","Uvlv4SbRYy","Waim6ECMvU","I7p2ad85a9","lH1ktW7cTs","y94nwQnJ1S","uAWyprhl0J",
-"zQt6QciuWz","fLNg8FcWrW","Mkgy8jfREu","Fhtgl0YAGH","VIlwP4W0Tl","Ul4a1QChxs","7hyVvAkKTk","Mkgy8W3VFH","soy9tHlUbF","9y4lwOz8yZ",
-"pmeCduTacx","9GXkXJkzUn","RzaZAM6qcG","kZANmjzUqR","dmoS7hi5X7","O3iyQEoToP","MojnPjtn0X","zFgtBjSjS3","jiVBPsoy9t","VBjhznlaBy",
-"SWfoua00b5","lH1ktZUnqt","jiVBP9iGoT","X6PinzQt6Q","piJSkLewvM","L7cGcAXpwE","9iGoTMkgy8","pWiOscmXIX","ni2v1HfyNQ","No0QbjzUqR",
-"tjQxsbrhlQ","580YDlkMUA","RxrsmjS1aj","i3pydAIYUu","v8yFNblLA9","wDajXKASQ8","55rfBJkzUn","CK5W7AgJHQ","tl72WGSQwj","Mm8siFjHXR",
-"iwzGkQYxC0","7lUXZnFqik","n8pJ9hSSvQ","Cfgr3Ss0Zu","uTacxXyPZN","7X3uypWiOs","5Mg9rHlUbF","yofH39eoRc","0YAGHWPmlx","RBhp0AkKTk",
-"3weIFHzZT8","pFrrl9eoRc","xciqpQChxs","cShY25ZaEz","suY4xWaim6","RxrsmY1mC0","zHF1qNhXdu","ciuWzzmLYD","gjUTuEOE1o","Cfgr3xXTI4",
-"x3LDe8U2nU","TCgPpdpe1v","618Dixciqp","RxrsmgtCA5","Vprf24W0Tl","CxVEf618Di","uvf7A64s8N","JKWYRRzaZA","8cVD3v1Hln","aFFsstuDyS",
-"m4bxUgdQsS","gjUTuh1zcH","EOE1ozbIYY","FLsph2Yz7E","TCgPplH1kt","FFDuiX6Pin","GWqqX9y4lw","dmoS7RBhp0","TwanoGv3Fq","O3iyQsuY4x",
-"7Ow5C5ZaEz","S77LHM3zXL","l83Udb29RJ","EoToPUl4a1","h1zcHMojnP","azIWptjQxs","1j5L8NAFuw","jfREuyvOMI","qQxHPzHF1q","IBe8kkB5nP",
-"ZJTXHX6Pin","sqVrfatef2","pv0i7tuDyS","OHaBzprNT6","Z4I1vfaHir","i7WMQtuDyS","KsjRKmX2GE","Mm8siZUnqt","prNT6CNHmv","QYxC0fqypy",
-"UmaEvd7vjM","DQimpwiHrZ","POUYSfaHir","1v5hHMaJQs","yluBxM3zXL","pT8wuG1RhS","64s8NBpYhV","ZJTXH8FmFH","blLA99rlg9","NAFuwJkzUn",
-"brhlQ0ao3l","O3iyQGSQwj","AIYUu2ZHdk","xReecpFrrl","zbIYYYOfrY","pFrrlKZamH","9XyT9jfREu","JJs5mKsjRK","uTacxZv7z0","Ss0Zu0h1b1",
-"KZamHv1Hln","ydG8UlpF6W","hUTw7VBjhz","W7cTsBCxeC","In3NSC2Irc","Dz1R3xciqp","618DitvdkD","dQ586EdBKc","3weIFjeskS","9y4lw16lHc",
-"ZhwG1i7WMQ","ZJTXH5VZjS","MojnPU3yw5","5NammRzaZA","5nmWvAXpwE","BFkb8W7cTs","OHaBzs7Mxk","pWiOse6e4z","zbIYY5ZaEz","2hEEUdhSuH",
-"hSSvQuQIcz","8cVD3Qworu","4W0Tl64s8N","zFgtBIKxdL","Z4I1v5VZjS","QWxoTW7cTs","AgJHQNo0Qb","JXljWgjUTu","lXFOBfcJOy","07n1cFVMxo",
-"NAFuwWDVWJ","fqypyWaWsv","mz8gxuN6r3","IjTwPBGaQY","2TRI7VIlwP","4dEz6iwzGk","Oz8yZuAWyp","yvOMIJIqXi","d7vjMs7Mxk","QWxoThUTw7",
-"FVMxoBCxeC","gjUTui7WMQ","lXFOBMezSW","yvOMIZv7z0","rKDLJVLTy6","gIYvEMmKGJ","t59lR0h1b1","FLsphLbRTH","prNT6pT8wu","580YD4dEz6",
-"ru4UGsqVrf","IRh48kB5nP","KZamHDcpWB","VIlwPa00b5","DQimpJJs5m","FjHXRjS1aj","KASQ89eoRc","x3LDeIjTwP","BGaQYvkCHH","K20wKUlU3M",
-"FhtgloGu6x","Yw2oUuvf7A","580YDCp3mZ","FGzgpsuY4x","IKxdLD6rBy","Vprf2UlU3M","djsrvjeskS","BpYhVKr8ys","v1HlnW7cTs","tlILt7lUXZ",
-"taOXK6AFT0","yvOMIuN6r3","ZJTXH5drc6","pFrrlReKEW","IBe8k9XyT9","jfREuGSQwj","In3NSMK07Y","HzZT8uLtKs","DQimpgdQsS","faHirv8yFN",
-"OUqFMMK07Y","O3iyQd85a9","QClRLdjsrv","hUTw78xEKz","zY1GYVerEA","FGzgpZUnqt","djsrvCxVEf","8xEKzRxrsm","s93MlJIqXi","6AFT0FPfSE",
-"BFkb8XyPZN","xciqp45cIH","Waim6uupzk","BGaQYsx5Gl","pvgjStl72W","nnP8ojiVBP","yEfy9VLTy6","AgJHQtAOsr","DcpWBk85Ae","ThjNnRzaZA",
-"TwanofaHir","xReec1j5L8","CdyBVFhtgl","P6bcgpT8wu","618DisuY4x","iqv4ky94nw","Cp3mZ0YAGH","fmIK1S77LH","zbIYYsx5Gl","CqqaDAgJHQ",
-"RACujgf8rI","Pb1pagIYvE","OHaBzLbRTH","fFDrJ9XyT9","jSjS3M3zXL","QssNCK4GS8","fcwDaQbxXc","BpYhV0PktI","0ao3lhe9IA","KsjRKoGu6x",
-"QWxoTlj07Q","MojnP5ZaEz","0YAGHDQimp","16lHc07n1c","Nxx9VmX2GE","kB5nPHRxd8","LDk6f5Mg9r","WDVWJtjQxs","5IhmGGWqqX","JkzUnYjB9t",
-"n1pmOKr8ys","qUJMdYOfrY","RACuj4dEz6","POUYSKsjRK","Yw2oUjS1aj","euZA5NhXdu","Cfgr345cIH","aDGtSQ6Lix","4QMc9pWiOs","J2mQih1zcH",
-"9iGoTprNT6","yEfy9Ss0Zu","G1RhSI7p2a","8FmFH5IhmG","rhl0JfmIK1","uQIczF6PT2","faHirSmGzv","0BmCytlILt","MmKGJe6e4z","PYBf4No0Qb",
-"2Yz7EUvlv4","hSSvQs7Mxk","S77LHQClRL","HzZT8wDajX","48cHLrhl0J","fFDrJGv3Fq","dmoS72Yz7E","ciuWzZuDtD","piJSktjQxs","VjCZqdpe1v",
-"fcJOyFcWrW","ciuWzD6rBy","uAWypblLA9","cShY2i3pyd","Uvlv40BmCy","9iGoThe9IA","ZzJHWCfgr3","Oz8yZJkzUn","5iGN5CK5W7","VLTy6QbxXc",
-"XflUqI7p2a","QYxC0OHaBz","8U2nUfcwDa","taOXK24ARF","Dz1R3kZANm","yEfy9AgJHQ","aez9yWDVWJ","QbxXcFjHXR","iqv4kGv3Fq","fqypyxciqp",
-"dmoS7pWiOs","rz7UtPOUYS","CxVEfVerEA","XyPZNv8yFN","l83UdQworu","2Yz7EzFgtB","MGlTFO3iyQ","tjQxs0PktI","Dz1R3o8Uyd","2DREsQClRL",
-"9eoRcVNCPd","o8UydsuY4x","WDVWJuAWyp","tlILtwiHrZ","xXTI4vkCHH","VIlwPJ2mQi","RpBQmStlDJ","zHF1qs93Ml","zqH0WVerEA","1v5hHy94nw",
-"3weIFtlILt","Z4I1vcmXIX","S77LH8cVD3","TwanoKZamH","rhl0JKZamH","HfyNQwiHrZ","okgRiv2eC3","sqVrf3weIF","uoStwZuDtD","K4GS8C2Irc",
-"IBe8kZzJHW","AOgEezHF1q","2ZHdkcQOnv","AIYUuSs0Zu","uPX7G7X3uy","Yf2Ect59lR","zFgtBiKqhr","gf8rIJkzUn","FxX9qzHF1q","prNT60h1b1",
-"gjUTuaL6AJ","rz7UtTXQ0Z","uQIcziwzGk","QChxse6e4z","SjskQZv7z0","JIqXiEoToP","oVQp664s8N","S77LHx3LDe","C2Irc8FmFH","suY4xpv0i7",
-"vkCHHgIYvE","lViBvdjsrv","4dEz6FFDui","yofH3Cfgr3","fLNg8ru4UG","oQ87ruoStw","QbxXcSbRYy","yvOMIVIlwP","UmaEv1v5hH","OHaBzZ4I1v",
-"Oz8yZ8U2nU","LbRTHWPmlx","RmDcrfqypy","5nmWvGv3Fq","ThjNnOxWIH","SjskQZzJHW","yluBxQChxs","uJScXVprf2","IKxdLQssNC","8U2nUxciqp",
-"Oz8yZtAOsr","Oz8yZFxX9q","SbRYyB3qem","FxX9qcmXIX","MGlTFLewvM","SWfouUl4a1","tjQxs8cVD3","9y4lwe6e4z","AgJHQlpF6W","tl72W8FmFH",
-"FNYIM16lHc","jiVBPjSjS3","dQ586m4bxU","VNCPdW7cTs","OHaBzdmoS7","oQ87ryvOMI","TXQ0ZnnP8o","tAOsrAIYUu","fqypyguMb8","5IhmGThjNn",
-"lViBvatef2","faHirv2eC3","hUTw7OxWIH","gdQsS9iGoT","tlILto8Uyd","C2Irc7hyVv","4W0TlyToGW","pFrrlzz4ZU","G1RhSRsQUq","Z4I1vUlU3M",
-"suY4xtl72W","WmadAlXFOB","Kr8ysblLA9","GXdoHmX2GE","n1pmOMezSW","jtn0XBGaQY","Y1mC0nnP8o","POUYSqaofN","2hEEUKr8ys","Ss0ZuVIlwP",
-"t59lRpv0i7","CIShG8cVD3","No0Qbv8yFN","TCgPpYh1hF","aDGtS0Wr5y","Mm8siMmKGJ","WreyPLDk6f","x3LDeYjB9t","1LB1LJXljW","LDk6ffLNg8",
-"ReKEWIn3NS","Q6Lix2ZHdk","VIlwPqUJMd","StlDJWaim6","0MR5XWaim6","VerEAv8yFN","JJs5mMGlTF","WPmlx0PktI","VerEAG1RhS","FNYIMCNHmv",
-"CxVEf29QAz","4QMc9VNCPd","CNHmvatef2","5NammtuDyS","BpYhVv1Hln","JkzUn2Yz7E","RACujF6PT2","VIlwPGv3Fq","dQ586uvf7A","ECMvUxciqp",
-"QYxC04dEz6","J2mQi45cIH","TXQ0Zfqypy","OxWIHmz8gx","AOgEeVBjhz","CdyBVzz4ZU","uPX7Gaez9y","AXpwETCgPp","G1RhSzmLYD","2Yz7ESmGzv",
-"uQIczni2v1","iqv4kpv0i7","lm0pDRkQke","MK07YZJTXH","MezSWgf8rI","SmGzvkB5nP","kZANmpmeCd","yluBxFjHXR","kB5nPlm0pD","iqv4k5drc6",
-"8cVD3RpBQm","WaWsvjS1aj","fqypySmGzv","ZzJHWiqv4k","gtCA5n8pJ9","ReKEWJ2mQi","16lHciKqhr","GXdoH9y4lw","dhSuHBCxeC","Ss0Zu29QAz",
-"VLTy68xEKz","POUYSs7Mxk","lkMUA0ao3l","QnJ1SZuDtD","SmGzvFLsph","ix74rFGzgp","45cIHRxrsm","VerEAOHaBz","dhSuHFxX9q","ydG8UblLA9",
-"uAWypWPmlx","EdBKcfcwDa","ulk41lXFOB","fLNg8QYxC0","MGlTFM3zXL","ulk41HP433","lkMUAZ4I1v","HP433pvgjS","4dEz6QssNC","wiHrZ9iGoT",
-"ZUnqt0Wr5y","CqqaDZUnqt","7fKYUuTacx","ZzJHWW7cTs","lpF6W0Wr5y","0ao3lZhwG1","he9IAfcwDa","lpF6Wix74r","BGaQYuZPqg","mz8gxtvdkD",
-"Yf2EcjiVBP","3weIF55rfB","zbIYYQChxs","6AFT0StlDJ","QnJ1SIKxdL","Yw2oUFnPFB","cQOnvdjsrv","iqv4knnP8o","ogLgcsqVrf","0PktIuZPqg",
-"Cfgr3iqv4k","h1zcHWPmlx","48cHL580YD","Yh1hFDG4sT","uTacxWmadA","aDGtS9XyT9","NAFuwAIYUu","AIYUufmIK1","5nmWvCp3mZ","XyPZN7fsYM",
-"gtCA5zbIYY","RxrsmB3qem","ZzJHWmz8gx","NhXdufmIK1","x3LDeLewvM","NhXduuTacx","lViBvrhl0J","W7cTsFjHXR","tuDySl83Ud","2TRI7zz4ZU",
-"SjskQXflUq","cL0aEkZANm","zbIYYFcWrW","MojnPuTacx","YjB9tCdyBV","FGzgp7X3uy","zQt6Q0YAGH","SmGzvBbwgA","hYBCK16lHc","CK5W7yToGW",
-"Q6LixpiJSk","iKqhryluBx","JKWYRtAOsr","jfREuCqqaD","oVQp6XyPZN","BbwgA9rlg9","uupzkatef2","MezSWuJScX","4QMc9hE1Ql","jSjS3WaWsv",
-"MGlTF8RCUA","XflUqtAOsr","6AFT0HzZT8","8RCUAlViBv","Oz8yZKASQ8","24ARFFPfSE","xReectl72W","7lUXZWaim6","b29RJxXTI4","Y1mC0BpYhV",
-"8TxD75Mg9r","qQxHPSjskQ","lCMxyMmKGJ","QworuYh1hF","UlU3M7hyVv","JXljWWPmlx","S2Dfu55rfB","zFgtBFhtgl","OUqFMsoy9t","L7cGcP6bcg",
-"Yw2oUNhXdu","RkQkehi5X7","LbRTHI7p2a","M6qcG5VZjS","xReecHlUbF","M6qcGWaWsv","SWfou2Yz7E","LewvMwiHrZ","BFkb8Ta8f6","gf8rIMGlTF",
-"AgJHQMaJQs","guMb8aDGtS","gdQsSUl4a1","DLhzMGv3Fq","CdyBVM3zXL","EOE1oDz1R3","uN6r30BmCy","QClRLUvlv4","iwzGkTwano","dmoS7zmLYD",
-"uupzk2ZHdk","9rlg9FjHXR","v2eC3Vprf2","lj07Q7ku1p","s93MlIn3NS","QbxXcfmIK1","45cIHdQ586","pv0i7NAFuw","n1pmOMojnP","FFDuiLewvM",
-"y94nwCxVEf","gIYvEB3qem","MGlTFs93Ml","hE1Qlt59lR","VerEAhUTw7","fcJOyQ6hMC","OUYuFni2v1","BFkb8JRJQB","gjUTuGXdoH","8cVD3hUTw7",
-"0MR5XsqVrf","TwanociuWz","uJScXZJTXH","Vprf2guMb8","64s8Nxciqp","ydG8URzaZA","djsrvWDVWJ","BFkb8Dz1R3","lsQGoMK07Y","7Ow5CQ6Lix",
-"JIqXiRxrsm","8U2nUfaHir","tjQxsix74r","CxVEfuN6r3","UlU3MuoStw","P6bcg4QMc9","MK07YECMvU","SWfouzz4ZU","dhSuH9eoRc","guMb8zQt6Q",
-"s4786tl72W","ZuDtDLDk6f","RkQkePOUYS","euZA5aFFss","TCgPpMGlTF","vOqCEAXpwE","Yh1hFxReec","uQIczStlDJ","Nxx9VF6PT2","GSQwjNhXdu",
-"qUJMdI7p2a","ogLgcFcWrW","hSSvQQssNC","14FLR8RCUA","Nxx9VcmXIX","EdBKcOUYuF","NAFuwL7cGc","azIWp4QMc9","uQIczK20wK","ru4UGv8yFN",
-"ni2v129QAz","ksJbyuPX7G","9y4lwJJs5m","9iGoTdhSuH","GrDg7tuDyS","jS1ajZUnqt","EOE1oOUYuF","5nmWvgIYvE","9GXkXFwEJz","oVQp67fsYM",
-"oVQp6gtCA5","Oz8yZMmsIo","55rfBmz8gx","tlILtNAFuw","aDGtS14FLR","CIShGBCxeC","Zv7z0VIlwP","sx5GlqQxHP","Y1mC0t98iW","G1RhSru4UG",
-"FwEJzNAFuw","AgJHQ3weIF","gdQsS5VZjS","SWfouLewvM","ogLgc9GXkX","W3VFHaDGtS","1j5L80Wr5y","uTacxlweGy","2TRI7Fhtgl","0h1b1uAWyp",
-"fcwDaHfyNQ","7X3uyHRxd8","07n1ciqv4k","WreyPjeskS","8xEKzFhtgl","Z4I1vVprf2","9eoRcDz1R3","ZJTXH9eoRc","5NammVLTy6","VIlwPWaWsv",
-"ogLgcv1Hln","7fKYUQworu","ni2v12ZHdk","Pb1pafcJOy","9y4lw0YAGH","uN6r32ZHdk","I7p2aRpBQm","KASQ8Twano","LDk6fHRxd8","HP433lViBv",
-"zFgtBTa8f6","OUqFMy94nw","FFDuiMm8si","ZzJHWNhXdu","ZJTXHK4GS8","FGzgpMGlTF","b29RJuupzk","WDVWJd7vjM","zHF1qfcwDa","gjUTuuJScX",
-"C2IrcfLNg8","ZzJHWXflUq","Mkgy8m4bxU","yvOMIVerEA","xXTI40ao3l","jfREuIBe8k","3weIFnlaBy","cmXIXjS1aj","7ku1p8U2nU","ksJbyWreyP",
-"b29RJZuDtD","uPX7GBpYhV","ZUnqtSjskQ","MezSWlpF6W","QssNC1LB1L","Y1mC0B3qem","HfyNQiB08l","JXljWpWiOs","Cp3mZeuZA5","dhSuHzbIYY",
-"IBe8kAOgEe","qaofNBGaQY","prNT6vLsmS","DG4sT3otm6","DG4sTPOUYS","xReecKZamH","gf8rInlaBy","Waim6EoToP","iKqhr5Namm","GXdoHdhSuH",
-"F6PT2NhXdu","AIYUu5ZaEz","7lUXZMmKGJ","okgRimX2GE","XyPZNWmadA","jSjS3QChxs","iB08lUvlv4","Ta8f6fmIK1","P6bcg7fsYM","aFFssGXdoH",
-"L7cGcD6rBy","BpYhVjS1aj","t98iW0PktI","ReKEWprNT6","jfREu5Namm","FnPFBVNCPd","d85a9ix74r","9rlg9lkMUA","YjB9tyToGW","9y4lwNAFuw",
-"AkKTkvLsmS","nnP8oChuy3","qaofN6AFT0","0MR5XazIWp","RsQUqCNHmv","jtn0X5VZjS","sx5GlL7cGc","2NslmBFkb8","QssNCrz7Ut","FjHXRfaHir",
-"2ZHdks93Ml","4QMc9iqv4k","WPmlxEOE1o","ZzJHWM3zXL","SmGzvWaim6","SWfou7ku1p","O3iyQZv7z0","qQxHP0Wr5y","jzUqRBGaQY","DG4sTQYxC0",
-"BFkb8StlDJ","djsrvKZamH","lsQGopFrrl","i3pydzbIYY","euZA5Gv3Fq","gtCA5Yw2oU","aez9ysoy9t","5Mg9rpWiOs","zmLYDs93Ml","lj07QqUJMd",
-"uZPqgmz8gx","iB08l9iGoT","lH1ktJ2mQi","5IhmGBpYhV","AXpwEDcpWB","m4bxU8hJdt","4dEz6yluBx","IjTwPW7cTs","C2IrcjfREu","wDajX8TxD7",
-"64s8NNOHsz","0PktIjSjS3","zqH0WeuZA5","uPX7Gxciqp","uJScXi3pyd","bgJAzuQIcz","8FmFHZUnqt","fcJOynnP8o","S77LHZv7z0","ru4UGciuWz",
-"ZuDtD64s8N","Nxx9Vsoy9t","FPfSEjfREu","NcICAAmdQd","fcwDa7fKYU","L7cGcjtn0X","lweGyRmDcr","o8UydRmDcr","LewvM5ZaEz","fLNg8W3VFH",
-"NcICAuTacx","KZamHKZamH","TwanoEdBKc","VBjhzzQt6Q","M3zXLatef2","fqypylViBv","U3yw5b29RJ","euZA5Yf2Ec","jS1ajVNCPd","WMiS3atef2",
-"xciqpOUYuF","WreyPJRJQB","bZLvScmXIX","e6e4zprNT6","6AFT0Gv3Fq","TXQ0ZTXQ0Z","mz8gxFcWrW","ru4UGyofH3","uoStwt98iW","jS1aj55rfB",
-"jeskSWaWsv","jS1aj4W0Tl","POUYS1v5hH","ulk41Oz8yZ","sqVrfCxVEf","45cIHv8yFN","lm0pDwDajX","BCxeCGv3Fq","xXTI4RBhp0","Uvlv4jfREu",
-"8cVD3lH1kt","P6bcg1LB1L","pv0i7CNHmv","Ta8f6K4GS8","64s8NaFFss","tl72WMK07Y","JkzUn1LB1L","gIYvEGXdoH","AgJHQ618Di","AkKTk8FmFH",
-"OxWIHuJScX","07n1cs7Mxk","RACuj9y4lw","Yh1hFpvgjS","HP4339GXkX","FjHXRAgJHQ","cShY2Vprf2","Waim67Ow5C","MezSWX6Pin","uJScXJ2mQi",
-"aFFss55rfB","WreyPksJby","G1RhSzQt6Q","NhXduS77LH","n8pJ9s93Ml","8RCUApAhR1","5ZaEzVBjhz","KsjRKt98iW","Q6hMCy94nw","CNHmvVBjhz",
-"7ku1ps4786","bZLvSsqVrf","G1RhSNcICA","2ZHdkFGzgp","2NslmnnP8o","5iGN5JIqXi","dhSuHuAWyp","1j5L8Zv7z0","2DREslH1kt","nFqik2DREs",
-"pAhR1djsrv","TCgPp4W0Tl","soy9thUTw7","n8pJ90MR5X","mX2GElkMUA","CxVEfulk41","TCgPpZUnqt","VNCPdrhl0J","dmoS7oVQp6","QClRLqaofN",
-"K4GS8s7Mxk","VBjhzv1Hln","y94nwLbRTH","Cp3mZP6bcg","FcWrWC2Irc","h1zcHB3qem","RsQUqSmGzv","JIqXilCMxy","Nxx9VNhXdu","HP433POUYS",
-"qaofNLbRTH","J2mQiPOUYS","Kr8ysZhwG1","WaWsv2hEEU","taOXKJkzUn","1v5hHuZPqg","uvf7ANAFuw","SjskQ5drc6","FGzgps7Mxk","yluBxcmXIX",
-"X6PinAmdQd","K20wKMm8si","gf8rIzFgtB","bZLvSfLNg8","5drc6AkKTk","Kr8ys8xEKz","StlDJtjQxs","uJScX9rlg9","iB08leuZA5","uZPqg55rfB",
-"d7vjMeuZA5","hi5X7blLA9","nFqikzmLYD","KZamHlsQGo","7fsYMVprf2","ciuWzUmaEv","07n1ca00b5","QssNClkMUA","aL6AJuN6r3","hUTw7ix74r",
-"8U2nUx3LDe","rhl0JgdQsS","RmDcrzqH0W","M6qcG9XyT9","FjHXRCqqaD","MojnPgjUTu","Q6hMC9eoRc","qQxHPuZPqg","iKqhrFNYIM","1v5hHn8pJ9",
-"k85AeWaim6","GrDg7Yw2oU","uvf7AFLsph","k85Aesoy9t","VjCZqhe9IA","8hJdt8cVD3","FPfSEfLNg8","Zv7z0Ul4a1","uZPqgtvdkD","blLA90h1b1",
-"VerEAvLsmS","ru4UG8TxD7","FPfSEuPX7G","7fKYUzmLYD","In3NS2TRI7","ECMvUWmadA","FGzgplViBv","lH1ktUvlv4","vOqCEuJScX","Mm8simz8gx",
-"okgRiazIWp","Yh1hFNhXdu","zQt6QYOfrY","No0QbNo0Qb","WDVWJS2Dfu","i3pyd29QAz","MezSWgdQsS","2NslmpmeCd","vkCHHn8pJ9","faHirZJTXH",
-"M3zXLpFrrl","uLtKsWDVWJ","faHirxReec","Yh1hFv2eC3","2Yz7EQClRL","5IhmGkZANm","fcJOyfcJOy","SmGzvX6Pin","9rlg9QbxXc","RBhp0zQt6Q",
-"gjUTu9iGoT","cShY2G1RhS","vLsmSe6e4z","AgJHQlj07Q","wDajXAXpwE","dhSuHAmdQd","0ao3llH1kt","TCgPpSs0Zu","Dz1R3MojnP","o8UydokgRi",
-"DLhzMgtCA5","zz4ZUn8pJ9","QnJ1SoQ87r","vOqCEd7vjM","gjUTuVNCPd","Gv3FqSbRYy","uLtKscL0aE","5VZjScQOnv","lViBvxXTI4","0ao3l580YD",
-"Nxx9Vk85Ae","8U2nUMojnP","14FLRru4UG","iqv4koQ87r","Nxx9V1LB1L","s4786vOqCE","a00b50Kyfs","OUYuFRxrsm","07n1cuZPqg","0PktIrhl0J",
-"prNT6okgRi","gIYvEuupzk","CNHmvFcWrW","HlUbFUl4a1","hUTw7fcwDa","580YDcmXIX","YjB9tkZANm","prNT60ao3l","fLNg8CqqaD","Kr8ysUmaEv",
-"rz7Ut9GXkX","RpBQmzqH0W","lkMUAMojnP","xReecCK5W7","Dz1R3CIShG","xReecuN6r3","gdQsSHfyNQ","zbIYYO3iyQ","QClRLMaJQs","atef2oQ87r",
-"Yw2oUd85a9","8cVD3OUYuF","xReechi5X7","zmLYDBbwgA","OHaBzRBhp0","5Mg9rRBhp0","9iGoTzmLYD","7hyVvlpF6W","48cHLCIShG","VNCPdfLNg8",
-"5iGN5lViBv","ix74rkB5nP","o8UydoVQp6","DG4sTv2eC3","kZANmlkMUA","5Mg9rKZamH","y94nwbgJAz","zHF1qPOUYS","2DREse6e4z","7fKYUlViBv",
-"gjUTuyEfy9","IRh487Ow5C","uN6r3brhlQ","K20wKKsjRK","xciqpjzUqR","uupzkMojnP","2Yz7EblLA9","pT8wuRACuj","POUYSt98iW","29QAz45cIH",
-"ix74rVNCPd","v8yFNXyPZN","vkCHHQ6Lix","UmaEvogLgc","ZJTXHChuy3","pAhR1QnJ1S","DcpWBNOHsz","MojnP8xEKz","pT8wuFFDui","Rxrsmhe9IA",
-"1LB1LWDVWJ","azIWpni2v1","X6PinAkKTk","2DREsGWqqX","fFDrJ9y4lw","aez9ypv0i7","WDVWJdmoS7","OHaBz8FmFH","nlaBy29QAz","WreyPcL0aE",
-"QnJ1SFxX9q","9eoRc5iGN5","zbIYYVjCZq","64s8No8Uyd","uoStwyEfy9","CxVEfy94nw","KASQ8gtCA5","tl72WDz1R3","dQ586ni2v1","rhl0JKr8ys",
-"2hEEUJRJQB","e6e4zyEfy9","lXFOBUvlv4","K20wKVNCPd","9XyT9nnP8o","NhXduksJby","0MR5Xlm0pD","O3iyQ45cIH","lkMUA9iGoT","KZamHlXFOB",
-"jfREu1v5hH","Uvlv4StlDJ","soy9tgtCA5","GrDg78cVD3","WMiS3OxWIH","aFFssUl4a1","yEfy9DQimp","HP433zqH0W","lsQGolsQGo","RzaZAEOE1o",
-"VNCPdGrDg7","hi5X7Chuy3","fcwDaM3zXL","VNCPdbrhlQ","MGlTFe6e4z","VerEAIjTwP","cmXIXksJby","W3VFH2Nslm","7fKYUlweGy","jS1ajFnPFB",
-"HP433RBhp0","CqqaDNAFuw","8TxD7FFDui","7Ow5CyEfy9","WreyPhE1Ql","yEfy9VBjhz","GrDg7rz7Ut","zz4ZUbZLvS","GrDg7JKWYR","FNYIM5Drn0",
-"s4786WreyP","WaWsv29QAz","GSQwjMK07Y","Nxx9V2DREs","580YD580YD","ZhwG1xReec","jtn0XCdyBV","LewvMNcICA","2hEEURzaZA","2hEEUzFgtB",
-"FjHXReuZA5","3otm6uupzk","BFkb816lHc","x3LDeEoToP","Chuy3gdQsS","dQ586YjB9t","mz8gxCfgr3","mz8gxciuWz","i7WMQsoy9t","Yh1hFFcWrW",
-"xReecPb1pa","48cHLLewvM","atef2Ss0Zu","KZamHs93Ml","IRh4845cIH","rhl0JTXQ0Z","6AFT0WMiS3","pFrrlEdBKc","vkCHHWaim6","ksJbycmXIX",
-"tuDySY1mC0","TCgPpM6qcG","ECMvUyofH3","P6bcgulk41","CNHmvJKWYR","VjCZq5VZjS","OxWIH14FLR","7Ow5CqUJMd","LDk6fqQxHP","pAhR1VIlwP",
-"dpe1vAXpwE","0ao3lRmDcr","0h1b1IRh48","HfyNQGrDg7","fqypyKZamH","fcJOyI7p2a","KsjRKsx5Gl","OUYuFSbRYy","dpe1vHP433","AmdQdnlaBy",
-"JKWYRyvOMI","vOqCES2Dfu","QbxXclXFOB","bZLvSU3yw5","FFDuioVQp6","ZhwG124ARF","RxrsmFPfSE","IKxdL07n1c","hUTw7lH1kt","e6e4zW7cTs",
-"zbIYYlm0pD","ix74rnFqik","yluBxbgJAz","5iGN5IBe8k","suY4xo8Uyd","uupzkyofH3","POUYSECMvU","MaJQsuPX7G","aDGtShE1Ql","dhSuHOUYuF",
-"tl72WxXTI4","IjTwP0PktI","1v5hHksJby","tl72WiKqhr","9XyT9B3qem","MK07YydG8U","U3yw5gf8rI","bZLvSuvf7A","14FLRRxrsm","TXQ0ZFhtgl",
-"Yh1hFZzJHW","VNCPd7ku1p","1LB1LZv7z0","POUYSo8Uyd","0h1b1tvdkD","VNCPdfmIK1","K4GS8cQOnv","xciqptjQxs","RzaZAWMiS3","QWxoTtl72W",
-"JkzUnZ4I1v","VNCPdAmdQd","K4GS8a00b5","faHiruN6r3","lpF6WBpYhV","ZuDtD16lHc","FjHXRFGzgp","5Drn0KASQ8","EoToPgdQsS","zFgtBmz8gx",
-"5ZaEzDz1R3","ZUnqtRzaZA","PYBf4uZPqg","FwEJz9y4lw","pvgjS8xEKz","m4bxUFnPFB","xXTI48hJdt","In3NSzFgtB","VjCZqd85a9","8hJdtyofH3",
-"24ARFSs0Zu","ZzJHWKASQ8","6AFT0tuDyS","W3VFHNcICA","MGlTFMGlTF","580YDqQxHP","2Yz7EIRh48","AkKTkuN6r3","brhlQtaOXK","WaWsvCIShG",
-"n1pmOjS1aj","0Wr5yyluBx","1j5L8O3iyQ","HfyNQ7lUXZ","SWfougjUTu","JRJQBZJTXH","okgRiYjB9t","S77LHogLgc","9iGoTVerEA","t59lRQnJ1S",
-"6AFT05nmWv","ni2v1J2mQi","AgJHQcmXIX","cShY2tvdkD","TXQ0Zt98iW","7fKYUpvgjS","BFkb8mX2GE","Yf2Ec24ARF","EoToPbZLvS","yEfy945cIH",
-"UlU3MMkgy8","5iGN55drc6","M3zXL5Drn0","5VZjSru4UG","14FLRjS1aj","K4GS8WreyP","brhlQeuZA5","ni2v1M6qcG","soy9tk85Ae","gtCA5jSjS3",
-"s7MxkJ2mQi","ThjNntAOsr","cL0aEpAhR1","tl72WRkQke","v2eC3QClRL","P6bcglCMxy","QYxC0Q6Lix","djsrvIBe8k","TCgPp4QMc9","5Mg9riKqhr",
-"lH1ktgdQsS","FxX9q4QMc9","2Yz7E1v5hH","okgRis93Ml","lpF6W45cIH","5nmWvoGu6x","6q6L9Q6hMC","fLNg8nFqik","ZuDtD45cIH","k85AelH1kt",
-"P6bcgjtn0X","8U2nU7fsYM","tvdkD9GXkX","blLA9ksJby","vOqCE7hyVv","iwzGkogLgc","CqqaDd85a9","aDGtSblLA9","nFqikPOUYS","ThjNnBCxeC",
-"RACujvLsmS","9GXkXJRJQB","oVQp6iB08l","xReecI7p2a","qaofNs7Mxk","SbRYyGWqqX","Chuy3Vprf2","FwEJzdpe1v","soy9tpv0i7","BGaQY9GXkX",
-"ciuWzgtCA5","580YDdjsrv","dhSuHHRxd8","bgJAzzY1GY","FjHXR4dEz6","HRxd8AgJHQ","iwzGkhi5X7","VBjhzjeskS","OxWIHbgJAz","uZPqgzY1GY",
-"8cVD3YjB9t","pAhR15VZjS","gjUTuni2v1","zFgtBGWqqX","pAhR1s93Ml","BFkb8wDajX","kB5nP9XyT9","zFgtBFNYIM","NcICA1v5hH","LewvMUvlv4",
-"AOgEeNo0Qb","0PktINOHsz","prNT6taOXK","zbIYYlViBv","guMb8RzaZA","kZANm14FLR","9GXkX5VZjS","OHaBzGrDg7","EoToP0Wr5y","aL6AJdjsrv",
-"MojnPfaHir","Ss0Zux3LDe","cQOnvjSjS3","0ao3lCxVEf","fqypyfFDrJ","IRh48dQ586","8xEKzS77LH","dQ5862hEEU","dQ586lsQGo","4QMc9sx5Gl",
-"DcpWBzz4ZU","gjUTuIBe8k","SbRYypvgjS","uTacxgf8rI","lm0pDWPmlx","Oz8yZgf8rI","0ao3l9y4lw","XyPZNcL0aE","kZANmYOfrY","Yf2EcF6PT2",
-"No0QbokgRi","B3qems4786","blLA97lUXZ","MK07YOxWIH","0Wr5yd7vjM","5IhmGJRJQB","MmKGJ9XyT9","JkzUnW7cTs","pmeCdUlU3M","lCMxyulk41",
-"0KyfsXyPZN","VjCZqWaim6","Ta8f6tAOsr","64s8NSWfou","7Ow5Ctl72W","Cp3mZK4GS8","PYBf4WMiS3","VjCZqd7vjM","EOE1o0YAGH","rKDLJru4UG",
-"JXljWNcICA","aL6AJyvOMI","jfREue6e4z","TCgPpdjsrv","GrDg7aL6AJ","KZamHWMiS3","tjQxs8RCUA","5drc6oGu6x","64s8Njtn0X","D6rByLbRTH",
-"CdyBVJkzUn","lXFOB5Mg9r","LewvMoGu6x","zQt6QpmeCd","2NslmMmKGJ","JJs5mpFrrl","qaofN9GXkX","MaJQs1j5L8","CxVEf6q6L9","Kr8ysaDGtS",
-"Ul4a1t59lR","MaJQsksJby","VLTy6OUqFM","mX2GElpF6W","VjCZqBGaQY","Cp3mZ5IhmG","DLhzMVprf2","0MR5XpFrrl","JXljWVLTy6","uJScXThjNn",
-"BGaQYStlDJ","FnPFBRpBQm","fcwDaOUYuF","C2IrcQWxoT","iqv4kMojnP","uupzklXFOB","azIWpdQ586","MezSWF6PT2","MmKGJwiHrZ","GWqqXfqypy",
-"sx5GlJRJQB","0YAGHUmaEv","ru4UGX6Pin","ZUnqtXflUq","Chuy3FnPFB","dQ586jeskS","BFkb8JJs5m","cL0aEzz4ZU","7Ow5CMmsIo","QssNCkZANm",
-"618Div8yFN","pT8wuCqqaD","WmadAuoStw","O3iyQ5drc6","tl72W14FLR","45cIHNhXdu","wiHrZxXTI4","xciqptuDyS","45cIH8hJdt","FPfSElpF6W",
-"8xEKzmz8gx","FVMxoFVMxo","RkQkeCdyBV","8xEKzuTacx","tl72W3weIF","LbRTHDcpWB","qUJMdD6rBy","HP433IRh48","fcJOyFxX9q","KASQ8pAhR1",
-"oGu6xxciqp","U3yw5WDVWJ","SWfouHP433","YjB9ttl72W","y94nw2ZHdk","FjHXR4QMc9","Ul4a1qUJMd","ni2v1lpF6W","gdQsSYw2oU","piJSkatef2",
-"qUJMdydG8U","U3yw57lUXZ","I7p2aTCgPp","MojnPYjB9t","jfREutl72W","9eoRcCfgr3","vkCHHZ4I1v","M3zXLzmLYD","euZA5FxX9q","4W0Tlh1zcH",
-"55rfBZv7z0","QClRLlj07Q","hSSvQnlaBy","xReecmz8gx","euZA5BGaQY","7hyVvMojnP","he9IA7ku1p","14FLRU3yw5","v1Hln2Yz7E","QYxC0VLTy6",
-"ZzJHWGWqqX","5drc6pAhR1","yToGWd7vjM","zmLYD9rlg9","Yf2EcRkQke","KsjRKJKWYR","MGlTF1LB1L","GXdoHiwzGk","SjskQ8cVD3","OUYuF8U2nU",
-"uZPqg0ao3l","ydG8UuJScX","HRxd8RACuj","In3NSeuZA5","gjUTuoQ87r","ru4UGfcJOy","5nmWvMK07Y","2DREscShY2","he9IAaDGtS","t98iWlpF6W",
-"NOHsz2Yz7E","pT8wu9iGoT","Waim614FLR","v2eC3MmsIo","0Wr5yPb1pa","1v5hH5iGN5","DcpWBi7WMQ","sqVrfdjsrv","ECMvU29QAz","d7vjM7ku1p",
-"GrDg7d7vjM","SmGzvtaOXK","tl72WeuZA5","M6qcGokgRi","K4GS8v2eC3","jeskSUlU3M","hi5X7GXdoH","7ku1plkMUA","Uvlv4ThjNn","i3pyd0Kyfs",
-"16lHcY1mC0","pT8wuNOHsz","7fKYUXflUq","JKWYRRpBQm","JkzUncQOnv","618DiQssNC","KZamH0h1b1","QClRLzFgtB","tvdkDfaHir","cmXIXyofH3",
-"DG4sTfLNg8","hE1Qld85a9","FVMxoaFFss","mX2GE5Mg9r","tvdkDi7WMQ","uPX7GBFkb8","lXFOBuPX7G","4W0Tl9XyT9","Yf2EcfcJOy","dmoS7zFgtB",
-"WreyPoVQp6","G1RhSHlUbF","tvdkDEdBKc","rhl0JAgJHQ","MmsIoYOfrY","GrDg7yEfy9","nnP8oDLhzM","v1Hln7lUXZ","dmoS7Pb1pa","8hJdtKZamH",
-"ulk4164s8N","CK5W7tuDyS","he9IAI7p2a","1LB1LBGaQY","QworuVLTy6","XyPZN48cHL","GrDg7v1Hln","tAOsrsx5Gl","7Ow5C0MR5X","MGlTFlm0pD",
-"J2mQibrhlQ","FwEJzDz1R3","5iGN5faHir","ZuDtDuN6r3","0MR5Xru4UG","XyPZNe6e4z","cShY224ARF","4QMc9zmLYD","TCgPpNxx9V","tvdkDuoStw",
-"RzaZABGaQY","AkKTkOUqFM","fqypyVerEA","vLsmSCqqaD","VIlwPJXljW","FjHXRHRxd8","iKqhr2Yz7E","djsrvqaofN","8RCUA0Wr5y","jeskSs4786",
-"ECMvUFcWrW","uN6r3cL0aE","gtCA5X6Pin","NAFuwRpBQm","W7cTshSSvQ","0Wr5y7Ow5C","Kr8ysIn3NS","M3zXLogLgc","Yf2Ecd85a9","zY1GYHlUbF",
-"0YAGHyvOMI","WPmlxzqH0W","IKxdLpmeCd","hSSvQRBhp0","6q6L9Yh1hF","n8pJ9BFkb8","prNT62ZHdk","0BmCyOUYuF","48cHL618Di","d85a9rKDLJ",
-"l83UdY1mC0","uupzkbrhlQ","piJSkSs0Zu","djsrv5Drn0","KZamHF6PT2","iwzGkCIShG","WmadAaL6AJ","faHirEOE1o","5NammM3zXL","FVMxoP6bcg",
-"7fKYUS2Dfu","OUYuFUmaEv","5NammLDk6f","uLtKsOUYuF","2Yz7EQssNC","2Yz7EjfREu","4dEz6FwEJz","ReKEWZhwG1","5ZaEzeuZA5","euZA5vkCHH",
-"OxWIHksJby","9y4lwuvf7A","pv0i7okgRi","tAOsrfcwDa","taOXKWPmlx","5Drn0nnP8o","oGu6x8hJdt","uTacxiwzGk","v1Hlnzz4ZU","6q6L9yToGW",
-"hi5X7VIlwP","dQ586BCxeC","QChxsbgJAz","FLsphuQIcz","HzZT83otm6","29QAzWaim6","jiVBPGv3Fq","yToGW5Namm","Nxx9VIRh48","wDajX0Wr5y",
-"tvdkDgdQsS","tlILtJJs5m","n1pmOtvdkD","gf8rIDLhzM","KASQ8QbxXc","0h1b1MGlTF","BCxeC7hyVv","CIShGni2v1","2NslmZv7z0","bZLvSUlU3M",
-"ZUnqtgf8rI","WMiS3suY4x","LDk6fZv7z0","ThjNnzFgtB","LDk6fQClRL","bZLvS0h1b1","pT8wuMezSW","aez9yOHaBz","VIlwPuoStw","QbxXcZJTXH",
-"jfREuhE1Ql","yofH30Wr5y","gdQsSWaim6","BFkb8DG4sT","s7MxkpvgjS","Yw2oUOUqFM","SmGzvRxrsm","sqVrfhUTw7","WreyP07n1c","xXTI49eoRc",
-"FLsphzQt6Q","FhtglFhtgl","6AFT0QssNC","IjTwPFnPFB","iKqhruoStw","2hEEUNhXdu","55rfBUvlv4","RkQkeiwzGk","fFDrJIjTwP","pvgjSpvgjS",
-"8RCUAa00b5","LDk6fWmadA","MmsIoi3pyd","zY1GYKASQ8","F6PT2v2eC3","zY1GYb29RJ","vOqCECdyBV","d85a9HzZT8","cShY2FFDui","RkQkeb29RJ",
-"JXljW5Namm","piJSkFhtgl","s47869GXkX","CNHmv8cVD3","gIYvEDQimp","0PktIStlDJ","n8pJ9lXFOB","O3iyQYjB9t","SjskQjtn0X","tlILt8TxD7",
-"VerEAvOqCE","ru4UGWreyP","uAWypB3qem","618DiOUqFM","QssNCIKxdL","qQxHPi7WMQ","iqv4kuZPqg","oGu6x4W0Tl","JIqXiuZPqg","QssNCpAhR1",
-"rz7UtiKqhr","Q6LixWaWsv","oQ87rs4786","In3NSQ6hMC","RACujyToGW","M3zXLYOfrY","wiHrZuLtKs","FcWrW1j5L8","FcWrWTCgPp","LDk6fcShY2",
-"uPX7GWPmlx","FLsphKsjRK","he9IA64s8N","DLhzMHzZT8","FcWrWMGlTF","ru4UGni2v1","CdyBVTwano","580YDguMb8","t59lRCfgr3","piJSkni2v1",
-"OUYuFReKEW","5nmWv24ARF","cmXIXuZPqg","lkMUApAhR1","BGaQYL7cGc","ydG8UyEfy9","d7vjMXflUq","Nxx9Vhi5X7","ZzJHWXyPZN","1LB1LnFqik",
-"Ta8f6Oz8yZ","lH1ktpT8wu","Yf2EczQt6Q","64s8NqaofN","LewvM9rlg9","mX2GEn8pJ9","MojnPcQOnv","jeskSGv3Fq","8FmFHLDk6f","fLNg8CxVEf",
-"HP433FwEJz","64s8NfFDrJ","24ARFhSSvQ","nFqikdhSuH","2hEEUMkgy8","580YDJXljW","SbRYyEOE1o","v2eC3zFgtB","l83Udm4bxU","580YDCIShG",
-"FNYIMNcICA","0ao3lpWiOs","pv0i77fKYU","7X3uy5Namm","DcpWBFPfSE","DQimpYjB9t","gtCA58TxD7","QClRLEOE1o","RACujTwano","uN6r3JXljW",
-"o8UydRsQUq","OUqFMt98iW","fmIK1FVMxo","tlILtksJby","jzUqRHfyNQ","uAWyp9XyT9","L7cGcvOqCE","VBjhzZJTXH","uZPqghe9IA","9rlg9fmIK1",
-"zbIYY8TxD7","Ss0ZuQClRL","7ku1pVLTy6","FFDuiDz1R3","DcpWBCqqaD","CK5W7v2eC3","Ul4a1ECMvU","ru4UGMmKGJ","5VZjSuTacx","tAOsrS2Dfu",
-"GXdoHbrhlQ","cL0aEt59lR","5drc6HfyNQ","9XyT9YOfrY","djsrv8hJdt","tvdkDprNT6","Z4I1vlCMxy","S2DfuKr8ys","zz4ZUlXFOB","Yh1hFWDVWJ",
-"K4GS8okgRi","qaofNRkQke","qUJMdb29RJ","s93MlydG8U","v8yFNuTacx","CxVEfhUTw7","Q6LixdQ586","No0QbKr8ys","S2Dfuv2eC3","Oz8yZiB08l",
-"cmXIXtuDyS","TwanokB5nP","M6qcGlXFOB","AIYUuMGlTF","v1Hln0MR5X","KASQ8zqH0W","s7MxkCqqaD","6q6L9AmdQd","pT8wugf8rI","8hJdtlj07Q",
-"IRh48U3yw5","29QAzGrDg7","piJSk5nmWv","4W0TlLbRTH","lj07QF6PT2","0PktIlpF6W","t59lRuJScX","8TxD7WmadA","55rfBtAOsr","pT8wuzY1GY",
-"zQt6Q5VZjS","yToGWnFqik","wiHrZRmDcr","1j5L8AgJHQ","WDVWJO3iyQ","RzaZAJIqXi","gjUTun1pmO","14FLRqaofN","Uvlv4wiHrZ","lpF6W1LB1L",
-"7Ow5CLewvM","i3pydn8pJ9","JKWYR1v5hH","VNCPdQworu","P6bcgvOqCE","GXdoHo8Uyd","RmDcrsx5Gl","SWfoupvgjS","JXljWfcJOy","RBhp0suY4x",
-"JRJQBRpBQm","FPfSETCgPp","ogLgcAIYUu","VBjhzlj07Q","ix74rUmaEv","gf8rIwiHrZ","gf8rIUlU3M","2TRI7JKWYR","uAWypVIlwP","pFrrly94nw",
-"dmoS78U2nU","iB08l2ZHdk","he9IA5VZjS","h1zcH2Nslm","MaJQsxciqp","Yh1hF9rlg9","yToGWReKEW","LewvMEdBKc","x3LDeTXQ0Z","WDVWJU3yw5",
-"nlaByo8Uyd","i3pydsqVrf","pv0i7uvf7A","YjB9tuQIcz","618DiVjCZq","QChxsFNYIM","UlU3MQbxXc","d7vjMM3zXL","uAWypm4bxU","FxX9qzqH0W",
-"Zv7z0QYxC0","QChxsVprf2","piJSkReKEW","7Ow5CtAOsr","cQOnvaez9y","rKDLJ0ao3l","zFgtBbZLvS","XyPZNogLgc","RpBQmpv0i7","BFkb88TxD7",
-"2ZHdk64s8N","IjTwP5nmWv","lXFOBPYBf4","hSSvQqQxHP","AOgEen1pmO","Q6hMCD6rBy","yToGWGv3Fq","FwEJz5nmWv","Yw2oUAXpwE","pFrrljeskS",
-"fcJOyFjHXR","l83UdksJby","HlUbFwiHrZ","JJs5mMojnP","DQimpQ6hMC","5ZaEz9iGoT","Dz1R3QnJ1S","pvgjSl83Ud","m4bxUJXljW","Nxx9VhSSvQ",
-"WreyPkB5nP","S77LHd85a9","5VZjSQClRL","y94nwcmXIX","wDajXDG4sT","yvOMIMGlTF","vkCHHh1zcH","x3LDeydG8U","9GXkXTCgPp","lH1kttjQxs",
-"Yw2oU64s8N","d85a95iGN5","Gv3Fq45cIH","P6bcg29QAz","In3NSkB5nP","AIYUupiJSk","YOfrYUlU3M","uAWyp2DREs","UmaEv45cIH","v2eC3cmXIX",
-"jSjS3jzUqR","FPfSEC2Irc","gtCA59GXkX","M6qcGuN6r3","JKWYRVprf2","m4bxUpiJSk","zmLYDOz8yZ","cShY2ZUnqt","kB5nPDz1R3","lsQGoHP433",
-"m4bxURsQUq","v1HlnYOfrY","S2DfuVLTy6","azIWpdhSuH","O3iyQSbRYy","FNYIMksJby","No0QbFNYIM","lkMUACNHmv","cL0aEPYBf4","hi5X707n1c",
-"s93MlMm8si","JkzUn29QAz","CdyBVjzUqR","v2eC3dhSuH","jSjS3uoStw","fmIK1ThjNn","aL6AJEOE1o","1v5hHUl4a1","aez9yAgJHQ","m4bxUF6PT2",
-"tuDySuPX7G","8xEKz8cVD3","FGzgpFVMxo","taOXKRxrsm","Pb1pasqVrf","RmDcr4W0Tl","XyPZNNAFuw","0Kyfstl72W","9GXkXNcICA","BGaQYuPX7G",
-"5VZjSSs0Zu","DQimpxciqp","vOqCECIShG","lweGyb29RJ","gIYvEFPfSE","iwzGkyofH3","rKDLJv1Hln","zY1GYDQimp","dhSuHXyPZN","nnP8o0BmCy",
-"FPfSEMkgy8","Vprf2cQOnv","1v5hHBbwgA","Oz8yZ45cIH","BbwgAiKqhr","rKDLJjS1aj","6AFT0LDk6f","KsjRKMaJQs","5IhmGRzaZA","SWfoucQOnv",
-"WmadAtAOsr","pWiOsFcWrW","dhSuHK20wK","5iGN5VjCZq","iwzGkv8yFN","aez9yIn3NS","6q6L9fqypy","HP433lj07Q","jS1ajuJScX","1j5L8POUYS",
-"XflUqMaJQs","faHirzQt6Q","WPmlxmX2GE","wDajXpiJSk","MojnPOz8yZ","vkCHHnlaBy","PYBf4JRJQB","fFDrJU3yw5","uPX7GuLtKs","Ta8f6lH1kt",
-"lH1ktW3VFH","4QMc916lHc","jeskScL0aE","YOfrYkB5nP","zQt6QaL6AJ","C2Irc4W0Tl","5NammblLA9","gtCA5mX2GE","8xEKz8TxD7","a00b5hYBCK",
-"9XyT9FcWrW","nlaByDcpWB","MmsIo6AFT0","GWqqXk85Ae","LbRTHRzaZA","d85a9pFrrl","pAhR1mz8gx","rhl0JPb1pa","y94nwv2eC3","guMb87ku1p",
-"K20wKBbwgA","16lHcAIYUu","i7WMQ4QMc9","uoStw2DREs","Q6hMCVNCPd","gdQsSDG4sT","jS1ajSjskQ","HlUbFlm0pD","VjCZqjiVBP","7fsYMVLTy6",
-"IKxdLMmKGJ","k85Ae0MR5X","zFgtBni2v1","RBhp0QClRL","QChxssx5Gl","DG4sT6AFT0","zQt6Q0ao3l","ciuWzsx5Gl","FhtglL7cGc","1v5hH7fKYU",
-"pWiOstaOXK","gjUTu8xEKz","Ss0ZuJIqXi","TwanouZPqg","Mm8siuN6r3","7X3uyHP433","XflUqi7WMQ","Yw2oUuupzk","guMb8GrDg7","I7p2a0Kyfs",
-"1v5hHMojnP","FxX9qhUTw7","CNHmvZ4I1v","OUYuFQworu","FhtglF6PT2","tlILtP6bcg","Nxx9VzHF1q","pT8wulm0pD","EoToPs4786","lViBvJRJQB",
-"yEfy95nmWv","29QAz8U2nU","vkCHH0BmCy","Yh1hF2DREs","o8UydYOfrY","FPfSEIKxdL","gtCA5Mm8si","gdQsS5Drn0","cShY22Nslm","i3pydUl4a1",
-"48cHL4W0Tl","o8UydNo0Qb","fqypyd7vjM","jiVBPkZANm","B3qemnFqik","VIlwP8xEKz","WMiS3AgJHQ","No0QbVerEA","GSQwjdQ586","FnPFBMm8si",
-"2hEEUCqqaD","tvdkDm4bxU","e6e4zuLtKs","he9IAFVMxo","P6bcgksJby","NAFuwhE1Ql","fmIK1mz8gx","Z4I1vRmDcr","BbwgAlm0pD","0PktImz8gx",
-"5Drn0xciqp","VjCZqaez9y","O3iyQfFDrJ","prNT6zQt6Q","8TxD7KsjRK","GrDg7Waim6","Pb1pa48cHL","5Drn09XyT9","sqVrfJJs5m","iqv4kDG4sT",
-"jfREuuAWyp","gIYvElH1kt","atef2okgRi","W7cTslweGy","lpF6W0h1b1","hYBCKNcICA","fLNg8gIYvE","J2mQi1j5L8","Chuy3tjQxs","lpF6WCp3mZ",
-"xReecD6rBy","9XyT9UlU3M","RzaZAZzJHW","5drc6n1pmO","t59lRQClRL","8U2nUi7WMQ","e6e4zlsQGo","07n1cFPfSE","nFqikHzZT8","CK5W7zqH0W",
-"5Mg9rBpYhV","pFrrlgjUTu","RACujblLA9","fqypyi3pyd","taOXK7fsYM","fmIK1hi5X7","SbRYyZzJHW","QYxC0dhSuH","n1pmOlweGy","5ZaEz0Kyfs",
-"zHF1qKr8ys","ydG8U64s8N","fcwDa8RCUA","PYBf4VIlwP","WPmlxD6rBy","WPmlx5drc6","W7cTslXFOB","DQimpblLA9","Y1mC0uLtKs","JRJQBvLsmS",
-"lm0pDTXQ0Z","atef2uZPqg","JRJQBuupzk","jtn0XuLtKs","YOfrYqUJMd","oGu6xi7WMQ","MGlTFcmXIX","Z4I1v9eoRc","CNHmvDQimp","mX2GEt59lR",
-"oQ87rCIShG","9rlg9AOgEe","n8pJ9he9IA","yofH3pAhR1","48cHLAgJHQ","JRJQBWmadA","CK5W7dhSuH","1LB1L8TxD7","DcpWB1v5hH","JRJQBhi5X7",
-"he9IAGXdoH","brhlQogLgc","2ZHdkRACuj","8hJdtWaim6","taOXKtl72W","RACujBbwgA","Ta8f6pAhR1","QnJ1Sd85a9","StlDJ7ku1p","POUYS29QAz",
-"ZhwG1ix74r","ThjNn8hJdt","RpBQmnnP8o","RkQkeIjTwP","Yh1hFUl4a1","BpYhVzmLYD","djsrvwiHrZ","OUYuFVIlwP","8RCUAjSjS3","kB5nP0YAGH",
-"AOgEefqypy","yluBxIKxdL","LDk6faez9y","GSQwjNxx9V","MmKGJpiJSk","UlU3Msx5Gl","uQIcz4W0Tl","24ARFVjCZq","Mm8siW3VFH","RsQUqAmdQd",
-"xReecFVMxo","zHF1qwDajX","o8Uyde6e4z","mz8gxogLgc","8TxD78hJdt","IRh48oQ87r","MmKGJD6rBy","Zv7z0nlaBy","ReKEW0ao3l","FGzgpuvf7A",
-"2ZHdkdQ586","G1RhSi7WMQ","5VZjSGWqqX","1LB1L0PktI","jzUqR618Di","FNYIMfFDrJ","FGzgpM3zXL","S2DfutvdkD","fmIK1fqypy","aDGtS0Kyfs",
-"HRxd8dpe1v","Ta8f6ECMvU","zz4ZU0Wr5y","7hyVv16lHc","JKWYRdhSuH","yToGWzHF1q","0KyfsHP433","hUTw7Q6Lix","4QMc9hi5X7","iB08lQChxs",
-"7Ow5CtuDyS","L7cGcmz8gx","VerEAiB08l","uupzkguMb8","5Drn0Dz1R3","QbxXcuupzk","hSSvQLbRTH","X6Pinix74r","No0QbZv7z0","8FmFHSmGzv",
-"dpe1vuAWyp","618Di8RCUA","BpYhVHRxd8","zQt6Q7fKYU","W7cTs580YD","QWxoTCK5W7","WPmlxFPfSE","lpF6W64s8N","FwEJzAkKTk","M3zXLk85Ae",
-"07n1cCqqaD","lXFOBJXljW","7ku1pBFkb8","yofH3ZhwG1","FFDui2Yz7E","zmLYDMezSW","KZamHVIlwP","FwEJzG1RhS","14FLRLbRTH","8TxD7zY1GY",
-"FFDui2ZHdk","uN6r3ulk41","faHirFGzgp","0BmCyv1Hln","fFDrJSWfou","AgJHQjS1aj","XflUqlsQGo","JRJQBBGaQY","U3yw5In3NS","Dz1R3AkKTk",
-"8hJdtfFDrJ","45cIHUl4a1","yToGWHP433","ZUnqtni2v1","s93Ml3weIF","L7cGcSWfou","VIlwPgjUTu","1LB1LNcICA","5Drn0nlaBy","kZANmZUnqt",
-"ulk41kZANm","pvgjSIjTwP","8RCUAI7p2a","2DREssx5Gl","GSQwjuTacx","soy9tl83Ud","7lUXZCfgr3","ni2v1FjHXR","8FmFHIjTwP","OUYuFO3iyQ",
-"SmGzvQChxs","uTacxyofH3","zY1GYM3zXL","atef2Oz8yZ","ulk41MmsIo","ydG8U5Mg9r","WDVWJVprf2","5IhmG55rfB","WPmlx2TRI7","RmDcr5nmWv",
-"MmsIohe9IA","MmsIoLbRTH","gf8rIAXpwE","xXTI4AmdQd","FxX9qfmIK1","2TRI7h1zcH","b29RJUmaEv","KASQ80Wr5y","QworuFVMxo","RzaZAYf2Ec",
-"GSQwjVjCZq","EdBKcTwano","brhlQ1v5hH","RzaZA5nmWv","3otm6BCxeC","EdBKc6AFT0","cmXIXKsjRK","48cHLCK5W7","0MR5XblLA9","hi5X7gf8rI",
-"i7WMQgf8rI","In3NSHzZT8","QChxssoy9t","W7cTsJRJQB","Waim6d85a9","Q6hMCUvlv4","uTacxaez9y","pFrrlNcICA","14FLRP6bcg","MojnPxXTI4",
-"oQ87rZuDtD","d85a9PYBf4","M6qcGDcpWB","618DipiJSk","CK5W7nFqik","jzUqRsuY4x","he9IAKASQ8","tvdkD1j5L8","pmeCdFxX9q","SmGzvWreyP",
-"jeskSCxVEf","EdBKchSSvQ","7ku1pvLsmS","M3zXLHfyNQ","Ta8f6rz7Ut","iB08lIn3NS","FGzgpvLsmS","CdyBVC2Irc","uPX7Gdjsrv","6q6L9ZJTXH",
-"y94nw4W0Tl","VBjhzyluBx","cShY2uupzk","xciqph1zcH","gf8rIJKWYR","IRh48KsjRK","GWqqXogLgc","FjHXRnnP8o","FwEJzOz8yZ","iqv4kZuDtD",
-"uJScXeuZA5","zbIYYGWqqX","VNCPdK20wK","0ao3lAmdQd","qQxHP29QAz","9GXkXtuDyS","taOXKTCgPp","NhXdu4dEz6","t59lRKZamH","ThjNnnnP8o",
-"uvf7A7ku1p","7fKYUoGu6x","YOfrYyvOMI","AXpwEK20wK","Ss0Zue6e4z","5iGN5VIlwP","3weIFVprf2","dhSuHZhwG1","dhSuH5VZjS","jzUqRgjUTu",
-"ZhwG1hYBCK","okgRiS2Dfu","QWxoTulk41","guMb8UlU3M","gjUTujzUqR","SmGzvDLhzM","8cVD3EoToP","7fsYMzbIYY","HlUbFeuZA5","CxVEfIBe8k",
-"wDajXpAhR1","7fsYMo8Uyd","lsQGoJ2mQi","lH1ktHfyNQ","blLA9618Di","7fKYU618Di","oQ87rt98iW","tjQxsM6qcG","HRxd8FcWrW","QnJ1Sxciqp",
-"fcwDarhl0J","FcWrWMkgy8","WaWsvReKEW","tjQxspT8wu","ECMvUjzUqR","4dEz6v8yFN","dmoS7lViBv","MezSWMaJQs","5NammK20wK","AgJHQkB5nP",
-"0YAGHUlU3M","lj07QMm8si","9iGoTru4UG","CqqaDWMiS3","fmIK1Nxx9V","8TxD7ru4UG","Yf2Ec8U2nU","PYBf4gIYvE","QnJ1SEOE1o","soy9t6q6L9",
-"s93Ml2Yz7E","9GXkXBCxeC","L7cGc0ao3l","Qworub29RJ","jeskSlCMxy","okgRiCNHmv","nnP8oX6Pin","qUJMdgjUTu","JIqXiyvOMI","sx5GlWPmlx",
-"CdyBVs4786","M3zXLlweGy","gf8rIuLtKs","ThjNnAXpwE","dpe1vrhl0J","0BmCyFGzgp","JXljWW7cTs","1j5L8cmXIX","OUYuF1LB1L","jeskSguMb8",
-"ZUnqtlpF6W","FcWrWuLtKs","FLsphK4GS8","48cHLjiVBP","6q6L9QClRL","55rfBLewvM","VBjhzPOUYS","S77LHdhSuH","C2Irc8RCUA","FFDui1v5hH",
-"uAWypuvf7A","8cVD345cIH","h1zcHksJby","C2Irc9GXkX","I7p2aprNT6","mz8gx5VZjS","SWfouFNYIM","oVQp65drc6","PYBf4Twano","uPX7GRzaZA",
-"6q6L9618Di","sx5GlNhXdu","0PktIWDVWJ","K4GS8QYxC0","2ZHdkAmdQd","24ARFcQOnv","F6PT2s4786","lweGyWPmlx","Yw2oUiqv4k","k85AeKr8ys",
-"nnP8oJkzUn","WaWsvG1RhS","Zv7z02DREs","L7cGcWPmlx","2TRI76AFT0","lXFOB9y4lw","GWqqXxReec","oVQp6MmsIo","BCxeCmz8gx","brhlQdQ586",
-"POUYSTCgPp","tuDySzbIYY","lm0pDjzUqR","2hEEUZUnqt","CIShG9iGoT","pT8wujeskS","EoToPx3LDe","5nmWvVNCPd","okgRi5iGN5","CdyBVpFrrl",
-"uLtKs8hJdt","5NammzHF1q","UlU3MCdyBV","oQ87rlm0pD","BbwgA8hJdt","FPfSEYOfrY","pFrrlZJTXH","1j5L81LB1L","FNYIMyEfy9","x3LDetlILt",
-"gf8rI7hyVv","WMiS3GSQwj","7Ow5CDcpWB","IKxdLsoy9t","AmdQdtuDyS","Oz8yZMkgy8","TwanoM3zXL","XyPZNUlU3M","1LB1LMmsIo","RBhp0d7vjM",
-"Vprf2t98iW","Chuy38cVD3","lViBvBFkb8","qaofNpWiOs","Chuy3GrDg7","YOfrYyEfy9","2NslmWreyP","3weIFvkCHH","uJScXF6PT2","Q6hMCkZANm",
-"HRxd8U3yw5","ReKEW1j5L8","4QMc9SjskQ","5nmWvBCxeC","MmsIogf8rI","pWiOsAIYUu","ECMvUM6qcG","6AFT0MojnP","FnPFBAkKTk","rz7UtDQimp",
-"jSjS3HlUbF","i7WMQAkKTk","AOgEehi5X7","8U2nUyofH3","cmXIXkZANm","fqypyXyPZN","aFFssix74r","uvf7AbrhlQ","XflUqDLhzM","v2eC3uTacx",
-"wDajXzY1GY","dQ586EOE1o","618DilkMUA","NAFuwlXFOB","vOqCEpT8wu","FcWrWulk41","3weIFmz8gx","lViBveuZA5","0BmCyTXQ0Z","5drc6CxVEf",
-"kZANmK20wK","faHirRzaZA","5IhmGVIlwP","KZamHFnPFB","TXQ0Ztl72W","MK07YgjUTu","RmDcrAkKTk","HzZT8iwzGk","AXpwEksJby","lXFOBVNCPd",
-"QssNCqUJMd","d85a9uvf7A","GSQwj2TRI7","tl72WBbwgA","SWfoujiVBP","hE1Ql2TRI7","CNHmvbZLvS","2DREsmX2GE","aL6AJVLTy6","FGzgpRmDcr",
-"NhXduJIqXi","JJs5mCIShG","hi5X7X6Pin","he9IAPOUYS","JRJQBTXQ0Z","jeskS7X3uy","wiHrZ16lHc","cL0aEl83Ud","zY1GY2Nslm","O3iyQJJs5m",
-"Yf2Ece6e4z","sx5GlMK07Y","tvdkDW7cTs","Uvlv4y94nw","gIYvE8RCUA","AkKTkPOUYS","Ss0Zu5Namm","pWiOsBFkb8","djsrvDcpWB","EoToPru4UG",
-"pFrrldQ586","rKDLJSWfou","gjUTuPOUYS","M6qcGfFDrJ","ECMvUhe9IA","suY4x5drc6","zQt6Q6q6L9","Q6LixksJby","ZhwG1ThjNn","VjCZqHRxd8",
-"0PktI1j5L8","uJScXJIqXi","oGu6xCp3mZ","9GXkXHlUbF","NAFuwG1RhS","bgJAzi3pyd","FPfSEiB08l","jS1ajciuWz","y94nwiKqhr","tAOsruN6r3",
-"BGaQYFPfSE","M6qcGhe9IA","WaWsvU3yw5","uoStwQworu","v1HlnHfyNQ","hSSvQ9iGoT","MaJQsSmGzv","RkQkeMezSW","ZJTXHFVMxo","2ZHdkQnJ1S",
-"Pb1paWaim6","blLA9BpYhV","07n1ceuZA5","lpF6WpvgjS","fqypyQYxC0","JkzUnSbRYy","wiHrZ07n1c","DG4sT14FLR","hYBCK8cVD3","VBjhzThjNn",
-"taOXKuoStw","VerEAZhwG1","VIlwPmX2GE","zbIYY0Wr5y","oVQp64dEz6","s93MlzFgtB","M6qcGP6bcg","5Drn01j5L8","5Mg9rfLNg8","1LB1L6AFT0",
-"JRJQB6q6L9","xReecBCxeC","CxVEfjiVBP","FFDuizHF1q","b29RJlm0pD","MmsIoCIShG","NcICAMojnP","FNYIMfaHir","RkQkeVprf2","KsjRKNOHsz",
-"FLsphdhSuH","9iGoTl83Ud","Yh1hFReKEW","L7cGc2Yz7E","618DizQt6Q","2hEEUOUYuF","rKDLJ16lHc","rhl0J8TxD7","JRJQBguMb8","ReKEWQClRL",
-"8RCUA7X3uy","POUYSzz4ZU","8cVD3lkMUA","IjTwPNxx9V","fcJOysx5Gl","MmsIoK4GS8","45cIHjfREu","o8UydJJs5m","k85AeFPfSE","tvdkDNOHsz",
-"xciqp0PktI","xciqpSbRYy","6AFT0Nxx9V","M6qcGtlILt","G1RhSgjUTu","XyPZN8xEKz","iB08lWaim6","wiHrZVjCZq","X6PinGXdoH","BFkb8IRh48",
-"aL6AJm4bxU","s7MxkSs0Zu","0MR5XxXTI4","Nxx9VbrhlQ","Y1mC045cIH","aDGtSulk41","7hyVvIBe8k","lCMxyChuy3","d85a97Ow5C","ru4UGpmeCd",
-"ydG8UG1RhS","WPmlxMm8si","ciuWz55rfB","MezSWDQimp","AIYUunFqik","EdBKczHF1q","9GXkXQYxC0","D6rByt98iW","tl72Wa00b5","aez9yFNYIM",
-"AIYUuBbwgA","FFDuiiKqhr","4W0TllH1kt","o8UydFwEJz","UlU3M2Nslm","NcICADLhzM","JKWYRpT8wu","GSQwj2ZHdk","XflUq8FmFH","HzZT8WreyP",
-"k85AeD6rBy","AmdQdDz1R3","14FLRZv7z0","uJScXs7Mxk","2hEEUd85a9","a00b5P6bcg","4QMc90PktI","SmGzvXyPZN","fcwDae6e4z","lCMxyB3qem",
-"sx5GlksJby","jSjS3gf8rI","RBhp0B3qem","64s8N5Drn0","MGlTF2Nslm","8hJdt7ku1p","fFDrJi7WMQ","No0QbQnJ1S","oVQp6ydG8U","4W0Tl6AFT0",
-"FFDuipT8wu","QssNC8TxD7","SmGzvCNHmv","618DiDG4sT","FNYIMMezSW","14FLRIKxdL","CqqaDNxx9V","2hEEUHRxd8","FPfSEatef2","Z4I1vAgJHQ",
-"KASQ8CxVEf","l83UdQ6hMC","jtn0XJRJQB","2Yz7E4dEz6","DLhzMMm8si","cmXIXBGaQY","VBjhzfcJOy","sqVrfHfyNQ","uTacx618Di","d85a9ru4UG",
-"lCMxy55rfB","zbIYYgIYvE","oQ87rLewvM","pFrrlbrhlQ","SbRYyyEfy9","0KyfsCp3mZ","qQxHPJIqXi","SjskQDLhzM","Mm8sizbIYY","tuDySuLtKs",
-"tvdkD8TxD7","8FmFHyvOMI","lH1ktSs0Zu","pvgjSi7WMQ","FjHXRFwEJz","blLA9zmLYD","zFgtBUlU3M","SWfouIn3NS","W7cTsaDGtS","GXdoHWDVWJ",
-"vLsmSxXTI4","7fKYU45cIH","FLsphnnP8o","7X3uyLDk6f","9eoRcjtn0X","DLhzMatef2","L7cGczQt6Q","5IhmGSs0Zu","cShY2Zv7z0","Uvlv4AkKTk",
-"Mkgy8HlUbF","fLNg8Mkgy8","azIWpi7WMQ","9rlg9S2Dfu","ZuDtDiqv4k","F6PT20BmCy","ZJTXH5IhmG","KZamHn8pJ9","YjB9tJIqXi","KZamHcShY2",
-"lCMxye6e4z","tl72WmX2GE","uvf7AGv3Fq","NcICAs7Mxk","5ZaEzdjsrv","VLTy6NcICA","45cIHCdyBV","WMiS3d85a9","lCMxyAkKTk","oVQp6OxWIH",
-"tl72WOHaBz","C2Irc2TRI7","jSjS3pmeCd","MmKGJTXQ0Z","DQimpNhXdu","7fsYMnnP8o","mz8gxFFDui","WPmlxIn3NS","rz7Ut24ARF","zbIYYUlU3M",
-"bZLvSM6qcG","1j5L8iqv4k","uAWypHzZT8","jS1ajTa8f6","XyPZNmz8gx","618Di0h1b1","pv0i79iGoT","ydG8UjS1aj","d7vjM7lUXZ","s7Mxk14FLR",
-"RpBQmAXpwE","okgRiCxVEf","Ss0Zut59lR","StlDJoQ87r","8hJdtnFqik","mz8gxNOHsz","5nmWva00b5","Twano7hyVv","AgJHQJKWYR","azIWpyluBx",
-"WMiS3CdyBV","0MR5XAgJHQ","rz7UtqUJMd","zQt6QogLgc","LewvMWaWsv","mz8gxY1mC0","jzUqRsoy9t","CxVEf2hEEU","zY1GYjSjS3","8RCUAEdBKc",
-"s7MxkQ6Lix","StlDJCNHmv","o8UydGWqqX","uvf7AlpF6W","TCgPpS2Dfu","1LB1LyEfy9","suY4xgIYvE","prNT6Twano","MK07YoGu6x","pFrrlaL6AJ",
-"45cIHuPX7G","Dz1R3cShY2","14FLR2Yz7E","X6Pinx3LDe","5ZaEzlXFOB","0h1b1JRJQB","Mkgy8K4GS8","i7WMQTa8f6","dhSuHTwano","SWfou8FmFH",
-"Kr8ysfqypy","lViBvbgJAz","iwzGkNcICA","TCgPpOz8yZ","9iGoT7ku1p","QClRLWaim6","Yf2Ec9XyT9","GSQwj9GXkX","5drc6OUqFM","SWfou0Wr5y",
-"Gv3FqNOHsz","Yf2EczqH0W","TwanoSWfou","55rfB9rlg9","lViBvdpe1v","k85AeqQxHP","NcICABGaQY","GSQwjFGzgp","v2eC3euZA5","YjB9tfLNg8",
-"ix74rrhl0J","Mm8si16lHc","faHirReKEW","O3iyQhi5X7","kZANmFxX9q","JXljW8U2nU","pFrrlGXdoH","uAWyp3otm6","YjB9t8cVD3","8hJdt5Drn0",
-"GWqqXBbwgA","X6PinhYBCK","oGu6xJJs5m","dpe1vPYBf4","iB08l0ao3l","CK5W7i7WMQ","BFkb8e6e4z","cL0aEatef2","Ta8f6S2Dfu","nlaByTCgPp",
-"8xEKzFNYIM","FhtglfcJOy","Ta8f6QnJ1S","aez9yDG4sT","uPX7GwDajX","2NslmU3yw5","7X3uy2ZHdk","RpBQmVBjhz","F6PT2atef2","OUqFMMkgy8",
-"jzUqRgIYvE","oVQp6cShY2","BbwgA64s8N","fmIK1WDVWJ","14FLRTXQ0Z","K4GS8D6rBy","RmDcr8cVD3","HzZT8Ta8f6","Yf2EcNhXdu","lkMUA2TRI7",
-"ZzJHWEdBKc","FcWrWKsjRK","UlU3MI7p2a","fcwDamX2GE","i7WMQk85Ae","MmsIoQYxC0","9y4lwTXQ0Z","d85a9uN6r3","kZANmCdyBV","4dEz6M3zXL",
-"CK5W71v5hH","5ZaEzBCxeC","JIqXinFqik","zbIYYb29RJ","BbwgAUvlv4","gjUTuRBhp0","1LB1LBbwgA","KsjRKIjTwP","5iGN5hE1Ql","Yw2oUlweGy",
-"Cfgr32TRI7","bgJAzo8Uyd","C2IrcQ6hMC","XflUqyvOMI","uvf7AWaWsv","nFqikCNHmv","2DREsblLA9","9eoRcd85a9","pv0i7GWqqX","0ao3lGv3Fq",
-"QssNClpF6W","SWfouhYBCK","WDVWJNAFuw","soy9tAOgEe","RpBQmM3zXL","QworuAXpwE","EdBKcCK5W7","QYxC0d7vjM","580YDi3pyd","3weIFuoStw",
-"JJs5mjeskS","G1RhSIRh48","zqH0W9iGoT","oQ87rAgJHQ","2DREs0PktI","Cp3mZciuWz","okgRi7lUXZ","uAWypHP433","Cp3mZ2Nslm","5Nammn1pmO",
-"7ku1pn1pmO","s7MxkFhtgl","8TxD7DG4sT","2hEEUhE1Ql","S77LHtuDyS","hUTw73otm6","OHaBz0h1b1","hE1QlYw2oU","jS1ajyEfy9","CxVEfn1pmO",
-"QbxXcjiVBP","ogLgcBGaQY","WPmlxlpF6W","gjUTuRzaZA","Yh1hFjtn0X","l83UdokgRi","8xEKz0ao3l","S2DfuxReec","guMb80BmCy","Q6Lixuvf7A",
-"FnPFBPYBf4","RBhp0oQ87r","9eoRci7WMQ","5Drn0Uvlv4","cQOnvcmXIX","bgJAzrhl0J","WDVWJt98iW","Ss0Zu0MR5X","o8UydtaOXK","iB08lIBe8k",
-"lkMUA9y4lw","zbIYYFLsph","OUqFMG1RhS","hSSvQyofH3","JIqXiulk41","K20wK9GXkX","F6PT2U3yw5","blLA9YOfrY","YjB9tAIYUu","rhl0JJJs5m",
-"29QAzEOE1o","tl72WBGaQY","IKxdLnFqik","mX2GEuN6r3","zFgtBOUqFM","0PktI5Drn0","Yw2oU4QMc9","K20wK3otm6","MmsIoulk41","WmadAIKxdL",
-"RACujFcWrW","piJSkIjTwP","0PktIZuDtD","618DiKsjRK","618DiKASQ8","Ul4a1y94nw","tl72WlsQGo","ciuWzYh1hF","blLA9O3iyQ","lCMxyiwzGk",
-"vkCHHNhXdu","JXljW580YD","pFrrlJKWYR","MaJQse6e4z","d7vjMG1RhS","SjskQZ4I1v","7lUXZdQ586","JkzUnpvgjS","S77LHpiJSk","LDk6fOUYuF",
-"rz7UtlpF6W","5IhmGsuY4x","lm0pDaDGtS","5ZaEziKqhr","pT8wuCK5W7","HlUbFpAhR1","8TxD7pvgjS","sqVrfb29RJ","RsQUqMezSW","DG4sTt98iW",
-"FPfSEFFDui","7hyVvCfgr3","9GXkX5IhmG","S2Dfu9GXkX","lj07QuJScX","RsQUq4dEz6","7fsYM1v5hH","NAFuwUlU3M","QnJ1SBGaQY","5drc645cIH",
-"wiHrZo8Uyd","gtCA5FwEJz","v8yFNFjHXR","HRxd8n8pJ9","GWqqXzqH0W","gf8rIbZLvS","lXFOBydG8U","pWiOsHfyNQ","nFqikU3yw5","No0QbHlUbF",
-"uLtKshSSvQ","jeskSlkMUA","lpF6WRzaZA","DcpWBsx5Gl","LewvMMGlTF","Z4I1vLDk6f","xXTI4jeskS","FGzgpChuy3","lCMxyVLTy6","RmDcrpFrrl",
-"QbxXcXflUq","3weIF6q6L9","uPX7Ge6e4z","euZA5oGu6x","Z4I1vlXFOB","l83UdRzaZA","7lUXZzFgtB","55rfBaL6AJ","rhl0J9XyT9","8U2nUdQ586",
-"2TRI7cQOnv","ogLgcUvlv4","nlaBy2Yz7E","djsrvMkgy8","Mm8siWDVWJ","dQ586Chuy3","7hyVvJ2mQi","hYBCK8U2nU","KZamHydG8U","AIYUus4786",
-"Zv7z01j5L8","IBe8ky94nw","VLTy6lweGy","QYxC0HzZT8","y94nwuN6r3","WaWsvbrhlQ","aez9y5Namm","Yf2EcdhSuH","soy9tFhtgl","nFqikdQ586",
-"16lHcv1Hln","M6qcGZv7z0","45cIHHzZT8","lCMxy16lHc","CIShGcmXIX","FVMxoDcpWB","v8yFNSs0Zu","zFgtBzmLYD","pAhR1t98iW","tjQxs2TRI7",
-"48cHLHP433","8RCUAiB08l","ru4UGjtn0X","DG4sT7hyVv","0MR5XZJTXH","ThjNnQWxoT","5VZjSHzZT8","kB5nPyEfy9","BCxeChSSvQ","8cVD3lm0pD",
-"WaWsvKsjRK","0YAGHMK07Y","AgJHQECMvU","Uvlv4QnJ1S","POUYSlViBv","IBe8kaL6AJ","7Ow5ChSSvQ","xciqpRpBQm","mX2GE8xEKz","FLsphUmaEv",
-"9iGoTFwEJz","C2IrcNxx9V","3weIFWMiS3","FcWrWyEfy9","In3NSv2eC3","5Mg9rpiJSk","FGzgp24ARF","I7p2aNOHsz","Kr8ys7ku1p","29QAzVBjhz",
-"pT8wuoQ87r","iB08lAmdQd","suY4xNxx9V","Yw2oU8FmFH","FjHXRBCxeC","GrDg7uoStw","7hyVvWMiS3","24ARFlweGy","VLTy6gdQsS","kB5nP9rlg9",
-"EdBKcKZamH","GrDg7WPmlx","5drc6Chuy3","hi5X7FNYIM","ZuDtD8xEKz","RpBQmMojnP","Zv7z0Fhtgl","dpe1vvOqCE","KZamHoVQp6","uvf7AMojnP",
-"ulk41vkCHH","8cVD3soy9t","qUJMdulk41","1j5L8i7WMQ","LDk6fciuWz","M3zXLAIYUu","8hJdt4QMc9","Q6Lixlm0pD","lpF6WeuZA5","WaWsvC2Irc",
-"pFrrlU3yw5","xReecd7vjM","BFkb8VjCZq","QChxsIBe8k","RBhp0cShY2","x3LDejtn0X","WPmlxNxx9V","i7WMQs7Mxk","aFFssYh1hF","4W0TlQChxs",
-"0KyfsJJs5m","Yh1hF0Kyfs","Fhtgl3otm6","hYBCKoVQp6","hUTw7fFDrJ","iB08lMGlTF","xciqpyToGW","b29RJaL6AJ","I7p2aIKxdL","JXljWHRxd8",
-"WDVWJFPfSE","VerEA2ZHdk","P6bcg0MR5X","IKxdL5Mg9r","IRh48dhSuH","0YAGHHP433","45cIHReKEW","HRxd8K4GS8","HlUbFfLNg8","mX2GEoQ87r",
-"tl72WpvgjS","piJSkhUTw7","dpe1vdmoS7","4QMc9blLA9","bZLvSHP433","Cp3mZAXpwE","pvgjS8hJdt","G1RhSEoToP","guMb8J2mQi","NcICAS77LH",
-"1v5hH8cVD3","HRxd8RsQUq","DLhzMWmadA","uJScXRBhp0","QnJ1SWaWsv","x3LDeM6qcG","GXdoHtjQxs","AgJHQStlDJ","RpBQmtlILt","580YD7X3uy",
-"NcICAYf2Ec","2Yz7ERACuj","FcWrWhSSvQ","lweGyuJScX","HzZT8ydG8U","ogLgcDG4sT","F6PT2FNYIM","U3yw5FPfSE","0YAGHfcwDa","FPfSE64s8N",
-"hYBCKF6PT2","uPX7G9rlg9","QClRLZhwG1","dhSuHyEfy9","uN6r32TRI7","64s8NAmdQd","BCxeC6AFT0","YjB9tFPfSE","HP433FPfSE","uN6r3LDk6f",
-"In3NSVerEA","0PktIjS1aj","GSQwjuJScX","RsQUqbgJAz","C2IrcksJby","WreyPblLA9","lH1ktqQxHP","pv0i7K4GS8","CK5W7OHaBz","1LB1LfcJOy",
-"GSQwjv1Hln","VLTy6dmoS7","aDGtSwDajX","aez9yhYBCK","JRJQBBpYhV","ni2v1hYBCK","ni2v1djsrv","F6PT2yofH3","ZJTXHCxVEf","ksJbyNAFuw",
-"HP433MmKGJ","blLA9zFgtB","RmDcrv2eC3","DcpWBn1pmO","xReec24ARF","HlUbFdjsrv","9rlg9x3LDe","uTacxpAhR1","29QAzGXdoH","d7vjMGrDg7",
-"jS1aj07n1c","SWfou7lUXZ","XflUqQnJ1S","hUTw7jzUqR","cmXIXFFDui","3otm6Oz8yZ","uQIcz8xEKz","9y4lwjSjS3","2hEEUpT8wu","TwanoiwzGk",
-"piJSk8FmFH","mz8gxJXljW","jSjS3iB08l","rKDLJrhl0J","Ta8f6618Di","0BmCyGWqqX","J2mQihSSvQ","WDVWJHzZT8","Zv7z0suY4x","1LB1LVerEA",
-"fcJOyNOHsz","5VZjSyvOMI","QbxXct59lR","TwanouQIcz","Q6hMCChuy3","IBe8kKr8ys","pmeCdFGzgp","Qworu3otm6","dhSuH3weIF","uJScXDLhzM",
-"IjTwPzqH0W","euZA5fcwDa","d7vjMhUTw7","XyPZNOHaBz","WDVWJBFkb8","WreyPIjTwP","RzaZAJXljW","2DREs5Drn0","BGaQYVLTy6","l83UdFxX9q",
-"n1pmOe6e4z","AgJHQPOUYS","07n1c0BmCy","l83Ud55rfB","Gv3FqfmIK1","14FLREOE1o","zz4ZUhUTw7","RpBQmB3qem","qUJMdUl4a1","1v5hHs7Mxk",
-"AmdQd2Nslm","Chuy32ZHdk","RBhp0yToGW","ciuWzazIWp","ZhwG11v5hH","hUTw7tAOsr","GWqqXjSjS3","MezSW48cHL","o8UydRkQke","M3zXLFPfSE",
-"MojnPx3LDe","d7vjMMGlTF","SWfou9GXkX","StlDJulk41","BGaQY0ao3l","TXQ0ZMGlTF","soy9tDcpWB","FnPFBcShY2","14FLRs7Mxk","LewvMDcpWB",
-"DcpWBaDGtS","Dz1R3he9IA","M6qcGYf2Ec","EOE1oYf2Ec","b29RJm4bxU","pvgjSiB08l","kZANmReKEW","i7WMQEOE1o","In3NSuJScX","5NammprNT6",
-"rz7UtFGzgp","tvdkDrz7Ut","LbRTH8U2nU","4dEz6azIWp","ZUnqtTwano","yEfy9PYBf4","UlU3Mlj07Q","YOfrYiqv4k","cmXIXMkgy8","pAhR1MojnP",
-"YjB9tHfyNQ","Waim6v8yFN","cL0aEIn3NS","SjskQUlU3M","UlU3M6AFT0","0KyfslsQGo","v2eC3zmLYD","5nmWvbrhlQ","No0QbpFrrl","VerEAyofH3",
-"5IhmGo8Uyd","lViBv3otm6","5VZjSlkMUA","uPX7GRsQUq","lViBvFxX9q","2Nslm29QAz","m4bxUtjQxs","W7cTs5Drn0","GSQwjFhtgl","rKDLJv2eC3",
-"YOfrYlpF6W","n1pmO0ao3l","RsQUqguMb8","RBhp0M3zXL","Mm8sigdQsS","prNT6Oz8yZ","Mkgy8blLA9","OHaBz2hEEU","QssNC5nmWv","BCxeCfcwDa",
-"29QAzk85Ae","U3yw5EoToP","IjTwPjiVBP","ECMvU8TxD7","ZuDtDVerEA","AXpwEbgJAz","MezSW2Nslm","gjUTuFNYIM","Waim6QbxXc","9XyT9yofH3",
-"4W0TlFFDui","JkzUnokgRi","5iGN5v8yFN","xXTI4lj07Q","F6PT2POUYS","YOfrYdjsrv","FVMxoG1RhS","Y1mC0ydG8U","zz4ZU580YD","64s8NdhSuH",
-"HRxd8zbIYY","FxX9qCfgr3","brhlQtl72W","tuDySZzJHW","vOqCEW3VFH","uTacxHlUbF","lCMxyxReec","MezSWtuDyS","1v5hHHfyNQ","LewvM7fsYM",
-"zQt6Qix74r","FxX9qGXdoH","7ku1pJkzUn","YOfrYZ4I1v","AXpwENAFuw","zHF1q29QAz","6AFT0No0Qb","CdyBVs93Ml","ulk41FLsph","ydG8UMmKGJ",
-"xReecWPmlx","qUJMdFFDui","oGu6xgjUTu","RsQUqNxx9V","0BmCyVjCZq","FGzgpQClRL","Ta8f6zbIYY","FPfSE4QMc9","AOgEe618Di","FVMxocmXIX",
-"IRh48dmoS7","oVQp6UmaEv","hSSvQazIWp","lkMUAatef2","HfyNQdpe1v","AkKTkatef2","uTacxDcpWB","uTacx9GXkX","GSQwjC2Irc","ru4UGfmIK1",
-"8TxD7VLTy6","07n1coVQp6","DG4sTm4bxU","CNHmvNhXdu","pvgjSS2Dfu","RpBQmfaHir","Ta8f6lCMxy","QbxXcCIShG","Yh1hFZv7z0","IBe8kMmsIo",
-"guMb8d7vjM","Oz8yZTwano","uoStwECMvU","WMiS3uPX7G","5Drn0yofH3","TXQ0ZuZPqg","fFDrJBGaQY","SbRYyv1Hln","C2IrcBGaQY","2TRI7WreyP",
-"P6bcgdmoS7","sqVrfFVMxo","i7WMQUl4a1","a00b5AXpwE","DLhzMRsQUq","MmsIo9eoRc","jSjS3d7vjM","CqqaDi3pyd","iqv4kUvlv4","EdBKclViBv",
-"StlDJuPX7G","aL6AJpv0i7","WmadAMojnP","O3iyQiqv4k","MojnPiB08l","gdQsSlH1kt","WreyPaez9y","EdBKcO3iyQ","ZhwG1FwEJz","XflUqyofH3",
-"0PktIYf2Ec","M3zXLsoy9t","POUYSk85Ae","UlU3MDQimp","7fKYUMezSW","9iGoTS77LH","8TxD7ZJTXH","kZANm4QMc9","9iGoTfqypy","AOgEeoGu6x",
-"618DibZLvS","ThjNnpAhR1","U3yw5FLsph","yofH3lpF6W","8RCUATCgPp","tlILtB3qem","5ZaEz5IhmG","CqqaDni2v1","ogLgcMkgy8","rz7Ut5VZjS",
-"kB5nP4QMc9","atef2EoToP","AkKTk5drc6","pAhR15ZaEz","9iGoTiB08l","JRJQB9GXkX","BFkb8zqH0W","v8yFNtjQxs","Mkgy87Ow5C","jSjS314FLR",
-"oGu6xzQt6Q","CxVEfYh1hF","uvf7Ad7vjM","iB08lSmGzv","Q6hMCmz8gx","gjUTubgJAz","VerEAW7cTs","FLsph4dEz6","S2Dfuni2v1","lViBvOz8yZ",
-"QClRLFnPFB","lViBvd85a9","FwEJze6e4z","RsQUqBpYhV","CdyBVMmsIo","IBe8kdjsrv","5ZaEzPb1pa","FnPFB1LB1L","48cHL7hyVv","yToGWgtCA5",
-"JRJQBhUTw7","Dz1R3AXpwE","Pb1paWaWsv","WPmlx8U2nU","zz4ZUaFFss","MK07YcShY2","7Ow5CQnJ1S","UlU3MuAWyp","CxVEfsqVrf","SWfouVerEA",
-"okgRiuTacx","5ZaEzSjskQ","Cfgr38hJdt","4QMc9djsrv","RzaZAIRh48","6AFT0aL6AJ","48cHLB3qem","hSSvQsqVrf","xXTI4Twano","In3NSvLsmS",
-"dQ5862Yz7E","m4bxUuPX7G","jSjS3n8pJ9","zz4ZUJRJQB","Pb1paJRJQB","tlILtEOE1o","0ao3lguMb8","VNCPdzmLYD","taOXKYjB9t","9GXkX8cVD3",
-"lm0pDDz1R3","45cIH9eoRc","rz7UtiB08l","9eoRcsoy9t","07n1cOHaBz","okgRijS1aj","zY1GYJXljW","jiVBPReKEW","5drc614FLR","fLNg8ZJTXH",
-"zHF1qiB08l","RzaZAlsQGo","AXpwEMK07Y","v8yFN0h1b1","jzUqRQworu","tlILttlILt","uZPqgnlaBy","Zv7z0TCgPp","LbRTH0YAGH","FjHXRSbRYy",
-"ZzJHWUl4a1","pT8wuO3iyQ","pT8wuZv7z0","Ss0ZuIRh48","lj07Q4W0Tl","JkzUneuZA5","7ku1pS2Dfu","U3yw5cmXIX","24ARF5Namm","5Mg9rlweGy",
-"MojnPni2v1","O3iyQVjCZq","mz8gx8FmFH","TCgPpVprf2","16lHcQworu","pWiOs5ZaEz","4W0TlF6PT2","zY1GYO3iyQ","VerEA29QAz","s4786faHir",
-"YjB9tyluBx","yofH34W0Tl","JIqXiPb1pa","4dEz6VLTy6","ydG8Usx5Gl","MojnP2DREs","jeskSrKDLJ","ydG8U5IhmG","zbIYYTXQ0Z","blLA9QChxs",
-"lj07QTwano","nFqiktlILt","gIYvEKASQ8","s93Ml0MR5X","faHiryToGW","lweGyK4GS8","OHaBzIRh48","suY4xpvgjS","rKDLJK20wK","fFDrJKZamH",
-"o8UydDz1R3","AOgEeuQIcz","Ss0ZuUmaEv","bgJAziKqhr","jfREufFDrJ","IKxdLa00b5","K4GS8Fhtgl","8U2nUFcWrW","tvdkDGv3Fq","suY4xChuy3",
-"brhlQ9y4lw","7fKYUCNHmv","45cIH5Mg9r","618DiG1RhS","2TRI7n8pJ9","uupzkiqv4k","DQimpWMiS3","aDGtSyToGW","rKDLJ7ku1p","qaofNMmKGJ",
-"7X3uysoy9t","FNYIMdmoS7","hE1QlWreyP","hi5X7lj07Q","gIYvEgIYvE","RkQkeNo0Qb","0PktInFqik","jiVBPaFFss","ciuWzfmIK1","CIShGjfREu",
-"0PktIBFkb8","PYBf4ulk41","In3NSAgJHQ","7fsYMM3zXL","RpBQmKASQ8","xciqpAgJHQ","G1RhS45cIH","ReKEW9iGoT","fLNg85iGN5","lkMUAgjUTu",
-"zmLYDI7p2a","TwanoyluBx","azIWp0BmCy","t59lRyEfy9","nnP8oThjNn","In3NSFGzgp","nnP8o5VZjS","yEfy9Cp3mZ","x3LDePOUYS","RxrsmJJs5m",
-"HP433uQIcz","n1pmObZLvS","gIYvEOxWIH","jzUqRydG8U","brhlQEoToP","9iGoTAIYUu","7Ow5CbZLvS","JkzUndmoS7","ZuDtDP6bcg","ECMvUOUYuF",
-"0Wr5y45cIH","kZANmGSQwj","Ul4a12hEEU","djsrv07n1c","1v5hHDG4sT","jSjS3Yf2Ec","pmeCd64s8N","SWfouGv3Fq","ulk41IBe8k","OxWIHI7p2a",
-"fFDrJVLTy6","ydG8ULbRTH","AIYUudhSuH","NOHszhi5X7","MojnPDLhzM","d7vjMFxX9q","gIYvEmX2GE","ix74rFVMxo","b29RJQ6hMC","SbRYyK20wK",
-"S77LHs93Ml","VLTy6uJScX","yofH38cVD3","BGaQYChuy3","5IhmG8xEKz","7Ow5CGSQwj","0PktI55rfB","29QAzPYBf4","Kr8ys24ARF","aDGtSS77LH",
-"pv0i7BFkb8","Rxrsm2hEEU","Qworu4W0Tl","hi5X7gdQsS","uupzksoy9t","16lHcs4786","1j5L8FwEJz","lkMUALDk6f","he9IAZv7z0","Mm8si2TRI7",
-"U3yw5AXpwE","aL6AJKZamH","0ao3laDGtS","QnJ1SYf2Ec","SmGzvSmGzv","bgJAzFxX9q","PYBf4POUYS","uJScXG1RhS","Cfgr3FFDui","vLsmSQWxoT",
-"SjskQEoToP","Chuy3dhSuH","IKxdLQnJ1S","5IhmGmz8gx","i7WMQTwano","W7cTsYOfrY","VNCPduoStw","5iGN5X6Pin","uvf7A55rfB","azIWplj07Q",
-"MmsIopFrrl","Cp3mZReKEW","UmaEvbgJAz","7hyVvatef2","Gv3FqThjNn","UlU3MGSQwj","rz7UtCK5W7","RsQUq2hEEU","2ZHdkFVMxo","zY1GYZhwG1",
-"lpF6WY1mC0","vkCHHv1Hln","Gv3FqhE1Ql","5iGN5AkKTk","uvf7A6AFT0","HfyNQtl72W","uvf7AgjUTu","uAWypbZLvS","lH1ktsuY4x","v2eC3qUJMd",
-"gf8rIblLA9","Ss0Zud7vjM","piJSkfaHir","I7p2aMGlTF","djsrvuAWyp","ZuDtD2TRI7","NhXduChuy3","zQt6QI7p2a","gdQsSciuWz","Ss0ZuFGzgp",
-"X6PinJJs5m","ni2v19GXkX","WMiS3LewvM","nnP8oIn3NS","SWfouAXpwE","FcWrWcQOnv","bZLvScShY2","0YAGHzY1GY","24ARFx3LDe","iwzGkaL6AJ",
-"jtn0X07n1c","ZUnqtMm8si","9iGoT24ARF","618DiZJTXH","mX2GEuupzk","8cVD3Chuy3","Yw2oUe6e4z","ECMvUzqH0W","1LB1LiwzGk","0KyfsWaWsv",
-"piJSkjeskS","tuDySyofH3","8hJdtciuWz","ulk41S2Dfu","zY1GYtAOsr","C2IrcvLsmS","a00b5nnP8o","2hEEU24ARF","YjB9t45cIH","ZzJHWSmGzv",
-"WDVWJaDGtS","5VZjSdmoS7","t59lRcShY2","vLsmSSmGzv","lweGy4W0Tl","CIShGogLgc","yluBxS2Dfu","YjB9toGu6x","fcJOyGrDg7","4QMc9JXljW",
-"ru4UGix74r","YjB9tjS1aj","NcICAGrDg7","s93MlfLNg8","2Yz7EWMiS3","suY4xOHaBz","SWfouO3iyQ","yToGWCIShG","QChxskB5nP","U3yw5v2eC3",
-"J2mQiMojnP","9y4lwAkKTk","yofH3W7cTs","CxVEfEoToP","S2Dfu2hEEU","pmeCdF6PT2","gf8rIFcWrW","7fsYMNxx9V","W3VFHrhl0J","Chuy3o8Uyd",
-"FLsphydG8U","WaWsvuN6r3","v8yFNlpF6W","d7vjMuLtKs","9iGoTMmKGJ","azIWpnlaBy","X6Pinlj07Q","FnPFBfqypy","jeskS4dEz6","AgJHQSbRYy",
-"FnPFBlweGy","uAWyppFrrl","hUTw7BbwgA","Kr8ysbZLvS","cShY2zY1GY","LewvMZUnqt","POUYSatef2","48cHLzbIYY","prNT69GXkX","SWfouxXTI4",
-"0ao3lyvOMI","S2Dfurhl0J","4W0TlgtCA5","xXTI4Nxx9V","FwEJzQ6Lix","9rlg9NhXdu","TwanotaOXK","tlILtQWxoT","m4bxUjzUqR","HRxd86q6L9",
-"B3qem8TxD7","mz8gxJIqXi","BGaQYhe9IA","djsrv5nmWv","SjskQO3iyQ","uAWyppv0i7","Y1mC0No0Qb","TCgPp0PktI","S2DfuhUTw7","MGlTFSs0Zu",
-"FwEJz5VZjS","Uvlv45Drn0","5Mg9roVQp6","prNT6YOfrY","JJs5my94nw","AmdQdRkQke","o8UydWaWsv","JIqXidhSuH","8RCUAn8pJ9","ZJTXHqUJMd",
-"ZJTXHtjQxs","ReKEWfFDrJ","k85Ae16lHc","IBe8km4bxU","7ku1p4dEz6","L7cGclViBv","2TRI7fmIK1","hYBCKaDGtS","Mkgy8n1pmO","RBhp0Cfgr3",
-"o8Uydlm0pD","aFFssy94nw","7lUXZaDGtS","kZANmOUqFM","d7vjMxciqp","zFgtBFVMxo","Mkgy8ydG8U","n8pJ9GWqqX","BCxeCOUqFM","UmaEvIn3NS",
-"8cVD36AFT0","ZuDtDv2eC3","v8yFNIKxdL","Pb1paVNCPd","dmoS7lH1kt","lsQGoKZamH","Yf2EcD6rBy","QYxC0prNT6","i7WMQEdBKc","Ta8f65Mg9r",
-"piJSkzmLYD","aL6AJS77LH","pWiOsYf2Ec","6q6L9dpe1v","7fsYMbZLvS","lViBvYf2Ec","9XyT9G1RhS","zz4ZU7fKYU","FGzgpDLhzM","MmKGJRxrsm",
-"v1Hln24ARF","7hyVv48cHL","Chuy38FmFH","FPfSEAOgEe","HRxd8pAhR1","Dz1R32TRI7","hUTw7rKDLJ","pT8wuCxVEf","HfyNQwDajX","AmdQdQYxC0",
-"M3zXLy94nw","CK5W7FPfSE","JKWYRt98iW","QssNCVIlwP","dmoS7FxX9q","ZUnqtQChxs","uoStwNxx9V","bgJAzvkCHH","pmeCdD6rBy","CNHmv24ARF",
-"MaJQsyvOMI","VjCZqOHaBz","M6qcGkB5nP","P6bcgKsjRK","FFDuiQssNC","55rfBuN6r3","CqqaDC2Irc","I7p2ax3LDe","gIYvEMaJQs","vOqCEcShY2",
-"aFFssQYxC0","lj07Q4QMc9","ru4UGuN6r3","WmadAZhwG1","Zv7z0tjQxs","QssNCPYBf4","he9IAi7WMQ","Ul4a1wiHrZ","0PktIM3zXL","lH1ktuJScX",
-"FjHXRJkzUn","IKxdLt59lR","jeskSLDk6f","QnJ1SQYxC0","WDVWJ9XyT9","nlaBy0PktI","RxrsmtAOsr","pvgjSpWiOs","14FLRVNCPd","YjB9tS2Dfu",
-"FwEJzQClRL","48cHLuupzk","J2mQiBpYhV","5VZjSrz7Ut","Y1mC0iwzGk","WaWsvoQ87r","bZLvSFhtgl","n8pJ9M3zXL","x3LDe1LB1L","FjHXR5drc6",
-"bgJAzpAhR1","4dEz6VNCPd","4dEz6Cp3mZ","9iGoTfmIK1","yToGWo8Uyd","aL6AJAXpwE","O3iyQogLgc","EOE1oTwano","VBjhzuN6r3","ZzJHWHP433",
-"l83Ud5drc6","hi5X76AFT0","y94nwGXdoH","WreyPThjNn","pmeCd5ZaEz","B3qemPOUYS","tjQxsxciqp","ZUnqtAOgEe","ulk41yofH3","2ZHdkHRxd8",
-"s4786AmdQd","jiVBPJkzUn","JXljWReKEW","Ss0Zu7ku1p","2Yz7EL7cGc","ThjNnhe9IA","RmDcrQbxXc","D6rBySmGzv","AgJHQEOE1o","sx5GlhUTw7",
-"MmsIoZzJHW","SjskQ8RCUA","8hJdtLbRTH","Y1mC0lViBv","ZuDtDiB08l","MmKGJKASQ8","0MR5Xhi5X7","d7vjMRACuj","nlaByHP433","0MR5XMmsIo",
-"Y1mC0mz8gx","RkQkeI7p2a","0h1b1mX2GE","9y4lw7Ow5C","9rlg9M6qcG","uoStwjzUqR","JIqXiCIShG","OxWIHoVQp6","BbwgAgtCA5","cL0aE1v5hH",
-"Ta8f67fsYM","x3LDeciuWz","yEfy9Yf2Ec","7fsYMd7vjM","FjHXRHlUbF","aez9y14FLR","prNT6Q6hMC","jfREuYOfrY","tvdkDdmoS7","4QMc9EdBKc",
-"1LB1LtAOsr","YOfrYB3qem","nlaBy0YAGH","7ku1p8xEKz","9iGoTuLtKs","v1Hln64s8N","uoStwt59lR","UlU3MTwano","lViBv580YD","qQxHPatef2",
-"HfyNQKZamH","xciqpwiHrZ","0KyfsbZLvS","MmKGJiB08l","ix74ry94nw","4dEz6uTacx","tl72WRzaZA","618DiJIqXi","GXdoH9XyT9","1v5hHyofH3",
-"atef2soy9t","1v5hHpvgjS","XyPZNtuDyS","0h1b1WaWsv","JXljWaez9y","FNYIMBGaQY","FnPFBvLsmS","8U2nUt59lR","MaJQsThjNn","5Drn0iqv4k",
-"faHirM3zXL","FwEJz0BmCy","xXTI4YjB9t","MaJQslj07Q","uPX7G8TxD7","AmdQdZhwG1","48cHLvOqCE","zz4ZUYjB9t","DQimp5ZaEz","I7p2aSs0Zu",
-"aez9y1j5L8","BCxeCprNT6","9rlg98hJdt","iB08lzqH0W","Dz1R3ZhwG1","k85AeMkgy8","hE1QlqQxHP","2Yz7Eulk41","0MR5XoVQp6","uZPqg6q6L9",
-"PYBf45nmWv","IKxdLhe9IA","a00b59eoRc","0MR5X8xEKz","b29RJwDajX","t59lRChuy3","gjUTuIn3NS","cQOnvBGaQY","CqqaDl83Ud","RmDcrblLA9",
-"RsQUqECMvU","ZUnqtlj07Q","EoToPfLNg8","yluBxThjNn","hE1Qlh1zcH","Cp3mZNcICA","uTacxKsjRK","HzZT8DQimp","RBhp0YOfrY","aL6AJv8yFN",
-"Gv3Fq3weIF","cL0aEk85Ae","Y1mC0QClRL","zY1GYEdBKc","blLA9RsQUq","MmKGJ5Drn0","JKWYRdQ586","xciqp4dEz6","BFkb8Z4I1v","G1RhSVBjhz",
-"AkKTkRkQke","ix74ruoStw","9y4lwWmadA","gf8rILbRTH","ciuWzZ4I1v","0Wr5yyToGW","FxX9qXflUq","uZPqg5Mg9r","tlILtXflUq","piJSkFVMxo",
-"qUJMd1LB1L","CIShG9XyT9","VLTy6v1Hln","ulk41QbxXc","NcICAyToGW","LbRTH7Ow5C","uAWypX6Pin","NAFuwGSQwj","iB08lGrDg7","5Drn0K4GS8",
-"AOgEeBGaQY","Y1mC0iqv4k","n1pmOzz4ZU","h1zcHC2Irc","7lUXZuLtKs","fcwDa5IhmG","uLtKs580YD","0ao3l3otm6","FNYIMpv0i7","rz7UtMezSW",
-"jS1ajuQIcz","0YAGHxXTI4","lj07QJRJQB","FFDuiuZPqg","WmadA5Drn0","MK07YvOqCE","pvgjS2hEEU","cShY27X3uy","Y1mC0jzUqR","RsQUqpmeCd",
-"wDajXgf8rI","oGu6xReKEW","tAOsrgf8rI","FFDui5nmWv","lCMxydpe1v","QWxoT0YAGH","faHirP6bcg","8RCUACxVEf","NOHszpAhR1","x3LDeWaim6",
-"7fsYMK4GS8","8FmFHBCxeC","FNYIMlH1kt","0MR5X0BmCy","OxWIHbZLvS","NAFuwVNCPd","DG4sT8cVD3","Y1mC0CK5W7","1j5L8CxVEf","WDVWJBbwgA",
-"fFDrJBFkb8","CK5W7RkQke","HP433JKWYR","jtn0X0Kyfs","MezSWAIYUu","mX2GE0PktI","ECMvUzmLYD","SbRYylkMUA","PYBf4cL0aE","EoToP618Di",
-"55rfBlViBv","NAFuwVerEA","jiVBPQClRL","uJScXVerEA","GrDg70Kyfs","hi5X78TxD7","sqVrfuZPqg","fqypy5ZaEz","dhSuHuPX7G","rhl0J4dEz6",
-"Ul4a1CIShG","wiHrZni2v1","64s8N0PktI","7ku1pQChxs","tAOsr5VZjS","YOfrY1j5L8","aDGtSU3yw5","8RCUAzmLYD","bZLvSuAWyp","yluBxlViBv",
-"tvdkD9iGoT","M6qcGEdBKc","lkMUAUlU3M","Uvlv4yToGW","NcICAFjHXR","16lHcpmeCd","CdyBVAmdQd","jeskSMkgy8","cmXIX0Kyfs","fmIK1lm0pD",
-"ZuDtDGv3Fq","EoToPNcICA","euZA5aL6AJ","NcICA7fsYM","pv0i7GXdoH","2TRI7yluBx","euZA5pWiOs","Pb1pablLA9","MojnPK20wK","0ao3lfqypy",
-"a00b5zmLYD","Q6hMC0h1b1","K4GS8RzaZA","7hyVvOUYuF","FcWrWrKDLJ","Vprf2580YD","vLsmSlH1kt","CIShGC2Irc","prNT6pFrrl","tlILt9iGoT",
-"FnPFBZJTXH","HfyNQdmoS7","WmadAvkCHH","t59lRNcICA","Q6hMCRmDcr","NOHszL7cGc","dhSuH16lHc","Yf2EcydG8U","Pb1pajiVBP","zqH0WOHaBz",
-"CIShGv1Hln","MK07YWPmlx","6AFT0FGzgp","EoToPX6Pin","piJSkvkCHH","8TxD7DcpWB","jzUqR8hJdt","t98iWcQOnv","16lHcoVQp6","hi5X75nmWv",
-"pWiOsMezSW","2Yz7EaL6AJ","VLTy6G1RhS","GXdoHk85Ae","v1Hlnsx5Gl","ZJTXHsx5Gl","m4bxU64s8N","QnJ1SDQimp","OxWIHuTacx","QworuazIWp",
-"7Ow5CdhSuH","azIWpgdQsS","s93MltuDyS","pT8wuSmGzv","v2eC3Yh1hF","zmLYDThjNn","HlUbFtvdkD","v2eC3y94nw","iwzGka00b5","QClRLtl72W",
-"rz7UtZUnqt","zFgtBqQxHP","CIShG1j5L8","2ZHdkTXQ0Z","gIYvETwano","uPX7GyEfy9","SWfouv1Hln","atef2uLtKs","gdQsSlkMUA","l83UdFcWrW",
-"KZamH9eoRc","VNCPde6e4z","hYBCK1LB1L","QClRLe6e4z","7hyVv64s8N","ciuWz580YD","OUqFMUvlv4","yluBxKASQ8","tuDySLDk6f","VjCZq9GXkX",
-"VNCPdFnPFB","cmXIXSjskQ","9eoRcVIlwP","fcJOy8TxD7","BCxeCkZANm","y94nwlViBv","POUYSdjsrv","QWxoTFPfSE","lpF6WYOfrY","pmeCdZUnqt",
-"AkKTkHRxd8","TCgPpl83Ud","ix74rOxWIH","FhtglMkgy8","a00b5ix74r","L7cGc5VZjS","AmdQdPb1pa","jtn0XFnPFB","SWfou9eoRc","29QAz5IhmG",
-"v2eC3RmDcr","MaJQsbrhlQ","gf8rI0MR5X","uAWypECMvU","oVQp6d85a9","yvOMIBCxeC","9XyT9U3yw5","EdBKcX6Pin","No0QbSjskQ","U3yw5uJScX",
-"n8pJ9n8pJ9","9XyT98hJdt","ZhwG1lViBv","uZPqg1j5L8","BbwgA6q6L9","9y4lwsx5Gl","4W0TlaDGtS","2Nslm8xEKz","7Ow5CjSjS3","azIWpcL0aE",
-"AmdQdECMvU","0PktIyvOMI","MGlTFjeskS","ydG8UAgJHQ","FnPFBbgJAz","nFqikNOHsz","qUJMd8RCUA","xciqpksJby","FVMxoQYxC0","i7WMQ55rfB",
-"ksJbyuQIcz","uZPqgAgJHQ","8RCUANcICA","B3qemM6qcG","B3qemfcJOy","taOXKcShY2","FFDuiQ6hMC","2Yz7ElkMUA","lsQGoFwEJz","AmdQd7X3uy",
-"t59lRpT8wu","5iGN5MaJQs","ciuWzi3pyd","WaWsvt98iW","CIShGtAOsr","AmdQd8cVD3","nFqikHfyNQ","4dEz68xEKz","RmDcrOUYuF","KZamHtlILt",
-"O3iyQJXljW","djsrvt98iW","nnP8o5iGN5","NAFuwVLTy6","0MR5XRzaZA","oVQp6ogLgc","v8yFNpT8wu","3otm6Z4I1v","JRJQBVBjhz","UlU3MqQxHP",
-"QssNCuupzk","oVQp6XflUq","QClRL29QAz","jfREu7lUXZ","0PktIguMb8","LbRTHTa8f6","QClRLqQxHP","uN6r3pAhR1","sx5GlFNYIM","QClRL9y4lw",
-"jS1ajRzaZA","hYBCKTa8f6","vLsmS9eoRc","VIlwPHRxd8","jiVBPQworu","kB5nPHP433","QssNCReKEW","Pb1paXflUq","Mm8sifcwDa","FcWrWhe9IA",
-"soy9tChuy3","uAWypy94nw","8cVD3B3qem","o8UydMm8si","VLTy6QChxs","RsQUqHlUbF","fmIK15nmWv","OUqFMJIqXi","24ARFrz7Ut","Oz8yZpT8wu",
-"tvdkD0Wr5y","IKxdLFPfSE","2DREsjS1aj","pvgjS4QMc9","OUYuFwiHrZ","oQ87rLDk6f","GXdoHqQxHP","Ss0Zu8U2nU","TwanoFFDui","rhl0J5VZjS",
-"bgJAz9rlg9","okgRiVjCZq","2DREsuvf7A","QChxsjeskS","TwanovOqCE","14FLRblLA9","OHaBzmz8gx","6AFT0lj07Q","GrDg75IhmG","fmIK1dhSuH",
-"MK07YgtCA5","QbxXcJKWYR","5drc6lkMUA","FjHXRRBhp0","gjUTuJkzUn","AIYUu4dEz6","wDajXCK5W7","QbxXcLDk6f","s93MlUmaEv","uPX7GQworu",
-"pv0i75VZjS","JRJQB4W0Tl","lpF6W48cHL","NcICAFLsph","VerEAdjsrv","tvdkDiqv4k","Fhtgl8TxD7","FjHXRjtn0X","yvOMIPYBf4","WPmlxaFFss",
-"i3pydaL6AJ","BGaQYru4UG","aFFssIKxdL","vLsmS7fsYM","gIYvEFFDui","NcICAvLsmS","NOHszpiJSk","8hJdtydG8U","2Yz7Elm0pD","2DREsTa8f6",
-"cShY2MmsIo","3otm6Pb1pa","IjTwPWMiS3","tAOsrlpF6W","brhlQjSjS3","pmeCd9iGoT","oVQp6JKWYR","lXFOBS2Dfu","SWfoulCMxy","Waim6BCxeC",
-"Uvlv4YOfrY","Q6hMCThjNn","FcWrWyluBx","Ul4a1dhSuH","SmGzvRzaZA","O3iyQAIYUu","Zv7z0BpYhV","gf8rIW3VFH","uN6r3pFrrl","Y1mC0FNYIM",
-"uPX7GZUnqt","GXdoH6q6L9","uQIczKASQ8","DcpWBGXdoH","uN6r3Zv7z0","y94nwiqv4k","Chuy3OHaBz","hUTw7jeskS","CqqaDG1RhS","AgJHQlweGy",
-"RBhp0WaWsv","fqypyW7cTs","16lHcjiVBP","HRxd8ZuDtD","07n1cK4GS8","zz4ZUStlDJ","9rlg9AgJHQ","qQxHPEdBKc","5nmWv9eoRc","bgJAzLbRTH",
-"RmDcrYf2Ec","YjB9tJXljW","W3VFHhe9IA","tvdkD4W0Tl","HzZT8Ul4a1","9rlg9AmdQd","pAhR17fKYU","7ku1paFFss","gdQsS8RCUA","64s8NbrhlQ",
-"y94nwnnP8o","0Wr5ytjQxs","BCxeCzmLYD","JXljWo8Uyd","3otm65Drn0","soy9tRACuj","UmaEvP6bcg","D6rByL7cGc","s4786QWxoT","SmGzvi3pyd",
-"i3pydhi5X7","brhlQZJTXH","BbwgAbgJAz","mX2GE64s8N","yEfy9nlaBy","OUqFMWmadA","SjskQCqqaD","AIYUuUlU3M","29QAzBCxeC","BbwgAZUnqt",
-"EoToPKASQ8","Pb1paYw2oU","iKqhrcQOnv","64s8NzbIYY","tuDySgIYvE","y94nwHlUbF","W3VFH64s8N","zHF1qogLgc","WreyPGXdoH","5Drn0RBhp0",
-"JKWYRlsQGo","WreyPW3VFH","AgJHQ2TRI7","45cIHqUJMd","G1RhSXyPZN","ZhwG1W7cTs","WDVWJ1v5hH","bZLvSFGzgp","lkMUA07n1c","i3pydNo0Qb",
-"dhSuHrhl0J","gIYvEazIWp","FcWrWWDVWJ","S77LHIKxdL","o8UydRACuj","FNYIMGSQwj","rhl0JGSQwj","ReKEWnFqik","hE1Qlsx5Gl","KZamHHfyNQ",
-"1LB1LNAFuw","ThjNnPYBf4","AIYUuHlUbF","cL0aExciqp","HzZT89eoRc","QbxXcMmKGJ","iB08llkMUA","ix74rqQxHP","jeskS2Nslm","5IhmGyofH3",
-"S77LHNAFuw","MmKGJ5ZaEz","h1zcHx3LDe","4W0TlSbRYy","bgJAzMmsIo","taOXKk85Ae","QChxsJXljW","QChxs5iGN5","C2IrcMmsIo","lkMUAazIWp",
-"FNYIMwDajX","6AFT0yluBx","Kr8ysW3VFH","DG4sT29QAz","pT8wuhUTw7","GXdoHfqypy","GrDg7zY1GY","m4bxUW3VFH","suY4xiwzGk","dQ586tjQxs",
-"O3iyQDcpWB","QWxoTBbwgA","0YAGHpv0i7","EoToPlCMxy","AXpwE4dEz6","uLtKsgjUTu","y94nwEdBKc","lCMxy5Drn0","FNYIMVerEA","oVQp6FFDui",
-"SbRYyQ6hMC","Yw2oU7ku1p","nnP8oL7cGc","YOfrYuJScX","9iGoTUvlv4","ciuWzFnPFB","618DiuTacx","2Nslmpv0i7","nFqikQbxXc","QYxC08TxD7",
-"RpBQmru4UG","7hyVvMm8si","QChxszY1GY","zmLYDHzZT8","t59lRVprf2","lsQGo7Ow5C","8U2nUQWxoT","9rlg9IKxdL","Q6Lixpv0i7","ZJTXHy94nw",
-"pmeCdChuy3","atef2oVQp6","M3zXLn8pJ9","QChxsPOUYS","d85a9Chuy3","GSQwjsoy9t","FhtglgIYvE","uQIczfFDrJ","Chuy3LbRTH","s7MxkFVMxo",
-"BFkb8B3qem","7ku1pTwano","WPmlxbZLvS","WDVWJ2ZHdk","AkKTkdQ586","tl72W0BmCy","s93MlM3zXL","1v5hH9GXkX","qUJMdZhwG1","QworuxXTI4",
-"pvgjSSbRYy","fmIK10Kyfs","XflUqCp3mZ","WDVWJWPmlx","vOqCE5Mg9r","gIYvEaez9y","8cVD30BmCy","ZhwG12hEEU","QWxoTsoy9t","GrDg7ECMvU",
-"m4bxUjS1aj","4dEz6LDk6f","guMb8Mm8si","ZUnqtFGzgp","jeskSFNYIM","ni2v124ARF","mz8gxuZPqg","rKDLJWaWsv","hYBCKAmdQd","Waim6faHir",
-"a00b54dEz6","1j5L8VerEA","0ao3ljzUqR","y94nwOUqFM","kB5nP2Nslm","Nxx9VS2Dfu","ZuDtDBFkb8","nlaByZJTXH","guMb80Wr5y","SWfouWDVWJ",
-"CxVEfpvgjS","pAhR1M6qcG","fFDrJn8pJ9","lCMxyJRJQB","uupzk48cHL","zY1GYBbwgA","bgJAzJkzUn","8xEKzMK07Y","ZzJHWVLTy6","D6rBy6AFT0",
-"9rlg9zHF1q","lpF6WjzUqR","zQt6QK4GS8","Gv3FqZJTXH","gf8rINAFuw","v2eC3G1RhS","uvf7AlViBv","m4bxU9y4lw","2Nslmzz4ZU","HRxd8mX2GE",
-"W7cTsCK5W7","uLtKsulk41","OxWIHCqqaD","tvdkDRsQUq","djsrvyToGW","ciuWzEOE1o","sqVrfmX2GE","qUJMdm4bxU","tjQxsAgJHQ","nlaBydpe1v",
-"NhXduuLtKs","8cVD3uvf7A","hYBCK8TxD7","5IhmGlXFOB","9GXkX29QAz","Cfgr3JJs5m","oVQp6lkMUA","NcICAs4786","azIWpIKxdL","zqH0WxXTI4",
-"uZPqgDQimp","QnJ1SAIYUu","0Wr5yK20wK","45cIHJXljW","kZANmQChxs","suY4xtlILt","14FLR07n1c","5Drn0tl72W","AOgEeFFDui","jS1ajX6Pin",
-"KsjRKTXQ0Z","ZzJHWO3iyQ","gdQsSOz8yZ","tvdkD5IhmG","Mm8sizmLYD","TCgPpuPX7G","2Nslm7Ow5C","euZA5AOgEe","HzZT8FxX9q","6q6L9FjHXR",
-"StlDJNOHsz","Ul4a17fsYM","8cVD3n1pmO","GrDg7bZLvS","5Mg9rWaWsv","8TxD7CxVEf","VerEAk85Ae","oVQp6FGzgp","t98iWatef2","LewvMJ2mQi",
-"No0QbUl4a1","W3VFHEOE1o","wiHrZFLsph","6q6L9CqqaD","FFDuiHfyNQ","iwzGkAmdQd","29QAzguMb8","ZuDtDl83Ud","M6qcGNhXdu","cL0aERpBQm",
-"vkCHHS77LH","WmadA55rfB","MGlTFokgRi","XyPZNpAhR1","No0Qb6AFT0","suY4xXyPZN","Ul4a1uZPqg","2hEEUqQxHP","FjHXRCK5W7","9GXkXjiVBP",
-"ydG8UXflUq","Nxx9VFFDui","fLNg8ThjNn","pmeCdUvlv4","618DiEdBKc","xXTI4Mm8si","HRxd8lXFOB","9eoRcguMb8","29QAzIn3NS","48cHLW3VFH",
-"4dEz6SmGzv","FxX9q2ZHdk","Uvlv4tAOsr","POUYSpWiOs","1v5hHUlU3M","e6e4zfLNg8","a00b548cHL","14FLRxXTI4","0MR5Xi3pyd","piJSkbZLvS",
-"7lUXZ9iGoT","Y1mC05IhmG","lXFOB2TRI7","dmoS707n1c","StlDJAXpwE","tvdkDAXpwE","e6e4zK20wK","OUqFMUl4a1","9y4lwD6rBy","Y1mC0ZUnqt",
-"64s8N5VZjS","FwEJzVIlwP","Y1mC0KASQ8","Yf2EcokgRi","8cVD3BpYhV","x3LDepiJSk","8RCUA1v5hH","LDk6fUl4a1","oVQp6t59lR","4QMc9Z4I1v",
-"nnP8ouQIcz","rhl0JGWqqX","0BmCyhe9IA","oGu6xqQxHP","0ao3lB3qem","AXpwE55rfB","07n1c0YAGH","uZPqg5IhmG","618DiWDVWJ","2TRI7fqypy",
-"Yf2Ecaez9y","BCxeCuvf7A","M6qcGzQt6Q","yvOMICxVEf","4W0TlPOUYS","YjB9t2Nslm","Uvlv4v2eC3","SWfoun8pJ9","WreyPD6rBy","iKqhrjiVBP",
-"RBhp09eoRc","0YAGHTwano","nnP8oHfyNQ","5Drn0s7Mxk","hSSvQdjsrv","iB08ljiVBP","zbIYYulk41","P6bcgFnPFB","FnPFBYw2oU","BCxeC0h1b1",
-"NcICAuvf7A","ZUnqtFNYIM","zbIYYhE1Ql","8RCUAFLsph","xReecfaHir","MGlTFK20wK","29QAz1LB1L","MezSWh1zcH","gdQsSZJTXH","FjHXROUYuF",
-"618Di5Drn0","uZPqglm0pD","jSjS3HfyNQ","hUTw7bZLvS","lm0pDWaim6","AkKTkGXdoH","16lHcLbRTH","1j5L8lm0pD","l83UdSmGzv","n1pmOQClRL",
-"580YDt59lR","qUJMdmX2GE","HzZT8VerEA","y94nw9XyT9","dmoS7Mm8si","mX2GEcQOnv","fqypyZzJHW","ni2v1WPmlx","CIShG3weIF","hYBCKdjsrv",
-"D6rByEdBKc","HRxd8zHF1q","RsQUqS77LH","1j5L864s8N","blLA9pT8wu","8hJdtfLNg8","MmsIouN6r3","lH1ktAkKTk","lXFOBsqVrf","Vprf2yofH3",
-"9eoRcMGlTF","Nxx9VtvdkD","8TxD79rlg9","CqqaDRBhp0","tuDySlpF6W","YjB9tIRh48","uN6r3BFkb8","zFgtBKr8ys","hi5X7IRh48","zz4ZUzmLYD",
-"nFqikMaJQs","CxVEfDQimp","S77LHgjUTu","L7cGc0Wr5y","OHaBz5ZaEz","7hyVv4QMc9","Yh1hFGWqqX","nnP8o14FLR","Uvlv4W3VFH","n8pJ97X3uy",
-"FnPFBJKWYR","3weIFGrDg7","FFDuiFPfSE","yofH3F6PT2","SWfou0YAGH","BFkb8aDGtS","QChxsqUJMd","ZuDtDcL0aE","taOXKatef2","hi5X7CqqaD",
-"9y4lwCIShG","FjHXRPYBf4","Cp3mZNo0Qb","d7vjM24ARF","D6rByMm8si","X6Pinatef2","y94nws93Ml","qaofNuoStw","lViBv7hyVv","0h1b1RsQUq",
-"NOHszD6rBy","O3iyQChuy3","8RCUA6q6L9","X6PinMezSW","zHF1qRzaZA","FVMxoyofH3","FNYIMlj07Q","JRJQBt98iW","580YDjSjS3","618Di5VZjS",
-"6q6L99iGoT","suY4x9rlg9","3weIFAkKTk","JXljWQworu","jSjS3Dz1R3","i3pydWaWsv","DLhzMs4786","Dz1R3ZuDtD","FxX9q6AFT0","uoStwjtn0X",
-"k85Ae0BmCy","JXljWPb1pa","aFFss2TRI7","AkKTkYjB9t","pWiOsCK5W7","9XyT9oQ87r","O3iyQgdQsS","KsjRKC2Irc","m4bxUEOE1o","HfyNQAIYUu",
-"OUqFMEdBKc","0ao3lpiJSk","2hEEUWreyP","FwEJz3otm6","9XyT96q6L9","QYxC0KASQ8","Kr8yswiHrZ","8RCUAsoy9t","euZA57lUXZ","LDk6fQ6hMC",
-"XyPZNYw2oU","QChxsX6Pin","DG4sTKZamH","fqypy8cVD3","uQIczMm8si","29QAz5ZaEz","lsQGolH1kt","8cVD3Ss0Zu","M3zXLRzaZA","U3yw58cVD3",
-"gf8rIThjNn","aFFss5Mg9r","mX2GEaez9y","hE1QlM6qcG","jzUqRyEfy9","RxrsmMkgy8","Gv3FqGv3Fq","8RCUA6AFT0","wDajXsqVrf","Ul4a17hyVv",
-"zz4ZUcL0aE","DcpWBnlaBy","lweGyXflUq","O3iyQuN6r3","AmdQdgIYvE","Mkgy8tvdkD","lj07QuPX7G","BGaQYUl4a1","VNCPdguMb8","s4786xciqp",
-"2hEEUHP433","RzaZAAmdQd","WPmlxFwEJz","HP433pv0i7","BFkb8lsQGo","NOHszIRh48","C2IrcpmeCd","VNCPd4dEz6","DcpWBRzaZA","Kr8yspiJSk",
-"2ZHdkCNHmv","t98iWZhwG1","IjTwP7fKYU","JJs5mhUTw7","tl72WWPmlx","ThjNni3pyd","Y1mC0IBe8k","5iGN5uQIcz","KASQ87lUXZ","QChxsJkzUn",
-"i7WMQDG4sT","1v5hHRmDcr","wDajXJJs5m","TXQ0ZMaJQs","RkQkefcJOy","In3NSbrhlQ","8TxD72DREs","JXljWtl72W","07n1cFxX9q","b29RJpAhR1",
-"zHF1qIKxdL","W3VFHazIWp","faHirmz8gx","xciqpfcwDa","55rfB16lHc","JRJQBWDVWJ","MezSWlH1kt","gIYvE0Wr5y","LDk6fKr8ys","FLsphBGaQY",
-"7fsYMbrhlQ","ix74rokgRi","I7p2aWMiS3","hE1QlZUnqt","16lHczz4ZU","zqH0WBCxeC","4dEz6fcJOy","G1RhSuPX7G","x3LDetAOsr","L7cGcVprf2",
-"KASQ8sx5Gl","MmKGJ3weIF","In3NSYjB9t","M3zXLFNYIM","LbRTHFNYIM","vOqCE0YAGH","EdBKcdhSuH","Q6hMCAXpwE","FVMxo1LB1L","yEfy9WPmlx",
-"QworunnP8o","DQimptvdkD","FhtglEoToP","tl72W5Namm","Q6hMCFhtgl","BbwgA5IhmG","ulk414dEz6","8hJdtzqH0W","Gv3FqiKqhr","0Wr5ypT8wu",
-"VjCZqSmGzv","a00b5kZANm","24ARFtAOsr","2Yz7EVBjhz","JRJQBxReec","hYBCKy94nw","FcWrWAOgEe","UmaEvFVMxo","jfREuCNHmv","VerEAJXljW",
-"VNCPdPb1pa","FwEJzaez9y","o8UydS77LH","tl72WpiJSk","fqypyuQIcz","3weIFZUnqt","tl72WJXljW","KZamHCK5W7","JKWYR1LB1L","Ss0ZupAhR1",
-"lXFOBDQimp","i3pydEoToP","DLhzMJXljW","KZamHJKWYR","sqVrfVerEA","45cIH8TxD7","Zv7z0guMb8","ZzJHWoGu6x","Pb1paG1RhS","Kr8ys2Yz7E",
-"StlDJlH1kt","yEfy9uTacx","hYBCKUlU3M","ydG8Us7Mxk","AmdQdWmadA","CNHmvhe9IA","FVMxoGWqqX","Ul4a1VIlwP","RzaZAjtn0X","djsrvZhwG1",
-"5Drn0b29RJ","euZA5uQIcz","8U2nUtvdkD","x3LDe55rfB","Dz1R3gIYvE","64s8Nd7vjM","QssNCFxX9q","4QMc9t98iW","7hyVv6AFT0","tvdkDjiVBP",
-"n1pmOhSSvQ","64s8NStlDJ","tvdkD5drc6","K4GS8yluBx","LDk6fVNCPd","POUYSMm8si","9XyT92TRI7","n1pmOxReec","0YAGHMGlTF","BFkb8zmLYD",
-"k85AeksJby","lViBvZ4I1v","iB08lzHF1q","k85Aeix74r","KZamHzqH0W","1v5hH1v5hH","fcJOyFhtgl","O3iyQuJScX","6AFT0FwEJz","7ku1pDG4sT",
-"8FmFHVerEA","gtCA5gtCA5","lm0pDS2Dfu","aez9yVBjhz","AmdQd5nmWv","rKDLJazIWp","oQ87rLbRTH","iKqhrokgRi","zbIYYWMiS3","ECMvUiKqhr",
-"8xEKzs4786","ZJTXHyluBx","QChxsDz1R3","TXQ0ZFLsph","K20wK618Di","HlUbFhSSvQ","soy9ttvdkD","bZLvSVIlwP","MmsIooGu6x","LbRTHSmGzv",
-"lViBvB3qem","RzaZAx3LDe","Zv7z0i7WMQ","lpF6WHlUbF","d85a9brhlQ","Q6LixuQIcz","KASQ8lweGy","RsQUqZuDtD","lweGyfcwDa","D6rBy4dEz6",
-"HzZT85Namm","m4bxUBpYhV","2Nslm64s8N","NcICAguMb8","aez9ypFrrl","WmadAUlU3M","xReecQChxs","fFDrJThjNn","Oz8yZTa8f6","okgRigf8rI",
-"2NslmyofH3","Ss0ZuO3iyQ","s4786WDVWJ","FLsph0Wr5y","faHirVNCPd","uupzkZ4I1v","QssNCMezSW","jfREumz8gx","MmKGJiwzGk","yluBxXflUq",
-"s4786zbIYY","Cp3mZv1Hln","JKWYRlkMUA","rKDLJ7fsYM","NAFuwQYxC0","OUqFMiqv4k","6q6L9taOXK","D6rBy5nmWv","WmadAFGzgp","NhXduY1mC0",
-"IBe8k0Kyfs","0h1b1QbxXc","vLsmSWreyP","6q6L9nnP8o","6AFT0faHir","AmdQdiwzGk","v1Hln580YD","RmDcryluBx","uupzkaez9y","J2mQiZv7z0",
-"XyPZNHRxd8","qUJMdVBjhz","FhtglLDk6f","oQ87rpWiOs","SjskQAkKTk","bZLvSdhSuH","KsjRKGWqqX","okgRiStlDJ","ZUnqt4W0Tl","X6PinZzJHW",
-"StlDJaL6AJ","AOgEeJIqXi","45cIH2Yz7E","FhtgluoStw","LbRTH5Namm","FPfSEvkCHH","uAWypqaofN","MK07YjiVBP","cShY2RpBQm","BbwgAKr8ys",
-"BpYhVL7cGc","OUYuFQnJ1S","WMiS3uvf7A","blLA9HRxd8","YjB9tqUJMd","lpF6WazIWp","FGzgp07n1c","WPmlxSs0Zu","Ss0ZulXFOB","JKWYRzFgtB",
-"piJSk7Ow5C","ciuWzNxx9V","blLA9B3qem","3weIFi3pyd","Yh1hFF6PT2","Ss0ZuQWxoT","ReKEWcQOnv","JIqXiOz8yZ","lj07QyvOMI","n1pmOlXFOB",
-"lCMxyzqH0W","D6rByQbxXc","Cp3mZuAWyp","h1zcHJRJQB","suY4x2Yz7E","tlILtPOUYS","tlILtBFkb8","xXTI40BmCy","fFDrJ5VZjS","aL6AJhSSvQ",
-"i7WMQMmKGJ","OUqFMOUqFM","wDajX2DREs","F6PT2hE1Ql","cShY2BFkb8","TXQ0ZdQ586","Pb1pa16lHc","uvf7AprNT6","atef2MK07Y","2Nslm2ZHdk",
-"dmoS7BFkb8","aFFssBGaQY","rz7UtSbRYy","OxWIHNxx9V","uLtKsydG8U","2TRI7BpYhV","J2mQitjQxs","lm0pDCK5W7","8hJdtiwzGk","ksJbybgJAz",
-"yvOMIgIYvE","JkzUnTwano","zqH0W8RCUA","VjCZq7hyVv","v8yFNpvgjS","AIYUu07n1c","45cIHNOHsz","jeskSfcJOy","suY4xTa8f6","HP433bZLvS",
-"64s8NvLsmS","5NammSWfou","gtCA5OUYuF","RBhp0kZANm","ciuWzokgRi","RkQke9rlg9","lkMUAni2v1","RBhp0xXTI4","s93MlSjskQ","fcwDasx5Gl",
-"2TRI7atef2","ogLgc8xEKz","tAOsrzqH0W","yEfy9I7p2a","2Nslmd85a9","WDVWJYf2Ec","1v5hHWreyP","5iGN5F6PT2","o8Uyd2DREs","FFDui29QAz",
-"CIShGm4bxU","0YAGHgtCA5","8hJdt0h1b1","dhSuHxReec","C2IrclkMUA","okgRiNxx9V","yEfy9JRJQB","h1zcHQ6hMC","8U2nUbZLvS","2hEEUAkKTk",
-"Uvlv4GrDg7","lViBvGrDg7","he9IAvOqCE","brhlQFjHXR","faHirix74r","uN6r3S2Dfu","FVMxozY1GY","uAWypyToGW","5ZaEzAOgEe","gIYvEIjTwP",
-"Y1mC0suY4x","ulk41HlUbF","gIYvEJRJQB","F6PT29GXkX","yvOMIqaofN","DLhzMni2v1","QbxXc1LB1L","0MR5XPOUYS","suY4x1j5L8","tvdkDcL0aE",
-"Kr8ysQClRL","y94nwMmsIo","HRxd8UmaEv","FPfSEEOE1o","WDVWJqaofN","Oz8yZQnJ1S","P6bcglkMUA","pmeCd618Di","5Drn09iGoT","OUqFMUmaEv",
-"MK07Ydjsrv","s93Ml48cHL","U3yw5CxVEf","TwanopAhR1","GWqqXLDk6f","FFDui7fKYU","Ss0Zu9iGoT","mX2GEzqH0W","pWiOszHF1q","9GXkXQ6Lix",
-"SmGzvjfREu","qUJMdBFkb8","tvdkD6AFT0","X6PincmXIX","zqH0WIKxdL","pAhR1iB08l","9eoRcuN6r3","AgJHQ6AFT0","IRh48jzUqR","HfyNQSjskQ",
-"a00b5ydG8U","Kr8yspAhR1","guMb8yluBx","JXljWxciqp","pFrrlnFqik","lCMxyFnPFB","L7cGcFFDui","v8yFN2hEEU","QssNC2DREs","7lUXZhe9IA",
-"2TRI7jS1aj","0ao3lvOqCE","48cHLiB08l","VIlwPydG8U","GrDg7JIqXi","uAWyp5nmWv","Waim6FxX9q","TXQ0Zlj07Q","JkzUn2hEEU","euZA54W0Tl",
-"8cVD3d7vjM","8cVD37hyVv","djsrvlsQGo","vLsmSNcICA","uPX7GFGzgp","UlU3M2hEEU","nlaByIBe8k","piJSkpFrrl","SmGzvjzUqR","uJScXWaWsv",
-"lXFOBdQ586","xReecJIqXi","nnP8opAhR1","yluBx1LB1L","Yh1hFKZamH","nnP8oMmKGJ","618Dis93Ml","YOfrYuLtKs","n8pJ9jS1aj","uvf7AOxWIH",
-"dQ586ZUnqt","e6e4z9XyT9","pv0i7yEfy9","AOgEe29QAz","fLNg8G1RhS","AXpwEF6PT2","jeskSS77LH","0ao3lS77LH","blLA9lsQGo","h1zcHsx5Gl",
-"BCxeCfmIK1","aL6AJQYxC0","jzUqR9y4lw","iwzGkXflUq","8xEKz0MR5X","VjCZqLDk6f","rKDLJQYxC0","YOfrYmX2GE","iwzGklkMUA","FPfSE5iGN5",
-"Nxx9VfFDrJ","NAFuwfqypy","2NslmiwzGk","qQxHPQWxoT","a00b5IjTwP","azIWpKASQ8","kZANmVLTy6","DG4sT0PktI","x3LDeWaWsv","euZA5d7vjM",
-"W7cTsuLtKs","n8pJ91LB1L","uPX7GAXpwE","n8pJ9IKxdL","qQxHP5drc6","jSjS37hyVv","0KyfsF6PT2","uoStwVNCPd","5iGN5qQxHP","U3yw5hE1Ql",
-"Ss0ZueuZA5","iwzGk7fKYU","yEfy9KASQ8","RkQkeRsQUq","zbIYYru4UG","SmGzvZv7z0","K20wK7Ow5C","ogLgcNhXdu","No0QbSmGzv","nlaByDz1R3",
-"yvOMIOHaBz","gjUTuSs0Zu","14FLRuZPqg","soy9togLgc","gdQsSGWqqX","EoToPDQimp","0Kyfs4W0Tl","pAhR1l83Ud","EoToPbrhlQ","l83UdGXdoH",
-"0YAGHFLsph","lXFOBStlDJ","Vprf2MK07Y","hSSvQMaJQs","JKWYRzQt6Q","580YDjiVBP","lpF6WAXpwE","07n1cQnJ1S","s7Mxk8cVD3","xReecMmsIo",
-"QWxoTfcJOy","ksJby45cIH","EOE1omz8gx","4dEz6e6e4z","cQOnvC2Irc","Vprf2bZLvS","No0Qbsx5Gl","ZUnqtdhSuH","0ao3lRACuj","KsjRKtvdkD",
-"5VZjSEoToP","O3iyQzmLYD","kB5nPZuDtD","l83UdZhwG1","Dz1R3lm0pD","fqypy0BmCy","Gv3Fq5IhmG","jiVBPAmdQd","Mm8sipv0i7","VjCZqCfgr3",
-"29QAz7lUXZ","y94nwzbIYY","VNCPdoGu6x","pmeCdrKDLJ","MezSW9y4lw","yluBxMK07Y","G1RhSqQxHP","m4bxUPYBf4","b29RJKASQ8","azIWpkB5nP",
-"yEfy9aL6AJ","Gv3FqC2Irc","1v5hHO3iyQ","blLA90Wr5y","kB5nP0Kyfs","XyPZNJKWYR","AOgEeFxX9q","DQimp0Wr5y","QChxsCNHmv","MojnPCxVEf",
-"2NslmGrDg7","EOE1oCIShG","ZhwG1RBhp0","0Wr5y3weIF","tAOsrGSQwj","Ul4a14W0Tl","gdQsSlViBv","Oz8yZyofH3","gjUTuJXljW","YOfrYGv3Fq",
-"JIqXiQ6hMC","5nmWvY1mC0","tuDySfaHir","VBjhzgdQsS","jzUqRcQOnv","dpe1vNhXdu","zbIYY55rfB","QnJ1SuoStw","Nxx9VJkzUn","NcICAzQt6Q",
-"TCgPpM3zXL","5iGN5IRh48","iqv4kYf2Ec","FhtgldhSuH","0KyfsjS1aj","Waim6Vprf2","5VZjSPYBf4","8FmFHFnPFB","tAOsr5Drn0","atef25Mg9r",
-"xReecSjskQ","t98iW5IhmG","oQ87r1j5L8","Nxx9VqUJMd","QWxoT8cVD3","uvf7ACp3mZ","ix74rVLTy6","FjHXR9XyT9","d85a95Mg9r","8U2nUuLtKs",
-"i7WMQKsjRK","FVMxoHzZT8","CIShGguMb8","QworuzFgtB","xXTI4Oz8yZ","7fKYUyluBx","GSQwjQssNC","Yw2oUqUJMd","JIqXiBFkb8","rz7UtReKEW",
-"jeskSVBjhz","Ul4a12Yz7E","soy9tnlaBy","S2DfuAOgEe","XyPZNAIYUu","Ta8f6ydG8U","gjUTu5VZjS","d7vjMfcwDa","lpF6WVerEA","KZamHYh1hF",
-"2TRI707n1c","cQOnvPOUYS","cmXIXGWqqX","M6qcGrz7Ut","HRxd8o8Uyd","7lUXZCp3mZ","oGu6xFGzgp","SbRYyuPX7G","iKqhr6AFT0","2TRI7l83Ud",
-"FLsphiKqhr","DG4sTru4UG","9iGoTFPfSE","i3pydJXljW","zqH0WJXljW","pFrrlrz7Ut","aDGtSPOUYS","NOHszdpe1v","4dEz60Kyfs","I7p2aBbwgA",
-"8TxD7jeskS","lCMxyW3VFH","GrDg7djsrv","CqqaDKsjRK","Ul4a1vOqCE","FLsphQClRL","vkCHHZzJHW","o8UydnlaBy","WreyP1v5hH","JXljWuJScX",
-"5Mg9r2ZHdk","L7cGcCIShG","VBjhzd7vjM","GSQwjEdBKc","zY1GYtlILt","Ta8f6dQ586","SmGzvpiJSk","7lUXZWMiS3","RmDcrEoToP","s4786FcWrW",
-"oGu6xWPmlx","ydG8UFwEJz","gdQsSrKDLJ","9XyT99XyT9","RpBQmGSQwj","zFgtB5IhmG","X6PinWmadA","FLsphPOUYS","tuDySoQ87r","bZLvSIKxdL",
-"BbwgARxrsm","fFDrJhe9IA","uTacxdhSuH","fFDrJrhl0J","i3pydNxx9V","9y4lw5IhmG","BCxeCXflUq","lXFOBv2eC3","5Drn0Waim6","Ta8f6Rxrsm",
-"rz7UtblLA9","uvf7AhSSvQ","ix74ri3pyd","MmsIoKASQ8","lweGy2DREs","G1RhSReKEW","HP433oVQp6","uoStwF6PT2","dhSuHuQIcz","qUJMdtaOXK",
-"tlILtIn3NS","5VZjS580YD","AkKTkSjskQ","MK07YHRxd8","TXQ0Z07n1c","Mm8six3LDe","oVQp68U2nU","0Wr5yVBjhz","CdyBVdmoS7","618DiK4GS8",
-"M3zXLZUnqt","NhXdurhl0J","4dEz68TxD7","XflUq9XyT9","580YDYh1hF","FwEJzblLA9","AkKTk3weIF","tvdkDK4GS8","FNYIMaDGtS","d7vjM0h1b1",
-"fcJOy9XyT9","VBjhz2hEEU","7fsYMv2eC3","07n1cCIShG","RpBQmFjHXR","Vprf2GSQwj","tAOsrjS1aj","Cp3mZ55rfB","QChxsHzZT8","tjQxsFxX9q",
-"WMiS3VLTy6","MmsIoRBhp0","Nxx9VnnP8o","MK07YcQOnv","QnJ1SKr8ys","AIYUuMK07Y","uJScXFFDui","FwEJzQ6hMC","cL0aEJKWYR","14FLRNAFuw",
-"yvOMIlXFOB","LewvMJIqXi","MezSWJKWYR","JRJQBGv3Fq","RkQkeDcpWB","D6rByGrDg7","FwEJzhe9IA","lkMUAoVQp6","QworuDLhzM","vkCHHHP433",
-"ZUnqtWPmlx","YOfrY8FmFH","G1RhSGSQwj","8xEKzMm8si","FVMxojfREu","In3NSjfREu","7lUXZUmaEv","wiHrZFnPFB","L7cGcO3iyQ","2Yz7ECxVEf",
-"djsrv0BmCy","jzUqRFLsph","2NslmIn3NS","lm0pDdjsrv","XyPZNAgJHQ","tl72WVjCZq","FwEJz4dEz6","FcWrWyvOMI","IjTwP7hyVv","Chuy3580YD",
-"m4bxU5Mg9r","Pb1paLbRTH","ydG8UBGaQY","vkCHHs7Mxk","HzZT845cIH","fmIK1Dz1R3","NOHszgdQsS","VLTy6Dz1R3","GWqqXhSSvQ","VIlwPHzZT8",
-"7lUXZlXFOB","VjCZqNAFuw","uLtKsWPmlx","nnP8orhl0J","uLtKsWmadA","AgJHQlCMxy","AmdQduTacx","XflUqOUqFM","Q6LixoQ87r","JIqXivLsmS",
-"48cHLOUqFM","8cVD3suY4x","7fKYUnnP8o","ydG8UCfgr3","NOHsz5drc6","gIYvE48cHL","9y4lw3weIF","gtCA5faHir","cQOnvIRh48","VerEApFrrl",
-"8U2nU5Drn0","OUqFMo8Uyd","xReectvdkD","In3NSHRxd8","nFqiklsQGo","zmLYDYOfrY","ni2v1UlU3M","iwzGk0MR5X","5VZjSVprf2","hE1QlSs0Zu",
-"tvdkDIKxdL","QClRLJkzUn","QClRLrz7Ut","ZJTXHksJby","k85AekB5nP","v2eC3CxVEf","0PktIiwzGk","SbRYyulk41","n8pJ9CxVEf","6q6L9okgRi",
-"DG4sTix74r","aez9ylsQGo","L7cGc6q6L9","vOqCEk85Ae","580YDblLA9","i7WMQy94nw","zY1GYaDGtS","5VZjSaFFss","FnPFBsuY4x","tl72WcmXIX",
-"P6bcgcQOnv","iKqhr45cIH","5NammUl4a1","AIYUuMaJQs","QbxXcNOHsz","AkKTkpv0i7","FLsphQbxXc","zY1GYQClRL","FFDuiC2Irc","QnJ1SSbRYy",
-"uAWypiqv4k","fLNg8uJScX","UlU3MoGu6x","nnP8oQbxXc","Zv7z0xReec","0ao3lMGlTF","TXQ0Z8xEKz","8U2nUs4786","iB08lVIlwP","5IhmGO3iyQ",
-"HfyNQqUJMd","VBjhzFcWrW","jS1ajQClRL","tuDySVerEA","CIShGru4UG","t59lRs7Mxk","M3zXLTXQ0Z","JXljWzqH0W","lsQGo9rlg9","pT8wuv1Hln",
-"WMiS3IjTwP","Mm8siNhXdu","8FmFHWDVWJ","580YDnlaBy","Q6hMCuJScX","xciqpHzZT8","faHir55rfB","MGlTFNcICA","yvOMIFFDui","618DiI7p2a",
-"NAFuwQ6Lix","MojnP0BmCy","RpBQm8hJdt","dmoS7e6e4z","I7p2a3weIF","UmaEvCK5W7","taOXK1v5hH","t59lRRmDcr","FVMxowiHrZ","IRh48nlaBy",
-"s47868TxD7","nnP8ouvf7A","lm0pD7fKYU","t59lRguMb8","v8yFNe6e4z","5Drn0AOgEe","Ta8f6xReec","RACujt59lR","Dz1R3L7cGc","SjskQBFkb8",
-"VLTy6d7vjM","7fsYMAOgEe","jeskSSs0Zu","MezSWK4GS8","uvf7Av1Hln","cShY2lkMUA","FxX9qCdyBV","pFrrlSjskQ","SjskQzz4ZU","4QMc9C2Irc",
-"xReec16lHc","PYBf4Ta8f6","Q6hMCGv3Fq","pT8wuFwEJz","jSjS39GXkX","dmoS7n1pmO","5IhmGAIYUu","FVMxoThjNn","EdBKcksJby","6q6L9oQ87r",
-"NcICANcICA","7ku1pVIlwP","HP4339iGoT","o8UydVBjhz","LewvMQssNC","aDGtSBbwgA","ksJby0Wr5y","VBjhzprNT6","POUYSHP433","RBhp0yvOMI",
-"RxrsmNAFuw","mz8gxB3qem","djsrvvLsmS","GXdoH7ku1p","X6PinMm8si","JXljW0ao3l","7X3uy9y4lw","fcwDaUl4a1","9XyT9hSSvQ","Qworuxciqp",
-"vLsmSrhl0J","Ss0ZuqUJMd","lXFOB48cHL","uoStweuZA5","C2IrcFhtgl","zQt6Q9GXkX","4QMc9LbRTH","yEfy9QbxXc","rKDLJRpBQm","XflUqzHF1q",
-"5Mg9r9rlg9","jfREuFNYIM","5iGN5uJScX","Chuy3J2mQi","SmGzvJRJQB","OUYuFdjsrv","y94nwpT8wu","5NammFwEJz","5drc6piJSk","jtn0XuQIcz",
-"ThjNnLewvM","euZA51LB1L","RpBQmRpBQm","JXljWOHaBz","OUYuFlj07Q","BCxeCCNHmv","jzUqRLbRTH","RzaZA7Ow5C","F6PT2LDk6f","brhlQMmsIo",
-"Ul4a1Zv7z0","5iGN5ydG8U","HRxd8FwEJz","VNCPd2ZHdk","VIlwPB3qem","ZzJHWG1RhS","aFFssrz7Ut","uvf7AwiHrZ","mz8gxJJs5m","jeskSydG8U",
-"m4bxUSbRYy","Chuy3bgJAz","tuDyS5VZjS","Q6LixjfREu","CK5W7MmsIo","hi5X7AXpwE","5Drn0JkzUn","NcICAhSSvQ","55rfByToGW","jeskS8FmFH",
-"UmaEvzQt6Q","pvgjS1LB1L","7hyVvGWqqX","CNHmv0MR5X","0BmCyMK07Y","DQimpAgJHQ","MmsIoNhXdu","i7WMQoQ87r","2NslmwiHrZ","IjTwP580YD",
-"FjHXRZ4I1v","2ZHdk48cHL","iKqhrjeskS","hYBCKOHaBz","SWfouReKEW","m4bxUWreyP","07n1cY1mC0","zQt6QydG8U","Uvlv429QAz","aez9yCp3mZ",
-"WmadAv1Hln","DG4sTQworu","GSQwjgjUTu","fcwDa14FLR","Ul4a1Kr8ys","NhXduRxrsm","FcWrW0h1b1","C2Irc8cVD3","VjCZq8U2nU","VBjhzhYBCK",
-"ZhwG1h1zcH","tl72WThjNn","guMb85Namm","bgJAz29QAz","FnPFBi3pyd","oGu6xW3VFH","yEfy9RBhp0","07n1c9y4lw","NOHsz9iGoT","o8UydSWfou",
-"8FmFHhYBCK","SmGzvydG8U","rhl0JQClRL","o8UydChuy3","uupzkv2eC3","cShY2DG4sT","5drc6nnP8o","FNYIMFhtgl","5drc6WPmlx","KsjRK8RCUA",
-"iwzGkSbRYy","XflUqIKxdL","4dEz6gtCA5","l83UdlpF6W","fcwDaZ4I1v","zqH0WzqH0W","5Mg9rMK07Y","1j5L82TRI7","4W0TlMK07Y","7fsYMzz4ZU",
-"pvgjSHRxd8","5drc6lj07Q","lXFOBBGaQY","s7MxkwDajX","v1HlnyvOMI","NOHszydG8U","soy9tFGzgp","pAhR1S2Dfu","azIWpmz8gx","DLhzM618Di",
-"okgRiTa8f6","iKqhrAkKTk","oQ87rsuY4x","8xEKzQYxC0","D6rByAIYUu","cmXIX0BmCy","Gv3Fq55rfB","W7cTsuTacx","uN6r3tlILt","B3qemK4GS8",
-"mX2GEQssNC","uvf7AEoToP","AgJHQ2Yz7E","pT8wujtn0X","Waim6zbIYY","cL0aElCMxy","l83Uddjsrv","Gv3FqtlILt","K4GS8euZA5","s47869XyT9",
-"ulk41fLNg8","Cp3mZ8cVD3","8FmFHBFkb8","okgRiokgRi","2TRI7hE1Ql","n8pJ9lViBv","Ta8f62TRI7","5IhmGtl72W","djsrvKr8ys","RkQke07n1c",
-"uPX7GTXQ0Z","580YDRmDcr","ulk41Yh1hF","2DREsQworu","Nxx9VMmsIo","5Drn0oVQp6","FFDuiCK5W7","14FLRlH1kt","OUqFMjS1aj","cmXIXStlDJ",
-"lCMxycL0aE","wDajXulk41","NcICACxVEf","iB08lciuWz","v1HlnQClRL","9iGoTWMiS3","djsrvJRJQB","jtn0Xzz4ZU","uLtKsK20wK","fqypyCp3mZ",
-"ksJby48cHL","5NammVBjhz","QYxC0C2Irc","suY4xKr8ys","blLA9jtn0X","K20wKWPmlx","BFkb8IKxdL","6q6L9Oz8yZ","fmIK1ydG8U","EoToPPb1pa",
-"s7MxkWMiS3","m4bxUSjskQ","WaWsvWreyP","suY4xkZANm","d85a92Nslm","D6rBy9GXkX","5Nammulk41","P6bcgcL0aE","fqypy7fsYM","FcWrWwiHrZ",
-"7fsYMHfyNQ","zFgtBuAWyp","MezSWlXFOB","NcICA8hJdt","ix74rMmKGJ","JJs5m8cVD3","uZPqguN6r3","t59lRZ4I1v","FVMxoS77LH","tl72W9eoRc",
-"zHF1qn8pJ9","CK5W78TxD7","ZuDtD2Nslm","FFDuis7Mxk","pAhR1piJSk","yluBx0YAGH","x3LDelweGy","suY4xGSQwj","ThjNnZUnqt","Yw2oUCK5W7",
-"fcJOy5IhmG","ni2v1y94nw","W3VFHlsQGo","7Ow5CEoToP","MGlTF9GXkX","EoToPhUTw7","NhXdujzUqR","aDGtStl72W","fmIK1WMiS3","mX2GElm0pD",
-"zY1GYzbIYY","ru4UGZzJHW","48cHL7Ow5C","jfREuni2v1","ksJbyAmdQd","ni2v17lUXZ","WaWsvGXdoH","JRJQBlpF6W","SjskQNxx9V","BGaQYfcJOy",
-"64s8N8cVD3","VBjhzIRh48","lH1ktzbIYY","VLTy6gtCA5","GXdoHv2eC3","iqv4kQssNC","64s8NzFgtB","hSSvQ29QAz","9GXkXlweGy","kB5nPZv7z0",
-"ECMvU618Di","45cIHAIYUu","MmKGJeuZA5","MmKGJRACuj","WaWsvVerEA","zqH0W7fsYM","pAhR1xXTI4","iwzGkMojnP","FwEJzkZANm","fmIK1prNT6",
-"tvdkDIjTwP","GrDg7VerEA","JJs5mRxrsm","h1zcHbgJAz","KsjRKRACuj","jfREuCIShG","zFgtB45cIH","uAWypfmIK1","0Wr5yWDVWJ","QbxXcuJScX",
-"uoStwYh1hF","HRxd8RmDcr","0Kyfs0MR5X","TCgPpciuWz","UmaEvFNYIM","QbxXczz4ZU","WPmlxGXdoH","5iGN5Cfgr3","9XyT9RmDcr","0Wr5yGXdoH",
-"OUqFMZv7z0","uLtKsIn3NS","VNCPdt98iW","FcWrWt59lR","AIYUuVjCZq","KASQ86AFT0","14FLRMmsIo","C2IrcTXQ0Z","hUTw724ARF","vkCHHCdyBV",
-"zHF1qRmDcr","oQ87rCdyBV","5VZjSv2eC3","rKDLJD6rBy","aez9yZzJHW","IKxdLpFrrl","zz4ZU0BmCy","RzaZA0YAGH","2ZHdkHzZT8","t59lRk85Ae",
-"tjQxsVNCPd","HRxd8IBe8k","M3zXLTwano","ZUnqtRxrsm","DG4sT9GXkX","FNYIMQssNC","i3pyd3otm6","tjQxsEOE1o","pWiOsGWqqX","aDGtSlm0pD",
-"CxVEfCp3mZ","MojnPF6PT2","FFDuigjUTu","xciqpcQOnv","Qworu0PktI","iB08l6AFT0","uJScXAXpwE","RpBQm2TRI7","RpBQmhE1Ql","cmXIXcQOnv",
-"jiVBPStlDJ","NhXdu9rlg9","fqypyJIqXi","nnP8o6AFT0","qUJMdG1RhS","Zv7z0vkCHH","zbIYYsuY4x","GSQwjYjB9t","lj07Qulk41","QChxs8cVD3",
-"FFDuigIYvE","fFDrJ5iGN5","CqqaDlpF6W","ZzJHWDz1R3","gjUTuxReec","8hJdtsoy9t","pvgjSTCgPp","pFrrlSWfou","aDGtSJJs5m","xXTI42ZHdk",
-"l83Uds7Mxk","OUqFMn1pmO","TXQ0Z4W0Tl","zQt6QWmadA","0YAGHuAWyp","QClRLFxX9q","OUYuFo8Uyd","ZzJHWQChxs","07n1cuupzk","2TRI7gjUTu",
-"2TRI7djsrv","OxWIHtl72W","EdBKc9rlg9","VBjhzKASQ8","CqqaDYh1hF","MezSWFPfSE","C2Irc5iGN5","i7WMQU3yw5","bZLvSVerEA","I7p2aJIqXi",
-"0h1b14QMc9","5drc6AOgEe","ZJTXHuoStw","1j5L8fLNg8","yToGWWreyP","MojnP29QAz","ix74r4QMc9","RsQUqCfgr3","BbwgAIjTwP","ydG8Ul83Ud",
-"ECMvUx3LDe","7fKYU1v5hH","In3NSk85Ae","xciqpv2eC3","yvOMIkZANm","NhXdujS1aj","4W0TlKZamH","WaWsvh1zcH","dmoS7uZPqg","Q6LixWaim6",
-"fcwDajSjS3","No0QbxXTI4","jS1ajoVQp6","pvgjSyofH3","9rlg9OUYuF","KZamHBFkb8","piJSktvdkD","lweGyUmaEv","ZzJHWHfyNQ","RzaZAWaWsv",
-"pvgjSFGzgp","RpBQmqaofN","HzZT8S77LH","MezSW0Kyfs","3otm6HP433","IKxdLQChxs","yluBxjSjS3","uoStwzQt6Q","WPmlx2DREs","FjHXRpvgjS",
-"JJs5mUl4a1","Twanoa00b5","dhSuHJ2mQi","FjHXRzbIYY","HzZT8soy9t","SbRYytl72W","FxX9qXyPZN","FGzgpix74r","gf8rIksJby","QChxszz4ZU",
-"h1zcHUl4a1","gf8rIOz8yZ","b29RJzmLYD","d85a9QClRL","EoToPZv7z0","NcICAgjUTu","4QMc9dmoS7","ZhwG1iqv4k","Yh1hF9XyT9","zFgtBuZPqg",
-"UmaEvIKxdL","8cVD3Rxrsm","MojnPrz7Ut","1j5L88U2nU","piJSkydG8U","3weIFyluBx","xciqpfLNg8","EOE1oQChxs","9GXkXh1zcH","5NammiwzGk",
-"5IhmGJ2mQi","o8UydW7cTs","lH1kt3weIF","pv0i7BpYhV","HfyNQ2hEEU","Yf2EcPb1pa","WPmlxWmadA","AgJHQlH1kt","No0Qbhi5X7","J2mQidpe1v",
-"nFqikAmdQd","NAFuwhi5X7","MK07YEdBKc","VNCPdhYBCK","Nxx9VMm8si","WMiS3gIYvE","NcICAXflUq","FGzgpZzJHW","618DiciuWz","pFrrlpAhR1",
-"rz7UthE1Ql","DcpWBJ2mQi","2hEEUfLNg8","tAOsr8RCUA","W3VFHaFFss","ciuWzxXTI4","Y1mC02Nslm","zbIYYQClRL","euZA5ydG8U","Yh1hFs93Ml",
-"Yw2oUuN6r3","ZUnqt9XyT9","JXljWyToGW","fFDrJcL0aE","yluBx8U2nU","tvdkDb29RJ","D6rByl83Ud","QbxXcMezSW","0BmCySWfou","Mm8sihYBCK",
-"U3yw5x3LDe","ThjNnlweGy","5drc6FLsph","iKqhrBpYhV","QssNC5Namm","P6bcgCxVEf","5NammiKqhr","Z4I1vP6bcg","wDajXvkCHH","S2DfutaOXK",
-"UmaEv0YAGH","hYBCKprNT6","1v5hHZzJHW","ZUnqtI7p2a","uJScXDz1R3","DQimp5Mg9r","rKDLJW3VFH","5Mg9rgtCA5","mX2GEs7Mxk","CNHmvBpYhV",
-"RkQkeuPX7G","yluBx2TRI7","SjskQCIShG","zY1GYMaJQs","FNYIMoQ87r","AIYUunlaBy","9XyT9lweGy","qaofNWDVWJ","ru4UGKsjRK","EOE1oMkgy8",
-"FPfSECdyBV","e6e4zZUnqt","pFrrlnnP8o","ThjNnuTacx","45cIHxXTI4","dhSuHMaJQs","ydG8UVIlwP","vOqCEEoToP","2TRI7K20wK","dmoS75nmWv",
-"qaofNVprf2","5Drn0zY1GY","CxVEflj07Q","D6rBypWiOs","jS1aji7WMQ","WPmlxQworu","piJSkLbRTH","jtn0XIBe8k","dmoS7pFrrl","tuDySYh1hF",
-"guMb8MGlTF","jtn0XKsjRK","7X3uyfcwDa","uLtKszHF1q","WPmlx580YD","5drc6MezSW","hUTw7ZhwG1","oVQp6JRJQB","tlILttuDyS","JIqXiNhXdu",
-"TXQ0Zn1pmO","o8UydMK07Y","VBjhz8cVD3","iqv4kfLNg8","8RCUAOUYuF","WMiS3MK07Y","n8pJ90Wr5y","No0QbRsQUq","QnJ1SNhXdu","StlDJTa8f6",
-"LewvMuAWyp","QChxsZJTXH","RzaZAcmXIX","cShY2zFgtB","brhlQsoy9t","jS1ajfcJOy","5Mg9rfmIK1","bZLvSM3zXL","4W0TlTwano","1v5hHKr8ys",
-"CIShGpFrrl","dQ586FcWrW","WDVWJlpF6W","t59lR4W0Tl","FwEJzdmoS7","i3pydWMiS3","ogLgcHP433","zbIYYBCxeC","HzZT8QClRL","k85AeZJTXH",
-"RACuj16lHc","gjUTu9rlg9","uJScXulk41","qQxHPBCxeC","OxWIHs4786","fmIK18FmFH","QYxC0QnJ1S","uupzkt59lR","ciuWzMezSW","Waim6ni2v1",
-"aFFss48cHL","i3pydC2Irc","zFgtB7hyVv","yEfy9lsQGo","lH1ktguMb8","ciuWzsoy9t","fLNg8x3LDe","tlILtX6Pin","iB08luZPqg","CdyBVpT8wu",
-"BGaQY0Kyfs","DLhzMrhl0J","TXQ0Z7Ow5C","2Yz7EFGzgp","QssNCatef2","wiHrZciuWz","iKqhrzHF1q","h1zcH3weIF","jS1ajB3qem","k85Ae4dEz6",
-"U3yw5ZhwG1","45cIH45cIH","jS1ajCp3mZ","ZuDtDZzJHW","2NslmW3VFH","RzaZAru4UG","6q6L9hUTw7","JkzUn0YAGH","3weIFfmIK1","2DREsnnP8o",
-"uupzkdhSuH","atef2zz4ZU","7Ow5CGWqqX","JKWYRdpe1v","tvdkDYw2oU","Uvlv4CqqaD","qUJMdZv7z0","Oz8yZU3yw5","0Wr5y7X3uy","HfyNQfqypy",
-"SmGzvFVMxo","9eoRcAOgEe","BbwgAVLTy6","0Wr5ylj07Q","i3pydDz1R3","VNCPduvf7A","OHaBze6e4z","Ta8f6U3yw5","8TxD72TRI7","yofH37ku1p",
-"s93Mlfqypy","5IhmGKsjRK","No0Qbk85Ae","HP43324ARF","5nmWv6AFT0","cmXIXpvgjS","DLhzMvOqCE","prNT6tuDyS","ni2v1pWiOs","zz4ZUZv7z0",
-"Dz1R3ydG8U","HlUbFIjTwP","AmdQdHlUbF","xReecRmDcr","Q6hMCCp3mZ","9y4lw5Mg9r","AkKTkRpBQm","dQ586CNHmv","Waim6n1pmO","HRxd8tAOsr",
-"VBjhz0YAGH","NOHszgIYvE","7fsYMfmIK1","Yh1hFiB08l","iB08llweGy","16lHcJRJQB","TCgPp16lHc","0KyfsQ6Lix","zFgtBCp3mZ","FjHXRUmaEv",
-"sqVrfI7p2a","tlILtlkMUA","OHaBzMkgy8","2NslmZuDtD","uN6r3ru4UG","iwzGklpF6W","DLhzM9iGoT","zbIYY9y4lw","lH1ktuupzk","ZzJHW2ZHdk",
-"EdBKcGSQwj","2DREsWaim6","7fKYUydG8U","C2IrcJkzUn","jS1aj16lHc","9GXkXZ4I1v","0MR5X29QAz","8TxD7O3iyQ","Q6LixEoToP","Mm8siMmsIo",
-"faHirvkCHH","i7WMQdhSuH","Yf2EcvOqCE","JIqXiDz1R3","zY1GYHRxd8","pFrrl2DREs","LewvM8hJdt","Oz8yZHP433","o8UydM3zXL","RzaZABFkb8",
-"OUYuFNAFuw","o8UydgtCA5","8FmFHrhl0J","8RCUAatef2","C2IrcuAWyp","fcwDal83Ud","tjQxsMmsIo","lm0pDKZamH","VNCPdHlUbF","In3NSbgJAz",
-"kZANmlH1kt","2ZHdkn1pmO","Ta8f624ARF","uZPqgU3yw5","MGlTFjzUqR","BGaQYyofH3","8FmFH7X3uy","1j5L8MmKGJ","wiHrZC2Irc","GXdoHVerEA",
-"ogLgcStlDJ","W3VFHuTacx","MaJQszFgtB","MmKGJt98iW","ru4UGjeskS","ZUnqtHP433","VerEAv1Hln","HlUbFZ4I1v","NAFuwqUJMd","s7MxkNo0Qb",
-"ru4UGlViBv","taOXKulk41","EdBKcZzJHW","Ss0Zuhi5X7","FPfSE24ARF","UlU3M4QMc9","AOgEeS77LH","Mm8si45cIH","yluBxjeskS","v8yFNru4UG",
-"nnP8owiHrZ","Kr8ysix74r","WDVWJlCMxy","WDVWJfqypy","aDGtS3weIF","O3iyQLbRTH","l83Ud1j5L8","HfyNQhSSvQ","7fKYUm4bxU","uAWypFwEJz",
-"4W0TlcmXIX","uQIcznnP8o","v2eC3Oz8yZ","dQ5869XyT9","VerEAJkzUn","Ul4a11v5hH","MK07YU3yw5","xReecpT8wu","a00b5s93Ml","pFrrlFNYIM",
-"yToGWIRh48","I7p2aNxx9V","rz7UtCIShG","QworulH1kt","lH1ktFGzgp","FLsphY1mC0","ReKEWtlILt","Chuy33otm6","5Mg9rn8pJ9","Yh1hFyToGW",
-"8FmFH7fsYM","0h1b1FjHXR","XflUqZJTXH","AkKTk8TxD7","Mkgy8gIYvE","8RCUAIKxdL","0BmCylXFOB","KsjRKCp3mZ","Ss0ZulsQGo","7hyVvNhXdu",
-"uQIcz7X3uy","WMiS3Cp3mZ","OHaBzRzaZA","dhSuH7fKYU","jS1ajQYxC0","cQOnvzmLYD","LewvMCp3mZ","55rfBI7p2a","FhtglgtCA5","SbRYyQ6Lix",
-"QnJ1Slj07Q","GWqqXGWqqX","L7cGctvdkD","DQimpdhSuH","yofH3yvOMI","CK5W7v1Hln","0YAGHEdBKc","CdyBV5VZjS","cmXIXn8pJ9","iB08lfqypy",
-"CNHmv9eoRc","ni2v1cQOnv","vLsmSdmoS7","NhXduSs0Zu","LDk6fVjCZq","AkKTkxReec","JKWYRCIShG","J2mQiK20wK","YjB9tiKqhr","3otm66q6L9",
-"cShY2uTacx","618DivOqCE","Z4I1v2ZHdk","SjskQ0Wr5y","zQt6QsqVrf","FjHXRI7p2a","OUYuF16lHc","m4bxUThjNn","G1RhS8RCUA","K4GS8he9IA",
-"XflUq7X3uy","S2DfuoVQp6","CxVEfVBjhz","BbwgAi3pyd","0Wr5ySWfou","aFFssrhl0J","sqVrfEdBKc","WreyPSjskQ","F6PT2KASQ8","VjCZq8RCUA",
-"ciuWzuTacx","7lUXZcShY2","ThjNn5VZjS","Yw2oUmX2GE","FcWrW5Namm","n1pmOgIYvE","uQIcztvdkD","O3iyQS2Dfu","FPfSESjskQ","lkMUAQYxC0",
-"TXQ0ZcShY2","14FLRXflUq","HP433No0Qb","d85a9Gv3Fq","DLhzMsoy9t","ThjNnGSQwj","tl72Ws93Ml","QnJ1SgtCA5","AOgEeVerEA","HP433IjTwP",
-"XflUqkZANm","RpBQm7Ow5C","qUJMdhE1Ql","MmKGJZv7z0","dhSuHK4GS8","5drc6hSSvQ","mz8gxsx5Gl","uupzknFqik","G1RhSdpe1v","QssNCdjsrv",
-"2hEEUEoToP","Kr8ysIBe8k","jfREu5ZaEz","0h1b14dEz6","CIShGUl4a1","No0QbZUnqt","WMiS3oVQp6","QYxC0fcwDa","mz8gxuvf7A","hi5X7jtn0X",
-"s93MlblLA9","AOgEe8TxD7","Yf2EcgtCA5","45cIHtlILt","JIqXigIYvE","7fKYUpv0i7","XyPZNNcICA","yvOMIIBe8k","LDk6fHfyNQ","5Mg9riB08l",
-"Y1mC0Kr8ys","Qworus4786","Dz1R3bgJAz","pv0i7VerEA","ZUnqtJkzUn","Mm8silkMUA","atef2M3zXL","FGzgpi7WMQ","MojnPLDk6f","lm0pDnnP8o",
-"he9IAnFqik","oGu6xQworu","dQ586cL0aE","SmGzvP6bcg","lj07QUmaEv","suY4x3otm6","Q6hMCsoy9t","lXFOBhYBCK","nFqikaDGtS","CNHmvG1RhS",
-"CxVEfIn3NS","zmLYDZ4I1v","JRJQBcShY2","uPX7GVprf2","fLNg8RsQUq","guMb8zHF1q","Q6LixFcWrW","VLTy6oGu6x","No0QbsqVrf","ulk41Cp3mZ",
-"cQOnvEdBKc","ReKEWIRh48","BCxeCDz1R3","Nxx9VhYBCK","iwzGkBpYhV","GWqqXHfyNQ","WmadA0ao3l","yluBxChuy3","7lUXZl83Ud","Rxrsmfqypy",
-"gf8rIdjsrv","vOqCEs7Mxk","MezSW8U2nU","MaJQsni2v1","lm0pDtvdkD","qUJMdlpF6W","StlDJB3qem","9y4lwCqqaD","pWiOslCMxy","h1zcHAIYUu",
-"pAhR1TXQ0Z","djsrvCfgr3","uupzkJkzUn","K4GS8Gv3Fq","soy9tjtn0X","KsjRKe6e4z","WDVWJdhSuH","W3VFHGXdoH","qUJMd0Wr5y","e6e4zYjB9t",
-"1j5L8ogLgc","HzZT8tAOsr","55rfBZ4I1v","hi5X70Wr5y","cmXIXguMb8","ZuDtDBbwgA","JRJQB16lHc","YjB9t3weIF","5Drn0pT8wu","2hEEUxciqp",
-"FcWrWe6e4z","QssNCpmeCd","Waim6s93Ml","vLsmS5nmWv","lH1kt9eoRc","iqv4kK20wK","G1RhS9y4lw","GSQwjxXTI4","OHaBzFxX9q","fcJOy55rfB",
-"NhXduDLhzM","TwanoRkQke","hE1QlSbRYy","WreyP0Kyfs","29QAznnP8o","S77LHDQimp","Ta8f6kB5nP","Qworu580YD","O3iyQ4dEz6","BbwgAJJs5m",
-"FFDui2hEEU","t59lR1v5hH","MGlTFWDVWJ","0MR5Xv8yFN","G1RhSSjskQ","gjUTuS2Dfu","KASQ8jfREu","gjUTuRkQke","NAFuw7Ow5C","HlUbF5ZaEz",
-"dhSuHd85a9","7fKYUyToGW","MaJQslH1kt","K4GS8oGu6x","prNT6qaofN","zqH0Ws7Mxk","0Wr5yMkgy8","x3LDeAkKTk","ulk41GrDg7","lCMxyo8Uyd",
-"b29RJJXljW","FPfSE0BmCy","mX2GEnlaBy","0BmCyYw2oU","WDVWJBCxeC","d7vjMMmKGJ","LDk6fRpBQm","uQIcz0Kyfs","kZANmiwzGk","S77LHFwEJz",
-"jzUqRv2eC3","lH1ktyvOMI","XyPZNHP433","ZhwG1zQt6Q","uAWypDQimp","blLA9zbIYY","OUYuFKZamH","SmGzvtuDyS","m4bxUJkzUn","atef2vkCHH",
-"tlILtfLNg8","t98iWwDajX","VIlwPVprf2","he9IAjtn0X","CqqaDcShY2","ulk41zbIYY","YjB9tjiVBP","zHF1q8FmFH","4dEz6MK07Y","n8pJ9qUJMd",
-"GWqqXYh1hF","7fsYMSs0Zu","uoStwoGu6x","n8pJ9rKDLJ","Mm8siOHaBz","GWqqXfLNg8","D6rByFLsph","bgJAzhSSvQ","FnPFB8FmFH","DLhzMciuWz",
-"8TxD7zqH0W","rhl0JL7cGc","uAWyps7Mxk","EoToPRsQUq","y94nw5VZjS","m4bxUMkgy8","Yh1hFzqH0W","tuDySqaofN","ZUnqtZ4I1v","48cHLKZamH",
-"d7vjMStlDJ","VerEACK5W7","lj07QdQ586","KsjRKsoy9t","fcJOyTCgPp","RzaZAMGlTF","uupzkPYBf4","DLhzMazIWp","VNCPdMmKGJ","ReKEWfmIK1",
-"AOgEelsQGo","prNT6blLA9","jS1ajStlDJ","TCgPp1LB1L","tuDySHP433","HlUbFaFFss","bgJAzYOfrY","i3pydguMb8","hYBCKZv7z0","sqVrfFFDui",
-"lj07Qn8pJ9","mX2GEtlILt","oQ87rbgJAz","3weIFjiVBP","kZANmkB5nP","RxrsmvLsmS","k85AetvdkD","d7vjMQbxXc","azIWpOUqFM","WmadAgIYvE",
-"5ZaEzWaim6","Rxrsmi7WMQ","NhXdufFDrJ","prNT6Qworu","Vprf2QClRL","pT8wunFqik","ru4UGYjB9t","24ARF24ARF","Q6hMC2TRI7","jSjS3cL0aE",
-"Cfgr3s7Mxk","uN6r3uPX7G","TCgPpBpYhV","Waim6uZPqg","tuDySb29RJ","QClRLfcwDa","zQt6QM6qcG","zz4ZUGrDg7","zmLYDVNCPd","1LB1LGXdoH",
-"7fsYMtjQxs","zqH0WU3yw5","gjUTurKDLJ","pvgjSVLTy6","pFrrlL7cGc","0KyfsiKqhr","MezSWksJby","ZzJHWIBe8k","wiHrZfLNg8","QWxoTMK07Y",
-"pWiOsUvlv4","zbIYYVprf2","pFrrlRpBQm","JJs5m2ZHdk","8cVD3CdyBV","RpBQms7Mxk","UlU3M3otm6","0h1b1mz8gx","ogLgccL0aE","TXQ0ZuTacx",
-"ni2v1zqH0W","s4786e6e4z","45cIHOxWIH","5iGN58TxD7","OUqFMZuDtD","5NammlCMxy","ZJTXH5Namm","aez9yFcWrW","RBhp0uZPqg","ciuWzWreyP",
-"yToGWTa8f6","zQt6QSjskQ","pWiOstjQxs","QnJ1SVLTy6","Yh1hFCIShG","lXFOB29QAz","Y1mC0uoStw","8hJdtWDVWJ","FnPFBPb1pa","JIqXigf8rI",
-"4QMc9ZUnqt","OUqFMThjNn","QbxXcQnJ1S","G1RhSUl4a1","xReecOUYuF","W3VFHRACuj","Nxx9VPYBf4","In3NSnnP8o","AgJHQfcwDa","TXQ0ZkB5nP",
-"jeskSn8pJ9","FNYIMzqH0W","K4GS8In3NS","JkzUnY1mC0","yluBxprNT6","W7cTsm4bxU","LewvM0PktI","lj07QQWxoT","KZamHuLtKs","s4786XflUq",
-"MGlTFguMb8","Uvlv4BGaQY","8cVD3piJSk","zmLYDOHaBz","9GXkXFnPFB","prNT6S2Dfu","zY1GYQYxC0","FPfSE2DREs","7lUXZW3VFH","1j5L8lpF6W",
-"d85a9lH1kt","RzaZAhE1Ql","Q6Lix64s8N","Rxrsmdjsrv","tAOsrpFrrl","jzUqR0BmCy","guMb8NcICA","BGaQYHlUbF","uQIczOz8yZ","uJScXtjQxs",
-"FGzgpfaHir","vkCHHX6Pin","piJSk4dEz6","ZUnqt8cVD3","55rfBK4GS8","dhSuHiB08l","NcICAciuWz","YjB9tStlDJ","tAOsr3weIF","SbRYylXFOB",
-"ydG8UMGlTF","mz8gxlkMUA","SjskQjS1aj","gf8rImz8gx","s93MlFVMxo","No0QbCNHmv","QChxs5Drn0","2NslmWaim6","qQxHPM6qcG","8xEKzG1RhS",
-"K4GS8iKqhr","he9IA8U2nU","he9IA3weIF","2TRI7In3NS","cL0aE7lUXZ","0h1b1iqv4k","IBe8kQ6Lix","i3pydcQOnv","FPfSEcShY2","8U2nUMK07Y",
-"K4GS8fFDrJ","faHirVIlwP","he9IAtaOXK","3otm6HlUbF","lsQGoprNT6","cL0aEmX2GE","piJSks4786","QbxXcNhXdu","VjCZqaFFss","i3pydi7WMQ",
-"OxWIH9XyT9","bZLvScQOnv","FnPFBIKxdL","uPX7GzbIYY","m4bxUZhwG1","qQxHPMmKGJ","hSSvQ5IhmG","gtCA5uN6r3","Chuy3Gv3Fq","yToGWjS1aj",
-"OUqFMtuDyS","LbRTHBCxeC","gf8rIs93Ml","taOXKRACuj","DLhzMIn3NS","FxX9qQbxXc","BbwgAFGzgp","vkCHHQ6hMC","NOHszQWxoT","vOqCEzz4ZU",
-"Dz1R3LewvM","aDGtSd7vjM","QworuAkKTk","zY1GYv1Hln","iwzGkXyPZN","NOHsz0Kyfs","7hyVvS77LH","Gv3FquoStw","zY1GYVBjhz","zFgtBD6rBy",
-"pT8wuKr8ys","lweGyiqv4k","ZhwG1pmeCd","n8pJ9lkMUA","OxWIHJXljW","fcwDa9iGoT","ZhwG1P6bcg","s7MxkMkgy8","9y4lwMaJQs","rhl0JtvdkD",
-"Cfgr364s8N","2ZHdkzFgtB","8xEKzZJTXH","lXFOBGWqqX","7fsYMuJScX","WreyPgjUTu","Q6hMCCdyBV","s4786d7vjM","YOfrYrhl0J","G1RhSxXTI4",
-"vOqCEnnP8o","suY4x3weIF","Yw2oUS2Dfu","uPX7GReKEW","FnPFBPOUYS","a00b5OUYuF","0PktIRkQke","S77LHTa8f6","jiVBP48cHL","nnP8oPb1pa",
-"GXdoHBCxeC","AXpwEGv3Fq","7fsYMGWqqX","9GXkXOHaBz","suY4xoGu6x","uoStwaDGtS","RmDcrFGzgp","RkQkeFVMxo","aL6AJThjNn","suY4xD6rBy",
-"gdQsSix74r","xciqp9GXkX","xciqp0BmCy","FGzgpFPfSE","pv0i7suY4x","9iGoTCfgr3","YOfrYhSSvQ","oQ87rm4bxU","KASQ8x3LDe","lweGyyToGW",
-"HfyNQVBjhz","RxrsmlkMUA","7ku1pksJby","RACujaFFss","VBjhzhi5X7","618DiuQIcz","lm0pDgjUTu","Ta8f6iwzGk","4dEz6HfyNQ","yluBxm4bxU",
-"Kr8yshYBCK","SjskQChuy3","Gv3Fql83Ud","8TxD7k85Ae","QWxoTMezSW","JIqXiMojnP","qQxHPMaJQs","AgJHQRmDcr","Cp3mZUlU3M","Oz8yZwDajX",
-"OxWIHiB08l","FxX9qSmGzv","brhlQFFDui","GWqqXHRxd8","pWiOsJJs5m","zQt6QMaJQs","CxVEfiB08l","wiHrZ8RCUA","QnJ1ScL0aE","S2DfuCNHmv",
-"vLsmSxReec","VLTy6mX2GE","Qworu7X3uy","LbRTH6q6L9","QssNCfmIK1","UlU3MwiHrZ","RkQkeSjskQ","7X3uy8FmFH","FLsphoQ87r","W7cTsGv3Fq",
-"Mkgy88cVD3","jfREupT8wu","KZamHVjCZq","jeskSStlDJ","BFkb82DREs","Oz8yZtl72W","JJs5ms7Mxk","pmeCdkZANm","oQ87rgjUTu","jeskSOz8yZ",
-"8hJdtRkQke","aFFsshSSvQ","AgJHQulk41","P6bcgXflUq","QworuDG4sT","5ZaEzEOE1o","JKWYRmX2GE","azIWpPOUYS","pFrrlGWqqX","zmLYDoQ87r",
-"k85AeOxWIH","GrDg7ZzJHW","h1zcHEoToP","iB08lKASQ8","HRxd8v2eC3","JXljWvLsmS","WPmlx45cIH","uAWypMGlTF","uN6r3DLhzM","s93MlAXpwE",
-"n1pmOFjHXR","uN6r3FGzgp","QWxoTQChxs","fFDrJo8Uyd","yToGWCp3mZ","PYBf4QChxs","cShY2v8yFN","nFqik1LB1L","ZuDtDUmaEv","pvgjSVNCPd",
-"GSQwjKr8ys","zY1GYVjCZq","lViBvFGzgp","DG4sTS77LH","I7p2aNhXdu","0ao3ltAOsr","1j5L8Rxrsm","ru4UGs93Ml","B3qemfLNg8","sqVrf7X3uy",
-"i3pydRsQUq","wiHrZzQt6Q","2Yz7Ed85a9","J2mQibZLvS","dQ586CIShG","uJScXv8yFN","Chuy3Yf2Ec","5Drn0Ul4a1","iKqhrv1Hln","QworuHP433",
-"GrDg7iKqhr","cQOnvkB5nP","ulk41Mm8si","XflUqjS1aj","FhtglmX2GE","5ZaEzciuWz","5drc6vOqCE","he9IAuAWyp","ix74rjzUqR","KsjRKZhwG1",
-"KASQ8s93Ml","cmXIXdhSuH","dpe1v3otm6","7lUXZ29QAz","qaofNe6e4z","9rlg9BpYhV","pWiOshSSvQ","24ARFyToGW","Mm8sihSSvQ","jS1ajuAWyp",
-"5ZaEzfcJOy","cShY29GXkX","No0QbOxWIH","qQxHPDcpWB","hE1Ql9eoRc","5drc6Cp3mZ","uupzkuPX7G","8cVD3YOfrY","MaJQsx3LDe","OUqFMY1mC0",
-"rz7UtgdQsS","fcwDaDG4sT","tjQxsSmGzv","KZamHZ4I1v","VerEALbRTH","xReecVerEA","Y1mC0a00b5","e6e4zru4UG","14FLR8FmFH","5drc6HzZT8",
-"lXFOBuQIcz","zFgtBoQ87r","G1RhSAXpwE","v8yFNzQt6Q","9iGoT8hJdt","NcICACdyBV","Ss0Zuh1zcH","ix74rBGaQY","pWiOsJKWYR","FcWrW55rfB",
-"s4786CdyBV","C2IrcaL6AJ","jzUqRpAhR1","Yf2EcDz1R3","KsjRKk85Ae","tlILtOz8yZ","uJScX8U2nU","2TRI7FVMxo","G1RhSbrhlQ","ZUnqtMaJQs",
-"5NammVNCPd","5Drn0jiVBP","AOgEe6q6L9","9rlg97X3uy","fcJOyU3yw5","lkMUAix74r","QClRLTwano","uPX7GyluBx","2hEEUFcWrW","0MR5XjfREu",
-"pT8wuaL6AJ","FLsph7lUXZ","m4bxU7fsYM","ZuDtDSjskQ","RpBQmuAWyp","o8UydEdBKc","CIShGQssNC","In3NSCqqaD","BbwgAI7p2a","55rfBNcICA",
-"FnPFBFFDui","lViBvWDVWJ","AIYUuECMvU","J2mQizmLYD","7hyVvBpYhV","cQOnvtaOXK","iB08lM3zXL","NhXdupmeCd","FLsphm4bxU","W7cTsCNHmv",
-"DQimptaOXK","hi5X7fcwDa","ru4UGBGaQY","fmIK1NAFuw","lViBvQChxs","wiHrZRxrsm","l83Ud9eoRc","k85AeVBjhz","lH1ktTa8f6","VNCPdlCMxy",
-"uTacxReKEW","taOXKkB5nP","AkKTkguMb8","07n1cM6qcG","No0QbLDk6f","16lHcv2eC3","LbRTHs4786","nlaByNo0Qb","AIYUu9eoRc","8U2nUW3VFH",
-"LbRTHuLtKs","AgJHQ7lUXZ","n1pmOoGu6x","zbIYY5Namm","1LB1LDQimp","pFrrlhUTw7","14FLRhSSvQ","IBe8k1j5L8","6q6L9gjUTu","uPX7GjzUqR",
-"55rfBydG8U","soy9t2ZHdk","xciqpzQt6Q","0KyfsRpBQm","hSSvQUmaEv","5Namm0PktI","xXTI4UlU3M","GXdoHvLsmS","6AFT0VLTy6","IRh482DREs",
-"jtn0XjzUqR","7fKYU7fKYU","fcJOylViBv","gIYvEfqypy","TCgPpDLhzM","dQ586POUYS","ciuWzpiJSk","FGzgpYjB9t","FnPFBhYBCK","IRh48Dz1R3",
-"SjskQBCxeC","MmKGJ2ZHdk","iKqhrfLNg8","e6e4z618Di","OHaBzaez9y","kZANmAmdQd","soy9tksJby","jS1ajgIYvE","sqVrfAkKTk","aFFssVNCPd",
-"Gv3FqprNT6","yvOMI1LB1L","5IhmGZhwG1","8U2nUhe9IA","DcpWBJkzUn","Ss0ZuRmDcr","Dz1R3MK07Y","IKxdLjiVBP","brhlQ4W0Tl","J2mQiVjCZq",
-"lH1kt2DREs","aFFssazIWp","In3NSP6bcg","Q6hMCAgJHQ","QYxC0Cfgr3","0PktITCgPp","RkQke2ZHdk","pvgjSuoStw","5ZaEzguMb8","rz7UtVIlwP",
-"QClRL2TRI7","qQxHPL7cGc","lsQGo24ARF","fmIK1QClRL","Yw2oU5Mg9r","iwzGk9y4lw","3otm6brhlQ","0MR5XiB08l","piJSkMkgy8","aez9ylViBv",
-"HzZT8SmGzv","G1RhSWPmlx","Ss0ZuBCxeC","lXFOBmX2GE","14FLRVprf2","v8yFNmX2GE","Ul4a1pvgjS","taOXKpWiOs","5iGN5FVMxo","jiVBPVjCZq",
-"4dEz6ECMvU","VBjhzTCgPp","uJScXRpBQm","nlaByIKxdL","580YDuN6r3","7ku1pgIYvE","RxrsmQnJ1S","cL0aEIBe8k","GrDg72ZHdk","0MR5XP6bcg",
-"POUYSXflUq","XyPZNuJScX","t59lRZzJHW","uAWypM6qcG","FcWrWO3iyQ","aFFssni2v1","n1pmO8hJdt","D6rByNhXdu","nlaByWmadA","fqypyru4UG",
-"1LB1L580YD","AOgEe45cIH","MmKGJ1j5L8","Y1mC0BFkb8","OUqFM618Di","Z4I1v0PktI","kB5nPXyPZN","yofH3aL6AJ","sqVrfyToGW","7fKYUyEfy9",
-"MojnP5Namm","DQimp9XyT9","b29RJ5Namm","qaofNtuDyS","b29RJKr8ys","jeskScQOnv","rhl0JSs0Zu","Oz8yZPOUYS","8hJdtGrDg7","Zv7z0Gv3Fq",
-"EOE1ogdQsS","s4786mz8gx","CdyBVydG8U","7fsYMEOE1o","K20wKlCMxy","0PktIzY1GY","KASQ8fcJOy","FPfSEPb1pa","Cfgr3OxWIH","Mm8si4dEz6",
-"8FmFHru4UG","lViBvSbRYy","P6bcgfqypy","hE1Ql0PktI","0ao3lblLA9","TCgPpUl4a1","k85Aezz4ZU","a00b5tl72W","o8UydS2Dfu","7X3uyHlUbF",
-"CIShGgf8rI","HRxd8ECMvU","s7Mxkdjsrv","M3zXLs93Ml","dhSuHNxx9V","4QMc92TRI7","hYBCKulk41","5Namml83Ud","suY4x45cIH","jfREuY1mC0",
-"yEfy97fsYM","9eoRcFGzgp","zz4ZUMojnP","Nxx9VbgJAz","d7vjMJKWYR","1LB1LgdQsS","U3yw5AgJHQ","mX2GEK20wK","OUqFMlsQGo","DLhzMS2Dfu",
-"yluBxWDVWJ","QChxsMaJQs","dQ586D6rBy","faHirbZLvS","oGu6xtvdkD","wDajX5Mg9r","a00b5Chuy3","BFkb824ARF","jeskSHfyNQ","U3yw5Z4I1v",
-"JJs5mPb1pa","5iGN5Kr8ys","BFkb8s7Mxk","QYxC0YjB9t","0PktIciuWz","MmsIoRxrsm","Yh1hFlH1kt","OHaBzFVMxo","16lHc0h1b1","tAOsrjSjS3",
-"HfyNQzz4ZU","WaWsvxXTI4","wDajXThjNn","Fhtgl0ao3l","AkKTkFxX9q","AOgEeIjTwP","lViBvazIWp","RACujjeskS","GSQwjCNHmv","rhl0JS2Dfu",
-"FGzgpOxWIH","s4786S77LH","xReecQworu","hSSvQix74r","SWfoupAhR1","jeskS9iGoT","Ul4a1CqqaD","YjB9tt98iW","cQOnvSWfou","55rfBNOHsz",
-"cQOnvJRJQB","uAWypW7cTs","Oz8yZNcICA","jzUqRksJby","pAhR1zFgtB","9eoRcUlU3M","No0QbK4GS8","bZLvSix74r","dmoS7Twano","uvf7AGSQwj",
-"KsjRKRmDcr","kB5nP24ARF","x3LDe5iGN5","7Ow5CnFqik","JJs5mNOHsz","IKxdLZJTXH","K4GS8fcJOy","QbxXcfLNg8","he9IAGrDg7","prNT67ku1p",
-"4W0TlzmLYD","IKxdL2hEEU","F6PT2gtCA5","ZzJHWd7vjM","ReKEWsuY4x","2hEEUt59lR","uQIczi3pyd","qaofNtvdkD","zY1GYlsQGo","pvgjSuvf7A",
-"0h1b18cVD3","O3iyQuZPqg","LbRTHdjsrv","0Kyfsix74r","y94nwUvlv4","xReecguMb8","SbRYyjiVBP","zHF1q2DREs","cmXIXOz8yZ","jS1ajAOgEe",
-"M3zXLazIWp","P6bcgJJs5m","WDVWJpT8wu","PYBf4HzZT8","Q6LixDcpWB","Pb1paNxx9V","zz4ZUm4bxU","GrDg7MGlTF","tlILtuvf7A","RkQkeFjHXR",
-"vkCHHEOE1o","Zv7z0jiVBP","ReKEW5nmWv","QWxoTpFrrl","x3LDepv0i7","ru4UGJKWYR","fcJOyDcpWB","FPfSEGXdoH","UlU3Mt59lR","cmXIXZzJHW",
-"uQIczgIYvE","MmKGJjiVBP","GrDg7yvOMI","KASQ8aez9y","WaWsvzQt6Q","Dz1R3GWqqX","wiHrZFVMxo","MK07YWaWsv","JJs5mAXpwE","Cfgr35iGN5",
-"uupzkCfgr3","BGaQYb29RJ","ZUnqtMmsIo","W3VFHaL6AJ","fmIK18cVD3","VBjhzQnJ1S","C2IrcHfyNQ","M3zXLd7vjM","tAOsrQbxXc","JKWYRNOHsz",
-"fqypy0Kyfs","nlaBy2DREs","5ZaEzv8yFN","cmXIXokgRi","VLTy62hEEU","HfyNQJIqXi","n1pmOdmoS7","QnJ1SNcICA","K20wKy94nw","MojnPjS1aj",
-"7X3uyjzUqR","S2Dfupv0i7","0PktIUlU3M","7X3uyh1zcH","IKxdL2Yz7E","n1pmOtjQxs","NhXduprNT6","RkQke7X3uy","d85a9In3NS","M6qcGFxX9q",
-"LbRTHMojnP","BbwgAzFgtB","8U2nUatef2","ciuWz8xEKz","7fsYMjS1aj","TXQ0ZOz8yZ","Pb1pa8RCUA","9rlg97ku1p","rhl0JblLA9","l83UdAOgEe",
-"K4GS8dpe1v","CK5W7qaofN","07n1cJIqXi","5drc6ix74r","ix74rF6PT2","HfyNQpvgjS","t98iWWmadA","MK07YqQxHP","RzaZARkQke","Zv7z0uJScX",
-"pAhR1v2eC3","8hJdtl83Ud","YjB9tMkgy8","sx5GlJKWYR","HRxd8pv0i7","fmIK1U3yw5","jfREuFPfSE","QYxC01LB1L","4QMc9iKqhr","hE1QltaOXK",
-"vLsmSHlUbF","mX2GEbZLvS","yToGWuZPqg","55rfB64s8N","6q6L98hJdt","Fhtglhi5X7","lH1kttuDyS","VBjhzDz1R3","VLTy6SWfou","gjUTuWmadA",
-"9eoRcOHaBz","yvOMIRmDcr","D6rByHfyNQ","ksJbyFcWrW","0ao3l8TxD7","8U2nUsoy9t","5drc6ni2v1","zFgtBo8Uyd","tAOsr8TxD7","d85a9i7WMQ",
-"GXdoHMmsIo","8TxD78RCUA","BFkb8dhSuH","W7cTsGXdoH","brhlQCp3mZ","FxX9qk85Ae","TwanoZhwG1","ix74rNAFuw","U3yw5kZANm","okgRi1LB1L",
-"dQ586JIqXi","jeskSIKxdL","lpF6WW7cTs","gjUTuGWqqX","Oz8yZHfyNQ","lsQGoBbwgA","zQt6QIn3NS","ZuDtDtl72W","IjTwPwiHrZ","EOE1ovLsmS",
-"K20wKLDk6f","07n1cy94nw","jfREuFnPFB","gtCA5VBjhz","HRxd8SWfou","hYBCKv2eC3","cL0aEOHaBz","IjTwPRsQUq","lH1ktSWfou","n1pmOMkgy8",
-"QYxC0sqVrf","ECMvUQ6Lix","azIWpQworu","nFqikTwano","h1zcHcL0aE","Q6hMCWaim6","ix74rZ4I1v","kZANmIBe8k","BFkb83weIF","pmeCdYjB9t",
-"FcWrWQWxoT","pv0i7pmeCd","5nmWvQYxC0","O3iyQ1v5hH","7hyVva00b5","Yh1hFdpe1v","2Yz7EW3VFH","9GXkXCdyBV","C2IrcQnJ1S","uPX7GZ4I1v",
-"HRxd8XyPZN","yofH32Nslm","NhXduJRJQB","RpBQmxReec","5Mg9rzFgtB","9iGoTJRJQB","07n1cfcwDa","QworuFxX9q","B3qemk85Ae","5iGN5HRxd8",
-"m4bxUFjHXR","DG4sT5nmWv","t98iWFxX9q","wiHrZatef2","ZJTXHJRJQB","G1RhSl83Ud","8hJdtAOgEe","Cfgr329QAz","07n1cCp3mZ","hUTw7n8pJ9",
-"oGu6xfmIK1","pmeCdIKxdL","qQxHPsoy9t","SbRYy5nmWv","OUqFM3weIF","SjskQoQ87r","4dEz6XyPZN","VIlwPQChxs","8U2nUW7cTs","J2mQijzUqR",
-"rKDLJRACuj","VNCPdCK5W7","uPX7GBCxeC","5NammFLsph","QYxC0n1pmO","HRxd8AIYUu","QYxC029QAz","aDGtSiKqhr","lj07Qi7WMQ","C2IrcCfgr3",
-"jzUqRC2Irc","s93MlbZLvS","fFDrJAIYUu","7X3uyFFDui","d85a9FNYIM","oQ87rDG4sT","7hyVvyEfy9","FxX9qnnP8o","vkCHH8U2nU","FNYIMECMvU",
-"ZUnqtZuDtD","QnJ1S2DREs","m4bxUuvf7A","8hJdtSs0Zu","VLTy6PYBf4","t59lREoToP","atef2cL0aE","Dz1R3dQ586","lViBvjzUqR","Mm8siGXdoH",
-"ksJbyQ6hMC","sx5GlcShY2","ni2v18TxD7","s93Mlv2eC3","ReKEWlm0pD","NhXduBbwgA","lj07QwiHrZ","cL0aEZv7z0","MmsIo2DREs","rKDLJlj07Q",
-"rhl0JAIYUu","FhtglFLsph","guMb8RsQUq","Ss0ZuaFFss","NOHszCK5W7","NcICAGSQwj","b29RJCxVEf","ZJTXHGWqqX","FPfSEaez9y","v8yFNWreyP",
-"Pb1paKZamH","FLsphhYBCK","rKDLJuAWyp","BpYhViKqhr","5VZjSsuY4x","VLTy6F6PT2","KZamHuvf7A","prNT6CIShG","v2eC3dmoS7","9y4lwNhXdu",
-"5Mg9rjtn0X","AXpwEprNT6","uupzkQClRL","cmXIXk85Ae","zFgtBUl4a1","ru4UGwiHrZ","S77LHWmadA","OxWIHWaWsv","yToGWpT8wu","OUqFMVLTy6",
-"jfREuyluBx","taOXKfqypy","tjQxsFcWrW","FGzgpWmadA","qUJMd64s8N","NOHszThjNn","rz7UtZzJHW","2hEEUuvf7A","7lUXZ7hyVv","v2eC3GrDg7",
-"FGzgpksJby","hE1Ql5Mg9r","mX2GEP6bcg","BCxeCydG8U","ix74rGrDg7","9eoRc9GXkX","Z4I1vIKxdL","UlU3MSjskQ","k85Aeuupzk","0PktIgdQsS",
-"FPfSEhSSvQ","gjUTulpF6W","GXdoHuupzk","WreyPazIWp","y94nw48cHL","D6rByAgJHQ","bZLvSHRxd8","hSSvQni2v1","NOHszHzZT8","AkKTkBCxeC",
-"2DREsPb1pa","6q6L964s8N","IKxdL7X3uy","lH1ktn8pJ9","lXFOBTa8f6","ciuWzyEfy9","5IhmGMezSW","FPfSEJkzUn","CIShGjSjS3","BbwgAyvOMI",
-"zY1GYh1zcH","qaofNFPfSE","iKqhrgf8rI","lH1kt7Ow5C","taOXKSmGzv","O3iyQCfgr3","Y1mC09iGoT","MmsIopv0i7","gf8rIRACuj","aez9y2DREs",
-"jeskSGSQwj","F6PT2RkQke","azIWpW3VFH","nFqikYf2Ec","FFDui8hJdt","ReKEWQnJ1S","YjB9t9eoRc","5ZaEzVLTy6","AkKTkHlUbF","oQ87rzmLYD",
-"FVMxoReKEW","BFkb8dpe1v","8FmFH14FLR","WPmlxpiJSk","618DiJJs5m","WPmlxZ4I1v","v8yFNZJTXH","dhSuHMkgy8","Cp3mZa00b5","BbwgApvgjS",
-"8cVD3MaJQs","mX2GEW3VFH","DLhzMuQIcz","s93MlTXQ0Z","o8UydcShY2","W3VFHD6rBy","RzaZAlkMUA","pT8wuMkgy8","AIYUuF6PT2","IjTwPd7vjM",
-"4W0TlFPfSE","JJs5mDQimp","Zv7z0wDajX","UlU3MJ2mQi","taOXKChuy3","tvdkDd7vjM","RkQkeB3qem","ix74rl83Ud","RkQkeJIqXi","ZJTXHUvlv4",
-"JRJQBCp3mZ","CxVEf1j5L8","jSjS3jS1aj","GWqqX1j5L8","Q6LixWMiS3","d7vjMIKxdL","mz8gxDLhzM","i7WMQS2Dfu","FhtgllpF6W","7hyVvfcwDa",
-"VIlwPAgJHQ","BbwgAazIWp","s7MxkCIShG","jzUqRF6PT2","64s8NMm8si","uvf7AcQOnv","IRh48AkKTk","LewvM5nmWv","tuDySyToGW","HfyNQuAWyp",
-"Cp3mZtAOsr","jSjS3hE1Ql","RkQke0YAGH","dpe1vuN6r3","lsQGohUTw7","Q6LixuN6r3","v1HlnFnPFB","UmaEvlsQGo","8xEKzpFrrl","PYBf47fKYU",
-"64s8NlViBv","K20wKAmdQd","BpYhVI7p2a","dmoS77fsYM","SbRYy0Kyfs","JIqXiru4UG","MaJQsGXdoH","dhSuHqQxHP","I7p2aQ6hMC","uAWypCfgr3",
-"IBe8krz7Ut","5nmWvGSQwj","x3LDeYh1hF","ksJbyQWxoT","FGzgpYw2oU","Uvlv49rlg9","cShY2CqqaD","5iGN5Mkgy8","CNHmvMm8si","jzUqR3weIF",
-"JKWYRvkCHH","dhSuHuLtKs","RmDcrCNHmv","oVQp6AmdQd","FFDuiTCgPp","Chuy3U3yw5","AkKTkWaim6","gIYvEzY1GY","BGaQYv8yFN","1LB1Lsoy9t",
-"uvf7AAkKTk","K20wKlXFOB","fqypyn8pJ9","JRJQBMmsIo","ulk41hUTw7","jS1ajuTacx","5Drn0Mkgy8","1v5hHIjTwP","6q6L9X6Pin","iqv4kQWxoT",
-"prNT68U2nU","faHirfFDrJ","dhSuHHfyNQ","5IhmGLewvM","GSQwjNo0Qb","X6PinfaHir","XyPZNs4786","iwzGkJJs5m","CqqaDEdBKc","NAFuwdhSuH",
-"W3VFHVjCZq","D6rByCNHmv","cL0aEkB5nP","IBe8ktlILt","2Yz7EF6PT2","euZA5FFDui","MaJQstaOXK","MGlTFVprf2","zY1GY2Yz7E","IRh48d7vjM",
-"iKqhrdjsrv","FwEJzv8yFN","b29RJrKDLJ","uTacxAmdQd","XyPZNOUYuF","DLhzML7cGc","uupzkqUJMd","FwEJzS2Dfu","mX2GEqUJMd","FLsphxXTI4",
-"jzUqRfmIK1","Z4I1vaL6AJ","WMiS3WaWsv","DcpWBuupzk","uTacxFVMxo","POUYS8xEKz","AmdQd07n1c","HzZT8K4GS8","Q6hMCrKDLJ","5iGN5a00b5",
-"MaJQswDajX","W7cTstvdkD","5Mg9rIBe8k","uoStwlm0pD","fLNg8lm0pD","ydG8UaL6AJ","sx5GlvOqCE","zmLYD8TxD7","lH1ktatef2","oQ87razIWp",
-"b29RJFFDui","QssNCQYxC0","xXTI4OHaBz","16lHchE1Ql","TXQ0ZGWqqX","jeskSYh1hF","ksJbyhe9IA","64s8NhE1Ql","Kr8ysb29RJ","uupzkECMvU",
-"Q6hMCZv7z0","gjUTupT8wu","d7vjMFnPFB","Oz8yZCK5W7","2DREs4QMc9","Yh1hFAXpwE","RkQkeyluBx","gf8rIm4bxU","LDk6f7fsYM","QYxC08xEKz",
-"Y1mC0aDGtS","IjTwPdQ586","jzUqRDLhzM","VBjhz45cIH","AXpwECNHmv","Twano4dEz6","SWfoul83Ud","QbxXcECMvU","9XyT9gjUTu","5VZjSzY1GY",
-"QClRLhi5X7","AgJHQa00b5","BpYhVtAOsr","prNT6n1pmO","x3LDeulk41","VNCPdXyPZN","VBjhzReKEW","StlDJStlDJ","MezSWZJTXH","5NammOUYuF",
-"Ul4a10Kyfs","Nxx9VwDajX","uvf7Arz7Ut","JRJQBgf8rI","bgJAzCfgr3","618DiBGaQY","zHF1qXyPZN","lsQGorz7Ut","FVMxolCMxy","0PktIb29RJ",
-"jfREubgJAz","1j5L8GXdoH","zmLYDBFkb8","d7vjM16lHc","C2IrcmX2GE","sqVrfTa8f6","16lHc5ZaEz","Y1mC0vLsmS","zqH0WY1mC0","B3qemGSQwj",
-"TwanolXFOB","uAWypvOqCE","ydG8UuZPqg","WmadA8FmFH","7Ow5Clm0pD","5IhmGaez9y","CNHmv9iGoT","yluBxeuZA5","euZA5sx5Gl","C2IrcZJTXH",
-"blLA9TCgPp","ciuWzPOUYS","qQxHPRACuj","No0QbWreyP","0PktIKsjRK","QWxoTFhtgl","NAFuwW7cTs","iKqhrpiJSk","AgJHQzHF1q","taOXKMmKGJ",
-"pAhR1QYxC0","POUYS9GXkX","C2IrcRmDcr","MezSWuLtKs","MojnPJIqXi","e6e4zVerEA","n1pmOh1zcH","Waim6hUTw7","ThjNnFwEJz","X6PinhSSvQ",
-"yEfy9CK5W7","IjTwPIKxdL","Zv7z0OUYuF","FjHXRkB5nP","KASQ8lH1kt","fmIK1RzaZA","StlDJBpYhV","lweGyyofH3","5drc6uQIcz","RxrsmsuY4x",
-"xXTI45Namm","nlaBy7Ow5C","FnPFBUl4a1","BFkb8zY1GY","2TRI7MezSW","RACuji3pyd","n1pmOYw2oU","KASQ8tl72W","qaofN7fKYU","uQIczt59lR",
-"9rlg95drc6","GrDg7vLsmS","mX2GE3otm6","BFkb8ix74r","oVQp6VBjhz","P6bcgP6bcg","Yf2Ec4QMc9","OUYuFzbIYY","S2DfuC2Irc","pAhR1GXdoH",
-"rhl0JyluBx","Mkgy82TRI7","s93Mls7Mxk","MK07Y9eoRc","ni2v1AmdQd","iB08lgjUTu","RzaZAoQ87r","D6rByB3qem","ydG8U0MR5X","jfREuhSSvQ",
-"RBhp0v1Hln","BbwgAjS1aj","h1zcHOxWIH","uAWypWaWsv","FNYIMn8pJ9","GWqqXs93Ml","1LB1LzHF1q","9XyT94W0Tl","fmIK1vkCHH","SjskQVerEA",
-"fcwDaQClRL","DLhzMnnP8o","lCMxyPb1pa","6q6L9L7cGc","aez9yjS1aj","16lHcjtn0X","8hJdte6e4z","SmGzvuLtKs","m4bxUZJTXH","s7MxkYOfrY",
-"uTacxXflUq","K20wKSmGzv","O3iyQMmKGJ","0Wr5yMmsIo","VIlwPYjB9t","suY4xulk41","FjHXRAmdQd","yluBxFVMxo","HlUbFDcpWB","GSQwj4W0Tl",
-"uZPqgyEfy9","uvf7AfFDrJ","14FLRM6qcG","FcWrWx3LDe","CK5W729QAz","Mm8siQ6hMC","Oz8yZ4dEz6","lkMUAAXpwE","9XyT9Cp3mZ","5VZjSNOHsz",
-"gdQsSbZLvS","No0Qb7lUXZ","brhlQciuWz","Yf2EcdmoS7","taOXK48cHL","M6qcGtAOsr","ydG8UdQ586","F6PT2Twano","gdQsSzFgtB","bZLvSCIShG",
-"FxX9qS77LH","okgRitl72W","EdBKcMmKGJ","Q6hMCi7WMQ","XyPZNAkKTk","POUYSQbxXc","5nmWvi7WMQ","4W0TlqaofN","IKxdLRACuj","LDk6fLewvM",
-"S2Dfudpe1v","iqv4kVNCPd","6AFT0HRxd8","fLNg8ciuWz","gdQsShE1Ql","KZamHGv3Fq","7Ow5CG1RhS","618DiokgRi","YjB9tHP433","FjHXRoQ87r",
-"0BmCy07n1c","ThjNnfcJOy","KASQ8hYBCK","Ss0ZuJRJQB","oGu6x7lUXZ","QworuChuy3","X6PinTwano","BFkb8MojnP","pT8wudmoS7","O3iyQIjTwP",
-"qQxHPPb1pa","CqqaDWPmlx","AgJHQ7Ow5C","h1zcH7ku1p","618DicmXIX","lweGy8FmFH","ZzJHWzqH0W","lj07QDcpWB","guMb8Vprf2","BCxeC1v5hH",
-"v8yFNtlILt","jfREuru4UG","Mkgy8ZzJHW","lViBvblLA9","F6PT2dmoS7","No0QbAkKTk","5VZjSuoStw","Chuy3EdBKc","hSSvQlkMUA","i3pydCqqaD",
-"zz4ZUlCMxy","lViBvGSQwj","uLtKs2Nslm","6AFT0BGaQY","gjUTuRpBQm","fcwDaDQimp","lsQGoAmdQd","iKqhrx3LDe","hE1Ql0h1b1","qaofNulk41",
-"MezSWG1RhS","s7MxkQworu","vkCHHi3pyd","wiHrZQChxs","jeskS0BmCy","aDGtS9iGoT","P6bcgcShY2","qQxHPy94nw","pmeCdyToGW","SWfoueuZA5",
-"BCxeCOHaBz","qQxHPcmXIX","CK5W7GrDg7","7lUXZAOgEe","WaWsvaFFss","ix74rZJTXH","TCgPpy94nw","fFDrJK4GS8","4W0TlDG4sT","hE1QlfLNg8",
-"RkQkewDajX","okgRiyvOMI","CK5W72Yz7E","2NslmjiVBP","uAWyptvdkD","PYBf4S2Dfu","Ta8f6pWiOs","Twano0YAGH","Yh1hFFFDui","29QAzStlDJ",
-"8RCUAFwEJz","gjUTuHzZT8","RzaZAsoy9t","5VZjSCxVEf","cQOnv7fKYU","DcpWB8cVD3","blLA916lHc","C2IrcNcICA","YjB9tBFkb8","lpF6WfmIK1",
-"x3LDezqH0W","F6PT2zmLYD","hSSvQfqypy","14FLRWPmlx","tuDySWMiS3","9XyT96AFT0","AOgEeOUYuF","4W0TlSmGzv","MezSWhYBCK","o8UydKr8ys",
-"QClRL7fKYU","MojnPOxWIH","vkCHHZuDtD","s7Mxki7WMQ","AXpwETXQ0Z","fmIK1xciqp","5IhmGs4786","45cIHqaofN","5ZaEzBGaQY","45cIH5ZaEz",
-"l83UdyToGW","Ul4a1W7cTs","580YDJ2mQi","Yf2Ecix74r","0KyfsUl4a1","OHaBzDz1R3","ogLgclCMxy","VNCPd0Kyfs","JKWYRMK07Y","IBe8kIRh48",
-"Yh1hFY1mC0","2TRI7dQ586","KsjRKZv7z0","oQ87rQClRL","8cVD3uQIcz","jtn0X45cIH","5nmWvlweGy","S2DfuYh1hF","EOE1oZ4I1v","zQt6QBFkb8",
-"WmadAFcWrW","m4bxU0Kyfs","zqH0W9GXkX","zFgtB0h1b1","iqv4kIn3NS","1LB1L9rlg9","jSjS3MojnP","QWxoTBCxeC","14FLR0Kyfs","wDajX5drc6",
-"HfyNQru4UG","cShY20MR5X","IRh48pT8wu","atef2Q6Lix","n1pmOO3iyQ","gtCA5FLsph","x3LDelpF6W","jS1ajKZamH","hSSvQFPfSE","P6bcgHP433",
-"k85Ae5Drn0","pAhR1brhlQ","pWiOslweGy","14FLRfaHir","EoToPaFFss","IRh48dpe1v","GXdoH0Wr5y","G1RhSy94nw","NOHszDcpWB","7fKYU8hJdt",
-"8FmFHfmIK1","0ao3llj07Q","07n1cfaHir","qaofNsuY4x","FLsph0MR5X","prNT6djsrv","WreyP2ZHdk","FPfSERsQUq","cL0aE45cIH","kB5nPF6PT2",
-"HP433WreyP","SbRYyZhwG1","fFDrJa00b5","GXdoHd85a9","ECMvUpWiOs","9iGoTCqqaD","RBhp0C2Irc","aFFssK4GS8","tlILtRzaZA","3otm6FLsph",
-"ZUnqtpiJSk","NOHszCNHmv","VjCZqbZLvS","zqH0WMmsIo","SbRYy0YAGH","AXpwEW7cTs","29QAzsqVrf","9GXkXuupzk","n1pmOSmGzv","ciuWzdhSuH",
-"yEfy9W3VFH","tAOsrVjCZq","S2DfuogLgc","uoStwcL0aE","3otm6WMiS3","2Nslm0MR5X","7Ow5CfmIK1","t98iWHP433","UmaEvOHaBz","16lHcWMiS3",
-"jS1aj5nmWv","xciqpdQ586","NOHszcL0aE","8cVD3I7p2a","uPX7GgjUTu","9eoRcG1RhS","7X3uyfcJOy","n8pJ9v8yFN","taOXKxciqp","rKDLJZUnqt",
-"0YAGHpiJSk","VLTy6FnPFB","1LB1Ls7Mxk","e6e4zjSjS3","VjCZqBbwgA","SWfouuupzk","GSQwjZJTXH","1j5L8DcpWB","guMb8gtCA5","SmGzvG1RhS",
-"VIlwPyvOMI","prNT6RkQke","PYBf47lUXZ","SjskQprNT6","cmXIXJkzUn","yToGW4dEz6","uZPqgZzJHW","FLsphkZANm","s4786oGu6x","580YDxciqp",
-"ni2v1JIqXi","580YDzFgtB","CK5W7ZhwG1","ix74rAXpwE","suY4xzz4ZU","lj07QJ2mQi","x3LDeyluBx","Zv7z0djsrv","2Yz7E7fsYM","gf8rIUl4a1",
-"Twano2hEEU","StlDJtl72W","9y4lwFcWrW","TwanooQ87r","FGzgpJRJQB","HzZT8hE1Ql","OxWIHRsQUq","uJScX6q6L9","QbxXc5Mg9r","brhlQ2ZHdk",
-"8U2nUnlaBy","Yf2EcUmaEv","kZANmW7cTs","OUYuFQWxoT","QssNCFcWrW","b29RJmz8gx","JkzUnlj07Q","0PktIJIqXi","F6PT2piJSk","5drc616lHc",
-"oQ87rsx5Gl","IBe8kLDk6f","taOXKjeskS","StlDJMezSW","Cp3mZWaim6","5iGN5cQOnv","IKxdLblLA9","aFFssyluBx","RACujyofH3","SbRYyAIYUu",
-"7ku1pcQOnv","RkQke4QMc9","8TxD7uupzk","7fsYM4W0Tl","lkMUAGrDg7","QClRLDcpWB","FGzgpTCgPp","yEfy9EOE1o","Uvlv4Waim6","CdyBVNOHsz",
-"45cIH8xEKz","uQIczfmIK1","JIqXiFNYIM","KsjRKNxx9V","DLhzMDLhzM","1v5hHKASQ8","0PktIlsQGo","LDk6fiwzGk","D6rByhE1Ql","MK07YjSjS3",
-"OUqFMuZPqg","K4GS8AkKTk","s7MxkpFrrl","RpBQmdpe1v","lweGyYOfrY","VLTy6euZA5","JXljWhe9IA","0PktIprNT6","uJScXUl4a1","blLA9mX2GE",
-"RBhp0IBe8k","aL6AJyluBx","FxX9qRACuj","wiHrZzqH0W","NhXduGSQwj","FnPFBoGu6x","pFrrlW7cTs","NAFuwfcJOy","zbIYYGv3Fq","Cp3mZzmLYD",
-"qUJMdpT8wu","tuDySyvOMI","pT8wuhSSvQ","aDGtSrKDLJ","B3qem2Nslm","UmaEvZzJHW","I7p2aGv3Fq","jeskSnlaBy","2TRI7DLhzM","atef2jSjS3",
-"t59lRVIlwP","7lUXZpT8wu","okgRi5drc6","VNCPddQ586","F6PT2lj07Q","G1RhSs93Ml","jfREupv0i7","y94nwPOUYS","AOgEenlaBy","2hEEUMK07Y",
-"UlU3M1LB1L","dQ586vkCHH","Cfgr39rlg9","BFkb8t59lR","zY1GYn1pmO","v1HlnVBjhz","TXQ0ZlCMxy","0YAGHFxX9q","QnJ1SJRJQB","7lUXZHfyNQ",
-"Yh1hFvkCHH","bgJAzWaim6","i3pyddpe1v","uupzkJKWYR","hE1QlzbIYY","piJSkNhXdu","0ao3lkZANm","Yw2oUFGzgp","JKWYR29QAz","bZLvSBpYhV",
-"5IhmGjiVBP","5ZaEzuQIcz","5Mg9rFwEJz","dmoS7KASQ8","Cp3mZ0Wr5y","W3VFH45cIH","AIYUuzFgtB","2TRI7CK5W7","prNT6JkzUn","5ZaEzpvgjS",
-"uLtKshUTw7","Zv7z05Namm","Pb1paTCgPp","FPfSES2Dfu","zmLYDOxWIH","atef2mz8gx","BbwgAVIlwP","guMb8CIShG","FcWrWfFDrJ","tAOsrgdQsS",
-"aez9yTCgPp","azIWps7Mxk","PYBf4lm0pD","gjUTuiKqhr","9eoRcDG4sT","QClRLEdBKc","5Namm3weIF","blLA9ReKEW","ogLgcaL6AJ","gIYvEPOUYS",
-"0BmCy4QMc9","oVQp6VLTy6","uoStwNcICA","gf8rIzHF1q","Q6LixQClRL","S77LH5Namm","cShY2VerEA","lCMxyIKxdL","G1RhSSmGzv","1v5hHFwEJz",
-"b29RJECMvU","UlU3MlXFOB","v2eC3h1zcH","mz8gxpmeCd","QssNCeuZA5","uZPqgYh1hF","ni2v1kB5nP","a00b5pvgjS","Pb1paF6PT2","HlUbFxXTI4",
-"Ss0ZulViBv","ECMvUGv3Fq","HlUbF5Mg9r","fqypyoQ87r","a00b5h1zcH","5ZaEz1v5hH","MaJQsb29RJ","jS1ajlweGy","QYxC0oQ87r","fLNg8Q6hMC",
-"S2DfuvkCHH","jeskSe6e4z","24ARFPYBf4","i7WMQZuDtD","6AFT0VBjhz","Gv3FqokgRi","GrDg7uTacx","FLsphmz8gx","Waim6m4bxU","GXdoHyluBx",
-"OHaBzqaofN","h1zcHYh1hF","jS1ajKsjRK","Oz8yZkZANm","PYBf4NcICA","5IhmGF6PT2","ogLgcjSjS3","9rlg9GWqqX","ix74rMmsIo","RsQUqDcpWB",
-"Mm8siQbxXc","VerEAMK07Y","8hJdti7WMQ","b29RJsuY4x","TXQ0Zdpe1v","QYxC0UmaEv","uZPqgvOqCE","No0QbwDajX","AIYUueuZA5","Y1mC00PktI",
-"7Ow5Ch1zcH","uAWypGrDg7","7X3uyoQ87r","CqqaD5Drn0","XflUqTCgPp","lViBv9iGoT","7ku1p5VZjS","hE1QliwzGk","ECMvUiB08l","Cfgr3zqH0W",
-"RzaZAECMvU","MGlTFmX2GE","VerEAy94nw","Cfgr3IKxdL","2Yz7EJRJQB","gf8rIguMb8","X6PinQ6hMC","KsjRKDG4sT","24ARFfLNg8","FcWrWCNHmv",
-"WDVWJciuWz","bZLvSF6PT2","0KyfsLbRTH","FGzgpLDk6f","pT8wuWaWsv","lweGyWaWsv","3weIFuZPqg","ZhwG1k85Ae","uTacxY1mC0","GrDg7cmXIX",
-"1v5hHrhl0J","3otm6nFqik","okgRiQworu","oVQp6WaWsv","Dz1R3n8pJ9","WmadAd85a9","JIqXiAkKTk","GWqqXMK07Y","7fKYUEdBKc","24ARFMkgy8",
-"aez9yn8pJ9","ru4UGStlDJ","BCxeCy94nw","FxX9qjfREu","dhSuH29QAz","t98iWm4bxU","7lUXZuZPqg","Uvlv4o8Uyd","v1Hln2ZHdk","NAFuwfmIK1",
-"VerEAMezSW","6q6L9NOHsz","d85a9i3pyd","pv0i7AkKTk","wiHrZ6AFT0","48cHLG1RhS","LbRTHKASQ8","07n1cfLNg8","fLNg82hEEU","ru4UGQClRL",
-"CNHmvBbwgA","brhlQ1LB1L","fcJOyDG4sT","7X3uylpF6W","hYBCKW7cTs","tuDySBCxeC","9GXkXgIYvE","zFgtB48cHL","zFgtBprNT6","RACujVerEA",
-"aDGtSzQt6Q","FhtglbgJAz","EdBKclsQGo","n1pmOU3yw5","45cIHTXQ0Z","wDajXdmoS7","n8pJ9uLtKs","l83Udsx5Gl","M6qcGK20wK","zFgtBM6qcG",
-"WmadAJRJQB","yvOMIfqypy","mz8gxhYBCK","mX2GEzHF1q","VNCPdSWfou","9rlg9MezSW","RxrsmpT8wu","tuDyShi5X7","ksJbyPb1pa","5nmWvh1zcH",
-"Mm8siIBe8k","SWfounnP8o","DcpWBOz8yZ","ksJbyFLsph","2DREsydG8U","kB5nPFVMxo","soy9tSs0Zu","i3pyde6e4z","16lHcdpe1v","J2mQiiB08l",
-"LbRTHAmdQd","k85AeAIYUu","VerEAOz8yZ","okgRiJRJQB","lXFOB7ku1p","ECMvUm4bxU","l83UdciuWz","2DREsF6PT2","1v5hH07n1c","xciqpQssNC",
-"oVQp6K4GS8","QClRLiqv4k","Yf2Ec2ZHdk","o8UydGv3Fq","YjB9tIKxdL","cL0aEtvdkD","iqv4kUl4a1","h1zcHNcICA","atef2AgJHQ","lViBvguMb8",
-"S2DfubgJAz","cL0aEI7p2a","aDGtSsqVrf","Gv3Fq7fsYM","he9IAU3yw5","Yw2oUEdBKc","NOHsz0YAGH","ydG8Uzz4ZU","8RCUA48cHL","t98iWTCgPp",
-"Ul4a1M3zXL","RmDcrMojnP","tlILtJ2mQi","tuDySIjTwP","cQOnvlH1kt","uN6r37ku1p","ZzJHWl83Ud","lViBv7ku1p","Q6LixHRxd8","Mkgy8ni2v1",
-"Vprf2t59lR","l83UdWreyP","RxrsmBGaQY","48cHLHfyNQ","iwzGk5Mg9r","rKDLJVjCZq","l83Udv1Hln","mX2GEhE1Ql","faHirUvlv4","EoToPlViBv",
-"GXdoHni2v1","I7p2a5VZjS","v8yFNCdyBV","sx5GlMmsIo","ix74rO3iyQ","sqVrfuupzk","hi5X7OUYuF","s7MxkdmoS7","RsQUqkB5nP","ThjNntlILt",
-"qUJMd4dEz6","lViBvs7Mxk","EoToPn8pJ9","29QAztAOsr","9GXkXBGaQY","zqH0WStlDJ","lCMxyCdyBV","zY1GYQbxXc","tuDySgtCA5","7hyVvciuWz",
-"1j5L8Z4I1v","FGzgpzbIYY","8hJdtNcICA","gtCA5QnJ1S","NcICAAOgEe","dpe1vUmaEv","oQ87rv1Hln","3weIFjfREu","4QMc9jSjS3","StlDJru4UG",
-"LbRTHt59lR","ZuDtDx3LDe","FcWrWzFgtB","QbxXcnnP8o","dhSuHGWqqX","zHF1qi3pyd","lXFOBYOfrY","7hyVvCqqaD","ECMvUni2v1","yToGW8hJdt",
-"CNHmvvLsmS","4W0TlCp3mZ","yToGWKr8ys","azIWpcShY2","QnJ1SydG8U","RkQkeuoStw","uLtKsFPfSE","wDajXEdBKc","64s8NuN6r3","ulk41TCgPp",
-"t98iWFPfSE","CNHmvaL6AJ","v8yFNdpe1v","cShY2m4bxU","Y1mC0bZLvS","jtn0XhYBCK","7hyVvoVQp6","Uvlv4uPX7G","VNCPdFNYIM","Z4I1v9rlg9",
-"UmaEvv2eC3","atef2zQt6Q","RzaZApmeCd","rz7UtGWqqX","K4GS8ECMvU","aFFssPOUYS","zY1GYWaWsv","yluBxpWiOs","9GXkXAkKTk","5VZjSvOqCE",
-"X6PinQChxs","X6PinF6PT2","FLsphM3zXL","s7Mxk9y4lw","ksJby8xEKz","tvdkD7hyVv","prNT6WMiS3","qUJMdAmdQd","uPX7Gi7WMQ","uTacxfcJOy",
-"x3LDefmIK1","fmIK12ZHdk","IjTwPPYBf4","ogLgcQ6hMC","Waim6K4GS8","TwanotuDyS","tuDySgdQsS","7hyVvdQ586","In3NSRACuj","MezSWI7p2a",
-"gtCA514FLR","580YDP6bcg","gdQsSmX2GE","8RCUA618Di","In3NSvOqCE","0KyfspmeCd","KASQ8wiHrZ","7lUXZqUJMd","580YDVprf2","tlILtAgJHQ",
-"oQ87rprNT6","14FLRMkgy8","POUYSI7p2a","HfyNQh1zcH","JXljWVNCPd","CqqaD2Nslm","ZzJHWuupzk","iB08lB3qem","ru4UGVLTy6","K4GS8OHaBz",
-"9XyT9HRxd8","dpe1vfcJOy","yEfy9s93Ml","CxVEfQWxoT","MmsIoHlUbF","M3zXLCp3mZ","gf8rIRBhp0","iKqhro8Uyd","n8pJ9v2eC3","ZJTXHni2v1",
-"pvgjSaez9y","Q6hMCBpYhV","XflUqLDk6f","aez9yVjCZq","3weIFydG8U","QssNCW3VFH","0PktIHzZT8","AmdQd0BmCy","nFqik9eoRc","2Yz7EHzZT8",
-"RmDcrlweGy","0MR5XprNT6","Twano6q6L9","FLsph5Drn0","FxX9qaL6AJ","7Ow5CXflUq","fcwDaOxWIH","qaofNZv7z0","aez9yhSSvQ","WreyP9rlg9",
-"FnPFBNhXdu","iB08l2DREs","AOgEeC2Irc","ThjNnJRJQB","FLsphzFgtB","fqypym4bxU","v8yFNbrhlQ","DG4sTulk41","8U2nUpAhR1","wDajXY1mC0",
-"tAOsrMmKGJ","oGu6xGXdoH","a00b5LbRTH","lCMxyNAFuw","GXdoH580YD","NhXduJ2mQi","ZzJHWkZANm","gf8rIjSjS3","C2IrcDLhzM","WmadAulk41",
-"mz8gxOUYuF","CNHmv16lHc","Yw2oUbgJAz","guMb8hUTw7","16lHcgtCA5","b29RJjfREu","mz8gxUmaEv","lweGyStlDJ","cL0aEiB08l","KZamH0BmCy",
-"07n1cL7cGc","QssNCHRxd8","9eoRcNOHsz","xXTI4AXpwE","xXTI4IjTwP","rKDLJ1j5L8","2hEEU8U2nU","hSSvQrhl0J","xXTI4IKxdL","SbRYyFPfSE",
-"UlU3MJJs5m","iKqhr7fsYM","RsQUqRmDcr","FcWrWpiJSk","48cHLfcJOy","16lHcpWiOs","Z4I1vpWiOs","QWxoTFcWrW","9y4lws4786","v1HlnnlaBy",
-"hYBCKi7WMQ","ksJbyCxVEf","ydG8UFnPFB","rKDLJv8yFN","GXdoHXyPZN","lkMUA0h1b1","FNYIMX6Pin","FwEJzWreyP","o8Uyd7Ow5C","atef2gf8rI",
-"x3LDeG1RhS","iKqhrNcICA","Kr8ys55rfB","CxVEf5IhmG","2Yz7ERsQUq","QChxslXFOB","cShY2Kr8ys","Z4I1v5ZaEz","S77LHzmLYD","zqH0Wt98iW",
-"uZPqgiKqhr","guMb8MK07Y","9y4lw1v5hH","aez9yEOE1o","O3iyQYOfrY","zz4ZUaL6AJ","RACujPb1pa","iKqhrCdyBV","iB08ltlILt","QworuqQxHP",
-"M6qcG5iGN5","Pb1paDz1R3","W7cTsRBhp0","yToGWSjskQ","QssNCogLgc","aL6AJyToGW","HzZT8fcwDa","atef2qaofN","oQ87rWMiS3","POUYS7fKYU",
-"uN6r3GXdoH","FGzgphSSvQ","2hEEUI7p2a","JKWYRCqqaD","zz4ZUeuZA5","yvOMIFPfSE","K4GS8SbRYy","FcWrWh1zcH","pWiOsAkKTk","uTacxOz8yZ",
-"hi5X7WDVWJ","FwEJz8RCUA","cShY2PYBf4","9XyT9i7WMQ","5nmWvRxrsm","XflUqvLsmS","580YDRACuj","Gv3FqlXFOB","pT8wuVIlwP","CIShG5drc6",
-"LDk6fru4UG","cmXIX0ao3l","7fKYU7Ow5C","n8pJ9FFDui","uQIczru4UG","FGzgpC2Irc","Y1mC0WDVWJ","JIqXi1v5hH","29QAz7fsYM","I7p2as4786",
-"G1RhStjQxs","KsjRKguMb8","D6rByWreyP","vOqCEVerEA","1v5hHjS1aj","d7vjMCqqaD","2ZHdkoQ87r","VNCPdjzUqR","NOHszuLtKs","GrDg7Oz8yZ",
-"9GXkX9eoRc","t59lR55rfB","2Yz7ElH1kt","O3iyQVprf2","uZPqgHRxd8","W3VFHo8Uyd","blLA9lCMxy","tjQxsSbRYy","MmsIomX2GE","o8UydQ6hMC",
-"BbwgATwano","brhlQQYxC0","5IhmG0PktI","pv0i7OxWIH","ni2v1uupzk","gf8rIzmLYD","8TxD70Wr5y","dmoS7B3qem","aez9yAOgEe","M3zXLcL0aE",
-"9GXkXd7vjM","8xEKz9y4lw","I7p2aIBe8k","WaWsvi7WMQ","HP433AXpwE","he9IAhE1Ql","o8UydSs0Zu","O3iyQRzaZA","hi5X7zz4ZU","nnP8oo8Uyd",
-"ZJTXHlXFOB","RACujjiVBP","AmdQdwiHrZ","guMb8Ul4a1","o8Uyd8cVD3","euZA514FLR","Ss0Zu5ZaEz","s47869iGoT","4dEz6rhl0J","8cVD3Yf2Ec",
-"dmoS7X6Pin","IjTwPSWfou","JJs5mpv0i7","zqH0WPYBf4","Fhtglrhl0J","QChxsnFqik","Z4I1vMojnP","vOqCE0h1b1","Q6hMCfqypy","i3pydprNT6",
-"uupzkW3VFH","0ao3llViBv","xciqpfqypy","hYBCK5Drn0","IjTwPlXFOB","0PktIHlUbF","3otm6guMb8","euZA5ix74r","rKDLJpWiOs","s93Mlhe9IA",
-"ru4UGRxrsm","nnP8ouoStw","0MR5XZzJHW","zqH0WDQimp","bgJAzl83Ud","SWfouECMvU","P6bcgnFqik","7X3uyogLgc","0ao3lTwano","No0QbPYBf4",
-"2TRI7RBhp0","8xEKz9eoRc","oGu6x55rfB","M6qcGlH1kt","Cp3mZPYBf4","tuDyStjQxs","k85AeYw2oU","hSSvQaez9y","7fsYMWPmlx","yluBxy94nw",
-"Mm8si0h1b1","0ao3ltl72W","Oz8yZ2Yz7E","pFrrlru4UG","GWqqXuLtKs","Uvlv44W0Tl","IKxdLzbIYY","Nxx9VRpBQm","yvOMI4QMc9","azIWp0PktI",
-"Cp3mZHfyNQ","KZamHHP433","ciuWzcmXIX","MGlTF14FLR","aL6AJd85a9","d85a916lHc","lpF6WPYBf4","zQt6QxXTI4","DG4sTStlDJ","L7cGcRxrsm",
-"K4GS8VjCZq","he9IANAFuw","fmIK1FjHXR","6q6L90ao3l","vkCHHzHF1q","CNHmvBFkb8","7hyVvnlaBy","Gv3Fq5iGN5","618DiCp3mZ","F6PT2QChxs",
-"yToGW9rlg9","tlILtv1Hln","uLtKsMGlTF","nlaByKr8ys","kB5nPkZANm","SWfoulweGy","8FmFHzQt6Q","jiVBPCIShG","prNT6oQ87r","FPfSE9y4lw",
-"GSQwjvOqCE","d85a9POUYS","ciuWzSjskQ","NAFuwQssNC","Yf2EcYh1hF","8xEKzWaWsv","ReKEWjSjS3","BbwgA618Di","ogLgctaOXK","7ku1p0ao3l",
-"EoToPpAhR1","cShY2uAWyp","OHaBzVLTy6","tlILtUvlv4","n1pmO7hyVv","SmGzvfLNg8","NcICAhE1Ql","jeskSkB5nP","7lUXZfmIK1","JKWYRStlDJ",
-"bgJAzuLtKs","KsjRKXflUq","rhl0JFcWrW","pmeCdt98iW","tjQxssx5Gl","piJSkZJTXH","dhSuHTCgPp","4W0TlUvlv4","pmeCdgIYvE","SbRYyt98iW",
-"QChxs45cIH","RsQUqru4UG","tjQxs580YD","d7vjMpWiOs","gf8rIWMiS3","CqqaDPYBf4","sx5GlpT8wu","gjUTuatef2","cmXIX5ZaEz","WDVWJblLA9",
-"ciuWz8U2nU","O3iyQMK07Y","n8pJ9MojnP","D6rByZuDtD","FhtglciuWz","7X3uyv8yFN","t98iWfcJOy","OUqFMNOHsz","2DREsatef2","2DREstvdkD",
-"L7cGcHP433","jSjS3tjQxs","iKqhrFxX9q","9GXkXY1mC0","2TRI7i7WMQ","uvf7AEdBKc","5nmWvGrDg7","HlUbFFnPFB","45cIHzz4ZU","okgRiMmsIo",
-"zY1GY7lUXZ","0PktIuvf7A","ulk41Cfgr3","uQIczQnJ1S","WPmlxn1pmO","DG4sTlweGy","sx5GlzFgtB","dhSuHsqVrf","CK5W7uZPqg","k85AeFwEJz",
-"n1pmOWreyP","yluBxatef2","Z4I1vDcpWB","8TxD73otm6","pT8wuAkKTk","FhtglK4GS8","vLsmSWDVWJ","tvdkDFPfSE","kZANmCIShG","hi5X7ogLgc",
-"IKxdLRkQke","hE1QlGWqqX","mX2GERACuj","K4GS8HfyNQ","zz4ZUS2Dfu","5NammHfyNQ","Ul4a1v2eC3","Y1mC07fKYU","ZUnqtGv3Fq","16lHcFNYIM",
-"v8yFN0PktI","Oz8yZNo0Qb","qaofN5ZaEz","BFkb8W3VFH","MaJQsfLNg8","Cfgr3ZhwG1","aDGtSlweGy","HRxd8jtn0X","45cIHOz8yZ","zbIYYY1mC0",
-"4dEz6wiHrZ","AmdQddQ586","tAOsrWPmlx","i3pydiKqhr","Ta8f6iB08l","WPmlxfcJOy","IKxdL9rlg9","jSjS3AgJHQ","M6qcGuLtKs","v8yFNJXljW",
-"aez9yCIShG","AkKTkCdyBV","M3zXLgf8rI","pmeCdFnPFB","rz7UtlViBv","7hyVvOUqFM","FPfSEK20wK","QworuiB08l","ru4UGMGlTF","DLhzM0BmCy",
-"LewvMs7Mxk","DG4sT8TxD7","Chuy3sx5Gl","8cVD3jzUqR","prNT664s8N","OUqFMjeskS","jSjS3U3yw5","F6PT2MmKGJ","s93Ml5drc6","24ARFfaHir",
-"TCgPpQ6hMC","24ARF9rlg9","s7MxkyvOMI","QnJ1SbgJAz","jtn0XNxx9V","yvOMIB3qem","AIYUuS2Dfu","gdQsSU3yw5","sqVrfazIWp","7ku1pTXQ0Z",
-"okgRiIjTwP","F6PT2zqH0W","jSjS3fqypy","yluBxJJs5m","d85a9K4GS8","v2eC3jfREu","8TxD7aez9y","jeskSFFDui","Gv3Fq8U2nU","C2IrczqH0W",
-"Yf2EcAXpwE","0KyfslViBv","BpYhVydG8U","8RCUAMkgy8","X6PinUvlv4","8U2nUKZamH","QssNCAOgEe","lH1ktd7vjM","s7MxkIRh48","ZuDtDFxX9q",
-"aFFssyEfy9","2DREsHzZT8","In3NSjzUqR","FPfSEAkKTk","aez9yCdyBV","aFFssEoToP","DLhzMB3qem","qQxHPQ6hMC","yofH3lH1kt","WmadAcmXIX",
-"JJs5mbrhlQ","EOE1olm0pD","RsQUqWPmlx","uZPqg2TRI7","7fsYMpvgjS","tuDySyluBx","F6PT2Ss0Zu","blLA9yEfy9","LDk6fKsjRK","5iGN5GrDg7",
-"gjUTu07n1c","Yw2oUy94nw","ZuDtDWPmlx","ciuWzvkCHH","24ARFHP433","Nxx9VRmDcr","gIYvEhSSvQ","QssNCFPfSE","dhSuHNOHsz","lj07QsqVrf",
-"uJScXBFkb8","xReec5Mg9r","QClRLDQimp","nnP8oBbwgA","ru4UGlkMUA","0YAGHwiHrZ","m4bxUb29RJ","gtCA57X3uy","KASQ8Ul4a1","MmKGJ14FLR",
-"blLA9Rxrsm","uPX7G5nmWv","vOqCEIBe8k","dmoS7Y1mC0","MmKGJfFDrJ","uupzkZv7z0","RkQkeMaJQs","uZPqgaDGtS","0ao3lnnP8o","5Mg9rkZANm",
-"TCgPpRkQke","3weIFJXljW","CqqaDfcwDa","vLsmSRzaZA","aL6AJlj07Q","EoToP9GXkX","Cfgr37lUXZ","KASQ848cHL","lpF6W2ZHdk","SWfouVBjhz",
-"CK5W7h1zcH","zz4ZU9XyT9","nlaBy8U2nU","aFFsslpF6W","rKDLJFcWrW","b29RJzQt6Q","oVQp6G1RhS","VerEA2TRI7","IRh48MmsIo","Fhtglatef2",
-"VjCZqiB08l","uZPqgRpBQm","ReKEWmX2GE","euZA5CdyBV","t59lROHaBz","BFkb8ydG8U","ulk417fKYU","MK07YQClRL","XyPZNW7cTs","Y1mC0MmsIo",
-"I7p2a8cVD3","7hyVvRpBQm","taOXKlH1kt","kB5nPJRJQB","GWqqXeuZA5","AmdQdd7vjM","S77LHuoStw","NOHszCp3mZ","TXQ0ZaDGtS","5drc69iGoT",
-"7Ow5CuQIcz","AgJHQCdyBV","o8Uydb29RJ","FwEJzHlUbF","7Ow5Cuvf7A","Fhtglgf8rI","uPX7Gatef2","GWqqX4QMc9","RsQUqAIYUu","I7p2ani2v1",
-"zmLYDRkQke","ZzJHWhE1Ql","hE1QlM3zXL","lsQGol83Ud","6AFT055rfB","nFqiklj07Q","pFrrl24ARF","Vprf2AkKTk","FjHXRUlU3M","P6bcgNhXdu",
-"QssNCcQOnv","8TxD7oQ87r","Fhtglmz8gx","ciuWzWDVWJ","DQimp5Namm","Z4I1v9XyT9","U3yw5MaJQs","ECMvUJkzUn","hSSvQFwEJz","sqVrfGv3Fq",
-"5ZaEzv1Hln","y94nwydG8U","RkQkeix74r","5Mg9r5nmWv","HfyNQFwEJz","Cp3mZpAhR1","ru4UGl83Ud","7Ow5CzHF1q","Pb1pafaHir","vLsmSVBjhz",
-"aFFssQworu","lweGyJ2mQi","euZA5AkKTk","wDajX9XyT9","qQxHP6q6L9","piJSkTa8f6","aL6AJaL6AJ","9rlg9hSSvQ","piJSk5Mg9r","P6bcgTwano",
-"9y4lwMGlTF","ECMvUUl4a1","oVQp6he9IA","G1RhSO3iyQ","cL0aEBpYhV","x3LDePb1pa","djsrvVBjhz","ZuDtD9y4lw","ZuDtDAgJHQ","soy9tlm0pD",
-"KZamHTa8f6","jfREuOUqFM","ksJby1v5hH","8cVD3xciqp","CK5W7pv0i7","lkMUAuLtKs","okgRi5Namm","QnJ1SlViBv","5VZjSOUYuF","CqqaDVprf2",
-"lViBvtvdkD","DLhzMiB08l","uTacxxXTI4","HzZT8cmXIX","lsQGoCNHmv","cQOnvYw2oU","y94nwzz4ZU","fqypyCqqaD","RsQUqMK07Y","EoToP7hyVv",
-"OHaBzyofH3","pvgjSGWqqX","DcpWBNhXdu","L7cGcjSjS3","07n1cydG8U","U3yw5i3pyd","VBjhzsoy9t","SmGzvS77LH","gdQsSMojnP","DLhzMmX2GE",
-"nFqik8RCUA","IKxdLFhtgl","07n1cGWqqX","OUYuFL7cGc","TCgPpn8pJ9","5IhmGe6e4z","iqv4kt59lR","ReKEWJIqXi","uupzkt98iW","3otm60MR5X",
-"64s8Nmz8gx","RmDcroQ87r","fmIK1v1Hln","yToGWi3pyd","iKqhrpWiOs","JIqXi6q6L9","he9IAMGlTF","v8yFNtAOsr","QbxXcwiHrZ","uoStwVIlwP",
-"lj07QqQxHP","aL6AJtl72W","nnP8oMkgy8","o8Uyd1v5hH","t98iWpmeCd","tjQxsfaHir","suY4xdmoS7","iwzGkCNHmv","QYxC0IKxdL","uZPqgOxWIH",
-"jiVBPUvlv4","9rlg9oQ87r","Dz1R3gf8rI","lj07QEoToP","TwanoVprf2","ZzJHW2hEEU","M3zXLb29RJ","NOHszciuWz","iKqhr5IhmG","In3NSni2v1",
-"dpe1vBCxeC","v2eC3oGu6x","uPX7Gv8yFN","GSQwjGv3Fq","WPmlxYjB9t","P6bcgOUqFM","ZhwG1Kr8ys","pv0i724ARF","VLTy6nlaBy","lpF6Wt98iW",
-"euZA5FGzgp","7fKYUsoy9t","aDGtSsuY4x","580YDlweGy","GXdoHfcJOy","blLA9Cp3mZ","RsQUqcQOnv","lj07QYw2oU","BpYhVx3LDe","9y4lwcQOnv",
-"4dEz6s7Mxk","FFDuilweGy","7ku1pD6rBy","MK07YNAFuw","QssNCSWfou","O3iyQECMvU","RzaZAQClRL","BCxeCIBe8k","ZhwG1Cfgr3","Ul4a1HzZT8",
-"YjB9t55rfB","tAOsr7lUXZ","7hyVvCIShG","In3NSQssNC","Z4I1vzz4ZU","YOfrYQ6hMC","jiVBPazIWp","e6e4zQnJ1S","9eoRcwiHrZ","jeskSBFkb8",
-"wiHrZtlILt","pFrrl45cIH","mz8gxC2Irc","CxVEfbrhlQ","aL6AJRxrsm","Yh1hFmz8gx","4dEz6xciqp","GSQwjAOgEe","a00b5n8pJ9","bZLvSpAhR1",
-"5ZaEzpWiOs","GrDg7jfREu","HlUbFNo0Qb","0BmCyEoToP","fcJOyoQ87r","JJs5mM6qcG","KASQ8euZA5","RzaZAVBjhz","MmsIozz4ZU","16lHctl72W",
-"4W0TlHfyNQ","Z4I1vfcJOy","yvOMIuQIcz","QYxC0tl72W","y94nweuZA5","MK07YqUJMd","ZJTXHC2Irc","GrDg7h1zcH","GSQwj5Drn0","tuDySGXdoH",
-"h1zcHlH1kt","5VZjS9y4lw","2Nslm5iGN5","B3qemOUqFM","TCgPpjeskS","ix74rh1zcH","Pb1paFhtgl","azIWpHRxd8","ogLgchi5X7","JJs5mOz8yZ",
-"KZamHBpYhV","Ul4a1CNHmv","ZUnqtjSjS3","aFFssU3yw5","29QAzAXpwE","6q6L9fFDrJ","s7Mxkt98iW","FPfSE9eoRc","5nmWvs4786","uZPqgv1Hln",
-"0KyfsKASQ8","zY1GYMmKGJ","i3pyd2DREs","sx5Glxciqp","K20wK1j5L8","uJScXnlaBy","LewvMjS1aj","ulk417Ow5C","nlaByJRJQB","jS1ajlCMxy",
-"NOHszs93Ml","fcJOyOHaBz","ulk41Z4I1v","dmoS79XyT9","S2Dfub29RJ","jiVBPuZPqg","VLTy6jeskS","Q6hMCdQ586","Chuy3qUJMd","J2mQiru4UG",
-"tuDySWaWsv","CIShGFwEJz","tuDyS1v5hH","BCxeCuZPqg","OUYuFK20wK","0BmCyguMb8","ReKEWTwano","Ta8f6dmoS7","CIShGSs0Zu","yvOMIFwEJz",
-"NAFuwNOHsz","S77LHUlU3M","MK07Ydpe1v","CK5W78cVD3","OUqFMuupzk","7X3uyU3yw5","Yh1hFaFFss","5NammksJby","8hJdtuN6r3","Cfgr3Gv3Fq",
-"2ZHdk2Yz7E","EdBKcrKDLJ","FnPFBjS1aj","yluBxF6PT2","cQOnvTXQ0Z","7lUXZF6PT2","fcwDaAXpwE","VNCPdaL6AJ","gdQsSvOqCE","pv0i7sqVrf",
-"MaJQsfqypy","iB08lOxWIH","suY4xRsQUq","i7WMQRBhp0","jeskSAOgEe","suY4xVerEA","Gv3FqzmLYD","0BmCyiwzGk","oQ87rRBhp0","bgJAzuZPqg",
-"3weIFhSSvQ","Gv3Fq5Drn0","FjHXRtvdkD","qQxHPZv7z0","dpe1vt59lR","ix74rW7cTs","5VZjSP6bcg","8U2nUdpe1v","yofH35IhmG","FLspht98iW",
-"he9IA9GXkX","Zv7z0Ta8f6","No0Qb618Di","RzaZAgjUTu","zY1GYTa8f6","Y1mC00ao3l","dpe1vuupzk","Ss0ZuUvlv4","JKWYRk85Ae","ni2v1ciuWz",
-"7lUXZJRJQB","5Mg9rZzJHW","uTacxRpBQm","AOgEeVIlwP","ZzJHWeuZA5","GWqqXpmeCd","Q6Lix0ao3l","ZhwG1Z4I1v","0YAGHReKEW","NhXduv1Hln",
-"yvOMIPOUYS","AXpwErKDLJ","atef2SWfou","0h1b1FxX9q","aez9yAIYUu","9XyT9StlDJ","zbIYYDcpWB","M3zXLxciqp","he9IAni2v1","W7cTsCqqaD",
-"jtn0XuoStw","ThjNnFLsph","AXpwEiB08l","m4bxUJJs5m","Q6LixB3qem","oQ87roGu6x","hE1QlAmdQd","1LB1Ldpe1v","WreyPCNHmv","Waim6t98iW",
-"gjUTurz7Ut","HzZT82Nslm","GXdoHVLTy6","uLtKsuLtKs","2ZHdk8FmFH","s93MlFFDui","soy9tuupzk","pT8wuXflUq","WmadAtuDyS","M3zXL5nmWv",
-"OHaBzBpYhV","OUqFMs93Ml","YOfrYPYBf4","4QMc95Mg9r","pWiOsKr8ys","K4GS8GSQwj","VNCPdfqypy","tvdkDlkMUA","8FmFHYh1hF","AIYUu9GXkX",
-"jtn0XOUYuF","9eoRczQt6Q","JRJQBJRJQB","5NammJJs5m","fcwDatuDyS","jzUqROUYuF","lViBv8FmFH","djsrvJXljW","Twano8xEKz","Mm8siBpYhV",
-"soy9ttlILt","gf8rIjeskS","AXpwE5ZaEz","XflUqOHaBz","oGu6xZJTXH","RkQkeIKxdL","9y4lwAgJHQ","GSQwjpAhR1","QworuLbRTH","k85AeWmadA",
-"5Mg9rtvdkD","7ku1pRxrsm","sqVrfn8pJ9","qaofNoVQp6","guMb8Yf2Ec","14FLRuupzk","lweGyl83Ud","LewvMlm0pD","uTacxP6bcg","lkMUAgf8rI",
-"zY1GYP6bcg","AmdQdC2Irc","cQOnvQClRL","m4bxUhi5X7","Ta8f6sqVrf","Nxx9VjiVBP","L7cGcJJs5m","RkQke0Wr5y","L7cGcydG8U","64s8NpvgjS",
-"Oz8yZcShY2","QssNC0Wr5y","9GXkXlsQGo","ogLgcTCgPp","JkzUnoVQp6","JIqXicL0aE","LbRTHJJs5m","FFDuiMmKGJ","tjQxszY1GY","BbwgAn8pJ9",
-"s93Ml0Wr5y","uupzkvLsmS","6q6L9K20wK","9XyT9IBe8k","4dEz6KZamH","AOgEeEOE1o","L7cGciKqhr","RBhp0yEfy9","Nxx9VUmaEv","IjTwPcShY2",
-"hYBCKDz1R3","gf8rINcICA","SWfouHzZT8","GrDg7suY4x","IjTwPiKqhr","a00b5uJScX","K20wKjeskS","EoToPRpBQm","5NammZuDtD","ZUnqt0MR5X",
-"Y1mC0v2eC3","S2DfuFGzgp","d85a9CIShG","hE1Ql0Kyfs","kZANmUl4a1","7X3uy2Yz7E","5drc6vkCHH","L7cGcblLA9","5VZjS7fsYM","cShY2No0Qb",
-"5nmWvM3zXL","yToGWfcJOy","Ss0ZuOUYuF","mz8gxMmKGJ","qQxHP2Yz7E","WDVWJMmKGJ","cL0aEQworu","K20wKn1pmO","Q6Lixdjsrv","BbwgAlsQGo",
-"ECMvUrhl0J","cShY20YAGH","rhl0JM3zXL","CK5W7FGzgp","K4GS87Ow5C","1v5hHgf8rI","FGzgpYh1hF","8RCUAQnJ1S","IRh48iB08l","FcWrWMezSW",
-"7lUXZ5IhmG","7fKYUYOfrY","prNT6Yw2oU","8cVD3k85Ae","07n1ciwzGk","55rfBZJTXH","64s8NVNCPd","0h1b1tuDyS","aFFssRzaZA","m4bxUru4UG",
-"FhtglSmGzv","hUTw7v8yFN","gf8rILewvM","RkQkeAgJHQ","NcICA1j5L8","uJScXuQIcz","faHirLewvM","ni2v1CNHmv","m4bxUFNYIM","9GXkXguMb8",
-"uZPqgVIlwP","uoStw5nmWv","d85a9CNHmv","jiVBPaDGtS","ThjNngIYvE","dpe1vS2Dfu","SjskQPYBf4","TCgPptaOXK","2ZHdk45cIH","Kr8yshSSvQ",
-"iKqhrlH1kt","dhSuH1j5L8","s4786Uvlv4","9XyT9uupzk","Yf2EczHF1q","M6qcG1v5hH","Gv3FqzqH0W","AmdQdLewvM","FjHXRdQ586","uvf7ANo0Qb",
-"8TxD78cVD3","RBhp0Pb1pa","qQxHPuoStw","QClRLgf8rI","RmDcrBpYhV","IRh48uAWyp","oGu6xOxWIH","dhSuHaez9y","rz7UtMkgy8","IKxdLBGaQY",
-"OxWIHyluBx","kB5nPLewvM","5nmWv45cIH","lViBvyluBx","i3pydgtCA5","0ao3lCNHmv","OHaBzHzZT8","uTacxpv0i7","ciuWzuLtKs","EoToPnnP8o",
-"EOE1opiJSk","GXdoHGrDg7","QClRLjS1aj","ydG8UIBe8k","WMiS3WreyP","he9IAHRxd8","t98iWGrDg7","7fsYMXyPZN","lViBvHzZT8","QWxoTHP433",
-"9rlg9cShY2","7lUXZxReec","d85a9CxVEf","Chuy3v8yFN","s7Mxky94nw","v1HlnkZANm","UlU3Mb29RJ","QWxoTI7p2a","XflUqNOHsz","aDGtSuoStw",
-"55rfBsx5Gl","tAOsrXyPZN","VjCZqcShY2","iB08lJRJQB","rhl0JlkMUA","LewvMi7WMQ","U3yw5pFrrl","gtCA5zFgtB","fqypydpe1v","AmdQdd85a9",
-"h1zcHciuWz","TwanoQClRL","W3VFHRsQUq","LbRTHciuWz","dpe1vfcwDa","Gv3Fqi3pyd","5iGN55ZaEz","580YDWPmlx","O3iyQAXpwE","o8Uydn1pmO",
-"vkCHH9y4lw","580YDAkKTk","X6PingjUTu","8xEKzqQxHP","HzZT88FmFH","jtn0XS2Dfu","EOE1o3otm6","jfREuuoStw","uvf7AjiVBP","ZhwG1F6PT2",
-"t59lRCIShG","m4bxUdpe1v","QYxC0ru4UG","S77LHW3VFH","Gv3FqFPfSE","GWqqXh1zcH","d85a9hUTw7","5Mg9rF6PT2","0ao3luQIcz","7Ow5CUlU3M",
-"jS1ajfmIK1","xXTI4SjskQ","yvOMIhE1Ql","vOqCEwDajX","DLhzMgf8rI","14FLRbgJAz","yvOMI0h1b1","hSSvQtl72W","hYBCKOUYuF","BbwgA2Nslm",
-"0h1b17ku1p","EoToPuN6r3","GSQwjs4786","2DREsL7cGc","mX2GExReec","RACuj48cHL","In3NSb29RJ","pvgjSJ2mQi","In3NSFFDui","7fKYU7hyVv",
-"NhXduyvOMI","0KyfstuDyS","XyPZNRkQke","QWxoT5Mg9r","zFgtBIRh48","ciuWzGv3Fq","ulk41n1pmO","dmoS7AgJHQ","lXFOBLDk6f","KsjRK9iGoT",
-"O3iyQRkQke","VjCZq9rlg9","guMb8OUqFM","gjUTuQChxs","JIqXiBpYhV","d85a9GWqqX","YjB9tU3yw5","gtCA5AIYUu","DLhzMJKWYR","HP433VBjhz",
-"MezSWk85Ae","OUYuF9y4lw","OUqFM2ZHdk","QClRL24ARF","0Wr5yoGu6x","KZamHZuDtD","gf8rI8TxD7","ThjNnzz4ZU","MezSWOUqFM","MmsIo0ao3l",
-"dhSuH8cVD3","In3NSCxVEf","oVQp6JIqXi","WPmlx2Nslm","7X3uyZhwG1","5Drn0zbIYY","jeskSAmdQd","sqVrfCqqaD","OUqFMSs0Zu","Ta8f6AXpwE",
-"5iGN5fcJOy","RsQUqZJTXH","0Wr5yciuWz","uZPqgFPfSE","rz7UtbZLvS","ru4UGoGu6x","TCgPpfqypy","pvgjS5Namm","BbwgAoGu6x","qaofNuZPqg",
-"FjHXRzz4ZU","fmIK1KsjRK","7fsYMx3LDe","CxVEfYjB9t","tl72WPYBf4","v1HlnAmdQd","yToGWvLsmS","dmoS70BmCy","I7p2awiHrZ","x3LDea00b5",
-"0PktIdmoS7","WDVWJJJs5m","9iGoTGrDg7","9eoRcatef2","wiHrZ5iGN5","pFrrl7ku1p","dmoS7dQ586","JIqXi29QAz","Pb1paiwzGk","wDajXjeskS",
-"DcpWBYw2oU","55rfBYf2Ec","EoToPZUnqt","oVQp6Z4I1v","Pb1paQnJ1S","G1RhSsuY4x","5VZjSAkKTk","BbwgAHlUbF","lCMxyOHaBz","ydG8UTa8f6",
-"FjHXRvOqCE","BbwgAs4786","BbwgAY1mC0","tAOsrKZamH","Z4I1vuupzk","TXQ0ZlpF6W","WPmlx618Di","SjskQMK07Y","CqqaDZ4I1v","HRxd8lCMxy",
-"QssNCWmadA","0Kyfsfqypy","KZamHAkKTk","iKqhrNxx9V","8TxD7lpF6W","Waim6WMiS3","BCxeCRpBQm","cShY2HP433","gdQsSuupzk","Zv7z03weIF",
-"nnP8olweGy","0ao3lVLTy6","kZANmLDk6f","WDVWJKsjRK","2hEEUMmKGJ","zmLYDGXdoH","KASQ8F6PT2","GXdoHzFgtB","OxWIHhSSvQ","8FmFHJIqXi",
-"iwzGk5drc6","a00b5bZLvS","FxX9q8U2nU","WDVWJXflUq","uN6r3FwEJz","d7vjMBCxeC","okgRiix74r","SmGzvqUJMd","5nmWvFNYIM","5Drn0v1Hln",
-"cQOnv2ZHdk","UmaEvlH1kt","RkQkeBFkb8","WPmlxIKxdL","Mm8sibgJAz","zY1GYFwEJz","gdQsS9GXkX","UlU3M0PktI","gdQsSECMvU","lj07QzHF1q",
-"dhSuHLbRTH","mz8gxqQxHP","ZzJHWFGzgp","s4786618Di","t59lRvOqCE","7lUXZDLhzM","jtn0XPYBf4","5IhmGjSjS3","5nmWvulk41","uN6r30YAGH",
-"lm0pDUmaEv","2Yz7ETXQ0Z","tvdkDG1RhS","zbIYYjtn0X","JRJQB8xEKz","uN6r3StlDJ","MmKGJpWiOs","5Drn04QMc9","AIYUuFGzgp","gf8rIh1zcH",
-"pFrrlQbxXc","FNYIMFjHXR","Ta8f6X6Pin","JXljWk85Ae","8hJdt29QAz","fLNg8ix74r","24ARF5ZaEz","1v5hHs4786","DG4sTCK5W7","LewvMU3yw5",
-"CK5W7KZamH","QworuJIqXi","Ss0ZuC2Irc","uJScXprNT6","brhlQLDk6f","lXFOBRzaZA","Qworu8U2nU","ru4UGfcwDa","L7cGcKASQ8","Chuy3pFrrl",
-"FVMxo5VZjS","piJSk55rfB","zFgtB5Namm","In3NSK20wK","Zv7z0VNCPd","POUYS8cVD3","zbIYYoVQp6","uAWypOHaBz","lsQGocmXIX","tjQxsgIYvE",
-"4QMc9P6bcg","sqVrfCp3mZ","jzUqR64s8N","3weIF9y4lw","uQIczJ2mQi","SWfouU3yw5","GrDg7yluBx","pT8wuLbRTH","gIYvE618Di","oQ87rGSQwj",
-"faHirs7Mxk","FwEJzciuWz","BCxeC7X3uy","AmdQdPOUYS","HfyNQgjUTu","uoStw1v5hH","uJScXgf8rI","JIqXirhl0J","qUJMdn8pJ9","rz7UtciuWz",
-"dmoS7qUJMd","WreyPbrhlQ","VNCPdW3VFH","yofH30MR5X","No0QbdhSuH","lpF6WZv7z0","Yh1hFi7WMQ","sqVrfqUJMd","CIShG5nmWv","LDk6fsqVrf",
-"IRh48MK07Y","kB5nPi3pyd","zFgtBYf2Ec","2Yz7ElXFOB","BbwgAlXFOB","s7MxksqVrf","WreyPRkQke","hYBCKFNYIM","gf8rIJIqXi","Cp3mZiwzGk",
-"Q6Lixrz7Ut","HP433tvdkD","djsrv5VZjS","zQt6Qi3pyd","vLsmSlj07Q","yToGWtvdkD","k85Ae9GXkX","rz7UtdhSuH","hUTw7aL6AJ","Zv7z0KsjRK",
-"7X3uy2TRI7","BpYhVFjHXR","DQimp14FLR","ulk41pWiOs","euZA5Vprf2","pmeCdQssNC","uN6r3OUqFM","vkCHH1j5L8","zz4ZUDG4sT","uN6r3jfREu",
-"MK07Y7Ow5C","LbRTHgjUTu","5VZjSx3LDe","Yf2Ec618Di","uTacxHfyNQ","lViBvfqypy","brhlQGXdoH","rhl0JIKxdL","gIYvEZhwG1","QWxoTpmeCd",
-"GrDg7TCgPp","LDk6fZ4I1v","14FLRBFkb8","AXpwEDLhzM","Twano8TxD7","taOXKCNHmv","BFkb8zHF1q","t98iW7X3uy","UmaEvTCgPp","d7vjMWDVWJ",
-"lViBv5Namm","he9IAi3pyd","2Yz7EHRxd8","aez9y3otm6","O3iyQ0h1b1","gIYvEsqVrf","JKWYRWDVWJ","rhl0JhUTw7","dpe1v5Drn0","618DiyluBx",
-"LbRTH14FLR","jzUqR0MR5X","gIYvE6q6L9","Fhtgl8hJdt","DQimpOz8yZ","lpF6WOz8yZ","XyPZN1v5hH","y94nwW3VFH","vOqCE6AFT0","64s8N2TRI7",
-"yofH3GSQwj","0YAGHdpe1v","MGlTFrhl0J","8xEKzuZPqg","uTacxhUTw7","cShY29y4lw","RsQUq9GXkX","Dz1R37ku1p","HlUbFVerEA","vOqCEsqVrf",
-"jiVBPC2Irc","55rfB7hyVv","BFkb8Cp3mZ","9iGoTSWfou","JXljWK4GS8","Mkgy8gtCA5","AIYUu0YAGH","W7cTsRkQke","MmsIoHRxd8","a00b5yvOMI",
-"G1RhS5Mg9r","tjQxs24ARF","vLsmS0YAGH","djsrvsx5Gl","v8yFNKsjRK","x3LDenlaBy","Dz1R3uZPqg","i7WMQBGaQY","k85AeVprf2","pFrrlogLgc",
-"1v5hH0YAGH","JkzUnFLsph","e6e4zXyPZN","FGzgpFjHXR","vLsmS9rlg9","djsrvatef2","QnJ1S0YAGH","WaWsv1v5hH","AIYUuIn3NS","LewvMAXpwE",
-"PYBf4DLhzM","GXdoHnlaBy","zFgtBuupzk","a00b5suY4x","jtn0XVBjhz","KASQ8HzZT8","9iGoTVIlwP","ydG8UEOE1o","C2Ircix74r","DLhzMHP433",
-"PYBf4EOE1o","s93MlStlDJ","h1zcHpvgjS","gIYvECK5W7","4W0TlblLA9","64s8NjiVBP","OUqFM0YAGH","Mkgy8XyPZN","b29RJ6AFT0","RkQkeHzZT8",
-"Zv7z0a00b5","RpBQmKZamH","euZA5vLsmS","OUqFMP6bcg","LewvMZJTXH","SbRYyMm8si","TXQ0ZzFgtB","zbIYYJXljW","MojnPGrDg7","oGu6xru4UG",
-"fqypy8FmFH","ni2v1Ta8f6","618DijS1aj","7hyVvJJs5m","OUYuFSWfou","vkCHH1LB1L","gIYvECp3mZ","hSSvQzFgtB","CNHmvhYBCK","mz8gxChuy3",
-"RkQkeWMiS3","jiVBPdhSuH","ZJTXHM6qcG","9rlg9ReKEW","GrDg7AkKTk","4W0TlOxWIH","e6e4zO3iyQ","Oz8yZksJby","3weIF9eoRc","BbwgAhe9IA",
-"K4GS8FFDui","yluBx7ku1p","CK5W7Yw2oU","EdBKcuJScX","Twano2Yz7E","ix74rAmdQd","8U2nU2Nslm","QbxXcVIlwP","580YD2Nslm","XyPZNcShY2",
-"nnP8oEoToP","C2Irc2Yz7E","9eoRcWreyP","qQxHP14FLR","lViBvRsQUq","VerEACdyBV","0MR5XcmXIX","uPX7Gs93Ml","Mm8siGSQwj","Y1mC0ru4UG",
-"GSQwjW7cTs","Zv7z09eoRc","55rfB0PktI","BFkb807n1c","UlU3MblLA9","Fhtglulk41","1LB1LjiVBP","7hyVvMaJQs","CdyBVWmadA","ydG8Ud85a9",
-"tAOsrlkMUA","RkQketAOsr","JXljWFhtgl","tuDySUlU3M","UlU3MG1RhS","AmdQd4QMc9","AkKTkQ6hMC","0ao3lHlUbF","y94nwfmIK1","zY1GYulk41",
-"MojnPTXQ0Z","xReechE1Ql","AmdQd0Kyfs","SmGzvJ2mQi","ThjNnK4GS8","gtCA5ZzJHW","uvf7AfmIK1","HP433zbIYY","8FmFH29QAz","DQimps7Mxk",
-"WreyPQnJ1S","5drc6qUJMd","DG4sTMojnP","8xEKzpWiOs","he9IAFFDui","lweGyrKDLJ","SbRYyUlU3M","cmXIXmz8gx","5NammXflUq","wDajXOxWIH",
-"h1zcH1j5L8","JkzUnCNHmv","tuDySsqVrf","tl72WW3VFH","5VZjSNxx9V","Ta8f6jS1aj","FPfSEMGlTF","WDVWJfLNg8","8RCUAru4UG","618Dik85Ae",
-"MojnPhe9IA","t98iWMkgy8","QnJ1SRpBQm","No0QbJRJQB","XflUqMezSW","Kr8ysyluBx","pv0i7ksJby","W3VFH7fKYU","t98iWiKqhr","iB08li7WMQ",
-"nFqikJkzUn","X6PinZ4I1v","VIlwPazIWp","IBe8kyofH3","0KyfsKZamH","4dEz6OUqFM","sqVrf7Ow5C","zqH0WKZamH","soy9teuZA5","NhXduWaim6",
-"WaWsvGrDg7","AgJHQRACuj","pT8wuZhwG1","pWiOsuN6r3","hYBCKhi5X7","ThjNniwzGk","uoStw8hJdt","ZuDtDRsQUq","7X3uy7ku1p","cmXIXEdBKc",
-"EoToPwiHrZ","uoStwBpYhV","Y1mC0guMb8","VerEA8FmFH","v2eC37ku1p","KsjRKBCxeC","In3NSGWqqX","ksJbyBbwgA","Uvlv4MmKGJ","tAOsruJScX",
-"iB08luQIcz","45cIHFNYIM","kZANmciuWz","aez9yIKxdL","bZLvSyluBx","0KyfsZuDtD","mX2GEYOfrY","qUJMd9iGoT","lpF6WVLTy6","kB5nP64s8N",
-"GWqqXzQt6Q","a00b5zHF1q","D6rBy7Ow5C","FnPFBWmadA","lweGylsQGo","07n1c9iGoT","Yh1hFjSjS3","55rfBhi5X7","ZzJHW14FLR","gtCA5S77LH",
-"vkCHHMojnP","5ZaEzhUTw7","FjHXRHzZT8","iKqhrYOfrY","FGzgpL7cGc","gdQsS16lHc","euZA5GrDg7","1LB1LzY1GY","3otm6lH1kt","OUYuFiB08l",
-"hi5X7FjHXR","OUYuF7fsYM","48cHLlj07Q","FGzgpFFDui","qQxHPx3LDe","7Ow5CwiHrZ","xXTI4uupzk","Cfgr3FNYIM","P6bcgzQt6Q","jzUqR9iGoT",
-"taOXKWmadA","iKqhrQworu","zz4ZUZzJHW","l83UdHlUbF","GSQwj07n1c","pvgjSrKDLJ","VjCZqyvOMI","JXljWPYBf4","uJScXyofH3","FGzgpo8Uyd",
-"2TRI7jzUqR","v8yFNCxVEf","lH1kt2ZHdk","iB08lDLhzM","rhl0JEdBKc","dmoS7WMiS3","Q6hMCIjTwP","jSjS3AkKTk","OHaBz580YD","d7vjMOHaBz",
-"Yf2Ecv1Hln","JKWYRQYxC0","l83UdDQimp","pvgjSDQimp","jiVBP618Di","azIWpWreyP","Zv7z0LewvM","uPX7GhSSvQ","JRJQBGXdoH","M6qcGMGlTF",
-"6AFT0pvgjS","VLTy6U3yw5","TCgPpKZamH","Cp3mZ1LB1L","yofH3RkQke","0Wr5yTCgPp","Mkgy8atef2","jtn0X8FmFH","EdBKcReKEW","ZUnqtZhwG1",
-"rKDLJDQimp","uZPqgD6rBy","3otm6tjQxs","QworuJ2mQi","wDajXSbRYy","blLA9v8yFN","lj07QRBhp0","lm0pDl83Ud","I7p2a5Mg9r","7fKYUguMb8",
-"DcpWBQ6Lix","OUYuFThjNn","8TxD7M6qcG","ZJTXHQ6hMC","WaWsv5Namm","1v5hH4QMc9","mX2GEhe9IA","dmoS7taOXK","Vprf2FxX9q","hSSvQO3iyQ",
-"CK5W76AFT0","FNYIM0MR5X","oVQp6uvf7A","Yw2oUI7p2a","FNYIMFFDui","45cIHTwano","ECMvUhYBCK","d85a9mz8gx","8FmFHjfREu","mX2GEuAWyp",
-"b29RJU3yw5","ogLgcQbxXc","i7WMQQ6Lix","Ta8f6BbwgA","FNYIMRpBQm","dmoS7azIWp","W7cTsSWfou","2NslmtAOsr","24ARFv8yFN","Q6hMCFNYIM",
-"SWfouhUTw7","0KyfsuN6r3","IRh48v2eC3","FFDuiUl4a1","Dz1R3Chuy3","WmadAwDajX","oGu6x8U2nU","sx5Gl5Mg9r","piJSk24ARF","tjQxsQWxoT",
-"EdBKco8Uyd","2Yz7EqQxHP","RzaZA7fsYM","lj07QBCxeC","VIlwPs7Mxk","07n1cUvlv4","dmoS7prNT6","yofH3OUYuF","qaofNKsjRK","NcICA2ZHdk",
-"KASQ89GXkX","jSjS35iGN5","aFFssTCgPp","fmIK1piJSk","W7cTsfmIK1","8RCUA3otm6","JJs5mjS1aj","iqv4khe9IA","CNHmv5nmWv","lH1ktXyPZN",
-"jfREuoQ87r","CqqaDRmDcr","8cVD3ZhwG1","SjskQUmaEv","zQt6QblLA9","uAWypKsjRK","JKWYR45cIH","BpYhVNo0Qb","pT8wukZANm","hSSvQ1v5hH",
-"xciqpYw2oU","WaWsv55rfB","5iGN5s7Mxk","5IhmG0h1b1","In3NSMaJQs","suY4xMmKGJ","yofH3Qworu","Oz8yZ55rfB","9y4lwCNHmv","Ss0Zu64s8N",
-"kB5nP5IhmG","lViBv7Ow5C","pv0i7v8yFN","Gv3FqYOfrY","jeskSkZANm","8U2nUyToGW","0BmCyY1mC0","0PktIFNYIM","BbwgANcICA","ni2v1xXTI4",
-"x3LDesuY4x","zHF1qFGzgp","HfyNQG1RhS","NAFuw2TRI7","IjTwPBpYhV","2DREsY1mC0","FwEJznlaBy","qaofNni2v1","5iGN5rhl0J","faHir2hEEU",
-"oQ87rtjQxs","oVQp68xEKz","tAOsrokgRi","lweGym4bxU","ydG8Uk85Ae","yluBxbrhlQ","MK07Ygf8rI","n1pmOulk41","4dEz6Q6Lix","8RCUADz1R3",
-"LDk6f580YD","2TRI7NcICA","uZPqgyToGW","Q6LixLewvM","v8yFNNhXdu","G1RhSChuy3","lj07QfaHir","RsQUqAgJHQ","a00b50Wr5y","LbRTH1LB1L",
-"uN6r3Ul4a1","Q6LixW3VFH","Dz1R3EoToP","5ZaEzsqVrf","FPfSEciuWz","FwEJzM3zXL","P6bcgvLsmS","StlDJEOE1o","Uvlv4ZuDtD","uN6r3M3zXL",
-"4W0TlAmdQd","G1RhSuN6r3","lweGyFLsph","GSQwjFLsph","aDGtSBFkb8","lsQGoFGzgp","POUYSnlaBy","5nmWvwiHrZ","JIqXioQ87r","WPmlxxReec",
-"pv0i7lH1kt","pAhR1lH1kt","QbxXcwDajX","sx5Gliqv4k","5Namm9eoRc","QbxXcJIqXi","fLNg8TCgPp","KsjRK2Yz7E","lpF6W3weIF","tAOsrfqypy",
-"n1pmOAkKTk","2DREs8U2nU","dhSuH07n1c","CqqaD0YAGH","KsjRKv1Hln","OxWIHhe9IA","EOE1oJ2mQi","Y1mC0JkzUn","lweGy1j5L8","POUYSpmeCd",
-"qaofNKr8ys","RsQUqVIlwP","Mkgy8Vprf2","kB5nPgdQsS","CdyBVy94nw","cmXIX2ZHdk","gf8rInnP8o","yofH3okgRi","ydG8UcQOnv","iB08lZzJHW",
-"NhXduHlUbF","n8pJ9Mm8si","I7p2aFhtgl","XflUq2ZHdk","Cp3mZYf2Ec","MmKGJIjTwP","MGlTFy94nw","QworuLewvM","soy9t0h1b1","FxX9qI7p2a",
-"uTacxd85a9","8RCUAb29RJ","iKqhrKr8ys","VjCZqNcICA","U3yw5BbwgA","O3iyQyToGW","d85a9fFDrJ","5Mg9rQ6Lix","kB5nPwDajX","U3yw5S77LH",
-"lXFOBQClRL","ulk41KsjRK","oQ87r07n1c","hi5X7D6rBy","dpe1vW7cTs","he9IACIShG","yluBxhUTw7","5IhmGJIqXi","s4786dhSuH","0h1b1XyPZN",
-"cL0aEjfREu","ZuDtDW3VFH","iB08l7fKYU","zFgtBYw2oU","8TxD7faHir","pT8wutaOXK","RxrsmHlUbF","7fKYUAXpwE","GrDg7GrDg7","9GXkXdQ586",
-"Q6LixCfgr3","NOHszVLTy6","hi5X75Mg9r","ciuWzk85Ae","Ss0ZuFLsph","KZamHtjQxs","HlUbFkZANm","s7Mxkaez9y","580YDiB08l","HfyNQlj07Q",
-"7hyVvuupzk","jiVBPhE1Ql","0PktIJKWYR","XflUqThjNn","0PktIdhSuH","lkMUAo8Uyd","AgJHQCp3mZ","QnJ1SB3qem","ZzJHWZzJHW","l83UdPYBf4",
-"i7WMQ9rlg9","NOHszwiHrZ","uN6r3EOE1o","lm0pD5ZaEz","WaWsvF6PT2","HfyNQsx5Gl","i3pydbgJAz","uN6r3s7Mxk","Yw2oU9XyT9","h1zcH0ao3l",
-"ulk41aL6AJ","soy9t55rfB","55rfBdhSuH","fcJOyb29RJ","NhXduEoToP","8RCUAMaJQs","uZPqgRkQke","pvgjSDz1R3","lH1kttl72W","5iGN5CdyBV",
-"t59lRX6Pin","9iGoTQ6Lix","8RCUAfLNg8","kZANm1v5hH","zqH0WydG8U","VBjhzXflUq","cQOnvblLA9","VBjhzFnPFB","RpBQmiB08l","xciqpHfyNQ",
-"nnP8ozFgtB","Vprf2OUqFM","oGu6xsqVrf","2TRI7xReec","7Ow5CpmeCd","3otm6yvOMI","EdBKcmz8gx","Waim6MGlTF","29QAzuJScX","BpYhVXflUq",
-"atef2CK5W7","F6PT2HRxd8","v2eC3P6bcg","8U2nUSbRYy","pv0i7fcwDa","lm0pD5drc6","3weIF29QAz","DcpWB2Yz7E","bZLvSYjB9t","dQ586fLNg8",
-"BGaQYQnJ1S","2NslmdmoS7","yvOMI9y4lw","brhlQWaim6","FcWrWzHF1q","4QMc93otm6","zY1GYuPX7G","RBhp0i3pyd","VjCZqlj07Q","14FLRhUTw7",
-"FjHXRQChxs","sx5GlHzZT8","VerEAVerEA","zQt6QjfREu","IjTwPECMvU","CK5W72Nslm","uN6r3MojnP","tlILtCK5W7","580YDG1RhS","vLsmSWMiS3",
-"fcwDaEdBKc","brhlQk85Ae","B3qemdpe1v","Y1mC0Zv7z0","1v5hHNo0Qb","StlDJo8Uyd","8FmFHRBhp0","MmsIot59lR","5drc6Mm8si","oVQp6zY1GY",
-"SbRYyNAFuw","xReecOUqFM","FnPFBVerEA","Oz8yZ9eoRc","uLtKsvLsmS","MojnP1LB1L","PYBf4uvf7A","5VZjSS2Dfu","QClRLRmDcr","SWfouWreyP",
-"AIYUu7fKYU","vOqCEfaHir","X6Pinhi5X7","FVMxo5drc6","WPmlxhE1Ql","OUqFMlXFOB","BGaQYatef2","S77LHFFDui","5Drn0fFDrJ","JJs5m9y4lw",
-"faHirWreyP","9rlg9QssNC","pWiOsAgJHQ","VIlwPd85a9","FLsphgIYvE","I7p2ahE1Ql","Yw2oUmz8gx","MezSWru4UG","HzZT8Zv7z0","M6qcGlweGy",
-"jfREu0Wr5y","WMiS3C2Irc","fcJOyG1RhS","jeskS0YAGH","uJScXVLTy6","cShY28TxD7","sqVrfReKEW","8RCUAYh1hF","FwEJzOxWIH","EoToPjzUqR",
-"Cfgr3DcpWB","k85AegtCA5","y94nw14FLR","D6rByyluBx","HRxd8gtCA5","Waim6s4786","WreyPyEfy9","64s8N5drc6","Cfgr3lkMUA","NcICAk85Ae",
-"Qworux3LDe","9GXkXRzaZA","x3LDeKZamH","PYBf4OUYuF","4QMc9NcICA","FxX9qzFgtB","dQ586tvdkD","ReKEW8RCUA","jzUqRFcWrW","i3pydBbwgA",
-"yToGWLewvM","Vprf2CIShG","JRJQBHlUbF","OUYuFSmGzv","AIYUuUl4a1","VjCZqv1Hln","5Drn0RzaZA","prNT6M3zXL","IjTwPfmIK1","6q6L9Gv3Fq",
-"9XyT9a00b5","cL0aEblLA9","HP433m4bxU","KZamHNAFuw","PYBf4lkMUA","0KyfsCfgr3","9XyT9faHir","lsQGoiqv4k","WMiS35Drn0","FhtglsuY4x",
-"S77LHWMiS3","tl72W5Mg9r","WaWsvru4UG","M3zXLcShY2","uJScXhi5X7","prNT6GXdoH","uupzkGXdoH","Mkgy8BGaQY","FLsphulk41","FFDuidQ586",
-"QworuuTacx","0YAGHSWfou","uPX7G2DREs","QClRLZv7z0","v2eC35iGN5","VBjhziKqhr","TXQ0ZZv7z0","h1zcHUvlv4","QClRLfcJOy","0PktI0Wr5y",
-"MGlTF7lUXZ","DLhzMCp3mZ","aL6AJJRJQB","45cIH5Drn0","jfREuix74r","9iGoTStlDJ","jS1ajzFgtB","ciuWzO3iyQ","55rfB7Ow5C","5drc6Twano",
-"fmIK1vOqCE","lpF6WVBjhz","AXpwEs4786","Y1mC0hSSvQ","RACuj4QMc9","oGu6x6AFT0","MojnPRsQUq","pAhR1mX2GE","cL0aEuJScX","Waim6guMb8",
-"RkQkei3pyd","Y1mC0uvf7A","fLNg89iGoT","QClRLRACuj","pAhR1SWfou","Ul4a1pmeCd","HRxd8lH1kt","gjUTuprNT6","5drc6atef2","MojnPeuZA5",
-"Ss0ZucL0aE","24ARFxXTI4","UlU3Md7vjM","RkQkeZJTXH","MojnPRmDcr","PYBf4QnJ1S","WMiS3Y1mC0","aFFssuPX7G","d7vjMHRxd8","8xEKzx3LDe",
-"hYBCKRACuj","K20wKyvOMI","0BmCyydG8U","Oz8yZ4W0Tl","S77LHDz1R3","cL0aEVerEA","QbxXcgdQsS","8U2nU9rlg9","Q6LixU3yw5","h1zcHuJScX",
-"gjUTukZANm","Q6Lix2TRI7","QWxoTaDGtS","hSSvQatef2","uJScX16lHc","0YAGHRkQke","CqqaDJIqXi","iwzGkGXdoH","DcpWBAOgEe","WmadANhXdu",
-"fmIK1gtCA5","VBjhzZuDtD","o8UydMkgy8","5drc6faHir","P6bcgY1mC0","CIShGcShY2","AgJHQrz7Ut","Yh1hFWaim6","t59lR5nmWv","NAFuw5iGN5",
-"SWfou5iGN5","K20wKG1RhS","iKqhr3otm6","BpYhVJkzUn","6q6L9i7WMQ","ThjNnsoy9t","RACujlweGy","5VZjSFPfSE","brhlQlXFOB","ZUnqtVNCPd",
-"Cp3mZ1j5L8","v2eC39y4lw","okgRiVNCPd","yEfy9Ul4a1","IRh48CK5W7","ksJbytuDyS","lkMUAm4bxU","VLTy6FLsph","DLhzMEdBKc","pFrrl6AFT0",
-"S2Dfu14FLR","uupzklj07Q","AIYUuksJby","lXFOBRBhp0","ZJTXHOUqFM","5drc6QYxC0","x3LDeOUYuF","v1Hlnsoy9t","EoToP5nmWv","wDajXBFkb8",
-"lH1ktIjTwP","zmLYDvOqCE","55rfBWaWsv","jeskSTwano","jzUqR9eoRc","5IhmGPb1pa","aDGtSOHaBz","tAOsrMGlTF","cQOnv4QMc9","8FmFHl83Ud",
-"faHir9y4lw","1LB1L3weIF","iwzGkI7p2a","uTacxJIqXi","jiVBPChuy3","ZUnqtfqypy","Qworu0MR5X","dpe1vZJTXH","0Kyfsaez9y","wDajX9eoRc",
-"zFgtBaDGtS","LewvMXyPZN","d85a9lweGy","ThjNnMkgy8","k85Aefqypy","EOE1oCxVEf","0BmCyFLsph","OHaBzGSQwj","FLsphSmGzv","VIlwPjtn0X",
-"0ao3lsoy9t","sqVrfy94nw","DQimpKsjRK","piJSksuY4x","jSjS3SjskQ","yluBxpv0i7","O3iyQReKEW","fcJOyy94nw","SjskQJkzUn","JIqXitaOXK",
-"uJScX0YAGH","djsrv7fKYU","bZLvSMaJQs","PYBf4soy9t","jiVBPNcICA","5Mg9rQbxXc","fcwDaMezSW","SWfoulj07Q","uvf7AuAWyp","5nmWv9y4lw",
-"FhtglbrhlQ","I7p2awDajX","hi5X7618Di","i7WMQMGlTF","AmdQd5Mg9r","HzZT8lXFOB","HlUbFrhl0J","CNHmvFxX9q","zz4ZUAOgEe","8TxD7OUYuF",
-"J2mQi24ARF","CIShGdpe1v","jtn0XMkgy8","ix74rK4GS8","pFrrl2Yz7E","16lHcBbwgA","iKqhrPOUYS","lkMUARkQke","ix74rlweGy","v8yFNkZANm",
-"LbRTHzY1GY","BbwgAX6Pin","brhlQuPX7G","ni2v1uTacx","TCgPpxciqp","rhl0JJ2mQi","IjTwPMmKGJ","Yf2EcblLA9","JkzUnUlU3M","JIqXio8Uyd",
-"Q6Lix8RCUA","mX2GE2Nslm","zQt6Q0MR5X","RxrsmTa8f6","B3qemYf2Ec","iqv4kRsQUq","i3pydyEfy9","J2mQiEdBKc","1v5hHwDajX","RkQkedjsrv",
-"MK07YgIYvE","jtn0Xuvf7A","M3zXL7ku1p","OxWIHK20wK","MezSWbrhlQ","pAhR1qUJMd","faHirRpBQm","JXljWvOqCE","D6rByCK5W7","TCgPpJXljW",
-"vkCHHHRxd8","XflUqVBjhz","kB5nPEoToP","Nxx9Vh1zcH","Gv3FqCqqaD","guMb8In3NS","Y1mC0VIlwP","POUYSKZamH","i7WMQiwzGk","W7cTsNo0Qb",
-"uZPqglweGy","D6rByQWxoT","fcwDauupzk","djsrvHfyNQ","fFDrJlj07Q","wDajXRzaZA","pvgjSdjsrv","AkKTkfmIK1","Gv3Fqpv0i7","mz8gxguMb8",
-"GWqqXjeskS","OUqFMpv0i7","qaofNxciqp","0ao3lFjHXR","okgRi7hyVv","B3qemVjCZq","wiHrZeuZA5","BGaQYIBe8k","NOHszMezSW","OxWIHaFFss",
-"xReeckB5nP","LbRTHydG8U","B3qemzQt6Q","580YDyvOMI","FPfSE2ZHdk","U3yw5QbxXc","kB5nPqQxHP","Uvlv47Ow5C","x3LDev2eC3","lViBvQnJ1S",
-"BpYhV9eoRc","RzaZA9XyT9","vOqCEuAWyp","lj07Q8FmFH","GSQwjuPX7G","JKWYRfLNg8","mz8gxt59lR","HfyNQ7ku1p","M3zXLmX2GE","s4786k85Ae",
-"1j5L824ARF","lm0pDQYxC0","lCMxyt98iW","iB08lO3iyQ","uAWypStlDJ","UlU3M2TRI7","lm0pDOHaBz","lweGypmeCd","580YDix74r","5Mg9rjeskS",
-"QClRLzQt6Q","gf8rI5ZaEz","zz4ZU5drc6","qUJMdjeskS","0h1b1lCMxy","DLhzMFwEJz","bZLvSblLA9","O3iyQWreyP","WmadAZzJHW","lsQGogIYvE",
-"ThjNn9rlg9","kZANmNAFuw","Cp3mZQClRL","MGlTF1j5L8","DQimpiKqhr","Gv3FqRxrsm","UlU3MMaJQs","yvOMIuPX7G","vkCHHvOqCE","pWiOszmLYD",
-"JIqXil83Ud","jiVBPi3pyd","DLhzMPYBf4","14FLRtAOsr","FLsph9rlg9","XyPZNmX2GE","okgRi9iGoT","X6PinRpBQm","POUYS7X3uy","DcpWBNAFuw",
-"hUTw72Nslm","VBjhzpAhR1","EoToP7lUXZ","ZzJHWYf2Ec","RBhp0Nxx9V","VjCZqcQOnv","RmDcrGv3Fq","9GXkXCfgr3","iwzGkpWiOs","9eoRc14FLR",
-"HRxd8bZLvS","Ta8f6S77LH","t59lRo8Uyd","5VZjSQ6hMC","8TxD7BCxeC","45cIH7ku1p","9GXkX9XyT9","Ta8f6d85a9","FPfSEMm8si","No0QbQYxC0",
-"FNYIMguMb8","YjB9tMaJQs","s7MxkkB5nP","XyPZNuTacx","lm0pDlsQGo","jtn0XSbRYy","AgJHQyvOMI","CNHmvB3qem","nFqikuPX7G","5VZjS1v5hH",
-"WmadAfcJOy","Y1mC0l83Ud","uLtKsSs0Zu","5Mg9r8RCUA","fFDrJgdQsS","IjTwPDQimp","SmGzvcmXIX","29QAzIjTwP","ECMvUVLTy6","uTacxFGzgp",
-"580YDXflUq","faHirlj07Q","ZuDtD4W0Tl","S77LHfFDrJ","MGlTFv8yFN","DcpWBTXQ0Z","5drc69rlg9","C2IrcJRJQB","lXFOBksJby","M3zXLNOHsz",
-"9GXkXIKxdL","ix74rjSjS3","soy9thYBCK","K20wKgjUTu","BpYhVDz1R3","ZJTXHzbIYY","LbRTHZUnqt","uoStwK4GS8","FPfSE0PktI","zQt6QHRxd8",
-"AgJHQix74r","SmGzv8hJdt","okgRiHlUbF","kZANmbrhlQ","iqv4kCIShG","Fhtglsx5Gl","QnJ1SKsjRK","SmGzviKqhr","FVMxoZ4I1v","VNCPdKASQ8",
-"pFrrlO3iyQ","29QAzK4GS8","DcpWBlj07Q","Chuy3x3LDe","gdQsSTCgPp","AXpwESbRYy","0YAGHbZLvS","Yh1hF8xEKz","lsQGoYf2Ec","OxWIHwDajX",
-"D6rByoGu6x","WaWsvIBe8k","h1zcHHlUbF","UmaEvlXFOB","QbxXcyluBx","ZhwG1Uvlv4","TCgPpEdBKc","aFFss580YD","DQimpcQOnv","lH1kt5IhmG",
-"4dEz6SjskQ","55rfBYw2oU","v8yFN2Yz7E","W3VFHRzaZA","xXTI4lkMUA","BpYhVqQxHP","kZANmzY1GY","P6bcgJkzUn","TXQ0ZRACuj","S2DfuoQ87r",
-"5VZjSUvlv4","5ZaEzuLtKs","zbIYYMojnP","RxrsmW3VFH","O3iyQWPmlx","vLsmSlm0pD","8hJdtjSjS3","WDVWJiB08l","IBe8kHlUbF","ru4UGIKxdL",
-"vkCHHL7cGc","6AFT0KASQ8","DG4sT2DREs","2NslmCIShG","lkMUA4dEz6","i3pyd0PktI","ZhwG1bgJAz","CNHmv14FLR","SmGzv0Wr5y","x3LDe9GXkX",
-"DLhzM1LB1L","In3NSMmKGJ","GXdoH8TxD7","JRJQBZ4I1v","EoToPJKWYR","pvgjSxciqp","ix74rcQOnv","QYxC0JIqXi","n1pmOcL0aE","K20wKWmadA",
-"M6qcGCIShG","piJSkQbxXc","9XyT9EdBKc","WreyPuTacx","Ss0ZufaHir","CK5W71j5L8","wiHrZ2Yz7E","Zv7z0ZzJHW","pvgjSZuDtD","azIWpNxx9V",
-"GWqqXLewvM","BFkb8JkzUn","WPmlx5Drn0","BpYhVo8Uyd","lsQGoYw2oU","1j5L848cHL","7fsYMHP433","pmeCdd85a9","JXljWn8pJ9","KASQ8PYBf4",
-"dmoS7Q6hMC","64s8NK4GS8","suY4xfaHir","16lHcEoToP","lj07QkZANm","9iGoTksJby","8hJdt6q6L9","ksJbyDG4sT","qQxHPCfgr3","SWfouS77LH",
-"QnJ1SHP433","ru4UGL7cGc","yToGWNAFuw","d7vjM7fsYM","QClRLFFDui","d85a92DREs","8TxD7F6PT2","EOE1opWiOs","J2mQil83Ud","WreyPL7cGc",
-"lpF6W0ao3l","OUqFMYf2Ec","uoStws4786","NcICAOUqFM","PYBf4jS1aj","WaWsvlpF6W","OHaBzIKxdL","lH1kt2Nslm","RACujPOUYS","WmadAvOqCE",
-"wiHrZD6rBy","vLsmS0PktI","ECMvUBpYhV","i7WMQTXQ0Z","GXdoHIn3NS","5ZaEz5Mg9r","jiVBPlXFOB","FFDuidjsrv","FxX9qblLA9","Dz1R3VjCZq",
-"8FmFHPOUYS","HzZT8iqv4k","DLhzMM3zXL","uN6r3fLNg8","NOHszulk41","JIqXifFDrJ","48cHLFhtgl","zmLYDFNYIM","7fKYUOz8yZ","AOgEeogLgc",
-"piJSkh1zcH","WreyPDcpWB","L7cGcZv7z0","JJs5mxReec","6AFT0Z4I1v","s478629QAz","zFgtBn1pmO","nFqikru4UG","8FmFHsqVrf","Uvlv4Dz1R3",
-"NhXduuJScX","uvf7As93Ml","Mm8siPb1pa","bgJAz8U2nU","zz4ZUZUnqt","SmGzv5IhmG","pWiOslkMUA","nlaByi7WMQ","HfyNQZv7z0","v1HlnYf2Ec",
-"CIShGW7cTs","45cIHMK07Y","xciqpPOUYS","zbIYYReKEW","tlILtfcwDa","GrDg7Cp3mZ","RmDcrpWiOs","WreyPlH1kt","nFqikfmIK1","U3yw5lkMUA",
-"FnPFBpAhR1","J2mQiMaJQs","fcJOyjeskS","CNHmvzQt6Q","yEfy9sqVrf","No0QbaFFss","S2Dfu5nmWv","MGlTFJRJQB","s93MlNOHsz","ulk41LewvM",
-"sx5GlO3iyQ","yluBxAXpwE","O3iyQzHF1q","KASQ88TxD7","uTacxxReec","uJScXo8Uyd","Q6LixuTacx","v1Hln9y4lw","fLNg85IhmG","pAhR1d85a9",
-"t98iWl83Ud","ZJTXHtlILt","DLhzMGXdoH","jiVBP3weIF","45cIHDQimp","618DiWaim6","2DREsAXpwE","ni2v1b29RJ","VBjhzLbRTH","kB5nPtAOsr",
-"TwanoDLhzM","IKxdLHP433","nFqikcQOnv","7hyVvECMvU","JXljWzz4ZU","X6PinIRh48","hSSvQOUYuF","45cIHfmIK1","lsQGob29RJ","C2Ircru4UG",
-"jtn0Xjtn0X","qQxHPzmLYD","M6qcGhi5X7","Dz1R355rfB","QChxsoQ87r","OHaBzRpBQm","ZUnqtU3yw5","fFDrJ4W0Tl","BCxeC5nmWv","WPmlxJRJQB",
-"dQ586W7cTs","HP433Yh1hF","07n1ci3pyd","ru4UGCK5W7","lm0pDvLsmS","0PktINhXdu","Qworuaez9y","Zv7z05nmWv","hi5X7MaJQs","vkCHH4QMc9",
-"X6PinLDk6f","RkQkeFPfSE","9XyT95Mg9r","9eoRcpiJSk","9eoRc0MR5X","ZUnqtprNT6","5Namm2TRI7","Ta8f6yEfy9","Ul4a1AXpwE","W3VFH580YD",
-"5ZaEzwiHrZ","uoStwbrhlQ","iqv4kRBhp0","t98iWulk41","vOqCEtvdkD","zqH0WBFkb8","Gv3Fqjtn0X","LDk6fS2Dfu","OUqFMCNHmv","CqqaDU3yw5",
-"In3NSuupzk","okgRiLewvM","soy9tQnJ1S","lsQGoy94nw","8hJdtdmoS7","BCxeChi5X7","fmIK1oVQp6","IjTwPyToGW","FGzgpMmKGJ","ydG8UfcJOy",
-"zz4ZUF6PT2","F6PT2QssNC","taOXK9XyT9","lsQGo4W0Tl","rKDLJhe9IA","ZzJHWOUqFM","HlUbF1v5hH","djsrvfqypy","uQIcz7fKYU","7hyVvFwEJz",
-"SjskQ6q6L9","RBhp04dEz6","Mm8siMGlTF","NOHszzHF1q","mz8gxQClRL","BCxeCPb1pa","YOfrYni2v1","LbRTHNo0Qb","8cVD3rhl0J","B3qemdmoS7",
-"gtCA5P6bcg","2Yz7EydG8U","s4786uPX7G","0ao3lWMiS3","jS1ajWreyP","S77LHPOUYS","k85AeIjTwP","AkKTkHzZT8","jSjS3Nxx9V","tl72WFGzgp",
-"qUJMd7hyVv","HzZT8VBjhz","brhlQGrDg7","iB08ln1pmO","W7cTss93Ml","NcICAnFqik","1LB1LJkzUn","4dEz6BCxeC","pT8wud7vjM","wiHrZHlUbF",
-"pFrrll83Ud","JIqXiAIYUu","F6PT2FxX9q","ulk4124ARF","sx5GluZPqg","Y1mC0dQ586","lCMxyatef2","VerEARxrsm","Nxx9VAXpwE","yofH3QWxoT",
-"yluBxcL0aE","qUJMdB3qem","suY4xTCgPp","7ku1ppAhR1","No0QbKASQ8","Ta8f6lpF6W","7hyVvmX2GE","Mkgy8ksJby","yofH3zmLYD","55rfBMmKGJ",
-"pFrrlJJs5m","CqqaD14FLR","UmaEvRsQUq","07n1cjzUqR","K4GS8OxWIH","0Wr5yTXQ0Z","5Mg9rydG8U","IjTwPuPX7G","zz4ZUFVMxo","SWfouhSSvQ",
-"VLTy6uQIcz","U3yw54W0Tl","8FmFHvOqCE","AIYUu5Drn0","gjUTuMmsIo","Dz1R3dpe1v","lCMxyFFDui","mz8gxn8pJ9","QChxstlILt","8U2nUTa8f6",
-"zHF1qjSjS3","ThjNngjUTu","jiVBPDLhzM","QYxC064s8N","9GXkXeuZA5","RxrsmMmsIo","iB08l7X3uy","Kr8ysDz1R3","SWfouKr8ys","1LB1LIRh48",
-"pv0i7WDVWJ","OUYuFRmDcr","pT8wusoy9t","uZPqgiB08l","AXpwEFxX9q","AOgEe9y4lw","dpe1vUvlv4","WPmlxLewvM","48cHLX6Pin","2Yz7EdQ586",
-"gf8rIReKEW","0MR5XThjNn","zHF1qru4UG","rKDLJBGaQY","Mkgy816lHc","0Kyfs6AFT0","3otm6mX2GE","64s8NuoStw","gIYvEkB5nP","xciqpFxX9q",
-"EoToPW3VFH","suY4xpmeCd","ZuDtDaez9y","FjHXRFcWrW","9y4lwo8Uyd","n1pmOwDajX","n8pJ9AmdQd","qQxHP5nmWv","KZamHk85Ae","EdBKci3pyd",
-"yToGWRBhp0","YOfrYt98iW","jS1ajuN6r3","vOqCEzY1GY","lViBvHlUbF","aDGtSBpYhV","CqqaDfFDrJ","UmaEviqv4k","CqqaDJKWYR","pFrrluupzk",
-"GSQwjv2eC3","RzaZAL7cGc","O3iyQmz8gx","JJs5mgtCA5","MmsIoblLA9","VerEA8TxD7","FVMxoJJs5m","CIShGHzZT8","5Drn0FnPFB","MK07YJJs5m",
-"atef2sqVrf","ECMvUcShY2","sqVrfG1RhS","7X3uyWaWsv","VNCPd7Ow5C","Nxx9V4dEz6","Y1mC0FFDui","TwanobZLvS","LbRTHgdQsS","guMb8GSQwj",
-"WMiS3K20wK","mz8gxRACuj","J2mQiQClRL","sx5GlLbRTH","8cVD3VNCPd","zz4ZUpvgjS","h1zcHZUnqt","2hEEUDLhzM","uN6r3lj07Q","Q6Lixv1Hln",
-"i7WMQfaHir","BFkb8F6PT2","Zv7z0EoToP","cL0aEpFrrl","8TxD70YAGH","BCxeC5drc6","uJScXJRJQB","MGlTFYjB9t","uvf7AQssNC","IBe8kciuWz",
-"ksJbyAXpwE","s4786ZuDtD","y94nwzmLYD","8hJdtuAWyp","SjskQ55rfB","yEfy9gjUTu","y94nwGWqqX","CdyBVFLsph","xXTI4HzZT8","0ao3lRkQke",
-"AgJHQ0PktI","VNCPdGWqqX","pv0i75Drn0","0ao3l29QAz","JIqXigjUTu","iKqhrOUYuF","YjB9t5Mg9r","7ku1pChuy3","5drc6jeskS","jtn0XXyPZN",
-"ogLgcBFkb8","xReecX6Pin","guMb88U2nU","zQt6QCp3mZ","yofH3DcpWB","bZLvSydG8U","8xEKzlm0pD","Oz8yZeuZA5","ThjNnpFrrl","MaJQsvLsmS",
-"b29RJLDk6f","oGu6xJIqXi","ksJbytvdkD","No0Qbni2v1","hSSvQPOUYS","Waim6AmdQd","JXljWlXFOB","ydG8UCdyBV","RBhp0J2mQi","zY1GY5drc6",
-"YOfrYjfREu","zHF1qdhSuH","Waim6SbRYy","1j5L80Kyfs","0Wr5yn8pJ9","FVMxonlaBy","lkMUAuQIcz","HP433LbRTH","VLTy67fsYM","VIlwPvOqCE",
-"618DiAOgEe","fcJOy45cIH","Y1mC0Cfgr3","C2IrcAXpwE","2TRI7JXljW","0KyfsNhXdu","ydG8UzbIYY","JRJQBU3yw5","BCxeCNxx9V","StlDJUmaEv",
-"QClRLlm0pD","lsQGo0MR5X","s93MlpAhR1","LewvMBbwgA","t98iWi3pyd","5Drn0QnJ1S","Chuy314FLR","ZhwG1WDVWJ","uvf7AVprf2","cShY20Kyfs",
-"pmeCdUmaEv","AkKTk0Kyfs","oGu6xZzJHW","xXTI40PktI","F6PT2Z4I1v","zFgtBBCxeC","uAWypzY1GY","RpBQm1LB1L","jS1ajFVMxo","tjQxsSWfou",
-"B3qemt59lR","Oz8yZUmaEv","8U2nUlXFOB","CIShGqaofN","hYBCKxReec","9iGoTxciqp","IBe8kVIlwP","Ul4a17Ow5C","5IhmG2Yz7E","F6PT2OHaBz",
-"ReKEWe6e4z","fcwDad7vjM","M3zXLOHaBz","1v5hHatef2","VerEAru4UG","uLtKsdQ586","iqv4km4bxU","dhSuHbZLvS","ciuWzXflUq","FGzgp8U2nU",
-"YjB9tCIShG","Dz1R39XyT9","zmLYDv1Hln","Yw2oUgIYvE","uAWypiB08l","blLA99GXkX","7fsYMmz8gx","5NammNhXdu","KASQ8cShY2","AkKTkNxx9V",
-"BpYhV5ZaEz","s4786iqv4k","Mkgy8PYBf4","B3qemfqypy","Q6hMCFwEJz","zz4ZUHP433","NhXduFxX9q","rz7Ut7hyVv","WmadAQbxXc","uAWypatef2",
-"55rfBpWiOs","ZUnqtCxVEf","fcJOyZJTXH","jfREu2DREs","JIqXibrhlQ","o8Uyd5VZjS","pT8wuhYBCK","618DiGWqqX","8xEKz9GXkX","L7cGcChuy3",
-"zz4ZUlViBv","Chuy3P6bcg","FPfSEZUnqt","k85Ae55rfB","HlUbFlsQGo","MGlTFPb1pa","FjHXRsuY4x","TCgPpFNYIM","OHaBzOUYuF","lH1kts7Mxk",
-"EoToP2Nslm","45cIHgtCA5","cShY245cIH","6q6L9WreyP","EOE1oo8Uyd","cmXIXn1pmO","ECMvUjfREu","d85a9qQxHP","S2DfupT8wu","WmadALewvM",
-"9eoRc0YAGH","29QAz5drc6","kB5nPpmeCd","dmoS7F6PT2","Mkgy8FGzgp","Q6LixyToGW","7fKYUv1Hln","6q6L9SbRYy","fmIK1ksJby","rz7UtNOHsz",
-"9y4lwHzZT8","HlUbFdhSuH","wiHrZblLA9","5NammEdBKc","mX2GENhXdu","n8pJ9uAWyp","LDk6f5Namm","ni2v1prNT6","M3zXLtl72W","ni2v1QWxoT",
-"5IhmGXyPZN","dmoS7VerEA","hi5X7HP433","0BmCyThjNn","QYxC0QbxXc","AOgEe5IhmG","MK07YCdyBV","FcWrWtuDyS","s7MxkHzZT8","O3iyQ4QMc9",
-"55rfBe6e4z","X6Pin6q6L9","DG4sTkZANm","bgJAztlILt","i3pydBpYhV","G1RhSrhl0J","a00b5AkKTk","MezSWHP433","RACuj45cIH","i7WMQWmadA",
-"BGaQYiKqhr","soy9tMGlTF","FwEJzOUYuF","FwEJzuQIcz","MGlTFReKEW","5Drn0ZzJHW","tl72WZ4I1v","gIYvE0h1b1","Y1mC09rlg9","ZuDtDIKxdL",
-"618Diix74r","RmDcrtlILt","9rlg9LewvM","JIqXi7hyVv","JIqXifcwDa","Z4I1va00b5","AXpwE7fsYM","jS1ajmz8gx","6AFT03otm6","e6e4zRxrsm",
-"soy9tt98iW","RsQUqNOHsz","t59lRiB08l","0h1b19XyT9","iwzGkHRxd8","s4786G1RhS","IKxdLIjTwP","t59lRjfREu","iKqhr1v5hH","qQxHPAgJHQ",
-"POUYSwiHrZ","7fsYMJRJQB","SmGzvQbxXc","4dEz6MmKGJ","fmIK11j5L8","MaJQspmeCd","k85AeuQIcz","kZANmNOHsz","J2mQim4bxU","48cHLiKqhr",
-"WmadARkQke","k85Aen8pJ9","i3pydQbxXc","0MR5XIKxdL","zY1GYVprf2","faHirHzZT8","JXljWlweGy","KASQ8SmGzv","1j5L8AkKTk","G1RhSDcpWB",
-"0Wr5yiKqhr","Gv3Fq0YAGH","ZhwG13weIF","8xEKza00b5","48cHLZUnqt","0KyfsZJTXH","zFgtBZhwG1","5nmWvrhl0J","16lHcXflUq","iKqhrFLsph",
-"zz4ZUTCgPp","8TxD7iwzGk","DQimpRACuj","Nxx9Vjtn0X","Y1mC0Ta8f6","YOfrYUmaEv","0BmCyulk41","yvOMIS2Dfu","tAOsrVIlwP","gIYvEHP433",
-"VerEAnFqik","gf8rIKZamH","brhlQQClRL","s4786tuDyS","2Nslm2DREs","8U2nUhE1Ql","8xEKzsx5Gl","AXpwEUl4a1","5ZaEzYw2oU","dhSuH2Nslm",
-"QWxoTAXpwE","0MR5XMezSW","pT8wuJKWYR","2hEEU55rfB","MK07YVprf2","NcICAjS1aj","ReKEWDz1R3","RzaZAyluBx","FNYIMfLNg8","v1Hln9rlg9",
-"HfyNQbrhlQ","uPX7Gd7vjM","7fsYMgdQsS","n1pmOdjsrv","29QAzi3pyd","JkzUnCp3mZ","suY4xQChxs","lH1ktLbRTH","faHirJkzUn","lViBvTCgPp",
-"pvgjStuDyS","4QMc9iwzGk","J2mQikZANm","2TRI7FPfSE","4W0TllsQGo","dmoS7fcJOy","tAOsrGXdoH","lCMxyd7vjM","AXpwESs0Zu","J2mQilCMxy",
-"Yh1hFtvdkD","dpe1vQ6Lix","GXdoHjSjS3","okgRiqUJMd","wDajX5VZjS","yToGWqUJMd","HzZT8WmadA","GXdoHh1zcH","UmaEvAkKTk","RzaZANo0Qb",
-"x3LDepWiOs","5IhmGQworu","fFDrJpFrrl","d7vjM29QAz","8TxD7L7cGc","blLA97X3uy","QssNCl83Ud","AIYUuStlDJ","zQt6QdhSuH","NhXduCK5W7",
-"NOHszb29RJ","4dEz6Oz8yZ","oGu6xVLTy6","okgRiAmdQd","FjHXRWreyP","uupzk8hJdt","Q6LixFPfSE","pWiOsksJby","CdyBV2Nslm","HRxd8hSSvQ",
-"yluBxru4UG","fFDrJjtn0X","Ta8f6BCxeC","Dz1R3YjB9t","J2mQiVNCPd","lweGyJKWYR","gf8rIZhwG1","LDk6fuJScX","b29RJvLsmS","wiHrZPYBf4",
-"8U2nU2hEEU","b29RJVIlwP","K4GS8Vprf2","QYxC0uJScX","VNCPdhi5X7","aL6AJAmdQd","2Yz7Ea00b5","618Dis4786","07n1cMaJQs","ZUnqt7lUXZ",
-"FFDuiVerEA","nnP8oCdyBV","Nxx9VZ4I1v","0Wr5yi3pyd","29QAzHRxd8","1LB1LjSjS3","5VZjSZuDtD","jS1ajxReec","5VZjSm4bxU","FnPFBFwEJz",
-"v1HlnvLsmS","IKxdLcShY2","GWqqXdmoS7","y94nwfaHir","cQOnvfcwDa","Cfgr3ni2v1","O3iyQfLNg8","pmeCdSjskQ","RsQUquPX7G","Cp3mZFNYIM",
-"Q6hMCYjB9t","Mm8siQssNC","M6qcGVIlwP","v1HlnciuWz","Nxx9Vix74r","lCMxyzz4ZU","5nmWvfFDrJ","0ao3lS2Dfu","pWiOsOUYuF","QworuaDGtS",
-"0PktIh1zcH","wiHrZDQimp","JRJQB0YAGH","GrDg7gdQsS","BCxeCX6Pin","BbwgAxXTI4","Mm8siuZPqg","FcWrWWmadA","0h1b1hE1Ql","IKxdLCdyBV",
-"Yf2EcReKEW","0BmCygIYvE","RkQkeDLhzM","55rfBprNT6","lweGypWiOs","Twano5nmWv","1LB1L9eoRc","7fsYMIKxdL","RpBQmxXTI4","HfyNQIjTwP",
-"618Di3weIF","jfREuFhtgl","F6PT2zz4ZU","xciqpSjskQ","fcwDaCqqaD","fLNg8F6PT2","Zv7z0QbxXc","Kr8ysBGaQY","8cVD3vLsmS","YOfrYnFqik",
-"8hJdtjfREu","ECMvUVNCPd","FPfSE14FLR","0BmCyuLtKs","GSQwj0ao3l","cQOnvs7Mxk","uN6r3MmsIo","Pb1paFNYIM","b29RJKZamH","n1pmOk85Ae",
-"Pb1paM3zXL","CqqaDzY1GY","lXFOBTCgPp","9y4lwazIWp","LewvMjiVBP","s7Mxk55rfB","8TxD7FVMxo","brhlQAkKTk","S2Dfurz7Ut","o8UydWmadA",
-"8RCUAy94nw","Mm8siWMiS3","hi5X7I7p2a","n8pJ9mz8gx","mX2GEn1pmO","wiHrZprNT6","B3qemReKEW","s4786Fhtgl","pWiOs07n1c","JXljW9eoRc",
-"In3NSFjHXR","jzUqRhSSvQ","2Yz7ENAFuw","iKqhrYjB9t","FVMxoMK07Y","AXpwE5iGN5","NcICACp3mZ","n1pmO4dEz6","Fhtglni2v1","OHaBzqQxHP",
-"pmeCdprNT6","NhXdu4QMc9","iB08lt59lR","nlaByBFkb8","kZANmOxWIH","9XyT9QWxoT","MmKGJJIqXi","sx5Gli7WMQ","NcICA7lUXZ","YOfrYcQOnv",
-"tlILtdpe1v","Mm8silj07Q","UmaEvEoToP","DcpWB0ao3l","16lHc9GXkX","fFDrJAOgEe","azIWpTa8f6","atef2MezSW","Waim6FLsph","FGzgptAOsr",
-"64s8NtlILt","Oz8yZIjTwP","iB08luupzk","YjB9tzHF1q","wDajX7ku1p","B3qem2ZHdk","rhl0J29QAz","55rfBtlILt","guMb8O3iyQ","tjQxsRsQUq",
-"9y4lwQbxXc","S77LHQ6Lix","FnPFBTa8f6","L7cGc0YAGH","WmadAd7vjM","RBhp0iqv4k","MK07YCp3mZ","sqVrfJIqXi","oQ87rjfREu","2TRI7piJSk",
-"0Wr5yyvOMI","pWiOsFNYIM","FPfSEv2eC3","jtn0XNAFuw","MojnPkB5nP","Q6LixTCgPp","bgJAzRpBQm","SWfouwiHrZ","CNHmv7X3uy","LDk6fReKEW",
-"dmoS75ZaEz","prNT6JJs5m","fLNg8Fhtgl","bZLvSo8Uyd","OUqFMfmIK1","s93MlQWxoT","5ZaEztvdkD","DQimpfFDrJ","QWxoTJRJQB","XflUqgf8rI",
-"8FmFHguMb8","lH1kt48cHL","5Mg9rhSSvQ","5Mg9rd85a9","VNCPdFjHXR","8xEKzhSSvQ","ZJTXHpiJSk","WDVWJgIYvE","uQIczuvf7A","Q6hMCDz1R3",
-"No0Qb9eoRc","ru4UGECMvU","uvf7AAXpwE","SWfouvLsmS","BbwgAGWqqX","uTacxCfgr3","AXpwEjS1aj","atef25IhmG","lkMUAnFqik","x3LDeiwzGk",
-"cQOnvMkgy8","s93Mlt98iW","29QAzGv3Fq","ThjNnMK07Y","JkzUnOxWIH","fLNg8Kr8ys","guMb8zFgtB","5iGN57fsYM","s4786JJs5m","OHaBzn8pJ9",
-"9iGoThYBCK","ZhwG1d7vjM","uN6r35ZaEz","Ss0ZuZ4I1v","v1HlnThjNn","tjQxspmeCd","l83Ud0PktI","AgJHQOHaBz","MaJQsZJTXH","iwzGkRmDcr",
-"pAhR11LB1L","HP433Mm8si","tlILt1v5hH","QssNCBGaQY","e6e4z7Ow5C","DG4sT4QMc9","29QAzCxVEf","BFkb8SmGzv","TCgPpyofH3","IBe8kRsQUq",
-"ru4UGjzUqR","s4786JkzUn","MezSWHRxd8","OxWIHWreyP","e6e4zLDk6f","tuDySIBe8k","JIqXiJRJQB","euZA5FnPFB","Ss0Zut98iW","FLsphYw2oU",
-"yvOMIl83Ud","ru4UGm4bxU","HlUbFru4UG","ydG8UtvdkD","0BmCyFhtgl","2TRI75VZjS","uAWypPb1pa","tjQxsguMb8","uQIczAXpwE","TCgPp0BmCy",
-"i3pyd07n1c","F6PT25Namm","5drc6XflUq","xXTI4s4786","o8UydCfgr3","2Nslmx3LDe","MmsIoGrDg7","soy9tRxrsm","tvdkDNhXdu","d85a90BmCy",
-"zz4ZUdhSuH","QChxsSbRYy","bgJAzt98iW","hUTw70Kyfs","TCgPpvOqCE","ThjNn2Yz7E","uZPqgpv0i7","AmdQd0h1b1","YjB9tCK5W7","SjskQhi5X7",
-"AgJHQxciqp","S2DfublLA9","fqypy29QAz","zz4ZU9eoRc","x3LDeOHaBz","Vprf2QnJ1S","JkzUn5Drn0","JRJQBhSSvQ","pFrrluoStw","StlDJpAhR1",
-"oQ87r0MR5X","BGaQY45cIH","WreyPuZPqg","uN6r3FVMxo","NcICA5Namm","9XyT9x3LDe","aL6AJh1zcH","5VZjS2hEEU","soy9tVBjhz","0BmCyStlDJ",
-"y94nw64s8N","Dz1R3taOXK","IBe8k8cVD3","aez9yfLNg8","tlILt5Mg9r","oGu6xMkgy8","6AFT0B3qem","64s8NJJs5m","kZANm0h1b1","GXdoHaFFss",
-"s7MxkHlUbF","BGaQYFwEJz","tvdkDy94nw","JJs5mlCMxy","he9IAZ4I1v","hYBCKLbRTH","1v5hHgdQsS","fqypyFjHXR","2TRI7Z4I1v","NcICAl83Ud",
-"cmXIXydG8U","v8yFNMGlTF","FxX9qv8yFN","RzaZAzqH0W","hUTw7GrDg7","M3zXLiB08l","SbRYyzFgtB","uAWyp8U2nU","3otm616lHc","FFDuiOxWIH",
-"soy9tSWfou","5NammtjQxs","RzaZA9eoRc","FPfSEStlDJ","YjB9tfqypy","ReKEWOHaBz","64s8NGXdoH","atef2zbIYY","DcpWBRxrsm","vOqCEv2eC3",
-"DcpWBd7vjM","618DilCMxy","QworuQChxs","9GXkXIn3NS","FVMxoCfgr3","HP4331LB1L","v1HlnM3zXL","UmaEvpAhR1","VNCPd55rfB","No0Qbd7vjM",
-"6q6L9Q6Lix","tvdkDaez9y","sqVrf4dEz6","t98iWQChxs","zY1GYOxWIH","euZA5atef2","P6bcg5drc6","0KyfsDcpWB","tjQxsuQIcz","tjQxsrz7Ut",
-"dmoS7YjB9t","Q6Lixfqypy","b29RJMaJQs","MK07YbrhlQ","QChxs5Namm","5iGN5No0Qb","7lUXZ07n1c","FFDuiAkKTk","VLTy6VNCPd","RBhp07hyVv",
-"4W0TlW7cTs","pvgjS1v5hH","ZJTXHKr8ys","IKxdL5Namm","AOgEes4786","WaWsvCdyBV","Q6Lix8U2nU","fFDrJ9GXkX","prNT6Gv3Fq","5nmWvdjsrv",
-"IRh48Gv3Fq","SbRYyLDk6f","5drc6CdyBV","WMiS3IKxdL","uTacxO3iyQ","QnJ1SJXljW","brhlQUvlv4","4dEz6X6Pin","WreyPuN6r3","uJScXNAFuw",
-"6AFT0SjskQ","lH1ktfLNg8","BFkb8S2Dfu","0PktI7fsYM","9y4lwRkQke","9y4lwFPfSE","JIqXi8U2nU","FNYIMQYxC0","VjCZqjtn0X","2DREs8xEKz",
-"HlUbF0PktI","gjUTu5Drn0","GWqqXv1Hln","vOqCEjS1aj","pv0i7djsrv","h1zcHZv7z0","24ARFoGu6x","ZJTXHMmsIo","5Drn0No0Qb","0YAGHRmDcr",
-"wDajXZuDtD","7lUXZ5drc6","RzaZAuZPqg","SWfouSjskQ","RBhp0aez9y","0KyfsCNHmv","CK5W7DQimp","zbIYY0YAGH","gjUTuBFkb8","dQ586taOXK",
-"StlDJ9iGoT","Yf2EcFFDui","guMb8guMb8","rz7UtfcJOy","EoToPFnPFB","Vprf2ReKEW","K20wKDLhzM","gf8rIDG4sT","9eoRcmX2GE","8xEKzkZANm",
-"qQxHPVIlwP","d85a9YjB9t","aez9y5VZjS","wiHrZLbRTH","fLNg8kB5nP","Zv7z0uQIcz","FNYIM64s8N","AOgEebrhlQ","l83UdO3iyQ","qUJMdMmKGJ",
-"MGlTFCfgr3","Dz1R3gdQsS","GXdoHCp3mZ","0Wr5yFFDui","4W0Tl8RCUA","y94nw8TxD7","EOE1ox3LDe","lj07QbZLvS","G1RhSzbIYY","rz7UtYf2Ec",
-"yluBxQssNC","AOgEexReec","FcWrWtaOXK","WmadAZv7z0","Mm8siNxx9V","zmLYDy94nw","JkzUnCxVEf","gIYvE8hJdt","CqqaDZJTXH","FjHXRgtCA5",
-"Cfgr35nmWv","n1pmOn1pmO","RkQkeJkzUn","GSQwji3pyd","MmKGJn1pmO","he9IAulk41","Y1mC0ThjNn","nnP8ojS1aj","8hJdtM3zXL","FxX9qvOqCE",
-"cShY2azIWp","ru4UGJXljW","2NslmzbIYY","8xEKznFqik","v2eC3FVMxo","pv0i7HRxd8","uTacxfLNg8","L7cGc5Drn0","JJs5mt98iW","AmdQdOz8yZ",
-"OxWIHydG8U","4QMc9euZA5","uvf7AnlaBy","VIlwPblLA9","tAOsrfmIK1","gtCA5djsrv","MGlTFKsjRK","wiHrZUlU3M","yvOMIKASQ8","ru4UG618Di",
-"cShY2zmLYD","SjskQi3pyd","BCxeC6q6L9","gdQsSC2Irc","FnPFBjtn0X","O3iyQVNCPd","OxWIHeuZA5","Mkgy85Drn0","1j5L8KASQ8","RBhp0cmXIX",
-"4dEz6jzUqR","5IhmGNo0Qb","0ao3ldhSuH","M6qcG2Yz7E","rKDLJIKxdL","FPfSE5Drn0","M3zXLzqH0W","jzUqRjS1aj","Zv7z0zqH0W","Rxrsm6q6L9",
-"F6PT2hYBCK","EOE1oWDVWJ","fcJOyJIqXi","2DREsy94nw","BFkb8hUTw7","Cfgr3AkKTk","hE1QllpF6W","iKqhrQbxXc","8xEKzJIqXi","TCgPp1j5L8",
-"RpBQmrKDLJ","brhlQIKxdL","LewvMFPfSE","0KyfsqUJMd","wiHrZDz1R3","CxVEfRACuj","KZamHt98iW","AgJHQeuZA5","CdyBVAXpwE","X6PinFjHXR",
-"VLTy67ku1p","v2eC3DLhzM","QbxXcVjCZq","pvgjSydG8U","FPfSEpv0i7","HfyNQfaHir","HRxd8blLA9","hSSvQJ2mQi","RkQkeOUqFM","JRJQBhe9IA",
-"UmaEv9rlg9","2DREsl83Ud","qQxHPD6rBy","MaJQsOz8yZ","QYxC0h1zcH","ZJTXHThjNn","ZUnqtPb1pa","ix74rKZamH","suY4x2TRI7","jtn0XWmadA",
-"SWfouyvOMI","Uvlv43weIF","FcWrW8FmFH","bgJAzStlDJ","HP433dmoS7","5ZaEzqaofN","2TRI7cmXIX","DG4sTh1zcH","Cfgr3iwzGk","iKqhrIKxdL",
-"lsQGofqypy","7fsYMn8pJ9","d85a9jfREu","n1pmOPYBf4","KZamH7lUXZ","7fKYUe6e4z","QYxC05Mg9r","7Ow5CYjB9t","uZPqgL7cGc","nnP8oLDk6f",
-"0MR5XDz1R3","DG4sTlH1kt","0ao3l8xEKz","wiHrZRsQUq","QYxC0wDajX","ThjNn2TRI7","64s8NVIlwP","fLNg8jfREu","HfyNQ6q6L9","9GXkXjeskS",
-"zFgtBZJTXH","hUTw7ogLgc","lViBvGv3Fq","a00b5y94nw","X6PinqQxHP","b29RJi3pyd","zFgtBzz4ZU","lsQGoRkQke","5IhmGQWxoT","MaJQsFLsph",
-"o8Uyd6AFT0","jtn0XBCxeC","ZhwG1B3qem","BFkb8CdyBV","FFDuiRpBQm","VBjhzaL6AJ","SmGzvWmadA","uvf7AWMiS3","Cfgr3ReKEW","0PktI0ao3l",
-"8hJdtatef2","d7vjMHlUbF","FwEJzCp3mZ","nlaByL7cGc","AOgEeBCxeC","QClRLG1RhS","s47862Yz7E","d85a9Dz1R3","B3qemyEfy9","64s8Nzz4ZU",
-"M6qcGMojnP","a00b5CIShG","24ARFUvlv4","Nxx9VRsQUq","qaofNiwzGk","gIYvEQssNC","5drc6aez9y","Dz1R3GXdoH","jS1ajFwEJz","BCxeCFPfSE",
-"okgRiCK5W7","In3NSQClRL","2NslmDz1R3","e6e4z24ARF","nnP8opv0i7","dhSuHD6rBy","Z4I1v5drc6","fcJOyuJScX","1j5L8qQxHP","aez9yS77LH",
-"wiHrZuZPqg","OUqFM4QMc9","ZJTXHFNYIM","cL0aEYh1hF","lkMUA8RCUA","VerEAb29RJ","2NslmmX2GE","HP433Yw2oU","14FLRulk41","IKxdLpiJSk",
-"14FLRC2Irc","fFDrJxciqp","DG4sTvLsmS","b29RJDcpWB","ZuDtDprNT6","SbRYyQworu","pv0i7NcICA","lH1ktxReec","VLTy6yofH3","AgJHQRBhp0",
-"s4786C2Irc","0YAGHuoStw","07n1czmLYD","aL6AJ5Drn0","lCMxyYjB9t","UmaEvpmeCd","QChxsWmadA","0Wr5yFNYIM","LDk6fQworu","CIShGQnJ1S",
-"jS1ajJKWYR","7fsYMRkQke","MmKGJVNCPd","VerEA9eoRc","8xEKzBGaQY","Uvlv4yEfy9","EdBKcpFrrl","K4GS8AgJHQ","d7vjMHzZT8","TCgPpiwzGk",
-"Pb1paQWxoT","U3yw5vOqCE","mX2GEKsjRK","8FmFHcQOnv","aFFssK20wK","6q6L9i3pyd","uLtKsLewvM","07n1cOz8yZ","tAOsrjzUqR","QChxspFrrl",
-"aez9ya00b5","xReecRxrsm","Yw2oUpiJSk","StlDJpv0i7","TwanoBpYhV","KsjRKs7Mxk","pWiOsNhXdu","24ARFMmsIo","s7MxkPOUYS","atef2GXdoH",
-"cQOnvVprf2","tl72WDQimp","lpF6WBGaQY","9XyT9KZamH","ZhwG1MmsIo","LbRTHJKWYR","Cp3mZl83Ud","45cIHCfgr3","t98iWYh1hF","Cp3mZX6Pin",
-"WaWsvk85Ae","xReecqaofN","MK07YHlUbF","KsjRKQYxC0","HRxd8nFqik","ZuDtDnnP8o","uAWypDG4sT","dhSuHpiJSk","K20wKCxVEf","v8yFNqUJMd",
-"wiHrZe6e4z","cQOnvVNCPd","FxX9qpmeCd","FNYIMY1mC0","J2mQiGXdoH","MaJQsUmaEv","QWxoTNAFuw","QYxC0hYBCK","SjskQHRxd8","7fKYUM6qcG",
-"2hEEUoGu6x","QssNCOHaBz","bZLvSFjHXR","1v5hHtjQxs","aDGtSb29RJ","D6rByk85Ae","gIYvEMezSW","X6PinAXpwE","24ARFRkQke","SbRYyNOHsz",
-"CIShGzHF1q","VBjhzWDVWJ","xReec14FLR","CIShGJIqXi","JIqXiTa8f6","ZuDtDjzUqR","cShY2DQimp","l83UdQYxC0","HP433KASQ8","Mm8siB3qem",
-"5Mg9razIWp","ZuDtDJXljW","7Ow5CjfREu","TXQ0ZZhwG1","QssNCW7cTs","TwanooGu6x","djsrvTCgPp","DcpWB7fsYM","Gv3FqSmGzv","0h1b1okgRi",
-"cL0aEX6Pin","gdQsSFLsph","RACujyluBx","4QMc9ZzJHW","VNCPdyvOMI","0BmCyECMvU","Gv3FqO3iyQ","nlaByNcICA","QChxsn8pJ9","Yh1hFzz4ZU",
-"P6bcgC2Irc","x3LDe29QAz","Cfgr35drc6","Q6LixblLA9","xXTI47ku1p","d85a9P6bcg","CqqaDdmoS7","Chuy30PktI","t98iWVerEA","8cVD364s8N",
-"pFrrlRACuj","1LB1LAOgEe","hi5X7S77LH","uoStwFVMxo","fLNg81v5hH","JRJQBX6Pin","RACujB3qem","MaJQsYOfrY","RmDcrKsjRK","JXljWwDajX",
-"hYBCK580YD","gjUTulXFOB","MK07Y45cIH","7fKYUn8pJ9","zqH0Wjtn0X","pv0i7Zv7z0","cShY20PktI","Yf2EcP6bcg","HlUbF1LB1L","b29RJ9y4lw",
-"pAhR1Yf2Ec","gjUTujeskS","EoToPk85Ae","qaofNTCgPp","Ta8f6Dz1R3","6q6L95VZjS","oVQp6yluBx","GXdoHhSSvQ","2hEEUCp3mZ","YjB9tBbwgA",
-"0KyfsAkKTk","7lUXZdhSuH","7hyVvJRJQB","zQt6Qt59lR","8cVD3aez9y","bgJAzCNHmv","v2eC38hJdt","CIShGAXpwE","IBe8kokgRi","h1zcHeuZA5",
-"tvdkDEoToP","GrDg7Z4I1v","7hyVvm4bxU","zQt6Qs7Mxk","yvOMIdmoS7","AXpwEoGu6x","OxWIHStlDJ","BpYhVhUTw7","blLA9mz8gx","8U2nUbgJAz",
-"9y4lwFVMxo","hE1QlKr8ys","L7cGcAgJHQ","MmKGJs7Mxk","nlaByatef2","6AFT0cL0aE","cQOnvuAWyp","FwEJzrKDLJ","RmDcrazIWp","D6rBy45cIH",
-"jS1ajHzZT8","4dEz6IjTwP","24ARFYw2oU","VLTy6hYBCK","OUYuF9eoRc","uJScXqQxHP","hYBCKRpBQm","WaWsvWaWsv","ix74rSjskQ","MGlTFatef2",
-"yToGWZhwG1","CNHmvCIShG","l83UdCK5W7","0KyfsWaim6","oQ87rlsQGo","FwEJzzz4ZU","FnPFBS2Dfu","gdQsSjiVBP","IjTwPdpe1v","d7vjMh1zcH",
-"2DREspAhR1","uN6r3GrDg7","dQ586a00b5","VBjhz3otm6","CIShGOxWIH","euZA5WaWsv","1j5L814FLR","7X3uyJKWYR","LbRTHuoStw","0MR5Xmz8gx",
-"QnJ1SCfgr3","qQxHPguMb8","OxWIHlpF6W","gIYvEWPmlx","nnP8o7X3uy","RACujIBe8k","4QMc9POUYS","v1HlnpvgjS","Mm8siXyPZN","okgRiv8yFN",
-"LewvMKr8ys","POUYSmz8gx","lXFOBQWxoT","DLhzM7ku1p","ReKEW55rfB","5ZaEzgtCA5","XflUq24ARF","aFFsss93Ml","FVMxoIn3NS","qaofNfmIK1",
-"NhXduAmdQd","sx5Gllm0pD","VjCZqKZamH","dhSuHFcWrW","ZUnqtb29RJ","14FLRBbwgA","07n1cfcJOy","pv0i7h1zcH","piJSkOUYuF","BpYhVVjCZq",
-"tvdkDlViBv","Pb1pacL0aE","s7MxkZ4I1v","7hyVvzY1GY","RsQUqStlDJ","jiVBPokgRi","AIYUuhe9IA","ZUnqtpvgjS","BFkb8ZJTXH","LewvMzHF1q",
-"QssNCLewvM","QChxs55rfB","bZLvSfqypy","i3pydsoy9t","pWiOsSbRYy","48cHL07n1c","dQ586oVQp6","VBjhzF6PT2","GSQwjguMb8","lpF6WPb1pa",
-"dmoS7k85Ae","h1zcHd85a9","FnPFBKr8ys","Yw2oUKZamH","n8pJ9soy9t","Q6hMCv1Hln","zbIYYgtCA5","d7vjMGXdoH","ECMvUO3iyQ","zbIYYKASQ8",
-"9iGoTy94nw","48cHLMojnP","fLNg8zqH0W","zHF1qMGlTF","d85a9nnP8o","M6qcGQnJ1S","xciqpNcICA","Kr8ysKr8ys","8hJdtMojnP","OUYuF7hyVv",
-"sqVrfjfREu","cQOnvcQOnv","rKDLJEoToP","14FLRvLsmS","uZPqgxReec","ogLgcrz7Ut","16lHclpF6W","2TRI7wiHrZ","uQIczb29RJ","8TxD7FNYIM",
-"Ss0ZulpF6W","tuDySfqypy","nlaByh1zcH","1LB1L8cVD3","QChxsMK07Y","tAOsrYh1hF","VNCPdMGlTF","In3NSIBe8k","D6rByNOHsz","DLhzMdQ586",
-"55rfBZUnqt","8hJdtAkKTk","yvOMIAmdQd","azIWpIBe8k","Yf2EcJXljW","dhSuHCNHmv","lweGylH1kt","azIWp2ZHdk","wDajXokgRi","POUYSulk41",
-"UlU3MBCxeC","ulk41JKWYR","tAOsro8Uyd","CIShGUlU3M","aFFss24ARF","24ARFguMb8","MezSWTXQ0Z","xReech1zcH","1LB1LFwEJz","b29RJWPmlx",
-"7X3uyPYBf4","GWqqXkZANm","NAFuw8RCUA","GWqqXAgJHQ","iB08lK4GS8","UmaEvTa8f6","GWqqXAXpwE","ulk418FmFH","7ku1prz7Ut","jfREuazIWp",
-"S77LHCdyBV","gjUTuwiHrZ","O3iyQVIlwP","tjQxsvOqCE","lCMxyAgJHQ","3otm69XyT9","ZhwG1t59lR","lsQGoVerEA","fcwDaGXdoH","NOHsz29QAz",
-"taOXKJ2mQi","lm0pDdpe1v","djsrv9eoRc","t59lRQYxC0","gtCA5Oz8yZ","jzUqRtaOXK","zQt6QlViBv","S77LH64s8N","MaJQsLDk6f","ECMvUMmsIo",
-"BCxeC9XyT9","64s8NKr8ys","S2DfuazIWp","NhXduDcpWB","t98iW6q6L9","lkMUASbRYy","QChxsVerEA","UlU3M9XyT9","8TxD7i3pyd","L7cGcHRxd8",
-"prNT6uvf7A","d85a9nlaBy","FhtglGv3Fq","D6rByFxX9q","vLsmSFwEJz","uTacxBGaQY","K20wKt59lR","24ARFWMiS3","gIYvE5IhmG","CIShGFNYIM",
-"lsQGoChuy3","e6e4zAIYUu","2Nslms93Ml","azIWpIRh48","2TRI7dmoS7","F6PT2FwEJz","djsrvUmaEv","3weIFIRh48","FxX9qqaofN","EOE1oFNYIM",
-"6q6L9AXpwE","HzZT8JKWYR","0ao3lokgRi","QYxC0nnP8o","rhl0JYh1hF","zmLYDC2Irc","piJSk14FLR","DcpWBW7cTs","ZuDtDIBe8k","VNCPduAWyp",
-"gtCA50BmCy","y94nw3weIF","CxVEfZ4I1v","EdBKc4W0Tl","xciqpXyPZN","dpe1vKASQ8","DQimpGWqqX","WreyP64s8N","RkQkezz4ZU","uvf7AQWxoT",
-"qUJMd0MR5X","CqqaDRxrsm","zHF1qPYBf4","0PktIhE1Ql","XflUqiqv4k","lpF6WReKEW","pmeCd0BmCy","b29RJDQimp","2DREsv1Hln","OUqFMJkzUn",
-"POUYS8TxD7","QYxC0FLsph","fqypy3otm6","faHirpWiOs","StlDJBGaQY","XyPZNfcwDa","nnP8ob29RJ","gdQsS5Namm","vOqCEvkCHH","t98iWnlaBy",
-"uLtKsEoToP","ThjNnZ4I1v","JRJQBFGzgp","7X3uyOHaBz","AkKTkYw2oU","RkQke9eoRc","pFrrlBCxeC","BpYhVni2v1","55rfBRACuj","blLA9brhlQ",
-"WmadA5Namm","d85a9BpYhV","GXdoHhE1Ql","VLTy6Waim6","C2IrcuN6r3","uupzkksJby","UmaEvx3LDe","QbxXcGv3Fq","HRxd8yToGW","M3zXL2TRI7",
-"IBe8k0BmCy","euZA5YOfrY","0h1b1l83Ud","Dz1R3jiVBP","IjTwPlj07Q","v1Hlnv2eC3","zqH0WqaofN","Mm8si8TxD7","tvdkDqUJMd","1LB1Lpv0i7",
-"lXFOBs7Mxk","s4786FwEJz","4W0TlkZANm","7Ow5CFPfSE","wiHrZlm0pD","IjTwPHlUbF","qQxHPjtn0X","hi5X7ThjNn","RpBQmjfREu","hUTw7Z4I1v",
-"hi5X7uQIcz","s47860h1b1","8FmFHWmadA","uQIczCp3mZ","ru4UG5ZaEz","RmDcrix74r","uTacxGv3Fq","lXFOBWaim6","45cIHHRxd8","gtCA5ydG8U",
-"VIlwPoQ87r","TCgPpguMb8","mX2GEDLhzM","B3qemCK5W7","Oz8yZChuy3","a00b5SmGzv","ZuDtD1LB1L","Ul4a1MmsIo","Ta8f6Ss0Zu","Mkgy8JRJQB",
-"ReKEWChuy3","fmIK1C2Irc","uZPqgUmaEv","QChxsAOgEe","D6rByIn3NS","Rxrsm2Yz7E","B3qemblLA9","K20wKGXdoH","7fsYM9iGoT","djsrvyEfy9",
-"9eoRc0h1b1","EdBKcd85a9","SWfouBGaQY","ReKEWzqH0W","mX2GEzz4ZU","h1zcH9GXkX","uPX7GQ6Lix","uQIczs93Ml","WDVWJTXQ0Z","48cHLjS1aj",
-"ulk41uZPqg","HRxd816lHc","i3pydrz7Ut","7lUXZcQOnv","uoStwMK07Y","CK5W76q6L9","t59lRksJby","VBjhzcL0aE","pmeCdOxWIH","zFgtBiwzGk",
-"FnPFBd7vjM","tAOsr6q6L9","2ZHdkOUqFM","8xEKzQWxoT","MGlTF6AFT0","8hJdtMm8si","YOfrYOxWIH","9iGoT0MR5X","dpe1vzQt6Q","tvdkD7fKYU",
-"MaJQsfaHir","tvdkDfqypy","uJScXxciqp","a00b5x3LDe","t98iWuvf7A","k85Aes4786","RmDcrjSjS3","7fsYMUlU3M","0BmCyaez9y","Yh1hFdmoS7",
-"Mkgy8iqv4k","JJs5mEoToP","zQt6QW7cTs","taOXKFNYIM","vLsmSQ6Lix","8RCUAv2eC3","WmadApFrrl","YjB9tFVMxo","azIWpGv3Fq","m4bxUm4bxU",
-"EoToP8RCUA","ReKEW45cIH","OUqFMWMiS3","WreyPTCgPp","8cVD35Namm","ulk41J2mQi","JkzUnhYBCK","uLtKsHzZT8","t98iWVIlwP","gjUTuaFFss",
-"e6e4zoQ87r","7fsYMAmdQd","AIYUupmeCd","nnP8oNAFuw","5NammhUTw7","7fKYU2Yz7E","taOXK2Nslm","14FLRWDVWJ","aDGtSJXljW","9rlg99GXkX",
-"GXdoHMojnP","oGu6xzFgtB","lkMUA3otm6","lViBviKqhr","Cp3mZfLNg8","L7cGc8hJdt","HP433VjCZq","fqypycShY2","Mkgy8IBe8k","KsjRKWaim6",
-"nnP8oUlU3M","uPX7GCdyBV","cmXIXG1RhS","UlU3Mpv0i7","NOHszJXljW","b29RJqaofN","xXTI4Ul4a1","dQ586t59lR","2ZHdkcL0aE","aez9yS2Dfu",
-"jiVBPCqqaD","0YAGH9iGoT","y94nwStlDJ","F6PT2gjUTu","2ZHdkyEfy9","gdQsSiqv4k","pFrrlS2Dfu","SbRYyuupzk","l83UdNo0Qb","n8pJ9VNCPd",
-"wiHrZ0PktI","t98iWd7vjM","7fKYUJ2mQi","BFkb85ZaEz","gdQsShUTw7","D6rByyEfy9","jiVBPOUqFM","Vprf25iGN5","iB08lYw2oU","FGzgpVBjhz",
-"fcJOyAOgEe","0PktIv8yFN","NcICAjeskS","xciqpKr8ys","tjQxsJJs5m","v8yFNfmIK1","8hJdtVBjhz","GXdoHCIShG","MojnPblLA9","OUqFMWaim6",
-"Cp3mZ2hEEU","EOE1o5ZaEz","h1zcHL7cGc","gf8rI9y4lw","5Drn0WDVWJ","lCMxyl83Ud","zz4ZUChuy3","14FLRDG4sT","X6PinprNT6","8cVD3uupzk",
-"WmadAx3LDe","zQt6QZuDtD","ZhwG1CIShG","VerEAFFDui","8RCUA0h1b1","ZhwG1DLhzM","9y4lw4dEz6","atef2Yw2oU","WMiS3v8yFN","suY4xY1mC0",
-"EoToPfcwDa","v8yFNgf8rI","kZANmM3zXL","QChxs7fsYM","uQIczi7WMQ","blLA9hSSvQ","3weIFtl72W","n1pmOuupzk","GXdoHFNYIM","AOgEeqaofN",
-"0h1b1uLtKs","Vprf2SmGzv","vLsmSYOfrY","MojnPHP433","7lUXZRkQke","4W0TlAkKTk","Cfgr30Wr5y","lViBvAgJHQ","In3NSRxrsm","yluBxVNCPd",
-"KASQ8HlUbF","QssNC7ku1p","6AFT0n1pmO","Ta8f60BmCy","jSjS3zY1GY","HzZT8YOfrY","dpe1vJXljW","BbwgAFhtgl","iqv4kWaWsv","fcwDa5Namm",
-"NAFuwOUqFM","9XyT9gtCA5","SmGzvt98iW","ZhwG1hE1Ql","ulk41hi5X7","ZUnqt0Kyfs","tjQxstlILt","RkQkelViBv","S77LHLDk6f","Dz1R38xEKz",
-"tlILtni2v1","jS1aj6AFT0","JkzUntlILt","fFDrJlpF6W","Uvlv4CxVEf","dmoS7tjQxs","zFgtBfcwDa","CqqaDjeskS","djsrvCp3mZ","AgJHQdhSuH",
-"2hEEUK4GS8","8FmFHG1RhS","CdyBVni2v1","zqH0Wlm0pD","M6qcGyEfy9","KASQ8GWqqX","pFrrlvOqCE","QbxXcfFDrJ","7fsYMMaJQs","cShY2DcpWB",
-"DLhzMZuDtD","MmsIocQOnv","d85a914FLR","hE1QlvOqCE","NAFuw9y4lw","QChxs8FmFH","MmsIo7hyVv","oGu6xQ6hMC","I7p2aJXljW","uQIczMezSW",
-"HzZT8XyPZN","QWxoTs7Mxk","5Drn0QClRL","djsrvzFgtB","OUqFM9y4lw","zz4ZUfaHir","StlDJuvf7A","GSQwj14FLR","SWfouTa8f6","gf8rIfmIK1",
-"FFDuijeskS","zz4ZUCdyBV","m4bxUuQIcz","FcWrW9GXkX","0h1b1FcWrW","G1RhSMezSW","lm0pDulk41","QClRLOHaBz","jeskSDcpWB","Cp3mZZv7z0",
-"FwEJzt98iW","Ul4a1wDajX","0h1b1pFrrl","Y1mC0lpF6W","C2Ircv1Hln","cL0aEZuDtD","YOfrYBGaQY","MK07YTa8f6","dpe1viKqhr","hYBCKPYBf4",
-"S77LHOz8yZ","iKqhrL7cGc","RmDcrfmIK1","SbRYyMojnP","t98iWhi5X7","5Namm0MR5X","580YDPYBf4","0Wr5yiB08l","zFgtBQbxXc","7fKYUfFDrJ",
-"Q6LixRxrsm","v8yFNHP433","WaWsvCp3mZ","MmKGJ5VZjS","4dEz6Ul4a1","HfyNQGv3Fq","VerEABbwgA","vLsmS7lUXZ","l83Uduupzk","zqH0WHP433",
-"16lHc2hEEU","s4786kB5nP","v1Hlnn1pmO","Cfgr30ao3l","16lHcYh1hF","5nmWvwDajX","POUYSuAWyp","aDGtS5iGN5","yEfy90Kyfs","LewvMlViBv",
-"atef2zY1GY","QYxC02hEEU","i7WMQB3qem","uTacxTCgPp","4W0TlBbwgA","L7cGcuZPqg","KsjRKEoToP","Yh1hFNxx9V","nlaByU3yw5","qUJMdQnJ1S",
-"vOqCEhi5X7","14FLRFcWrW","LewvMNo0Qb","AgJHQRpBQm","rhl0JuN6r3","ix74r7fKYU","uZPqgatef2","D6rByciuWz","S77LHOUqFM","PYBf4CIShG",
-"9iGoT5Mg9r","zbIYYiwzGk","5IhmGZJTXH","KsjRKZuDtD","pWiOsTXQ0Z","lj07QFjHXR","uTacx0Wr5y","Yf2EcpWiOs","WMiS3jfREu","hUTw7WaWsv",
-"9XyT9DLhzM","aL6AJd7vjM","Oz8yZGWqqX","djsrvy94nw","ksJbysuY4x","FNYIMBFkb8","W7cTsZJTXH","IKxdL8hJdt","AgJHQ7hyVv","MaJQstlILt",
-"FxX9q8TxD7","SbRYys4786","v1Hlnk85Ae","K20wKYh1hF","QClRLEoToP","vLsmS8U2nU","jiVBPRmDcr","lpF6WaL6AJ","fcJOy7Ow5C","FxX9qguMb8",
-"O3iyQmX2GE","tuDySatef2","MGlTFNxx9V","4W0TlChuy3","aL6AJNOHsz","bgJAzECMvU","rhl0JpAhR1","HRxd88hJdt","k85AeRmDcr","HzZT8S2Dfu",
-"HfyNQBFkb8","CqqaDpAhR1","QChxsxXTI4","7ku1pSs0Zu","GSQwj7fKYU","FLsphsoy9t","i7WMQ5nmWv","cShY2QChxs","lCMxypv0i7","pWiOsX6Pin",
-"iwzGk5iGN5","D6rBy0BmCy","sx5GlOHaBz","MezSWVerEA","ZzJHWCp3mZ","sqVrfd85a9","Kr8ys2hEEU","3otm61LB1L","WDVWJjiVBP","qUJMdZuDtD",
-"cShY2uZPqg","7Ow5C1v5hH","6q6L9l83Ud","uN6r3GSQwj","cmXIX9GXkX","VjCZqDLhzM","RsQUq07n1c","DcpWBi3pyd","9GXkXVprf2","iwzGkZuDtD",
-"l83Ud0Kyfs","taOXKuupzk","zmLYDM6qcG","tAOsr0YAGH","8cVD3fcJOy","No0QbjS1aj","ulk41ZUnqt","zmLYDhE1Ql","Uvlv4iKqhr","RmDcrCK5W7",
-"aFFssFhtgl","AkKTkdjsrv","RxrsmS2Dfu","PYBf45drc6","yEfy9G1RhS","55rfBciuWz","ksJbyQClRL","faHir0PktI","WDVWJUvlv4","BFkb8fcwDa",
-"dQ586vLsmS","29QAzjeskS","JRJQB7lUXZ","RkQke5VZjS","7lUXZuAWyp","4QMc9gIYvE","JJs5muLtKs","BGaQYx3LDe","pmeCdpFrrl","DcpWB7X3uy",
-"Cp3mZMmKGJ","ThjNnb29RJ","0h1b17Ow5C","lpF6WokgRi","t59lRFwEJz","Pb1pauPX7G","Cp3mZUl4a1","ZhwG1BbwgA","RACuj0BmCy","uAWyp0BmCy",
-"Cp3mZDz1R3","brhlQXyPZN","ZuDtDsx5Gl","TXQ0ZCNHmv","v1HlnRsQUq","0ao3lqQxHP","Ta8f6ciuWz","i3pydo8Uyd","pWiOsrKDLJ","ulk41B3qem",
-"rKDLJzFgtB","7fsYMI7p2a","piJSk2ZHdk","RkQkeFLsph","uAWypzmLYD","EOE1o9iGoT","HfyNQyofH3","WreyPTa8f6","UmaEvuoStw","dhSuHCK5W7",
-"4dEz6prNT6","2Yz7EStlDJ","6AFT0fqypy","DcpWBFNYIM","SjskQi7WMQ","qQxHPkZANm","DcpWBHRxd8","pFrrlmX2GE","JRJQBpvgjS","BGaQYOUYuF",
-"QWxoT0Kyfs","y94nwciuWz","DcpWBAmdQd","W3VFHY1mC0","DQimpOUYuF","X6PinlweGy","RsQUq5nmWv","HRxd8ni2v1","qUJMdZUnqt","dQ586DcpWB",
-"prNT6StlDJ","OUYuFCp3mZ","ZuDtDkZANm","GrDg7FGzgp","WmadAjtn0X","5ZaEz7Ow5C","vkCHHGSQwj","djsrvsqVrf","ZhwG1UlU3M","JRJQBHfyNQ",
-"pv0i7Kr8ys","LbRTHpmeCd","W3VFHxciqp","Y1mC09y4lw","2hEEUNAFuw","RxrsmL7cGc","J2mQiCIShG","LbRTHs7Mxk","IBe8kiKqhr","9GXkX24ARF",
-"uupzkVjCZq","uTacx0MR5X","i7WMQzqH0W","yToGWCNHmv","G1RhSNxx9V","CdyBVDQimp","SjskQUvlv4","Yh1hFfcJOy","B3qemU3yw5","EOE1oMaJQs",
-"AmdQdUmaEv","FjHXRvLsmS","ZUnqt8hJdt","tAOsrKASQ8","jfREuUlU3M","0MR5Xiqv4k","uoStwY1mC0","fmIK1J2mQi","mX2GEQWxoT","atef2pAhR1",
-"ni2v1QnJ1S","8TxD7lj07Q","CK5W7nlaBy","AmdQdLbRTH","brhlQni2v1","7X3uyni2v1","RpBQmjS1aj","ZUnqtKZamH","DG4sT0Kyfs","4QMc9okgRi",
-"dQ5864dEz6","wDajXuupzk","lj07QGWqqX","jeskSOHaBz","b29RJSWfou","YjB9tlj07Q","Mm8sipmeCd","uAWypprNT6","9eoRcSs0Zu","i7WMQDQimp",
-"VIlwPpWiOs","6q6L9aL6AJ","VLTy6yvOMI","TCgPp9iGoT","WaWsvs4786","AkKTkpFrrl","LDk6fs93Ml","7hyVvuJScX","HzZT8Q6Lix","Cfgr3pAhR1",
-"gdQsSLbRTH","P6bcg8FmFH","0YAGHRsQUq","uTacxv2eC3","B3qemMojnP","KZamHdQ586","jSjS3yEfy9","jzUqRfLNg8","5ZaEzGWqqX","qQxHPgf8rI",
-"HfyNQ8FmFH","Pb1paHP433","2NslmuN6r3","m4bxUMK07Y","atef2yEfy9","2DREsNcICA","JIqXiUmaEv","45cIHdjsrv","aDGtSVLTy6","G1RhSuoStw",
-"iwzGkRzaZA","G1RhSEOE1o","24ARFpmeCd","hYBCKo8Uyd","iB08lpWiOs","XflUq5ZaEz","EdBKcVjCZq","NAFuwuLtKs","b29RJhSSvQ","D6rByhi5X7",
-"ThjNnLDk6f","BCxeCuLtKs","KsjRK9y4lw","NhXdu1v5hH","29QAzhE1Ql","JRJQBAXpwE","FjHXRKr8ys","3otm6dhSuH","pT8wuVjCZq","jtn0XWreyP",
-"SbRYy4dEz6","MmsIoaDGtS","8hJdtFVMxo","HRxd8Waim6","ni2v18hJdt","CxVEfGXdoH","Cfgr3QChxs","SbRYyiB08l","OxWIHQssNC","S77LHUl4a1",
-"zmLYDHfyNQ","FnPFBni2v1","5IhmGD6rBy","48cHLTXQ0Z","yToGWYOfrY","FVMxomz8gx","fFDrJ24ARF","Mm8sifLNg8","nnP8o9eoRc","aDGtSK4GS8",
-"nFqik7Ow5C","x3LDeQworu","618DiStlDJ","HRxd864s8N","lpF6WguMb8","5Mg9rK20wK","RkQkeVLTy6","s7MxkCxVEf","U3yw5QYxC0","9rlg9pFrrl",
-"CdyBVQClRL","KsjRKcShY2","xciqpd85a9","zHF1qGrDg7","ogLgctjQxs","v8yFNFxX9q","NhXduAkKTk","MK07YSs0Zu","GWqqXfFDrJ","BbwgAIn3NS",
-"yToGWb29RJ","ZuDtDOUqFM","Q6hMCpWiOs","RmDcrprNT6","SbRYycmXIX","xXTI4NcICA","RBhp07lUXZ","5Mg9rnFqik","0PktIuQIcz","0h1b1ulk41",
-"JXljWt59lR","G1RhSYw2oU","CxVEftAOsr","n8pJ9yvOMI","Ta8f6Ta8f6","OUYuFNOHsz","QClRLKZamH","S77LHeuZA5","WmadAKZamH","SjskQ618Di",
-"5ZaEztAOsr","MaJQsQworu","zHF1qjfREu","14FLRsx5Gl","TwanoNAFuw","uTacxyluBx","zmLYDS77LH","brhlQNo0Qb","U3yw5prNT6","5Mg9rSbRYy",
-"24ARF5IhmG","RBhp0qaofN","uTacxni2v1","jfREulweGy","EOE1o14FLR","aDGtS7lUXZ","d7vjMlpF6W","tvdkDGrDg7","s4786lH1kt","QWxoTGXdoH",
-"zHF1qh1zcH","ksJbyHP433","FcWrWwDajX","faHirRBhp0","JIqXi8RCUA","lViBvQ6hMC","gIYvEQChxs","o8UydLDk6f","tAOsri3pyd","qUJMdOxWIH",
-"MaJQsNAFuw","v8yFNhYBCK","DQimplsQGo","jiVBPGSQwj","XflUqzFgtB","QChxs5nmWv","SWfou4W0Tl","RpBQmiKqhr","SjskQ7lUXZ","7X3uyM3zXL",
-"n8pJ9CdyBV","BCxeC1j5L8","tuDyS64s8N","uLtKst98iW","BCxeCUl4a1","iB08lfFDrJ","BbwgAKZamH","hSSvQuTacx","VBjhzoQ87r","kB5nPdQ586",
-"BbwgAChuy3","SmGzvlH1kt","CxVEfFjHXR","FcWrWrhl0J","0PktIPb1pa","4W0TltlILt","uupzkL7cGc","0Wr5yulk41","ZJTXHZ4I1v","NAFuwTwano",
-"DQimptuDyS","RsQUq5iGN5","LDk6fzqH0W","0YAGHLewvM","0KyfsLewvM","OxWIHoQ87r","O3iyQ5Namm","tAOsrIjTwP","yofH3hi5X7","Chuy3ni2v1",
-"qQxHPIjTwP","ZJTXHWreyP","qQxHP8RCUA","Uvlv4WPmlx","5nmWvBpYhV","ix74r9iGoT","QnJ1SQworu","5NammIRh48","EoToP0ao3l","JRJQB1v5hH",
-"soy9tZuDtD","UlU3MpFrrl","jSjS3QbxXc","ksJbyWPmlx","14FLR0YAGH","FxX9q7fKYU","JIqXi14FLR","uAWypbgJAz","jzUqRyToGW","RsQUqogLgc",
-"lsQGoAgJHQ","QbxXcaDGtS","AXpwEpv0i7","1v5hHcQOnv","RBhp0vkCHH","t59lReuZA5","ThjNnKsjRK","NAFuw3otm6","QbxXcFLsph","Chuy3NOHsz",
-"suY4xeuZA5","ni2v1XflUq","RACuj1v5hH","B3qem7X3uy","bgJAzQssNC","07n1cdjsrv","CK5W7ciuWz","WDVWJQworu","hE1QlEdBKc","1LB1LgjUTu",
-"bgJAzaL6AJ","ReKEWx3LDe","SbRYyDcpWB","In3NSyluBx","zFgtBdmoS7","euZA5x3LDe","7lUXZs7Mxk","ZuDtD7X3uy","i3pyd0h1b1","CqqaDoVQp6",
-"ZUnqtqQxHP","9rlg9yofH3","W3VFHoGu6x","jSjS3y94nw","W3VFHt98iW","MezSWvkCHH","Gv3FqGXdoH","e6e4zpiJSk","B3qemK20wK","QbxXccQOnv",
-"lkMUArhl0J","wiHrZ2DREs","4QMc9xReec","cL0aEzqH0W","VLTy6suY4x","Vprf2SWfou","SmGzv8xEKz","9y4lws7Mxk","lj07QCqqaD","BGaQYCdyBV",
-"yluBxFLsph","U3yw5AkKTk","Pb1pa0YAGH","sqVrf618Di","zHF1quJScX","rKDLJPb1pa","8hJdt9GXkX","6q6L9wDajX","AgJHQDQimp","MezSWprNT6",
-"POUYSUlU3M","BpYhVsx5Gl","cmXIXCIShG","sx5Gl4dEz6","B3qem7lUXZ","G1RhSOUYuF","oQ87rni2v1","FFDuiyvOMI","IjTwP5Namm","JkzUnaL6AJ",
-"ulk41iB08l","7fKYUFxX9q","hSSvQlCMxy","7ku1py94nw","WmadAvLsmS","tl72WokgRi","GWqqXru4UG","YjB9tYw2oU","Mkgy8nFqik","RACujzbIYY",
-"qUJMdpv0i7","5Namm9rlg9","v8yFNs7Mxk","uPX7GLDk6f","yToGWVerEA","pmeCdsoy9t","qUJMdIRh48","pvgjS2DREs","MK07Yk85Ae","pAhR1Yh1hF",
-"5Drn0hSSvQ","5VZjSM6qcG","7fKYUCqqaD","Gv3Fquupzk","bZLvS8cVD3","WmadATa8f6","taOXKe6e4z","a00b5oVQp6","AIYUu618Di","4dEz6QWxoT",
-"ZuDtDFNYIM","9eoRcGWqqX","brhlQvLsmS","0Wr5yQWxoT","2Yz7Eo8Uyd","nlaByM6qcG","lweGyAIYUu","XyPZNlCMxy","7ku1pe6e4z","XyPZNKr8ys",
-"2TRI7AmdQd","JkzUn07n1c","5NammvLsmS","1LB1LYjB9t","Zv7z0ReKEW","ulk41rKDLJ","1v5hH9rlg9","NAFuwbgJAz","AkKTkHfyNQ","fmIK1Qworu",
-"7hyVvYOfrY","Cfgr3WDVWJ","8RCUAtlILt","F6PT24QMc9","jtn0X7Ow5C","JJs5mqaofN","9rlg9guMb8","Gv3Fq9rlg9","gIYvE7fKYU","0PktIMm8si",
-"rz7UtuQIcz","RzaZA5Namm","Mkgy8EOE1o","RACujaez9y","tvdkDydG8U","jS1ajOUqFM","9rlg9zQt6Q","RxrsmjSjS3","0BmCyxXTI4","0MR5X5nmWv",
-"zHF1qpFrrl","gIYvEBGaQY","3otm6EoToP","CxVEfoQ87r","Yw2oUC2Irc","8FmFHrKDLJ","RsQUqxciqp","5Drn0gtCA5","iqv4kn1pmO","QClRLguMb8",
-"7lUXZ2Yz7E","gf8rIQ6hMC","7fKYURzaZA","8FmFHCIShG","8FmFH07n1c","FnPFBCfgr3","KASQ8ZhwG1","ksJbysx5Gl","pAhR1YjB9t","VBjhz0h1b1",
-"h1zcHrKDLJ","07n1cDcpWB","TXQ0ZQnJ1S","StlDJFVMxo","zqH0WSs0Zu","nFqikZv7z0","AgJHQHRxd8","KZamHTCgPp","DcpWBfqypy","HRxd8jzUqR",
-"48cHLAIYUu","d7vjMrhl0J","n1pmOguMb8","GWqqXCdyBV","Uvlv4TCgPp","Yw2oUVIlwP","MmsIojiVBP","wDajXpvgjS","pAhR1Zv7z0","O3iyQokgRi",
-"W3VFHO3iyQ","ThjNnEOE1o","OUqFMtvdkD","4W0TlgdQsS","DcpWBgf8rI","ZuDtD5iGN5","9rlg9U3yw5","Kr8ysnFqik","0YAGH14FLR","0BmCyRxrsm",
-"BGaQYYf2Ec","n8pJ9bZLvS","ni2v1Kr8ys","Waim6jiVBP","h1zcHMmsIo","ZUnqtNhXdu","v2eC3YOfrY","cL0aECNHmv","WreyPBFkb8","iB08l9XyT9",
-"2DREssqVrf","I7p2aRzaZA","guMb8vLsmS","uAWypYjB9t","h1zcH7fsYM","BCxeCZ4I1v","i7WMQL7cGc","euZA516lHc","9y4lwpmeCd","brhlQGWqqX",
-"FLsphx3LDe","nnP8ocShY2","55rfBMaJQs","WreyPJ2mQi","1LB1LQYxC0","ZUnqt2Yz7E","gf8rIHlUbF","29QAziqv4k","ZhwG1EdBKc","lm0pDAOgEe",
-"M6qcGlkMUA","qaofN8U2nU","zbIYYWDVWJ","iKqhrWMiS3","WMiS3gjUTu","ReKEWDG4sT","G1RhS2Yz7E","Zv7z0qQxHP","29QAzBGaQY","n8pJ9BpYhV",
-"S77LHYjB9t","OUqFMRzaZA","dhSuHGrDg7","GXdoHZv7z0","AgJHQv2eC3","vOqCE0BmCy","hSSvQoQ87r","Z4I1viB08l","o8UydKASQ8","7ku1pl83Ud",
-"0ao3lM3zXL","HRxd8GrDg7","aFFssAOgEe","WPmlx3otm6","29QAzMezSW","hUTw79eoRc","ru4UG7ku1p","BGaQYBFkb8","B3qem29QAz","FLsphcQOnv",
-"rhl0JIRh48","JKWYRazIWp","oGu6xrhl0J","fqypyAIYUu","Mm8siDcpWB","tuDySwDajX","rKDLJRBhp0","WMiS30PktI","tlILt2Nslm","No0Qb0PktI",
-"IBe8kIKxdL","uvf7ANOHsz","OxWIHZzJHW","zbIYYaez9y","pAhR1a00b5","xReecgIYvE","fLNg8FLsph","2TRI7Pb1pa","i3pyd8hJdt","zz4ZUXyPZN",
-"J2mQiix74r","RBhp0OUYuF","0Wr5y7fsYM","uQIczDG4sT","tlILtdjsrv","OUYuFy94nw","SbRYyFNYIM","HRxd8QChxs","iB08lD6rBy","FnPFBSjskQ",
-"RBhp0bZLvS","0Wr5ypmeCd","VBjhzuupzk","SWfouRpBQm","ZhwG1kZANm","JXljWlH1kt","suY4xAOgEe","VNCPd2DREs","RBhp0vOqCE","OUqFMVIlwP",
-"bgJAz5IhmG","ECMvU0MR5X","IjTwPhUTw7","uZPqgDz1R3","iwzGkAkKTk","1j5L8tvdkD","2ZHdkgIYvE","HlUbFbrhlQ","tjQxs9rlg9","W7cTsazIWp",
-"uoStwnlaBy","DcpWBoQ87r","e6e4zi7WMQ","LbRTHVIlwP","iB08lokgRi","Vprf2Dz1R3","HP433FjHXR","gtCA5QYxC0","BGaQYIjTwP","5Mg9rSs0Zu",
-"Pb1patAOsr","FLsphSjskQ","azIWpTwano","7lUXZpFrrl","x3LDe9iGoT","ulk41iwzGk","uupzkuZPqg","7fKYU9GXkX","16lHcZ4I1v","7fsYM5IhmG",
-"h1zcHa00b5","k85AezmLYD","zbIYYHzZT8","i3pydMm8si","Ta8f6a00b5","yluBxHRxd8","qUJMdDG4sT","zQt6QtAOsr","8xEKzOHaBz","64s8NFnPFB",
-"djsrvMmKGJ","sqVrfJKWYR","K4GS8pAhR1","14FLRaDGtS","ulk41VerEA","lm0pDVLTy6","Yw2oUZUnqt","XflUq5IhmG","D6rBy29QAz","SbRYymX2GE",
-"UlU3MFnPFB","sx5Gl5nmWv","CNHmvKsjRK","29QAzRBhp0","IRh48MojnP","VLTy6ix74r","RsQUqmX2GE","5NammWreyP","1j5L89iGoT","JRJQBSmGzv",
-"NOHszsqVrf","Nxx9VFGzgp","Pb1pa9GXkX","FVMxofLNg8","lj07QgjUTu","0MR5XOxWIH","Oz8yZBpYhV","4QMc9Ss0Zu","Chuy3dmoS7","b29RJChuy3",
-"uupzk3otm6","S77LHQssNC","nlaByxReec","taOXK9GXkX","NOHsziqv4k","tvdkDLewvM","AIYUulm0pD","0BmCy0PktI","y94nw7X3uy","M3zXLOz8yZ",
-"8FmFHFFDui","uZPqg0YAGH","vkCHH5nmWv","BFkb8lj07Q","dhSuHoGu6x","FnPFBHRxd8","4W0TlOUYuF","BCxeC9GXkX","MmsIoyToGW","jSjS3OUYuF",
-"zz4ZUFjHXR","NcICAQworu","0PktIfFDrJ","2TRI7FwEJz","dhSuH9rlg9","MmsIoRmDcr","TXQ0ZlH1kt","D6rByn8pJ9","uJScXYh1hF","zHF1qhE1Ql",
-"JIqXiokgRi","HlUbFuQIcz","ulk415Mg9r","FjHXRmz8gx","lpF6WzbIYY","wDajXyofH3","AIYUuRACuj","cL0aEFcWrW","OHaBzEOE1o","6q6L9cmXIX",
-"9XyT9HlUbF","tvdkDbgJAz","O3iyQAmdQd","3otm6n8pJ9","DQimprz7Ut","Uvlv46AFT0","8TxD7uN6r3","JJs5matef2","MK07YIjTwP","brhlQcmXIX",
-"AXpwEAXpwE","64s8NHP433","v2eC3AXpwE","KsjRKUmaEv","zbIYYQssNC","1LB1LVLTy6","29QAzrz7Ut","rhl0JvkCHH","xciqpaDGtS","0Wr5ydpe1v",
-"2hEEUIjTwP","uupzkzQt6Q","Waim6RpBQm","RxrsmcQOnv","W3VFH5VZjS","uoStwFcWrW","HP433uAWyp","WDVWJBpYhV","Gv3Fq7hyVv","618DiSmGzv",
-"taOXKC2Irc","W7cTsiqv4k","rz7Ut7fsYM","xXTI4pWiOs","FGzgpzFgtB","StlDJ29QAz","LewvMQChxs","ksJbyVNCPd","FVMxouN6r3","yToGW4QMc9",
-"P6bcgNcICA","dhSuHBFkb8","ydG8UQbxXc","7ku1pdmoS7","7fsYMjfREu","Chuy3QssNC","uupzkQ6hMC","S2DfuReKEW","AOgEe7lUXZ","JIqXiSs0Zu",
-"Vprf2QssNC","mz8gx5ZaEz","tAOsrRACuj","GSQwj7hyVv","BGaQYlweGy","DQimprKDLJ","nnP8oJ2mQi","Uvlv4bZLvS","dmoS7O3iyQ","Ul4a1Fhtgl",
-"AOgEeUl4a1","2hEEUlH1kt","lViBvpAhR1","Vprf2jSjS3","BCxeCAOgEe","FVMxoTwano","1LB1LTCgPp","L7cGcdpe1v","xXTI4SWfou","zmLYDzmLYD",
-"Waim6Waim6","8FmFHhSSvQ","Ss0ZuK20wK","OUYuFl83Ud","zmLYDlm0pD","AXpwE9iGoT","FLsphHlUbF","dpe1vpWiOs","Vprf2ix74r","Ul4a1CdyBV",
-"WmadAeuZA5","qaofNRpBQm","qQxHPRkQke","s93MlKASQ8","RACuj5VZjS","xciqpuJScX","FFDui0PktI","SmGzv5Mg9r","Kr8ys7X3uy","y94nwJIqXi",
-"5Mg9rThjNn","9GXkXGrDg7","AkKTkyofH3","Waim6SmGzv","8TxD7dpe1v","O3iyQ7fKYU","NcICA8TxD7","DLhzMmz8gx","tl72WVerEA","kZANm7lUXZ",
-"XyPZNRsQUq","sqVrfX6Pin","d85a9AkKTk","lkMUA1LB1L","ydG8Usoy9t","LewvM48cHL","TCgPpzY1GY","JJs5myvOMI","fqypyMezSW","SjskQyvOMI",
-"MmKGJaDGtS","oGu6xSjskQ","nnP8ouLtKs","W7cTs55rfB","Dz1R3SmGzv","8hJdthe9IA","RmDcrNAFuw","VLTy69XyT9","0BmCyfmIK1","vkCHHtl72W",
-"pFrrlblLA9","jiVBPn1pmO","VIlwPx3LDe","Yw2oU0MR5X","oVQp66q6L9","QnJ1SMaJQs","xXTI464s8N","CxVEf0BmCy","lsQGoyofH3","KZamH8hJdt",
-"rKDLJFVMxo","a00b5UlU3M","NOHsz5iGN5","RxrsmiwzGk","XflUqhUTw7","prNT6Rxrsm","F6PT2lViBv","xXTI4KZamH","0ao3lQnJ1S","16lHcbZLvS",
-"D6rByjfREu","NAFuw24ARF","AkKTkLewvM","ogLgcQWxoT","5drc65VZjS","7fKYUhUTw7","NhXduFcWrW","oGu6xCxVEf","zqH0WwiHrZ","FFDuifLNg8",
-"zFgtBBbwgA","BbwgAdpe1v","uPX7G3weIF","CdyBVRBhp0","Mm8siFLsph","HP433iB08l","ydG8UX6Pin","azIWpxReec","1LB1LRACuj","DcpWBBbwgA",
-"nFqikuTacx","K20wKThjNn","AXpwEAkKTk","tlILts4786","F6PT2lweGy","2Yz7Ev2eC3","BFkb8uQIcz","QssNCuJScX","3otm6G1RhS","3otm64W0Tl",
-"WMiS3YjB9t","Kr8ysWDVWJ","8cVD3jtn0X","2Yz7E5ZaEz","cmXIXRmDcr","W7cTsjfREu","AmdQdZJTXH","fmIK15VZjS","G1RhSEdBKc","gjUTu0Kyfs",
-"WmadAI7p2a","zFgtBVjCZq","QClRLuAWyp","yofH3Chuy3","AkKTkcQOnv","AmdQdLDk6f","iwzGkb29RJ","zqH0WpT8wu","EdBKcyEfy9","pWiOsJ2mQi",
-"BpYhVlsQGo","0YAGHZJTXH","n1pmO7lUXZ","SmGzv0Kyfs","lm0pDiwzGk","uLtKsAmdQd","iqv4kbgJAz","hi5X7m4bxU","gf8rIaL6AJ","D6rByjiVBP",
-"QClRL4W0Tl","8FmFH8RCUA","MmKGJd85a9","0YAGHuN6r3","QWxoTG1RhS","taOXKkZANm","lpF6Ws7Mxk","nFqikd7vjM","64s8NYOfrY","XyPZNzQt6Q",
-"Pb1padjsrv","gf8rI1LB1L","pT8wu1LB1L","aL6AJwDajX","0PktIEoToP","55rfBtvdkD","Yf2EcZuDtD","OUYuFyluBx","NcICARxrsm","RxrsmFLsph",
-"FjHXRlXFOB","Q6hMC1LB1L","FLsphguMb8","aez9yUvlv4","Yf2EcEOE1o","ZuDtDNcICA","uJScXjeskS","2hEEUgtCA5","4QMc9XflUq","5drc6lH1kt",
-"1LB1Lv1Hln","brhlQ0Kyfs","Y1mC0W7cTs","EoToPuupzk","QworuksJby","s7MxkMK07Y","NcICAv2eC3","WreyP2Nslm","iKqhr0MR5X","IBe8kEOE1o",
-"VjCZqjeskS","2DREsHP433","FwEJzjiVBP","nFqikMezSW","1LB1LJRJQB","ZuDtDd7vjM","TCgPpMK07Y","gjUTu4W0Tl","CdyBViqv4k","atef2WPmlx",
-"OHaBzCfgr3","IRh487fKYU","fFDrJuTacx","s93MlGSQwj","4W0TluAWyp","Yw2oU8xEKz","8U2nUrz7Ut","BCxeCKASQ8","64s8NFGzgp","O3iyQuAWyp",
-"xciqpydG8U","TCgPpsoy9t","JXljWMojnP","pmeCdMmKGJ","jSjS3xciqp","K4GS8azIWp","4dEz61v5hH","lkMUAZJTXH","CK5W75Mg9r","DLhzMQWxoT",
-"OUqFMuAWyp","CNHmv7fKYU","9rlg9K20wK","qUJMdAXpwE","qQxHPix74r","5iGN5Uvlv4","Pb1paLDk6f","fmIK1y94nw","oVQp6JJs5m","ZuDtD3otm6",
-"suY4xHP433","euZA52Nslm","Q6Lixrhl0J","MmKGJ7X3uy","ZzJHWlsQGo","zbIYYjeskS","n8pJ97Ow5C","blLA9pv0i7","SWfou0PktI","lweGyXyPZN",
-"KASQ87Ow5C","2TRI7EOE1o","9XyT9y94nw","uLtKsO3iyQ","fcJOyuoStw","HRxd8Chuy3","l83UdXyPZN","rz7Utiqv4k","uTacxZJTXH","faHirMGlTF",
-"gdQsSxXTI4","6AFT0YjB9t","lweGylweGy","cL0aE8U2nU","HfyNQdhSuH","U3yw5lweGy","DLhzM14FLR","jtn0XQChxs","Yf2EcX6Pin","2NslmVLTy6",
-"nlaBycShY2","VjCZqZhwG1","FxX9qAXpwE","4W0TlQnJ1S","Dz1R3yofH3","ciuWzBGaQY","MaJQsyToGW","cQOnvNAFuw","1LB1Ld7vjM","fFDrJlH1kt",
-"lXFOBQssNC","iqv4ktuDyS","48cHLZ4I1v","DG4sTuPX7G","zqH0WRmDcr","Z4I1vJJs5m","Yh1hFZuDtD","FPfSEyvOMI","45cIHiwzGk","cL0aEQChxs",
-"ZhwG19XyT9","sqVrfAIYUu","Kr8yslXFOB","4dEz6lweGy","fcJOy3weIF","CdyBVIn3NS","VjCZqRzaZA","MGlTF48cHL","0PktIGv3Fq","s478614FLR",
-"6q6L9MaJQs","lsQGo0BmCy","gIYvEpvgjS","1v5hHTwano","StlDJokgRi","vkCHH2Yz7E","P6bcgyvOMI","Mkgy8vLsmS","BCxeCMmKGJ","ru4UGhi5X7",
-"pFrrlsoy9t","zz4ZUix74r","HfyNQUmaEv","dmoS7tlILt","HRxd8jSjS3","KsjRKCNHmv","JXljWNhXdu","suY4xEdBKc","jfREuYw2oU","5nmWvrz7Ut",
-"MmsIoU3yw5","n8pJ9ulk41","WmadAt59lR","qaofN9XyT9","OHaBzBFkb8","cL0aEO3iyQ","OUYuFJJs5m","zz4ZUdjsrv","qUJMd45cIH","POUYS64s8N",
-"jiVBPSs0Zu","6q6L9lpF6W","zY1GYEoToP","Yh1hFcmXIX","lpF6WzqH0W","iwzGkoQ87r","1v5hHguMb8","C2IrcbgJAz","azIWpYOfrY","5drc6guMb8",
-"IBe8k618Di","jiVBPlm0pD","tAOsrFFDui","xReecsoy9t","P6bcgW7cTs","d7vjMTa8f6","AXpwElweGy","VBjhzlXFOB","Mm8siMaJQs","v2eC3l83Ud",
-"Nxx9VDQimp","uJScX0ao3l","zz4ZU0YAGH","LDk6fzHF1q","WMiS3prNT6","i7WMQ2DREs","FPfSEZhwG1","G1RhS9XyT9","t98iW9y4lw","m4bxUn8pJ9",
-"dpe1vv2eC3","uPX7GDLhzM","oQ87rZzJHW","lkMUAYOfrY","SmGzvZhwG1","XflUq5Mg9r","uvf7AY1mC0","9GXkX8hJdt","2TRI7GXdoH","uN6r3BbwgA",
-"4dEz6aez9y","lCMxyQWxoT","7X3uylXFOB","BbwgAcL0aE","J2mQioVQp6","piJSkDLhzM","YOfrYOHaBz","IRh48lj07Q","IjTwPMaJQs","8RCUA8hJdt",
-"o8UydVIlwP","piJSkP6bcg","IBe8kdmoS7","MezSWt98iW","WDVWJGv3Fq","AIYUuNOHsz","nnP8oydG8U","pmeCdcL0aE","hYBCKNo0Qb","n1pmO4QMc9",
-"okgRit59lR","l83UdrKDLJ","16lHcL7cGc","m4bxUjfREu","5IhmGHRxd8","cL0aE4QMc9","WDVWJsoy9t","TXQ0Z0PktI","IBe8kHzZT8","bZLvSPb1pa",
-"9GXkXNOHsz","yToGWD6rBy","x3LDeuZPqg","14FLRiwzGk","GWqqXNcICA","8xEKzs7Mxk","xXTI41v5hH","Zv7z08xEKz","ix74r5iGN5","lXFOBFGzgp",
-"gjUTuWPmlx","48cHLqQxHP","blLA9vOqCE","tlILty94nw","fqypyChuy3","s4786W3VFH","gf8rIaDGtS","J2mQiWDVWJ","OUYuFHRxd8","Q6LixVBjhz",
-"K20wKLewvM","b29RJHlUbF","8U2nU5VZjS","HRxd8i7WMQ","fmIK13otm6","0YAGHWaim6","8FmFHvkCHH","In3NSF6PT2","xReeclXFOB","iqv4k2ZHdk",
-"14FLRWmadA","MojnPNxx9V","k85AeWaWsv","rz7UtFhtgl","CqqaDjtn0X","ThjNn0BmCy","Uvlv4BpYhV","oVQp6aL6AJ","WMiS3uoStw","dQ586DG4sT",
-"0h1b1rKDLJ","k85AeGWqqX","9y4lwhSSvQ","618DiHP433","iqv4kcQOnv","LewvMpT8wu","GrDg7fcwDa","5drc6x3LDe","FwEJzs4786","zQt6QWDVWJ",
-"GWqqXn1pmO","NhXdusx5Gl","h1zcHYjB9t","DG4sTNcICA","uQIczs4786","MezSW5Drn0","kB5nPQnJ1S","s7Mxke6e4z","5ZaEzKr8ys","yofH3yToGW",
-"W3VFH3otm6","v1HlnoVQp6","hSSvQGSQwj","oGu6x2Yz7E","Waim6Ul4a1","pAhR1sqVrf","fLNg8ogLgc","2NslmFcWrW","uvf7AU3yw5","5IhmGuTacx",
-"tvdkDMezSW","sqVrf8cVD3","uAWypnlaBy","hE1Ql2Yz7E","IjTwPOUYuF","t59lRm4bxU","mX2GE9XyT9","Q6Lixk85Ae","4QMc9uoStw","zmLYDYw2oU",
-"IRh48zQt6Q","6AFT06q6L9","dQ586KsjRK","dpe1vaez9y","TwanomX2GE","lXFOBMojnP","NhXduzbIYY","6AFT0Q6Lix","pAhR1Vprf2","Z4I1vIn3NS",
-"okgRiuoStw","24ARFcmXIX","zY1GY3weIF","suY4xrKDLJ","lm0pDRsQUq","nlaByjSjS3","0BmCyJRJQB","djsrvEoToP","24ARFhi5X7","5VZjSfLNg8",
-"55rfBHP433","aFFssHRxd8","d85a9ZJTXH","7ku1paDGtS","rKDLJk85Ae","dhSuH7X3uy","v2eC3ReKEW","VBjhzzHF1q","QYxC0WaWsv","8TxD7blLA9",
-"gtCA5pT8wu","W7cTsv2eC3","7ku1pX6Pin","BGaQYi7WMQ","IKxdL7ku1p","2TRI7hUTw7","64s8Nx3LDe","5Drn0pmeCd","16lHcWreyP","F6PT27lUXZ",
-"pmeCdSbRYy","L7cGcpvgjS","ECMvUsoy9t","TCgPpn1pmO","FVMxoKsjRK","5IhmGMaJQs","8TxD75VZjS","ZzJHWyToGW","FLsph24ARF","iwzGkx3LDe",
-"JKWYRxReec","FjHXR5VZjS","l83UdeuZA5","MojnPhi5X7","4dEz6l83Ud","SjskQMaJQs","ZuDtDzY1GY","7Ow5CMezSW","RBhp0a00b5","vLsmSWaWsv",
-"b29RJrz7Ut","prNT61v5hH","djsrvuTacx","HlUbFBCxeC","3otm6uZPqg","8U2nU580YD","gjUTucQOnv","GrDg76q6L9","lj07QCp3mZ","hUTw7MmKGJ",
-"Yh1hFYh1hF","DG4sTWMiS3","9GXkXhYBCK","Cfgr3VNCPd","lpF6WnlaBy","TXQ0ZuQIcz","lCMxyBbwgA","6AFT024ARF","UmaEvhSSvQ","pT8wu29QAz",
-"QworulpF6W","EOE1ouN6r3","B3qemcShY2","tAOsr48cHL","bgJAzsqVrf","hi5X7HlUbF","iB08la00b5","lXFOBo8Uyd","I7p2aU3yw5","EoToPMmKGJ",
-"jfREuZJTXH","In3NSGrDg7","RBhp0MojnP","rKDLJX6Pin","azIWpGrDg7","uvf7AgdQsS","NcICASbRYy","K20wKjtn0X","9XyT9TXQ0Z","JXljWNo0Qb",
-"J2mQiuJScX","jfREu618Di","nlaByguMb8","RsQUq8hJdt","Chuy345cIH","suY4xhUTw7","Nxx9VOUqFM","kB5nPW7cTs","sx5Gl0Kyfs","ECMvUZUnqt",
-"Zv7z0ZJTXH","BFkb8tl72W","uTacxOxWIH","9eoRcqUJMd","7ku1p14FLR","FNYIMBCxeC","0ao3luLtKs","XflUq6q6L9","QChxsaFFss","jS1ajUlU3M",
-"0h1b1y94nw","5IhmGQssNC","tuDySvLsmS","RzaZAzz4ZU","NcICAzHF1q","GrDg7No0Qb","jtn0XF6PT2","BpYhV0Kyfs","zqH0Wsx5Gl","brhlQokgRi",
-"KsjRKfcwDa","s4786yluBx","ZzJHW5nmWv","DG4sTOz8yZ","WMiS3dhSuH","FwEJzUl4a1","uoStwNo0Qb","9rlg94dEz6","vkCHHVprf2","b29RJjiVBP",
-"Uvlv4yofH3","QbxXcWmadA","LbRTHuN6r3","Oz8yZ8hJdt","zHF1qNcICA","I7p2a1v5hH","0PktIWaWsv","jS1ajtvdkD","MGlTFpvgjS","GXdoH2hEEU",
-"JJs5m9iGoT","piJSkguMb8","FVMxoB3qem","64s8NtjQxs","ydG8U8TxD7","VLTy6m4bxU","UlU3M3weIF","yluBx5ZaEz","aFFsszmLYD","Gv3FqDG4sT",
-"G1RhSjtn0X","RACuj7X3uy","BFkb8piJSk","XflUqReKEW","cQOnvAgJHQ","Yw2oUzmLYD","WMiS3faHir","lj07Q0Wr5y","aez9y9iGoT","0MR5XvOqCE",
-"iKqhrHRxd8","64s8N5IhmG","FnPFB64s8N","MK07YAIYUu","bgJAzm4bxU","gdQsSJ2mQi","HzZT8CxVEf","8U2nUMm8si","uoStwD6rBy","lkMUA7Ow5C",
-"lm0pDjSjS3","8RCUAChuy3","lsQGoHfyNQ","MaJQslsQGo","piJSkK4GS8","G1RhSWDVWJ","uoStwtl72W","580YDHlUbF","8cVD35VZjS","fcwDapAhR1",
-"BbwgA5Mg9r","e6e4zaL6AJ","MaJQsi3pyd","MK07Y4W0Tl","IKxdL4dEz6","gtCA5h1zcH","y94nwb29RJ","lH1ktpAhR1","OxWIHs7Mxk","y94nwqaofN",
-"aFFssuvf7A","In3NSs7Mxk","EoToPlm0pD","t98iWBpYhV","DQimpGv3Fq","AOgEeWDVWJ","oQ87rxXTI4","fLNg8K20wK","rz7UttaOXK","he9IAdjsrv",
-"MmsIoyEfy9","5IhmGM6qcG","MaJQspFrrl","POUYSJIqXi","F6PT2GSQwj","n1pmORkQke","VerEAFjHXR","YOfrYMmsIo","rKDLJguMb8","wDajXiKqhr",
-"QssNC5VZjS","GSQwjYw2oU","PYBf42TRI7","yofH39iGoT","faHir8U2nU","xXTI4dmoS7","0YAGH0BmCy","v1HlnjSjS3","P6bcgQClRL","PYBf4vLsmS",
-"0PktIqQxHP","7lUXZcL0aE","JkzUn7fKYU","AkKTkSbRYy","55rfBQYxC0","1v5hHmz8gx","ksJbyqQxHP","fcwDan1pmO","Vprf2YjB9t","RzaZANhXdu",
-"9GXkXvOqCE","YjB9tFGzgp","8TxD7SWfou","brhlQK4GS8","JkzUnS77LH","tjQxsyvOMI","JkzUn5Namm","k85Ae6AFT0","8FmFHgjUTu","FnPFB5Mg9r",
-"guMb8rhl0J","vOqCE0Kyfs","FVMxoFPfSE","9GXkXAIYUu","YOfrY9eoRc","uLtKsBCxeC","i3pydK4GS8","RzaZADz1R3","Vprf2Twano","jS1ajhi5X7",
-"a00b5BCxeC","K20wKhUTw7","sqVrfpmeCd","1LB1LtaOXK","K20wKn8pJ9","Cp3mZKsjRK","dpe1vQ6hMC","SmGzvO3iyQ","he9IA8TxD7","gf8rIfLNg8",
-"8RCUA2Yz7E","FLsph580YD","zFgtBaez9y","aFFssTa8f6","HlUbFMGlTF","Ul4a1lCMxy","WaWsv0h1b1","BbwgAwDajX","ZJTXHFnPFB","aFFssOUYuF",
-"aFFssuTacx","k85Ae2Yz7E","3weIFZv7z0","pmeCdSWfou","suY4xrz7Ut","gjUTu8TxD7","zY1GY1LB1L","Nxx9V48cHL","sx5Gl8RCUA","OUYuFLbRTH",
-"TwanoAOgEe","45cIHStlDJ","aDGtSIjTwP","hUTw7POUYS","CxVEfRzaZA","Q6hMCs4786","vOqCECp3mZ","9rlg9Ss0Zu","2ZHdkRxrsm","9rlg9RsQUq",
-"cmXIXI7p2a","lpF6Wsoy9t","pFrrltlILt","ZuDtDMGlTF","0BmCy7Ow5C","Pb1paMezSW","Gv3FqYjB9t","GrDg7Ss0Zu","hi5X7QnJ1S","HzZT80Kyfs",
-"qaofNzmLYD","lm0pDZ4I1v","CK5W7qUJMd","2ZHdkuN6r3","lkMUARmDcr","EoToPNAFuw","Ta8f6JKWYR","K4GS85VZjS","BCxeCVBjhz","gtCA5aDGtS",
-"7Ow5C8hJdt","x3LDe7ku1p","EdBKchi5X7","rz7UtQ6hMC","Pb1pa0Wr5y","tvdkDdQ586","7Ow5CNxx9V","zmLYDG1RhS","hi5X77X3uy","7hyVvyofH3",
-"lkMUAMGlTF","7fKYUBFkb8","uoStwmz8gx","pT8wuF6PT2","iB08l0h1b1","5drc6JIqXi","vOqCE0MR5X","fqypybrhlQ","ogLgc07n1c","WDVWJuJScX",
-"hUTw7lkMUA","t98iWogLgc","7fKYUd85a9","5VZjSh1zcH","suY4xMezSW","uQIczWPmlx","uQIcziB08l","6q6L9JJs5m","uQIczfcJOy","7lUXZZUnqt",
-"8TxD7jiVBP","hi5X7UlU3M","Q6hMCQ6Lix","IjTwPX6Pin","k85AeVNCPd","HRxd8OUqFM","In3NSJRJQB","HfyNQFcWrW","JIqXik85Ae","Ta8f6t59lR",
-"gjUTuAgJHQ","faHirjeskS","Zv7z05Mg9r","2hEEUBGaQY","0ao3laFFss","o8UydCNHmv","DG4sTIBe8k","kZANmuLtKs","xciqppvgjS","M6qcG9rlg9",
-"HRxd8soy9t","2hEEUbrhlQ","he9IAQChxs","16lHc3otm6","bZLvSSbRYy","Yf2EcAIYUu","e6e4zdQ586","BCxeCJIqXi","QChxscQOnv","6q6L9vkCHH",
-"9iGoTZv7z0","O3iyQRsQUq","6q6L98cVD3","BpYhVdhSuH","jeskS1j5L8","yToGWRmDcr","piJSkRxrsm","IBe8k5nmWv","AmdQdHzZT8","O3iyQJKWYR",
-"ECMvUv1Hln","y94nw5Mg9r","Pb1pa24ARF","7fsYMoGu6x","IRh48uZPqg","CK5W7DLhzM","7hyVvRsQUq","ZhwG1VerEA","J2mQi618Di","uLtKsQClRL",
-"7fKYUhSSvQ","yvOMIYOfrY","lpF6W0Kyfs","taOXKyvOMI","MmsIovOqCE","9iGoTpAhR1","rKDLJJJs5m","soy9tWaim6","OHaBzCIShG","JkzUnpT8wu",
-"qaofNSs0Zu","wDajXQChxs","I7p2aZuDtD","Chuy3Qworu","lweGytuDyS","5nmWvPOUYS","5NammkB5nP","07n1cRmDcr","JRJQBK20wK","ix74rQbxXc",
-"C2IrcF6PT2","qUJMdyofH3","azIWpqQxHP","FFDuitvdkD","yEfy9WreyP","fFDrJSbRYy","HfyNQStlDJ","BFkb8tlILt","ulk41Twano","MGlTFk85Ae",
-"Pb1paBGaQY","AgJHQVLTy6","qQxHPFjHXR","EOE1ofmIK1","RxrsmNOHsz","qQxHPLbRTH","cL0aEs93Ml","pWiOslXFOB","m4bxURzaZA","NhXduhi5X7",
-"CNHmvNo0Qb","lpF6WSjskQ","Oz8yZpFrrl","hi5X7VNCPd","yofH3M6qcG","0BmCyogLgc","fcJOyhe9IA","lXFOBlm0pD","29QAzVIlwP","Chuy3M6qcG",
-"5drc6ydG8U","64s8N0Wr5y","WreyPeuZA5","QWxoTn1pmO","8U2nUOHaBz","9GXkXcQOnv","mz8gxkZANm","0BmCyciuWz","YOfrYS2Dfu","Waim66q6L9",
-"2ZHdkoGu6x","ZJTXHRkQke","n1pmOY1mC0","GWqqXiB08l","HP433i3pyd","hi5X79iGoT","jeskSNAFuw","ulk41a00b5","5IhmGn1pmO","7lUXZBCxeC",
-"JJs5m5Drn0","jiVBPlj07Q","atef27X3uy","0MR5XKr8ys","lkMUAkZANm","W3VFHx3LDe","IRh48NOHsz","atef20BmCy","FhtglvkCHH","oVQp6ZhwG1",
-"lm0pD14FLR","uTacx6AFT0","HP433FcWrW","9GXkX2hEEU","ulk41Ul4a1","5Drn0FLsph","MmKGJQWxoT","nFqikuoStw","uoStwsqVrf","MK07YIRh48",
-"lCMxyjiVBP","uQIczbgJAz","8cVD3ulk41","Waim6In3NS","SjskQHfyNQ","nnP8oYjB9t","zQt6QCqqaD","jzUqRlpF6W","l83Ud4QMc9","64s8N7X3uy",
-"lm0pDVprf2","OUqFMAkKTk","AgJHQydG8U","RmDcrvOqCE","gjUTuMm8si","aDGtSYh1hF","dpe1vGrDg7","MojnP1j5L8","BCxeCv2eC3","ulk415Drn0",
-"pmeCdlm0pD","UmaEvZ4I1v","7Ow5Csoy9t","jfREudpe1v","lXFOBAOgEe","jfREu3otm6","brhlQOHaBz","TwanoP6bcg","TCgPpNAFuw","aL6AJdmoS7",
-"XyPZNi3pyd","AOgEeyofH3","FcWrW0BmCy","ThjNnOHaBz","NhXduLDk6f","8hJdtLDk6f","0PktIoQ87r","ZhwG1nlaBy","yEfy9jtn0X","tvdkD2TRI7",
-"m4bxUJIqXi","uQIcz6AFT0","ZuDtDNo0Qb","NcICA0YAGH","D6rByUvlv4","HP433aez9y","VerEAWmadA","lViBvn8pJ9","7ku1p0YAGH","9GXkXfcJOy",
-"FVMxo14FLR","K20wKblLA9","iwzGkRBhp0","rKDLJhYBCK","DQimpjfREu","7X3uy7X3uy","AIYUuuQIcz","Q6Lix6AFT0","ZJTXHXyPZN","qQxHPtlILt",
-"TXQ0Zh1zcH","gtCA5sx5Gl","FwEJz9XyT9","M3zXLBbwgA","0Kyfs55rfB","9y4lwI7p2a","VerEARACuj","5iGN5QnJ1S","ZJTXHKsjRK","OUqFMzqH0W",
-"dhSuHFPfSE","pAhR1No0Qb","FFDuiyToGW","5iGN5nFqik","y94nwOz8yZ","ZuDtDuAWyp","FVMxofqypy","K4GS8taOXK","FjHXRfcJOy","ksJbyNcICA",
-"RACujfcwDa","POUYStjQxs","dhSuHmz8gx","HRxd88TxD7","AXpwEuQIcz","tvdkDpFrrl","DLhzMFcWrW","Kr8ysatef2","qQxHPd7vjM","zHF1qJ2mQi",
-"dhSuH5iGN5","lm0pDAIYUu","AXpwEmz8gx","GXdoHdmoS7","v2eC3Ta8f6","blLA9yluBx","jtn0XpvgjS","t59lRIjTwP","O3iyQtuDyS","uJScX48cHL",
-"XyPZNdmoS7","gf8rISjskQ","fcwDaNAFuw","pFrrlJkzUn","vOqCEC2Irc","MezSWChuy3","9iGoTVprf2","1j5L8t98iW","9rlg9ulk41","tjQxsuPX7G",
-"BFkb8cL0aE","fFDrJQssNC","ZJTXHIRh48","QWxoTUl4a1","LbRTHMkgy8","F6PT2WaWsv","SmGzvUmaEv","NcICAzFgtB","ksJbyS77LH","AkKTkdpe1v",
-"XyPZNzFgtB","7ku1puTacx","DLhzMOz8yZ","ix74r8xEKz","lViBvs4786","Yw2oUaL6AJ","iqv4kRkQke","2Nslm5IhmG","n8pJ9fcwDa","WPmlxFjHXR",
-"Gv3FqHzZT8","U3yw5uAWyp","FwEJzcQOnv","CxVEf7X3uy","xXTI4RkQke","fqypy2hEEU","vkCHHaez9y","YjB9tK4GS8","yofH3lweGy","uupzkgjUTu",
-"yluBxtuDyS","2Yz7EAOgEe","EdBKcxXTI4","LbRTHChuy3","OxWIH1j5L8","m4bxUdmoS7","zQt6Q2hEEU","EOE1ohUTw7","WaWsvFnPFB","RzaZAC2Irc",
-"24ARFBFkb8","yluBxQClRL","SmGzv4W0Tl","ni2v19y4lw","580YDhYBCK","29QAzvkCHH","kZANmP6bcg","5VZjSFLsph","cmXIX7X3uy","RzaZAO3iyQ",
-"d7vjMbZLvS","W3VFHM3zXL","NhXduydG8U","lH1ktHzZT8","24ARFRsQUq","HzZT8uJScX","HzZT8AkKTk","ydG8USjskQ","DLhzMQnJ1S","HzZT8dmoS7",
-"OxWIHFGzgp","9eoRc2ZHdk","Yf2EcTwano","zmLYDxciqp","JKWYRfmIK1","TwanoECMvU","n1pmOhi5X7","pAhR1JXljW","uZPqgpT8wu","Chuy3B3qem",
-"Cfgr3l83Ud","fLNg89GXkX","cQOnva00b5","hi5X7kB5nP","Chuy3Nxx9V","RACujpFrrl","aez9yWreyP","zqH0WZhwG1","uQIcz24ARF","oGu6xcShY2",
-"Mkgy8FjHXR","7hyVvDLhzM","o8UydJkzUn","FjHXRzQt6Q","QworuBpYhV","jiVBPdmoS7","lj07QWmadA","pT8wut98iW","dhSuH0PktI","55rfBtl72W",
-"4dEz6I7p2a","7X3uy1j5L8","uAWypNxx9V","Gv3Fqa00b5","RxrsmK20wK","EoToPQChxs","CIShGxciqp","oVQp624ARF","lkMUA1v5hH","SbRYylpF6W",
-"8FmFHlkMUA","LbRTHCqqaD","lm0pDSmGzv","NhXduWPmlx","nnP8oAgJHQ","xReecWMiS3","VerEAEOE1o","aez9ytl72W","gdQsS55rfB","mX2GE7fKYU",
-"Ul4a1Waim6","IjTwPyofH3","5nmWvcQOnv","7lUXZBFkb8","IKxdLfcwDa","4dEz6B3qem","i7WMQThjNn","cQOnviwzGk","BbwgAOxWIH","d85a9s7Mxk",
-"BbwgAG1RhS","d7vjMMm8si","Ul4a164s8N","FhtglFFDui","Mm8sin1pmO","580YD16lHc","BCxeCiKqhr","WaWsv2DREs","2DREsChuy3","uAWypcL0aE",
-"QClRLDG4sT","qaofNhSSvQ","nFqikYjB9t","Zv7z0gjUTu","AIYUupT8wu","yToGWLDk6f","ix74rhi5X7","RBhp09XyT9","uupzkn1pmO","64s8NAIYUu",
-"euZA55VZjS","RmDcrMezSW","16lHcs93Ml","GWqqXJRJQB","Yf2Eculk41","Yh1hFbZLvS","2hEEUNo0Qb","MK07YcmXIX","8RCUAC2Irc","oQ87rru4UG",
-"Yh1hFdjsrv","0BmCyksJby","AXpwEcQOnv","CxVEfblLA9","jiVBPQ6Lix","1LB1LZhwG1","CK5W7pAhR1","iB08lQ6Lix","sqVrfB3qem","n8pJ90Kyfs",
-"o8UydhSSvQ","JRJQBiqv4k","ZUnqts4786","lpF6WNxx9V","8TxD7GWqqX","VerEAqUJMd","JkzUnnnP8o","fmIK1HP433","AOgEelj07Q","IjTwPxReec",
-"55rfBLbRTH","QssNCtvdkD","RkQkejtn0X","I7p2aFjHXR","nlaBygjUTu","KZamHWaWsv","tl72WHfyNQ","lViBvCdyBV","hYBCKMojnP","vOqCEfFDrJ",
-"48cHL4dEz6","M6qcGpWiOs","AXpwEdQ586","HlUbFFFDui","WDVWJYh1hF","NcICA8xEKz","uupzkJXljW","2TRI7ru4UG","14FLRBCxeC","Oz8yZMojnP",
-"FGzgpS2Dfu","ydG8UUl4a1","Mkgy8zY1GY","0Wr5yYw2oU","ZzJHWNOHsz","TCgPpuQIcz","DG4sTTwano","fmIK1VLTy6","n8pJ98U2nU","uTacxuvf7A",
-"CqqaDzmLYD","piJSk5ZaEz","n8pJ9VjCZq","RmDcr0PktI","Ul4a1lpF6W","gjUTulCMxy","MmKGJ07n1c","uJScXtuDyS","hi5X7uLtKs","FwEJz16lHc",
-"UmaEvrz7Ut","gjUTuQWxoT","pmeCdZuDtD","Mkgy8ZUnqt","v8yFNQYxC0","zbIYYIjTwP","7fKYU5IhmG","ThjNn9y4lw","7fsYMQnJ1S","Uvlv4pAhR1",
-"JkzUnru4UG","07n1cSWfou","zFgtBMK07Y","5iGN5QClRL","JkzUnLewvM","fmIK1MojnP","618DipWiOs","SbRYynlaBy","MmsIozmLYD","KASQ8Ta8f6",
-"5drc60h1b1","FNYIMrz7Ut","Waim6CqqaD","FVMxolViBv","azIWp0MR5X","NAFuwJRJQB","jS1ajuoStw","euZA5nnP8o","xciqp4W0Tl","jtn0XlweGy",
-"djsrvlm0pD","mz8gxzbIYY","jeskSQ6hMC","jfREuTwano","0YAGHSs0Zu","lm0pDhE1Ql","dQ586Cp3mZ","UmaEvOUYuF","SbRYyksJby","29QAzkB5nP",
-"yluBx7Ow5C","Chuy3cShY2","zY1GYydG8U","kZANmzmLYD","ZUnqt0YAGH","B3qem5Mg9r","ZhwG1s7Mxk","5nmWv5VZjS","X6PinIjTwP","Cfgr3MaJQs",
-"W3VFHQ6Lix","16lHcdQ586","9y4lwHRxd8","h1zcH48cHL","Kr8ysP6bcg","v1Hln29QAz","ZJTXHiwzGk","G1RhScShY2","lsQGouoStw","vLsmSjtn0X",
-"CNHmviKqhr","hYBCKXyPZN","WmadAqaofN","pvgjSAOgEe","hSSvQmz8gx","xXTI4yToGW","zFgtBFxX9q","CxVEfzY1GY","NOHsz0PktI","J2mQiFLsph",
-"2Yz7EyvOMI","VIlwPQworu","ThjNn14FLR","5drc60MR5X","BGaQYlsQGo","Ul4a1mX2GE","55rfBuZPqg","oGu6xdhSuH","vkCHHU3yw5","cQOnvk85Ae",
-"IBe8klkMUA","0h1b1Chuy3","8RCUAzbIYY","4W0Tlsoy9t","IjTwP2DREs","ogLgcWDVWJ","nnP8oh1zcH","pT8wuzmLYD","cShY2HlUbF","QYxC0WmadA",
-"7ku1pzz4ZU","fmIK1guMb8","5Drn0lweGy","S77LHSmGzv","m4bxU29QAz","zbIYYiB08l","14FLRpT8wu","UlU3M55rfB","8cVD3e6e4z","FLsphzqH0W",
-"7fKYUDG4sT","uZPqgZJTXH","FxX9qRxrsm","EoToP1LB1L","618DiTXQ0Z","prNT6JXljW","EdBKccmXIX","580YDpAhR1","vLsmSpWiOs","GSQwjlViBv",
-"5drc6soy9t","FGzgpVerEA","0PktIogLgc","s7Mxk0MR5X","CK5W7aFFss","uZPqgyofH3","55rfBpT8wu","s93MlRzaZA","LDk6fMmsIo","i7WMQ8FmFH",
-"YjB9tazIWp","AgJHQMmKGJ","dpe1vydG8U","cShY2jtn0X","ru4UG1v5hH","pWiOs4W0Tl","IjTwP29QAz","QnJ1SSmGzv","RsQUqi7WMQ","jeskSI7p2a",
-"EoToPRmDcr","lkMUAfLNg8","dhSuHzz4ZU","iqv4kJkzUn","JkzUnqQxHP","HzZT8M6qcG","uZPqggdQsS","vkCHHzFgtB","IBe8kKASQ8","pT8wugIYvE",
-"zHF1qbgJAz","0ao3lJ2mQi","AkKTkCK5W7","gIYvEYjB9t","AmdQdn1pmO","KZamH45cIH","v2eC32ZHdk","zY1GYpmeCd","jzUqRfaHir","v8yFNi7WMQ",
-"QworublLA9","lweGya00b5","07n1cCdyBV","ZJTXHIBe8k","ulk41RsQUq","POUYSaez9y","HfyNQPb1pa","W3VFHIBe8k","2TRI7ulk41","OUqFMlweGy",
-"rz7UtlsQGo","QWxoTRkQke","Q6hMCuoStw","0ao3lU3yw5","y94nwuvf7A","7lUXZblLA9","atef2IjTwP","bZLvSS77LH","OxWIHPOUYS","S77LHrKDLJ",
-"IRh48qQxHP","WmadAWmadA","gdQsSY1mC0","8FmFHCqqaD","ksJbyKASQ8","uZPqgtlILt","Uvlv4jS1aj","xReectaOXK","atef29y4lw","14FLRqQxHP",
-"TCgPpwiHrZ","HRxd8M6qcG","s4786EdBKc","W7cTsa00b5","VerEAL7cGc","NAFuw618Di","TCgPpni2v1","EdBKcFnPFB","Vprf28FmFH","uAWypgtCA5",
-"s7MxkfFDrJ","lCMxy64s8N","Chuy3zQt6Q","uoStwIKxdL","KsjRKYjB9t","MojnPEoToP","MK07YpWiOs","4QMc9zFgtB","IBe8kFFDui","n8pJ9U3yw5",
-"euZA5uN6r3","In3NSciuWz","jfREuwiHrZ","zQt6QLewvM","kB5nPMmKGJ","zHF1qfLNg8","MezSWoVQp6","EOE1ojSjS3","GrDg7POUYS","M3zXLhi5X7",
-"aDGtSIn3NS","nFqikhE1Ql","lpF6WMezSW","8FmFHzqH0W","lViBvpv0i7","TXQ0ZbrhlQ","24ARFKZamH","Oz8yZt98iW","CIShG0PktI","okgRigIYvE",
-"14FLRGWqqX","FPfSECqqaD","ciuWzVLTy6","5Mg9rzHF1q","0h1b14W0Tl","pAhR1lj07Q","QbxXcMmsIo","VIlwPjSjS3","euZA5QssNC","a00b5NhXdu",
-"FFDuiokgRi","GSQwjY1mC0","k85Aesx5Gl","5drc6lweGy","bZLvSZzJHW","uupzkF6PT2","RACuj618Di","mX2GEIRh48","MaJQsfcwDa","RpBQmQ6hMC",
-"pvgjSm4bxU","gtCA5Waim6","BGaQY24ARF","ZuDtDReKEW","LbRTHlm0pD","b29RJYf2Ec","Y1mC0rKDLJ","hYBCK7fsYM","lkMUAAmdQd","Q6LixuoStw",
-"fFDrJAkKTk","FFDuisqVrf","8TxD7NhXdu","n1pmOaL6AJ","CNHmvO3iyQ","s93Mlsoy9t","kB5nP2Yz7E","qaofNn1pmO","55rfBdQ586","Waim6IRh48",
-"8hJdtZhwG1","brhlQ7X3uy","iKqhrhYBCK","suY4xb29RJ","gtCA5s7Mxk","14FLRzqH0W","x3LDe9XyT9","FLsphP6bcg","Kr8ysokgRi","M6qcG7Ow5C",
-"618Disx5Gl","ZhwG1EoToP","JXljWZv7z0","U3yw5uPX7G","IjTwPEoToP","fLNg8l83Ud","sx5GlRBhp0","Yh1hFOUqFM","580YD9eoRc","ogLgc5Mg9r",
-"1j5L8QYxC0","LDk6fDQimp","uoStwGWqqX","5nmWvWPmlx","t59lRpmeCd","jSjS3AmdQd","uLtKslXFOB","24ARFt59lR","y94nwGrDg7","ciuWze6e4z",
-"TXQ0ZtAOsr","aL6AJ3weIF","lXFOBfcwDa","h1zcHPOUYS","o8UyduoStw","NOHszv2eC3","8xEKzJKWYR","KZamH7Ow5C","s4786LewvM","FLsphpiJSk",
-"FxX9qtvdkD","zmLYDJIqXi","lXFOBzHF1q","qQxHPtaOXK","ulk41ZJTXH","pWiOsK4GS8","JKWYRKsjRK","B3qemsx5Gl","uvf7AHP433","i7WMQhi5X7",
-"QYxC05VZjS","FLsphFwEJz","a00b5QYxC0","uN6r35IhmG","ZhwG1HzZT8","0YAGHjS1aj","9y4lwY1mC0","Y1mC0zz4ZU","aDGtS1j5L8","AOgEeuupzk",
-"Pb1paXyPZN","SbRYyVNCPd","fcwDaSbRYy","0YAGHIRh48","v2eC3nFqik","gIYvE1LB1L","C2Ircpv0i7","0YAGHaez9y","3weIF5Namm","Q6LixwDajX",
-"RBhp07fsYM","S77LHDcpWB","1LB1LZJTXH","DLhzM5nmWv","5nmWvzQt6Q","aFFsszFgtB","Gv3FqFjHXR","Ul4a1hSSvQ","iwzGk8RCUA","Z4I1vjSjS3",
-"y94nwokgRi","JkzUnTa8f6","YOfrY7fsYM","MmKGJrKDLJ","1j5L8VIlwP","jzUqRU3yw5","Kr8yszbIYY","G1RhSOz8yZ","KZamHx3LDe","nlaByIRh48",
-"YjB9tZzJHW","RpBQmiwzGk","45cIH5drc6","8xEKzvkCHH","zz4ZUSWfou","Yf2EcCIShG","ciuWzDG4sT","5Mg9rt59lR","CxVEfMm8si","1LB1L4QMc9",
-"Ta8f664s8N","CdyBVZ4I1v","pT8wuMGlTF","QChxsuTacx","CK5W7JJs5m","MezSWsqVrf","M6qcGRsQUq","tlILt55rfB","ZUnqtxXTI4","Vprf2BpYhV",
-"he9IAoQ87r","yluBxhYBCK","aDGtStAOsr","0PktID6rBy","fmIK1v8yFN","xciqpW7cTs","yofH3FjHXR","WaWsvrKDLJ","vkCHHLDk6f","KZamHKsjRK",
-"Yw2oUrz7Ut","o8UydPb1pa","he9IARpBQm","8RCUAJkzUn","VIlwP24ARF","pT8wuDz1R3","DcpWBReKEW","SbRYy7ku1p","lCMxy14FLR","uTacxK20wK",
-"QworuMezSW","m4bxU7Ow5C","qUJMdF6PT2","aDGtSpFrrl","55rfBxciqp","45cIHv2eC3","ReKEW6q6L9","mz8gxbgJAz","bZLvS55rfB","GSQwjxReec",
-"gjUTuIjTwP","uoStwNAFuw","VIlwPhe9IA","hYBCKQ6hMC","uoStwblLA9","WDVWJQYxC0","jtn0XMezSW","cQOnvaL6AJ","RxrsmVLTy6","8cVD38U2nU",
-"uQIczlj07Q","SWfoublLA9","Q6LixIRh48","zmLYD5VZjS","iwzGkeuZA5","cQOnvEOE1o","2hEEUFLsph","cL0aEGXdoH","YjB9tRsQUq","W7cTsVprf2",
-"VerEA0ao3l","M6qcG5Namm","aL6AJuJScX","K20wKzFgtB","UmaEvlCMxy","JJs5mEdBKc","SWfouQClRL","AgJHQvOqCE","45cIHKZamH","gIYvEOz8yZ",
-"FcWrWQ6hMC","WaWsvCNHmv","55rfBPYBf4","faHirgf8rI","MmKGJdQ586","FjHXREOE1o","zQt6QIBe8k","sx5GlnlaBy","hYBCKBbwgA","lpF6WMaJQs",
-"5ZaEzQChxs","k85AeDcpWB","Yf2EcFVMxo","4QMc9uN6r3","9rlg9M3zXL","dQ586Zv7z0","FxX9qcQOnv","iB08lhE1Ql","Nxx9VDG4sT","Twanoi3pyd",
-"TXQ0Z580YD","2ZHdke6e4z","0YAGHGWqqX","k85AeZuDtD","2DREs0Kyfs","hSSvQFVMxo","CNHmvhSSvQ","SjskQrKDLJ","CIShGDcpWB","HlUbFcQOnv",
-"DQimpVprf2","FNYIMKZamH","K4GS8sqVrf","DG4sTKr8ys","iwzGkB3qem","tAOsrNOHsz","9XyT9gf8rI","gtCA5qQxHP","lkMUAY1mC0","WDVWJFjHXR",
-"FNYIMtjQxs","NhXduqUJMd","s7MxkfLNg8","vOqCEMaJQs","4dEz62TRI7","ZUnqtlCMxy","8xEKz2TRI7","FjHXRi7WMQ","yluBx8hJdt","GWqqXVprf2",
-"dQ586ZuDtD","4dEz6xReec","nlaByjzUqR","aFFssJJs5m","55rfBQworu","aDGtSUvlv4","QChxs7fKYU","guMb8nFqik","aDGtSFNYIM","UlU3MqaofN",
-"fLNg8SWfou","vLsmSpv0i7","pWiOs7ku1p","fcwDaJXljW","RsQUq8FmFH","oQ87rQYxC0","GXdoHCqqaD","l83UdsqVrf","KZamH2hEEU","Q6hMCHzZT8",
-"AmdQdFVMxo","CIShGLewvM","zqH0WlViBv","2Yz7EuN6r3","Yf2EcFhtgl","RBhp0FjHXR","UlU3MKr8ys","nlaBy0BmCy","i7WMQWaim6","bgJAzYf2Ec",
-"lj07QlweGy","BGaQYbZLvS","SmGzvl83Ud","h1zcHrhl0J","guMb8tAOsr","k85Aemz8gx","RBhp08cVD3","S77LH0BmCy","iKqhr14FLR","ECMvUkB5nP",
-"RkQke2TRI7","FcWrWtAOsr","fFDrJY1mC0","fcwDa0Kyfs","W7cTsZv7z0","dmoS7U3yw5","jfREuvOqCE","dhSuH8FmFH","Yf2Ecy94nw","AmdQdEdBKc",
-"OUqFMnnP8o","HRxd8OxWIH","Pb1paRpBQm","dmoS7ThjNn","FxX9q2hEEU","ciuWzIn3NS","24ARFQbxXc","TCgPpRzaZA","RACujVjCZq","RkQkecQOnv",
-"uupzkfmIK1","Pb1paOHaBz","dhSuHLewvM","2Yz7EzQt6Q","lkMUAeuZA5","ksJbyMkgy8","TwanoW7cTs","ulk412Yz7E","dQ5862Nslm","fcJOyNAFuw",
-"DG4sTqQxHP","GrDg7FVMxo","EoToPMGlTF","B3qem7fsYM","BCxeCQWxoT","Chuy38U2nU","O3iyQdjsrv","VIlwPzbIYY","HlUbF64s8N","580YDwDajX",
-"SjskQNcICA","dhSuHd7vjM","Yf2Eclm0pD","e6e4z0MR5X","lsQGoYjB9t","v1Hln2TRI7","BpYhVNOHsz","fFDrJm4bxU","FVMxoRpBQm","LDk6fl83Ud",
-"W3VFH8FmFH","v8yFNCqqaD","7Ow5COxWIH","POUYSlkMUA","5VZjSFVMxo","yToGWv2eC3","oVQp62DREs","FjHXRGWqqX","Yw2oUEoToP","7hyVv5VZjS",
-"xReechSSvQ","RzaZAs7Mxk","DG4sTk85Ae","euZA5jfREu","VLTy6soy9t","brhlQVjCZq","a00b5AIYUu","5Drn0Twano","FjHXRv2eC3","hSSvQQClRL",
-"xciqp7fsYM","suY4xru4UG","9y4lwokgRi","rKDLJMmsIo","DQimpmX2GE","KZamHTXQ0Z","yEfy9QChxs","lkMUAbrhlQ","DQimphE1Ql","TCgPpo8Uyd",
-"EOE1oIjTwP","VNCPd2hEEU","v1Hlnl83Ud","UlU3MyluBx","0KyfsFwEJz","CIShG2ZHdk","SWfoulsQGo","QnJ1SFwEJz","YjB9tgjUTu","9GXkXqaofN",
-"9y4lwlj07Q","ciuWzcL0aE","FnPFBzz4ZU","nnP8oAkKTk","ZJTXHFwEJz","BpYhVQssNC","Mm8sicQOnv","rKDLJ7lUXZ","JJs5mblLA9","lXFOBHzZT8",
-"Kr8ysSbRYy","soy9t4dEz6","nnP8ok85Ae","JkzUnS2Dfu","guMb8jiVBP","FwEJzfqypy","BpYhVMezSW","KsjRKx3LDe","tl72WSbRYy","jfREublLA9",
-"1LB1L5ZaEz","GWqqXy94nw","L7cGcdmoS7","gjUTuhYBCK","VjCZq1v5hH","24ARF2DREs","5VZjS1LB1L","EoToPuAWyp","M3zXLjtn0X","hi5X7tl72W",
-"W7cTssx5Gl","nnP8oxciqp","2Yz7EazIWp","G1RhS7hyVv","atef29iGoT","PYBf4azIWp","JkzUnogLgc","WMiS3KsjRK","5iGN5VBjhz","nnP8ohUTw7",
-"guMb8uoStw","pvgjSReKEW","uoStwuJScX","Mkgy8Rxrsm","jtn0Xiqv4k","m4bxUTa8f6","RpBQmAmdQd","Mm8si9y4lw","bZLvS8FmFH","RBhp02Yz7E",
-"jzUqR0Kyfs","8cVD31j5L8","CK5W7o8Uyd","MmsIoguMb8","zbIYY8U2nU","SjskQStlDJ","6AFT09iGoT","VerEAQ6Lix","24ARFNxx9V","RBhp0XflUq",
-"K4GS83weIF","0MR5XQYxC0","1v5hHAOgEe","dQ586QbxXc","BFkb8NOHsz","MezSWJIqXi","hE1QlPYBf4","VNCPds4786","suY4xtjQxs","MezSWTwano",
-"24ARFsuY4x","ZJTXHwDajX","GrDg79rlg9","BbwgAJ2mQi","s47869eoRc","FjHXRG1RhS","Mkgy8ulk41","yofH3GWqqX","ru4UGK4GS8","JKWYRRsQUq",
-"EoToP0Kyfs","gtCA59eoRc","fcJOyvkCHH","SjskQ4dEz6","n1pmOjzUqR","F6PT2zHF1q","gtCA5SjskQ","gtCA59rlg9","fqypywDajX","MaJQsDLhzM",
-"1LB1LJKWYR","lweGy5VZjS","tl72W4dEz6","d85a90ao3l","No0QbMezSW","oQ87rReKEW","Y1mC0DQimp","9GXkXGXdoH","5VZjSjiVBP","O3iyQ7hyVv",
-"FwEJzgIYvE","ix74rogLgc","RkQket59lR","TCgPpQbxXc","MGlTFOUYuF","lpF6WcShY2","e6e4zaez9y","Yw2oUxReec","qaofNEoToP","OUqFMlpF6W",
-"KZamH5IhmG","In3NS0YAGH","QYxC0CNHmv","GXdoHokgRi","tlILtG1RhS","xXTI4dQ586","fLNg8oVQp6","SmGzvlj07Q","d7vjMgtCA5","ThjNnRBhp0",
-"aez9yJ2mQi","VBjhzHRxd8","qQxHP0h1b1","Mm8si1j5L8","lH1ktIBe8k","0h1b1pv0i7","dQ586KZamH","IKxdLLewvM","29QAzpAhR1","VLTy6RzaZA",
-"zQt6QfmIK1","AkKTkAXpwE","MGlTFMm8si","h1zcHPYBf4","Yh1hFEoToP","5VZjSK4GS8","ru4UG0BmCy","4QMc9JkzUn","FLsphaDGtS","NOHszSjskQ",
-"i7WMQW7cTs","VNCPd0YAGH","MaJQsoGu6x","GSQwjSmGzv","brhlQe6e4z","9rlg9lXFOB","xXTI4OUYuF","pvgjSBCxeC","ni2v17fKYU","guMb8brhlQ",
-"EoToP6q6L9","NOHszpvgjS","SbRYyqUJMd","FwEJzfaHir","v1Hln9iGoT","CNHmvnnP8o","Ul4a1LDk6f","ReKEWUmaEv","MK07Ys93Ml","QworuM3zXL",
-"RsQUqdmoS7","Pb1paRsQUq","sx5GluLtKs","zFgtBGXdoH","uLtKslH1kt","ZuDtDKr8ys","nFqikbgJAz","vkCHHJJs5m","yvOMIRkQke","MezSWxciqp",
-"7ku1p0BmCy","xXTI4WaWsv","zmLYDDLhzM","sqVrfbrhlQ","rz7Utru4UG","i7WMQ48cHL","wDajXzQt6Q","5iGN5EdBKc","8TxD7d7vjM","EOE1obZLvS",
-"UmaEvECMvU","Waim6JKWYR","uPX7G2Yz7E","uoStw1j5L8","AmdQdt98iW","VBjhzO3iyQ","lm0pD9rlg9","618Di9XyT9","LbRTHzHF1q","d85a9FGzgp",
-"jeskSDG4sT","IjTwPa00b5","RBhp0WmadA","GWqqXNOHsz","pT8wuZzJHW","Cp3mZlkMUA","qQxHP8U2nU","pWiOsNxx9V","zmLYDFFDui","8TxD7xReec",
-"dQ586FNYIM","fLNg8NcICA","Zv7z0D6rBy","ZJTXHiB08l","HP433nFqik","618Di8cVD3","QYxC0atef2","pmeCdThjNn","POUYSni2v1","4dEz6ksJby",
-"uupzkBFkb8","o8UydAmdQd","DQimpzbIYY","rKDLJThjNn","5VZjShe9IA","lsQGo8FmFH","wDajXvOqCE","F6PT2Yf2Ec","s7MxknnP8o","lm0pDYh1hF",
-"EoToPix74r","CdyBVtl72W","8RCUAdmoS7","5ZaEzNOHsz","FnPFBs93Ml","FcWrWhi5X7","lkMUA24ARF","CqqaDuoStw","lweGycQOnv","1v5hHlViBv",
-"FhtglS2Dfu","JkzUnlCMxy","xXTI4aL6AJ","JXljW1j5L8","hSSvQIBe8k","4W0TlJJs5m","45cIHksJby","7fsYMtAOsr","iqv4kd85a9","dQ5869GXkX",
-"t59lRuoStw","Yf2EczY1GY","P6bcgsx5Gl","ZuDtDfcJOy","ZhwG1ciuWz","ciuWzoQ87r","d85a99rlg9","zmLYDrz7Ut","IjTwPMGlTF","1j5L86q6L9",
-"l83UdMm8si","9iGoT2ZHdk","8cVD329QAz","zQt6Q2TRI7","v2eC3GWqqX","Kr8ysQYxC0","yofH3OHaBz","4W0TlP6bcg","Ul4a1suY4x","DcpWBn8pJ9",
-"fLNg8BbwgA","xciqpRmDcr","SbRYyRzaZA","hUTw7vOqCE","WmadAChuy3","K20wKsqVrf","M6qcGSWfou","DLhzMBpYhV","B3qem5VZjS","EoToP4dEz6",
-"IRh48Zv7z0","6AFT0MGlTF","AgJHQQbxXc","HzZT8OHaBz","AmdQdCK5W7","JXljWiKqhr","Pb1paCNHmv","mX2GEFVMxo","Mkgy8QYxC0","i3pyd8cVD3",
-"580YDTwano","WmadAn1pmO","uPX7GuQIcz","RzaZAD6rBy","cShY2oGu6x","DQimp7fKYU","jzUqRTXQ0Z","gdQsS8hJdt","Nxx9V64s8N","lH1ktEoToP",
-"RsQUqAkKTk","sqVrfCfgr3","RmDcrvkCHH","pmeCdguMb8","K20wKQbxXc","2Yz7EdhSuH","QworuydG8U","ix74rQssNC","7X3uylm0pD","zmLYD1LB1L",
-"AIYUu5Mg9r","o8Uyd7fKYU","0PktI5nmWv","RsQUqe6e4z","5nmWvvLsmS","DQimphUTw7","StlDJPYBf4","xXTI4MGlTF","fcJOyHRxd8","yEfy9YOfrY",
-"64s8NaL6AJ","tl72Wo8Uyd","Vprf2Mm8si","fLNg8he9IA","2hEEU9eoRc","C2IrcSbRYy","brhlQulk41","blLA9OUqFM","ix74rW3VFH","IjTwPI7p2a",
-"fFDrJO3iyQ","ydG8Uy94nw","2hEEUeuZA5","pAhR1tAOsr","iKqhryEfy9","7fsYMZJTXH","5Mg9rhe9IA","t59lRaez9y","v2eC3v2eC3","Vprf2djsrv",
-"pmeCduoStw","SWfouHfyNQ","0YAGHFPfSE","jiVBPgdQsS","HzZT8lj07Q","tAOsrJkzUn","s93MluN6r3","atef2v8yFN","5Drn0prNT6","ZJTXHmz8gx",
-"8cVD3KASQ8","5iGN59GXkX","WaWsvkZANm","yToGWQnJ1S","JJs5mNxx9V","FFDuiQWxoT","5VZjSqaofN","5Mg9rDG4sT","ECMvU0Wr5y","YjB9t7X3uy",
-"TXQ0ZSbRYy","xciqplweGy","Waim6dhSuH","fLNg8GXdoH","In3NS2Nslm","IRh48xReec","JRJQBVLTy6","lXFOBVjCZq","MmKGJdpe1v","JRJQBFVMxo",
-"JRJQBmz8gx","K20wKFnPFB","v8yFNOHaBz","K4GS8WPmlx","3weIFoGu6x","YOfrYfFDrJ","Uvlv4sx5Gl","SjskQMmsIo","TXQ0ZNOHsz","AOgEerz7Ut",
-"hYBCKbgJAz","zHF1qyToGW","uupzkpT8wu","gtCA5hUTw7","8hJdtnlaBy","hUTw7pvgjS","XyPZNCIShG","QChxssuY4x","Pb1pavkCHH","FPfSEQworu",
-"rz7UtVBjhz","djsrvFxX9q","cQOnvP6bcg","FPfSE0ao3l","0PktIe6e4z","NhXdu9GXkX","lkMUAqUJMd","ZUnqtyluBx","tlILtciuWz","BFkb8faHir",
-"RxrsmiB08l","pv0i70BmCy","Q6LixVLTy6","7hyVvBGaQY","5nmWv618Di","29QAzb29RJ","dhSuHvOqCE","J2mQiGv3Fq","VjCZqlCMxy","Oz8yZSs0Zu",
-"rKDLJgdQsS","J2mQifmIK1","h1zcHMaJQs","he9IANcICA","tlILtcQOnv","5IhmGRmDcr","zbIYYWmadA","S77LHZuDtD","OHaBzIjTwP","s7MxkKr8ys",
-"fLNg8qaofN","tl72WfLNg8","RsQUqokgRi","CK5W7HfyNQ","GSQwjOz8yZ","QYxC02TRI7","2TRI7IKxdL","Mkgy8rKDLJ","BpYhVQClRL","jtn0XHzZT8",
-"HfyNQuZPqg","hUTw7kZANm","ZhwG1n8pJ9","zmLYDFVMxo","zQt6QyvOMI","UlU3MvkCHH","QnJ1StAOsr","16lHcQ6Lix","uZPqgTa8f6","fmIK1Cp3mZ",
-"tl72W07n1c","WaWsvDLhzM","16lHce6e4z","VLTy6hSSvQ","RkQkeFcWrW","Mkgy8JKWYR","ix74r0PktI","b29RJlViBv","8RCUAZzJHW","JKWYRsx5Gl",
-"t98iWQworu","YjB9ts4786","2Yz7E7hyVv","W7cTsvkCHH","3weIFStlDJ","uoStwReKEW","HzZT8cL0aE","l83UdprNT6","pT8wutuDyS","fFDrJAmdQd",
-"ni2v1s4786","jfREuv2eC3","8U2nUYjB9t","i7WMQJIqXi","ZuDtDh1zcH","taOXKh1zcH","MGlTFDcpWB","t98iWgtCA5","5IhmGcL0aE","FnPFB16lHc",
-"JJs5mNhXdu","YjB9t7fsYM","okgRisoy9t","AmdQduZPqg","5ZaEzgjUTu","yluBxIRh48","vkCHHjS1aj","Q6LixBFkb8","FwEJzThjNn","VBjhzFGzgp",
-"vLsmSKr8ys","KASQ8RzaZA","VLTy69iGoT","I7p2aiB08l","oQ87r9eoRc","JRJQBtl72W","s93Mli7WMQ","QClRLpmeCd","24ARFv1Hln","ksJbytAOsr",
-"gtCA5S2Dfu","Ul4a1cL0aE","FVMxoVprf2","45cIHGXdoH","zY1GYSWfou","WMiS316lHc","tuDySeuZA5","Vprf2YOfrY","MaJQs14FLR","x3LDeRpBQm",
-"RACujNhXdu","lkMUAB3qem","EoToPOUYuF","2DREsrKDLJ","OUYuF2DREs","l83UduJScX","dpe1vDz1R3","S2DfuTwano","pv0i7iKqhr","AkKTkYOfrY",
-"pmeCdzmLYD","1LB1LQWxoT","DG4sTFnPFB","QYxC09GXkX","Ss0ZuMaJQs","5IhmGTa8f6","5nmWvAIYUu","MGlTFQChxs","hYBCKyvOMI","n1pmOWaim6",
-"3otm6aDGtS","DLhzMfqypy","WreyPvLsmS","MezSWYh1hF","MK07YtjQxs","BpYhVGXdoH","Waim6k85Ae","RsQUqyvOMI","JIqXijS1aj","cL0aEprNT6",
-"MGlTFazIWp","K20wKRBhp0","gdQsSBCxeC","lsQGoxciqp","xXTI4BbwgA","BbwgApiJSk","5nmWvVIlwP","wiHrZS77LH","RpBQmcQOnv","580YDciuWz",
-"kB5nPTa8f6","S77LHG1RhS","gtCA56AFT0","WaWsvKZamH","uTacxDz1R3","Yf2Ectl72W","24ARFJXljW","MezSW14FLR","FLsphWmadA","pT8wuFGzgp",
-"pT8wuJkzUn","BpYhVyEfy9","Mkgy8fcwDa","prNT6UmaEv","GSQwj45cIH","zQt6Q8TxD7","d7vjM2hEEU","VNCPd5Drn0","LDk6fNxx9V","cmXIXOUqFM",
-"lj07QThjNn","yluBxlweGy","MGlTFNOHsz","45cIHQbxXc","hE1Ql1j5L8","0h1b1hYBCK","S77LHYf2Ec","gdQsSO3iyQ","Q6hMC14FLR","FLsphWaWsv",
-"tuDySEoToP","ECMvUKASQ8","5IhmGSjskQ","DG4sT24ARF","y94nwCp3mZ","Ss0ZuHlUbF","5Mg9rhE1Ql","5Drn0D6rBy","QYxC05Namm","CqqaDdpe1v",
-"uAWypcmXIX","0PktIS2Dfu","aez9yHRxd8","HzZT8ksJby","Q6LixfFDrJ","faHirFhtgl","FjHXRWaWsv","No0QbprNT6","IjTwPru4UG","k85AeQbxXc",
-"RzaZA5ZaEz","KsjRKJRJQB","rz7UtThjNn","2hEEUuQIcz","5NammFxX9q","bZLvSRpBQm","ogLgcQworu","FLsphMmKGJ","tlILtn8pJ9","ThjNnfFDrJ",
-"7ku1plpF6W","Rxrsmrz7Ut","HRxd8HRxd8","M3zXLVNCPd","lViBvjfREu","DcpWBStlDJ","D6rByK4GS8","jfREu14FLR","yluBx0Wr5y","FwEJza00b5",
-"jSjS3a00b5","C2IrcrKDLJ","jiVBPjS1aj","Ta8f62hEEU","QWxoTaez9y","WPmlx5ZaEz","jzUqRYw2oU","qaofNblLA9","ZzJHW8FmFH","7fKYUWaWsv",
-"KZamHFPfSE","uJScXL7cGc","vkCHHNOHsz","9eoRcJ2mQi","StlDJ1v5hH","ThjNnlpF6W","guMb8L7cGc","jzUqRzbIYY","tjQxsh1zcH","ZJTXHn8pJ9",
-"OxWIHcShY2","MmKGJU3yw5","CIShG29QAz","gf8rIogLgc","8TxD7zmLYD","ix74raez9y","taOXKs93Ml","QChxsS2Dfu","oGu6xnlaBy","WDVWJjeskS",
-"ciuWz2Nslm","d7vjMHfyNQ","0h1b1vkCHH","cShY2HRxd8","Vprf2lCMxy","FGzgpKASQ8","Z4I1vn8pJ9","sqVrfoQ87r","NAFuwRBhp0","xciqpVerEA",
-"fqypy5drc6","IBe8kjSjS3","Cfgr3gIYvE","tjQxsHRxd8","suY4x4QMc9","4QMc9KASQ8","Yf2EcoVQp6","CK5W7ZuDtD","1v5hH8TxD7","0h1b1IKxdL",
-"BGaQYdjsrv","lj07QAXpwE","s4786OHaBz","hi5X7iwzGk","euZA5fcJOy","Z4I1vk85Ae","7hyVvrz7Ut","45cIHBCxeC","FxX9q9XyT9","7fKYUThjNn",
-"X6Pingf8rI","45cIHZJTXH","5VZjSogLgc","Ss0ZufmIK1","6AFT0QnJ1S","1j5L8DQimp","S77LHaFFss","s93Ml7ku1p","HlUbFFjHXR","HfyNQQClRL",
-"cShY2WaWsv","aFFsscShY2","5NammQClRL","MK07Y14FLR","CNHmvhi5X7","55rfBru4UG","K20wKMK07Y","FwEJzb29RJ","LbRTHdmoS7","HP433fqypy",
-"oVQp6iKqhr","VIlwPuTacx","S2DfufaHir","0Wr5yZuDtD","5ZaEzaez9y","WPmlxzmLYD","VNCPdC2Irc","tlILtaez9y","zbIYYzFgtB","55rfBCqqaD",
-"s4786uupzk","1LB1LuTacx","9XyT95ZaEz","zqH0W580YD","NcICAHzZT8","ZJTXHQnJ1S","Cfgr3FxX9q","K4GS8SmGzv","lCMxyPYBf4","580YDWDVWJ",
-"8xEKz8RCUA","RsQUqAXpwE","ZUnqtS77LH","zz4ZU0MR5X","vLsmSM6qcG","WPmlxnnP8o","Ss0Zujtn0X","fcJOyS77LH","2TRI7RpBQm","SjskQiKqhr",
-"0YAGHMmsIo","okgRiVIlwP","3otm6d7vjM","tjQxsPOUYS","ix74riKqhr","ZUnqtECMvU","5ZaEzHzZT8","45cIHZhwG1","FLsphcL0aE","tuDySDQimp",
-"BCxeCguMb8","fqypyaez9y","iKqhrsuY4x","VerEAZJTXH","IjTwP1j5L8","uLtKsy94nw","JJs5mi3pyd","X6PinmX2GE","HlUbFe6e4z","lkMUA7fsYM",
-"yToGWxReec","IKxdLxReec","ru4UG7X3uy","MezSWfcJOy","Q6hMClH1kt","iqv4kKASQ8","yEfy90BmCy","fcJOyokgRi","XyPZNI7p2a","Kr8ysuZPqg",
-"8xEKzjzUqR","uvf7ARkQke","wiHrZAOgEe","cL0aEWaWsv","M6qcGprNT6","rKDLJksJby","WPmlxXflUq","k85AefcwDa","bgJAzzz4ZU","Q6hMCRACuj",
-"aDGtSBCxeC","s7MxkjSjS3","cmXIXMm8si","BbwgAnlaBy","8hJdtUl4a1","4QMc9WPmlx","jiVBPm4bxU","SWfouoGu6x","AXpwE5VZjS","L7cGcCK5W7",
-"55rfBSmGzv","atef2kZANm","vOqCEGrDg7","4W0TlQbxXc","ogLgcgtCA5","1v5hHhSSvQ","24ARFaFFss","ThjNnjiVBP","hYBCKlweGy","Waim6ulk41",
-"jfREu2Nslm","BGaQYhUTw7","lkMUAOUqFM","FxX9qsqVrf","sqVrfDLhzM","GWqqXlpF6W","5ZaEz5drc6","W3VFHGrDg7","7ku1pvkCHH","ru4UGyluBx",
-"mX2GEBpYhV","tl72WsqVrf","h1zcHfcwDa","0YAGHk85Ae","v2eC3uQIcz","Vprf2HRxd8","lViBvvkCHH","AIYUuFPfSE","taOXKQWxoT","v8yFNCK5W7",
-"Cp3mZ64s8N","nnP8o5nmWv","HP433fcwDa","fcJOyBGaQY","JIqXiFhtgl","gtCA52DREs","fLNg8jeskS","hi5X7RpBQm","64s8NZhwG1","FFDuilsQGo",
-"ksJbya00b5","MaJQs2Nslm","ydG8UQClRL","lm0pDMK07Y","iKqhrhe9IA","5VZjS0MR5X","fFDrJ3otm6","FFDuiMGlTF","CdyBVUmaEv","iKqhrQYxC0",
-"uLtKssuY4x","v1Hln3otm6","fmIK1Rxrsm","UmaEvni2v1","FjHXRIjTwP","48cHL0Wr5y","O3iyQK20wK","RzaZA8FmFH","DLhzMlj07Q","Z4I1vTa8f6",
-"ksJbyulk41","2Yz7EfLNg8","i3pydJ2mQi","L7cGcTwano","0MR5XtjQxs","CxVEf9XyT9","7Ow5C0PktI","FLsphIRh48","nnP8oZuDtD","1j5L8t59lR",
-"7ku1pgtCA5","Nxx9Vl83Ud","KZamHQ6hMC","8U2nULewvM","h1zcHuTacx","EdBKc7fKYU","FVMxoJKWYR","pT8wu14FLR","B3qemRzaZA","J2mQiv8yFN",
-"Zv7z0W3VFH","07n1cs4786","YjB9tdjsrv","KsjRKJIqXi","pAhR1yToGW","k85AepAhR1","Nxx9V7fsYM","jzUqRWPmlx","azIWpb29RJ","uZPqgt98iW",
-"0MR5XZ4I1v","RxrsmRBhp0","618DicL0aE","dmoS7cShY2","dmoS7zz4ZU","Q6hMC9XyT9","lsQGoC2Irc","vkCHHJKWYR","QbxXczbIYY","yofH3lkMUA",
-"uupzkD6rBy","pFrrlAkKTk","xciqpQWxoT","0PktIWreyP","2hEEUSWfou","2hEEUSjskQ","MojnP0YAGH","wiHrZ3weIF","MojnPFxX9q","djsrv7ku1p",
-"uLtKspAhR1","nFqikAIYUu","ZuDtDtjQxs","guMb8tjQxs","t59lRbrhlQ","ulk41O3iyQ","v1HlnuZPqg","ZzJHWB3qem","UmaEvZJTXH","zz4ZUUl4a1",
-"taOXKW7cTs","nFqikL7cGc","ZuDtDzqH0W","aez9yoGu6x","nFqikhUTw7","Vprf2zHF1q","CIShGsx5Gl","mX2GEQ6hMC","WPmlxYf2Ec","AOgEesuY4x",
-"S2Dfu6AFT0","Q6hMC8cVD3","l83UdOxWIH","fqypyGWqqX","GWqqXZzJHW","UlU3MDLhzM","55rfBAkKTk","5drc67X3uy","Yh1hFzFgtB","0PktIdpe1v",
-"cQOnv1v5hH","AIYUu3weIF","GWqqXW7cTs","Ul4a1uTacx","dpe1vYOfrY","VLTy6ZUnqt","Waim6x3LDe","0PktIVjCZq","DQimpYh1hF","29QAza00b5",
-"IBe8k2Yz7E","618DiuoStw","uupzkNo0Qb","8TxD7JXljW","5iGN5hi5X7","EdBKc16lHc","W3VFHMaJQs","2Yz7Eb29RJ","S2DfuzQt6Q","DLhzMwiHrZ",
-"Ss0ZuQChxs","EOE1ooQ87r","zFgtBhUTw7","55rfBUl4a1","WMiS36q6L9","UlU3MnnP8o","07n1cguMb8","jiVBPuJScX","OUYuFYw2oU","lsQGo8hJdt",
-"a00b5uN6r3","NhXdu8TxD7","azIWpRzaZA","fLNg80MR5X","Mkgy8Ta8f6","lpF6WaFFss","QWxoTlViBv","oVQp6WmadA","5iGN5prNT6","fcJOySbRYy",
-"8FmFHHzZT8","Pb1paFFDui","Waim6QChxs","Q6hMCwDajX","iKqhrCNHmv","LewvMTa8f6","WaWsv0ao3l","OUqFMAmdQd","pT8wuVerEA","tjQxse6e4z",
-"5Mg9rZv7z0","cmXIXs4786","ECMvU9rlg9","Yw2oUMaJQs","x3LDeiB08l","Mkgy8dhSuH","ix74rM3zXL","1j5L8WPmlx","sx5GlcQOnv","8U2nUCp3mZ",
-"WDVWJOHaBz","nnP8oVLTy6","jtn0XW7cTs","rhl0JlXFOB","TCgPpTa8f6","fFDrJtl72W","soy9t9GXkX","ECMvUS2Dfu","NAFuwd7vjM","BGaQYCNHmv",
-"n8pJ9Yw2oU","WaWsvzz4ZU","iKqhrjS1aj","lCMxyVBjhz","qaofNyluBx","hSSvQzz4ZU","3weIFguMb8","zqH0W7Ow5C","9eoRcix74r","pAhR1AmdQd",
-"DcpWBni2v1","6q6L9ZUnqt","cShY2CK5W7","AIYUuiqv4k","uoStwuPX7G","m4bxUpmeCd","PYBf4nlaBy","bgJAzEoToP","RmDcrtAOsr","pv0i75iGN5",
-"ni2v1tl72W","okgRiFNYIM","BFkb8CIShG","580YDaL6AJ","yToGW1LB1L","gjUTuVIlwP","fLNg8pAhR1","zFgtBfmIK1","FxX9qlH1kt","Ta8f6zHF1q",
-"wDajXcShY2","x3LDetl72W","MaJQsRACuj","ydG8UZzJHW","F6PT2JKWYR","WDVWJAOgEe","LewvMpvgjS","oQ87rv8yFN","OUqFMgjUTu","lj07Qdjsrv",
-"jS1ajy94nw","AgJHQOz8yZ","piJSk9GXkX","8xEKzfqypy","Qworulj07Q","4W0TldhSuH","VNCPd1LB1L","IRh48O3iyQ","JKWYRIjTwP","B3qemgf8rI",
-"7ku1phSSvQ","zHF1qlCMxy","FcWrWWaWsv","FnPFBv8yFN","Qworuiqv4k","VjCZqHlUbF","Oz8yZuoStw","yluBx1j5L8","lm0pDjfREu","In3NSWPmlx",
-"YjB9t6q6L9","DLhzMYjB9t","zY1GYPYBf4","0YAGHHlUbF","TXQ0ZgdQsS","C2Irc5ZaEz","m4bxUaez9y","FhtglAIYUu","5iGN5hYBCK","X6PinfFDrJ",
-"pv0i71v5hH","0YAGHFNYIM","Q6Lixsx5Gl","GWqqX2hEEU","dmoS7VBjhz","YOfrY2DREs","m4bxUReKEW","S77LHAgJHQ","RACuj2hEEU","WmadAWaim6",
-"dhSuHMGlTF","fmIK11v5hH","s4786Dz1R3","MmsIoRpBQm","618DiMkgy8","5iGN5n8pJ9","euZA5MaJQs","VIlwPUlU3M","2DREsFPfSE","BGaQYKr8ys",
-"O3iyQRBhp0","ksJbylj07Q","07n1cI7p2a","AkKTkGrDg7","pmeCdjfREu","0PktII7p2a","IjTwPFjHXR","aL6AJJXljW","HfyNQZuDtD","kB5nPVIlwP",
-"qaofNQ6Lix","0MR5XNo0Qb","45cIH0h1b1","IKxdLpT8wu","0YAGHAOgEe","vOqCE0PktI","RmDcryToGW","prNT6Chuy3","n1pmO5Drn0","gtCA5G1RhS",
-"yToGWYjB9t","5IhmGazIWp","pT8wubgJAz","EoToPIKxdL","Cp3mZRzaZA","jSjS3HRxd8","n8pJ9M6qcG","OHaBzP6bcg","kZANmEOE1o","2Yz7EMmsIo",
-"fmIK1t59lR","t98iW8TxD7","lj07QDG4sT","piJSkvLsmS","n8pJ9jzUqR","5IhmGYjB9t","7hyVv5Mg9r","9eoRc3weIF","M6qcGQClRL","ix74rUl4a1",
-"uTacxjSjS3","CxVEf14FLR","8xEKzuoStw","v8yFNuAWyp","fmIK114FLR","ZhwG1euZA5","AOgEeaDGtS","atef20PktI","K20wKhE1Ql","C2IrcBbwgA",
-"AIYUuuZPqg","Nxx9VZJTXH","JKWYRni2v1","P6bcgZJTXH","rKDLJB3qem","In3NSxXTI4","L7cGcMGlTF","K4GS8dhSuH","Mm8si7lUXZ","Yw2oUOHaBz",
-"atef2lkMUA","618Di1v5hH","lpF6WrKDLJ","yEfy9zQt6Q","xReecFcWrW","s93MlECMvU","oGu6xpvgjS","618DidhSuH","Y1mC0pFrrl","5iGN5POUYS",
-"VjCZqP6bcg","OxWIHMGlTF","b29RJfcJOy","MezSW8xEKz","jfREuhi5X7","s93MlK20wK","Nxx9VFVMxo","jtn0X7X3uy","prNT6mX2GE","BCxeC8xEKz",
-"Zv7z016lHc","suY4xv2eC3","FNYIM7X3uy","FnPFBiKqhr","brhlQSWfou","kZANmYf2Ec","5drc6aFFss","0PktIgjUTu","9GXkXtvdkD","gtCA5gdQsS",
-"nlaByOUYuF","gtCA5M6qcG","FPfSEWaim6","e6e4zn8pJ9","7fsYMIRh48","jzUqRiqv4k","pWiOsZhwG1","IRh48AmdQd","2ZHdkBFkb8","48cHLsuY4x",
-"2hEEUfcwDa","1LB1LCfgr3","TwanonnP8o","Gv3FqlsQGo","BpYhVHP433","VLTy6iqv4k","a00b555rfB","580YDAOgEe","0YAGHYf2Ec","RpBQmIjTwP",
-"fqypylXFOB","piJSkCIShG","WaWsvAIYUu","9XyT9fLNg8","5NammWaWsv","8xEKzv8yFN","SWfoudjsrv","Yw2oUDcpWB","ix74rHRxd8","8TxD7In3NS",
-"Vprf2l83Ud","S77LHgIYvE","4dEz6Qworu","xXTI4X6Pin","zHF1qAkKTk","IBe8kWreyP","9eoRcDQimp","P6bcglXFOB","Pb1paYOfrY","t59lRSjskQ",
-"ZhwG1VNCPd","S2DfuJkzUn","KASQ8oQ87r","AkKTkS77LH","JRJQBzbIYY","y94nwi7WMQ","FhtglVerEA","07n1cYjB9t","KZamHnFqik","7lUXZBGaQY",
-"piJSkkB5nP","KsjRKlViBv","8xEKzAkKTk","2DREsdmoS7","VBjhz0PktI","8xEKzEOE1o","MezSWJJs5m","FxX9q0ao3l","xXTI4jiVBP","iqv4klm0pD",
-"AXpwENxx9V","StlDJKASQ8","lXFOBlpF6W","B3qem55rfB","9XyT97Ow5C","5NammyToGW","cL0aElpF6W","Pb1pa64s8N","aDGtSeuZA5","D6rBydmoS7",
-"FVMxodQ586","uQIcz618Di","okgRiJXljW","ZuDtDeuZA5","EoToPAIYUu","euZA5jSjS3","D6rBys7Mxk","HlUbFNOHsz","pmeCdTa8f6","uQIczRsQUq",
-"RpBQmzz4ZU","16lHcMaJQs","55rfBiwzGk","D6rByECMvU","uTacxeuZA5","OUYuFJRJQB","hYBCKK4GS8","NcICA2hEEU","YOfrYjeskS","qUJMduZPqg",
-"aez9yuTacx","Ul4a1ZJTXH","aFFsstvdkD","2ZHdk8hJdt","XyPZNm4bxU","guMb8SWfou","brhlQCdyBV","kZANmmz8gx","hUTw7I7p2a","gdQsSfaHir",
-"uZPqgK20wK","VIlwPIjTwP","tvdkD5Namm","pmeCd07n1c","uJScXRxrsm","t98iWXyPZN","uTacxv1Hln","blLA9ydG8U","4dEz6soy9t","7fKYUk85Ae",
-"XflUqk85Ae","a00b5vLsmS","MojnPVNCPd","Yw2oUzHF1q","9eoRc7X3uy","h1zcH5iGN5","YOfrYuZPqg","xReecNcICA","zmLYD4dEz6","azIWpBpYhV",
-"Gv3FqCxVEf","d7vjM4W0Tl","VerEAOUqFM","faHirQYxC0","t59lRRzaZA","mz8gxNAFuw","jSjS3Oz8yZ","KZamHKASQ8","atef2DLhzM","BCxeCdjsrv",
-"64s8NHlUbF","9XyT9bZLvS","HlUbF4dEz6","nnP8o9y4lw","jSjS3azIWp","AOgEeIn3NS","ni2v1Cfgr3","kB5nPRxrsm","k85AeOz8yZ","ksJbyhE1Ql",
-"iqv4k4dEz6","y94nwhSSvQ","EOE1oSjskQ","RpBQmL7cGc","M3zXLaDGtS","W3VFHrz7Ut","MojnPFVMxo","Q6LixIBe8k","suY4xBFkb8","TCgPpRxrsm",
-"gf8rICp3mZ","AOgEe0ao3l","brhlQJJs5m","Zv7z08U2nU","a00b55ZaEz","dQ586TCgPp","2Yz7ElpF6W","SmGzvmz8gx","tl72WkB5nP","8TxD7AIYUu",
-"jfREuF6PT2","6AFT0he9IA","7X3uyUlU3M","nlaByn1pmO","MGlTFOxWIH","uLtKsjeskS","iB08loQ87r","iqv4kFxX9q","uQIczRxrsm","mz8gxzqH0W",
-"JIqXiiwzGk","1LB1LIn3NS","64s8NhUTw7","XyPZNpvgjS","KZamHyluBx","v8yFNCIShG","lweGyNAFuw","MmKGJAkKTk","euZA50MR5X","580YDQYxC0",
-"8FmFHnlaBy","lCMxy8hJdt","StlDJUl4a1","OUqFMBCxeC","SbRYyhE1Ql","uN6r3lkMUA","aL6AJBCxeC","JRJQBRmDcr","6AFT0ECMvU","SbRYyt59lR",
-"AIYUusoy9t","RzaZAaez9y","ksJby618Di","8TxD7K20wK","uQIczFnPFB","LewvMECMvU","uLtKsi3pyd","cShY2tl72W","FNYIM5IhmG","VLTy6rz7Ut",
-"SjskQWaim6","FnPFBpiJSk","FhtglGrDg7","zz4ZU8U2nU","HP433faHir","zqH0WRpBQm","oQ87rFxX9q","HRxd8brhlQ","wiHrZnnP8o","d7vjMMojnP",
-"CdyBV4QMc9","No0Qb1LB1L","okgRiFwEJz","0Wr5yKASQ8","NcICAJJs5m","jzUqRSWfou","uAWypzz4ZU","FnPFBfcJOy","yToGWhSSvQ","WreyPt98iW",
-"HfyNQOz8yZ","zY1GYDcpWB","jzUqREoToP","h1zcHrz7Ut","yToGWxciqp","yToGW2hEEU","WmadAW3VFH","i3pydzHF1q","SjskQDz1R3","No0Qb0Wr5y",
-"QnJ1SDcpWB","jS1ajhE1Ql","2Nslmh1zcH","tl72W9rlg9","8U2nUlsQGo","1v5hHQnJ1S","4W0TlDcpWB","vOqCEIRh48","Mm8siZv7z0","zY1GYtjQxs",
-"lm0pDCqqaD","yEfy9QWxoT","bZLvSx3LDe","iqv4krz7Ut","QChxsdhSuH","FPfSEs7Mxk","lXFOBjS1aj","hi5X7kZANm","ZUnqtZv7z0","tAOsr5Mg9r",
-"LewvMGSQwj","v8yFNM6qcG","s93Mlv1Hln","Ta8f6zQt6Q","SjskQzqH0W","9eoRcStlDJ","Uvlv47hyVv","OxWIH8xEKz","CqqaDVerEA","Waim69GXkX",
-"fqypyni2v1","DG4sTlsQGo","7X3uyYf2Ec","8U2nUCIShG","pT8wuAIYUu","Nxx9VuQIcz","EOE1oaFFss","qQxHPDQimp","M3zXL5iGN5","MojnPRACuj",
-"tjQxshi5X7","BFkb8iB08l","Pb1pa5drc6","EOE1oyofH3","NhXdusoy9t","G1RhS0MR5X","aL6AJECMvU","GSQwj8xEKz","t98iW1v5hH","d7vjMtvdkD",
-"8RCUAZhwG1","qQxHPJ2mQi","580YDGv3Fq","CdyBVLbRTH","RsQUq8RCUA","gIYvEQbxXc","Chuy3vkCHH","NhXduPb1pa","16lHcuTacx","yEfy9Vprf2",
-"vLsmSjfREu","VLTy6tlILt","YjB9tMmKGJ","RpBQmjeskS","gtCA5ZuDtD","lm0pDk85Ae","SjskQFNYIM","IKxdLn8pJ9","0YAGHZhwG1","FxX9q7ku1p",
-"pmeCdoVQp6","14FLRxciqp","Y1mC0OUYuF","5nmWvzY1GY","0h1b1v1Hln","Rxrsmulk41","nnP8oNhXdu","yofH3jS1aj","FjHXRx3LDe","rz7UtU3yw5",
-"3weIFgdQsS","zY1GYcL0aE","mX2GEtvdkD","jeskSP6bcg","YOfrYLbRTH","uupzkzFgtB","7Ow5CHRxd8","XflUqpWiOs","jfREuS2Dfu","OHaBzs4786",
-"aDGtSfcJOy","rKDLJ5nmWv","yvOMIfaHir","tAOsrDQimp","brhlQKr8ys","D6rByRxrsm","uvf7AbgJAz","s7Mxklm0pD","AOgEeTXQ0Z","aL6AJuPX7G",
-"hYBCKHRxd8","tlILtzqH0W","uJScXzFgtB","ydG8U7ku1p","lH1ktJkzUn","WMiS3M3zXL","v1HlnzHF1q","ThjNnrhl0J","AOgEeL7cGc","8RCUAdjsrv",
-"FNYIMGv3Fq","zHF1qlweGy","FnPFBAgJHQ","2hEEUsoy9t","JRJQBa00b5","d7vjMRmDcr","pT8wuxReec","uvf7ARzaZA","Yf2Ecxciqp","48cHL9y4lw",
-"uQIczVprf2","HP433BCxeC","64s8NBbwgA","CdyBVK20wK","JkzUnF6PT2","cmXIXb29RJ","ZJTXHlkMUA","5nmWvtAOsr","0BmCyM6qcG","K20wKgf8rI",
-"9GXkX0Wr5y","Kr8ysFNYIM","qUJMdP6bcg","MGlTFIjTwP","xReec5drc6","JkzUnm4bxU","BpYhVK20wK","t59lRCNHmv","fcwDazY1GY","ciuWzEdBKc",
-"55rfBY1mC0","LbRTHx3LDe","HP4338hJdt","yofH3BpYhV","7lUXZ3weIF","gf8rIoVQp6","s93MlS77LH","PYBf4dQ586","VIlwPgdQsS","14FLRMaJQs",
-"MmKGJpAhR1","s4786OUYuF","rz7UtRkQke","iwzGkv2eC3","v1HlnpFrrl","7Ow5C48cHL","JXljWQYxC0","W3VFHciuWz","hSSvQfFDrJ","Twano24ARF",
-"fFDrJQYxC0","uPX7GfLNg8","ru4UGtAOsr","FLsphDcpWB","HRxd8e6e4z","Cp3mZrz7Ut","580YDEOE1o","pmeCdStlDJ","rhl0Jt98iW","hUTw7d7vjM",
-"h1zcH0MR5X","1j5L8VjCZq","7ku1pJ2mQi","v8yFN5nmWv","AmdQdMkgy8","oQ87rHP433","tuDyStvdkD","FPfSEEdBKc","aDGtSjeskS","lCMxyQnJ1S",
-"oGu6xyEfy9","euZA5TXQ0Z","8TxD7POUYS","jtn0XuN6r3","24ARFWaWsv","Dz1R3tvdkD","uZPqgKr8ys","WmadAHzZT8","yEfy9RACuj","WPmlxQWxoT",
-"pAhR1fFDrJ","MmsIoReKEW","8RCUAo8Uyd","pmeCdQ6Lix","KZamH0Wr5y","ZzJHWX6Pin","zFgtB5drc6","uupzk7ku1p","qQxHP7ku1p","hUTw748cHL",
-"Pb1paSs0Zu","lsQGouZPqg","D6rByFnPFB","55rfBaez9y","x3LDeKASQ8","QnJ1SjzUqR","Q6LixfLNg8","SWfoun1pmO","mz8gxwDajX","RpBQmbrhlQ",
-"5drc6fcJOy","QChxsVjCZq","hSSvQ45cIH","OUqFMxReec","jS1ajUl4a1","uAWyp9rlg9","K4GS81v5hH","DLhzMuTacx","0KyfscQOnv","i3pydKr8ys",
-"2hEEUHlUbF","d85a9oGu6x","BCxeCVprf2","vLsmSAOgEe","In3NS7ku1p","24ARFRmDcr","soy9txReec","qQxHPFFDui","qaofNoGu6x","SWfou580YD",
-"pv0i7DG4sT","nlaByix74r","Yw2oUgdQsS","U3yw5AOgEe","sx5GlZzJHW","WMiS3In3NS","Dz1R3G1RhS","d7vjMEOE1o","WPmlxAkKTk","kB5nPYOfrY",
-"2Nslmi7WMQ","ThjNnuupzk","07n1c5IhmG","9y4lwy94nw","RsQUq45cIH","55rfB07n1c","BpYhV4QMc9","IRh48HzZT8","a00b5SbRYy","JKWYRKr8ys",
-"Mm8si0YAGH","RpBQmQssNC","dpe1vGXdoH","v1HlnYh1hF","JRJQBAmdQd","i7WMQY1mC0","qQxHP4W0Tl","pv0i7gf8rI","s93MljSjS3","UmaEvs93Ml",
-"uupzkpFrrl","uLtKsDcpWB","aFFssv2eC3","P6bcgLbRTH","aL6AJiqv4k","WMiS3Q6hMC","n8pJ9QbxXc","BbwgAlj07Q","jS1ajNxx9V","mz8gxG1RhS",
-"jzUqRAkKTk","5VZjSSWfou","b29RJ6q6L9","uAWypHfyNQ","DcpWB16lHc","Pb1paQworu","RpBQm64s8N","FPfSEksJby","VerEAJKWYR","9rlg9n1pmO",
-"BFkb8ZhwG1","LbRTH5drc6","CK5W7pWiOs","v1HlnMaJQs","Gv3FqVLTy6","Q6hMCkB5nP","fLNg8NAFuw","CxVEfGrDg7","d85a9RACuj","DG4sTNhXdu",
-"K4GS8pWiOs","sx5GluoStw","In3NSi7WMQ","aFFssfcJOy","KASQ8suY4x","y94nwFnPFB","AIYUuciuWz","qQxHPPYBf4","8TxD7l83Ud","jS1aj9iGoT",
-"QChxsFxX9q","ZJTXHuLtKs","uvf7A48cHL","5ZaEzZuDtD","580YDs4786","dpe1vEOE1o","tl72WkZANm","oGu6xUl4a1","64s8Nn8pJ9","jiVBPRzaZA",
-"o8Uyd8TxD7","HfyNQv1Hln","8xEKzuLtKs","4W0Tl4W0Tl","cmXIXnnP8o","ksJbyNo0Qb","uoStwBFkb8","Yf2EcOxWIH","MezSWjeskS","bZLvS8hJdt",
-"9GXkXk85Ae","5Drn048cHL","TXQ0ZgtCA5","fcJOy9y4lw","7lUXZD6rBy","yEfy9KsjRK","5nmWvFVMxo","FwEJzK4GS8","DLhzMVNCPd","zmLYDXyPZN",
-"FnPFBkB5nP","pvgjSs7Mxk","Mkgy85ZaEz","dhSuHYOfrY","bZLvStl72W","zQt6Qb29RJ","he9IACfgr3","aDGtSRzaZA","lweGyTwano","aL6AJprNT6",
-"MaJQsFwEJz","W7cTstlILt","mz8gxqaofN","a00b5KZamH","2Yz7EQbxXc","MaJQs6q6L9","CIShGoGu6x","9eoRcQnJ1S","RkQkem4bxU","Uvlv4ni2v1",
-"Gv3FqbgJAz","lH1ktBbwgA","RsQUq7Ow5C","LbRTHwiHrZ","sqVrfJXljW","Ss0ZulkMUA","y94nw2Yz7E","uupzkyToGW","MGlTFUlU3M","Cp3mZkZANm",
-"fLNg8rKDLJ","No0QbM3zXL","kB5nPSbRYy","uJScXFxX9q","L7cGcqaofN","s7MxkprNT6","BpYhV1LB1L","tjQxsRmDcr","9GXkXWMiS3","AXpwE1v5hH",
-"2TRI7uJScX","oQ87rAkKTk","uPX7GDcpWB","CdyBVlpF6W","xciqpP6bcg","8hJdtPYBf4","EoToPHRxd8","1j5L8OxWIH","580YDHfyNQ","K20wKv1Hln",
-"pvgjSRmDcr","0ao3lzz4ZU","DQimpfLNg8","RxrsmpmeCd","yluBxBbwgA","MaJQsW7cTs","uTacxtuDyS","hE1QlDcpWB","iqv4k07n1c","O3iyQydG8U",
-"Cfgr3rz7Ut","HlUbF8cVD3","IKxdLWreyP","618Diulk41","lViBvKsjRK","B3qemRACuj","P6bcgRmDcr","tl72W64s8N","cL0aEBCxeC","zmLYDZhwG1",
-"CqqaDFVMxo","JKWYR7hyVv","0ao3luupzk","xciqpuZPqg","jfREuxXTI4","ksJbysoy9t","Waim6gdQsS","07n1cksJby","9XyT9Pb1pa","VerEA2hEEU",
-"rKDLJIRh48","0Wr5ys7Mxk","9iGoTbrhlQ","0KyfsIn3NS","FnPFBBGaQY","HP433iwzGk","CqqaDBFkb8","IBe8k0MR5X","Nxx9VJJs5m","FFDui9iGoT",
-"7Ow5CdmoS7","BbwgAfcJOy","FGzgpbrhlQ","Y1mC0NhXdu","PYBf4yvOMI","CdyBVlj07Q","xciqp6AFT0","prNT6VLTy6","wDajXtjQxs","GSQwjOxWIH",
-"lpF6WRACuj","3otm6RmDcr","Ta8f6fcJOy","soy9tRmDcr","QssNCY1mC0","FLsphjfREu","0ao3ltaOXK","mz8gxIjTwP","WreyPzY1GY","okgRiC2Irc",
-"aFFss8FmFH","CxVEfWmadA","gjUTu8RCUA","Z4I1vOHaBz","aFFssQnJ1S","NcICARmDcr","K20wKcShY2","uJScXciuWz","s4786lpF6W","BbwgAOz8yZ",
-"azIWpzbIYY","Zv7z0QnJ1S","ulk41pAhR1","uPX7GbrhlQ","ZUnqttuDyS","rKDLJpT8wu","48cHLVprf2","Chuy3mX2GE","6AFT0uLtKs","LewvMIBe8k",
-"9iGoTZuDtD","14FLR16lHc","pT8wut59lR","uJScXgtCA5","RmDcrTwano","gIYvEgtCA5","atef2LDk6f","VBjhzWaWsv","0Wr5yhe9IA","YjB9tgf8rI",
-"aL6AJQClRL","FxX9quoStw","uAWyphE1Ql","ZuDtDgjUTu","ECMvUNAFuw","2NslmUmaEv","0MR5XnFqik","zQt6QlXFOB","ni2v12TRI7","Cfgr3NOHsz",
-"8RCUAh1zcH","07n1c2DREs","gf8rIiwzGk","pFrrlokgRi","Fhtgl9GXkX","AXpwETa8f6","d85a9v1Hln","8cVD35nmWv","SjskQs4786","AmdQdrKDLJ",
-"sx5GlAOgEe","iKqhrdpe1v","uLtKsfcJOy","zz4ZU0PktI","M6qcGnFqik","4dEz6YjB9t","JKWYR580YD","Z4I1vqQxHP","7fKYUPYBf4","NcICAuN6r3",
-"AOgEetjQxs","ksJbyW3VFH","5iGN5BpYhV","l83UdJ2mQi","cmXIXzFgtB","rKDLJSmGzv","JIqXioVQp6","dpe1v8U2nU","Waim6xciqp","Gv3Fqiqv4k",
-"580YDhUTw7","F6PT28hJdt","brhlQDLhzM","5iGN52Yz7E","xReecIKxdL","gIYvEbrhlQ","rKDLJ2hEEU","ksJby5VZjS","WaWsv7fKYU","VBjhzZ4I1v",
-"uupzkv8yFN","Ta8f6suY4x","e6e4ziqv4k","uAWypBbwgA","D6rByM6qcG","WreyPh1zcH","k85Ae5drc6","0MR5X7lUXZ","uPX7GpT8wu","D6rByuQIcz",
-"QChxsMGlTF","lweGyZhwG1","5VZjSpFrrl","LbRTHmz8gx","OUqFMZJTXH","uoStwDQimp","5NammjeskS","tuDySM3zXL","WaWsvatef2","s7Mxkrhl0J",
-"aFFss0PktI","07n1ce6e4z","RpBQmDcpWB","DcpWBlViBv","U3yw59XyT9","oGu6xhE1Ql","aL6AJCIShG","hYBCKKZamH","MaJQstl72W","VNCPduJScX",
-"RBhp08hJdt","MGlTFi3pyd","0MR5XCqqaD","FFDui0MR5X","SmGzvvOqCE","Ul4a1qQxHP","2DREsBbwgA","guMb8WPmlx","FFDuiY1mC0","ix74rGv3Fq",
-"5IhmGCfgr3","atef2brhlQ","8FmFHNxx9V","CdyBVfFDrJ","StlDJOz8yZ","L7cGc2hEEU","prNT6QWxoT","KsjRK5Namm","BGaQY3otm6","taOXK4dEz6",
-"iB08l618Di","QnJ1SlkMUA","RACujfLNg8","QnJ1SnnP8o","2NslmjeskS","G1RhSgIYvE","Oz8yZOUqFM","lkMUAJKWYR","0MR5XHzZT8","tvdkDZ4I1v",
-"4dEz6Nxx9V","VLTy6y94nw","JJs5mpmeCd","55rfB5Mg9r","lH1kthUTw7","29QAzqaofN","bgJAz2TRI7","tuDySPYBf4","Mkgy855rfB","gtCA52ZHdk",
-"0BmCyQworu","he9IAkB5nP","suY4xZzJHW","SbRYy7lUXZ","m4bxUMmsIo","i7WMQtl72W","xciqpTwano","ZUnqt7ku1p","he9IA2ZHdk","xReeclj07Q",
-"fcJOy0YAGH","lj07QtuDyS","M6qcGcL0aE","ECMvU2TRI7","24ARFi7WMQ","wDajXuZPqg","AXpwEQ6Lix","jzUqRWaWsv","ni2v1CK5W7","WPmlx8xEKz",
-"CNHmvM6qcG","lH1ktMaJQs","24ARFjtn0X","ZUnqtCp3mZ","9y4lwIBe8k","wiHrZYf2Ec","vLsmS0Wr5y","3otm6K4GS8","7fsYM8hJdt","bgJAz64s8N",
-"24ARFpvgjS","NOHszAkKTk","1v5hH0MR5X","5VZjSSmGzv","OxWIHqQxHP","7hyVvI7p2a","euZA58cVD3","v1HlnCIShG","MmKGJpvgjS","s4786dpe1v",
-"SmGzv5iGN5","JXljWdQ586","WDVWJs93Ml","jSjS3NhXdu","fcJOy0PktI","yvOMIrz7Ut","K20wK2TRI7","jSjS3618Di","FLsphpAhR1","hi5X7a00b5",
-"U3yw5uupzk","iqv4kgtCA5","DcpWBhYBCK","uvf7AeuZA5","Y1mC0lkMUA","BGaQY8FmFH","0BmCyDG4sT","QWxoTMmKGJ","2NslmJXljW","yToGWsoy9t",
-"FPfSEVIlwP","8U2nUCK5W7","fLNg848cHL","Q6hMChi5X7","9eoRcRmDcr","NAFuwzY1GY","pvgjSUmaEv","gdQsSOUYuF","tjQxsuTacx","3otm6VIlwP",
-"Cp3mZtl72W","ZhwG1RpBQm","0BmCyHlUbF","BpYhVJRJQB","m4bxU16lHc","fLNg82TRI7","JJs5mJIqXi","Y1mC0Qworu","gdQsSo8Uyd","Kr8ysVjCZq",
-"lViBvpvgjS","Zv7z05VZjS","nlaByECMvU","ZuDtD7fKYU","FPfSE5nmWv","1LB1LpFrrl","aDGtSe6e4z","d7vjM8xEKz","JRJQBokgRi","MmKGJBFkb8",
-"yvOMI0PktI","ksJby5Drn0","wiHrZcShY2","LewvMChuy3","wDajXuAWyp","Cp3mZOUYuF","6AFT0k85Ae","mX2GEECMvU","zHF1qOUYuF","EdBKcHzZT8",
-"fmIK1azIWp","dmoS7fqypy","gdQsSt98iW","dQ586AmdQd","0PktIfaHir","gtCA5OxWIH","7hyVvuvf7A","VBjhzlweGy","HP433uvf7A","29QAzMojnP",
-"Yw2oUCqqaD","rKDLJXyPZN","FGzgp9XyT9","WreyPYjB9t","5iGN5mz8gx","In3NSsuY4x","rhl0JF6PT2","n1pmO5IhmG","zz4ZUSs0Zu","tjQxs5nmWv",
-"taOXK9rlg9","IKxdL1j5L8","MojnPECMvU","PYBf4K4GS8","K20wK0BmCy","jSjS3Y1mC0","580YDlm0pD","cmXIX8cVD3","CNHmvaez9y","29QAzyToGW",
-"zHF1qvOqCE","OHaBzyEfy9","Yf2EcFLsph","oQ87r9y4lw","1LB1LqQxHP","wiHrZm4bxU","OxWIHOxWIH","LbRTHVLTy6","hSSvQI7p2a","618DiSs0Zu",
-"oGu6xdjsrv","0BmCyKsjRK","wDajXl83Ud","3weIFfqypy","SbRYy1v5hH","S2Dfud7vjM","gdQsSprNT6","MGlTFB3qem","CIShGkB5nP","lXFOBqaofN",
-"d7vjMYjB9t","2NslmJIqXi","48cHLgf8rI","fcwDaxXTI4","EOE1oQworu","3otm6IKxdL","IKxdLAgJHQ","FxX9qbZLvS","2ZHdk3weIF","fqypyjiVBP",
-"zY1GY5VZjS","ThjNnHP433","uZPqg1LB1L","jtn0XGXdoH","7Ow5CfaHir","BpYhVVLTy6","YjB9tgdQsS","64s8NLDk6f","YjB9tP6bcg","ThjNnRkQke",
-"2Yz7EReKEW","gtCA5fmIK1","UmaEvIBe8k","lj07QBFkb8","MmKGJMojnP","fLNg8LewvM","ix74r3otm6","YOfrYNxx9V","pAhR1vOqCE","RxrsmNcICA",
-"jzUqRVIlwP","0h1b1Z4I1v","gf8rIyvOMI","xciqphYBCK","CdyBVgf8rI","iB08lRxrsm","BbwgAJRJQB","7hyVvIRh48","8U2nUDLhzM","pAhR1AXpwE",
-"29QAzIRh48","2hEEUMmsIo","jSjS3zbIYY","QworuuN6r3","RkQkeCp3mZ","oVQp6HP433","QbxXcuvf7A","B3qem2hEEU","fqypyqQxHP","HRxd80Wr5y",
-"0ao3lcL0aE","atef2C2Irc","fqypyHRxd8","FVMxoQnJ1S","DcpWBnFqik","SbRYyLewvM","ni2v1QYxC0","hUTw7uAWyp","14FLRX6Pin","bZLvSDLhzM",
-"NAFuwTXQ0Z","U3yw5KZamH","FNYIMtlILt","SjskQKZamH","rKDLJt59lR","uTacxtl72W","ni2v1uoStw","ciuWzv2eC3","Q6hMChe9IA","Uvlv4QYxC0",
-"U3yw5uZPqg","QYxC0OxWIH","VIlwPOUqFM","Mm8sinnP8o","DcpWBVIlwP","ni2v1BpYhV","YjB9tNAFuw","rKDLJPOUYS","k85AeW7cTs","Ta8f6JRJQB",
-"vOqCEFcWrW","XyPZNQnJ1S","0Wr5yRACuj","cmXIXFGzgp","lCMxyWmadA","SmGzvksJby","ZUnqtbgJAz","ZuDtD1j5L8","8hJdtFFDui","tl72Wtl72W",
-"rKDLJxReec","9iGoTKsjRK","Gv3FqMm8si","WreyPM3zXL","Zv7z0pT8wu","lXFOByEfy9","BFkb8gjUTu","uJScX0Kyfs","KsjRKtl72W","nFqikEOE1o",
-"8U2nUK4GS8","gIYvEt98iW","hE1QlRxrsm","Uvlv4NcICA","Oz8yZo8Uyd","rz7UtiwzGk","mz8gx5IhmG","s7MxkZJTXH","UmaEvPOUYS","CK5W70Wr5y",
-"FcWrWs4786","7Ow5CAkKTk","cL0aEdQ586","wiHrZ3otm6","J2mQin8pJ9","lm0pDNAFuw","U3yw5WPmlx","4W0TliKqhr","Cp3mZ0Kyfs","ZzJHWulk41",
-"GrDg72hEEU","SbRYyPOUYS","GSQwjlCMxy","FPfSEt98iW","F6PT2No0Qb","G1RhSFVMxo","brhlQtjQxs","wiHrZbgJAz","JKWYRtaOXK","QssNCCIShG",
-"5Drn0aFFss","FxX9qIjTwP","zQt6QK20wK","W3VFHqUJMd","d7vjMTXQ0Z","lsQGoYOfrY","brhlQ5iGN5","aFFsspAhR1","rKDLJl83Ud","5NammCIShG",
-"Vprf2RpBQm","TCgPpZhwG1","TXQ0ZwiHrZ","RpBQm9XyT9","yofH3BFkb8","m4bxUXflUq","WDVWJKASQ8","M6qcGk85Ae","AgJHQ14FLR","5NammNcICA",
-"lm0pDWMiS3","GrDg7Kr8ys","5iGN57X3uy","ZUnqtWDVWJ","RACujeuZA5","CK5W7CdyBV","pvgjS64s8N","IBe8kJRJQB","7fKYUHzZT8","gtCA5iwzGk",
-"GSQwjVerEA","fLNg8dmoS7","0MR5XUlU3M","L7cGcQWxoT","WreyPulk41","gjUTuhE1Ql","jSjS3fcJOy","0ao3l0h1b1","ZuDtDYf2Ec","8TxD7uJScX",
-"Ul4a1Chuy3","WreyPNcICA","BFkb8OHaBz","No0QbNhXdu","P6bcgydG8U","5drc6dhSuH","CK5W7OUqFM","DQimpnFqik","5ZaEzHP433","ZzJHWP6bcg",
-"FhtglZhwG1","FjHXRJRJQB","J2mQihYBCK","ZhwG1NhXdu","4dEz6s93Ml","POUYS5nmWv","b29RJlj07Q","GXdoHCfgr3","pWiOscL0aE","ru4UGrz7Ut",
-"CK5W7RpBQm","24ARFmX2GE","oQ87rAmdQd","fLNg8lsQGo","L7cGcyofH3","azIWpWPmlx","xReecFNYIM","LDk6fWDVWJ","pvgjSCxVEf","tAOsrs4786",
-"gtCA5oGu6x","t98iWJ2mQi","NOHszHRxd8","55rfBuvf7A","MezSWb29RJ","lsQGojeskS","NhXduFwEJz","SmGzvTa8f6","lkMUAqQxHP","ogLgcAXpwE",
-"rKDLJgf8rI","gf8rIdpe1v","cQOnvM3zXL","0MR5XNhXdu","hSSvQ8RCUA","cL0aEqQxHP","Y1mC05Namm","x3LDeru4UG","Z4I1vlj07Q","14FLRQWxoT",
-"FxX9q5drc6","x3LDeuN6r3","Z4I1vKZamH","dhSuHsoy9t","uJScX2TRI7","DLhzMkZANm","IjTwP3weIF","a00b55Drn0","Waim6KASQ8","uN6r3fcJOy",
-"HfyNQlkMUA","VIlwPokgRi","he9IAfcJOy","LDk6f8cVD3","yEfy9aDGtS","jtn0X1j5L8","MK07YIn3NS","lH1ktgtCA5","Ul4a1XflUq","ni2v1WreyP",
-"jiVBP2TRI7","Y1mC0tl72W","GXdoHFFDui","iB08lKr8ys","W3VFH0MR5X","F6PT2zbIYY","zQt6Q7fsYM","fqypyFLsph","XyPZNvkCHH","euZA5QClRL",
-"QWxoTTwano","e6e4zDcpWB","HP433Ss0Zu","CIShGs7Mxk","GWqqXSbRYy","55rfB5VZjS","uAWypFVMxo","vLsmShE1Ql","CK5W75nmWv","jfREuAOgEe",
-"tlILtZJTXH","pAhR1dhSuH","4dEz6DLhzM","L7cGcRACuj","zQt6QG1RhS","i3pydPYBf4","FLsphbZLvS","zFgtBxciqp","jtn0XQWxoT","jzUqRdQ586",
-"7ku1p5Drn0","gf8rIatef2","XyPZN29QAz","FhtglG1RhS","IRh48ZuDtD","FjHXRXyPZN","bZLvSe6e4z","QWxoTFnPFB","kB5nPuQIcz","zY1GYo8Uyd",
-"lkMUAcQOnv","m4bxU4QMc9","uZPqgcmXIX","9iGoT2Yz7E","ZzJHWRkQke","fLNg8EdBKc","ni2v1In3NS","Waim6uPX7G","lweGyjS1aj","7lUXZjtn0X",
-"7X3uyru4UG","djsrvRmDcr","k85AeBpYhV","x3LDeCxVEf","gjUTuJIqXi","JIqXi16lHc","oVQp6StlDJ","pWiOsF6PT2","HRxd8Nxx9V","uTacxSbRYy",
-"prNT6lpF6W","uoStw580YD","LewvMxXTI4","5IhmGfaHir","prNT6RACuj","JRJQBC2Irc","uTacxUmaEv","RBhp0K4GS8","DcpWB2TRI7","nFqikxReec",
-"nnP8oDz1R3","Ss0Zun1pmO","jfREuDz1R3","5IhmGvOqCE","zmLYDRACuj","mX2GE5nmWv","t59lR14FLR","GXdoHNAFuw","tuDyShSSvQ","uQIczFGzgp",
-"9y4lwlpF6W","BCxeCuAWyp","7hyVv2Yz7E","dhSuHuZPqg","RsQUqatef2","RsQUqjtn0X","AOgEehE1Ql","zbIYYfFDrJ","FFDuiXflUq","t59lRYjB9t",
-"RsQUq2Nslm","HfyNQW7cTs","POUYSSs0Zu","uJScXksJby","Gv3FqKr8ys","0BmCyzHF1q","NOHszRxrsm","v8yFNwDajX","Mm8siSs0Zu","AmdQdsoy9t",
-"IjTwPIBe8k","uZPqglXFOB","pT8wukB5nP","cmXIXZuDtD","brhlQNxx9V","vOqCE8FmFH","6AFT0XflUq","5VZjSulk41","lXFOBtjQxs","jiVBPhi5X7",
-"AIYUuUvlv4","BFkb8POUYS","CK5W7oQ87r","MmKGJzHF1q","zbIYYNAFuw","uTacx7X3uy","n1pmOKsjRK","24ARFaDGtS","SjskQhE1Ql","Cp3mZd85a9",
-"K4GS8lm0pD","P6bcgUvlv4","h1zcHiB08l","SmGzv9rlg9","b29RJ7ku1p","b29RJzHF1q","HlUbFF6PT2","t59lRd7vjM","cL0aEjzUqR","k85Ae3weIF",
-"UlU3MAOgEe","F6PT2yluBx","FnPFBprNT6","PYBf4618Di","YjB9taDGtS","TXQ0Z5Namm","dmoS7TXQ0Z","BpYhVBCxeC","5ZaEzdhSuH","fcJOyQssNC",
-"0Wr5yOz8yZ","v2eC3lViBv","e6e4zTXQ0Z","D6rByQChxs","vLsmS8FmFH","Waim6ZzJHW","FxX9qZhwG1","uPX7GWreyP","nlaByyToGW","16lHczqH0W",
-"t59lRjSjS3","In3NStvdkD","MezSWTCgPp","RmDcrLbRTH","4W0TlQ6Lix","Waim6FjHXR","k85AewiHrZ","lweGyJIqXi","tuDySWmadA","hSSvQ0BmCy",
-"bgJAzRsQUq","0ao3lReKEW","7Ow5CReKEW","Zv7z064s8N","Mm8siAmdQd","G1RhSoQ87r","fFDrJdjsrv","S77LHVLTy6","TwanoIn3NS","55rfBXflUq",
-"0KyfsNxx9V","cQOnvAXpwE","zqH0W0BmCy","I7p2aB3qem","uAWypv1Hln","48cHLrz7Ut","ZuDtDuJScX","taOXKVNCPd","3otm6VNCPd","14FLRaez9y",
-"tjQxsGv3Fq","NAFuwgdQsS","kZANmVNCPd","8U2nUIjTwP","7lUXZU3yw5","hYBCK8hJdt","RACujJXljW","FNYIMJKWYR","BCxeCGSQwj","HP433MezSW",
-"14FLRogLgc","YOfrYwDajX","nlaBysqVrf","0BmCyrz7Ut","tuDySWaim6","POUYSiKqhr","14FLRIjTwP","pFrrlY1mC0","Ss0ZuTwano","QChxsdQ586",
-"P6bcgPb1pa","FGzgpuQIcz","CxVEfFcWrW","55rfB5nmWv","Waim63otm6","AgJHQM3zXL","CqqaDHP433","48cHL9rlg9","AgJHQIn3NS","v8yFN1j5L8",
-"QClRLBpYhV","2Yz7EzbIYY","dmoS7zqH0W","fFDrJpWiOs","VBjhzgtCA5","e6e4zv1Hln","hE1QlAOgEe","FcWrWFGzgp","lpF6W9y4lw","uvf7A9XyT9",
-"s7MxkNcICA","Uvlv4Ta8f6","5ZaEzrz7Ut","gf8rImX2GE","yluBx7lUXZ","SWfoujeskS","IjTwP4dEz6","4QMc9pv0i7","kZANmm4bxU","fcJOyZv7z0",
-"pvgjSksJby","s93Ml1LB1L","zY1GYlweGy","G1RhSdQ586","2ZHdklXFOB","29QAzOz8yZ","Ss0ZucmXIX","qUJMdjtn0X","gtCA5StlDJ","yvOMIokgRi",
-"yvOMIa00b5","hE1Ql0Wr5y","prNT6Ss0Zu","C2IrcyluBx","2TRI72hEEU","LDk6ftlILt","RsQUqSWfou","zz4ZU3otm6","FLsphRACuj","CIShG2hEEU",
-"PYBf47hyVv","aFFssOz8yZ","LewvMfqypy","AmdQdSjskQ","6AFT0lViBv","s93MlLbRTH","0BmCyZUnqt","ydG8UQWxoT","uLtKsL7cGc","ReKEWI7p2a",
-"JIqXiRsQUq","suY4xFVMxo","07n1cuAWyp","RzaZAbrhlQ","e6e4zMmKGJ","ru4UGdhSuH","VjCZqi7WMQ","SmGzvokgRi","MK07YuQIcz","AkKTkGv3Fq",
-"pWiOspv0i7","Kr8ysJRJQB","d85a9zQt6Q","i3pyd1v5hH","dmoS7CdyBV","EoToPGrDg7","FNYIMyToGW","MmKGJ9iGoT","FjHXRRpBQm","JRJQBi7WMQ",
-"DLhzM5drc6","QChxsFhtgl","uoStwNOHsz","TXQ0ZiB08l","pvgjSQYxC0","oQ87ratef2","RACujKZamH","2ZHdkVIlwP","blLA9jeskS","7lUXZjfREu",
-"zbIYYcQOnv","qUJMd16lHc","RBhp0SjskQ","0h1b1Yh1hF","Z4I1v1v5hH","1LB1LChuy3","CxVEfG1RhS","rz7Utmz8gx","K20wKxciqp","y94nwyEfy9",
-"tvdkDWMiS3","gdQsSSbRYy","FLsph7Ow5C","ogLgcazIWp","ciuWzKASQ8","7ku1pGSQwj","Oz8yZQWxoT","suY4xZ4I1v","4W0TlxReec","RxrsmBCxeC",
-"9XyT95Namm","I7p2avLsmS","jiVBPDQimp","jfREuIn3NS","2ZHdkIjTwP","aDGtSL7cGc","dmoS72DREs","DG4sT0MR5X","uLtKs9y4lw","jeskSThjNn",
-"6AFT0OUYuF","cQOnvStlDJ","bZLvSChuy3","3otm60Kyfs","8RCUAiKqhr","dmoS7jS1aj","s4786jeskS","MojnPPOUYS","nnP8o29QAz","5iGN5ZUnqt",
-"guMb82ZHdk","suY4xHfyNQ","uQIczTCgPp","MaJQsWDVWJ","64s8NFwEJz","RkQkeWPmlx","h1zcHMm8si","BbwgA1LB1L","AkKTkRBhp0","pAhR1uZPqg",
-"uJScXFPfSE","8TxD7aFFss","Vprf2oQ87r","wDajXFFDui","ThjNnNOHsz","Q6hMCO3iyQ","tuDyS5ZaEz","iKqhrWaim6","XyPZNWDVWJ","mX2GEuoStw",
-"ThjNnyEfy9","Oz8yZJJs5m","euZA5hE1Ql","ogLgcDQimp","taOXKaDGtS","QworuLDk6f","X6Pin0ao3l","Mm8si0PktI","v1HlnS2Dfu","0h1b1RzaZA",
-"uQIczRpBQm","VIlwPzFgtB","uupzkoVQp6","iwzGkP6bcg","W7cTshYBCK","Cfgr3dhSuH","vOqCEfcJOy","yvOMIblLA9","L7cGcix74r","Q6LixHzZT8",
-"tlILtt98iW","Ul4a1StlDJ","taOXKIKxdL","5NammZJTXH","8xEKzZv7z0","Cp3mZPOUYS","IBe8kiqv4k","2ZHdkzz4ZU","AgJHQLDk6f","BFkb8VNCPd",
-"BGaQYNOHsz","RBhp0iB08l","In3NSKASQ8","zmLYDoGu6x","LDk6fuvf7A","aL6AJFFDui","FjHXRhYBCK","9rlg916lHc","yvOMID6rBy","suY4xjzUqR",
-"dpe1vP6bcg","F6PT2HP433","cmXIXlCMxy","9iGoTlweGy","atef2S77LH","lViBvECMvU","PYBf45VZjS","CK5W7mX2GE","VLTy64dEz6","zHF1qguMb8",
-"FNYIMOxWIH","Q6hMChE1Ql","yluBx8cVD3","2NslmfFDrJ","LbRTHGXdoH","hYBCKfqypy","ZuDtDMojnP","qUJMd0PktI","MmKGJ3otm6","0ao3lX6Pin",
-"9y4lwzFgtB","sx5Gl45cIH","xReecW7cTs","d85a9C2Irc","Cfgr3lXFOB","Pb1pajfREu","QnJ1SYjB9t","QYxC0O3iyQ","uQIczuPX7G","hUTw7e6e4z",
-"FwEJzWPmlx","cL0aEHlUbF","4QMc9zY1GY","kZANm7hyVv","MmKGJv8yFN","cL0aEKsjRK","618Diatef2","lm0pDs93Ml","DLhzMBFkb8","mX2GEaFFss",
-"Yf2Ecatef2","1v5hHHlUbF","zFgtB8cVD3","CNHmvwDajX","pFrrltvdkD","LewvMydG8U","ZzJHWYOfrY","pAhR1cShY2","AXpwEl83Ud","0Kyfs64s8N",
-"lj07Q8RCUA","uJScXpT8wu","pWiOsbgJAz","uupzkOxWIH","fqypy0PktI","tvdkD4QMc9","pvgjStAOsr","9iGoTSjskQ","faHirksJby","zQt6QoQ87r",
-"fFDrJni2v1","G1RhSgf8rI","mz8gxnnP8o","Oz8yZCNHmv","zY1GYYw2oU","QChxsCp3mZ","AmdQd7ku1p","tuDySv2eC3","pWiOsDG4sT","zmLYDAmdQd",
-"iB08lUmaEv","HzZT89rlg9","TXQ0Zm4bxU","Q6Lixdpe1v","FNYIMpvgjS","MmKGJxXTI4","oVQp6jfREu","C2Irc0Wr5y","6q6L9Cfgr3","fqypyIn3NS",
-"UlU3MogLgc","MmKGJ64s8N","lkMUAK4GS8","0MR5XMkgy8","HP433Cfgr3","Q6hMCTCgPp","zFgtBW7cTs","kB5nPru4UG","lViBv9GXkX","BGaQYd85a9",
-"yluBxQnJ1S","NOHszPb1pa","d85a9OHaBz","zmLYD2TRI7","8RCUAXyPZN","QChxseuZA5","0PktICNHmv","FwEJzNcICA","l83Ud0BmCy","fcJOyUl4a1",
-"lCMxyprNT6","2ZHdkMGlTF","tAOsr7Ow5C","AOgEeoQ87r","RsQUqQWxoT","GSQwjChuy3","CNHmvVprf2","l83UdK20wK","RzaZAqaofN","QnJ1SS2Dfu",
-"9iGoTjiVBP","iqv4kVIlwP","zFgtBSbRYy","Pb1pahUTw7","G1RhSpAhR1","pT8wuFnPFB","6AFT00ao3l","dpe1v5nmWv","In3NSiKqhr","uPX7GOUYuF",
-"rKDLJwiHrZ","U3yw5K4GS8","8cVD3okgRi","kZANmMGlTF","NcICApvgjS","zQt6QgjUTu","Yw2oUpFrrl","Mkgy8Mkgy8","ni2v1Mm8si","s93MlvLsmS",
-"TwanoQYxC0","LewvMyluBx","64s8NMezSW","QbxXcfcJOy","qaofNdpe1v","Yw2oUuJScX","Uvlv4qaofN","fqypyb29RJ","Ul4a15Drn0","ciuWzx3LDe",
-"ZJTXHIKxdL","DcpWBMmsIo","M6qcGRBhp0","Mkgy8QssNC","RsQUqFhtgl","2Yz7E9XyT9","uLtKsDQimp","Uvlv4lkMUA","NhXduMGlTF","5NammG1RhS",
-"Nxx9VzbIYY","6AFT00YAGH","I7p2ah1zcH","64s8NOHaBz","6q6L99y4lw","a00b54QMc9","vkCHH9XyT9","0BmCyW3VFH","FxX9qrz7Ut","lsQGosuY4x",
-"PYBf4gtCA5","I7p2aLbRTH","7X3uyfmIK1","yEfy92TRI7","QssNCyToGW","v2eC3NAFuw","K20wK9rlg9","4QMc9RBhp0","0YAGHZzJHW","WMiS3ulk41",
-"mX2GEYh1hF","4dEz6POUYS","S2Dfu8cVD3","EOE1oThjNn","7Ow5Cv8yFN","EdBKcQnJ1S","QworuXyPZN","StlDJYf2Ec","ECMvUgtCA5","S2DfuuN6r3",
-"fmIK1FwEJz","vLsmSDQimp","cQOnvRzaZA","lXFOBnnP8o","OUqFMDLhzM","qQxHPv2eC3","jzUqRVjCZq","7fKYUHfyNQ","vLsmS48cHL","iqv4k0MR5X",
-"pvgjS9y4lw","JKWYRd85a9","aL6AJHRxd8","XflUq8TxD7","CNHmvs93Ml","RkQkeTCgPp","hYBCKsx5Gl","ix74rvOqCE","Vprf2DG4sT","P6bcgRkQke",
-"n1pmOCIShG","FnPFBuQIcz","D6rByfcJOy","ulk41QClRL","FVMxoFhtgl","pWiOstlILt","Cp3mZdjsrv","oVQp6v2eC3","zz4ZUo8Uyd","RpBQmYf2Ec",
-"BFkb8618Di","3weIF14FLR","C2Irciqv4k","uupzkjzUqR","y94nwrz7Ut","vOqCEZJTXH","29QAzUmaEv","AXpwECIShG","6AFT0M3zXL","RACujNAFuw",
-"vLsmS9iGoT","v8yFNNOHsz","dmoS7MaJQs","gf8rIFPfSE","MmKGJFxX9q","O3iyQSWfou","FGzgptvdkD","CdyBVpWiOs","EdBKcpiJSk","5VZjSW7cTs",
-"MaJQs7X3uy","fcJOy0ao3l","kB5nPsoy9t","CIShGv8yFN","WMiS3hYBCK","0BmCys4786","euZA5Q6hMC","AXpwEd85a9","IBe8ki3pyd","8xEKzJkzUn",
-"Zv7z0uZPqg","WPmlx9eoRc","hUTw7yEfy9","CqqaD9GXkX","7lUXZ9XyT9","y94nwlkMUA","8TxD7vOqCE","yofH3KsjRK","7Ow5Caez9y","cQOnv5Drn0",
-"taOXKLewvM","djsrvAIYUu","2ZHdkqQxHP","O3iyQGv3Fq","xXTI4K20wK","45cIH4QMc9","1v5hHlj07Q","BbwgAD6rBy","4QMc9oVQp6","QClRL5Mg9r",
-"blLA9m4bxU","QClRLydG8U","RBhp0L7cGc","jSjS33otm6","KASQ8rz7Ut","5drc6prNT6","EOE1ozHF1q","wDajXnFqik","lm0pDlXFOB","K4GS8iB08l",
-"TCgPpPOUYS","WaWsvXflUq","4QMc9pvgjS","QworuwDajX","gtCA5DG4sT","48cHLAOgEe","uN6r3hYBCK","4dEz6zFgtB","wDajXuTacx","Nxx9VCdyBV",
-"ix74r8TxD7","jSjS3lCMxy","uvf7AJ2mQi","n1pmOXyPZN","okgRidjsrv","24ARFpiJSk","FwEJzLewvM","Vprf2okgRi","qaofNNcICA","4QMc9ZuDtD",
-"0MR5X6AFT0","pAhR1GrDg7","dmoS7RkQke","FNYIM2TRI7","rz7UtCNHmv","MmsIofcJOy","M3zXLCqqaD","SbRYyXyPZN","jzUqRnnP8o","S77LHIRh48",
-"iqv4kEdBKc","iqv4kNAFuw","d7vjM8cVD3","SWfou16lHc","9eoRcBGaQY","WreyPFhtgl","W7cTsM6qcG","zHF1qGv3Fq","v8yFNCfgr3","8cVD3QClRL",
-"pFrrl7fsYM","9eoRc5Mg9r","CIShGBpYhV","0MR5XcQOnv","2TRI7VBjhz","MmsIok85Ae","ulk41tl72W","lweGykB5nP","rhl0JvLsmS","fLNg8wDajX",
-"9y4lw4QMc9","fLNg8lweGy","0Kyfsuupzk","aFFsssuY4x","EOE1o3weIF","FGzgpThjNn","8U2nUKASQ8","S2Dfuuvf7A","7fKYUZv7z0","IjTwPuupzk",
-"o8UydMojnP","KASQ8KsjRK","lsQGotvdkD","i7WMQXyPZN","TwanoPYBf4","G1RhSkZANm","0Kyfs24ARF","Q6hMC8RCUA","Rxrsmsoy9t","xReecv1Hln",
-"5ZaEz7lUXZ","UlU3MIRh48","uAWypwiHrZ","2DREslXFOB","FcWrW9rlg9","DcpWBMaJQs","Gv3FqJIqXi","MK07YfmIK1","brhlQoVQp6","ThjNnEoToP",
-"RkQkeMojnP","s7Mxk9GXkX","24ARF9XyT9","mz8gxyToGW","CdyBVuZPqg","5VZjSVerEA","7hyVvzqH0W","7fsYMb29RJ","6q6L90PktI","dmoS7h1zcH",
-"yofH3VBjhz","0YAGHIjTwP","uPX7GI7p2a","a00b529QAz","O3iyQM3zXL","LewvMFNYIM","blLA9jfREu","vLsmSPb1pa","CIShGjiVBP","a00b5MaJQs",
-"yofH3rKDLJ","zFgtBhi5X7","lViBvOUYuF","ReKEW5Mg9r","AgJHQ45cIH","nnP8o9iGoT","Oz8yZZuDtD","M3zXLciuWz","5iGN5d7vjM","IjTwPF6PT2",
-"fLNg8HfyNQ","2ZHdk2DREs","lm0pDyluBx","lXFOBZv7z0","taOXKnFqik","zFgtBWPmlx","jtn0XIKxdL","M6qcGzz4ZU","iB08l9rlg9","hUTw7RsQUq",
-"IKxdLlm0pD","GWqqX7X3uy","aez9yVNCPd","pFrrlQWxoT","7lUXZMK07Y","cShY2gf8rI","Y1mC04dEz6","RkQkeMK07Y","C2IrcuoStw","6q6L924ARF",
-"7lUXZZv7z0","taOXKlweGy","yToGWhe9IA","x3LDehUTw7","sqVrfP6bcg","C2Ircatef2","8TxD7s7Mxk","zbIYYGSQwj","J2mQihi5X7","VBjhz8hJdt",
-"Twanorz7Ut","2DREsRkQke","LewvMs93Ml","1LB1LB3qem","HlUbF8hJdt","FjHXR24ARF","8RCUA8U2nU","VNCPd14FLR","rz7Ut9iGoT","qQxHP7hyVv",
-"2ZHdkrKDLJ","gjUTujtn0X","FcWrW4W0Tl","IRh48RmDcr","yluBxGXdoH","m4bxUzqH0W","pFrrlOUYuF","AkKTkmz8gx","yvOMIjSjS3","s4786pmeCd",
-"JKWYRzY1GY","CxVEfIjTwP","ix74rEoToP","MmsIoNcICA","AXpwEdmoS7","AXpwEC2Irc","pT8wu7Ow5C","x3LDeI7p2a","NAFuwOxWIH","J2mQi0Kyfs",
-"fqypygjUTu","uJScX64s8N","gIYvE5ZaEz","NOHszGrDg7","uJScXAIYUu","jSjS3LbRTH","b29RJLbRTH","rz7Utdpe1v","DG4sTQssNC","WaWsv2Yz7E",
-"16lHciB08l","OUqFMzbIYY","45cIH14FLR","fLNg89y4lw","piJSkcmXIX","LDk6f1v5hH","7fKYUh1zcH","kB5nP45cIH","WMiS38xEKz","aFFssMmsIo",
-"uTacx9rlg9","guMb8mz8gx","pmeCdQWxoT","fmIK1uQIcz","3otm69y4lw","P6bcgtaOXK","HRxd8VjCZq","7ku1pReKEW","pmeCds7Mxk","CdyBVGv3Fq",
-"ZhwG1l83Ud","Yf2Ec8xEKz","AkKTkD6rBy","i7WMQmX2GE","4W0TlXflUq","QssNCfaHir","KASQ8RkQke","iB08ltjQxs","rKDLJNcICA","qUJMdEdBKc",
-"I7p2aNcICA","P6bcguN6r3","7hyVvKZamH","YjB9ti7WMQ","MojnPyvOMI","5Drn0FwEJz","ZhwG15VZjS","B3qem8RCUA","9GXkXlXFOB","3weIF0h1b1",
-"FnPFBblLA9","tuDySFnPFB","QChxsi3pyd","iqv4ke6e4z","sqVrfFxX9q","FcWrWjSjS3","iB08lsoy9t","iKqhry94nw","yluBxAkKTk","i7WMQ16lHc",
-"BFkb8OxWIH","hE1QluAWyp","v1HlnyofH3","DQimp8RCUA","okgRiBpYhV","SmGzvsx5Gl","BFkb8VerEA","MezSWazIWp","FnPFBVjCZq","ix74rydG8U",
-"BFkb8pv0i7","pAhR1vLsmS","BbwgAzz4ZU","pFrrlRBhp0","NAFuwCxVEf","lsQGot59lR","wDajXa00b5","lCMxyuJScX","CK5W7XflUq","t59lRxciqp",
-"wiHrZjSjS3","UmaEv4dEz6","fmIK1aez9y","yluBx8TxD7","cQOnvgjUTu","0ao3lW7cTs","lsQGo7fsYM","hUTw7Ss0Zu","t98iWuLtKs","tl72W9iGoT",
-"fcwDazqH0W","WPmlxJXljW","8TxD745cIH","xXTI4fFDrJ","hSSvQ5drc6","MK07YlweGy","Z4I1vpFrrl","h1zcHi7WMQ","7fKYUQssNC","aL6AJB3qem",
-"VjCZqt98iW","JKWYRHzZT8","nnP8oECMvU","zQt6QTXQ0Z","TXQ0ZcmXIX","pmeCds4786","KZamHyToGW","gdQsS6AFT0","piJSkiKqhr","KsjRKAmdQd",
-"BpYhVOHaBz","5iGN5RmDcr","WDVWJkZANm","aez9yRsQUq","FcWrWAmdQd","QYxC0piJSk","POUYSrhl0J","BGaQYCp3mZ","0KyfsHzZT8","JJs5mMK07Y",
-"9iGoT16lHc","7Ow5CzY1GY","9y4lwhUTw7","AOgEeGWqqX","NAFuwJKWYR","pv0i70MR5X","xXTI4Kr8ys","v8yFNlsQGo","uZPqgNxx9V","1j5L85Namm",
-"IKxdLUmaEv","d7vjMEdBKc","2Yz7ESs0Zu","Kr8ysjSjS3","MmsIo7lUXZ","7fsYM55rfB","4QMc9i7WMQ","KsjRKvkCHH","RmDcrWaim6","hSSvQNAFuw",
-"RACujs4786","FVMxob29RJ","PYBf47X3uy","F6PT2OUYuF","O3iyQy94nw","VjCZqVBjhz","CK5W7FjHXR","GSQwj9rlg9","wiHrZRpBQm","FPfSEuoStw",
-"OHaBzRsQUq","FLsphhi5X7","CqqaDyluBx","EdBKccQOnv","0MR5Xuvf7A","tAOsrZzJHW","Chuy3Ul4a1","0KyfspFrrl","gIYvEiB08l","soy9tfFDrJ",
-"MojnPjzUqR","MezSWNhXdu","nnP8oulk41","JkzUn9XyT9","VerEA24ARF","ZzJHWxXTI4","UmaEvdmoS7","8TxD7vLsmS","mz8gxAIYUu","fFDrJiwzGk",
-"Mkgy8lm0pD","S77LHAOgEe","BbwgASWfou","euZA5pT8wu","pT8wuS2Dfu","nlaByRkQke","EdBKcBbwgA","hSSvQXflUq","v2eC3a00b5","Zv7z0jeskS",
-"Yh1hFStlDJ","OHaBzv2eC3","aDGtSmX2GE","kB5nPMGlTF","RsQUqReKEW","XflUqwDajX","hYBCKjtn0X","JXljWcShY2","aDGtSuPX7G","Uvlv41LB1L",
-"MK07YlCMxy","i7WMQ0Kyfs","v8yFNKZamH","nFqik7X3uy","YjB9tSWfou","aDGtS7Ow5C","Pb1pa2DREs","b29RJo8Uyd","NOHszNhXdu","YOfrY5iGN5",
-"h1zcHVjCZq","nlaByBbwgA","yofH3guMb8","9rlg9Waim6","Uvlv4d7vjM","KZamHWreyP","5NammZzJHW","iqv4kaL6AJ","rhl0JpT8wu","nlaBy64s8N",
-"1LB1LDcpWB","WreyPWDVWJ","OUYuFjiVBP","IjTwPdhSuH","AmdQd2ZHdk","LDk6fn8pJ9","uQIczuoStw","yvOMIogLgc","lXFOBv8yFN","FPfSEHRxd8",
-"uJScXEoToP","CNHmv7fsYM","VBjhzh1zcH","QYxC0U3yw5","Uvlv4piJSk","wDajXSs0Zu","0BmCyQChxs","NcICApiJSk","kB5nPjtn0X","soy9tTXQ0Z",
-"qQxHPOz8yZ","QYxC0HP433","Z4I1vQ6Lix","5Namm45cIH","580YDMGlTF","FcWrW8hJdt","NAFuwEOE1o","IBe8kSWfou","5VZjSv8yFN","LewvMWmadA",
-"ZzJHWReKEW","Cfgr3Ta8f6","qaofNCqqaD","JRJQBzz4ZU","ciuWzCK5W7","0PktIZJTXH","tuDyS5IhmG","BFkb8FnPFB","8cVD3RzaZA","taOXKdhSuH",
-"S77LHjtn0X","sx5GlYjB9t","tvdkD16lHc","ix74rzFgtB","tAOsrs7Mxk","FFDuiBbwgA","I7p2aOUqFM","n1pmOlsQGo","Uvlv4580YD","5VZjS0h1b1",
-"9GXkXbrhlQ","ZzJHWy94nw","3otm6pWiOs","Cfgr3vOqCE","mX2GEFGzgp","NAFuwFGzgp","mz8gxblLA9","L7cGcsqVrf","GSQwjI7p2a","BGaQYFNYIM",
-"AmdQdrhl0J","8FmFHciuWz","DcpWBuZPqg","iKqhrfmIK1","WMiS3FNYIM","MmKGJMmsIo","JIqXizz4ZU","29QAzEoToP","kZANmqUJMd","Gv3FqtjQxs",
-"QbxXcVBjhz","qaofNMojnP","55rfBS77LH","2Yz7ECdyBV","MezSWogLgc","HfyNQzQt6Q","CdyBVtvdkD","CdyBVKASQ8","LewvMdjsrv","5ZaEz24ARF",
-"t98iWWPmlx","JKWYRWaim6","QClRL5nmWv","2TRI7gdQsS","7hyVvCdyBV","jSjS3KZamH","8hJdtCIShG","Z4I1vrz7Ut","JRJQB7fKYU","JRJQBqaofN",
-"sqVrfhYBCK","piJSk8cVD3","WPmlxJJs5m","cQOnvhSSvQ","Gv3Fq580YD","RsQUqzqH0W","QChxsjSjS3","RsQUqTCgPp","ZzJHWQ6Lix","KZamHChuy3",
-"lCMxyzbIYY","2DREsdhSuH","7fsYM2Yz7E","6AFT0JkzUn","7Ow5CTXQ0Z","yToGWWmadA","MmsIoNAFuw","n8pJ9HP433","I7p2aJJs5m","v2eC3s93Ml",
-"dQ586dpe1v","n8pJ9tlILt","F6PT29XyT9","EoToPyvOMI","CxVEfLbRTH","ZJTXH8hJdt","L7cGcSjskQ","AmdQdEOE1o","Z4I1vjtn0X","lCMxyuN6r3",
-"kB5nPUl4a1","ZUnqtlsQGo","RBhp0fFDrJ","FwEJzRzaZA","Zv7z0blLA9","WMiS3J2mQi","RsQUqjS1aj","lweGyZUnqt","9XyT9MaJQs","VNCPdiKqhr",
-"qQxHPU3yw5","iKqhr7X3uy","xReecS77LH","s93MlQ6hMC","ru4UGC2Irc","lkMUAv2eC3","VjCZqRACuj","VLTy6Yh1hF","BbwgAzHF1q","qQxHPokgRi",
-"2DREs7hyVv","CK5W7VLTy6","48cHL1v5hH","QssNCFwEJz","GrDg755rfB","tlILt2ZHdk","dhSuHzqH0W","taOXKVLTy6","ru4UGeuZA5","64s8NYf2Ec",
-"faHirMezSW","1j5L8fmIK1","QbxXck85Ae","SjskQFFDui","GWqqXRzaZA","s93MlrKDLJ","tjQxslViBv","pAhR1PYBf4","7X3uygtCA5","29QAzSjskQ",
-"prNT6JKWYR","TXQ0ZThjNn","atef2QYxC0","aFFsspmeCd","VerEAZ4I1v","rz7Ut9rlg9","M6qcG5Mg9r","7Ow5C29QAz","8RCUARxrsm","RkQkev2eC3",
-"FFDui0ao3l","No0Qbm4bxU","fFDrJVprf2","Ss0Zu2TRI7","aez9y4dEz6","9eoRcOUqFM","BpYhVogLgc","qUJMd24ARF","euZA5EOE1o","0BmCyaDGtS",
-"ru4UGxXTI4","RmDcroGu6x","gIYvEQnJ1S","gjUTujSjS3","qaofN9iGoT","l83UdJKWYR","HfyNQpAhR1","64s8Nhi5X7","pWiOsKsjRK","ix74rtAOsr",
-"lViBvWMiS3","VLTy6wiHrZ","lpF6WQClRL","hi5X7NAFuw","29QAzv1Hln","kZANmDQimp","6q6L9BCxeC","pWiOs6q6L9","Cp3mZtaOXK","s7MxkUl4a1",
-"FxX9qMK07Y","Waim6VLTy6","Q6LixX6Pin","JIqXiUvlv4","2hEEUMGlTF","bgJAzHRxd8","y94nwfFDrJ","3otm63weIF","PYBf4taOXK","gIYvEW7cTs",
-"t59lRWMiS3","lH1ktZ4I1v","pv0i7hSSvQ","NAFuw0Wr5y","fcJOyhSSvQ","Uvlv4fcwDa","aez9y9GXkX","GrDg7uvf7A","SmGzvhi5X7","WaWsvKr8ys",
-"taOXKRpBQm","zz4ZUrhl0J","K4GS8uN6r3","soy9tmX2GE","hSSvQzmLYD","Cfgr3POUYS","n8pJ9WPmlx","x3LDennP8o","yvOMIydG8U","fmIK1UmaEv",
-"FLsphWMiS3","s7Mxkd85a9","5VZjSlweGy","uN6r3rhl0J","CNHmvpmeCd","ZzJHWni2v1","yluBxhe9IA","QworuWreyP","RmDcrJXljW","M6qcGD6rBy",
-"QbxXcDz1R3","PYBf4wDajX","Dz1R3PYBf4","azIWphi5X7","prNT6Mkgy8","yofH35Mg9r","zqH0W55rfB","d7vjMLDk6f","1LB1LKASQ8","uZPqgTXQ0Z",
-"FPfSEbgJAz","aFFsszHF1q","JkzUns4786","nlaByzY1GY","5Mg9rReKEW","Kr8ysuAWyp","IRh48MGlTF","piJSkJ2mQi","vOqCEazIWp","lH1ktMojnP",
-"LDk6fdhSuH","ix74riqv4k","4QMc9mz8gx","uupzkKr8ys","lCMxyuZPqg","tlILtLewvM","gf8rIeuZA5","pWiOsFPfSE","d85a9e6e4z","tjQxsTwano",
-"7ku1pgjUTu","aL6AJsx5Gl","aez9yJXljW","8U2nU2TRI7","QworuP6bcg","MmsIoni2v1","oGu6xTa8f6","zY1GYi3pyd","s4786iwzGk","uPX7Gdpe1v",
-"cL0aEWmadA","GWqqXQ6Lix","J2mQiaez9y","S77LHIn3NS","QnJ1SuTacx","BCxeCM6qcG","2NslmYOfrY","8FmFH24ARF","3otm6aFFss","RmDcrSWfou",
-"24ARFlXFOB","zmLYD5IhmG","RpBQmlViBv","WMiS3RBhp0","RmDcrWDVWJ","zHF1qcmXIX","sx5GlfmIK1","KZamH8U2nU","9GXkXM3zXL","TwanopmeCd",
-"k85AeSbRYy","FVMxoHlUbF","CqqaD5drc6","8FmFHTa8f6","FNYIMQWxoT","CdyBVQ6hMC","7lUXZ5nmWv","Z4I1vHzZT8","CxVEfECMvU","dmoS7ru4UG",
-"5Drn0JIqXi","B3qemNo0Qb","OUYuFQYxC0","WPmlxUlU3M","AmdQdprNT6","suY4xwDajX","AOgEeFVMxo","FjHXRVNCPd","CxVEfpT8wu","XyPZNL7cGc",
-"MK07Y55rfB","ru4UGuPX7G","HP4330Wr5y","okgRiRBhp0","s7MxkXyPZN","8FmFHOUqFM","Z4I1vFwEJz","MmKGJCIShG","tvdkDNcICA","EdBKcIn3NS",
-"MK07YQWxoT","FcWrWFFDui","d7vjMVerEA","In3NShE1Ql","taOXKG1RhS","zFgtBMezSW","SbRYy8RCUA","uLtKslpF6W","9iGoTRmDcr","QYxC0vOqCE",
-"DG4sTjfREu","dhSuHdpe1v","uTacxFnPFB","5iGN5uAWyp","JXljWO3iyQ","WMiS3AOgEe","tvdkDyToGW","8cVD3pT8wu","2DREscL0aE","okgRiRxrsm",
-"Gv3FqVprf2","9GXkXlViBv","fcJOyiB08l","cmXIXMmKGJ","MGlTFJIqXi","No0QbK20wK","fFDrJuN6r3","WMiS38RCUA","16lHclkMUA","2ZHdkkZANm",
-"VBjhzIn3NS","o8UydksJby","2hEEUQ6Lix","8hJdt14FLR","4dEz6uAWyp","3weIFLDk6f","6q6L9GXdoH","rz7Ut4QMc9","S77LHbgJAz","7hyVvXflUq",
-"ECMvUAmdQd","lweGyi7WMQ","S2DfuRsQUq","VjCZq5ZaEz","rhl0Jsoy9t","S2DfujS1aj","IKxdLVprf2","L7cGckB5nP","2Yz7EjS1aj","Yw2oUVBjhz",
-"9rlg9S77LH","s47865IhmG","X6PindmoS7","BGaQYjeskS","Twanogf8rI","nFqikfFDrJ","sx5Gl2DREs","X6PinXflUq","uTacxGXdoH","ZJTXHzHF1q",
-"64s8NF6PT2","ix74ruZPqg","jS1ajpmeCd","ulk41m4bxU","fcJOyzQt6Q","Q6hMCi3pyd","ulk41bgJAz","ni2v14dEz6","LbRTHa00b5","5Drn029QAz",
-"8U2nUs93Ml","7fsYMsx5Gl","uQIczHfyNQ","CxVEfqUJMd","9rlg9J2mQi","uZPqgjS1aj","5IhmG5nmWv","M6qcGcShY2","LbRTHsqVrf","ix74r5Namm",
-"gIYvECNHmv","fFDrJQworu","taOXKI7p2a","W7cTsfcJOy","VIlwPuLtKs","F6PT264s8N","Yw2oUyofH3","uoStw2TRI7","0Kyfssoy9t","2NslmOHaBz",
-"gIYvEaFFss","ReKEWCK5W7","WMiS3lweGy","IRh48HfyNQ","sx5Gli3pyd","Rxrsmdpe1v","tvdkDRxrsm","2ZHdkTCgPp","tl72WQ6Lix","Cfgr3blLA9",
-"QnJ1She9IA","ni2v1yluBx","x3LDe2Nslm","OxWIHi7WMQ","XflUqtuDyS","FPfSEwDajX","blLA9WreyP","WaWsvI7p2a","3weIFB3qem","0PktIjfREu",
-"ZuDtDFcWrW","RkQke2Nslm","HP43307n1c","lj07Qv2eC3","7fsYMix74r","AXpwERsQUq","hUTw7HzZT8","yofH3L7cGc","ksJbyRpBQm","64s8NgIYvE",
-"L7cGcfmIK1","MaJQsWmadA","lpF6Wiqv4k","ZUnqtfmIK1","zY1GYCdyBV","8xEKzBpYhV","OxWIH6q6L9","ECMvUEdBKc","VjCZqgdQsS","45cIHPYBf4",
-"2TRI7KsjRK","FcWrWzqH0W","ydG8UUvlv4","fcJOyd85a9","ZUnqt2hEEU","VNCPdOUYuF","5Mg9rG1RhS","7X3uyMkgy8","zY1GYpAhR1","piJSkIBe8k",
-"QWxoTciuWz","5nmWv3otm6","Ss0ZuXflUq","RsQUq4QMc9","PYBf416lHc","uTacxnnP8o","d7vjMJ2mQi","5ZaEzzmLYD","SWfouprNT6","7Ow5C7hyVv",
-"i3pydbZLvS","U3yw5Ul4a1","YOfrYIn3NS","a00b5X6Pin","t59lRRsQUq","lXFOBJKWYR","QbxXcIKxdL","HlUbFs4786","LewvMatef2","pFrrlgtCA5",
-"n8pJ9MmsIo","0MR5XqUJMd","RpBQmNOHsz","GWqqXpFrrl","9iGoTjzUqR","brhlQhSSvQ","OHaBzZhwG1","zQt6Qo8Uyd","gIYvEprNT6","blLA9QssNC",
-"azIWpLewvM","FjHXRyToGW","Nxx9V7fKYU","7fsYM6q6L9","bZLvSFwEJz","JkzUnd7vjM","hi5X7W7cTs","euZA5fLNg8","lpF6WKsjRK","Pb1paIKxdL",
-"hi5X7NhXdu","aDGtSRmDcr","d85a9FFDui","uAWypEdBKc","jtn0XZ4I1v","Uvlv4hUTw7","YOfrYuvf7A","16lHc618Di","AOgEe3otm6","s4786lXFOB",
-"9y4lwRzaZA","29QAzZhwG1","RsQUqzHF1q","3otm6tAOsr","fLNg8QChxs","MojnPZUnqt","UlU3MLbRTH","m4bxUAOgEe","soy9t64s8N","blLA9FnPFB",
-"jzUqRoVQp6","DQimp45cIH","FVMxoRzaZA","0ao3ljfREu","v2eC3zQt6Q","gdQsSogLgc","zbIYYXyPZN","5VZjSUl4a1","P6bcgYjB9t","24ARFoQ87r",
-"HP433yToGW","XyPZNatef2","8hJdtgjUTu","JXljWtjQxs","zqH0WMezSW","oGu6xVBjhz","In3NS5ZaEz","gjUTu8hJdt","tjQxstAOsr","s7MxkokgRi",
-"lH1kts4786","mX2GEs93Ml","7Ow5Che9IA","5drc6gf8rI","0KyfsWPmlx","h1zcH9eoRc","8cVD3JJs5m","WmadAS77LH","d7vjMDcpWB","uoStwh1zcH",
-"prNT6RsQUq","AOgEeLewvM","2hEEU4QMc9","4W0TlQYxC0","WDVWJ2DREs","RBhp0MaJQs","Dz1R3zFgtB","x3LDelj07Q","9eoRcFcWrW","uoStw1LB1L",
-"K20wKECMvU","2TRI7Cp3mZ","jiVBPFnPFB","ZuDtDYjB9t","suY4xIKxdL","3weIFoVQp6","Waim6prNT6","hSSvQCNHmv","aez9ypWiOs","5IhmGUvlv4",
-"n1pmOCNHmv","14FLRFnPFB","tAOsrXflUq","hSSvQfcwDa","okgRifmIK1","qUJMdSjskQ","zmLYDaDGtS","SmGzvcQOnv","lj07Qru4UG","h1zcHmX2GE",
-"lXFOBm4bxU","5Mg9rRxrsm","VerEAzY1GY","IBe8kh1zcH","t98iWRACuj","G1RhS6q6L9","24ARF5nmWv","hE1QlFGzgp","Oz8yZlViBv","tAOsriKqhr",
-"iwzGkiKqhr","5drc6dmoS7","WPmlxLDk6f","jeskSRkQke","0YAGHCxVEf","pFrrlhi5X7","atef2yluBx","lm0pDSWfou","hE1Ql07n1c","s7MxkGrDg7",
-"kZANmx3LDe","lj07QBpYhV","VerEAOxWIH","kZANmJIqXi","0Wr5yFPfSE","QChxsdpe1v","pWiOsPOUYS","atef2jiVBP","S77LHuZPqg","Ss0ZuK4GS8",
-"d7vjM3otm6","DG4sTuQIcz","5nmWv5Namm","FNYIMKsjRK","MmKGJ9eoRc","ksJbygIYvE","m4bxULbRTH","TXQ0ZvkCHH","t59lRWDVWJ","Waim6xReec",
-"lXFOB0ao3l","9iGoTNo0Qb","l83UdWPmlx","BCxeC9eoRc","MK07YUmaEv","8RCUAgIYvE","M3zXLPb1pa","jS1ajx3LDe","FFDuiGrDg7","1j5L8ciuWz",
-"OUYuFFcWrW","TCgPptl72W","ksJbylH1kt","HfyNQBpYhV","VIlwPtuDyS","FnPFBOUqFM","ciuWzW3VFH","HRxd8ydG8U","9y4lwuJScX","Y1mC0W3VFH",
-"7X3uyDcpWB","qUJMdFVMxo","Gv3FqIRh48","POUYS0BmCy","qQxHP7fsYM","vOqCE5nmWv","fcwDaoVQp6","qQxHPgdQsS","Pb1paMkgy8","I7p2atuDyS",
-"Zv7z0lj07Q","5nmWvJXljW","FjHXRpiJSk","WreyP6q6L9","kB5nPStlDJ","RsQUq5ZaEz","9iGoTRxrsm","o8Uyd0YAGH","iKqhr0YAGH","Cp3mZQWxoT",
-"tjQxsIjTwP","vkCHHYw2oU","6q6L9t98iW","Nxx9V0Kyfs","rKDLJbrhlQ","2DREsVerEA","vLsmSulk41","5iGN5OUYuF","zHF1qjtn0X","CIShGAIYUu",
-"KASQ8zHF1q","7ku1puvf7A","zHF1qd85a9","14FLR5Namm","RsQUqaL6AJ","FFDuiru4UG","StlDJWreyP","NcICA3otm6","uZPqgWmadA","yEfy9n1pmO",
-"pmeCdksJby","2Yz7Ed7vjM","lCMxyfcwDa","l83UdpT8wu","sx5GltAOsr","LewvMEoToP","4W0TlbgJAz","BbwgA8U2nU","s4786zz4ZU","BpYhVBFkb8",
-"vOqCEHzZT8","7fsYMeuZA5","0BmCyazIWp","6AFT02ZHdk","OxWIH8cVD3","pAhR1kZANm","xciqppv0i7","RsQUqCp3mZ","CNHmvCdyBV","GWqqX5Mg9r",
-"Cp3mZJ2mQi","v1Hln14FLR","HP433xciqp","Y1mC0SbRYy","rz7UttvdkD","lj07Q7fsYM","k85AeMK07Y","sx5Glh1zcH","5NammX6Pin","CK5W7RsQUq",
-"0h1b1jzUqR","wiHrZDG4sT","FnPFB7Ow5C","HRxd8k85Ae","JkzUnP6bcg","pmeCdzY1GY","lkMUA48cHL","aL6AJLewvM","7X3uyYjB9t","uN6r36q6L9",
-"dpe1vni2v1","Uvlv4jSjS3","07n1cTXQ0Z","jS1aj5Drn0","KsjRKQssNC","ix74rK20wK","GXdoH5nmWv","tjQxs0Wr5y","iqv4klViBv","TXQ0ZPYBf4",
-"s4786aez9y","v8yFNDLhzM","SbRYyfaHir","i3pyd580YD","taOXKWaim6","Ul4a1yluBx","JIqXiaL6AJ","jtn0XCIShG","W7cTshE1Ql","xReeclsQGo",
-"XyPZNtjQxs","XflUqyluBx","YjB9t0ao3l","uvf7Alj07Q","07n1c7X3uy","XflUq5VZjS","WPmlxXyPZN","8U2nUQ6hMC","Mkgy8Yf2Ec","zbIYYuLtKs",
-"jSjS3K4GS8","lCMxyguMb8","JRJQBQbxXc","suY4xrhl0J","VLTy6hi5X7","qaofNaL6AJ","P6bcgEoToP","55rfBzbIYY","tlILtMaJQs","ogLgcx3LDe",
-"CxVEf9iGoT","7fsYM9eoRc","5ZaEzWMiS3","9XyT9618Di","WreyP24ARF","hi5X7fqypy","64s8NiB08l","BGaQYaFFss","Gv3FqIn3NS","9iGoTjtn0X",
-"iwzGkjfREu","hUTw7zY1GY","FhtglydG8U","ECMvUNcICA","KZamHlpF6W","vOqCEoQ87r","AkKTky94nw","MmsIoFGzgp","BCxeC16lHc","Cp3mZAIYUu",
-"G1RhShe9IA","SWfouRmDcr","QssNCEoToP","IBe8kI7p2a","iKqhrRmDcr","pWiOsWPmlx","suY4xogLgc","lpF6Wulk41","jS1ajrKDLJ","uoStwksJby",
-"okgRipFrrl","7ku1piKqhr","cmXIX48cHL","Cp3mZW3VFH","9XyT9Ta8f6","m4bxUrhl0J","Vprf2QWxoT","JRJQBCNHmv","uPX7GXflUq","2hEEUdmoS7",
-"he9IAnlaBy","BpYhVUvlv4","WMiS3fFDrJ","s4786POUYS","ru4UGpWiOs","S77LHnnP8o","XflUqhi5X7","QClRL5IhmG","DQimpulk41","29QAzFhtgl",
-"CNHmvzmLYD","ciuWzGSQwj","POUYSF6PT2","5iGN5QYxC0","djsrvZv7z0","cShY2s7Mxk","2Yz7Esx5Gl","8xEKzPOUYS","oQ87rWmadA","NAFuwQClRL",
-"lCMxytaOXK","5VZjSfqypy","FwEJzs7Mxk","JXljWoVQp6","y94nwsuY4x","yofH3MojnP","uAWypmX2GE","BbwgAuQIcz","9y4lwkZANm","prNT6GrDg7",
-"guMb8kB5nP","Z4I1vRxrsm","07n1csoy9t","1j5L8qUJMd","EdBKcJkzUn","tlILtAkKTk","JkzUnWaWsv","he9IAhYBCK","3otm6h1zcH","lCMxyWreyP",
-"0Wr5ywiHrZ","i3pydKZamH","SmGzvHzZT8","vLsmSkB5nP","Mkgy8uZPqg","GSQwjsx5Gl","8xEKz9XyT9","29QAzJIqXi","0ao3lfcJOy","TwanoblLA9",
-"BFkb8lm0pD","SmGzvrz7Ut","zmLYDWMiS3","vLsmSokgRi","07n1cNcICA","fcwDacQOnv","Mkgy8W7cTs","s4786FGzgp","KZamH2Yz7E","IjTwPOUqFM",
-"tvdkDzqH0W","WaWsvBbwgA","soy9tAIYUu","FVMxohUTw7","gjUTuSWfou","1j5L8TCgPp","rKDLJcmXIX","RxrsmMezSW","1v5hHoQ87r","okgRiiKqhr",
-"pmeCdfcJOy","0YAGHJ2mQi","NOHszqQxHP","7fKYUpFrrl","ulk41Ss0Zu","QChxs2Yz7E","14FLRF6PT2","Nxx9Vuvf7A","Pb1patvdkD","RpBQmlXFOB",
-"RBhp0GWqqX","Yh1hFguMb8","lXFOBMkgy8","guMb8lXFOB","tlILtRBhp0","zY1GY0Kyfs","4W0TllViBv","k85Ae7X3uy","soy9tgf8rI","Q6hMCqUJMd",
-"Kr8ysoGu6x","i3pyd5VZjS","b29RJFjHXR","iwzGkBbwgA","HlUbFMezSW","BGaQYn1pmO","n1pmOVprf2","uZPqgX6Pin","AmdQdgjUTu","QssNCfcJOy",
-"5nmWvpFrrl","uAWypsoy9t","ogLgcJXljW","dpe1vNxx9V","hUTw7ydG8U","9XyT98RCUA","4W0TlJ2mQi","pv0i70YAGH","cQOnvru4UG","vkCHHHzZT8",
-"9rlg9BGaQY","M6qcGfqypy","ZuDtD2ZHdk","2DREsAgJHQ","Mkgy8zFgtB","QnJ1Suupzk","cShY2tlILt","9GXkX0PktI","RBhp0b29RJ","jeskS24ARF",
-"3otm6Cp3mZ","rKDLJ8hJdt","GSQwjfmIK1","6AFT0pv0i7","JkzUnoQ87r","KsjRKgjUTu","MGlTFK4GS8","s93MlLewvM","5VZjS7ku1p","v1HlndQ586",
-"MezSWL7cGc","5NammOHaBz","s4786MezSW","StlDJRBhp0","LDk6f5nmWv","14FLRYjB9t","zHF1qyluBx","EoToPTwano","K4GS8lH1kt","i3pyd0BmCy",
-"jtn0X24ARF","4dEz6Ss0Zu","s4786VIlwP","YOfrYZUnqt","LbRTHRxrsm","FhtglrKDLJ","t59lRZJTXH","RACuj5Drn0","FnPFB9rlg9","vOqCErz7Ut",
-"qQxHPAmdQd","VIlwP3weIF","ix74rjfREu","zFgtBTXQ0Z","BCxeCzFgtB","Y1mC0MezSW","VBjhzciuWz","W3VFHCqqaD","cShY2NAFuw","ZhwG1Waim6",
-"lweGydmoS7","dQ586LewvM","YOfrYgdQsS","0KyfsCK5W7","Dz1R3HP433","SmGzvTCgPp","oQ87reuZA5","LewvMHRxd8","GXdoHMm8si","piJSkF6PT2",
-"kB5nPfmIK1","XflUqx3LDe","lCMxyzFgtB","Yw2oU618Di","EdBKc5ZaEz","Y1mC0piJSk","fmIK1tvdkD","QbxXc5VZjS","pT8wuHlUbF","LewvMFjHXR",
-"KsjRKY1mC0","FFDuipvgjS","uN6r3yToGW","nFqikjS1aj","FVMxojS1aj","RACuj4W0Tl","In3NSMm8si","Dz1R3uJScX","SmGzvzFgtB","b29RJ1v5hH",
-"aFFssIRh48","FxX9qPOUYS","8RCUAiwzGk","jzUqR5ZaEz","VjCZqFwEJz","HP4330MR5X","FPfSEsqVrf","4dEz6y94nw","HfyNQdjsrv","QssNCKr8ys",
-"SWfou7hyVv","uTacxnlaBy","BFkb8SbRYy","HzZT8HlUbF","rKDLJP6bcg","fFDrJW3VFH","LbRTH9iGoT","5iGN50PktI","yvOMI45cIH","SWfouxReec",
-"uN6r3n1pmO","M6qcGIjTwP","oVQp6t98iW","Mkgy8guMb8","X6PincQOnv","JKWYRrKDLJ","U3yw5zqH0W","uTacx580YD","uTacxpFrrl","LewvMYw2oU",
-"DG4sTVIlwP","fqypyJ2mQi","yEfy914FLR","0YAGHlsQGo","No0QbOUqFM","KZamHhSSvQ","WaWsvFNYIM","tAOsr16lHc","t98iW8hJdt","24ARFHzZT8",
-"cmXIXjeskS","PYBf42Yz7E","soy9tbrhlQ","Mm8sizHF1q","No0QbiwzGk","fLNg8Ss0Zu","0YAGHxciqp","Chuy3MaJQs","14FLRJXljW","2hEEUlkMUA",
-"zFgtBZv7z0","4dEz65IhmG","DG4sTjeskS","nnP8ofqypy","ThjNnD6rBy","SjskQWDVWJ","Twano5iGN5","4dEz69XyT9","7ku1p5Mg9r","5ZaEzY1mC0",
-"IjTwPUlU3M","2NslmSbRYy","9rlg9azIWp","lCMxyXyPZN","aez9yOxWIH","KsjRKYh1hF","DLhzMzqH0W","l83Ud5VZjS","ZJTXHfqypy","fmIK1AOgEe",
-"SjskQP6bcg","K20wK9XyT9","t98iWB3qem","4QMc9bZLvS","8xEKzjfREu","tl72WtaOXK","MmKGJjS1aj","PYBf4WPmlx","aDGtSWDVWJ","WPmlxcL0aE",
-"CK5W7No0Qb","d7vjMyEfy9","yluBxM6qcG","tjQxsThjNn","MGlTF1v5hH","0KyfsChuy3","VerEACqqaD","s4786VerEA","uAWypNcICA","FVMxoHRxd8",
-"JKWYRFxX9q","o8Uydlj07Q","JkzUnsoy9t","D6rBydhSuH","QWxoTgIYvE","faHirRxrsm","TCgPpJJs5m","lm0pDBCxeC","I7p2a14FLR","BpYhVDLhzM",
-"iB08ltvdkD","IKxdL24ARF","RACujlXFOB","NcICAL7cGc","WaWsvokgRi","5nmWvChuy3","W3VFHX6Pin","8U2nUv1Hln","ni2v1i7WMQ","VNCPdsx5Gl",
-"uupzkRBhp0","he9IAYh1hF","RBhp0OUqFM","ZuDtDSs0Zu","oGu6xQYxC0","1LB1Ltl72W","dmoS78FmFH","tl72WyluBx","8FmFH55rfB","JRJQBCqqaD",
-"Gv3FqQssNC","lH1kt2TRI7","TXQ0Zk85Ae","ZzJHW2DREs","blLA929QAz","sqVrfyvOMI","zFgtB3otm6","n8pJ9iKqhr","aFFssVjCZq","9eoRcVLTy6",
-"SbRYym4bxU","k85AelkMUA","5Drn024ARF","WPmlxEdBKc","HlUbFfcwDa","VjCZq48cHL","zFgtBIjTwP","0PktI14FLR","jSjS3YjB9t","RxrsmP6bcg",
-"JkzUnqUJMd","TCgPpokgRi","2hEEU8hJdt","yEfy9GSQwj","RpBQms93Ml","fFDrJ2DREs","AIYUutuDyS","Cfgr3HlUbF","ZJTXHQssNC","e6e4zRkQke",
-"MmKGJ6AFT0","o8UydgdQsS","guMb85Drn0","8hJdtOxWIH","G1RhSlkMUA","mX2GEoVQp6","7fKYUvkCHH","2TRI7aez9y","zHF1qK20wK","W3VFHCNHmv",
-"Q6hMCzz4ZU","0YAGHPYBf4","hi5X7JkzUn","kB5nPlpF6W","QYxC08RCUA","e6e4zUvlv4","Vprf2EOE1o","nnP8o8FmFH","vOqCEKZamH","SWfouYjB9t",
-"I7p2agjUTu","9XyT9wDajX","Twanoxciqp","gjUTuFwEJz","OUYuFpiJSk","RxrsmsqVrf","RpBQmLewvM","MK07YhSSvQ","0BmCy5Mg9r","Vprf245cIH",
-"5VZjSiqv4k","uPX7Gmz8gx","zFgtBqUJMd","d7vjMQWxoT","nnP8oD6rBy","LewvMxReec","XyPZNWaWsv","618Di2TRI7","hYBCKJIqXi","yEfy9Q6Lix",
-"zqH0WZv7z0","FhtglGWqqX","5IhmGQnJ1S","WPmlxzz4ZU","lCMxyxciqp","l83UdguMb8","GXdoHK4GS8","a00b5lXFOB","HzZT8jfREu","Cp3mZYh1hF",
-"LbRTHIn3NS","VBjhzOz8yZ","t98iWiB08l","No0QbCfgr3","x3LDe7hyVv","4dEz6DG4sT","VjCZqFxX9q","Gv3Fqo8Uyd","CK5W7e6e4z","CNHmvP6bcg",
-"55rfBjtn0X","aFFsslweGy","rz7UtYOfrY","nFqikAkKTk","TCgPpY1mC0","brhlQS2Dfu","DcpWBKASQ8","v8yFNTa8f6","uvf7Adjsrv","W7cTsOUqFM",
-"OUYuF0ao3l","LDk6flj07Q","YOfrYVerEA","7lUXZsuY4x","hSSvQuAWyp","lm0pDVerEA","In3NSyToGW","azIWpFPfSE","ogLgcGXdoH","Dz1R3Cp3mZ",
-"pWiOstAOsr","GXdoHrz7Ut","blLA9Gv3Fq","F6PT207n1c","jeskSd85a9","Cp3mZ7fsYM","VNCPdYOfrY","Zv7z0rKDLJ","55rfBb29RJ","M6qcG8RCUA",
-"5Drn0blLA9","CK5W7wiHrZ","Yw2oUSs0Zu","IRh48X6Pin","7ku1pQ6Lix","mz8gxHP433","zQt6QDG4sT","MGlTFd7vjM","ydG8UxXTI4","64s8NzHF1q",
-"jSjS39rlg9","lweGy2Yz7E","v1HlntvdkD","OUqFMdjsrv","zmLYD2DREs","CK5W7rhl0J","TCgPptlILt","VLTy6yEfy9","POUYSuQIcz","Yh1hF9y4lw",
-"WMiS34dEz6","9y4lwbrhlQ","Mkgy8VNCPd","GWqqX1LB1L","D6rByjS1aj","fcwDa2TRI7","8U2nUVBjhz","euZA5uTacx","azIWpSs0Zu","lXFOBBFkb8",
-"618Di2Nslm","v2eC3CIShG","guMb82Yz7E","7hyVv2DREs","azIWpJXljW","Ul4a10BmCy","Cp3mZe6e4z","HzZT8AmdQd","t59lR5Namm","y94nwcShY2",
-"XyPZNuAWyp","5drc6qaofN","tjQxsJ2mQi","KASQ816lHc","Q6hMCRkQke","GXdoHMGlTF","FwEJzRACuj","vLsmSBCxeC","suY4xlH1kt","ZJTXH9rlg9",
-"MaJQsn8pJ9","cL0aE8RCUA","55rfBbrhlQ","4QMc9NOHsz","lCMxyM6qcG","WDVWJMm8si","iB08lAIYUu","9iGoTCK5W7","djsrvVprf2","0ao3l0MR5X",
-"618DiPb1pa","piJSkzQt6Q","QChxsCfgr3","CK5W7sx5Gl","DQimpL7cGc","YjB9tF6PT2","uQIczM3zXL","n8pJ9oVQp6","9XyT9WmadA","OUYuFfqypy",
-"5ZaEzOUYuF","dhSuHNAFuw","djsrvHP433","AgJHQ9y4lw","9rlg9bgJAz","45cIHRACuj","EoToP8U2nU","OUqFMPOUYS","KASQ8LewvM","hE1Ql9XyT9",
-"gtCA5vOqCE","iwzGkoGu6x","RmDcrgf8rI","4W0TlFhtgl","7fKYUGv3Fq","OxWIHsx5Gl","AgJHQhUTw7","IRh48vOqCE","aez9yDz1R3","IBe8khUTw7",
-"BCxeCThjNn","NOHszVprf2","uJScXk85Ae","DLhzMReKEW","1LB1L2DREs","vOqCEQYxC0","EdBKcvOqCE","DcpWBPb1pa","sx5Gl4W0Tl","sx5GlNOHsz",
-"WMiS3zY1GY","yvOMI7fKYU","7X3uyNo0Qb","uN6r3BGaQY","aez9yBCxeC","uvf7AIKxdL","JKWYRrz7Ut","TwanoVBjhz","Gv3FqtAOsr","djsrvuupzk",
-"5drc6MmsIo","3weIFMm8si","5IhmGatef2","NAFuwBGaQY","HRxd8HP433","0KyfssqVrf","CNHmvKr8ys","9rlg9euZA5","o8UyduN6r3","OUqFMVBjhz",
-"8FmFHGv3Fq","29QAzzbIYY","WmadADQimp","rz7UtHfyNQ","Q6hMC29QAz","9GXkXK20wK","Waim6Yw2oU","FwEJzTXQ0Z","dQ58607n1c","FjHXRv8yFN",
-"ECMvUsuY4x","TwanotAOsr","guMb82TRI7","sx5Gl5iGN5","pAhR1cL0aE","CdyBVZUnqt","FhtgluTacx","d85a91LB1L","RkQke5Drn0","pAhR1tjQxs",
-"StlDJe6e4z","5ZaEzEdBKc","zY1GYs93Ml","64s8NoQ87r","G1RhSpT8wu","ksJby5Namm","FPfSElweGy","jiVBPFwEJz","FhtglTa8f6","uPX7GEOE1o",
-"580YDFLsph","5NammOUqFM","StlDJQClRL","IBe8kcQOnv","qUJMdCIShG","KASQ8Pb1pa","lH1ktRsQUq","W3VFHMGlTF","0KyfsRmDcr","iKqhrD6rBy",
-"vkCHHtaOXK","cmXIXzbIYY","L7cGcjzUqR","fcwDaStlDJ","2ZHdkHP433","Yh1hFh1zcH","SbRYyGSQwj","OxWIHuN6r3","prNT64QMc9","MGlTFiwzGk",
-"hE1QldmoS7","xciqp3weIF","ru4UGFVMxo","GSQwjHRxd8","2ZHdk8RCUA","ECMvUCNHmv","MK07YwiHrZ","CdyBVqUJMd","RsQUq29QAz","pmeCdBpYhV",
-"soy9tv2eC3","CNHmvRsQUq","pvgjS618Di","sx5Gll83Ud","GrDg7QbxXc","fLNg8rz7Ut","9iGoT5Namm","1v5hH2Yz7E","uJScXS77LH","NhXdu2hEEU",
-"LewvMix74r","s7MxkQ6hMC","L7cGcRkQke","Yf2Ec8cVD3","JIqXiNo0Qb","7hyVvlH1kt","4dEz6Mkgy8","EoToPHP433","7X3uyguMb8","IRh48S2Dfu",
-"Zv7z0JkzUn","pv0i7vkCHH","X6Pinru4UG","SbRYyReKEW","NcICAI7p2a","NhXdulXFOB","aDGtS55rfB","0YAGHRBhp0","Z4I1vFhtgl","guMb8QssNC",
-"jfREul83Ud","IRh48iqv4k","RzaZAv2eC3","hUTw79iGoT","kZANmRmDcr","QnJ1S2ZHdk","tuDySnnP8o","jSjS3kZANm","pvgjSG1RhS","fLNg88RCUA",
-"yluBxXyPZN","5iGN58RCUA","jzUqREOE1o","5NammYf2Ec","yToGWFnPFB","QWxoTa00b5","cL0aEh1zcH","pv0i7pFrrl","O3iyQn8pJ9","16lHcix74r",
-"zmLYDW7cTs","5VZjSOHaBz","dpe1v8TxD7","MmsIoJXljW","FVMxojeskS","tlILtZUnqt","fLNg85Mg9r","IBe8kWMiS3","WDVWJWreyP","RBhp0SbRYy",
-"qaofNOUYuF","KZamHyvOMI","uAWypGv3Fq","2ZHdkjS1aj","Yh1hFHRxd8","ix74rix74r","pWiOsiB08l","tlILtIRh48","prNT6gtCA5","In3NSbZLvS",
-"WreyPOz8yZ","VIlwPkB5nP","i7WMQlkMUA","LDk6fRkQke","CNHmvnlaBy","7ku1pwDajX","VjCZq3weIF","ZJTXHMK07Y","9rlg9ogLgc","gtCA5QChxs",
-"fmIK15IhmG","8RCUAjeskS","1LB1LcShY2","POUYSVLTy6","RzaZARpBQm","SmGzvReKEW","soy9ts4786","WreyPqaofN","WaWsvxReec","WMiS3WDVWJ",
-"s4786Yw2oU","i3pydF6PT2","YOfrYulk41","gtCA5jfREu","yToGWQClRL","dhSuH6q6L9","Q6hMCStlDJ","64s8NCdyBV","pFrrlCqqaD","lj07QC2Irc",
-"AOgEeDz1R3","uJScXAmdQd","b29RJyvOMI","cmXIXrKDLJ","Z4I1vCIShG","tl72WFcWrW","n8pJ9Qworu","QssNC0PktI","lViBv3weIF","YjB9tlsQGo",
-"RmDcrSjskQ","uvf7AThjNn","v2eC3ix74r","lH1kt4dEz6","CdyBVP6bcg","HlUbFfmIK1","GrDg75drc6","mX2GEbgJAz","oGu6xtAOsr","BpYhVn8pJ9",
-"HzZT8euZA5","Ss0ZupT8wu","lsQGo8TxD7","iB08lFVMxo","4W0TleuZA5","SjskQhSSvQ","0PktIDz1R3","lkMUAtAOsr","AkKTks93Ml","2TRI7W3VFH",
-"M6qcGiKqhr","G1RhSlsQGo","SbRYyNxx9V","uvf7AvLsmS","SWfouQnJ1S","xXTI4WMiS3","i7WMQGSQwj","hi5X7azIWp","8TxD7QssNC","aFFsslCMxy",
-"FnPFBrKDLJ","2hEEUJIqXi","P6bcgAkKTk","zz4ZUFPfSE","Zv7z0NcICA","fqypyiKqhr","I7p2adhSuH","lsQGoNcICA","o8Uydhi5X7","GrDg73weIF",
-"MezSWOUYuF","rz7Ut1v5hH","JXljWmX2GE","WaWsvW3VFH","fcwDad85a9","6AFT0BCxeC","zFgtBpiJSk","Gv3FqBGaQY","guMb8OxWIH","JIqXipv0i7",
-"BGaQYZ4I1v","FGzgpJKWYR","DLhzMzY1GY","QChxs3weIF","9iGoTvkCHH","8FmFHcShY2","DLhzM48cHL","6AFT0mz8gx","aez9yGWqqX","FVMxoOHaBz",
-"S77LHHRxd8","WPmlxbgJAz","9GXkXgdQsS","WmadACfgr3","AIYUuEdBKc","DLhzMY1mC0","EdBKcMezSW","suY4xzY1GY","gdQsS3weIF","EdBKcTCgPp",
-"U3yw5BCxeC","HfyNQAOgEe","GWqqX4dEz6","iwzGkYjB9t","6q6L9RBhp0","hUTw77ku1p","QworuRBhp0","zHF1q6q6L9","pv0i7Nxx9V","s4786IjTwP",
-"BbwgAulk41","Uvlv45drc6","DcpWBhE1Ql","pFrrl5ZaEz","POUYSbZLvS","DQimpOxWIH","No0QbZhwG1","AOgEeYw2oU","EoToPpWiOs","XyPZNlViBv",
-"OHaBzUmaEv","AIYUu0h1b1","RpBQmvLsmS","mX2GEVNCPd","HlUbFv8yFN","LDk6fWMiS3","AmdQdJkzUn","WDVWJVNCPd","OHaBzpiJSk","6AFT0VIlwP",
-"n1pmO5drc6","GSQwjvkCHH","WPmlxvLsmS","2DREsQ6hMC","FPfSEIjTwP","CNHmvpiJSk","ZUnqtjtn0X","2DREsk85Ae","TXQ0Z7fKYU","14FLRCdyBV",
-"IRh48VBjhz","Chuy3VjCZq","kZANmIn3NS","0ao3lG1RhS","45cIHMmsIo","WPmlxP6bcg","kZANmTXQ0Z","9y4lwWaWsv","FLsphDLhzM","PYBf4YjB9t",
-"yluBxP6bcg","JJs5mVprf2","ThjNnGXdoH","P6bcg8U2nU","X6PinIn3NS","fqypyt98iW","lpF6WlsQGo","TXQ0Z2DREs","BbwgAhSSvQ","ydG8U4dEz6",
-"QnJ1SQbxXc","o8Uydru4UG","P6bcgogLgc","ulk41SjskQ","7X3uyIRh48","suY4xMkgy8","a00b5uvf7A","0YAGHCK5W7","rKDLJpAhR1","fcwDaydG8U",
-"24ARFM3zXL","9iGoTatef2","P6bcgaFFss","lkMUA5Namm","ydG8Um4bxU","VNCPdHP433","lCMxySbRYy","e6e4zQssNC","n8pJ9tuDyS","FVMxov1Hln",
-"fcwDafLNg8","IRh48POUYS","DQimpfaHir","jeskSGWqqX","Uvlv4HP433","BpYhVEdBKc","AmdQdCdyBV","yofH3KZamH","8TxD7FnPFB","Dz1R3aL6AJ",
-"iB08lAOgEe","RpBQmWaWsv","yToGWfqypy","C2Irci3pyd","oGu6xMK07Y","M6qcGs7Mxk","uPX7Gv1Hln","pAhR1D6rBy","XyPZNjtn0X","IKxdLKZamH",
-"pFrrlThjNn","Gv3FqYf2Ec","JRJQBaez9y","wDajXSjskQ","KsjRKy94nw","2TRI79eoRc","7Ow5C55rfB","lkMUANo0Qb","UmaEvbZLvS","EOE1oS77LH",
-"cShY2In3NS","zbIYYogLgc","TCgPpDz1R3","ciuWzNo0Qb","ZhwG1e6e4z","F6PT2Pb1pa","HlUbF7fsYM","8RCUALbRTH","9iGoTQWxoT","y94nwHP433",
-"wDajX6q6L9","AkKTk7ku1p","t59lRG1RhS","7X3uyFnPFB","5Nammn8pJ9","2TRI7HlUbF","QworuY1mC0","FcWrWThjNn","BGaQYRxrsm","M3zXLFLsph",
-"POUYSe6e4z","TXQ0ZjiVBP","jS1ajNcICA","WmadABbwgA","Yh1hFrz7Ut","tAOsrMojnP","S77LHuJScX","pmeCdnnP8o","CdyBVVIlwP","8xEKzAIYUu",
-"Qworu0Wr5y","QssNCDQimp","PYBf4k85Ae","VNCPdwiHrZ","Q6LixBCxeC","d85a9n1pmO","MmsIofqypy","yToGWQbxXc","55rfBYh1hF","pv0i707n1c",
-"ni2v1MK07Y","suY4xuTacx","wiHrZlpF6W","VjCZqbgJAz","0BmCyMmKGJ","FVMxorhl0J","jS1ajtuDyS","JKWYRlj07Q","y94nwy94nw","BCxeCvLsmS",
-"Zv7z0nFqik","hE1QlFnPFB","UmaEvfcJOy","v8yFNyluBx","9XyT9lpF6W","HP433M3zXL","lweGyFVMxo","JIqXiMezSW","y94nwzqH0W","cShY2Twano",
-"v8yFNHlUbF","QWxoTWDVWJ","ydG8UP6bcg","NAFuwgjUTu","HP433CdyBV","FPfSE55rfB","TCgPpFhtgl","atef2UmaEv","o8UydD6rBy","jS1ajBFkb8",
-"MmKGJoQ87r","uZPqgm4bxU","FGzgpvOqCE","vOqCEEOE1o","iwzGk2ZHdk","Z4I1vSs0Zu","lH1ktWPmlx","suY4xi7WMQ","7X3uyHzZT8","G1RhSpvgjS",
-"yEfy9FLsph","RBhp0NOHsz","ThjNnprNT6","bgJAzWMiS3","euZA5WreyP","Gv3FqjeskS","7X3uydhSuH","Pb1papvgjS","uN6r39eoRc","Nxx9VQbxXc",
-"KZamHjzUqR","GWqqXYw2oU","qQxHPo8Uyd","9GXkXHfyNQ","cQOnvAIYUu","jtn0XiB08l","mX2GEx3LDe","ix74rMGlTF","Oz8yZzz4ZU","Yf2EcguMb8",
-"lpF6WG1RhS","1LB1Lm4bxU","AOgEeiwzGk","brhlQs4786","M6qcGDQimp","CdyBVAgJHQ","e6e4zVNCPd","hSSvQ2Yz7E","0MR5XCxVEf","suY4xCfgr3",
-"4QMc97fsYM","NhXduFVMxo","UmaEvWaim6","OHaBzSs0Zu","kZANm0ao3l","4W0TlThjNn","Vprf2m4bxU","d7vjMokgRi","dmoS75Drn0","aDGtSS2Dfu",
-"ru4UGmz8gx","jS1ajiKqhr","K4GS8bgJAz","Y1mC0SmGzv","i7WMQt59lR","OxWIHTa8f6","m4bxU3weIF","LbRTH7hyVv","0KyfsMojnP","qQxHP5iGN5",
-"5nmWvCdyBV","BbwgAni2v1","FnPFB1v5hH","HP433Dz1R3","oVQp6guMb8","FGzgp8FmFH","IjTwPKsjRK","lXFOBFwEJz","QbxXcTwano","oVQp61j5L8",
-"QClRLB3qem","yluBxfqypy","y94nwUl4a1","gdQsS1LB1L","0Kyfs8TxD7","5Mg9rXflUq","m4bxUtl72W","oGu6xBpYhV","7Ow5CfFDrJ","FhtglFVMxo",
-"BbwgA29QAz","ZhwG1FPfSE","Z4I1vAXpwE","Vprf22ZHdk","l83UdfaHir","qQxHPzY1GY","EdBKcQ6hMC","TwanoJRJQB","RsQUqy94nw","RzaZAMezSW",
-"lCMxyfLNg8","faHirFNYIM","C2IrcKZamH","soy9tcL0aE","wDajXaL6AJ","X6PinjeskS","a00b5yEfy9","X6Pindjsrv","brhlQQWxoT","pT8wuv2eC3",
-"s4786mX2GE","QworuSmGzv","OUYuFUlU3M","0MR5XIRh48","1j5L8lj07Q","hYBCKv1Hln","xReecbgJAz","zY1GYyluBx","IBe8kn1pmO","i3pydaFFss",
-"gf8rIjiVBP","hi5X7hYBCK","kZANmWaim6","U3yw5QnJ1S","yvOMINcICA","m4bxUNhXdu","lCMxyZ4I1v","24ARFDG4sT","NhXduK4GS8","cmXIXFhtgl",
-"lpF6Wo8Uyd","0PktIAmdQd","zqH0WZuDtD","StlDJfLNg8","l83Uds93Ml","5drc6Rxrsm","LewvMSbRYy","okgRi3otm6","UmaEvRxrsm","M3zXLXflUq",
-"2hEEU0ao3l","3weIFQworu","QnJ1SzFgtB","YOfrYMojnP","AgJHQiB08l","VBjhzY1mC0","y94nwlj07Q","uN6r39XyT9","7lUXZqQxHP","lkMUAQ6hMC",
-"ru4UGzFgtB","tl72WyEfy9","uAWypReKEW","5Drn055rfB","FFDuiix74r","Y1mC05Drn0","oGu6xHlUbF","uPX7Gn8pJ9","MezSW0Wr5y","nFqikyluBx",
-"MmKGJNAFuw","yEfy9soy9t","jtn0XVNCPd","7X3uyzz4ZU","Waim65Namm","kB5nPkB5nP","BGaQY5iGN5","GrDg7M6qcG","xciqpDcpWB","pAhR1Dz1R3",
-"uZPqgBpYhV","nnP8owDajX","s47860PktI","GrDg77fsYM","FcWrWB3qem","HP433Y1mC0","he9IA8FmFH","Vprf2zmLYD","pWiOszY1GY","FcWrWEoToP",
-"0KyfsCxVEf","TXQ0Zi3pyd","pFrrlMojnP","GrDg7ThjNn","Z4I1v7ku1p","SjskQZJTXH","EoToPSs0Zu","soy9tYOfrY","MGlTFSWfou","s93MljfREu",
-"FjHXRlViBv","aFFssi3pyd","jtn0XaDGtS","QChxstl72W","5ZaEzRACuj","XflUqAXpwE","9rlg9pT8wu","GSQwjqaofN","b29RJAgJHQ","bgJAzjS1aj",
-"0PktI0MR5X","MGlTFFwEJz","Chuy3VBjhz","xReecQClRL","zY1GYlViBv","Cfgr3okgRi","ru4UGIRh48","WPmlxNOHsz","WMiS3Gv3Fq","NOHszjeskS",
-"bgJAzfLNg8","s7MxkjiVBP","EdBKc48cHL","dhSuH2ZHdk","pAhR1uvf7A","blLA9hYBCK","oGu6x0Kyfs","okgRiZUnqt","RkQkelj07Q","RpBQmZzJHW",
-"W7cTsuvf7A","W3VFHt59lR","K20wKZuDtD","gf8rIFjHXR","D6rBylm0pD","8TxD7RzaZA","IRh48ReKEW","euZA5Ta8f6","Chuy34QMc9","KsjRKPb1pa",
-"pmeCd0YAGH","0Wr5yS77LH","2NslmuZPqg","TCgPpFVMxo","HfyNQIRh48","yluBxNAFuw","FnPFBs4786","Ss0ZuOUqFM","aFFssuLtKs","XyPZNlpF6W",
-"fFDrJCNHmv","fcwDa8U2nU","tvdkDZUnqt","aFFssd85a9","M3zXL7fsYM","cL0aEEoToP","7ku1pLewvM","DG4sTLbRTH","MmKGJWreyP","U3yw5o8Uyd",
-"Yw2oU7hyVv","AgJHQ580YD","AOgEe6AFT0","5Mg9rEoToP","t98iWjSjS3","48cHLs7Mxk","FxX9qh1zcH","EOE1ol83Ud","Uvlv4tjQxs","Ss0Zu0BmCy",
-"yvOMIuLtKs","K4GS8gf8rI","IRh48okgRi","0Kyfs2Yz7E","8xEKzprNT6","kZANmWmadA","okgRiSbRYy","lCMxy0BmCy","AOgEenFqik","2Yz7EYOfrY",
-"24ARFlH1kt","IjTwPHP433","pv0i7Mkgy8","VerEASjskQ","e6e4zVBjhz","Oz8yZRxrsm","Cfgr3WmadA","GSQwjJ2mQi","OHaBza00b5","M3zXLBpYhV",
-"QChxsLDk6f","pmeCdDLhzM","aDGtSv1Hln","FnPFBUlU3M","jS1ajtlILt","bgJAzpv0i7","ksJbylweGy","J2mQi8U2nU","kB5nPaDGtS","gtCA5U3yw5",
-"MojnP0Wr5y","d7vjM8TxD7","Yw2oUv8yFN","tAOsrPYBf4","iqv4kydG8U","Q6LixYOfrY","K20wKRkQke","azIWpe6e4z","l83UdFhtgl","BFkb8HzZT8",
-"WMiS3yofH3","Q6Lixxciqp","x3LDepvgjS","0BmCyAmdQd","Yh1hFFPfSE","9eoRcxXTI4","aDGtSRkQke","6AFT0oVQp6","iKqhrSs0Zu","Pb1paCqqaD",
-"pvgjSFxX9q","JXljWuQIcz","qaofNF6PT2","suY4xlweGy","OxWIHjfREu","pWiOsEdBKc","2NslmNo0Qb","xReechYBCK","ix74rUlU3M","zHF1qGWqqX",
-"G1RhSVprf2","55rfB9y4lw","LbRTHUl4a1","9iGoTix74r","XyPZNY1mC0","lViBvpmeCd","DcpWBwiHrZ","ReKEW5ZaEz","8cVD3AOgEe","No0QbiB08l",
-"FxX9q9iGoT","rKDLJ5IhmG","QYxC0xReec","xXTI4EoToP","NOHszUmaEv","t98iWfLNg8","U3yw5NOHsz","uvf7AydG8U","pAhR1Mkgy8","RzaZACIShG",
-"m4bxUpFrrl","RzaZAKZamH","Ul4a1mz8gx","Q6hMCWmadA","WMiS3ECMvU","rhl0Julk41","MmKGJYOfrY","HRxd8D6rBy","lViBvFPfSE","oQ87rQWxoT",
-"a00b5dpe1v","hSSvQAXpwE","KsjRKdmoS7","hUTw7HRxd8","zFgtBNOHsz","uZPqgBFkb8","FwEJzmX2GE","zqH0WRsQUq","9GXkXVjCZq","FGzgp64s8N",
-"Waim6G1RhS","zHF1qtaOXK","5iGN5zFgtB","yToGWh1zcH","8TxD7bgJAz","mz8gx8cVD3","AmdQd2TRI7","JJs5msx5Gl","kZANmbgJAz","9eoRcW7cTs",
-"F6PT2MK07Y","yofH3MezSW","aDGtSxReec","JJs5mnlaBy","vLsmShYBCK","0KyfsZUnqt","8FmFH16lHc","jtn0XVjCZq","FxX9q9GXkX","5iGN5dQ586",
-"s93MlqUJMd","EoToP55rfB","2DREsEoToP","4QMc9U3yw5","CqqaDHlUbF","lH1ktVBjhz","FPfSEChuy3","zFgtBQYxC0","Zv7z0MojnP","4dEz6hi5X7",
-"J2mQisuY4x","7fsYMFnPFB","3weIFWaWsv","JKWYRUlU3M","9iGoTZzJHW","9iGoTM6qcG","uvf7ALbRTH","Uvlv49iGoT","cL0aE7fKYU","QChxs1LB1L",
-"tuDySZuDtD","iwzGkuN6r3","5NammUlU3M","5Mg9r618Di","prNT624ARF","BFkb80PktI","s7MxkfmIK1","RBhp0KZamH","WDVWJlsQGo","m4bxUECMvU",
-"Ul4a1pv0i7","azIWp7Ow5C","0PktIOHaBz","TXQ0ZtjQxs","JRJQByluBx","wDajXs93Ml","JkzUnyvOMI","a00b5qQxHP","QClRLkZANm","LDk6fGv3Fq",
-"hUTw7TCgPp","FGzgpGv3Fq","HRxd87fKYU","djsrv4W0Tl","ydG8U7Ow5C","TXQ0ZtaOXK","ZUnqtVjCZq","MK07YuN6r3","s93Mlsx5Gl","ni2v1Pb1pa",
-"UmaEv8RCUA","Pb1paRkQke","TCgPpHfyNQ","NAFuwuAWyp","dQ5865ZaEz","RpBQmTa8f6","pAhR1EOE1o","EdBKcVIlwP","s93MlUvlv4","55rfBB3qem",
-"i3pyd5Mg9r","dpe1vzY1GY","QClRL5VZjS","G1RhSmX2GE","UmaEvvOqCE","s93MleuZA5","Dz1R3nnP8o","2DREsAIYUu","SWfouo8Uyd","iB08lbZLvS",
-"0ao3l0ao3l","ydG8UZv7z0","NOHsztAOsr","POUYSxciqp","RzaZA07n1c","7lUXZBbwgA","yvOMIv1Hln","ZuDtDyvOMI","LDk6fIjTwP","W3VFH5iGN5",
-"kZANmpAhR1","lpF6W7X3uy","RxrsmFVMxo","QnJ1SjiVBP","JkzUnU3yw5","7X3uyzqH0W","MGlTFDG4sT","IBe8kRmDcr","FwEJzVNCPd","IjTwPxciqp",
-"fcwDaNxx9V","CdyBVWMiS3","0h1b12hEEU","9iGoT7X3uy","G1RhSMGlTF","5Mg9r5iGN5","No0Qb5VZjS","618DipvgjS","EOE1o9XyT9","RzaZAJJs5m",
-"9y4lwyEfy9","i3pydpWiOs","B3qemiwzGk","qaofNVLTy6","AgJHQprNT6","580YDQbxXc","aez9yjzUqR","Ss0ZuVerEA","yofH3HlUbF","hUTw7xXTI4",
-"SWfouC2Irc","zFgtBBpYhV","Y1mC09GXkX","iqv4klsQGo","AmdQdbgJAz","tl72WWmadA","FjHXRa00b5","48cHLZzJHW","AgJHQHlUbF","F6PT2d7vjM",
-"4dEz6aDGtS","K4GS8jeskS","9eoRcHP433","45cIHYf2Ec","IBe8kUvlv4","lViBvgtCA5","8RCUARmDcr","jiVBPpAhR1","X6PinjzUqR","tjQxspv0i7",
-"IjTwPkB5nP","4QMc9pFrrl","dmoS7Yh1hF","rhl0Jd85a9","K20wKcL0aE","S2DfuM3zXL","lViBv618Di","WMiS37ku1p","RACujfaHir","JKWYRcmXIX",
-"HlUbF7hyVv","9y4lwulk41","0PktIECMvU","1j5L8W7cTs","ZuDtDECMvU","FLsphRzaZA","K4GS8AmdQd","BFkb8Ul4a1","S77LHb29RJ","Cp3mZs4786",
-"FjHXRxciqp","BbwgAWDVWJ","cShY21j5L8","RBhp0pT8wu","sqVrfRBhp0","Vprf2uQIcz","xReecQssNC","07n1cRACuj","7fKYU0ao3l","In3NSEOE1o",
-"pT8wuo8Uyd","hUTw7YjB9t","UlU3McShY2","CK5W7djsrv","Dz1R3BpYhV","n8pJ948cHL","QworuSbRYy","AOgEeQworu","suY4x5VZjS","GSQwjhUTw7",
-"guMb8VLTy6","BbwgA4W0Tl","OUqFMFxX9q","sx5GlbgJAz","4dEz6kB5nP","ix74rtuDyS","dQ5862ZHdk","tl72WgIYvE","IBe8kAIYUu","ni2v1YjB9t",
-"zz4ZUECMvU","OHaBzjfREu","blLA9SbRYy","Mkgy8GSQwj","oVQp6uLtKs","vLsmSaFFss","Z4I1v7Ow5C","uAWyp7hyVv","yofH3FnPFB","2NslmRkQke",
-"Ss0ZuChuy3","07n1cYw2oU","L7cGcFnPFB","Z4I1vWaim6","StlDJtAOsr","5iGN5WreyP","DQimp9GXkX","JKWYRMaJQs","t59lRkB5nP","aL6AJMezSW",
-"ru4UGNOHsz","hSSvQt59lR","WMiS3uZPqg","ogLgclpF6W","W3VFHyToGW","U3yw5gjUTu","DLhzMSWfou","aDGtS7ku1p","SjskQMGlTF","IBe8kzz4ZU",
-"jtn0Xsoy9t","2Nslm7ku1p","RxrsmVNCPd","29QAzMmKGJ","zHF1qwiHrZ","IRh48t59lR","OHaBzgjUTu","suY4xFFDui","NOHszv1Hln","djsrvqQxHP",
-"gf8rIMmsIo","v2eC37X3uy","v2eC3jS1aj","Rxrsm8RCUA","gIYvERBhp0","s7Mxk5Mg9r","pAhR1hSSvQ","HP4338xEKz","07n1c7fsYM","cQOnvbrhlQ",
-"piJSkBCxeC","uupzkFjHXR","oGu6xOz8yZ","lsQGohE1Ql","9XyT9jiVBP","5IhmGIRh48","FGzgpuN6r3","NAFuwQnJ1S","MojnP64s8N","oQ87rmz8gx",
-"OHaBzOxWIH","lsQGoFPfSE","DG4sTt59lR","JIqXihSSvQ","0YAGHZv7z0","lj07QQ6Lix","zHF1qhUTw7","9rlg92hEEU","ZhwG17fsYM","djsrvnnP8o",
-"uPX7GyToGW","OHaBzqUJMd","uQIczprNT6","pmeCdjSjS3","yluBx7X3uy","sx5GlMkgy8","LDk6fydG8U","YOfrYNo0Qb","FxX9qC2Irc","FcWrWFVMxo",
-"Nxx9VaL6AJ","k85AeSWfou","2ZHdkjfREu","AIYUupWiOs","pv0i77fsYM","C2Irc2Nslm","FcWrWMaJQs","K20wKtAOsr","In3NSn8pJ9","OUYuFyToGW",
-"5drc67lUXZ","Ss0Zu8RCUA","soy9tHRxd8","brhlQvkCHH","FFDuis93Ml","yEfy9iKqhr","atef2fcJOy","CxVEf5drc6","FcWrWRsQUq","5ZaEzfLNg8",
-"he9IAa00b5","m4bxUWMiS3","ECMvUAXpwE","azIWpJ2mQi","AXpwEjeskS","ThjNnmz8gx","5Mg9rC2Irc","5Mg9rgjUTu","5IhmGQ6Lix","hSSvQRACuj",
-"8U2nUvLsmS","azIWpCIShG","8RCUAyluBx","1j5L8Dz1R3","ksJbyKZamH","DQimpRpBQm","OxWIHVIlwP","fcwDaCdyBV","RsQUqx3LDe","uJScXfcJOy",
-"xReec9iGoT","AgJHQjzUqR","Yh1hF5Drn0","K4GS8uupzk","aL6AJlpF6W","fmIK17Ow5C","Gv3FqBCxeC","oGu6xMezSW","atef2I7p2a","yofH3brhlQ",
-"lH1ktLDk6f","EoToPM3zXL","rKDLJ0Wr5y","BpYhVS77LH","JKWYRNcICA","blLA9K4GS8","dQ586S77LH","5NammL7cGc","prNT6xciqp","CxVEf4dEz6",
-"DG4sT0h1b1","ZzJHWfaHir","nlaBylH1kt","yluBx9y4lw","v2eC3WmadA","tvdkDYf2Ec","B3qemrz7Ut","JkzUnFFDui","ix74r3weIF","RsQUqMm8si",
-"jtn0XMojnP","1v5hHeuZA5","fLNg8y94nw","jS1ajNOHsz","4dEz6K20wK","8U2nUY1mC0","TCgPpRACuj","yEfy9dhSuH","WreyPZzJHW","zHF1qM6qcG",
-"rKDLJ6AFT0","x3LDegf8rI","tuDyS618Di","S77LHMkgy8","kB5nPksJby","VjCZqhSSvQ","xciqpdjsrv","In3NSpWiOs","16lHcQYxC0","29QAzMm8si",
-"t98iWtAOsr","yluBxMaJQs","5drc6StlDJ","7Ow5CFVMxo","IBe8kpvgjS","GSQwjtl72W","cShY2IjTwP","FVMxoPYBf4","POUYSQworu","RpBQmuvf7A",
-"iB08lvkCHH","tl72WtuDyS","QssNCMkgy8","uJScXNxx9V","fmIK1m4bxU","cL0aENxx9V","IjTwPVjCZq","sqVrfRsQUq","hE1Qli7WMQ","FwEJz24ARF",
-"UlU3MUmaEv","8U2nUdjsrv","No0QbCqqaD","dpe1v0Wr5y","PYBf4Q6Lix","7fsYMguMb8","0BmCyZv7z0","s7MxkVLTy6","Ul4a1QClRL","7lUXZm4bxU",
-"ZhwG1b29RJ","8hJdtzbIYY","gtCA58cVD3","MmsIov2eC3","16lHca00b5","Q6LixCNHmv","WaWsvPYBf4","zFgtBtlILt","ogLgcCxVEf","K4GS83otm6",
-"uAWypCp3mZ","brhlQrKDLJ","jSjS3tlILt","FcWrWCK5W7","soy9tix74r","gf8rIzqH0W","qUJMdyluBx","JJs5mJKWYR","pAhR19y4lw","MezSWuAWyp",
-"5NammThjNn","FGzgpQnJ1S","9y4lwQssNC","AIYUuUmaEv","ix74rgdQsS","XflUqDG4sT","n1pmO2TRI7","s4786ThjNn","pAhR15drc6","gtCA50Wr5y",
-"FjHXRcL0aE","oQ87r4dEz6","hi5X7d7vjM","s93MlbrhlQ","rz7UtzQt6Q","BpYhVPYBf4","ni2v1DQimp","JXljWyofH3","uupzkfqypy","t59lRZuDtD",
-"VLTy6ZhwG1","wDajX618Di","pv0i7LewvM","aFFssJkzUn","WDVWJYw2oU","lweGy580YD","Chuy3WDVWJ","wDajXUmaEv","SmGzvGSQwj","Gv3FqkZANm",
-"Ta8f6Yw2oU","XflUqqQxHP","uPX7G0MR5X","29QAz9rlg9","U3yw5Yf2Ec","FGzgpt98iW","CqqaDuPX7G","6q6L9lkMUA","prNT68xEKz","7ku1pEOE1o",
-"fLNg8K4GS8","J2mQiCp3mZ","xciqpi3pyd","7fKYURACuj","DG4sTSbRYy","tuDySlH1kt","lsQGoWreyP","16lHcprNT6","618DiguMb8","lpF6We6e4z",
-"2TRI7suY4x","SmGzvaDGtS","piJSkJXljW","8TxD7QChxs","5iGN54W0Tl","zbIYYvOqCE","P6bcgoGu6x","pv0i7qaofN","RACujOUYuF","8FmFHlH1kt",
-"Yw2oUjfREu","zmLYDRBhp0","9GXkXtlILt","uQIczuJScX","HzZT8jeskS","J2mQiLDk6f","ciuWzOz8yZ","bZLvSTCgPp","QWxoTpvgjS","8cVD3nnP8o",
-"XflUqrKDLJ","B3qempmeCd","7lUXZjiVBP","blLA9lXFOB","3otm68xEKz","tAOsrciuWz","Mm8si8xEKz","JJs5m5iGN5","i7WMQJJs5m","PYBf4AkKTk",
-"Fhtgls93Ml","tAOsreuZA5","oGu6xqUJMd","5VZjSnnP8o","uupzkcQOnv","2hEEUl83Ud","euZA5WDVWJ","4W0TlL7cGc","HP433hi5X7","jeskSNcICA",
-"t98iWAmdQd","0ao3l7Ow5C","Cp3mZSbRYy","jfREui3pyd","MmsIoMmsIo","BCxeClpF6W","blLA98xEKz","JkzUn6AFT0","uPX7GCqqaD","RACujW7cTs",
-"vLsmSW3VFH","dQ586l83Ud","FVMxokB5nP","XyPZNZhwG1","brhlQcL0aE","RzaZAs93Ml","jeskS45cIH","Yf2EcaFFss","nnP8oe6e4z","F6PT2pAhR1",
-"Pb1pakZANm","WmadAuupzk","DLhzMv8yFN","aFFsssoy9t","s7Mxk2Nslm","AmdQdYh1hF","CdyBVd7vjM","i3pydGSQwj","aDGtSkZANm","6AFT0W3VFH",
-"9XyT98xEKz","XflUq4dEz6","BFkb8uvf7A","QWxoTIKxdL","EdBKcQbxXc","x3LDeAIYUu","hi5X7FVMxo","WMiS3he9IA","Mkgy8wDajX","lXFOBReKEW",
-"L7cGclweGy","C2IrcRxrsm","7X3uyThjNn","No0QbIn3NS","lpF6Waez9y","s4786v2eC3","MGlTFpv0i7","BGaQYTXQ0Z","tlILtS2Dfu","mX2GEQ6Lix",
-"hSSvQpmeCd","FLsphbgJAz","aL6AJfqypy","jtn0Xx3LDe","5Mg9r1LB1L","tlILt3otm6","t98iWn8pJ9","Oz8yZS2Dfu","hYBCK29QAz","YjB9tm4bxU",
-"lweGyuupzk","EoToPuPX7G","VIlwPTwano","6q6L9uZPqg","zFgtBRpBQm","5Mg9rW7cTs","RzaZAAgJHQ","AgJHQGSQwj","qUJMdoVQp6","lkMUAlViBv",
-"RBhp0HRxd8","FGzgpSs0Zu","djsrvix74r","wiHrZdjsrv","aez9y1LB1L","2NslmxXTI4","M6qcGvOqCE","Z4I1vNAFuw","lm0pDMojnP","xXTI41LB1L",
-"Oz8yZd85a9","5IhmGEdBKc","QbxXcFPfSE","5NammLbRTH","v1HlnGWqqX","2TRI7lj07Q","v1HlnVprf2","1LB1L9GXkX","8U2nU9eoRc","KZamHJIqXi",
-"iwzGk8cVD3","qUJMdIBe8k","dpe1vbZLvS","6q6L9Qworu","QWxoT7ku1p","pv0i7atef2","taOXK0BmCy","ZzJHW29QAz","taOXKaez9y","hYBCKJXljW",
-"xciqpWaWsv","JKWYR9iGoT","v2eC3AgJHQ","FVMxolm0pD","iwzGkVIlwP","AgJHQsoy9t","DQimpkZANm","YjB9tn1pmO","LewvMvOqCE","LbRTHk85Ae",
-"FxX9qG1RhS","KsjRKfmIK1","5VZjS7hyVv","ciuWzlsQGo","jfREum4bxU","KZamH14FLR","jzUqR2hEEU","RmDcrFFDui","zqH0WZUnqt","VNCPdJKWYR",
-"HfyNQ5drc6","DQimpAOgEe","v2eC3OUqFM","B3qemJIqXi","uLtKsiqv4k","NcICAi7WMQ","M3zXL7hyVv","m4bxUuZPqg","vOqCElsQGo","48cHLiqv4k",
-"fFDrJNcICA","vOqCEJ2mQi","s7MxkPb1pa","In3NSFLsph","fFDrJmz8gx","fmIK1jS1aj","lkMUAGSQwj","wDajXRkQke","zz4ZUazIWp","MGlTFQworu",
-"SjskQd7vjM","DcpWBBpYhV","azIWpmX2GE","MGlTFnnP8o","FGzgpK4GS8","uvf7ANcICA","O3iyQ9GXkX","7hyVvd85a9","J2mQi2hEEU","MojnPKASQ8",
-"4QMc90YAGH","Cfgr36AFT0","jS1ajQWxoT","O3iyQqUJMd","aez9yWaWsv","lsQGoRsQUq","ru4UGFnPFB","ThjNnMojnP","cmXIXAXpwE","lweGy2Nslm",
-"JKWYRjiVBP","jiVBPnlaBy","FFDuiwiHrZ","FVMxoFNYIM","PYBf4GXdoH","UmaEv48cHL","HzZT8Dz1R3","hYBCKWaWsv","h1zcHcQOnv","QnJ1SJKWYR",
-"aL6AJt59lR","DG4sTWDVWJ","soy9tHzZT8","IjTwP5Drn0","faHirIn3NS","QChxsd85a9","5Mg9rcShY2","LDk6fRBhp0","F6PT23otm6","m4bxUQworu",
-"WDVWJAXpwE","jeskSBCxeC","bZLvSRkQke","WDVWJmz8gx","QYxC07lUXZ","M3zXLG1RhS","IKxdLG1RhS","pWiOsW7cTs","bgJAzksJby","Yf2Ec6q6L9",
-"7Ow5CKsjRK","m4bxU9XyT9","hSSvQ6AFT0","4dEz6StlDJ","pT8wuRpBQm","Yf2EcPYBf4","ZzJHWqQxHP","RBhp0ZUnqt","2ZHdkCK5W7","qUJMdaez9y",
-"5NammcL0aE","No0QbfcJOy","618DitAOsr","4QMc98cVD3","s4786sx5Gl","Gv3FqReKEW","sx5GlaL6AJ","uLtKsTwano","zY1GYYh1hF","blLA9gdQsS",
-"Ta8f6MmKGJ","Z4I1v7hyVv","xReeckZANm","Q6LixZzJHW","pv0i7yvOMI","5nmWvhSSvQ","v1HlnkB5nP","QYxC0VBjhz","Dz1R3Yf2Ec","FxX9qUl4a1",
-"JIqXi55rfB","lweGy1LB1L","U3yw5lpF6W","XflUqZ4I1v","tl72WMaJQs","uPX7G5Drn0","24ARFs93Ml","ogLgc7fKYU","guMb8DQimp","EoToPogLgc",
-"C2IrcRBhp0","ogLgcFwEJz","G1RhSUlU3M","cmXIXEoToP","IKxdLv2eC3","MGlTFfmIK1","AgJHQhYBCK","uAWypZzJHW","aL6AJFjHXR","Kr8ysOUYuF",
-"MezSWokgRi","vkCHHbrhlQ","3otm6cQOnv","Yw2oUwiHrZ","RzaZAzmLYD","aFFssQbxXc","dmoS748cHL","fLNg8TXQ0Z","RpBQmoGu6x","QworugtCA5",
-"No0Qbhe9IA","yvOMI7Ow5C","Yw2oUydG8U","EOE1o7X3uy","l83UduQIcz","RzaZAl83Ud","zFgtB2ZHdk","FhtgllH1kt","zqH0WXflUq","In3NSjSjS3",
-"d85a9Y1mC0","5NammGv3Fq","cQOnvLDk6f","2NslmogLgc","tjQxsqUJMd","3otm68FmFH","vOqCEWaim6","4QMc92Yz7E","5Drn00BmCy","5iGN5EOE1o",
-"zbIYY4dEz6","bZLvSUvlv4","D6rByv8yFN","cL0aE0h1b1","G1RhStvdkD","NAFuwdjsrv","uTacxbgJAz","uZPqgdmoS7","d85a9WMiS3","5iGN5UlU3M",
-"iqv4kTa8f6","OUqFMulk41","5nmWvEdBKc","BGaQYs7Mxk","pv0i7m4bxU","gtCA5lkMUA","hSSvQ8TxD7","MmsIoZv7z0","TCgPpB3qem","aL6AJF6PT2",
-"jeskSuTacx","soy9tU3yw5","MK07YkB5nP","In3NS7fsYM","Ul4a1Ta8f6","taOXKZzJHW","BbwgAMK07Y","okgRizY1GY","FLsphZuDtD","0Kyfsa00b5",
-"1v5hHlCMxy","brhlQ0Wr5y","MmKGJ8cVD3","GWqqXdjsrv","fFDrJFjHXR","qUJMdReKEW","fqypy0YAGH","d85a9BGaQY","Pb1palkMUA","C2IrcQworu",
-"i7WMQW3VFH","tvdkDogLgc","8RCUAvkCHH","MK07YgdQsS","zY1GYQ6Lix","QssNCGSQwj","t98iWDG4sT","Cfgr3n8pJ9","1LB1LGv3Fq","i7WMQpvgjS",
-"hYBCK7fKYU","SmGzvd85a9","IjTwPBCxeC","wiHrZBpYhV","0Wr5ylm0pD","he9IAXyPZN","pAhR18U2nU","QnJ1S1j5L8","oVQp6YOfrY","FFDui4QMc9",
-"Mkgy87fKYU","iKqhr7hyVv","XyPZNpFrrl","EOE1o2hEEU","b29RJ8RCUA","QworuMm8si","No0QbXflUq","RmDcrYOfrY","CIShGRzaZA","gtCA5tvdkD",
-"n1pmOQ6Lix","uLtKs24ARF","nlaByzQt6Q","1v5hHaDGtS","FjHXR8FmFH","2hEEU8RCUA","ReKEWpFrrl","WDVWJ48cHL","5VZjSQbxXc","jS1ajCIShG",
-"guMb8GWqqX","rKDLJ2Yz7E","t59lRzqH0W","jfREucQOnv","FGzgps4786","WMiS3HfyNQ","yluBxguMb8","6AFT029QAz","CK5W7ru4UG","55rfBC2Irc",
-"k85Aegf8rI","VLTy6zQt6Q","LewvMaez9y","FPfSEzqH0W","GrDg7aez9y","t98iWh1zcH","VjCZqtuDyS","hi5X7LewvM","uQIczvkCHH","yluBxqaofN",
-"4dEz6RACuj","lViBvStlDJ","2Yz7ECIShG","5drc6jzUqR","M3zXLlViBv","m4bxUI7p2a","uZPqgQYxC0","BpYhVDcpWB","EoToP5VZjS","dhSuHAXpwE",
-"UmaEvguMb8","ogLgc8RCUA","FLsphpT8wu","5drc69eoRc","POUYS5drc6","uTacxt59lR","ZUnqtm4bxU","t98iWyofH3","zQt6Qm4bxU","guMb8CqqaD",
-"jfREu5iGN5","i3pydpT8wu","S77LH9iGoT","BbwgAJKWYR","C2IrctjQxs","nlaByQ6hMC","xciqpwDajX","uvf7A6q6L9","zbIYYv2eC3","VerEAFxX9q",
-"lpF6WBbwgA","M6qcGCxVEf","sx5GlCNHmv","lsQGoazIWp","5IhmGzFgtB","lsQGojtn0X","qQxHPZUnqt","pFrrlh1zcH","Y1mC0ZuDtD","tAOsrNcICA",
-"gdQsSXyPZN","O3iyQpAhR1","gf8rI618Di","RBhp0iwzGk","euZA50ao3l","MmsIo0YAGH","jzUqRtuDyS","SmGzvZJTXH","lXFOB9eoRc","yluBxjfREu",
-"Q6Lix5Namm","MmsIoxciqp","tvdkDuZPqg","RBhp0yluBx","l83Ud2ZHdk","8RCUAWMiS3","k85AeJkzUn","FxX9qCK5W7","MmKGJYw2oU","SbRYyM6qcG",
-"FxX9qOUqFM","DcpWB1LB1L","K20wKuZPqg","a00b5Ta8f6","guMb8uLtKs","fFDrJaL6AJ","VLTy6lXFOB","ReKEWb29RJ","Chuy3VNCPd","dhSuHyToGW",
-"U3yw5lXFOB","JkzUntaOXK","7fsYM0h1b1","taOXKpmeCd","uvf7A2hEEU","ZJTXHbZLvS","J2mQimX2GE","HP433Kr8ys","gIYvEMojnP","fmIK1wDajX",
-"MmKGJStlDJ","K4GS8LDk6f","zz4ZUMmsIo","45cIHJRJQB","pWiOs3weIF","TwanoJ2mQi","07n1cMezSW","CdyBVn8pJ9","8RCUA7ku1p","zY1GYlkMUA",
-"hE1QllkMUA","CdyBV580YD","zmLYDCNHmv","tlILt5nmWv","AkKTkFjHXR","hE1QlDG4sT","RxrsmWaWsv","2hEEUCfgr3","WPmlxyToGW","mz8gxIn3NS",
-"I7p2aWmadA","oVQp6uTacx","NOHsztlILt","tlILtRmDcr","BbwgAoQ87r","POUYScL0aE","ix74r9eoRc","U3yw5pAhR1","aDGtSix74r","suY4xDcpWB",
-"EoToPciuWz","yEfy9l83Ud","64s8NyvOMI","Nxx9VGXdoH","yToGWhYBCK","W7cTsoGu6x","fqypyQWxoT","U3yw5aDGtS","7ku1puLtKs","QChxss93Ml",
-"pmeCdfqypy","Yw2oUFVMxo","ydG8UuTacx","8xEKzm4bxU","DcpWBm4bxU","QssNCZzJHW","djsrvpv0i7","l83Ud4dEz6","he9IAiB08l","Zv7z0FwEJz",
-"1LB1L0MR5X","nlaBy7X3uy","SbRYyFjHXR","ix74rs93Ml","C2IrcEdBKc","VIlwPZv7z0","GrDg7tlILt","SWfouuN6r3","9iGoTpWiOs","LDk6feuZA5",
-"BbwgA24ARF","okgRiWaim6","2ZHdkBGaQY","VerEABFkb8","FLsphZhwG1","2Yz7EWPmlx","gdQsSJkzUn","ogLgcIn3NS","2hEEU6AFT0","uoStwpvgjS",
-"oGu6xsoy9t","lsQGoIjTwP","jS1ajaDGtS","vkCHHWaWsv","29QAzpiJSk","tAOsruAWyp","In3NSFxX9q","d85a9AOgEe","Q6LixwiHrZ","2hEEUD6rBy",
-"No0QbGWqqX","okgRiB3qem","Vprf2y94nw","fqypyCxVEf","JkzUnMezSW","NcICAiqv4k","lsQGolweGy","MojnP7ku1p","QYxC00PktI","7fsYMDLhzM",
-"JIqXi580YD","45cIHyEfy9","aL6AJBFkb8","U3yw5EdBKc","dpe1v9y4lw","fcwDay94nw","ZJTXHLbRTH","zQt6QAOgEe","ZhwG1ECMvU","D6rByMmKGJ",
-"NAFuwM3zXL","hE1Ql1v5hH","K4GS8tjQxs","tAOsrWDVWJ","Uvlv4Rxrsm","tvdkDOxWIH","OUqFMokgRi","guMb88xEKz","atef2EdBKc","aL6AJTa8f6",
-"t59lRJkzUn","pv0i76AFT0","2Yz7EpFrrl","MmKGJhi5X7","FcWrWaL6AJ","fFDrJ2hEEU","o8UydIjTwP","FNYIMjfREu","AgJHQS2Dfu","G1RhSYjB9t",
-"djsrvUlU3M","uN6r3AkKTk","oGu6x29QAz","zmLYDsoy9t","uAWyppvgjS","SbRYyh1zcH","uQIczhe9IA","In3NSuZPqg","29QAz7ku1p","guMb86q6L9",
-"iqv4kaDGtS","UmaEvGXdoH","0h1b1NhXdu","BpYhV7Ow5C","b29RJQworu","ZUnqtiwzGk","piJSkhe9IA","BCxeCRkQke","sx5GlRxrsm","Yf2EcVNCPd",
-"rKDLJfFDrJ","P6bcguJScX","lweGyjiVBP","IKxdLmX2GE","BCxeCh1zcH","5drc6pWiOs","t98iW2DREs","aL6AJ5Mg9r","xReecuQIcz","wiHrZlH1kt",
-"NOHszJJs5m","lH1ktOUYuF","5drc6tvdkD","b29RJG1RhS","SjskQOUYuF","JJs5mGWqqX","K4GS8RsQUq","5VZjSBGaQY","KsjRKm4bxU","ogLgcPb1pa",
-"G1RhSjiVBP","29QAzsoy9t","8xEKz6q6L9","KZamHGXdoH","l83UdFFDui","FFDuilj07Q","KsjRKaFFss","XflUqZUnqt","mX2GEb29RJ","ReKEWuoStw",
-"DcpWBAXpwE","WaWsvOUYuF","nlaByaFFss","lViBvsqVrf","Yw2oUgf8rI","lViBvjSjS3","KsjRKS2Dfu","QssNCFVMxo","mX2GEfFDrJ","MK07Y16lHc",
-"aFFssVIlwP","iB08lAkKTk","iKqhrGXdoH","jiVBP7Ow5C","pT8wuMaJQs","tvdkDx3LDe","m4bxUuTacx","NAFuwuZPqg","EOE1oF6PT2","prNT6dhSuH",
-"nFqikWMiS3","hSSvQAkKTk","Nxx9V7lUXZ","vLsmSM3zXL","HlUbFxReec","Yf2EcFnPFB","7hyVvvOqCE","l83UduoStw","C2IrciKqhr","l83Ud8FmFH",
-"9XyT9t59lR","F6PT2qUJMd","tjQxso8Uyd","C2IrcChuy3","OxWIHDz1R3","h1zcHpmeCd","8FmFH5Drn0","tAOsraDGtS","bZLvSMGlTF","VLTy6DQimp",
-"StlDJ8xEKz","C2Irculk41","0MR5X7hyVv","4dEz6ZUnqt","soy9t7X3uy","d7vjMlXFOB","1v5hH4W0Tl","zFgtBuLtKs","jzUqR5Drn0","fFDrJRBhp0",
-"yluBx29QAz","0YAGHXflUq","8FmFHlm0pD","Chuy3iKqhr","HRxd8BGaQY","uQIczlViBv","lm0pDmX2GE","SjskQGv3Fq","RzaZAP6bcg","M3zXL16lHc",
-"ulk417ku1p","TXQ0ZQWxoT","8RCUAS77LH","HzZT8azIWp","8TxD71j5L8","Vprf2x3LDe","7fsYMCqqaD","ogLgcRxrsm","AXpwEk85Ae","S77LHQYxC0",
-"cL0aEazIWp","QworuzbIYY","wiHrZaL6AJ","he9IAlCMxy","yToGW1v5hH","Yh1hFVNCPd","FhtgluZPqg","k85AeGSQwj","aFFssZUnqt","7fsYMuN6r3",
-"uLtKs7Ow5C","QworuRpBQm","FNYIMDcpWB","MGlTFkZANm","tjQxszHF1q","d85a9Ul4a1","kB5nPpv0i7","P6bcgWPmlx","ru4UGDG4sT","tlILtmz8gx",
-"OUYuFpvgjS","blLA9S77LH","zY1GYAkKTk","Vprf2yEfy9","pmeCdM3zXL","oQ87rbrhlQ","wiHrZ64s8N","jiVBPQnJ1S","cQOnvJkzUn","KsjRKHP433",
-"AgJHQFxX9q","XyPZN9GXkX","6q6L92DREs","jiVBPOUYuF","I7p2aC2Irc","CxVEf2TRI7","JKWYRSbRYy","t59lRJXljW","NOHszfcJOy","3weIFyToGW",
-"7Ow5CuLtKs","m4bxUZ4I1v","ksJbynnP8o","SjskQGWqqX","PYBf4iqv4k","9eoRcv1Hln","JJs5m5Mg9r","uJScXkB5nP","5IhmG16lHc","P6bcgmX2GE",
-"2hEEU0Wr5y","b29RJuTacx","POUYSGSQwj","uupzkQnJ1S","i3pydgjUTu","tlILt0BmCy","lsQGoMkgy8","OxWIH5IhmG","ciuWzYf2Ec","zz4ZUNhXdu",
-"Ul4a19eoRc","ZUnqtEoToP","ZUnqt8U2nU","9y4lwuupzk","StlDJCIShG","bgJAzlpF6W","2NslmM3zXL","y94nwLewvM","WreyPSs0Zu","RBhp0aDGtS",
-"d7vjMl83Ud","9y4lwiB08l","xciqpuupzk","ru4UGWMiS3","gjUTu9y4lw","zY1GYBGaQY","9y4lwLbRTH","NAFuw1j5L8","S77LH3weIF","aDGtSiqv4k",
-"b29RJlCMxy","AgJHQt59lR","Chuy3fFDrJ","29QAzPOUYS","uQIczC2Irc","qQxHPiB08l","MGlTF8FmFH","WreyPe6e4z","uTacxru4UG","aL6AJYjB9t",
-"bZLvSWaim6","KsjRKM3zXL","W7cTsMm8si","GXdoHt98iW","5Drn02ZHdk","MezSWIjTwP","IjTwPiwzGk","jS1ajKr8ys","IBe8kSbRYy","KsjRKBpYhV",
-"ZhwG12ZHdk","EOE1o7fKYU","1v5hHbZLvS","FhtglVjCZq","7lUXZUl4a1","o8UydK20wK","kB5nPK20wK","SmGzvbZLvS","dQ586SjskQ","SmGzvVBjhz",
-"ZhwG17lUXZ","sx5GluTacx","d7vjMFVMxo","sx5Gluvf7A","CK5W7jzUqR","tAOsrzY1GY","FNYIMs4786","8hJdtogLgc","W3VFHJIqXi","v8yFN9XyT9",
-"7Ow5CM3zXL","qQxHPwiHrZ","RBhp0BCxeC","FGzgpIn3NS","BbwgAlweGy","sx5GlguMb8","SjskQuAWyp","W7cTssuY4x","L7cGcJXljW","JXljWSbRYy",
-"a00b55iGN5","OHaBzX6Pin","BpYhViB08l","RmDcrqQxHP","WDVWJbZLvS","5VZjSHRxd8","KZamHEdBKc","zbIYYFxX9q","ru4UG6q6L9","yToGWI7p2a",
-"MaJQsQWxoT","K4GS89rlg9","IRh48GWqqX","FGzgpiB08l","QClRLcL0aE","hUTw7MmsIo","RmDcrJKWYR","HfyNQhYBCK","tl72W0h1b1","uN6r3HzZT8",
-"WPmlxNcICA","0Wr5yxXTI4","8hJdtFwEJz","U3yw58U2nU","jeskSIBe8k","uAWyppAhR1","2hEEU0MR5X","cShY2yEfy9","pv0i7Ss0Zu","pAhR1oGu6x",
-"QYxC0BFkb8","UmaEvQYxC0","ZzJHW4W0Tl","580YDAIYUu","2DREsKsjRK","0h1b1wDajX","FcWrWfLNg8","7lUXZKASQ8","AkKTkFhtgl","t98iWPOUYS",
-"7X3uycmXIX","HfyNQ0YAGH","MaJQsiB08l","uJScXVIlwP","azIWpzFgtB","PYBf4pFrrl","qUJMd5nmWv","XflUqgjUTu","QYxC0y94nw","uAWypkB5nP",
-"7X3uyFjHXR","NAFuw6q6L9","8FmFHuoStw","ogLgctAOsr","07n1c07n1c","qUJMdChuy3","vLsmSHfyNQ","pmeCdFLsph","uJScXVNCPd","VNCPduPX7G",
-"ciuWzBpYhV","TwanofLNg8","HRxd8BpYhV","uJScXm4bxU","e6e4zIKxdL","5Drn0y94nw","lpF6WRsQUq","cShY2ZJTXH","AmdQdnFqik","L7cGczqH0W",
-"ru4UGbZLvS","580YDDcpWB","Cp3mZgf8rI","FxX9qIKxdL","cL0aE9GXkX","dpe1vHzZT8","0PktIuN6r3","29QAz5Namm","Ul4a1pAhR1","0BmCy7ku1p",
-"tl72WzFgtB","fqypyC2Irc","VIlwPd7vjM","M3zXLKsjRK","8TxD7ix74r","jtn0XCxVEf","yEfy9lpF6W","tjQxs0ao3l","WDVWJ4dEz6","SmGzvzQt6Q",
-"6AFT0hE1Ql","fcwDagf8rI","F6PT2Mm8si","i7WMQqaofN","fcwDa5nmWv","tlILt9XyT9","FGzgp6AFT0","6q6L9HP433","16lHcZuDtD","MK07Y2TRI7",
-"GSQwjyvOMI","kB5nPjfREu","JJs5mVBjhz","lXFOBG1RhS","nlaByni2v1","xciqpJKWYR","5Drn0LbRTH","MezSWwDajX","wiHrZWaim6","lj07QMmKGJ",
-"GSQwjAkKTk","ZJTXHQClRL","zbIYYMmsIo","Cfgr35Drn0","ru4UGOUYuF","8cVD3cShY2","uPX7GhUTw7","IjTwPNAFuw","n8pJ9d7vjM","NOHszjSjS3",
-"14FLRNcICA","dhSuHGXdoH","RkQkePb1pa","rKDLJjfREu","M6qcGpiJSk","AkKTkuQIcz","pAhR1fqypy","dhSuHnFqik","L7cGcbgJAz","Dz1R3Cfgr3",
-"Ta8f6uvf7A","uPX7GciuWz","ulk41uoStw","sx5GlFGzgp","8xEKzv2eC3","azIWpZJTXH","ThjNnuZPqg","iKqhrStlDJ","5IhmG7fsYM","iKqhrblLA9",
-"0ao3lBFkb8","s47860YAGH","uPX7GVBjhz","e6e4zwDajX","OHaBzDG4sT","tjQxsNOHsz","lm0pD2Yz7E","In3NSS2Dfu","AkKTkLDk6f","0h1b1iB08l",
-"IKxdLYh1hF","NOHszCfgr3","29QAzSbRYy","i7WMQ9GXkX","HRxd8KASQ8","prNT6SjskQ","0PktItaOXK","QssNCB3qem","9y4lwKsjRK","bZLvS8U2nU",
-"Z4I1vix74r","vkCHHJ2mQi","tvdkDMaJQs","ZuDtDL7cGc","vLsmSyofH3","Yf2Ec0h1b1","AgJHQQYxC0","W3VFHgdQsS","ECMvU1LB1L","prNT6euZA5",
-"qQxHP9eoRc","WDVWJsqVrf","8hJdtNOHsz","5iGN5Ss0Zu","5drc6BFkb8","FjHXRjeskS","QWxoTChuy3","5Drn0i7WMQ","L7cGcksJby","5Mg9rguMb8",
-"JKWYRzqH0W","yToGWSbRYy","FNYIMS77LH","1v5hHYjB9t","PYBf464s8N","i7WMQChuy3","lweGyWreyP","POUYS2TRI7","AgJHQSWfou","AXpwEsoy9t",
-"U3yw5Uvlv4","TCgPpbgJAz","xXTI49XyT9","mX2GE8RCUA","X6PinWreyP","MGlTFJ2mQi","gjUTuNo0Qb","lH1ktDG4sT","8U2nUReKEW","VerEAuPX7G",
-"W7cTsK4GS8","iKqhrVBjhz","cmXIXMK07Y","gjUTub29RJ","DcpWBPYBf4","X6PinjfREu","jeskSjiVBP","QworutvdkD","WaWsv580YD","VNCPdAgJHQ",
-"jzUqRn8pJ9","9eoRcSWfou","VjCZqjzUqR","kB5nPzHF1q","5Mg9r8hJdt","45cIHXyPZN","zz4ZUY1mC0","FNYIMRACuj","EOE1ohi5X7","BCxeCKsjRK",
-"64s8N0ao3l","3otm6CxVEf","FNYIMaFFss","9y4lwPOUYS","uJScX2hEEU","uoStwS2Dfu","3weIFuPX7G","guMb8AmdQd","Chuy3jiVBP","0h1b1QYxC0",
-"QYxC0MmKGJ","FjHXRECMvU","Kr8ysVBjhz","lpF6WzmLYD","ulk41NcICA","lj07Qn1pmO","e6e4zJRJQB","AmdQdlH1kt","hYBCKFnPFB","mX2GEQnJ1S",
-"a00b5PYBf4","n1pmOdpe1v","CIShGMkgy8","1v5hHkZANm","v2eC3Qworu","dpe1vChuy3","QbxXcyvOMI","8FmFHe6e4z","Kr8ysFhtgl","RACuj0PktI",
-"P6bcgCp3mZ","uLtKs8xEKz","dhSuHMK07Y","PYBf4guMb8","9y4lwF6PT2","9GXkXpAhR1","XyPZNoGu6x","HlUbFix74r","gf8rIIKxdL","CxVEfF6PT2",
-"zbIYY2TRI7","IBe8kpAhR1","fcJOyfqypy","Dz1R3i3pyd","XyPZNfaHir","fFDrJv8yFN","580YDCK5W7","Kr8ysMK07Y","Q6hMC9GXkX","lH1ktcL0aE",
-"AIYUuEoToP","CIShGokgRi","h1zcHoQ87r","GWqqXhe9IA","5IhmGKr8ys","FFDui9eoRc","64s8NZv7z0","rhl0JAOgEe","jfREuQssNC","pWiOsSjskQ",
-"y94nwIBe8k","2ZHdkW3VFH","AOgEeYOfrY","XflUqEoToP","t59lR64s8N","4W0TlsqVrf","5ZaEzpiJSk","MezSWpv0i7","YOfrY9rlg9","IBe8ksqVrf",
-"RsQUq4W0Tl","JRJQBpT8wu","X6Pindpe1v","DcpWBcL0aE","RBhp0guMb8","IjTwPn8pJ9","5iGN5I7p2a","wiHrZdhSuH","Chuy3yEfy9","8U2nU29QAz",
-"o8Uyd7fsYM","NhXdutjQxs","MmsIolj07Q","7Ow5CJkzUn","djsrvFLsph","WPmlxAOgEe","hi5X7qQxHP","Dz1R35Mg9r","s7MxkGXdoH","lweGyCNHmv",
-"AmdQdZuDtD","RpBQmpvgjS","ZzJHWWaWsv","5drc6Cfgr3","Mm8siBCxeC","0h1b1XflUq","FxX9qNo0Qb","FwEJzjzUqR","2Yz7EGSQwj","sx5GlRpBQm",
-"jS1ajdmoS7","lkMUAOUYuF","faHirO3iyQ","QssNCdpe1v","nlaBy5Mg9r","VerEAzbIYY","FPfSEuvf7A","OUqFM7lUXZ","ru4UGx3LDe","bgJAzs7Mxk",
-"WDVWJlkMUA","07n1cSs0Zu","vkCHH7ku1p","5Drn0he9IA","64s8NI7p2a","n8pJ9Zv7z0","NhXduLbRTH","jfREu2Yz7E","QWxoTuJScX","pvgjSni2v1",
-"nnP8oMaJQs","k85AeFVMxo","CxVEfZJTXH","ulk41UlU3M","jtn0XDcpWB","gjUTuBCxeC","VIlwPsx5Gl","0PktIhYBCK","s7MxkTXQ0Z","BpYhV9GXkX",
-"NhXduYf2Ec","cQOnv1j5L8","pWiOsU3yw5","P6bcguAWyp","NOHszDQimp","5VZjS8U2nU","DG4sTtlILt","i7WMQQbxXc","24ARFfcwDa","ulk417X3uy",
-"aez9yfqypy","n8pJ9OxWIH","cShY2GWqqX","5ZaEzt59lR","48cHLFFDui","RsQUqZ4I1v","Ss0ZuZzJHW","BCxeCjfREu","yToGWoVQp6","5NammoGu6x",
-"No0QbSs0Zu","MezSWD6rBy","e6e4zlH1kt","NhXduSWfou","M3zXLWDVWJ","azIWpn8pJ9","8TxD7gIYvE","SbRYyCIShG","FVMxoW7cTs","gIYvEhUTw7",
-"MmKGJuN6r3","Qworuulk41","QworuoGu6x","29QAzUvlv4","4QMc9Mkgy8","G1RhSazIWp","m4bxUgIYvE","pT8wuIBe8k","HRxd8L7cGc","EOE1oNAFuw",
-"S2DfuzmLYD","Oz8yZsx5Gl","uupzkHzZT8","LewvMY1mC0","Kr8ystl72W","5ZaEzqQxHP","azIWp580YD","F6PT2O3iyQ","zqH0WB3qem","h1zcH45cIH",
-"IRh48FPfSE","5Drn0iwzGk","Y1mC0Yw2oU","fqypyWreyP","qUJMd8TxD7","EoToPjeskS","4W0Tl5iGN5","Qworu5Mg9r","Q6hMC6AFT0","lweGy0BmCy",
-"QnJ1SyvOMI","kB5nPJ2mQi","HlUbFHzZT8","nlaByUvlv4","piJSkuN6r3","BbwgA48cHL","O3iyQiwzGk","J2mQi8cVD3","uPX7GCK5W7","O3iyQP6bcg",
-"pT8wuUvlv4","Q6hMCHRxd8","v2eC3okgRi","0YAGH5VZjS","suY4xAgJHQ","0BmCyuJScX","qaofN2DREs","1LB1LFVMxo","MojnP2Yz7E","QworutlILt",
-"CIShGYw2oU","GWqqXQ6hMC","RpBQmG1RhS","IjTwP5VZjS","Ta8f6nFqik","W7cTs24ARF","pmeCdMmsIo","HRxd8QWxoT","BbwgAECMvU","rhl0J2hEEU",
-"ulk41Pb1pa","24ARFAmdQd","SWfou9iGoT","FGzgp0BmCy","VIlwPRmDcr","MmKGJCqqaD","yToGWvkCHH","i7WMQaDGtS","lpF6WuoStw","oGu6x5Drn0",
-"5nmWvHfyNQ","QworuVerEA","mX2GEpAhR1","lm0pDReKEW","rz7UtTCgPp","16lHcJJs5m","NAFuw55rfB","fcwDaMGlTF","VjCZqVprf2","xciqpWPmlx",
-"lj07QaDGtS","XyPZNRmDcr","OUYuFzY1GY","x3LDeHP433","QYxC0HRxd8","nlaBypmeCd","bgJAzdjsrv","4dEz6FxX9q","xReecJKWYR","G1RhSCNHmv",
-"9iGoTYf2Ec","Gv3Fq6AFT0","oGu6xuLtKs","FNYIMxciqp","rz7UtFnPFB","RxrsmhSSvQ","8RCUA580YD","IjTwP6q6L9","9iGoTlsQGo","v2eC31v5hH",
-"gf8rIHP433","WPmlxOz8yZ","mz8gx64s8N","2Nslm4W0Tl","VBjhzHzZT8","AXpwEVerEA","ciuWzThjNn","QssNCCdyBV","uTacxDLhzM","oQ87r24ARF",
-"7X3uyFwEJz","SmGzvSWfou","2hEEU9GXkX","MmsIoFhtgl","fmIK1yofH3","cmXIXfLNg8","pFrrlGv3Fq","4W0TlCIShG","tAOsrWMiS3","x3LDeDz1R3",
-"FNYIM8FmFH","Z4I1vSbRYy","K4GS824ARF","soy9tKsjRK","SbRYyRmDcr","1j5L89GXkX","gf8rIQ6Lix","rz7UtChuy3","e6e4znlaBy","P6bcgeuZA5",
-"fqypyk85Ae","ksJby8hJdt","PYBf4jeskS","tvdkDUvlv4","uvf7AguMb8","0BmCyuN6r3","K20wK4dEz6","tvdkDuAWyp","CxVEfaDGtS","No0QbhYBCK",
-"oGu6xn8pJ9","K20wKHfyNQ","hi5X7MojnP","580YDlpF6W","hYBCKAXpwE","SWfoukZANm","lCMxygIYvE","iqv4klXFOB","16lHcd7vjM","mz8gxGv3Fq",
-"fFDrJQ6Lix","VIlwPFwEJz","2hEEU9rlg9","kB5nP55rfB","pT8wuK4GS8","vOqCEWmadA","gjUTuzmLYD","QChxsprNT6","1j5L8JJs5m","MK07YUvlv4",
-"ECMvURxrsm","45cIHoVQp6","i3pydzY1GY","K4GS807n1c","uPX7G5drc6","ru4UGgjUTu","5iGN5cL0aE","Ss0Zu0YAGH","qQxHPQ6Lix","7fKYUU3yw5",
-"mX2GEnFqik","0KyfsgdQsS","hUTw7Nxx9V","iqv4kZv7z0","jSjS3GWqqX","faHirk85Ae","oVQp6gjUTu","618DidQ586","oGu6x7hyVv","6q6L9fmIK1",
-"GSQwjNAFuw","SjskQtl72W","lkMUAFnPFB","jiVBPzQt6Q","9rlg9ni2v1","Q6hMCmX2GE","atef2FVMxo","7fKYU6AFT0","0KyfsokgRi","RACujzQt6Q",
-"Mkgy8gdQsS","BGaQYO3iyQ","YjB9tuPX7G","ZhwG148cHL","7hyVvZzJHW","ogLgczmLYD","wDajXQ6Lix","NOHszWDVWJ","G1RhSMm8si","oGu6x1v5hH",
-"9GXkXyvOMI","dhSuHQYxC0","YjB9thi5X7","dpe1vNAFuw","OHaBzlsQGo","dQ586HfyNQ","5Mg9rJKWYR","s93MljzUqR","lweGyciuWz","9GXkXOxWIH",
-"e6e4z0BmCy","Ul4a17fKYU","14FLRCNHmv","DLhzMt98iW","8RCUAJKWYR","CqqaD2Yz7E","AOgEecQOnv","LewvMCIShG","D6rByIBe8k","zQt6QRzaZA",
-"d7vjMTCgPp","TCgPpfLNg8","yluBxdjsrv","AgJHQjeskS","PYBf4d85a9","CqqaD580YD","FcWrW64s8N","M3zXLQYxC0","jS1ajS2Dfu","kB5nPIKxdL",
-"07n1cZhwG1","s7Mxk2Yz7E","Yh1hFuoStw","U3yw5580YD","FLsphQChxs","O3iyQLewvM","D6rByQ6Lix","Uvlv4jeskS","Ta8f6Zv7z0","tuDySfcJOy",
-"POUYSS77LH","uPX7GiwzGk","KZamHQnJ1S","tl72WhYBCK","RmDcrZuDtD","FGzgpReKEW","QworupWiOs","fqypyY1mC0","0YAGH3weIF","djsrvIn3NS",
-"QChxsiKqhr","azIWpfqypy","K20wK580YD","nnP8oUl4a1","ciuWzzQt6Q","GrDg7bgJAz","0h1b1zmLYD","qaofNyofH3","QYxC0lCMxy","9eoRcaFFss",
-"0Wr5y9GXkX","pvgjSdmoS7","gtCA56q6L9","iqv4kkZANm","7Ow5CbrhlQ","Oz8yZ5drc6","qaofNnFqik","MGlTFS2Dfu","7fsYMEdBKc","tjQxsuAWyp",
-"29QAzHlUbF","vLsmSJkzUn","rhl0JVprf2","OxWIHSs0Zu","pWiOsQbxXc","NAFuw0BmCy","lXFOBZ4I1v","RBhp07Ow5C","UlU3Mxciqp","W3VFHmX2GE",
-"pWiOsP6bcg","2Yz7EhE1Ql","VIlwPfaHir","8U2nUtl72W","GWqqXuQIcz","rz7Ut64s8N","v8yFNYOfrY","iKqhr4QMc9","pAhR1VBjhz","YOfrYlweGy",
-"iqv4kJIqXi","1j5L8JKWYR","8RCUAoVQp6","atef2v2eC3","B3qemMm8si","P6bcguoStw","guMb8hYBCK","WaWsvAkKTk","Mkgy8jtn0X","Cp3mZVerEA",
-"FPfSEZuDtD","FGzgpZuDtD","zz4ZUAXpwE","Pb1paOUYuF","n1pmOgf8rI","1LB1LCK5W7","lkMUACxVEf","29QAzfFDrJ","0BmCyLDk6f","dhSuHZzJHW",
-"Waim6MK07Y","zHF1qlViBv","6q6L9tAOsr","WPmlxhe9IA","WreyPzmLYD","Dz1R3sx5Gl","AkKTkqUJMd","Oz8yZ7hyVv","JIqXiatef2","Yw2oUCdyBV",
-"pvgjSCIShG","FxX9qMaJQs","cL0aELDk6f","vOqCEKr8ys","Gv3FqTwano","v1HlniwzGk","fcJOyXflUq","he9IAdhSuH","BFkb8h1zcH","9rlg9v2eC3",
-"uQIcz0PktI","tlILtTXQ0Z","nlaByFNYIM","CqqaD07n1c","FjHXRuQIcz","uQIczBCxeC","8TxD7S2Dfu","AIYUua00b5","W7cTsY1mC0","LDk6fnlaBy",
-"RmDcrn1pmO","SWfouK4GS8","K20wKiwzGk","Yf2EcHlUbF","sqVrfW7cTs","pT8wumz8gx","F6PT2BFkb8","aL6AJIBe8k","bZLvSpv0i7","v1HlnQbxXc",
-"FGzgpuAWyp","YOfrYtaOXK","14FLRuoStw","qUJMdtlILt","1LB1LVjCZq","prNT67fKYU","5IhmGVNCPd","pFrrlMGlTF","kZANmPOUYS","MojnPUlU3M",
-"StlDJ5iGN5","pvgjSfcwDa","Gv3FqWDVWJ","SWfougIYvE","dQ586uupzk","soy9tCfgr3","BbwgAhYBCK","rz7Ut0YAGH","ulk415drc6","CNHmvFwEJz",
-"45cIHFnPFB","ulk41BGaQY","guMb8X6Pin","v8yFNFVMxo","v1HlnZuDtD","RACujpT8wu","SWfouYh1hF","D6rByWDVWJ","FFDuihUTw7","jzUqR8FmFH",
-"SjskQQ6hMC","x3LDexXTI4","e6e4z1j5L8","Chuy37X3uy","yvOMIiqv4k","ni2v1NAFuw","GrDg7UlU3M","KASQ82Yz7E","RpBQm9rlg9","lViBvSs0Zu",
-"Ta8f6h1zcH","ksJby2Nslm","mz8gxRBhp0","MmKGJaL6AJ","gjUTuqQxHP","uTacx2ZHdk","pv0i71j5L8","euZA5Ss0Zu","Dz1R3TXQ0Z","OxWIHtvdkD",
-"QssNCpvgjS","jS1ajMkgy8","VIlwPdmoS7","jeskSgIYvE","0h1b1taOXK","Mm8si9rlg9","IKxdL4QMc9","cmXIXUmaEv","kZANmUlU3M","pFrrl07n1c",
-"OUYuFgf8rI","jiVBPpFrrl","5iGN50h1b1","0PktI8hJdt","t98iW16lHc","lpF6WpFrrl","taOXKNo0Qb","xciqp5Namm","Yh1hF2hEEU","Q6hMCzbIYY",
-"uTacxBCxeC","pFrrlUvlv4","VLTy6vLsmS","9eoRciwzGk","qUJMduPX7G","5drc69GXkX","zY1GYsuY4x","BFkb8Pb1pa","rhl0JQnJ1S","5iGN5JRJQB",
-"fqypyRxrsm","VNCPd24ARF","CdyBVYOfrY","FGzgpsx5Gl","pAhR1JIqXi","0ao3lCIShG","WreyPlXFOB","2DREsv8yFN","U3yw5mX2GE","WmadAxXTI4",
-"VNCPdEdBKc","oVQp6Uvlv4","5nmWvxReec","C2Irck85Ae","Waim6yluBx","vOqCEMkgy8","rz7UtBFkb8","hYBCKblLA9","RBhp0SWfou","uupzkAXpwE",
-"0Wr5y64s8N","5drc64W0Tl","kZANm24ARF","FxX9qdQ586","5Mg9ra00b5","t98iW618Di","QbxXcjS1aj","s4786tvdkD","UlU3MzQt6Q","oVQp6fmIK1",
-"GrDg7uLtKs","iqv4kFNYIM","2ZHdkTa8f6","sqVrfYOfrY","8U2nUU3yw5","sx5GlIn3NS","s7MxkUmaEv","bgJAzhYBCK","oQ87rKr8ys","CqqaD7lUXZ",
-"BGaQYguMb8","Mkgy8LbRTH","v2eC3CdyBV","tjQxsi3pyd","jtn0XtjQxs","5Namm64s8N","aL6AJGv3Fq","ciuWzAOgEe","2Nslms7Mxk","WreyPdmoS7",
-"HP433S2Dfu","3otm6uAWyp","618Disoy9t","FVMxoS2Dfu","CK5W77hyVv","m4bxUNOHsz","P6bcgS77LH","Gv3FqStlDJ","mX2GE3weIF","pWiOsEoToP",
-"zqH0Wgf8rI","vkCHHdQ586","i7WMQpWiOs","YjB9t580YD","lpF6W3otm6","QWxoTuAWyp","NAFuwwiHrZ","jiVBPrKDLJ","Uvlv4AgJHQ","v1HlnGrDg7",
-"ZhwG1jfREu","tAOsrStlDJ","fFDrJatef2","zY1GYlm0pD","BFkb8lCMxy","8xEKzQ6Lix","SWfoutvdkD","RxrsmuQIcz","Waim6uN6r3","QChxsW3VFH",
-"9eoRcYjB9t","brhlQ4dEz6","AOgEeyvOMI","WaWsvMaJQs","B3qemDcpWB","QbxXcqaofN","yToGWkZANm","NhXdud85a9","Ta8f69iGoT","9XyT9o8Uyd",
-"I7p2alkMUA","SbRYy2hEEU","7ku1pI7p2a","pT8wuY1mC0","MezSWMmKGJ","xciqpAOgEe","YjB9tM3zXL","i3pydWDVWJ","7Ow5CDz1R3","ru4UGRBhp0",
-"2TRI7tl72W","Yf2Ecfqypy","24ARFdhSuH","lpF6WTwano","U3yw5oQ87r","zbIYYK20wK","LDk6fAgJHQ","prNT6RBhp0","G1RhSuupzk","5drc6OUYuF",
-"Ss0ZuECMvU","DLhzMcL0aE","5drc6Dz1R3","VBjhzJXljW","B3qemKZamH","piJSkhYBCK","29QAzZuDtD","RkQkedpe1v","55rfB0MR5X","DcpWBlkMUA",
-"jSjS3dhSuH","gIYvEuZPqg","7X3uyRBhp0","x3LDeAXpwE","48cHLRzaZA","s93MlprNT6","FjHXR16lHc","tAOsrM3zXL","AmdQdyToGW","hSSvQrKDLJ",
-"2Yz7E2Yz7E","1LB1LjS1aj","uLtKsKr8ys","uN6r3FxX9q","VjCZq8cVD3","gjUTuulk41","I7p2aCdyBV","fmIK1brhlQ","NcICAsuY4x","jfREutaOXK",
-"iKqhrlCMxy","CqqaDOUYuF","5ZaEzX6Pin","FVMxoChuy3","8FmFHP6bcg","pvgjSCqqaD","ydG8Udjsrv","CqqaDzqH0W","yEfy9a00b5","Kr8ys5Drn0",
-"RBhp0ksJby","jSjS3okgRi","MezSWUmaEv","lViBvIRh48","AIYUu8RCUA","UlU3MAmdQd","NcICAZzJHW","U3yw5FNYIM","64s8NVerEA","iwzGkEdBKc",
-"Ss0Zuru4UG","FLsphCdyBV","JIqXiQnJ1S","EOE1ofLNg8","3weIF0MR5X","gdQsSpv0i7","Mkgy8FcWrW","hYBCKFVMxo","MGlTF5IhmG","t59lRgf8rI",
-"VBjhzuZPqg","Waim607n1c","yEfy9uJScX","lm0pDydG8U","wDajXEoToP","e6e4zXflUq","faHirazIWp","qaofNpvgjS","VjCZq7lUXZ","SjskQ8U2nU",
-"v8yFNv8yFN","qaofN8xEKz","WPmlxiwzGk","OUYuF5nmWv","LDk6fv1Hln","uN6r3RzaZA","AkKTkC2Irc","55rfBzY1GY","RmDcrnFqik","M3zXLbrhlQ",
-"jzUqR2ZHdk","9XyT9CqqaD","lkMUAzqH0W","t98iWG1RhS","lViBvuPX7G","cQOnvbgJAz","5iGN5iqv4k","aFFssFcWrW","zFgtByEfy9","9rlg9hUTw7",
-"pAhR1Rxrsm","Dz1R3sqVrf","RzaZAFFDui","EOE1oQbxXc","aDGtSVBjhz","pFrrlfFDrJ","NhXduIBe8k","P6bcgdjsrv","2hEEU4W0Tl","pT8wupiJSk",
-"Uvlv4xXTI4","IRh48CIShG","WMiS3FLsph","iB08lbgJAz","KsjRKOUqFM","CK5W7ZUnqt","AXpwEWMiS3","Cp3mZhUTw7","fLNg8cmXIX","vOqCEru4UG",
-"gjUTufFDrJ","n1pmOQbxXc","5IhmGzqH0W","uN6r3PYBf4","nlaByuPX7G","AgJHQVjCZq","FNYIMIKxdL","hUTw7LDk6f","ReKEWix74r","s93MlHlUbF",
-"ZJTXH7Ow5C","G1RhS5VZjS","fcwDaNo0Qb","okgRit98iW","7fKYUTwano","jiVBPTwano","0PktIQ6hMC","FnPFBZUnqt","618Di9y4lw","0Wr5yRpBQm",
-"2DREszmLYD","cL0aElXFOB","DQimp2Yz7E","RsQUqlH1kt","xciqpgtCA5","RzaZAK4GS8","W3VFHEdBKc","2DREs2hEEU","o8UydtAOsr","29QAzuTacx",
-"QssNCaez9y","1v5hHQWxoT","sqVrfblLA9","fmIK1JkzUn","ksJby5ZaEz","BGaQYQssNC","JXljWfqypy","0ao3l6q6L9","4dEz6FcWrW","brhlQ7fsYM",
-"CIShGZJTXH","ix74rOHaBz","tl72Wx3LDe","5Mg9r9iGoT","pT8wuxciqp","O3iyQ07n1c","BFkb8lweGy","lweGyqaofN","ZhwG1Y1mC0","FFDuiPb1pa",
-"0ao3lLbRTH","v2eC33weIF","h1zcH29QAz","C2IrcFjHXR","5iGN5zY1GY","AXpwEsuY4x","brhlQBbwgA","VNCPdgIYvE","HRxd8b29RJ","5iGN55Namm",
-"NOHsziwzGk","jfREun1pmO","S77LH7fKYU","gf8rI7X3uy","zz4ZUHlUbF","5Drn0cL0aE","cL0aEdmoS7","oVQp6xXTI4","MmKGJjtn0X","y94nwlweGy",
-"xReecRkQke","8TxD7Twano","W7cTsxXTI4","HRxd8StlDJ","5IhmGprNT6","0BmCyCfgr3","WmadAprNT6","jiVBPFVMxo","StlDJChuy3","AkKTkIKxdL",
-"uLtKsAIYUu","iB08lni2v1","xXTI4CIShG","O3iyQBFkb8","v1Hln8cVD3","zQt6Qs93Ml","NcICA0h1b1","v8yFNjSjS3","7hyVvFVMxo","8hJdt580YD",
-"n1pmOIRh48","tlILtmX2GE","IBe8kNAFuw","xXTI4uQIcz","AXpwEChuy3","9rlg9nFqik","lsQGo9eoRc","FjHXRFxX9q","vOqCEh1zcH","2Nslmiqv4k",
-"GXdoH9rlg9","b29RJCIShG","MmsIoo8Uyd","StlDJi7WMQ","LDk6fTa8f6","FNYIM14FLR","piJSkdjsrv","gIYvEUlU3M","29QAzyvOMI","1LB1Lh1zcH",
-"ksJbyru4UG","t59lRUmaEv","SbRYypiJSk","2Nslm580YD","29QAz580YD","iqv4kfqypy","ciuWzuPX7G","24ARFTa8f6","tAOsrLbRTH","b29RJjtn0X",
-"OHaBz9GXkX","uQIczK4GS8","DQimpP6bcg","AmdQdVprf2","ciuWzlj07Q","Mm8si9eoRc","v2eC3NcICA","pmeCdPOUYS","uZPqgrKDLJ","14FLR7hyVv",
-"cShY2suY4x","0h1b1jeskS","lpF6WM6qcG","wDajXx3LDe","ix74rHzZT8","lXFOBv1Hln","ix74rOUYuF","AIYUu1LB1L","Ta8f6Cp3mZ","Q6LixtAOsr",
-"G1RhS1LB1L","QbxXcM6qcG","zqH0WBGaQY","VBjhzcQOnv","AIYUuQssNC","5drc6GXdoH","K4GS8Qworu","zFgtBVIlwP","WPmlxru4UG","fcwDa3weIF",
-"kZANm9y4lw","S77LHlpF6W","SbRYykZANm","iKqhroVQp6","tjQxsvLsmS","Ta8f6WMiS3","aDGtSfmIK1","VIlwPFVMxo","5VZjSFNYIM","suY4xs7Mxk",
-"lpF6W618Di","2DREsuZPqg","8hJdtm4bxU","lweGy0MR5X","OUYuFzFgtB","s7MxkuoStw","5Drn05VZjS","n1pmOM3zXL","gjUTuZzJHW","qUJMdlm0pD",
-"WMiS30BmCy","Y1mC007n1c","DLhzM55rfB","lsQGo5Drn0","MmKGJlweGy","SjskQFxX9q","HlUbFWPmlx","WaWsvFPfSE","gf8rIF6PT2","cL0aEydG8U",
-"Pb1pa618Di","lm0pDxciqp","8TxD7aL6AJ","0YAGHYOfrY","blLA9Ul4a1","PYBf4fcJOy","OxWIHYw2oU","ZJTXHFcWrW","DLhzMhe9IA","WPmlxJKWYR",
-"Chuy3qQxHP","lpF6WCxVEf","uJScXFcWrW","48cHLoVQp6","K4GS8FcWrW","16lHcnnP8o","DG4sT1LB1L","uN6r3zqH0W","AOgEeuTacx","fcJOyWPmlx",
-"lweGyn1pmO","Yw2oUU3yw5","KsjRKVNCPd","uN6r3hE1Ql","FxX9qciuWz","v1HlnNAFuw","ReKEWogLgc","J2mQiWPmlx","SmGzvfcwDa","4W0TlyluBx",
-"lViBvBCxeC","mz8gxFVMxo","55rfBtaOXK","RACujMkgy8","gdQsSWPmlx","4W0TlguMb8","IjTwPsqVrf","azIWpYjB9t","Q6hMCblLA9","HfyNQ2TRI7",
-"RsQUqBFkb8","JIqXiNcICA","fmIK1FNYIM","euZA5IKxdL","wDajXXyPZN","jSjS3RACuj","7X3uyd85a9","CqqaDFNYIM","Q6LixtaOXK","MojnPBFkb8",
-"24ARFQnJ1S","MmsIosqVrf","Z4I1vJ2mQi","n8pJ9O3iyQ","JkzUnlkMUA","euZA56q6L9","580YDZhwG1","uAWypdjsrv","lm0pDaL6AJ","9GXkXRBhp0",
-"aez9y55rfB","WMiS3pFrrl","QbxXc9GXkX","qaofNFFDui","LewvMuvf7A","azIWpY1mC0","jiVBPGXdoH","SmGzv0h1b1","xReecXflUq","yluBx07n1c",
-"gIYvEv2eC3","2ZHdkFjHXR","qaofNlsQGo","M3zXLkB5nP","uupzkTwano","hUTw7jfREu","zQt6QbgJAz","0BmCylm0pD","jSjS3aDGtS","MK07YAOgEe",
-"taOXKGv3Fq","JRJQBVNCPd","M3zXLvkCHH","EoToPGv3Fq","OUYuFMK07Y","hSSvQM6qcG","i7WMQQnJ1S","AOgEet59lR","v1Hln4dEz6","jSjS355rfB",
-"QWxoTv2eC3","lsQGouAWyp","FPfSEv8yFN","No0QbPOUYS","NAFuwIn3NS","n1pmOjeskS","tlILtuPX7G","MK07Y618Di","d85a9K20wK","lXFOBChuy3",
-"P6bcgAmdQd","0h1b1GXdoH","JRJQBjtn0X","No0QbzQt6Q","Yw2oU5Drn0","k85AeyvOMI","FGzgprKDLJ","tvdkDC2Irc","hi5X7QWxoT","RpBQmOz8yZ",
-"dmoS7K4GS8","hE1Qly94nw","qQxHPwDajX","64s8NThjNn","ZUnqtDcpWB","OUYuFIBe8k","gdQsS8xEKz","tAOsrAgJHQ","uPX7G5Mg9r","kZANmQnJ1S",
-"GWqqXo8Uyd","U3yw5TCgPp","ReKEWVerEA","okgRiNo0Qb","FNYIMaez9y","cmXIXDz1R3","XyPZNaL6AJ","RkQkeCqqaD","TXQ0ZDQimp","Nxx9V6AFT0",
-"AmdQd4dEz6","FPfSEPOUYS","Mm8si14FLR","FFDuiAOgEe","zQt6QNOHsz","Nxx9VAOgEe","azIWpWmadA","uTacxMkgy8","uvf7AyofH3","xReecZ4I1v",
-"OUYuF5VZjS","Q6LixVNCPd","lm0pDgdQsS","iKqhrEdBKc","IBe8khSSvQ","2NslmTCgPp","brhlQnnP8o","aDGtS8cVD3","7hyVvFxX9q","e6e4zWmadA",
-"lkMUAJRJQB","7fKYUfmIK1","jtn0XLDk6f","guMb8Nxx9V","FNYIMCfgr3","wiHrZ5ZaEz","1j5L8pFrrl","HlUbFGrDg7","QbxXc2Yz7E","fcwDalm0pD",
-"DQimpZuDtD","rz7UtJJs5m","piJSkv2eC3","okgRiGWqqX","qQxHPi3pyd","v2eC3618Di","gf8rI9iGoT","QWxoTMmsIo","AIYUucShY2","jfREu9rlg9",
-"OUqFMhSSvQ","UlU3M9GXkX","zQt6Q1LB1L","jeskSgf8rI","lH1kt2hEEU","uPX7GaL6AJ","yluBx55rfB","hE1QliB08l","2ZHdkGXdoH","SbRYy8hJdt",
-"VjCZqzHF1q","2ZHdkM6qcG","TwanorKDLJ","OUYuFBGaQY","CNHmv0Kyfs","oGu6xyluBx","AmdQdBFkb8","KASQ8mz8gx","Chuy3HlUbF","IRh48NAFuw",
-"8U2nUuQIcz","7hyVvt98iW","Q6Lixd85a9","oVQp6RsQUq","AgJHQcL0aE","pAhR10Kyfs","JJs5mQ6Lix","WDVWJW7cTs","tuDyS7X3uy","5drc6ulk41",
-"s4786rKDLJ","64s8NsqVrf","TwanoU3yw5","Ss0ZuZUnqt","S77LHOHaBz","uZPqgCp3mZ","CNHmvZUnqt","7fKYU5nmWv","dmoS7K20wK","pmeCd2DREs",
-"5nmWvMGlTF","fFDrJ7ku1p","EoToPUmaEv","C2IrcuPX7G","tjQxsWmadA","lweGy7fKYU","gtCA5nFqik","55rfBuQIcz","RpBQmM6qcG","gtCA5atef2",
-"5Drn08RCUA","SmGzv9y4lw","3weIFZ4I1v","1LB1Lsx5Gl","ZUnqtOUYuF","No0Qb7hyVv","2NslmNhXdu","Chuy3lsQGo","MK07YlsQGo","wiHrZU3yw5",
-"euZA5bgJAz","4dEz6WDVWJ","AkKTknlaBy","tjQxsfcJOy","CdyBVsuY4x","PYBf4jfREu","hi5X7POUYS","xReecEdBKc","vLsmSuAWyp","soy9taL6AJ",
-"gtCA5rz7Ut","FhtglMm8si","brhlQO3iyQ","rKDLJ618Di","qUJMdVIlwP","ZUnqtRkQke","IjTwPWPmlx","brhlQyvOMI","FFDuiuAWyp","K20wKReKEW",
-"FFDui5Drn0","Yh1hF7fKYU","XflUqzmLYD","CNHmvoVQp6","FnPFBNcICA","qaofN6q6L9","VLTy6MaJQs","tjQxslCMxy","TXQ0ZqQxHP","VBjhzEdBKc",
-"mz8gxix74r","TwanovLsmS","sqVrfS77LH","DQimpCK5W7","oGu6xHfyNQ","GWqqXOxWIH","In3NSVLTy6","x3LDePYBf4","FGzgpM6qcG","AOgEeTCgPp",
-"fqypyM6qcG","gIYvEuPX7G","bZLvSsuY4x","AkKTkoVQp6","5drc66q6L9","cmXIXFcWrW","uAWypZuDtD","MmsIoMmKGJ","v8yFNxXTI4","45cIHazIWp",
-"7lUXZSmGzv","zbIYYOUqFM","2ZHdkzQt6Q","l83UduN6r3","G1RhSHRxd8","VNCPdi7WMQ","jS1ajMojnP","a00b5Qworu","jzUqRNhXdu","blLA94QMc9",
-"Cfgr3Ul4a1","atef2hYBCK","lViBvMaJQs","jS1ajcQOnv","OUYuF9iGoT","DLhzMsqVrf","tjQxs8hJdt","I7p2a7ku1p","ksJbyRsQUq","2DREsTXQ0Z",
-"M3zXLCNHmv","POUYSFwEJz","m4bxUIn3NS","soy9tVerEA","s47862Nslm","FLsphdjsrv","IRh48FLsph","ZJTXHuvf7A","ni2v164s8N","vOqCE7ku1p",
-"fqypyS77LH","YOfrYKZamH","b29RJM6qcG","RACujuTacx","RBhp0Mm8si","TXQ0Z9rlg9","GrDg7IBe8k","IKxdLMGlTF","LewvMWPmlx","prNT6n8pJ9",
-"BCxeC45cIH","soy9tY1mC0","SmGzvBGaQY","ZJTXH6q6L9","0YAGHFFDui","n1pmOGSQwj","FVMxotlILt","nnP8oKr8ys","gdQsSs93Ml","EdBKcjzUqR",
-"atef2KZamH","brhlQMkgy8","fcwDauvf7A","yvOMIW7cTs","prNT6FFDui","piJSkoQ87r","5VZjSWreyP","Oz8yZhUTw7","580YDSjskQ","QssNCCp3mZ",
-"ECMvUZuDtD","0YAGHX6Pin","o8UydJXljW","5IhmG8U2nU","uQIcze6e4z","MaJQsaDGtS","CdyBVBpYhV","5Drn0XyPZN","CIShGjzUqR","W3VFHOHaBz",
-"okgRiQWxoT","Y1mC0kZANm","jeskSatef2","NhXdulViBv","ksJbyQ6Lix","QssNCpFrrl","JKWYRO3iyQ","lViBvnlaBy","WDVWJMaJQs","5drc6FnPFB",
-"Chuy3LewvM","pvgjSQssNC","aL6AJ5iGN5","AIYUuSjskQ","S2Dfua00b5","s7MxkOz8yZ","FcWrWfcJOy","dmoS7Q6Lix","Yw2oU3otm6","XyPZNpT8wu",
-"6q6L9ogLgc","RACujBFkb8","faHirFPfSE","No0QbRmDcr","8TxD7TCgPp","tvdkDSmGzv","5nmWvWaim6","2DREsNo0Qb","Gv3Fq5ZaEz","5IhmGL7cGc",
-"NhXduYjB9t","5iGN5rz7Ut","NhXduni2v1","Mm8siRxrsm","K20wKguMb8","5Nammhi5X7","he9IAWMiS3","aDGtS2Yz7E","CdyBVNxx9V","7hyVvSs0Zu",
-"KASQ8t98iW","BCxeCF6PT2","kB5nPazIWp","pFrrltaOXK","BbwgAFnPFB","RsQUqNhXdu","oQ87r8FmFH","8FmFHix74r","yEfy9jzUqR","W3VFHXyPZN",
-"tl72Wmz8gx","48cHLNxx9V","Y1mC0tvdkD","WaWsv45cIH","MmKGJqQxHP","s7MxkjeskS","QworuQYxC0","WDVWJzQt6Q","dQ586s93Ml","5drc6a00b5",
-"KZamHSmGzv","uTacxaDGtS","d7vjMLbRTH","jzUqRNOHsz","TwanoUvlv4","Ul4a1Y1mC0","guMb8n8pJ9","xXTI4rz7Ut","aDGtSAXpwE","pv0i72TRI7",
-"0h1b114FLR","UmaEvaFFss","bgJAzvOqCE","hE1QlXflUq","soy9tatef2","S2DfuZv7z0","5iGN54QMc9","QnJ1SJJs5m","zmLYDNOHsz","29QAzB3qem",
-"QworuhSSvQ","v1HlnmX2GE","ReKEWsqVrf","qaofNmX2GE","FcWrWReKEW","yToGWG1RhS","CIShGuoStw","XyPZN5Namm","aL6AJCfgr3","uupzkeuZA5",
-"o8Uyd9eoRc","YOfrYzY1GY","lViBvyvOMI","HzZT8s93Ml","zbIYYlj07Q","gtCA5NcICA","GrDg7gIYvE","FGzgpGrDg7","9y4lwoQ87r","4dEz6RsQUq",
-"vkCHHRACuj","jeskSlj07Q","pvgjSBbwgA","brhlQfcwDa","1v5hH55rfB","9XyT9blLA9","6q6L9ThjNn","W7cTscL0aE","aFFssqQxHP","uAWypFLsph",
-"Cp3mZJIqXi","mz8gx3otm6","HP433L7cGc","Yh1hFuN6r3","FPfSEd85a9","HfyNQ48cHL","Yh1hFBbwgA","fcwDajfREu","yofH3fcJOy","DQimpfqypy",
-"i3pydU3yw5","kZANmWreyP","0PktIuTacx","AOgEeFGzgp","5VZjSRzaZA","mz8gxuPX7G","Yw2oUM3zXL","a00b5euZA5","pv0i7uTacx","euZA5yvOMI",
-"WmadADcpWB","FGzgpk85Ae","QClRLkB5nP","K4GS8jtn0X","Oz8yZQ6Lix","cmXIXSWfou","ZhwG1uPX7G","fLNg8pFrrl","5NammW7cTs","0MR5XPb1pa",
-"nFqikjSjS3","suY4xyluBx","QbxXcCK5W7","lkMUAcL0aE","okgRipT8wu","P6bcgLDk6f","d85a9sx5Gl","FnPFBiqv4k","AOgEegdQsS","uPX7G3otm6",
-"k85Aeatef2","JJs5mrz7Ut","2Yz7ECp3mZ","tl72WM3zXL","djsrvni2v1","Waim6o8Uyd","hi5X7lViBv","JRJQBIRh48","9eoRccQOnv","OUqFMWaWsv",
-"hi5X75ZaEz","C2IrcsuY4x","nlaBycQOnv","azIWpNOHsz","Oz8yZgIYvE","a00b5Uvlv4","zbIYYlkMUA","aFFssoGu6x","uN6r34W0Tl","bZLvS1LB1L",
-"soy9tydG8U","W3VFHMmsIo","WDVWJFFDui","t59lR3weIF","GSQwjdpe1v","JKWYRRxrsm","DLhzMpWiOs","zQt6Q4W0Tl","VjCZqFVMxo","7ku1pNAFuw",
-"AXpwEMkgy8","ru4UGtjQxs","fLNg8yofH3","I7p2auJScX","HlUbFulk41","rKDLJMaJQs","3otm6s7Mxk","jS1ajJkzUn","45cIHzHF1q","HfyNQ07n1c",
-"RACujMaJQs","BFkb8vLsmS","MmKGJ48cHL","soy9tCxVEf","JIqXiYOfrY","cQOnvuPX7G","Yf2Ecn8pJ9","dhSuHWaWsv","rz7UtWPmlx","nlaByMK07Y",
-"jfREuDLhzM","Vprf22Nslm","oQ87rAIYUu","Y1mC0Twano","IjTwPQYxC0","zY1GY0BmCy","FLsphrhl0J","tvdkDnnP8o","MojnPRBhp0","ZzJHW7Ow5C",
-"lm0pD07n1c","guMb8vOqCE","Q6hMCOHaBz","14FLRl83Ud","Zv7z0SbRYy","2DREs16lHc","uQIczL7cGc","5nmWvpv0i7","NcICAYjB9t","64s8NYw2oU",
-"JIqXihUTw7","55rfBHzZT8","8xEKz0Kyfs","ix74rpv0i7","0PktI6AFT0","uAWypoVQp6","vLsmSHP433","NOHszuupzk","qQxHPuTacx","RBhp0zqH0W",
-"ECMvUpmeCd","fcJOys4786","K20wKOxWIH","ECMvUtaOXK","l83UdwDajX","uPX7GGSQwj","ix74rbgJAz","0BmCyjtn0X","F6PT2HlUbF","Qworu6AFT0",
-"U3yw5MojnP","Mkgy8gf8rI","uQIczIKxdL","Twanomz8gx","Mm8silXFOB","atef2GrDg7","In3NSVprf2","d7vjMm4bxU","UlU3MIBe8k","gIYvEfaHir",
-"5NammPOUYS","FNYIMzHF1q","jzUqRs7Mxk","NhXduxciqp","yluBxFwEJz","brhlQlm0pD","StlDJVIlwP","64s8NblLA9","5ZaEzP6bcg","dhSuHIRh48",
-"tjQxsSjskQ","CqqaDNhXdu","Y1mC0zQt6Q","RACujhe9IA","s93MlEdBKc","Uvlv4MaJQs","IKxdLl83Ud","AgJHQvLsmS","U3yw5iwzGk","pv0i7QYxC0",
-"7Ow5CWmadA","tAOsrDG4sT","5NammJRJQB","QWxoT5nmWv","1LB1LhUTw7","GXdoHNOHsz","ydG8UMaJQs","CdyBVatef2","5iGN555rfB","YOfrYRsQUq",
-"FVMxo9rlg9","1v5hH5ZaEz","dpe1vyofH3","5drc62Nslm","IKxdLQWxoT","uPX7GNhXdu","fmIK17hyVv","UlU3MVerEA","5nmWvMaJQs","fLNg8tAOsr",
-"I7p2afmIK1","ogLgc5Namm","SmGzvVerEA","8xEKzWreyP","pAhR1BbwgA","MGlTF2TRI7","EOE1ov1Hln","zQt6Qk85Ae","NcICAUvlv4","1LB1LyvOMI",
-"t98iWFcWrW","rhl0JRACuj","pWiOsFVMxo","07n1cKASQ8","RpBQmJXljW","QnJ1SjS1aj","9eoRcUl4a1","WDVWJoGu6x","8U2nUQChxs","X6PinnnP8o",
-"OHaBzQssNC","zY1GYAIYUu","GWqqXUmaEv","rz7UtUlU3M","tuDySjiVBP","bZLvSZUnqt","mz8gxxXTI4","wDajXiB08l","qaofNAIYUu","JJs5mZuDtD",
-"Mm8siaDGtS","okgRiOUYuF","Dz1R3HzZT8","QssNCix74r","gdQsS0BmCy","i7WMQAgJHQ","piJSkb29RJ","mz8gxZhwG1","gf8rIhYBCK","0ao3ll83Ud",
-"1j5L8HlUbF","ThjNnFNYIM","xXTI4zbIYY","hSSvQKr8ys","EOE1ouvf7A","CNHmvokgRi","vLsmSZUnqt","i3pydmz8gx","pmeCd29QAz","cQOnvZuDtD",
-"0BmCyOHaBz","pv0i7prNT6","LbRTHvOqCE","n8pJ9Dz1R3","Zv7z0FcWrW","QnJ1S29QAz","zHF1qdpe1v","fcwDaJJs5m","7ku1piqv4k","uoStw64s8N",
-"FFDuijSjS3","3weIFd85a9","ydG8UGWqqX","zmLYDVprf2","24ARFkZANm","2hEEUuLtKs","pWiOsfcJOy","No0QbMkgy8","fmIK1VNCPd","FjHXRtuDyS",
-"ksJby9eoRc","gjUTu7Ow5C","KZamHRmDcr","No0Qbx3LDe","zqH0Wrz7Ut","Nxx9VZv7z0","JkzUnSmGzv","JRJQBi3pyd","QnJ1SdQ586","n1pmOdhSuH",
-"AmdQds4786","618DiQChxs","Kr8ysa00b5","v1Hln4W0Tl","14FLR8U2nU","BGaQYk85Ae","s4786gIYvE","OxWIHt98iW","djsrvguMb8","AkKTkuvf7A",
-"OxWIHuZPqg","BpYhVaDGtS","cShY2W3VFH","6q6L9MmKGJ","OxWIHMmsIo","FVMxoCK5W7","S2DfufcwDa","sqVrfsqVrf","Vprf2tlILt","pvgjSoGu6x",
-"wDajXVNCPd","5Drn0uPX7G","iqv4k2Yz7E","tAOsrOUYuF","zz4ZUzz4ZU","Mkgy8FPfSE","5VZjS5Namm","ECMvUcL0aE","HzZT8uupzk","dhSuHjiVBP",
-"W3VFHsqVrf","FjHXRY1mC0","s7MxkRkQke","QYxC0lpF6W","DLhzMI7p2a","zz4ZUVBjhz","oVQp6uupzk","RBhp02hEEU","fqypyzz4ZU","tl72W8RCUA",
-"JXljWvkCHH","PYBf47fsYM","jfREu5IhmG","ZuDtDYh1hF","OUYuFlH1kt","9iGoT2TRI7","7fsYMhe9IA","Dz1R3Kr8ys","s4786VNCPd","i7WMQAmdQd",
-"dQ586i7WMQ","7hyVv9XyT9","5VZjSRmDcr","0BmCy9XyT9","oVQp6xciqp","ZzJHWNxx9V","yEfy9AIYUu","yvOMIYf2Ec","K4GS8rz7Ut","ECMvU16lHc",
-"Cp3mZ8xEKz","Q6hMCW7cTs","I7p2aQYxC0","3weIFFcWrW","DQimpk85Ae","S77LHBbwgA","iB08ljeskS","blLA9rz7Ut","RACujIn3NS","uZPqgNOHsz",
-"0BmCy14FLR","dQ586gdQsS","NOHszzbIYY","BpYhVBGaQY","9GXkXYjB9t","5IhmGFNYIM","RzaZALDk6f","ydG8Ua00b5","OUYuF0Kyfs","Yh1hFtaOXK",
-"lH1kt0Kyfs","tAOsrUvlv4","zz4ZUni2v1","IRh480PktI","9rlg93weIF","NAFuwpv0i7","uupzkZzJHW","zqH0W07n1c","zFgtBOHaBz","ciuWzpAhR1",
-"Pb1pacmXIX","dhSuHt98iW","4dEz67hyVv","sqVrfC2Irc","7hyVvHP433","lH1ktQChxs","8cVD3WreyP","DQimpECMvU","OHaBzzFgtB","Yf2EccQOnv",
-"MaJQsNxx9V","JXljWSjskQ","aez9yP6bcg","l83Ud6q6L9","lViBvqaofN","CNHmvNcICA","ZzJHWAXpwE","Dz1R38hJdt","RmDcrP6bcg","QWxoTnnP8o",
-"s7MxkyluBx","piJSkHzZT8","jtn0XiKqhr","RkQkeru4UG","gIYvE9XyT9","fqypyfqypy","CNHmv45cIH","ogLgcSWfou","jiVBPsqVrf","RpBQmuTacx",
-"7fsYMFLsph","K20wKWMiS3","QChxsuAWyp","zbIYYOxWIH","ksJbykZANm","MK07YuLtKs","jtn0XoQ87r","WreyP7X3uy","LDk6fS77LH","StlDJDz1R3",
-"Gv3FqgtCA5","M6qcGG1RhS","lViBv14FLR","14FLRt59lR","lpF6WKASQ8","Mkgy8oQ87r","wiHrZCK5W7","aL6AJnlaBy","J2mQiUl4a1","618Dis7Mxk",
-"fFDrJ55rfB","5iGN5HlUbF","Y1mC0nlaBy","rKDLJlpF6W","GWqqXni2v1","NAFuw9iGoT","hUTw7v1Hln","oQ87rqQxHP","6q6L9Yw2oU","QWxoTCxVEf",
-"GWqqXyvOMI","hE1QllViBv","k85AeVerEA","QYxC0gf8rI","RkQkemX2GE","K4GS8lCMxy","6q6L9kB5nP","IKxdLAOgEe","CK5W7lViBv","o8UydOHaBz",
-"faHirrz7Ut","pvgjSzz4ZU","FwEJzUmaEv","pmeCdzbIYY","4dEz6hE1Ql","zmLYDatef2","v1HlnBpYhV","lpF6W0YAGH","AOgEe5Namm","lCMxy9iGoT",
-"kB5nPpAhR1","ru4UGqQxHP","KASQ8uupzk","No0QbuoStw","B3qemyofH3","7lUXZTCgPp","bZLvSeuZA5","LbRTHFFDui","ksJbyfaHir","gjUTuI7p2a",
-"5iGN5YOfrY","xciqpZzJHW","yluBxFPfSE","WmadAM6qcG","BpYhVmz8gx","JkzUnD6rBy","JRJQBECMvU","No0QbSbRYy","QnJ1Ssoy9t","DG4sT7fKYU",
-"djsrv8U2nU","sx5GlRACuj","TCgPpuvf7A","29QAzQChxs","WmadAzHF1q","UlU3MDcpWB","FcWrWStlDJ","NOHszMGlTF","nlaByWPmlx","cShY2soy9t",
-"uJScXqaofN","4dEz6tuDyS","pv0i7JJs5m","S77LHyToGW","lm0pDK20wK","xciqpAkKTk","2Yz7EMmKGJ","fcJOytjQxs","7X3uyn1pmO","lsQGomX2GE",
-"MGlTFCxVEf","No0QbYh1hF","CxVEfVNCPd","cL0aEXflUq","7hyVvEoToP","nlaByVjCZq","b29RJt59lR","Mkgy8pT8wu","DQimpLbRTH","In3NSfaHir",
-"hUTw7k85Ae","M3zXLMojnP","JXljWFxX9q","5drc6JKWYR","tlILtFFDui","AIYUuyToGW","MGlTFZJTXH","iqv4kpWiOs","zHF1q5Drn0","oVQp6pWiOs",
-"b29RJlXFOB","LbRTHuJScX","Q6hMCjfREu","GrDg7wiHrZ","BFkb8NAFuw","580YDC2Irc","lm0pDQChxs","Waim6mz8gx","aFFss6AFT0","Mkgy8L7cGc",
-"FwEJz2TRI7","t59lRFhtgl","Q6hMCReKEW","Zv7z0C2Irc","d7vjMv8yFN","yEfy9LbRTH","nnP8o6q6L9","4W0Tl45cIH","WMiS3t98iW","9rlg9XyPZN",
-"5nmWv64s8N","CqqaD5iGN5","6AFT0ZUnqt","9eoRcpFrrl","FnPFBCqqaD","2Yz7EkB5nP","oGu6xWreyP","OHaBzbZLvS","gdQsSVprf2","VIlwPi7WMQ",
-"7X3uyblLA9","S2DfudmoS7","lkMUA7ku1p","BbwgAblLA9","i3pydxciqp","l83UdgdQsS","fcJOy8U2nU","AIYUuy94nw","2DREsZUnqt","IKxdLKsjRK",
-"jfREunlaBy","07n1cThjNn","BFkb8aez9y","suY4xyofH3","8FmFHxReec","NOHszjzUqR","ix74rL7cGc","CdyBVSmGzv","55rfBksJby","gdQsSFVMxo",
-"1j5L8pmeCd","RkQkeIn3NS","MezSWTa8f6","lXFOBRxrsm","Chuy3Rxrsm","yEfy9nnP8o","jSjS30MR5X","5NammIn3NS","jtn0Xv1Hln","5VZjSNo0Qb",
-"lj07Qv1Hln","uLtKsogLgc","s7Mxkatef2","FFDuilm0pD","bZLvSRsQUq","2ZHdkuvf7A","KsjRKwiHrZ","WMiS3MojnP","oVQp60h1b1","a00b59XyT9",
-"AIYUuRxrsm","S2DfuMmsIo","0h1b1lpF6W","8U2nUStlDJ","okgRi5Mg9r","Uvlv4AIYUu","hSSvQFGzgp","5Drn0s93Ml","faHiryluBx","Mm8siFNYIM",
-"CxVEfuZPqg","aDGtSVprf2","QnJ1SVIlwP","5iGN5kB5nP","pv0i7FwEJz","pmeCdC2Irc","uJScX4dEz6","MK07YdmoS7","Uvlv4M3zXL","VLTy6Cp3mZ",
-"cmXIXSs0Zu","faHirfcwDa","zQt6QdQ586","yToGWgdQsS","B3qeml83Ud","DcpWBfLNg8","3otm6tlILt","1v5hHS77LH","ZJTXHrhl0J","yToGWlCMxy",
-"JIqXiguMb8","8RCUA8cVD3","qQxHPn1pmO","jfREufcJOy","FFDuiKZamH","1LB1LNo0Qb","fqypyIBe8k","9iGoTt98iW","aL6AJI7p2a","FnPFBydG8U",
-"n1pmOAOgEe","8FmFHx3LDe","fFDrJVerEA","FjHXRDQimp","pv0i7StlDJ","ZJTXHZv7z0","FxX9qgtCA5","UmaEvWreyP","KASQ88cVD3","K4GS82DREs",
-"blLA95drc6","vkCHHiB08l","5nmWvReKEW","Oz8yZZzJHW","WMiS3iqv4k","iwzGkF6PT2","QnJ1SuJScX","ksJbydpe1v","wiHrZTwano","oVQp65IhmG",
-"FNYIMYOfrY","y94nwhUTw7","jzUqRVerEA","29QAzAIYUu","uZPqgCK5W7","pmeCdGXdoH","rKDLJlViBv","JkzUnn1pmO","DLhzMW3VFH","o8UydfcJOy",
-"16lHcFwEJz","uQIczyvOMI","VLTy6MmKGJ","JKWYRs93Ml","MezSWqQxHP","pAhR1jtn0X","5VZjS0ao3l","Ta8f629QAz","0YAGHY1mC0","LbRTHBFkb8",
-"DG4sTqaofN","BCxeCFhtgl","GWqqXQssNC","DG4sT7lUXZ","IBe8kFPfSE","NOHszpFrrl","uLtKs0YAGH","y94nwBCxeC","s93MlyluBx","rz7UtzqH0W",
-"P6bcgQnJ1S","v8yFNeuZA5","uPX7GSmGzv","RzaZAy94nw","EoToPNo0Qb","Ul4a18TxD7","i3pydblLA9","XflUq5iGN5","M3zXLzQt6Q","Cp3mZIn3NS",
-"0h1b1AgJHQ","FLsphVerEA","vLsmSFcWrW","zqH0Ws4786","lViBvaL6AJ","64s8NZzJHW","WMiS3Chuy3","4W0Tl580YD","M3zXLReKEW","5NammsuY4x",
-"piJSk1v5hH","GrDg7BGaQY","ReKEWG1RhS","uJScXCxVEf","6q6L9wiHrZ","oGu6xcL0aE","YjB9tuAWyp","Mm8siCIShG","FjHXRSjskQ","pvgjSa00b5",
-"RACujVBjhz","jS1ajU3yw5","jfREuulk41","Y1mC0fLNg8","ulk41StlDJ","b29RJv2eC3","yEfy9HlUbF","Dz1R3jSjS3","t59lRYOfrY","a00b5lViBv",
-"jSjS3WPmlx","ZJTXH9GXkX","zHF1qv1Hln","DLhzM64s8N","FnPFBtl72W","G1RhSfqypy","ulk41K4GS8","7Ow5CIjTwP","Cp3mZD6rBy","DcpWBGWqqX",
-"nFqik8xEKz","JJs5mazIWp","CqqaD7Ow5C","64s8NCqqaD","tlILtokgRi","In3NS9y4lw","Nxx9VWMiS3","5nmWvjzUqR","8FmFHGrDg7","vOqCE45cIH",
-"XflUq8cVD3","6AFT0I7p2a","Cp3mZuPX7G","Rxrsmni2v1","ix74ryEfy9","hi5X7BbwgA","Z4I1vpAhR1","Z4I1vIjTwP","8cVD3lViBv","U3yw5m4bxU",
-"9GXkXNo0Qb","HRxd8fmIK1","iB08lNo0Qb","gtCA5ulk41","bgJAzjzUqR","ZuDtDoVQp6","qUJMdCfgr3","I7p2a9GXkX","Cp3mZ9eoRc","ksJby4dEz6",
-"taOXK2ZHdk","HzZT87X3uy","VIlwPlkMUA","SjskQCp3mZ","1LB1LRkQke","GWqqXFxX9q","W7cTsFxX9q","Waim6jfREu","OUqFMlkMUA","uN6r3SmGzv",
-"5nmWvKsjRK","hi5X7Yw2oU","fmIK17lUXZ","OUYuFoQ87r","fFDrJiB08l","fqypytlILt","0Kyfs2ZHdk","ciuWzRsQUq","5VZjSHfyNQ","NcICAQbxXc",
-"dpe1vlweGy","FnPFBaFFss","zbIYYn1pmO","CqqaDmz8gx","EoToPM6qcG","SmGzvogLgc","8TxD7yvOMI","QChxsfFDrJ","ECMvUYjB9t","Oz8yZOxWIH",
-"NhXduyEfy9","QssNCWaim6","9GXkXjtn0X","X6PinjiVBP","uPX7GuTacx","s93MlxReec","xXTI4FVMxo","C2IrcyofH3","t59lRokgRi","euZA5QYxC0",
-"pT8wuEOE1o","5VZjSaL6AJ","1j5L8pT8wu","In3NSNAFuw","wDajXG1RhS","lXFOB580YD","zQt6Qaez9y","CNHmvhE1Ql","ru4UGlm0pD","Pb1pafFDrJ",
-"ix74rbZLvS","LbRTHSbRYy","hYBCKSs0Zu","o8Uyddjsrv","UmaEvs4786","JkzUn7X3uy","2TRI7MaJQs","ogLgcoVQp6","FxX9q0PktI","FcWrWQbxXc",
-"CNHmvQClRL","7X3uyydG8U","oGu6xksJby","JJs5mkB5nP","lm0pD7X3uy","yluBxh1zcH","7ku1pRmDcr","5VZjSWMiS3","fLNg8M3zXL","zz4ZUG1RhS",
-"ZUnqtd7vjM","9y4lwQYxC0","Waim6GXdoH","uupzkFwEJz","W7cTss7Mxk","NAFuwzz4ZU","SbRYysqVrf","2TRI7fcwDa","BCxeCatef2","ogLgc9iGoT",
-"tAOsr2ZHdk","mX2GEO3iyQ","iqv4kECMvU","QworutaOXK","pAhR1uJScX","5drc6pvgjS","2Yz7EM6qcG","FVMxogIYvE","QbxXcAXpwE","qUJMdNcICA",
-"euZA5qaofN","VjCZqrKDLJ","vOqCEMojnP","IjTwPpiJSk","azIWpGWqqX","hYBCKi3pyd","ECMvUK4GS8","HP433QbxXc","SbRYyyofH3","Pb1paZUnqt",
-"8RCUAZJTXH","JKWYRlpF6W","ZUnqtpFrrl","QYxC0BbwgA","4dEz6he9IA","e6e4zvLsmS","QClRL7Ow5C","azIWp7ku1p","ogLgcdhSuH","guMb8G1RhS",
-"BGaQYix74r","RzaZA8cVD3","nlaBydQ586","0ao3llXFOB","s93Ml0ao3l","NcICAlCMxy","P6bcg64s8N","MojnPh1zcH","7X3uyRmDcr","Waim6LbRTH",
-"vLsmSAmdQd","KsjRKpmeCd","BCxeCOxWIH","fqypyVBjhz","XflUq45cIH","LewvMk85Ae","WmadA8xEKz","Vprf28xEKz","hYBCKJRJQB","tAOsrdjsrv",
-"MK07Y7ku1p","lViBvWaim6","CxVEfsuY4x","he9IAiKqhr","RkQkezQt6Q","EdBKcIBe8k","MK07YjzUqR","RBhp0hi5X7","s47868FmFH","ciuWz6q6L9",
-"xciqpt59lR","gjUTuGrDg7","8U2nUaDGtS","64s8NfaHir","uTacxksJby","lpF6W0MR5X","tl72WtjQxs","RkQketvdkD","zY1GYCIShG","WDVWJ9eoRc",
-"S2Dfulm0pD","3otm6okgRi","LbRTH8RCUA","jiVBP9XyT9","v1HlnMK07Y","HRxd83weIF","yToGWMK07Y","aFFssdmoS7","uQIczaFFss","7hyVvFnPFB",
-"2TRI7M3zXL","QssNCQ6Lix","faHir9XyT9","WMiS3GrDg7","pAhR1okgRi","Cp3mZnnP8o","lm0pD8RCUA","AIYUuAmdQd","xXTI4fcwDa","2hEEUHfyNQ",
-"7fsYM2ZHdk","HfyNQdQ586","CxVEfe6e4z","EoToPprNT6","HlUbFMojnP","fFDrJgjUTu","AkKTkDLhzM","BGaQYuTacx","lsQGoHzZT8","W7cTsQbxXc",
-"64s8NWMiS3","fLNg8KsjRK","JJs5mJ2mQi","OUYuFqUJMd","a00b53weIF","Waim6618Di","BbwgArz7Ut","Yf2EcMmKGJ","jS1ajtAOsr","8hJdt64s8N",
-"Nxx9V8cVD3","uupzkMm8si","HP433vLsmS","s4786Mm8si","16lHcWaWsv","NhXdu7ku1p","ZUnqt6AFT0","iKqhrSmGzv","RACuj7ku1p","0Kyfs8RCUA",
-"soy9tn1pmO","ZuDtDMkgy8","n1pmOJJs5m","tjQxsjtn0X","ZUnqtazIWp","CIShGWPmlx","i3pydRmDcr","Dz1R3K20wK","Yw2oUyToGW","7hyVvMkgy8",
-"ReKEWWPmlx","I7p2atlILt","WreyPSmGzv","Yh1hFIn3NS","JXljW7lUXZ","UlU3MEoToP","VNCPdYf2Ec","PYBf4Pb1pa","J2mQi4dEz6","aFFssn8pJ9",
-"IKxdLfLNg8","8hJdtmX2GE","lCMxyaFFss","jiVBPWreyP","8U2nUQbxXc","Z4I1vGv3Fq","taOXKHzZT8","5Mg9raFFss","XflUqLewvM","7lUXZEoToP",
-"ZUnqtgIYvE","hE1QlLewvM","pAhR1JKWYR","sx5Gl580YD","s4786MojnP","Qworu7hyVv","S77LHVBjhz","Oz8yZ5iGN5","2ZHdk5IhmG","WaWsvGSQwj",
-"HRxd86AFT0","uLtKsXflUq","ZzJHWOHaBz","Ss0ZuDG4sT","jzUqRTa8f6","sqVrfuoStw","IRh48FnPFB","Y1mC0vkCHH","s93MlI7p2a","WMiS3cShY2",
-"he9IAksJby","faHir16lHc","StlDJ5VZjS","blLA9ZuDtD","POUYS3otm6","iwzGkQworu","jtn0XKZamH","0BmCyBCxeC","v1Hlns7Mxk","4W0TltuDyS",
-"8cVD33otm6","uvf7AjSjS3","xciqp618Di","JIqXiStlDJ","1v5hHFGzgp","EoToPbgJAz","GrDg716lHc","pvgjSsqVrf","ZJTXH29QAz","pmeCdqQxHP",
-"YOfrYP6bcg","GWqqXjS1aj","KsjRKBbwgA","ciuWzRpBQm","StlDJMkgy8","tvdkD55rfB","WMiS3uupzk","VBjhz7fKYU","JRJQBo8Uyd","taOXKStlDJ",
-"aL6AJFNYIM","29QAzX6Pin","x3LDeIn3NS","MmsIo4W0Tl","9eoRcChuy3","blLA9OHaBz","o8Uyds4786","t59lRgIYvE","W3VFHFNYIM","oQ87rlXFOB",
-"k85AeAmdQd","FPfSE7ku1p","JRJQBVIlwP","Gv3FqlH1kt","vkCHH618Di","OxWIH8TxD7","UmaEvDLhzM","MK07YogLgc","2Yz7EOHaBz","5nmWvUmaEv",
-"b29RJMK07Y","ni2v1Z4I1v","lkMUA8TxD7","7fsYMd85a9","guMb8cShY2","aez9yXflUq","cmXIXX6Pin","3otm6IBe8k","0Wr5ypv0i7","hYBCKazIWp",
-"0PktICfgr3","UmaEvjS1aj","ydG8Us4786","Vprf2XflUq","Y1mC0pvgjS","oQ87riB08l","0BmCyAIYUu","ogLgcru4UG","9XyT9RsQUq","NcICAuQIcz",
-"CK5W7iB08l","ogLgc2Nslm","TXQ0ZzbIYY","64s8NKZamH","pv0i7nnP8o","7Ow5Cd85a9","KsjRKuAWyp","C2IrcKr8ys","yvOMIxciqp","fqypyFGzgp",
-"cL0aEP6bcg","WMiS3n8pJ9","3otm6v8yFN","HlUbFReKEW","IKxdLxciqp","yvOMI5ZaEz","gIYvEvLsmS","2DREsXflUq","aDGtSpv0i7","5NammBCxeC",
-"djsrv2ZHdk","faHirkZANm","FVMxo7hyVv","vkCHHMK07Y","M3zXLWaWsv","dQ586JJs5m","HzZT8hi5X7","Dz1R3pFrrl","6q6L9mX2GE","HP433DLhzM",
-"ZuDtDgIYvE","Mkgy8FwEJz","k85AelCMxy","WDVWJMGlTF","FxX9qJXljW","JIqXiiKqhr","bgJAz7hyVv","M3zXLGSQwj","Nxx9VogLgc","CdyBVuJScX",
-"FGzgp48cHL","kZANmTCgPp","gIYvE07n1c","kZANmsx5Gl","xciqplH1kt","azIWpqUJMd","jiVBPuvf7A","CNHmvjS1aj","MezSWZUnqt","16lHc1j5L8",
-"9GXkXWmadA","uQIcz8hJdt","AgJHQ2DREs","J2mQipAhR1","nlaByXflUq","X6PinI7p2a","8hJdtuupzk","d7vjMVprf2","pAhR124ARF","dpe1vyEfy9",
-"2Yz7E5IhmG","hUTw74QMc9","GSQwj4QMc9","fFDrJkB5nP","BpYhVY1mC0","ReKEWzz4ZU","yToGWYf2Ec","8TxD7MezSW","zz4ZUZuDtD","9iGoTjeskS",
-"pT8wuazIWp","KZamHfcwDa","MGlTFhYBCK","dQ586MaJQs","uN6r3AgJHQ","tAOsrcL0aE","WaWsv07n1c","wDajX48cHL","hUTw7Uvlv4","rKDLJCK5W7",
-"8U2nU14FLR","YjB9tSjskQ","9XyT9CIShG","xXTI4ThjNn","WmadAPYBf4","7Ow5CyluBx","XflUqxXTI4","t59lRVBjhz","JRJQBlCMxy","okgRiL7cGc",
-"POUYS9iGoT","ZJTXHF6PT2","5NammSmGzv","djsrvIKxdL","pWiOsiqv4k","YjB9tNxx9V","iqv4k1j5L8","a00b5jfREu","4dEz6FnPFB","8cVD32DREs",
-"2hEEUVerEA","pvgjSfFDrJ","jfREuiwzGk","cL0aEThjNn","K4GS8KsjRK","pv0i7XyPZN","GSQwjRsQUq","XyPZNt98iW","HfyNQaez9y","pmeCda00b5",
-"DG4sT5drc6","Q6hMCpT8wu","iB08lX6Pin","AXpwEtaOXK","X6PinuAWyp","Cp3mZIBe8k","AIYUuzY1GY","ZhwG1IjTwP","JkzUnRzaZA","aFFssJXljW",
-"5ZaEzRpBQm","JRJQByvOMI","ksJbySjskQ","blLA98TxD7","DcpWBaez9y","MezSW2Yz7E","WmadA2hEEU","JXljW2Nslm","he9IAWDVWJ","iwzGkZv7z0",
-"wiHrZCNHmv","Pb1paReKEW","azIWp48cHL","ni2v1soy9t","ru4UGkZANm","JRJQBpmeCd","jtn0XTa8f6","TXQ0Zs7Mxk","sx5Gla00b5","HzZT8JkzUn",
-"pmeCdOUqFM","yvOMIvLsmS","JKWYR0Kyfs","vOqCEI7p2a","fcJOy580YD","JXljWpv0i7","ReKEW2Nslm","atef2lViBv","rhl0Jiqv4k","OUqFMDQimp",
-"aez9ysqVrf","uJScXxReec","14FLR0MR5X","VerEAB3qem","OxWIHm4bxU","07n1cRBhp0","S2Dfu5iGN5","UlU3MFLsph","Nxx9Vuupzk","dhSuHPYBf4",
-"NcICAsoy9t","KASQ8SjskQ","EoToPU3yw5","lXFOBAkKTk","DQimpuQIcz","8cVD3CxVEf","lweGylCMxy","FPfSEoGu6x","lCMxyIRh48","faHiratef2",
-"lXFOBfqypy","uLtKsS77LH","zHF1qQChxs","Ul4a1e6e4z","gIYvEs7Mxk","FLsphIn3NS","jfREuGWqqX","i7WMQxReec","h1zcH7fKYU","CdyBV7hyVv",
-"rKDLJ64s8N","F6PT2CIShG","0Wr5yhSSvQ","yToGWEdBKc","Mkgy8AOgEe","24ARFuupzk","wDajXTCgPp","1LB1LDz1R3","9eoRc5Namm","QnJ1Saez9y",
-"8xEKzL7cGc","XflUqcL0aE","Mkgy8rhl0J","5drc6hi5X7","29QAzru4UG","NAFuwWreyP","Yh1hFKr8ys","WMiS3QClRL","djsrvxReec","uZPqg8hJdt",
-"s7MxkhSSvQ","GSQwj48cHL","xciqpIRh48","HlUbFWMiS3","lkMUACqqaD","b29RJSmGzv","pAhR1K20wK","8xEKzI7p2a","kZANmfFDrJ","soy9tMaJQs",
-"tlILtlpF6W","tAOsrogLgc","zqH0Waez9y","sqVrflkMUA","Waim6W3VFH","yEfy93otm6","fmIK1uN6r3","5drc6CqqaD","O3iyQrz7Ut","45cIHCp3mZ",
-"ThjNnogLgc","5IhmGQYxC0","VerEALDk6f","NOHszzz4ZU","uZPqgpWiOs","IBe8k8U2nU","wDajXIn3NS","CqqaDTCgPp","hSSvQ0h1b1","EoToPmX2GE",
-"i3pyd64s8N","vOqCEgjUTu","5nmWvRpBQm","CqqaDyvOMI","hSSvQCK5W7","pWiOs14FLR","azIWpv2eC3","zmLYDZUnqt","QYxC0GWqqX","gf8rI55rfB",
-"ECMvU8FmFH","k85Ae14FLR","v1Hlny94nw","TXQ0ZGSQwj","faHirFxX9q","aDGtSt59lR","M6qcG45cIH","2hEEUvkCHH","0Wr5yFhtgl","zY1GYnFqik",
-"taOXKNAFuw","dmoS7ni2v1","7fKYUMGlTF","5Mg9rFVMxo","hi5X7e6e4z","Uvlv4VBjhz","TCgPpVNCPd","rhl0JVBjhz","2ZHdk7hyVv","SbRYyQbxXc",
-"Ul4a1uLtKs","LbRTHCK5W7","b29RJRxrsm","Dz1R3XflUq","yofH3580YD","lCMxyRsQUq","5VZjSoQ87r","6AFT09y4lw","yofH3jeskS","ogLgc14FLR",
-"lsQGoqUJMd","CIShG8TxD7","fcwDaTCgPp","ReKEWJRJQB","W7cTsix74r","0BmCysuY4x","zHF1qB3qem","dmoS7FLsph","Waim6Zv7z0","1v5hHx3LDe",
-"lkMUAMmsIo","fqypylj07Q","7hyVvxReec","jS1ajQssNC","Z4I1v9y4lw","BFkb88U2nU","LDk6fm4bxU","Zv7z0BCxeC","sqVrfDz1R3","nnP8oMGlTF",
-"ogLgc2ZHdk","45cIHPOUYS","StlDJFLsph","RACujPYBf4","lH1kt0MR5X","euZA5HP433","mX2GEPb1pa","pT8wulpF6W","uPX7GtAOsr","W7cTsO3iyQ",
-"CqqaDCNHmv","M3zXLFwEJz","L7cGcFVMxo","zY1GYlj07Q","Pb1padmoS7","DQimppiJSk","gtCA5pAhR1","5Namm7ku1p","AgJHQ0h1b1","D6rBy55rfB",
-"VLTy6ThjNn","Pb1paJXljW","uLtKs5iGN5","AkKTkEoToP","hSSvQkZANm","DQimpjtn0X","8RCUAW3VFH","hi5X72TRI7","VjCZqZv7z0","64s8NMaJQs",
-"Vprf25drc6","tuDySazIWp","JRJQBmX2GE","uZPqgJXljW","lj07QprNT6","I7p2aVNCPd","29QAzfqypy","MaJQspT8wu","ZuDtD5IhmG","CNHmvuAWyp",
-"wiHrZFNYIM","M6qcG5IhmG","W3VFHFFDui","FNYIMSjskQ","zz4ZUxciqp","0ao3lFPfSE","DG4sTZv7z0","QYxC0iB08l","iKqhr4dEz6","guMb8fqypy",
-"DQimp5nmWv","VLTy6BFkb8","Ta8f6SWfou","dmoS7pT8wu","0PktI2ZHdk","4QMc92ZHdk","QssNC24ARF","TCgPpMojnP","8RCUAKZamH","GrDg7d85a9",
-"2TRI79GXkX","2Yz7Eru4UG","suY4xblLA9","No0Qb2Nslm","C2Irc9iGoT","1LB1LLewvM","vOqCEDG4sT","0ao3l7fsYM","wiHrZjiVBP","CxVEfVLTy6",
-"VjCZqsuY4x","K20wKXflUq","7hyVvjiVBP","8U2nUM6qcG","Chuy3iB08l","OHaBztl72W","CxVEfuoStw","nlaByhe9IA","pvgjSThjNn","jS1ajQworu",
-"zY1GY8xEKz","SWfouuTacx","lm0pDChuy3","IjTwPydG8U","DQimp8cVD3","uN6r3NhXdu","uvf7AuLtKs","4dEz6aL6AJ","ix74rU3yw5","ZhwG1Nxx9V",
-"k85AeZhwG1","vLsmSuoStw","JXljWuPX7G","pAhR1FVMxo","qQxHPZJTXH","IjTwPDG4sT","xciqpWmadA","6q6L9Ta8f6","DG4sTGSQwj","IKxdLZzJHW",
-"NOHszFcWrW","fcJOyZzJHW","UlU3MO3iyQ","FwEJzCdyBV","JXljWWaim6","uTacxqaofN","GrDg77Ow5C","ogLgcix74r","Nxx9VnFqik","8cVD3Kr8ys",
-"CK5W7uoStw","zqH0WUl4a1","1j5L8xXTI4","ThjNnvkCHH","ThjNntl72W","9GXkXa00b5","Yf2EcGWqqX","FcWrWvLsmS","ReKEW64s8N","GXdoHI7p2a",
-"RBhp0bgJAz","o8Uydgf8rI","1LB1Lo8Uyd","3otm6HzZT8","48cHLjzUqR","Ul4a1gjUTu","OxWIHdhSuH","0ao3lIn3NS","6q6L9s4786","WmadA9iGoT",
-"CdyBVJIqXi","y94nwFGzgp","GXdoHL7cGc","QYxC07hyVv","KsjRKvLsmS","cShY2ksJby","Nxx9VdmoS7","1j5L8d85a9","1v5hH64s8N","L7cGcQnJ1S",
-"8U2nUjSjS3","VIlwPpT8wu","BpYhVNcICA","8xEKz5Drn0","gjUTu9XyT9","o8UydazIWp","vLsmSoGu6x","vLsmSY1mC0","ciuWzDz1R3","AkKTkAgJHQ",
-"RzaZASmGzv","yEfy9hUTw7","Ta8f67fKYU","uJScXBbwgA","l83UdLDk6f","BpYhVSbRYy","16lHcQnJ1S","GXdoHGSQwj","lkMUAlweGy","djsrvkB5nP",
-"hSSvQZ4I1v","RsQUqGSQwj","Q6Lix1j5L8","4dEz6JIqXi","uJScX5iGN5","mz8gxPOUYS","SWfouIjTwP","s93MlpWiOs","yluBxzQt6Q","HfyNQaFFss",
-"hSSvQi3pyd","pvgjSciuWz","0BmCyD6rBy","ciuWz07n1c","CIShG5Mg9r","zQt6QMmsIo","FVMxo5Namm","MmsIoF6PT2","LDk6fEoToP","brhlQsuY4x",
-"uN6r3zmLYD","cShY20Wr5y","K4GS8h1zcH","1v5hHPOUYS","8FmFHqaofN","0BmCySs0Zu","QClRL0Kyfs","t59lRzFgtB","yEfy9RkQke","HfyNQn1pmO",
-"IRh48vLsmS","x3LDeXyPZN","IRh48HlUbF","AIYUuL7cGc","WaWsv618Di","k85AelViBv","RzaZA0Wr5y","JKWYRoQ87r","7fsYM48cHL","Pb1pa5iGN5",
-"guMb8pv0i7","45cIHgjUTu","8RCUAt59lR","No0QbWaWsv","9iGoTzFgtB","Mkgy8YjB9t","ciuWzI7p2a","mz8gxdhSuH","5drc6uTacx","lj07QjzUqR",
-"QYxC0GXdoH","TCgPpjfREu","PYBf4Rxrsm","5NammguMb8","8hJdtNo0Qb","FnPFBgdQsS","lweGyFwEJz","580YDEdBKc","taOXKQClRL","gIYvEIBe8k",
-"HRxd8JXljW","FcWrWuN6r3","Yh1hF2ZHdk","uJScX8cVD3","3weIFy94nw","0YAGHcL0aE","FcWrW24ARF","Uvlv4MK07Y","fLNg8gtCA5","iB08lU3yw5",
-"fqypy16lHc","TwanoMmKGJ","bgJAz0PktI","IBe8koQ87r","MojnPfqypy","FjHXRJ2mQi","SbRYyOxWIH","QClRLjiVBP","NOHszmX2GE","xXTI4HlUbF",
-"ZuDtDTXQ0Z","G1RhS0h1b1","pT8wutAOsr","CNHmvdpe1v","U3yw57fKYU","taOXKciuWz","Z4I1vI7p2a","WPmlxfqypy","d85a9EoToP","5iGN55Mg9r",
-"ni2v1tlILt","M6qcGRkQke","qUJMdn1pmO","FwEJzTCgPp","0BmCyHRxd8","WmadAPOUYS","UmaEvZhwG1","CqqaDnnP8o","8cVD3UmaEv","pvgjSNOHsz",
-"gIYvEblLA9","fFDrJzFgtB","uTacxuZPqg","jeskSCIShG","uPX7GYf2Ec","618DiM6qcG","suY4xpWiOs","vOqCEJkzUn","zQt6QazIWp","RmDcrcShY2",
-"5IhmGuQIcz","QWxoTjSjS3","FcWrWIRh48","GrDg7Qworu","NcICAatef2","K20wKjiVBP","4dEz6dpe1v","1v5hHuTacx","ThjNndpe1v","G1RhSv2eC3",
-"d85a9dmoS7","nlaByGSQwj","SWfouoVQp6","7hyVvMK07Y","K20wKVBjhz","WaWsvQbxXc","FLsphW7cTs","lpF6WOUqFM","ogLgcuN6r3","5ZaEz14FLR",
-"WreyPpvgjS","WPmlxsuY4x","IRh48atef2","8xEKzIn3NS","uvf7AfcwDa","pmeCdaL6AJ","yluBxMojnP","euZA5hYBCK","iB08ld85a9","RmDcr0BmCy",
-"KZamHlViBv","In3NSmX2GE","QworujfREu","ix74rsuY4x","pWiOss7Mxk","Uvlv4GWqqX","0ao3lgf8rI","07n1cb29RJ","45cIHy94nw","FGzgpVprf2",
-"nFqikhSSvQ","F6PT214FLR","VIlwPQnJ1S","k85Ae8TxD7","gf8rIGSQwj","d7vjMJXljW","vLsmSuN6r3","MK07Ylm0pD","VjCZqfcwDa","MmsIo2TRI7",
-"tlILtYw2oU","faHirRmDcr","yvOMIoQ87r","Zv7z0EOE1o","ydG8UQssNC","guMb8W3VFH","0PktIWMiS3","LDk6fIKxdL","dmoS7nFqik","VjCZqNo0Qb",
-"C2IrcZv7z0","2TRI7sqVrf","16lHcVNCPd","rKDLJCfgr3","580YDoQ87r","iKqhrX6Pin","lm0pDlkMUA","J2mQilH1kt","fcJOyeuZA5","0PktIXflUq",
-"lweGyiwzGk","WPmlx9GXkX","580YDni2v1","CxVEffmIK1","atef2atef2","OUYuFsoy9t","VerEAfqypy","LbRTHxReec","Chuy3xXTI4","RzaZAjSjS3",
-"GrDg7lm0pD","IRh48Fhtgl","gIYvEYOfrY","EOE1oO3iyQ","48cHLEdBKc","yEfy9Z4I1v","MezSWWreyP","7fsYMuTacx","bgJAzPOUYS","rz7Ut2ZHdk",
-"kB5nPzqH0W","DcpWBM3zXL","ulk411v5hH","SbRYyvLsmS","QbxXcFwEJz","Vprf2WmadA","pmeCdzFgtB","CqqaDd7vjM","oGu6xZv7z0","zmLYDWaim6",
-"AgJHQsuY4x","NOHsziB08l","OUYuFTa8f6","xReeche9IA","WDVWJJRJQB","W3VFHiKqhr","zbIYY2hEEU","EoToPIRh48","lH1ktdjsrv","7fKYUmz8gx",
-"s93MlpvgjS","2Yz7EjiVBP","J2mQitl72W","ksJbyMGlTF","m4bxUIKxdL","Pb1paCxVEf","0Kyfs9rlg9","dmoS764s8N","k85AejS1aj","aL6AJnFqik",
-"MmsIo55rfB","SjskQYOfrY","JRJQBbgJAz","jzUqRvkCHH","55rfB2ZHdk","O3iyQwiHrZ","hYBCKI7p2a","QworuzQt6Q","AgJHQwDajX","C2IrcMojnP",
-"4QMc9fLNg8","i7WMQIn3NS","7Ow5CMm8si","fFDrJtjQxs","OxWIH9eoRc","NAFuwYjB9t","aFFsszQt6Q","lsQGo5IhmG","QssNCNhXdu","fcJOyS2Dfu",
-"FxX9q3otm6","soy9tX6Pin","14FLRHlUbF","MojnPlXFOB","s7MxkHP433","zQt6Q618Di","b29RJvOqCE","jeskSQChxs","FFDuitjQxs","xReec0PktI",
-"L7cGcJ2mQi","FxX9qlkMUA","cShY2ix74r","5NammlXFOB","vLsmSMm8si","iKqhrMmsIo","EOE1oNOHsz","45cIH55rfB","QnJ1Se6e4z","U3yw5fmIK1",
-"NOHszChuy3","pmeCddpe1v","WPmlxoGu6x","lpF6W9eoRc","Fhtgl2Yz7E","Yh1hF7ku1p","HlUbFYw2oU","oVQp6S2Dfu","bZLvS7fsYM","lm0pD5Drn0",
-"L7cGc7fsYM","dpe1vEoToP","hSSvQQYxC0","lj07QRACuj","IRh48AOgEe","ThjNnBbwgA","x3LDeVBjhz","FnPFBCxVEf","fmIK1IBe8k","fLNg814FLR",
-"HzZT8yluBx","AgJHQpAhR1","7Ow5CazIWp","yofH3m4bxU","tjQxs9eoRc","aDGtS618Di","KZamHO3iyQ","MojnPgtCA5","s93Mlt59lR","ReKEWoVQp6",
-"7X3uyFVMxo","GWqqXRpBQm","9y4lwblLA9","POUYSfcJOy","FGzgpuPX7G","VNCPdTXQ0Z","tl72W6AFT0","dhSuHlj07Q","uAWypv2eC3","6q6L90h1b1",
-"45cIHTa8f6","2hEEUS2Dfu","piJSkzbIYY","ciuWzhE1Ql","48cHLuZPqg","KsjRKzmLYD","AXpwEM3zXL","PYBf4KsjRK","WmadAAkKTk","KsjRKYf2Ec",
-"hSSvQtvdkD","HlUbFIBe8k","Vprf2BFkb8","M6qcGm4bxU","zY1GYNcICA","MojnPpiJSk","hE1QlWMiS3","i7WMQ5drc6","zmLYDdpe1v","e6e4zuJScX",
-"kZANmHP433","n8pJ9EdBKc","5Drn0jSjS3","faHirrhl0J","0PktI07n1c","8cVD3pWiOs","zHF1quvf7A","BbwgAbZLvS","OHaBz9eoRc","JXljWiB08l",
-"s47867hyVv","cL0aEdhSuH","M3zXLprNT6","Uvlv4prNT6","9iGoTuJScX","5VZjSzqH0W","ogLgcjtn0X","prNT62Nslm","DQimpdQ586","0ao3llkMUA",
-"0ao3l7lUXZ","yofH3LewvM","JkzUnpWiOs","uZPqgMmKGJ","cShY2FPfSE","KsjRKv8yFN","2Nslm0Wr5y","D6rBylj07Q","45cIHjzUqR","fcJOyn8pJ9",
-"zQt6Qv8yFN","Cp3mZ5drc6","fcwDaxReec","gIYvE0PktI","8FmFHqUJMd","ZJTXHiKqhr","zz4ZUNxx9V","ReKEWTCgPp","FnPFBxciqp","vLsmSB3qem",
-"OUqFMjSjS3","FGzgpsqVrf","3weIFSjskQ","gjUTulweGy","zz4ZUThjNn","jS1aj0Kyfs","uLtKsQnJ1S","VLTy63otm6","FFDuieuZA5","guMb8s4786",
-"gjUTu618Di","euZA5DLhzM","2Yz7EO3iyQ","fqypytl72W","vOqCE2TRI7","prNT6iKqhr","DcpWBrKDLJ","lH1ktfFDrJ","0PktIfqypy","F6PT2pT8wu",
-"tlILtvOqCE","QChxsjiVBP","VBjhzogLgc","prNT6CqqaD","lj07QG1RhS","dQ586GXdoH","gtCA5e6e4z","GXdoHoGu6x","uLtKse6e4z","mX2GEBFkb8",
-"4dEz6tvdkD","5ZaEzksJby","tAOsrzz4ZU","d85a9DLhzM","Mkgy8CxVEf","QYxC0fLNg8","SjskQLewvM","s7MxkCdyBV","gf8rIcL0aE","9iGoTkZANm",
-"FjHXRK4GS8","bZLvSQnJ1S","AmdQdFFDui","RzaZAGWqqX","CxVEfBpYhV","5NammAIYUu","7lUXZ0PktI","Zv7z0FNYIM","pmeCdOUYuF","8FmFHM3zXL",
-"mX2GEl83Ud","OHaBz0YAGH","tl72WDLhzM","uoStwHzZT8","RACujLDk6f","POUYSFFDui","blLA90BmCy","tlILtVprf2","P6bcgjSjS3","P6bcgsqVrf",
-"24ARFVIlwP","fFDrJFhtgl","IRh48aL6AJ","WreyPfLNg8","X6PinpT8wu","vOqCE3weIF","1j5L83weIF","MmKGJOz8yZ","jSjS3tAOsr","XyPZNydG8U",
-"oQ87rWPmlx","C2IrcKASQ8","mz8gxzY1GY","55rfBqaofN","tlILttaOXK","Vprf2hSSvQ","tjQxsru4UG","uQIcztuDyS","Mm8si48cHL","FcWrWBFkb8",
-"1j5L8K20wK","ogLgcuoStw","ZUnqtfLNg8","l83UdJXljW","bZLvSfFDrJ","cShY2ydG8U","QbxXc29QAz","zbIYYpFrrl","FNYIMVLTy6","QClRLuvf7A",
-"No0QbFxX9q","O3iyQo8Uyd","rhl0JuAWyp","tvdkDoGu6x","CNHmvru4UG","GWqqXlViBv","CxVEfyofH3","64s8NGrDg7","DQimpvLsmS","OxWIHOHaBz",
-"P6bcgzHF1q","fLNg8ZUnqt","Q6hMCG1RhS","U3yw5L7cGc","1LB1LKZamH","F6PT2o8Uyd","QbxXcG1RhS","uoStwyluBx","v8yFNiqv4k","1j5L855rfB",
-"YOfrYO3iyQ","WaWsvvLsmS","SmGzvPOUYS","BbwgAPb1pa","UlU3MXyPZN","Y1mC0LbRTH","DLhzMFxX9q","v8yFNIjTwP","16lHcFxX9q","Twano580YD",
-"oVQp6FjHXR","atef23otm6","d85a9t59lR","JKWYRi7WMQ","VerEApiJSk","kZANmix74r","ni2v1oVQp6","ciuWzulk41","CNHmvv1Hln","nFqiknnP8o",
-"jiVBPzz4ZU","uLtKstAOsr","2TRI7t59lR","fcwDa7fsYM","9eoRc45cIH","jSjS3RkQke","S2Dfu7hyVv","pmeCdGv3Fq","No0QbqUJMd","jfREuogLgc",
-"0Kyfs8xEKz","zz4ZUtvdkD","s4786F6PT2","AXpwEJkzUn","YOfrY14FLR","SmGzvIjTwP","iKqhrW7cTs","XflUqLbRTH","0PktIgIYvE","Nxx9Vlj07Q",
-"dpe1vZUnqt","m4bxUVerEA","v8yFNgIYvE","vkCHHulk41","tuDyS55rfB","pWiOsMaJQs","x3LDehYBCK","C2Irc48cHL","FNYIM0h1b1","2DREsrhl0J",
-"VjCZqFPfSE","Ss0ZuMmKGJ","ru4UGGXdoH","M3zXLCxVEf","2DREsYOfrY","CdyBVgIYvE","hE1QlRzaZA","ZUnqtLewvM","ydG8U9eoRc","LbRTHy94nw",
-"J2mQitvdkD","hE1QlGv3Fq","qaofNVjCZq","gtCA5SWfou","16lHcQClRL","euZA5bZLvS","J2mQiNxx9V","VjCZqMK07Y","WDVWJ8FmFH","Vprf2cmXIX",
-"Ss0Zu5Mg9r","B3qem9rlg9","d85a9NOHsz","StlDJm4bxU","WMiS32ZHdk","07n1cyofH3","2ZHdk9GXkX","8TxD7s93Ml","v8yFN9rlg9","ThjNnDQimp",
-"BpYhVX6Pin","2TRI7ZUnqt","LewvMSs0Zu","kZANmlsQGo","Cfgr3zz4ZU","0MR5XXflUq","AkKTkxciqp","Y1mC0fcJOy","GSQwjMm8si","Cp3mZ7hyVv",
-"uZPqgM6qcG","jiVBPVprf2","e6e4zQWxoT","QClRLuupzk","L7cGcYf2Ec","pWiOslH1kt","o8UydyvOMI","TXQ0ZFnPFB","W3VFHTa8f6","ulk41pFrrl",
-"gIYvEIRh48","BFkb8QYxC0","WreyPuQIcz","DLhzMb29RJ","580YDJJs5m","C2IrcQssNC","cmXIXCdyBV","S77LHs7Mxk","MojnPFNYIM","ZuDtDdjsrv",
-"a00b5ECMvU","CNHmvCp3mZ","24ARFGv3Fq","vLsmSjzUqR","lViBvkB5nP","fLNg816lHc","QssNC3weIF","TCgPpOHaBz","2Yz7EQ6Lix","8RCUAxReec",
-"zQt6QVLTy6","M3zXL9GXkX","tjQxsReKEW","0PktI7lUXZ","Mkgy8n8pJ9","2hEEU7fsYM","taOXKiKqhr","4dEz6KASQ8","lkMUAPb1pa","FGzgpIRh48",
-"euZA5JJs5m","uAWyp48cHL","SjskQWaWsv","a00b5Z4I1v","brhlQtvdkD","AOgEeuLtKs","rKDLJkB5nP","8RCUA2ZHdk","L7cGcHzZT8","580YD45cIH",
-"UlU3MzmLYD","cShY2XflUq","cShY2pmeCd","lH1kts93Ml","9XyT95drc6","4dEz6wDajX","cL0aESmGzv","QClRLRpBQm","POUYS0h1b1","fLNg8Rxrsm",
-"8xEKzHRxd8","tl72WWreyP","lj07QQnJ1S","P6bcgrhl0J","3weIFEoToP","hE1QljSjS3","xXTI4StlDJ","lXFOBI7p2a","Cp3mZiKqhr","aez9yhi5X7",
-"Yw2oUQnJ1S","AIYUulpF6W","cmXIXGSQwj","EdBKcpvgjS","jSjS3K20wK","QClRLIRh48","tvdkD2Nslm","9y4lwUvlv4","uJScX45cIH","4W0Tl3weIF",
-"VjCZquTacx","FGzgpX6Pin","WaWsvS2Dfu","FNYIMjzUqR","7Ow5CzFgtB","Kr8ysdmoS7","zz4ZU2Nslm","XflUqPOUYS","S77LH5iGN5","NOHsz9rlg9",
-"Fhtgl5Namm","QChxsru4UG","0MR5XCdyBV","1j5L8JkzUn","atef2wDajX","0KyfslpF6W","nFqikOz8yZ","0KyfsvkCHH","SjskQ9rlg9","VjCZqnlaBy",
-"lH1ktsoy9t","J2mQigf8rI","45cIHs7Mxk","lCMxy8xEKz","aDGtSjSjS3","uPX7GEoToP","iB08lW7cTs","GWqqXFFDui","RmDcrMkgy8","RzaZAsqVrf",
-"F6PT2VBjhz","SWfousuY4x","m4bxU8xEKz","uJScXW3VFH","0PktIYw2oU","GrDg77fKYU","24ARFuJScX","7X3uy5Drn0","3otm65Namm","gdQsSQ6Lix",
-"YOfrYIBe8k","DQimpZJTXH","2DREsZzJHW","RxrsmjfREu","uTacxjS1aj","CdyBVguMb8","3otm6uJScX","0PktISmGzv","Ta8f6M6qcG","tuDySx3LDe",
-"FxX9qMkgy8","MaJQsNhXdu","dhSuHciuWz","sqVrflpF6W","he9IAwiHrZ","AOgEeZzJHW","7ku1pTa8f6","RACujmX2GE","0MR5XxReec","5VZjSZzJHW",
-"C2Ircuvf7A","cL0aEUl4a1","tjQxs5ZaEz","VIlwPhi5X7","SWfouaez9y","zbIYYuvf7A","vOqCEK20wK","soy9ttuDyS","jzUqRWreyP","AkKTk3otm6",
-"EOE1oTa8f6","WmadAOz8yZ","PYBf4MmsIo","k85AesqVrf","guMb8wiHrZ","Yh1hFK4GS8","gdQsSgIYvE","pFrrlQnJ1S","jtn0XNhXdu","0ao3lQ6hMC",
-"d7vjMfcJOy","kB5nPQWxoT","W7cTspFrrl","d7vjMfaHir","WreyPdhSuH","ciuWz2Yz7E","Y1mC0faHir","BFkb8azIWp","Q6LixlpF6W","9XyT9s7Mxk",
-"LewvMMm8si","iB08luPX7G","ZhwG1o8Uyd","qQxHPCNHmv","oQ87r48cHL","he9IA45cIH","CNHmvVNCPd","tvdkDSWfou","l83Udzz4ZU","L7cGc5Namm",
-"m4bxUAXpwE","Q6hMCjSjS3","yToGWtAOsr","JKWYRvOqCE","aDGtSuJScX","OxWIHU3yw5","JXljWgtCA5","QworuCxVEf","CK5W7tjQxs","QChxsiqv4k",
-"n8pJ9C2Irc","8cVD3ReKEW","lweGyCp3mZ","0Wr5yblLA9","MK07YRACuj","29QAzU3yw5","6q6L9EOE1o","BbwgAMojnP","zmLYD6q6L9","lsQGoQssNC",
-"ZUnqtksJby","t98iWlCMxy","NOHsz2hEEU","No0Qb7fKYU","HP433sqVrf","1j5L8l83Ud","jeskSiB08l","QbxXc9eoRc","sqVrfFjHXR","6AFT0n8pJ9",
-"2Yz7EcQOnv","2hEEUciuWz","uvf7ANxx9V","VjCZqEdBKc","JIqXi3otm6","jiVBPZzJHW","jS1ajIBe8k","mz8gxCqqaD","CNHmv0YAGH","kB5nPi7WMQ",
-"48cHLNOHsz","i3pydpAhR1","POUYSjSjS3","9eoRcTCgPp","VjCZqFnPFB","cmXIXsuY4x","rKDLJni2v1","hE1QlbZLvS","taOXKvOqCE","pWiOsHlUbF",
-"Pb1paazIWp","Uvlv4n8pJ9","faHirPYBf4","dhSuHgjUTu","IRh48G1RhS","iKqhrrz7Ut","S77LHydG8U","K20wKgIYvE","nFqikzQt6Q","7X3uyyluBx",
-"2hEEUjzUqR","d85a9QWxoT","24ARFUl4a1","SWfou5nmWv","Q6LixlCMxy","s93MlAIYUu","2DREs7X3uy","ZzJHWIKxdL","dpe1vIRh48","ydG8U9XyT9",
-"QWxoTHRxd8","S77LHsx5Gl","ydG8ULewvM","FPfSELewvM","16lHcBpYhV","8cVD3580YD","uN6r329QAz","rhl0J48cHL","7X3uyjtn0X","Ta8f6ru4UG",
-"MezSWCK5W7","0PktIC2Irc","29QAzHfyNQ","WreyPjfREu","5NammHlUbF","IBe8kjS1aj","yofH3tlILt","JXljWVjCZq","QChxs14FLR","zqH0WFNYIM",
-"3weIFhe9IA","vOqCEbgJAz","WMiS3qQxHP","y94nwlXFOB","CIShGIjTwP","HlUbFOz8yZ","W7cTsBGaQY","GSQwj1LB1L","8FmFHtlILt","ni2v1OUYuF",
-"faHir5iGN5","jzUqRS2Dfu","HzZT8suY4x","TCgPpFxX9q","MGlTFs4786","PYBf4ZUnqt","QworuVIlwP","tlILtjS1aj","BFkb8QnJ1S","BbwgAjfREu",
-"0KyfsThjNn","6AFT0M6qcG","7hyVvwiHrZ","WmadA0Kyfs","0YAGHyToGW","n1pmOL7cGc","RpBQmIKxdL","okgRi5nmWv","h1zcHKr8ys","YOfrYiwzGk",
-"jfREuaDGtS","JIqXixciqp","9XyT9nlaBy","8xEKzjtn0X","iwzGkUvlv4","jSjS3P6bcg","wiHrZ1LB1L","tAOsr5ZaEz","BpYhVzFgtB","45cIHs93Ml",
-"guMb8okgRi","aDGtSTwano","lkMUAjtn0X","X6Pinsoy9t","ThjNnbZLvS","F6PT2S2Dfu","HfyNQblLA9","gdQsSEOE1o","NcICAbgJAz","tl72WuQIcz",
-"Vprf20Wr5y","nnP8oUmaEv","kZANmrz7Ut","KASQ8RmDcr","tjQxs8U2nU","3otm6oQ87r","X6Pind7vjM","OHaBzHlUbF","UlU3MfaHir","ZhwG1vLsmS",
-"lsQGoDcpWB","h1zcHWaWsv","Q6hMCogLgc","0MR5X8U2nU","lpF6WYjB9t","uvf7AtaOXK","yofH3RpBQm","d85a97fKYU","FcWrWFhtgl","IKxdLDLhzM",
-"ZhwG1QClRL","AkKTklH1kt","piJSkgtCA5","8xEKzKr8ys","In3NSUl4a1","8RCUAm4bxU","5drc67ku1p","POUYS2DREs","kZANmk85Ae","3weIFv1Hln",
-"fcwDaFLsph","ThjNnHlUbF","ogLgcd7vjM","WreyPSWfou","8cVD3W3VFH","FnPFBgjUTu","yluBxokgRi","MaJQsyofH3","5nmWvjS1aj","2DREs8FmFH",
-"iwzGkK20wK","DLhzMuZPqg","OUqFMJXljW","GSQwjRxrsm","kB5nPv1Hln","piJSk4W0Tl","xciqpFFDui","v8yFNqaofN","ydG8UpT8wu","B3qem580YD",
-"POUYSMmKGJ","SmGzvyvOMI","5drc6brhlQ","v8yFNm4bxU","tlILti3pyd","zY1GYlXFOB","jeskStaOXK","QssNC5Mg9r","t98iWQClRL","5Drn0HzZT8",
-"8RCUAQWxoT","v8yFNwiHrZ","618DiMaJQs","16lHcyofH3","CxVEf4W0Tl","hE1QlChuy3","VBjhzatef2","AkKTkd85a9","YjB9tSs0Zu","uoStwuoStw",
-"cL0aEXyPZN","s4786S2Dfu","WMiS3M6qcG","cL0aEsoy9t","iqv4kCqqaD","d7vjMPb1pa","6q6L9BFkb8","5iGN5FwEJz","tl72W5IhmG","v8yFNY1mC0",
-"07n1cdhSuH","ZhwG1aFFss","JXljWS2Dfu","ReKEWpiJSk","nFqikJ2mQi","atef21v5hH","2hEEUVIlwP","HlUbF5Namm","mX2GEZzJHW","7fsYMcmXIX",
-"8xEKz7fKYU","ni2v1HP433","LDk6fYf2Ec","Waim6aFFss","t59lRoQ87r","i3pyd7fsYM","16lHcogLgc","tjQxsd85a9","16lHc55rfB","dQ586WPmlx",
-"kZANm29QAz","Yh1hFfcwDa","7fsYMNhXdu","Zv7z0IRh48","LbRTHDG4sT","FjHXR3weIF","Zv7z0QssNC","pWiOsjSjS3","gjUTuydG8U","45cIHxReec",
-"BFkb8XflUq","k85AeBFkb8","lkMUAfFDrJ","hUTw7GSQwj","Zv7z06AFT0","QnJ1SFLsph","TCgPp7hyVv","7fKYUJXljW","SjskQksJby","VerEAvkCHH",
-"AIYUu9iGoT","SjskQpT8wu","VjCZqvkCHH","L7cGcCNHmv","b29RJNOHsz","blLA9nFqik","TXQ0ZO3iyQ","yToGWCK5W7","GWqqX5drc6","0h1b15Namm",
-"5IhmG7Ow5C","FNYIMzY1GY","xciqpHlUbF","blLA964s8N","SWfoud85a9","hE1QldQ586","fFDrJLewvM","atef2RmDcr","OHaBztjQxs","d7vjMi7WMQ",
-"IKxdLKr8ys","iKqhrv2eC3","0YAGH5iGN5","jtn0X580YD","9GXkXpWiOs","lj07Q55rfB","zFgtB5Drn0","HRxd8S2Dfu","IBe8kZ4I1v","wiHrZfmIK1",
-"gdQsStuDyS","ReKEW3weIF","2Nslm0ao3l","0ao3lv1Hln","wDajX0PktI","VBjhzRmDcr","fLNg8RACuj","s7MxkzHF1q","Chuy3CdyBV","Mm8sidpe1v",
-"OxWIHECMvU","5drc6uJScX","fFDrJ5ZaEz","J2mQinFqik","0BmCyZuDtD","lCMxyCp3mZ","brhlQWMiS3","BbwgAYf2Ec","v8yFNi3pyd","OxWIH9y4lw",
-"ThjNnfmIK1","48cHLhE1Ql","pv0i7RkQke","tl72WogLgc","8TxD7pWiOs","BbwgAYOfrY","tjQxsNAFuw","M6qcGMK07Y","HP433blLA9","XflUqIRh48",
-"ix74r618Di","QWxoTAgJHQ","JXljWSWfou","Nxx9VFLsph","lCMxy0ao3l","v1HlnNcICA","QbxXcUl4a1","JKWYR8FmFH","QClRLo8Uyd","ZuDtDAIYUu",
-"uupzkTa8f6","6q6L9IjTwP","b29RJVprf2","gf8rIZ4I1v","qQxHPKsjRK","hi5X7KZamH","64s8NpWiOs","jiVBP5Mg9r","0MR5XuoStw","tjQxsBGaQY",
-"LbRTHK20wK","8xEKzHzZT8","0ao3lCK5W7","WDVWJAmdQd","7hyVvFPfSE","FLsphzmLYD","ZJTXHv2eC3","O3iyQfaHir","YOfrYVprf2","yToGWbrhlQ",
-"CdyBVCp3mZ","pFrrllsQGo","wDajXfmIK1","aez9yFFDui","qUJMd8U2nU","a00b5tjQxs","M6qcGSbRYy","mz8gxuupzk","2ZHdkWreyP","ECMvU7ku1p",
-"K4GS8bZLvS","7hyVvuZPqg","0KyfsmX2GE","cL0aEtl72W","soy9tdpe1v","pWiOsDcpWB","k85AeCdyBV","8RCUA3weIF","BFkb8k85Ae","Gv3FqZ4I1v",
-"fFDrJ9iGoT","7fsYMbgJAz","gIYvEJ2mQi","faHir7fsYM","X6Pin1j5L8","MezSWQ6Lix","dmoS7HlUbF","VjCZqECMvU","jSjS3zqH0W","azIWpAmdQd",
-"FLsphRxrsm","uoStwCNHmv","faHirHP433","lm0pDTa8f6","ZUnqtUl4a1","4dEz6zz4ZU","SbRYyHlUbF","AOgEegjUTu","nlaBy4W0Tl","gtCA5tuDyS",
-"yEfy9FNYIM","POUYSyToGW","CNHmvcmXIX","jSjS3zz4ZU","s93MlksJby","F6PT2B3qem","29QAz8TxD7","QWxoTFjHXR","FhtglPYBf4","aFFssqaofN",
-"pFrrl5Drn0","fcwDaOHaBz","TCgPpydG8U","fcJOyVprf2","fmIK1vLsmS","CNHmvdmoS7","jS1ajYw2oU","AmdQdBGaQY","Dz1R39y4lw","djsrvydG8U",
-"16lHct59lR","8U2nUm4bxU","QWxoTuupzk","jSjS3t59lR","jeskSjS1aj","FGzgp9iGoT","FjHXRfFDrJ","Vprf207n1c","b29RJSs0Zu","SWfouRBhp0",
-"he9IAv8yFN","MK07YAgJHQ","ydG8UhE1Ql","2Yz7E7fKYU","s4786s4786","LDk6f2ZHdk","uAWyp4QMc9","8hJdt618Di","KsjRKFVMxo","Yw2oUBFkb8",
-"lXFOBY1mC0","CxVEfguMb8","5Drn0xXTI4","TXQ0ZfFDrJ","ZJTXHWaWsv","uoStwbgJAz","0KyfshE1Ql","tl72Wh1zcH","iwzGkMmKGJ","pFrrl5IhmG",
-"7X3uyNxx9V","zqH0WW7cTs","MK07YMmKGJ","VIlwPSjskQ","KZamHStlDJ","y94nwzY1GY","OxWIHpv0i7","VNCPdcShY2","0PktIQWxoT","ogLgccmXIX",
-"Vprf27Ow5C","Yf2EclCMxy","ydG8UY1mC0","45cIHlj07Q","DG4sTHRxd8","QnJ1Sdpe1v","LbRTHFPfSE","zz4ZUO3iyQ","fcwDauN6r3","2ZHdkPOUYS",
-"dQ586iwzGk","prNT67lUXZ","uupzk5iGN5","JKWYRxXTI4","hSSvQXyPZN","uQIczQClRL","S2DfukZANm","JRJQBwDajX","piJSknnP8o","cL0aE0Kyfs",
-"yToGWFjHXR","RzaZA1v5hH","s4786s7Mxk","t59lRlXFOB","5Drn0OxWIH","guMb8Cp3mZ","Yw2oUlpF6W","618DiIKxdL","Chuy3hE1Ql","Pb1papmeCd",
-"iwzGkwiHrZ","n1pmO7fKYU","6q6L9gIYvE","M6qcG8U2nU","QClRLChuy3","fLNg8fFDrJ","GWqqXFwEJz","zqH0W0Wr5y","ZJTXH0YAGH","FwEJzCNHmv",
-"7lUXZNAFuw","ix74roQ87r","EdBKcIKxdL","oQ87rAOgEe","4QMc955rfB","Yw2oUChuy3","7lUXZRxrsm","5Drn0ZhwG1","MGlTFRACuj","aDGtSNhXdu",
-"lpF6WQssNC","OUqFMFLsph","pv0i7n8pJ9","Dz1R3DLhzM","W7cTsoVQp6","Gv3Fqrz7Ut","lkMUAFGzgp","9rlg9Gv3Fq","n1pmOaDGtS","OxWIHMaJQs",
-"DLhzMcQOnv","MojnPiwzGk","kZANmJ2mQi","soy9te6e4z","vOqCEThjNn","MezSWVNCPd","618DiAmdQd","24ARFS77LH","G1RhSOHaBz","FFDui5Namm",
-"CIShG580YD","lkMUAEdBKc","GWqqXDQimp","blLA9NhXdu","S77LHJ2mQi","24ARFQChxs","7hyVvQYxC0","ksJby2TRI7","0Wr5yOxWIH","BGaQYblLA9",
-"guMb8VNCPd","FLsphdmoS7","2ZHdkn8pJ9","5NammMojnP","0Wr5ydjsrv","ZhwG1wDajX","Gv3FqjS1aj","soy9tFjHXR","0KyfszbIYY","Uvlv45ZaEz",
-"FwEJzzmLYD","fLNg8t59lR","qUJMdxXTI4","QYxC0rhl0J","gjUTuU3yw5","OHaBzoQ87r","2NslmpAhR1","9y4lwFjHXR","QChxsGXdoH","tjQxsStlDJ",
-"ulk41AkKTk","WDVWJSbRYy","In3NSjtn0X","5Drn0Q6Lix","fcJOy24ARF","dQ586tlILt","SbRYyuN6r3","7ku1p1LB1L","2ZHdkUvlv4","soy9tDLhzM",
-"Qworurz7Ut","XyPZNStlDJ","I7p2aVIlwP","FcWrWdjsrv","Q6LixjeskS","i7WMQlweGy","v8yFN2Nslm","qQxHPuQIcz","Y1mC0ZhwG1","QworufmIK1",
-"9XyT9K4GS8","5ZaEzThjNn","fFDrJcShY2","5nmWvnnP8o","blLA9RBhp0","DcpWBS2Dfu","wDajXuQIcz","cShY25drc6","lCMxy5iGN5","Pb1paZzJHW",
-"Pb1parhl0J","s4786ZJTXH","mX2GEM6qcG","uoStwatef2","7lUXZvOqCE","m4bxUdjsrv","GWqqXCxVEf","ZUnqtWmadA","faHirCp3mZ","yofH3xciqp",
-"pvgjS29QAz","iwzGk1j5L8","ogLgcfcwDa","QWxoTi7WMQ","7hyVvl83Ud","ksJby8U2nU","K4GS8BbwgA","IjTwPJKWYR","BpYhVhe9IA","7ku1pOUqFM",
-"WreyPzQt6Q","tvdkDd85a9","5nmWvM6qcG","gtCA5Chuy3","Yw2oUyEfy9","euZA5U3yw5","vOqCEtAOsr","IKxdL55rfB","ReKEWSmGzv","OUYuF0h1b1",
-"i3pydlweGy","8U2nUy94nw","6q6L9JXljW","uAWypJIqXi","LewvMNOHsz","2ZHdkfLNg8","gjUTupv0i7","cShY2IRh48","TCgPpuAWyp","atef2ciuWz",
-"hUTw7wDajX","8TxD79y4lw","cShY2b29RJ","nFqik0ao3l","xXTI4KsjRK","MK07YjS1aj","5NammY1mC0","IKxdLhSSvQ","FPfSEBFkb8","pvgjSS77LH",
-"lViBvSjskQ","VerEAmz8gx","JIqXiBCxeC","lViBvW3VFH","ZuDtDMmKGJ","cL0aEksJby","v1Hln5drc6","RzaZAB3qem","Z4I1vmz8gx","DLhzMMmKGJ",
-"L7cGciB08l","hSSvQ9XyT9","WreyPIRh48","ix74rCK5W7","gjUTugdQsS","azIWpWaWsv","i3pyd0YAGH","ydG8UChuy3","xXTI4M6qcG","nlaByAgJHQ",
-"ksJbyi7WMQ","Mm8sipvgjS","2ZHdkEdBKc","jtn0XL7cGc","n1pmOG1RhS","pv0i7he9IA","yvOMIulk41","NAFuwnlaBy","WPmlx7hyVv","S77LHzqH0W",
-"aDGtSzbIYY","jeskSRsQUq","AgJHQKsjRK","5drc62hEEU","QbxXcVerEA","7X3uyDLhzM","WreyPnnP8o","0BmCyk85Ae","8RCUAjzUqR","0Wr5yYh1hF",
-"2DREsNhXdu","HRxd8uTacx","M6qcGBbwgA","IjTwPYh1hF","L7cGc4dEz6","64s8NazIWp","MmKGJ8hJdt","AIYUunnP8o","v1Hln7fsYM","tjQxsuZPqg",
-"k85AehUTw7","WMiS3IRh48","tAOsrG1RhS","gdQsSCp3mZ","atef2WDVWJ","ECMvUWMiS3","8xEKzK4GS8","ZuDtDlj07Q","lkMUAFLsph","FnPFBpmeCd",
-"WreyPZ4I1v","2ZHdkOHaBz","2Yz7EDz1R3","QnJ1SpAhR1","hE1QlwiHrZ","P6bcgaDGtS","ksJbyUlU3M","7hyVvCNHmv","0Kyfs6q6L9","s4786xXTI4",
-"0KyfsM3zXL","uupzksqVrf","HlUbFAmdQd","FGzgpWMiS3","ReKEWlpF6W","d7vjMd7vjM","zz4ZUCp3mZ","4QMc9S2Dfu","fFDrJJkzUn","rhl0JWDVWJ",
-"oVQp6Fhtgl","fFDrJfcJOy","v8yFNW3VFH","5IhmGqUJMd","y94nw0MR5X","16lHcqaofN","iB08lxReec","cmXIX618Di","FjHXREdBKc","M3zXL2Nslm",
-"pmeCde6e4z","uJScX7hyVv","EdBKcZUnqt","pv0i7FjHXR","In3NSTXQ0Z","tAOsrhSSvQ","gdQsS580YD","M3zXL24ARF","9y4lwfmIK1","DcpWBDz1R3",
-"wDajXHzZT8","Ul4a1B3qem","Kr8ysx3LDe","3weIFYh1hF","7ku1pcmXIX","s93MlcmXIX","7hyVvqUJMd","Dz1R39eoRc","jiVBPThjNn","h1zcHFLsph",
-"gIYvEIKxdL","P6bcgWMiS3","vkCHHzz4ZU","RsQUqvkCHH","lsQGoi7WMQ","gIYvEnFqik","fmIK19rlg9","FFDui7hyVv","rhl0JOHaBz","I7p2alH1kt",
-"SbRYy9rlg9","UlU3MuLtKs","guMb8uAWyp","S2DfujfREu","mX2GEIjTwP","AXpwEatef2","JIqXitl72W","vOqCE2DREs","ThjNnGWqqX","vOqCEY1mC0",
-"guMb8bgJAz","e6e4z7hyVv","CIShG5ZaEz","JJs5mFjHXR","Cp3mZzFgtB","VerEANOHsz","fcJOy4W0Tl","EOE1oP6bcg","HP433U3yw5","Q6LixtjQxs",
-"XflUqiwzGk","pAhR1pv0i7","OxWIHn8pJ9","hYBCK24ARF","oGu6xIBe8k","JIqXilpF6W","hE1QlhUTw7","SjskQ0ao3l","pFrrlpv0i7","jS1ajEdBKc",
-"7fKYU2hEEU","HRxd8CqqaD","d7vjMJIqXi","9iGoTBCxeC","MK07Y8xEKz","bZLvS2DREs","lH1ktChuy3","WMiS3lkMUA","VIlwPMezSW","Kr8ysh1zcH",
-"CK5W70PktI","45cIH9y4lw","wDajXqQxHP","L7cGc8xEKz","VIlwPEoToP","JXljWThjNn","Vprf2iwzGk","8TxD78xEKz","HP433cL0aE","FnPFBzmLYD",
-"QnJ1Sv8yFN","zmLYDn1pmO","FPfSE8RCUA","yvOMIStlDJ","7fKYUazIWp","lm0pDZUnqt","WreyPbgJAz","Zv7z0k85Ae","RmDcr8U2nU","aFFssmz8gx",
-"tl72WtAOsr","RACuj7Ow5C","d7vjMdmoS7","W7cTssoy9t","jtn0XY1mC0","2ZHdk5Namm","iwzGksqVrf","X6Pin4dEz6","zqH0WtaOXK","iwzGkYOfrY",
-"dpe1v45cIH","gf8rIy94nw","2hEEUQ6hMC","Uvlv4BFkb8","lj07QBbwgA","atef2FcWrW","hSSvQ8cVD3","lViBvuZPqg","ciuWzOUYuF","bZLvSazIWp",
-"oVQp6dQ586","fFDrJ580YD","pWiOslm0pD","GWqqXKZamH","jSjS3ydG8U","zHF1qzqH0W","t59lRKr8ys","HfyNQQworu","8TxD7yToGW","QnJ1SuQIcz",
-"jSjS3OUqFM","5nmWvlm0pD","ni2v1x3LDe","s7Mxk8hJdt","CxVEflm0pD","CqqaD16lHc","9eoRclCMxy","pv0i7tAOsr","ECMvUsx5Gl","45cIHvOqCE",
-"NhXdu0PktI","nlaByWDVWJ","BGaQYGWqqX","brhlQ8xEKz","SbRYysuY4x","mX2GElXFOB","xXTI4GSQwj","8U2nUYOfrY","ZuDtDXyPZN","WreyP7ku1p",
-"QClRLSWfou","bgJAz5iGN5","QWxoTJkzUn","CxVEfQnJ1S","rKDLJBpYhV","cmXIXuJScX","IjTwPUvlv4","AgJHQyluBx","n8pJ9NhXdu","29QAzChuy3",
-"rz7Ut580YD","KZamHQYxC0","yEfy9tjQxs","Q6hMCulk41","580YDWMiS3","TXQ0ZbgJAz","vOqCE9eoRc","Mkgy8WPmlx","lm0pDzz4ZU","zqH0WWaWsv",
-"IKxdLzmLYD","G1RhSqUJMd","n8pJ9a00b5","IKxdLdpe1v","618DiNcICA","pWiOsix74r","hSSvQjS1aj","2Yz7Exciqp","I7p2akZANm","MezSW7lUXZ",
-"0MR5XJRJQB","zqH0WrKDLJ","K4GS8lsQGo","JRJQBaDGtS","FxX9qhE1Ql","Yw2oUtl72W","AmdQdNAFuw","FxX9qnFqik","1LB1LOz8yZ","SmGzvWDVWJ",
-"lXFOB2hEEU","SjskQeuZA5","SjskQlH1kt","VLTy629QAz","BpYhVAIYUu","M3zXL580YD","atef2jzUqR","J2mQiVerEA","Nxx9VazIWp","uJScXCK5W7",
-"FGzgpfLNg8","oVQp6tjQxs","lpF6Ws4786","AgJHQThjNn","7fKYUFnPFB","TCgPp8FmFH","8cVD35IhmG","ZUnqtG1RhS","sx5GlReKEW","nnP8ohSSvQ",
-"7Ow5CAXpwE","LewvMKASQ8","fLNg8e6e4z","FVMxopAhR1","1j5L8UlU3M","Y1mC0tjQxs","FnPFBQssNC","Q6hMC9rlg9","L7cGcfqypy","zFgtB1LB1L",
-"yEfy9SmGzv","gtCA5IjTwP","CxVEfuQIcz","0YAGHlm0pD","VBjhz4dEz6","J2mQiqUJMd","guMb8JkzUn","In3NSKZamH","fmIK1n8pJ9","lXFOBAIYUu",
-"W7cTs0Kyfs","Uvlv407n1c","2ZHdktaOXK","AgJHQciuWz","29QAzMmsIo","oQ87rzz4ZU","FGzgpuJScX","xciqp1v5hH","bgJAzCp3mZ","45cIHlXFOB",
-"gIYvE9rlg9","MK07YGWqqX","ECMvUSWfou","9iGoTHzZT8","QChxsCIShG","yvOMIAOgEe","C2IrcFwEJz","0Wr5yWmadA","GXdoHVNCPd","lweGytaOXK",
-"3otm6J2mQi","5drc6uZPqg","8U2nUuZPqg","LewvMKZamH","euZA50Wr5y","nFqikdmoS7","sqVrf55rfB","piJSk8hJdt","Uvlv49XyT9","LewvMuZPqg",
-"QssNC0BmCy","BpYhVAmdQd","djsrvNcICA","C2Irc8U2nU","Chuy3fLNg8","CqqaDpWiOs","QChxsTwano","TXQ0Zgf8rI","atef25iGN5","BpYhVRsQUq",
-"wDajXGv3Fq","5drc6mX2GE","2TRI79XyT9","1LB1LIBe8k","k85AeIKxdL","MmKGJpmeCd","POUYS618Di","FVMxojSjS3","Yh1hFuPX7G","2Yz7EMm8si",
-"Kr8ystvdkD","NcICAQChxs","0BmCyJIqXi","uZPqg9y4lw","pT8wux3LDe","zbIYYtAOsr","WaWsvUmaEv","gjUTuuupzk","MaJQs4QMc9","IKxdLyluBx",
-"BpYhVs93Ml","ciuWzcQOnv","14FLRguMb8","lCMxyTa8f6","hSSvQsx5Gl","7fKYUfcJOy","HzZT8h1zcH","Y1mC07X3uy","NhXduKZamH","MojnPDG4sT",
-"Z4I1vU3yw5","fFDrJKsjRK","ReKEWLewvM","QYxC0CK5W7","ciuWz9eoRc","e6e4z5IhmG","GrDg7J2mQi","DLhzMaDGtS","IBe8kRBhp0","LbRTHC2Irc",
-"7X3uy8U2nU","lweGy0h1b1","xReecGWqqX","NAFuwt59lR","BGaQYnlaBy","k85AeHlUbF","BFkb8L7cGc","Gv3Fq9eoRc","FnPFB5Namm","DcpWB4QMc9",
-"SbRYy9eoRc","tAOsre6e4z","lweGyZzJHW","VerEAAIYUu","jfREuOz8yZ","618DizmLYD","BFkb8WreyP","DG4sTECMvU","2TRI7Y1mC0","jtn0XECMvU",
-"Chuy35IhmG","FwEJzuvf7A","i3pydksJby","RzaZA580YD","prNT60YAGH","wiHrZ9GXkX","y94nwTXQ0Z","okgRi4W0Tl","i3pydMojnP","jtn0Xl83Ud",
-"BCxeCzz4ZU","FhtglBbwgA","QworubgJAz","xReecVIlwP","uPX7GfmIK1","Chuy3SmGzv","MojnPHlUbF","CNHmvPYBf4","CIShGU3yw5","RACujuLtKs",
-"Mkgy8Fhtgl","TwanoguMb8","VBjhzFwEJz","tvdkDB3qem","ZUnqtpT8wu","9y4lwSmGzv","o8UydDQimp","GrDg71j5L8","guMb8xReec","h1zcHFGzgp",
-"k85AeCK5W7","BGaQYzmLYD","zHF1qoGu6x","gjUTuSmGzv","ZuDtDHP433","lViBv24ARF","vkCHHlXFOB","QworuDz1R3","v2eC3Nxx9V","v8yFNpiJSk",
-"580YDB3qem","mX2GE0h1b1","tAOsraez9y","FFDuixciqp","CK5W7UlU3M","hSSvQ5Namm","5VZjSCqqaD","soy9tYjB9t","FVMxoRkQke","8U2nU0PktI",
-"HfyNQZJTXH","F6PT2lCMxy","x3LDe8FmFH","ZUnqtcmXIX","jSjS3x3LDe","5IhmGU3yw5","djsrvAgJHQ","1v5hHqaofN","kB5nP5Namm","KZamHksJby",
-"oGu6x2DREs","MmsIo5Namm","HRxd89iGoT","uoStwaez9y","LbRTHFnPFB","FcWrWJJs5m","5Mg9rGv3Fq","cQOnve6e4z","uN6r3aFFss","fqypyKASQ8",
-"CdyBVYw2oU","jtn0XqaofN","CIShGaDGtS","OUYuFCqqaD","SWfouix74r","uoStwe6e4z","lH1kta00b5","i7WMQReKEW","JRJQBTa8f6","ulk419iGoT",
-"fFDrJUvlv4","0MR5X3weIF","MojnP7Ow5C","yluBxjS1aj","SmGzv2DREs","1LB1LzFgtB","SjskQ8TxD7","0Kyfsx3LDe","GWqqX3otm6","YOfrYWreyP",
-"euZA5d85a9","aFFssWmadA","vOqCEGXdoH","Zv7z0yvOMI","C2IrcOUqFM","rhl0J5Mg9r","t98iW0Kyfs","aL6AJo8Uyd","BFkb8uAWyp","fFDrJ7lUXZ",
-"9y4lwM3zXL","soy9tYf2Ec","yofH3RmDcr","ThjNndmoS7","CK5W7sqVrf","0KyfsFGzgp","14FLRjSjS3","QYxC0bgJAz","y94nwFwEJz","uAWypdmoS7",
-"oQ87rHRxd8","v8yFNQChxs","7ku1p16lHc","ZzJHWx3LDe","ksJbyCNHmv","IRh48fcJOy","7fsYMC2Irc","gIYvE0Kyfs","guMb8ru4UG","VerEAgtCA5",
-"uoStw0MR5X","0Wr5yqaofN","PYBf4MaJQs","uN6r3nlaBy","7fsYML7cGc","k85Aeo8Uyd","gIYvEwiHrZ","fqypyRzaZA","ThjNnVLTy6","HP433FGzgp",
-"blLA9pAhR1","djsrvm4bxU","0KyfsJKWYR","AkKTkdmoS7","jS1ajOxWIH","vLsmSatef2","lm0pDzQt6Q","9iGoTBpYhV","5iGN5azIWp","FnPFBJRJQB",
-"DLhzMZhwG1","1v5hHtvdkD","uupzkKsjRK","0Wr5yxReec","S2DfuVjCZq","m4bxU4W0Tl","t98iWpAhR1","lXFOBTwano","OUqFMHRxd8","MmsIo5nmWv",
-"pT8wu5drc6","W7cTsRxrsm","7Ow5Cb29RJ","Mm8siXflUq","uPX7G2Nslm","Twano1LB1L","t98iWlweGy","uN6r3BpYhV","tjQxsYw2oU","WaWsvdpe1v",
-"1LB1L64s8N","GXdoHSbRYy","Ta8f6jSjS3","RkQkeuAWyp","m4bxUChuy3","In3NSFVMxo","soy9thE1Ql","tl72W8xEKz","I7p2auLtKs","suY4xpT8wu",
-"brhlQbgJAz","x3LDeAmdQd","bZLvSulk41","pFrrldmoS7","5ZaEzsx5Gl","gdQsSQssNC","sx5GlIBe8k","VBjhzVjCZq","xXTI4JkzUn","Kr8ysECMvU",
-"sx5GlpWiOs","7X3uyStlDJ","AXpwEK4GS8","FjHXRo8Uyd","QYxC07Ow5C","2ZHdkjeskS","7fKYUWDVWJ","MaJQslViBv","iqv4kWaim6","pv0i7kB5nP",
-"v1Hln5nmWv","8U2nUbrhlQ","jS1ajuupzk","x3LDek85Ae","9GXkXQssNC","tuDySRxrsm","FVMxouvf7A","ni2v1xciqp","FxX9qmz8gx","cL0aEs7Mxk",
-"0MR5XkB5nP","e6e4zUl4a1","Pb1pas7Mxk","4dEz6n8pJ9","CIShG0ao3l","3otm6lm0pD","GXdoHS77LH","VLTy6aFFss","0h1b1nnP8o","uZPqg8U2nU",
-"jfREuNxx9V","FnPFB2TRI7","hUTw7Yh1hF","7fsYMsuY4x","fcJOygtCA5","nlaByMm8si","MmsIoi7WMQ","n1pmO8xEKz","tvdkD3otm6","iwzGko8Uyd",
-"KASQ8uZPqg","pWiOsJXljW","B3qemXyPZN","RACujkB5nP","zbIYY5drc6","rz7UtzHF1q","WreyP8RCUA","fqypyEdBKc","WDVWJazIWp","NhXduAXpwE",
-"Nxx9VNAFuw","QWxoTRpBQm","VLTy6ru4UG","pmeCdReKEW","ZhwG1gtCA5","he9IAJkzUn","ksJbyRzaZA","yofH3NcICA","nlaByjS1aj","k85AeUmaEv",
-"No0Qb7ku1p","FFDuiK20wK","7lUXZ5ZaEz","NOHszaL6AJ","pv0i7KASQ8","YjB9tHzZT8","MojnPOUqFM","LDk6fuupzk","QWxoT8hJdt","EOE1o55rfB",
-"ulk41qQxHP","lkMUAuTacx","zbIYYRkQke","fFDrJqaofN","fFDrJ16lHc","cmXIXEOE1o","QssNCprNT6","faHir7ku1p","kZANmJJs5m","Chuy3CNHmv",
-"fcwDapiJSk","m4bxUKASQ8","uLtKstaOXK","24ARFCfgr3","BpYhVOUYuF","mX2GE7fsYM","AmdQdVjCZq","zY1GY07n1c","uAWypJRJQB","pvgjSkZANm",
-"suY4xtAOsr","gjUTu9GXkX","9rlg9bZLvS","OUYuFiqv4k","pvgjSW7cTs","SjskQfLNg8","dmoS7BbwgA","Mm8siK4GS8","2Nslm55rfB","RmDcrlj07Q",
-"7Ow5C7Ow5C","J2mQi9eoRc","DcpWB5IhmG","AgJHQi7WMQ","pAhR1n8pJ9","IjTwPKASQ8","e6e4zW3VFH","lm0pDDQimp","ECMvU0Kyfs","x3LDeSbRYy",
-"LDk6fcL0aE","pmeCdUl4a1","KASQ80Kyfs","FjHXRBbwgA","3weIFm4bxU","wiHrZMojnP","Zv7z0oVQp6","uoStwuN6r3","y94nwNOHsz","jS1ajCxVEf",
-"P6bcg7X3uy","FwEJz618Di","LDk6fQssNC","55rfBMezSW","5drc6QChxs","Yh1hFRBhp0","gIYvElsQGo","ZUnqtydG8U","uQIczulk41","Oz8yZW7cTs",
-"faHirCqqaD","K20wKFFDui","s4786t98iW","RzaZAzbIYY","7Ow5CFNYIM","NOHszFnPFB","9XyT9v1Hln","J2mQifLNg8","IjTwPJkzUn","IKxdLuN6r3",
-"lsQGoatef2","kZANmcL0aE","FcWrWuZPqg","7fsYMxXTI4","BFkb8FLsph","EdBKcGWqqX","580YD9GXkX","yofH3FLsph","Vprf2FVMxo","M6qcG7ku1p",
-"dQ586he9IA","2DREsIKxdL","zz4ZUQ6Lix","MojnPuupzk","IKxdLQClRL","LewvMuN6r3","0h1b1W3VFH","jeskSjSjS3","FFDuiNhXdu","prNT6lkMUA",
-"FhtglNAFuw","Q6Lixb29RJ","Yw2oU07n1c","G1RhSRzaZA","Q6LixzQt6Q","1v5hHaez9y","m4bxUHfyNQ","7hyVvQWxoT","aFFsslViBv","RzaZAKr8ys",
-"xReec0ao3l","FnPFBJkzUn","AkKTkqaofN","Waim6KZamH","IRh48QYxC0","X6Pin2TRI7","uTacxkZANm","HfyNQD6rBy","hE1QlcQOnv","ru4UGM6qcG",
-"1LB1LfaHir","45cIHpmeCd","F6PT2pmeCd","CqqaD4dEz6","RxrsmFhtgl","UlU3MOHaBz","RBhp00MR5X","Yw2oUQworu","lH1ktEdBKc","GXdoHPb1pa",
-"e6e4zmz8gx","FxX9q1v5hH","Mkgy8y94nw","fmIK17ku1p","LbRTHlCMxy","aez9yMm8si","GWqqXtlILt","jeskSuQIcz","suY4xbZLvS","2ZHdkgjUTu",
-"Oz8yZ1v5hH","Ul4a1KsjRK","Vprf2FwEJz","QworuiwzGk","nnP8onFqik","l83UdtuDyS","BbwgA9eoRc","m4bxUfcwDa","2TRI7WmadA","2NslmnFqik",
-"VLTy6B3qem","jeskSlsQGo","5ZaEzjSjS3","IKxdLguMb8","Cp3mZFGzgp","Cfgr3Fhtgl","gjUTuFLsph","618DimX2GE","prNT6Kr8ys","DQimp7X3uy",
-"v8yFN2TRI7","l83UdoQ87r","suY4xFGzgp","LewvMMezSW","7fKYUcL0aE","jfREux3LDe","M3zXLfFDrJ","4dEz6Mm8si","pv0i7RpBQm","YOfrYFLsph",
-"MojnPWreyP","VBjhz1v5hH","lj07QSmGzv","Y1mC0QbxXc","he9IAblLA9","hSSvQOz8yZ","CNHmvTwano","RBhp0Kr8ys","580YDDQimp","LDk6flkMUA",
-"kZANmW3VFH","Rxrsmx3LDe","xciqp2ZHdk","jSjS3lH1kt","s7MxkS2Dfu","CdyBVjSjS3","yluBxJ2mQi","uZPqgAOgEe","4dEz67fKYU","tl72WAkKTk",
-"I7p2aK20wK","VIlwPpvgjS","GWqqX7ku1p","kZANm4W0Tl","tl72WgdQsS","JJs5mBGaQY","iB08l0PktI","uLtKs5nmWv","rhl0JK20wK","ReKEWOUYuF",
-"5VZjSyofH3","qUJMd29QAz","cShY24dEz6","QWxoTtjQxs","0MR5Xn1pmO","W7cTsfLNg8","7lUXZiwzGk","3weIFDz1R3","BFkb8DLhzM","e6e4z14FLR",
-"D6rByuZPqg","SmGzvuupzk","uTacxQYxC0","qUJMdTXQ0Z","o8UydWMiS3","Y1mC0uTacx","ECMvURBhp0","Vprf2FNYIM","WPmlxQnJ1S","tuDySoVQp6",
-"5drc6xXTI4","Qworu9GXkX","suY4x8RCUA","lsQGo2hEEU","0MR5X0MR5X","ydG8Utl72W","M6qcGZJTXH","9GXkXaDGtS","TXQ0ZRpBQm","mz8gxBCxeC",
-"d85a9fcJOy","QnJ1SwDajX","bZLvSpmeCd","Ta8f6IRh48","2hEEUv2eC3","zqH0WAOgEe","EdBKcHRxd8","xReec5Drn0","9rlg9v1Hln","ReKEWLDk6f",
-"MGlTFrz7Ut","dhSuHYf2Ec","W3VFHQChxs","KASQ8EoToP","55rfBeuZA5","hSSvQ2ZHdk","3weIFBGaQY","MaJQssqVrf","ulk41DcpWB","1LB1L5Mg9r",
-"pFrrlpmeCd","JXljW5Drn0","BGaQYFGzgp","wDajXni2v1","RpBQmBFkb8","lCMxy7fsYM","FcWrWatef2","LbRTHv2eC3","d85a9AXpwE","Vprf2No0Qb",
-"CNHmv1v5hH","Ss0Zufqypy","M3zXL1v5hH","Chuy3k85Ae","TXQ0ZB3qem","M6qcGYjB9t","ciuWzuQIcz","14FLRI7p2a","kZANmvLsmS","uoStwv2eC3",
-"O3iyQ5IhmG","0h1b1qQxHP","zz4ZUKsjRK","ksJbylViBv","xReecZuDtD","GSQwj9iGoT","1j5L8FNYIM","JXljWni2v1","FGzgpJ2mQi","oGu6x5nmWv",
-"JIqXiEdBKc","pmeCdQClRL","F6PT2yToGW","No0QbEOE1o","0YAGHnlaBy","8FmFHlsQGo","ru4UG9GXkX","WPmlxNo0Qb","Y1mC0yToGW","MmKGJ9GXkX",
-"euZA5n1pmO","KASQ8X6Pin","tjQxsMojnP","SbRYy24ARF","cShY2QWxoT","djsrvDLhzM","4dEz6t98iW","9XyT93otm6","WreyPtuDyS","TXQ0ZZzJHW",
-"n8pJ9FPfSE","C2IrcRsQUq","qQxHPYf2Ec","2NslmpiJSk","v1HlnlkMUA","TwanoQChxs","7Ow5CFhtgl","Ul4a1AgJHQ","B3qem4W0Tl","blLA9WaWsv",
-"Pb1pa0MR5X","UmaEvAgJHQ","TXQ0ZzqH0W","AgJHQHfyNQ","ZhwG18FmFH","DLhzMMK07Y","WaWsvjeskS","wDajXqaofN","3weIFUlU3M","Zv7z0xciqp",
-"JkzUnfLNg8","580YD2ZHdk","nnP8oMmsIo","Cfgr30Kyfs","Q6LixyofH3","piJSkRzaZA","zQt6QVNCPd","Kr8ysJXljW","CxVEfQ6hMC","7X3uyv2eC3",
-"I7p2aOz8yZ","ru4UGgtCA5","2NslmQ6hMC","M3zXLMK07Y","l83Ud3weIF","1j5L8WreyP","Vprf2X6Pin","FhtglFwEJz","NOHszjfREu","hSSvQGrDg7",
-"WPmlxlCMxy","4W0TlRsQUq","UlU3MjS1aj","Q6Lixa00b5","48cHLVIlwP","B3qemVprf2","QClRL7X3uy","lm0pDh1zcH","7ku1pZUnqt","I7p2axXTI4",
-"ZhwG10MR5X","No0QbEdBKc","EOE1ocmXIX","JXljWDG4sT","lj07QAkKTk","yEfy9Chuy3","Waim6uJScX","CdyBVlweGy","0ao3l55rfB","faHirsqVrf",
-"JkzUnAmdQd","guMb8Yh1hF","JkzUnB3qem","uJScXI7p2a","nlaByzbIYY","yEfy9iqv4k","pAhR1RBhp0","Oz8yZh1zcH","2hEEUJkzUn","4dEz6WreyP",
-"29QAzM3zXL","VLTy6mz8gx","7hyVvhUTw7","5VZjSRBhp0","No0Qb5Mg9r","RsQUqMaJQs","h1zcHhSSvQ","jeskS3otm6","5IhmGKZamH","M6qcGsuY4x",
-"faHirSWfou","WmadApiJSk","e6e4zlXFOB","sx5Glt98iW","lweGyBbwgA","Oz8yZuvf7A","oVQp69y4lw","dpe1vdhSuH","uLtKs5IhmG","ZzJHWatef2",
-"nFqikZUnqt","aFFssJKWYR","hSSvQSWfou","POUYSS2Dfu","VerEANcICA","cmXIXBFkb8","7lUXZtjQxs","1j5L80PktI","t59lRv8yFN","8xEKzdjsrv",
-"7lUXZtlILt","guMb8lCMxy","MojnPFcWrW","JRJQBjiVBP","ZhwG1piJSk","qaofNK4GS8","v8yFNhi5X7","fmIK1nlaBy","faHirtAOsr","AgJHQTXQ0Z",
-"KZamHokgRi","fLNg8uAWyp","1v5hHnnP8o","5IhmGBbwgA","mX2GEjS1aj","S2Dfuuupzk","ni2v1JXljW","zFgtB5ZaEz","0Wr5yzY1GY","tvdkD0PktI",
-"RkQkeQnJ1S","e6e4zeuZA5","Yf2EclkMUA","9XyT98U2nU","lViBv0PktI","fLNg8vLsmS","24ARFatef2","lH1ktF6PT2","In3NSjeskS","CqqaD2ZHdk",
-"uTacxJkzUn","8hJdtAgJHQ","618Di7hyVv","WDVWJ1j5L8","dQ586t98iW","KsjRKIRh48","hSSvQpFrrl","FLsphVIlwP","I7p2aix74r","NhXdunnP8o",
-"2TRI7jSjS3","pWiOsQworu","RkQkennP8o","JKWYR8cVD3","CIShGFVMxo","7ku1pQWxoT","7hyVvoGu6x","ciuWzlweGy","fFDrJnlaBy","rhl0JAXpwE",
-"HfyNQRACuj","W3VFHLDk6f","VBjhzCK5W7","Q6hMCBCxeC","zqH0WfFDrJ","QChxs5Mg9r","rhl0Je6e4z","DLhzMfLNg8","Q6LixQnJ1S","BFkb8tjQxs",
-"BpYhVlViBv","oQ87r29QAz","7fKYUFNYIM","F6PT2QClRL","lXFOBX6Pin","d85a9a00b5","tlILtZhwG1","GSQwjjzUqR","ulk41nlaBy","8TxD7dmoS7",
-"lCMxydmoS7","AmdQd2Yz7E","RACujJkzUn","0Wr5y0PktI","FhtglcL0aE","M3zXL7X3uy","okgRiogLgc","zY1GY0Wr5y","hSSvQFhtgl","NhXdu0h1b1",
-"ru4UGMaJQs","fFDrJpv0i7","Rxrsmzz4ZU","dmoS7IjTwP","ZUnqt0PktI","VBjhz2ZHdk","L7cGcqUJMd","Yw2oUBpYhV","CdyBVaez9y","aDGtStvdkD",
-"1j5L8WDVWJ","DcpWBQChxs","pT8wun1pmO","No0QbAOgEe","hUTw7VNCPd","iB08ldpe1v","Mm8sifmIK1","gjUTugIYvE","P6bcgrKDLJ","yvOMInFqik",
-"2Yz7E3otm6","POUYSs93Ml","o8UydO3iyQ","QssNCjeskS","8FmFHCxVEf","5iGN5yToGW","JXljWtaOXK","AOgEeDG4sT","lm0pDFPfSE","mz8gxMGlTF",
-"zqH0WpAhR1","rKDLJtuDyS","suY4xPOUYS","BbwgAStlDJ","0ao3lGrDg7","QChxsKsjRK","hUTw7uN6r3","v2eC3QWxoT","5ZaEzsuY4x","DQimpbZLvS",
-"EOE1oReKEW","vkCHHLewvM","atef2h1zcH","y94nwMmKGJ","RmDcrd85a9","ix74rM6qcG","JIqXiblLA9","n8pJ9cShY2","VjCZqeuZA5","5drc6MojnP",
-"mX2GEJJs5m","MojnPdmoS7","h1zcHIRh48","uLtKsJIqXi","VerEAwiHrZ","v8yFNlj07Q","Mkgy8tl72W","FFDuiDcpWB","ix74rxReec","d85a97fsYM",
-"BbwgA2TRI7","2ZHdkpT8wu","8TxD7s4786","Pb1paFLsph","uLtKsuPX7G","RpBQmUmaEv","WmadAG1RhS","8RCUAyEfy9","3weIF5IhmG","GXdoHfaHir",
-"W3VFHlH1kt","StlDJL7cGc","zY1GYdhSuH","CqqaDy94nw","Vprf2JKWYR","hi5X7vOqCE","euZA5Nxx9V","Y1mC00YAGH","cmXIXaFFss","3weIFt59lR",
-"ZJTXHAOgEe","ru4UGBpYhV","6q6L9k85Ae","hYBCKhUTw7","8U2nUOz8yZ","gIYvEChuy3","2TRI7QWxoT","JKWYRfqypy","pWiOs0PktI","yEfy9IKxdL",
-"WDVWJyEfy9","rKDLJBFkb8","6AFT0EOE1o","AmdQd7fKYU","dhSuH5nmWv","48cHLyvOMI","0MR5XfFDrJ","3weIFRBhp0","okgRitvdkD","lj07QS2Dfu",
-"29QAzogLgc","0Wr5yoQ87r","GSQwjix74r","7Ow5CPb1pa","RpBQmQClRL","zHF1qx3LDe","tuDySDz1R3","G1RhSYf2Ec","hYBCKkB5nP","FNYIMiwzGk",
-"K4GS8brhlQ","3otm6ReKEW","ix74r8FmFH","O3iyQpvgjS","Qworuix74r","618Di5Namm","pvgjSyToGW","ni2v1EoToP","DcpWBs7Mxk","v2eC3ZUnqt",
-"uQIczXflUq","suY4xzbIYY","P6bcgjiVBP","uupzkjfREu","Gv3FqZuDtD","yluBxWmadA","Q6hMCvLsmS","dQ586PYBf4","MmsIojfREu","e6e4z5VZjS",
-"i3pydx3LDe","ThjNniKqhr","0Wr5yksJby","3otm6t98iW","bZLvSlm0pD","2TRI7oGu6x","sx5GlkZANm","ThjNnd85a9","9iGoTW3VFH","yofH3AmdQd",
-"No0QbgjUTu","0BmCy0MR5X","0YAGHlj07Q","lViBv0Kyfs","C2IrcVLTy6","D6rByn1pmO","FFDuiG1RhS","qaofNOz8yZ","iKqhr64s8N","Cfgr30h1b1",
-"qUJMdQssNC","dmoS7MmKGJ","WaWsvFGzgp","FPfSEhYBCK","ydG8UQnJ1S","zY1GY8cVD3","xReecHP433","rKDLJECMvU","o8UydFcWrW","vLsmSguMb8",
-"Vprf2aFFss","AXpwEjzUqR","SWfouni2v1","CK5W7CxVEf","RkQkehSSvQ","sx5GlRzaZA","ZUnqtEOE1o","9y4lwogLgc","mz8gxlj07Q","UmaEv4QMc9",
-"ZuDtDzFgtB","tl72WDG4sT","hYBCKhSSvQ","KASQ8ogLgc","7fsYMIBe8k","4QMc9jiVBP","FcWrWtlILt","0KyfsRBhp0","O3iyQJ2mQi","48cHLQWxoT",
-"POUYS2Yz7E","Mkgy829QAz","5ZaEzCdyBV","0MR5Xs7Mxk","NOHszYh1hF","8U2nUjeskS","Oz8yZlH1kt","a00b5uTacx","48cHLxciqp","Mm8siKZamH",
-"oVQp6zQt6Q","m4bxUzz4ZU","ogLgczQt6Q","gtCA5580YD","5ZaEzjS1aj","jtn0XyluBx","y94nwni2v1","5iGN5Q6hMC","Q6hMCZzJHW","iB08lStlDJ",
-"KASQ8No0Qb","yToGWRACuj","jtn0Xlm0pD","nFqikC2Irc","s93MlHRxd8","k85AefaHir","9eoRcv2eC3","QworuokgRi","Z4I1v580YD","In3NSfFDrJ",
-"FLsphWPmlx","he9IACdyBV","x3LDeogLgc","d85a9KZamH","QnJ1Sn1pmO","Cfgr3580YD","618Dii3pyd","h1zcH0YAGH","t59lRVjCZq","zFgtBd7vjM",
-"uZPqgb29RJ","t98iWNAFuw","5Mg9r4dEz6","U3yw5oGu6x","kZANmRACuj","Ul4a1nFqik","d85a9ydG8U","5nmWvKr8ys","iwzGk580YD","CdyBVNo0Qb",
-"0h1b12Yz7E","5IhmGMmsIo","9GXkXQWxoT","K20wKl83Ud","dhSuHY1mC0","yofH3M3zXL","xciqpK4GS8","pAhR1MmsIo","m4bxU9eoRc","EoToPlXFOB",
-"AIYUuuoStw","WmadASs0Zu","FFDuii3pyd","QssNCECMvU","Oz8yZs4786","lsQGopT8wu","RzaZA9iGoT","s7MxkRACuj","GSQwjd85a9","v1Hlnaez9y",
-"yvOMIU3yw5","pv0i7QChxs","suY4xFxX9q","RkQkeVIlwP","CdyBVxXTI4","ydG8U55rfB","v8yFNHRxd8","Cp3mZWmadA","hSSvQIjTwP","StlDJ4W0Tl",
-"iwzGk29QAz","e6e4zQbxXc","vkCHHQnJ1S","24ARF4QMc9","tjQxsMkgy8","s7MxkQChxs","8xEKz5Mg9r","8TxD7ulk41","FLsph5VZjS","zz4ZU9GXkX",
-"VIlwPWaim6","JKWYRsoy9t","BbwgAMkgy8","blLA9tl72W","Z4I1vazIWp","J2mQiuLtKs","JkzUnv1Hln","5Nammpv0i7","C2IrcbrhlQ","JJs5mcL0aE",
-"he9IAtvdkD","UmaEvhYBCK","5IhmGVprf2","taOXKPYBf4","MojnPYh1hF","xReecK4GS8","brhlQYh1hF","rz7UtuoStw","ru4UGFGzgp","HRxd8FxX9q",
-"7lUXZOUqFM","qUJMdCp3mZ","5nmWvjeskS","16lHcChuy3","uQIczix74r","ksJby7ku1p","RsQUqni2v1","JKWYRB3qem","qaofNhUTw7","QClRL14FLR",
-"IKxdLtaOXK","uoStw5IhmG","aL6AJCp3mZ","5Mg9rFPfSE","TwanoGXdoH","5drc65Drn0","wiHrZd7vjM","nFqikDz1R3","BpYhVJJs5m","BGaQYs93Ml",
-"CK5W7t59lR","xciqps7Mxk","CqqaDb29RJ","Chuy3Pb1pa","RsQUqBCxeC","WMiS3tuDyS","RsQUqlj07Q","9GXkXzbIYY","5iGN5Yh1hF","KZamHaL6AJ",
-"ECMvUaez9y","guMb8gjUTu","Cp3mZaL6AJ","7fsYMiqv4k","HP433CIShG","2Yz7EQworu","s93MlRsQUq","Pb1pa2hEEU","v2eC3C2Irc","BpYhVsoy9t",
-"a00b5pFrrl","ru4UGFxX9q","BpYhV9XyT9","gf8rIiKqhr","7lUXZGSQwj","fcwDaYh1hF","ni2v10MR5X","pmeCdfcwDa","ksJbyTa8f6","5VZjSgf8rI",
-"CNHmvksJby","BpYhVZv7z0","Cp3mZogLgc","Ul4a1MGlTF","O3iyQStlDJ","ix74rtjQxs","jSjS3Pb1pa","lViBva00b5","D6rBy2Nslm","ulk41ZuDtD",
-"vLsmSK20wK","uupzksx5Gl","zmLYDlj07Q","9eoRcNo0Qb","FnPFB7fKYU","Waim6Fhtgl","taOXKlViBv","qaofNEdBKc","SjskQIn3NS","iqv4kBFkb8",
-"s4786wDajX","pAhR1n1pmO","azIWpMmsIo","C2IrcS2Dfu","hUTw7Pb1pa","t98iWRpBQm","Yw2oUzQt6Q","uQIcz2Yz7E","0PktIF6PT2","dhSuH45cIH",
-"9eoRcrhl0J","h1zcHnlaBy","8U2nUWaim6","FLsphOHaBz","QssNCQnJ1S","n8pJ9D6rBy","faHirsx5Gl","5ZaEzMmKGJ","2TRI7HP433","Ul4a1vLsmS",
-"rz7UtzFgtB","prNT6o8Uyd","lweGybrhlQ","Waim6M6qcG","MmsIoM3zXL","AmdQdUlU3M","CK5W70BmCy","Gv3FqyvOMI","uQIczogLgc","RpBQmOHaBz",
-"taOXKn8pJ9","ThjNnCIShG","AOgEeWreyP","FcWrWZzJHW","8FmFHdhSuH","m4bxUmz8gx","S2DfuZuDtD","iKqhrCqqaD","UmaEvC2Irc","3weIFYOfrY",
-"DG4sTpWiOs","Cp3mZjSjS3","MGlTF0Kyfs","jiVBPd85a9","IBe8kRpBQm","dhSuHVjCZq","yvOMIC2Irc","SjskQ5iGN5","4dEz6ix74r","K4GS8qaofN",
-"fmIK1RpBQm","uJScXZv7z0","0BmCyAOgEe","JRJQBni2v1","CxVEfiKqhr","rKDLJMezSW","GWqqXRxrsm","JIqXiM6qcG","Yw2oUuPX7G","gtCA50h1b1",
-"qaofNM3zXL","t98iWSbRYy","LbRTHTwano","nFqikYOfrY","Ss0ZupmeCd","jtn0Xy94nw","NhXduZ4I1v","aDGtSOxWIH","DG4sTFxX9q","jeskSC2Irc",
-"ZUnqtdpe1v","8U2nUYw2oU","6q6L92Yz7E","oGu6xcQOnv","3weIFokgRi","XflUq2DREs","BGaQYrz7Ut","4QMc9gdQsS","9y4lwlm0pD","G1RhSTa8f6",
-"gtCA5EOE1o","HlUbFuPX7G","OUYuFxReec","14FLRQYxC0","oQ87r0PktI","x3LDeCqqaD","pvgjSjtn0X","JkzUn9iGoT","dpe1vlpF6W","X6PinChuy3",
-"Dz1R3Dz1R3","0Kyfst59lR","vkCHHiKqhr","I7p2aJkzUn","yEfy98TxD7","CqqaDyEfy9","Yf2Ec48cHL","mX2GEi3pyd","B3qemdQ586","bZLvS6AFT0",
-"a00b5yluBx","2hEEUWDVWJ","StlDJ6q6L9","VNCPdjtn0X","i7WMQFnPFB","SjskQOz8yZ","okgRiFcWrW","IRh48tvdkD","OUqFM0Wr5y","uAWyplViBv",
-"RACuj7lUXZ","Cfgr3uLtKs","XflUqNxx9V","brhlQAOgEe","NAFuwyToGW","ix74rpT8wu","7fKYUdhSuH","8cVD3uLtKs","faHirOUYuF","ni2v1o8Uyd",
-"Q6LixOUqFM","rKDLJatef2","MGlTFMaJQs","Chuy3oQ87r","ThjNnCqqaD","mX2GEpFrrl","JKWYRIKxdL","8TxD7Yh1hF","AXpwElCMxy","29QAzs4786",
-"xciqpI7p2a","fcwDaI7p2a","uupzkYjB9t","uPX7GGWqqX","8U2nUKsjRK","IRh48JKWYR","5IhmGStlDJ","fcJOy7fsYM","vLsmSyluBx","16lHcNo0Qb",
-"FVMxoECMvU","gf8rIDQimp","RACujb29RJ","lpF6WCqqaD","wDajXVBjhz","O3iyQgjUTu","SbRYyJ2mQi","NAFuwuPX7G","DG4sTpvgjS","uLtKsksJby",
-"9rlg9VjCZq","J2mQiNcICA","yluBxiqv4k","uZPqg2hEEU","9rlg9VBjhz","Pb1paEoToP","VNCPd8FmFH","UmaEvVNCPd","yEfy9hYBCK","4dEz6n1pmO",
-"8U2nU16lHc","IKxdLQbxXc","kB5nPOUqFM","fcJOyWmadA","kZANmb29RJ","Yh1hFPb1pa","hUTw7HfyNQ","StlDJ16lHc","lXFOBU3yw5","RACujnFqik",
-"XflUqWPmlx","FVMxojtn0X","0Wr5yuvf7A","JKWYR8xEKz","VNCPdo8Uyd","cL0aEoGu6x","pFrrlD6rBy","VIlwPG1RhS","dhSuHC2Irc","jeskSMK07Y",
-"AIYUu45cIH","3otm6X6Pin","BGaQY9iGoT","cQOnvvkCHH","4QMc9Chuy3","lCMxysx5Gl","Nxx9V2Yz7E","AIYUuqUJMd","fcwDaVIlwP","45cIHmX2GE",
-"ni2v1Oz8yZ","guMb8ksJby","iqv4kkB5nP","piJSkEoToP","CdyBVK4GS8","QChxsrhl0J","JRJQBS2Dfu","Uvlv47ku1p","Uvlv4WDVWJ","piJSkWaWsv",
-"bgJAzKr8ys","zbIYYuN6r3","POUYSuupzk","RsQUqMojnP","AXpwEMmsIo","SWfouGXdoH","FwEJzyEfy9","8hJdtqUJMd","ciuWzIBe8k","7fsYMBFkb8",
-"blLA9VerEA","nlaByQWxoT","yToGWWaim6","e6e4znnP8o","4dEz6MmsIo","5VZjSBCxeC","hYBCKMmKGJ","ciuWz0Wr5y","uvf7AkB5nP","xReec1LB1L",
-"IKxdLgjUTu","lm0pDI7p2a","WMiS314FLR","uoStwTXQ0Z","JkzUn3otm6","Ta8f6WreyP","EOE1olH1kt","tuDySxciqp","RACujGSQwj","48cHL9XyT9",
-"FhtglQnJ1S","qQxHPFPfSE","x3LDeMkgy8","pT8wu8RCUA","Yh1hFd7vjM","OUqFM0PktI","2hEEURkQke","OUqFM14FLR","AmdQdSWfou","yToGWrz7Ut",
-"RkQkeuvf7A","wDajXWreyP","bZLvSNo0Qb","x3LDelsQGo","Oz8yZY1mC0","WPmlxdmoS7","xciqpQbxXc","lweGyEdBKc","wDajXs7Mxk","s7Mxk2TRI7",
-"vLsmSDz1R3","zqH0WBpYhV","zQt6QJJs5m","pAhR1ulk41","gdQsSBpYhV","Y1mC0blLA9","hUTw7JIqXi","7Ow5CvLsmS","cShY22Yz7E","MmsIoVIlwP",
-"ni2v1a00b5","S77LHcShY2","rKDLJzHF1q","xXTI4WPmlx","brhlQ580YD","qaofNHzZT8","RBhp0RpBQm","5drc6lViBv","tlILtD6rBy","9eoRca00b5",
-"sqVrfECMvU","RzaZAuN6r3","JXljWzHF1q","BbwgA7ku1p","gjUTuCqqaD","hYBCK2hEEU","BbwgAhE1Ql","W3VFHTCgPp","hi5X7lweGy","8FmFHIRh48",
-"Dz1R3hi5X7","k85AejeskS","lkMUAKr8ys","0PktIjtn0X","7X3uyfLNg8","jS1ajv2eC3","i7WMQRxrsm","9iGoTTCgPp","qUJMdbgJAz","7ku1pFPfSE",
-"mz8gx4W0Tl","dhSuHni2v1","NhXdulH1kt","K4GS8tuDyS","FcWrWEOE1o","uAWypsx5Gl","kB5nPk85Ae","h1zcHQClRL","tjQxsMezSW","zqH0WnlaBy",
-"d7vjMdhSuH","45cIHCIShG","uQIcz14FLR","wDajXFLsph","AIYUuSmGzv","7lUXZyofH3","Ta8f6Mm8si","lViBvC2Irc","ydG8UTXQ0Z","mX2GE5Namm",
-"YjB9tEdBKc","Gv3FqyluBx","JJs5mtuDyS","O3iyQkZANm","64s8NQYxC0","BGaQYcShY2","uQIczWMiS3","Mkgy8LDk6f","pAhR1pmeCd","BpYhVlweGy",
-"5VZjSZJTXH","h1zcHLDk6f","FNYIMuLtKs","s7MxkSbRYy","uJScXuoStw","pmeCdRACuj","55rfBgIYvE","WPmlxVLTy6","brhlQQChxs","Mkgy8Yw2oU",
-"F6PT2L7cGc","tuDyS2DREs","Ta8f6nnP8o","JJs5mX6Pin","2NslmjS1aj","qaofN4dEz6","yofH3b29RJ","v2eC3Cp3mZ","m4bxUhE1Ql","atef2K20wK",
-"7hyVvQbxXc","uJScXFjHXR","OUqFMCqqaD","oGu6xnnP8o","8U2nUFhtgl","7ku1pzFgtB","QbxXcVLTy6","2Nslmm4bxU","iwzGkO3iyQ","Ss0Zu0Wr5y",
-"gIYvElpF6W","Cp3mZQssNC","QnJ1SVBjhz","wiHrZzz4ZU","Mkgy8cShY2","FFDuiQ6Lix","Waim6S77LH","5IhmGSbRYy","2Yz7Eix74r","Yw2oUfqypy",
-"qaofNhi5X7","RmDcrpmeCd","3otm6pFrrl","AOgEejtn0X","7hyVv0YAGH","lsQGoni2v1","24ARFLbRTH","8U2nU0Wr5y","nnP8ozHF1q","lj07Q5iGN5",
-"GWqqXGv3Fq","SWfouCNHmv","NhXduqaofN","jeskSzFgtB","Kr8ys8hJdt","0ao3lfcwDa","rKDLJokgRi","n8pJ9W7cTs","yofH3iqv4k","Q6LixRBhp0",
-"hi5X7ZhwG1","zz4ZUhSSvQ","lpF6WOHaBz","lj07Q29QAz","gjUTu0Wr5y","580YDChuy3","aL6AJv2eC3","iwzGkzHF1q","t98iW64s8N","iB08llViBv",
-"HzZT8HzZT8","0ao3l48cHL","Mm8si9GXkX","VLTy67X3uy","PYBf4EoToP","RBhp0WPmlx","XyPZN8U2nU","d7vjMZzJHW","5drc6jSjS3","Ta8f6rhl0J",
-"8xEKzd85a9","pv0i7F6PT2","uAWypJ2mQi","K4GS8uTacx","FjHXRZzJHW","kB5nPjzUqR","y94nwuQIcz","jtn0XlXFOB","rKDLJHfyNQ","VerEAyvOMI",
-"soy9tM3zXL","HfyNQQChxs","M3zXL4W0Tl","LDk6f2DREs","SjskQfFDrJ","0KyfsKsjRK","v1Hln8xEKz","45cIHWaim6","RzaZAfcJOy","ogLgceuZA5",
-"vkCHH07n1c","KASQ8uAWyp","S77LHgtCA5","zmLYDv8yFN","fcwDaeuZA5","VBjhzzbIYY","hUTw7WMiS3","FhtglCK5W7","Vprf29rlg9","tuDySvkCHH",
-"Yw2oUX6Pin","POUYSY1mC0","n1pmONcICA","Cp3mZ8U2nU","48cHLd7vjM","8TxD7Mkgy8","dQ586HRxd8","tvdkDX6Pin","x3LDegtCA5","Mm8siiKqhr",
-"WDVWJThjNn","ReKEWC2Irc","9y4lwv1Hln","ReKEWdpe1v","POUYSIRh48","DQimpUl4a1","guMb8piJSk","GXdoHqUJMd","cL0aEtuDyS","24ARFlsQGo",
-"prNT6QChxs","JIqXi7fKYU","Vprf2ksJby","v2eC3ogLgc","L7cGc24ARF","fmIK1BbwgA","8RCUA1LB1L","YOfrYfmIK1","uvf7A7fsYM","2hEEUe6e4z",
-"Kr8ysv1Hln","MmsIoSjskQ","t98iWVprf2","cL0aEMGlTF","AmdQdQbxXc","Q6LixGv3Fq","fcwDa7hyVv","fcwDahSSvQ","J2mQiCfgr3","0PktI4W0Tl",
-"NhXduTa8f6","MmKGJAOgEe","VLTy6M3zXL","lCMxym4bxU","VNCPdP6bcg","hSSvQgdQsS","0ao3lDQimp","wiHrZ8hJdt","JIqXiqQxHP","Cfgr3GrDg7",
-"580YDBFkb8","ksJbyReKEW","C2Irczz4ZU","9rlg9dpe1v","9iGoTPYBf4","s7Mxkv1Hln","jeskSEOE1o","14FLRpAhR1","hE1QlYjB9t","UmaEvMmKGJ",
-"8FmFH9eoRc","FVMxoguMb8","euZA5t59lR","tl72W24ARF","he9IAjfREu","8xEKzGWqqX","EdBKck85Ae","tAOsrQ6Lix","O3iyQnnP8o","SjskQBbwgA",
-"lViBvMojnP","uvf7AzQt6Q","IRh48hSSvQ","AmdQdBbwgA","Uvlv48FmFH","RBhp0zHF1q","jtn0XzY1GY","BFkb8IBe8k","gtCA5WMiS3","VLTy6he9IA",
-"SjskQxReec","5drc6uPX7G","HlUbFQClRL","NAFuwI7p2a","8xEKztaOXK","zqH0WzFgtB","0ao3l24ARF","BFkb8Q6Lix","BFkb8RBhp0","jtn0XCqqaD",
-"RBhp0RmDcr","uPX7GnnP8o","SmGzv7fsYM","i3pydI7p2a","yluBxhSSvQ","o8UydC2Irc","5ZaEzBFkb8","aFFssWreyP","lXFOBk85Ae","0PktISWfou",
-"NAFuwnFqik","zQt6Qni2v1","CK5W7xReec","GWqqX45cIH","JRJQBYw2oU","Chuy3MmKGJ","fFDrJhUTw7","9y4lwFwEJz","taOXKzz4ZU","DQimpNAFuw",
-"brhlQAXpwE","JIqXi48cHL","6q6L9Z4I1v","RzaZA16lHc","HP433QYxC0","uQIcz4QMc9","QbxXcU3yw5","lpF6W2DREs","OUYuFJXljW","Ss0ZusqVrf",
-"29QAzprNT6","s93MlcShY2","CIShGB3qem","d7vjMUlU3M","NAFuwx3LDe","16lHcfcJOy","CK5W7xXTI4","BpYhVatef2","MK07Y580YD","FNYIMVprf2",
-"QClRLYf2Ec","8TxD7o8Uyd","5Mg9r55rfB","yEfy9xReec","ogLgcQnJ1S","atef2xciqp","cmXIXsoy9t","n8pJ9AIYUu","FwEJztaOXK","64s8N55rfB",
-"VLTy6faHir","7Ow5CHfyNQ","xReecfcwDa","o8UydfmIK1","zbIYY7ku1p","yEfy9mz8gx","dmoS7GWqqX","RpBQm9GXkX","MmsIodpe1v","G1RhSuQIcz",
-"h1zcHKASQ8","IBe8kSmGzv","jtn0XLewvM","CqqaDQYxC0","FVMxoqUJMd","U3yw5HRxd8","W7cTsydG8U","YjB9tThjNn","n1pmOOUYuF","oQ87rNAFuw",
-"L7cGc1LB1L","FwEJz1j5L8","SbRYyzz4ZU","oQ87rGXdoH","d85a9v2eC3","7lUXZh1zcH","FwEJzlCMxy","Yw2oUguMb8","QssNCiqv4k","QssNCOUYuF",
-"2hEEUqUJMd","EoToPtAOsr","55rfB29QAz","uZPqgDG4sT","FFDuiv8yFN","cmXIXIn3NS","0KyfsI7p2a","D6rByStlDJ","ZhwG1RmDcr","7X3uy48cHL",
-"4W0TlRmDcr","uupzkvOqCE","gtCA5GrDg7","FxX9qFwEJz","K20wKoVQp6","7fKYUNxx9V","Cfgr3DG4sT","TwanogIYvE","vOqCEcL0aE","IjTwPgIYvE",
-"AmdQdOxWIH","l83Ud8cVD3","d85a9zFgtB","fmIK1dpe1v","BCxeCTCgPp","0KyfsJ2mQi","uPX7G4dEz6","ni2v1KsjRK","ZUnqtmz8gx","C2IrcBCxeC",
-"6AFT048cHL","tlILtjSjS3","qaofNLewvM","5IhmGokgRi","0BmCyQ6Lix","HRxd8Y1mC0","QWxoTM3zXL","tvdkDru4UG","Zv7z07hyVv","KZamHWPmlx",
-"jS1ajDz1R3","FxX9q8RCUA","4dEz6atef2","cQOnvD6rBy","CxVEfuAWyp","JKWYR5nmWv","tuDySMmsIo","No0Qb07n1c","yEfy9OUqFM","CdyBVtuDyS",
-"uupzkUvlv4","2Nslmru4UG","okgRiaez9y","Uvlv4e6e4z","HzZT8M3zXL","OHaBzaL6AJ","gtCA5uLtKs","DcpWB2Nslm","5ZaEzUl4a1","Y1mC05iGN5",
-"zQt6QS2Dfu","FnPFBSs0Zu","NOHszKASQ8","9eoRcsx5Gl","Ul4a1J2mQi","3otm6vOqCE","yToGWdhSuH","zmLYDlsQGo","dmoS7QWxoT","K4GS8zFgtB",
-"yEfy9taOXK","iKqhrM6qcG","5Mg9rPb1pa","qUJMd4W0Tl","POUYSqUJMd","lm0pD16lHc","jtn0XOxWIH","24ARFQworu","9GXkX5Drn0","s47868hJdt",
-"HRxd8tlILt","UmaEv0BmCy","2ZHdkNxx9V","DQimpjiVBP","2Nslm5nmWv","jfREu0h1b1","No0Qbl83Ud","lweGyokgRi","pv0i7FPfSE","QworuuJScX",
-"S77LH7ku1p","dmoS7ciuWz","ZuDtDQYxC0","vLsmSJIqXi","hE1Qlo8Uyd","BCxeCQbxXc","QChxs2ZHdk","fqypyXflUq","Yh1hFCqqaD","FcWrWJXljW",
-"vOqCEFPfSE","CNHmvW7cTs","FGzgp580YD","TXQ0ZzHF1q","Mm8sim4bxU","EOE1oSbRYy","azIWpK4GS8","VerEAlsQGo","DQimpazIWp","0Wr5yzQt6Q",
-"Waim6uoStw","oVQp6WDVWJ","MmKGJFwEJz","v1HlnHlUbF","QworuFcWrW","P6bcg55rfB","HRxd8O3iyQ","uoStw2Yz7E","X6PinGWqqX","zqH0WqUJMd",
-"0Kyfsb29RJ","OHaBzazIWp","8FmFHFwEJz","gdQsS7lUXZ","X6PinyvOMI","07n1cUl4a1","NAFuwX6Pin","MGlTFtl72W","HfyNQZzJHW","mz8gxyvOMI",
-"yofH36AFT0","taOXKY1mC0","faHirFFDui","ydG8UvOqCE","XflUquLtKs","QChxsAkKTk","suY4xguMb8","hUTw745cIH","0Wr5yMezSW","QYxC0NhXdu",
-"jSjS3d85a9","ZJTXH14FLR","OxWIHdmoS7","2NslmrKDLJ","K4GS8Pb1pa","UlU3Mzz4ZU","BpYhVjiVBP","wDajXF6PT2","tAOsrfLNg8","9y4lwpvgjS",
-"brhlQCNHmv","zY1GYi7WMQ","5ZaEzMezSW","0YAGH2ZHdk","yvOMIk85Ae","QssNCzFgtB","HRxd8JKWYR","IKxdLoGu6x","tvdkD580YD","FFDuiBGaQY",
-"wiHrZs4786","GrDg7WreyP","48cHLRxrsm","xXTI4taOXK","lweGynlaBy","gdQsS3otm6","F6PT2faHir","YjB9tUmaEv","fcJOyVIlwP","J2mQi0YAGH",
-"piJSkDQimp","xciqpgjUTu","YjB9tBpYhV","EoToPAOgEe","9rlg9cQOnv","VBjhz5IhmG","AkKTk2hEEU","SWfoufqypy","x3LDebrhlQ","J2mQi5iGN5",
-"AkKTk9eoRc","0YAGHvLsmS","lpF6WAkKTk","l83UdZJTXH","pFrrl16lHc","BFkb8LbRTH","8TxD7JIqXi","64s8NpT8wu","IRh48ZUnqt","pWiOsCIShG",
-"D6rByTwano","zHF1q7hyVv","SWfouStlDJ","P6bcgqQxHP","wDajXogLgc","VerEAcQOnv","HP433TCgPp","WPmlxOHaBz","7Ow5CStlDJ","No0QbbgJAz",
-"pAhR1Pb1pa","CqqaDjzUqR","rhl0Jpv0i7","cmXIXRxrsm","uvf7As4786","zQt6QzqH0W","WmadAZ4I1v","FLsphrKDLJ","AkKTkgtCA5","CK5W755rfB",
-"LDk6fNhXdu","n1pmOB3qem","IjTwPkZANm","ZzJHW8cVD3","zFgtBFjHXR","jeskSa00b5","L7cGcSbRYy","NcICA3weIF","pT8wuRBhp0","xciqpGWqqX",
-"oGu6xjS1aj","5iGN524ARF","TCgPpVIlwP","DLhzMk85Ae","uN6r3t98iW","XflUqYjB9t","piJSkWreyP","FNYIMNo0Qb","3otm6Zv7z0","W3VFHl83Ud",
-"4QMc9EoToP","qQxHPX6Pin","jiVBPBGaQY","zqH0WI7p2a","UmaEvm4bxU","9rlg9qUJMd","3weIFKr8ys","l83UdcmXIX","i7WMQcL0aE","9iGoTcQOnv",
-"CxVEfTCgPp","cShY2rKDLJ","JXljWBCxeC","VjCZq4dEz6","POUYSJRJQB","OxWIHQ6hMC","pvgjSEoToP","EdBKcZuDtD","LbRTHn1pmO","GSQwjaL6AJ",
-"djsrv8RCUA","ZzJHWZv7z0","k85Ae48cHL","07n1cFnPFB","v1HlnbgJAz","16lHcb29RJ","9y4lwoGu6x","yEfy9jfREu","4dEz6uoStw","7hyVvs93Ml",
-"FLsphbrhlQ","xReect98iW","6q6L9RsQUq","Twanos93Ml","8TxD7IjTwP","MmsIopT8wu","XflUqPYBf4","jeskSnnP8o","wiHrZMezSW","jS1ajfLNg8",
-"6AFT02Nslm","4QMc9l83Ud","kZANmiqv4k","HfyNQ7hyVv","C2IrcO3iyQ","3otm6i3pyd","FNYIMciuWz","mX2GECp3mZ","fLNg8prNT6","ni2v1Nxx9V",
-"TCgPpzmLYD","2TRI7Ta8f6","QClRLjfREu","aL6AJkZANm","zHF1qciuWz","5drc6nFqik","yEfy9HRxd8","s4786i3pyd","LewvMThjNn","ZuDtDv1Hln",
-"QYxC0pWiOs","zHF1qQ6Lix","lkMUAzHF1q","uupzk580YD","uoStwMGlTF","QYxC0JXljW","pWiOs3otm6","1LB1Lrz7Ut","5iGN5BCxeC","0KyfsyEfy9",
-"0KyfsBbwgA","AmdQduJScX","B3qemZhwG1","580YDOHaBz","yluBxDQimp","cQOnvOHaBz","IjTwPlCMxy","KASQ8SWfou","aez9yRmDcr","OUYuFOUYuF",
-"NcICADcpWB","tuDySv1Hln","zHF1qFcWrW","5nmWvQWxoT","atef2qUJMd","JJs5m9GXkX","CIShGWaWsv","C2Ircn1pmO","WreyP618Di","9eoRche9IA",
-"wiHrZvLsmS","2hEEU7lUXZ","suY4xDLhzM","vOqCE7fKYU","qaofNiB08l","jS1ajblLA9","ReKEWKZamH","SmGzvMmsIo","vkCHHRkQke","JIqXiIKxdL",
-"LewvMuJScX","n8pJ9RBhp0","9iGoTAXpwE","POUYSW3VFH","s7Mxksx5Gl","6q6L9bZLvS","64s8Nru4UG","uQIczfaHir","fcJOyZuDtD","atef2Dz1R3",
-"dhSuHwiHrZ","Oz8yZWDVWJ","0YAGHlweGy","Yf2EchYBCK","CxVEfFFDui","k85AeI7p2a","8hJdtHzZT8","Ul4a1NhXdu","atef2AkKTk","aez9yqQxHP",
-"Dz1R3ZUnqt","4dEz6G1RhS","SbRYyiwzGk","1j5L8tlILt","9eoRcFhtgl","2hEEUTa8f6","ulk41HzZT8","zz4ZUX6Pin","ZzJHWsuY4x","5nmWv0MR5X",
-"GXdoHs93Ml","JRJQBhE1Ql","FwEJzFwEJz","AgJHQ29QAz","Gv3FqWaWsv","aL6AJMojnP","fLNg8Cfgr3","JIqXiFPfSE","uoStwrKDLJ","0MR5XIjTwP",
-"0MR5XzHF1q","W3VFHFLsph","s7MxkaDGtS","pFrrlni2v1","o8UydZhwG1","GXdoHLbRTH","fLNg8JkzUn","i3pydCdyBV","5NammcmXIX","FGzgpDcpWB",
-"MaJQsJXljW","uvf7AK4GS8","8TxD7OUqFM","jSjS3ulk41","FnPFBpFrrl","7X3uyMmKGJ","C2IrclweGy","WMiS3kB5nP","soy9tS2Dfu","gf8rIVLTy6",
-"jSjS3i3pyd","blLA9SWfou","rz7UtMojnP","HlUbF45cIH","Dz1R3QWxoT","yvOMIzY1GY","lpF6WAOgEe","mX2GEsoy9t","JJs5mHfyNQ","uTacxlH1kt",
-"GSQwjlH1kt","QbxXcHRxd8","2DREs2Yz7E","uAWypNo0Qb","VerEA0PktI","No0Qb8hJdt","HRxd8Qworu","Y1mC0zmLYD","MmKGJvOqCE","AXpwEECMvU",
-"ni2v1BGaQY","7Ow5CY1mC0","MaJQsVNCPd","1j5L8iB08l","5VZjSRxrsm","RkQketaOXK","hYBCKP6bcg","NcICATa8f6","FxX9qt98iW","lsQGoUlU3M",
-"AOgEePYBf4","2Yz7Elj07Q","7Ow5CJJs5m","9rlg90Kyfs","l83UdhE1Ql","n1pmO8RCUA","0Wr5yIBe8k","Q6hMC0Wr5y","24ARFZJTXH","U3yw5XflUq",
-"QssNCOUqFM","S2DfucQOnv","1j5L807n1c","KsjRK0PktI","lweGy5IhmG","n1pmO9GXkX","M3zXLdhSuH","5ZaEzECMvU","0MR5XtAOsr","S2Dfu8FmFH",
-"K4GS8fqypy","lm0pDsqVrf","OxWIHKZamH","RzaZANcICA","BpYhVlCMxy","Uvlv4xReec","SWfouFhtgl","FcWrWBCxeC","zbIYYpWiOs","lsQGoOxWIH",
-"W3VFHqaofN","CxVEftaOXK","EOE1ooGu6x","BGaQY9y4lw","jfREuEdBKc","uLtKsuupzk","ECMvUTXQ0Z","tl72WYh1hF","OUYuF9XyT9","xReec9y4lw",
-"Yf2EcNcICA","48cHLJKWYR","SbRYys93Ml","iB08lS77LH","FVMxo64s8N","aez9yQworu","580YDOz8yZ","d85a9iqv4k","CIShGQ6Lix","RpBQm8cVD3",
-"hSSvQ5Mg9r","Fhtgllm0pD","fcJOy7hyVv","nFqik7fsYM","CqqaDjfREu","sx5GllXFOB","s7MxkFNYIM","4QMc9KZamH","M3zXLP6bcg","cQOnvfcJOy",
-"ksJbyGXdoH","Q6LixhSSvQ","M6qcGlCMxy","FjHXRAOgEe","7ku1pRzaZA","gtCA5prNT6","pT8wulViBv","nlaByb29RJ","uN6r3mz8gx","24ARF580YD",
-"WMiS33weIF","1LB1LQbxXc","ECMvULbRTH","SWfouVNCPd","DQimpOUqFM","JRJQBpFrrl","hSSvQfcJOy","t59lRwDajX","ECMvU5nmWv","dmoS7cQOnv",
-"3otm6cShY2","vkCHHjiVBP","WaWsvuZPqg","9iGoTguMb8","5Mg9ri7WMQ","BFkb80Kyfs","prNT6ZhwG1","n1pmOAXpwE","qQxHPDz1R3","ZUnqtGrDg7",
-"fLNg8yToGW","ydG8UGSQwj","XflUq7lUXZ","UlU3MdhSuH","MK07YBCxeC","pmeCd14FLR","ix74rAIYUu","RBhp06AFT0","0YAGHP6bcg","KASQ8cmXIX",
-"5VZjSuJScX","0Kyfsrhl0J","2TRI77lUXZ","BpYhVy94nw","RACujAIYUu","uN6r3xXTI4","9y4lw2DREs","iwzGks7Mxk","IBe8kt59lR","EOE1oK4GS8",
-"9eoRcy94nw","lCMxyeuZA5","tvdkDLbRTH","uZPqgJkzUn","MezSWUvlv4","WreyPTXQ0Z","KASQ8KZamH","7lUXZ8xEKz","5IhmGwiHrZ","uLtKs6AFT0",
-"a00b58TxD7","IRh48AIYUu","vLsmS24ARF","jfREudQ586","ThjNnv8yFN","ThjNnwDajX","uZPqg6AFT0","qUJMdzQt6Q","WaWsvlViBv","faHirNhXdu",
-"rhl0JciuWz","TCgPp3otm6","BCxeCC2Irc","hYBCK2DREs","hUTw7djsrv","aL6AJmX2GE","hE1QlzqH0W","tvdkDS2Dfu","0ao3lciuWz","mX2GEZv7z0",
-"m4bxUGv3Fq","EoToPCdyBV","euZA58hJdt","hSSvQX6Pin","uvf7A5nmWv","atef2he9IA","zbIYYqUJMd","TwanodQ586","Dz1R3Vprf2","pAhR19XyT9",
-"bZLvSt59lR","MmsIo8xEKz","qUJMdatef2","yofH3AOgEe","QssNC7X3uy","sqVrfSmGzv","KsjRKatef2","ReKEWW3VFH","IjTwPoVQp6","UmaEvNAFuw",
-"D6rBy0PktI","taOXK5drc6","9y4lwt59lR","hUTw7BGaQY","yEfy90PktI","UlU3MNcICA","7fKYUIjTwP","DG4sTjzUqR","lXFOBL7cGc","NAFuwC2Irc",
-"F6PT25drc6","aL6AJGrDg7","s7Mxksoy9t","Yh1hFuZPqg","0h1b1gIYvE","uJScXWaim6","AOgEeChuy3","soy9ty94nw","iKqhrzY1GY","cShY2UlU3M",
-"suY4xzHF1q","MojnPVjCZq","NcICAMGlTF","fmIK1blLA9","UlU3MEOE1o","bgJAzOUYuF","JIqXiRmDcr","0MR5XFjHXR","LewvMrz7Ut","JKWYRlViBv",
-"t98iW3weIF","tuDyS7fsYM","h1zcHo8Uyd","ni2v1aDGtS","Gv3FqoGu6x","aDGtSRpBQm","blLA9qaofN","9XyT9oGu6x","Pb1pa0PktI","k85AezY1GY",
-"blLA9taOXK","G1RhSsoy9t","yluBxs4786","LbRTHM6qcG","NcICAP6bcg","QssNCCqqaD","VBjhzuoStw","IjTwPWDVWJ","O3iyQXyPZN","tjQxsbgJAz",
-"FPfSEM6qcG","JJs5m2Nslm","Oz8yZv1Hln","580YDv1Hln","uJScX8FmFH","8hJdtyToGW","rz7UtVNCPd","S2Dfu3weIF","IKxdLdjsrv","EdBKc5IhmG",
-"hYBCK07n1c","NcICAx3LDe","IBe8k7hyVv","ydG8UTwano","zY1GYYjB9t","uvf7AnFqik","5Nammd85a9","5ZaEzTXQ0Z","RBhp0ZuDtD","0KyfsiwzGk",
-"DQimp8U2nU","SWfoujSjS3","vkCHH29QAz","QChxsfcwDa","JkzUnFjHXR","S2DfuY1mC0","YOfrYMezSW","ZhwG15IhmG","J2mQiOUYuF","P6bcgCIShG",
-"Q6hMCZJTXH","ix74rjeskS","2ZHdkAkKTk","AOgEed7vjM","TCgPpyluBx","KZamHfFDrJ","iKqhrv8yFN","UlU3MydG8U","Yh1hFhUTw7","VLTy6jzUqR",
-"W7cTsDz1R3","dpe1vjiVBP","Ta8f6RpBQm","Cp3mZ0MR5X","16lHcWmadA","Uvlv4Twano","tl72WCp3mZ","ogLgcbZLvS","suY4x29QAz","0h1b1GWqqX",
-"Mm8siRACuj","W3VFHFwEJz","QssNCni2v1","FPfSE618Di","7hyVvzbIYY","sqVrfdpe1v","tuDySzQt6Q","B3qem6AFT0","14FLRFPfSE","DLhzMJkzUn",
-"okgRiwiHrZ","pWiOsRmDcr","7lUXZzmLYD","IKxdLvkCHH","7hyVvx3LDe","wDajXpWiOs","GXdoH0ao3l","No0QbGXdoH","In3NSKsjRK","t59lRU3yw5",
-"FwEJzzFgtB","pT8wu4QMc9","euZA5jS1aj","cQOnvQbxXc","2NslmCqqaD","dQ586ksJby","8FmFH7ku1p","OUqFMsuY4x","mX2GEThjNn","BpYhVS2Dfu",
-"GXdoH16lHc","GSQwjfaHir","wDajXn1pmO","e6e4zaFFss","guMb8Mkgy8","2TRI7POUYS","yluBxnFqik","vLsmSpAhR1","TXQ0Z0MR5X","CNHmvFPfSE",
-"nnP8o7Ow5C","oVQp6aFFss","vLsmSBGaQY","taOXK2hEEU","CdyBVBbwgA","45cIH6q6L9","IRh48tAOsr","AIYUuSbRYy","nnP8ofcwDa","ni2v1Qworu",
-"DLhzMMaJQs","RsQUqK4GS8","TwanogdQsS","HP433Uvlv4","0BmCyB3qem","8TxD7fmIK1","s93MllXFOB","StlDJM3zXL","Ta8f6hUTw7","CIShGMezSW",
-"0Wr5yW7cTs","lCMxyWPmlx","8cVD3RkQke","0h1b19rlg9","IjTwPv8yFN","sx5GluQIcz","MmsIojzUqR","tAOsrrKDLJ","MK07YuPX7G","xciqpsqVrf",
-"NcICA24ARF","uTacxyToGW","v1HlnZhwG1","OUqFMuN6r3","618DiWreyP","Dz1R35IhmG","CdyBVU3yw5","07n1cs93Ml","a00b5NcICA","fcwDazFgtB",
-"ZzJHWWaim6","5Mg9rWreyP","8TxD7pFrrl","tuDySWPmlx","nnP8onlaBy","CNHmvtuDyS","uPX7GX6Pin","qUJMd8hJdt","Uvlv4tlILt","64s8Nuvf7A",
-"tlILtK4GS8","y94nwtuDyS","DLhzMWreyP","FLsphru4UG","FxX9qvLsmS","SbRYyJkzUn","FjHXRIn3NS","3weIFsuY4x","zbIYYWreyP","5ZaEzTa8f6",
-"bZLvS9eoRc","Q6hMCAmdQd","uvf7AHlUbF","AgJHQNhXdu","ZJTXHdmoS7","9eoRcgdQsS","HRxd8I7p2a","uN6r3CK5W7","rz7Ut8RCUA","1LB1LaL6AJ",
-"bZLvSxXTI4","JRJQBqQxHP","rz7Ut48cHL","CNHmvni2v1","9XyT9AkKTk","OUqFMPYBf4","cmXIXeuZA5","uN6r3Waim6","5Drn007n1c","lXFOBEoToP",
-"lCMxyzmLYD","FhtglP6bcg","qQxHPMkgy8","ZJTXHEoToP","TXQ0ZjzUqR","okgRinFqik","TXQ0ZxXTI4","RxrsmRzaZA","dhSuHIBe8k","rKDLJy94nw",
-"e6e4z8TxD7","fcwDauJScX","ZuDtDFnPFB","xXTI4uoStw","4W0Tlt98iW","MmsIosoy9t","AkKTkMGlTF","cmXIXDcpWB","lkMUAP6bcg","FcWrWni2v1",
-"07n1ciB08l","OUqFMjiVBP","hSSvQokgRi","cmXIXZhwG1","580YDdhSuH","5Drn02hEEU","yluBxydG8U","QWxoTfqypy","blLA9Oz8yZ","OHaBz5Namm",
-"BbwgAjiVBP","Zv7z0zQt6Q","QWxoTlXFOB","Cfgr3tlILt","RpBQmoQ87r","Twano5Namm","uupzkLDk6f","SbRYyJXljW","8cVD3aL6AJ","WMiS3DQimp",
-"mz8gxzz4ZU","lsQGoJJs5m","VNCPdJRJQB","dmoS7W3VFH","mX2GETa8f6","618DiqUJMd","Cp3mZStlDJ","7lUXZyToGW","uTacxcmXIX","s47862TRI7",
-"0BmCyFVMxo","FwEJzRmDcr","RsQUqIn3NS","uJScXZ4I1v","DcpWB0Wr5y","ZzJHWKsjRK","VIlwPKr8ys","WmadACNHmv","QworuAIYUu","i7WMQbgJAz",
-"7fsYMStlDJ","SmGzvWPmlx","W7cTs9iGoT","Y1mC0gjUTu","QnJ1STCgPp","he9IAjiVBP","Waim6lViBv","tAOsr2Yz7E","K20wKCdyBV","Yh1hFx3LDe",
-"0ao3lpT8wu","2hEEUNxx9V","8cVD3TCgPp","FPfSEmX2GE","hUTw70BmCy","O3iyQCqqaD","d85a9uAWyp","aFFssQClRL","v1HlnCK5W7","h1zcHS2Dfu",
-"jfREuChuy3","jiVBP24ARF","VNCPd0MR5X","Zv7z0WmadA","uPX7GZv7z0","QWxoT8RCUA","gIYvEpFrrl","uQIcz5IhmG","y94nwMaJQs","JIqXi2TRI7",
-"U3yw5VerEA","wiHrZZzJHW","FxX9qSs0Zu","K20wK0PktI","FxX9qAkKTk","nlaBybgJAz","qaofNvkCHH","aL6AJStlDJ","RzaZAQ6hMC","3weIFHlUbF",
-"hE1Ql8cVD3","o8Uydaez9y","55rfBl83Ud","cL0aEDG4sT","zmLYDUvlv4","0h1b1zFgtB","t59lR5VZjS","Kr8ysWmadA","48cHL1j5L8","Mm8sirKDLJ",
-"blLA97fKYU","rz7UtSmGzv","tl72WO3iyQ","Mm8si7fsYM","rz7Ut2TRI7","o8UydIn3NS","sx5GlpmeCd","fmIK19eoRc","WDVWJRACuj","ulk41Dz1R3",
-"lweGyaL6AJ","pT8wuksJby","uoStwgjUTu","DcpWBvLsmS","DQimpC2Irc","VLTy6D6rBy","uQIczPYBf4","CqqaDF6PT2","v2eC3lm0pD","t59lR2Nslm",
-"atef2dQ586","xReecYf2Ec","WPmlxZv7z0","hUTw7n1pmO","lH1ktZhwG1","U3yw55Namm","64s8NCxVEf","n1pmO0h1b1","Nxx9Vhe9IA","5Drn07hyVv",
-"9y4lwUmaEv","WMiS3Q6Lix","Q6hMCaez9y","2ZHdk0Wr5y","FcWrW2DREs","24ARFoVQp6","TXQ0ZbZLvS","5VZjSJ2mQi","FjHXRQWxoT","9XyT924ARF",
-"VjCZqFLsph","7Ow5CfLNg8","rz7UtMK07Y","lweGySWfou","zQt6QnFqik","k85Ae9iGoT","atef2zHF1q","9XyT91v5hH","RsQUqaez9y","x3LDejSjS3",
-"9iGoTHP433","FjHXRzY1GY","CxVEfRBhp0","1LB1LMojnP","fFDrJpiJSk","piJSkMaJQs","lpF6WC2Irc","Dz1R3bZLvS","uZPqg2DREs","IRh48cShY2",
-"2Yz7EBpYhV","16lHcNAFuw","ix74ro8Uyd","zFgtBfcJOy","LbRTHAkKTk","Y1mC0i7WMQ","VjCZqKr8ys","FFDui7X3uy","lsQGohYBCK","GrDg75nmWv",
-"Cp3mZLDk6f","kZANmPYBf4","AgJHQk85Ae","pv0i7fqypy","HfyNQ0PktI","8xEKz2DREs","UlU3MhUTw7","brhlQUmaEv","oVQp6QssNC","X6PinQnJ1S",
-"Dz1R3Nxx9V","qQxHP3weIF","s47860Kyfs","bZLvS5nmWv","y94nw6q6L9","FjHXRMojnP","Vprf2WPmlx","oGu6xn1pmO","6q6L95Namm","45cIHdpe1v",
-"a00b5AgJHQ","dmoS79rlg9","RzaZALbRTH","gdQsShSSvQ","Uvlv4MmsIo","HfyNQ2Yz7E","5Mg9rIKxdL","IjTwPJ2mQi","24ARFiqv4k","WaWsvStlDJ",
-"4QMc95drc6","lsQGopmeCd","AgJHQCfgr3","wiHrZ0h1b1","jS1ajIKxdL","tlILttvdkD","cL0aELewvM","gIYvEQYxC0","euZA5SWfou","pFrrlRmDcr",
-"mX2GERxrsm","rz7UtMm8si","uPX7GRpBQm","J2mQi2DREs","7ku1pAIYUu","WDVWJhSSvQ","HRxd8zFgtB","Cp3mZMmsIo","piJSktaOXK","JRJQBZv7z0",
-"16lHc8xEKz","OUqFMgdQsS","dmoS77X3uy","U3yw5zQt6Q","0Kyfs7hyVv","o8UydTwano","RkQke6q6L9","yEfy94QMc9","CxVEfru4UG","Cp3mZtuDyS",
-"sx5Glhe9IA","nlaByGWqqX","Cp3mZsx5Gl","lH1ktnFqik","7ku1pfFDrJ","ZuDtDsqVrf","No0Qblj07Q","8xEKz618Di","BCxeC5ZaEz","DcpWBFnPFB",
-"fcJOyvLsmS","HRxd845cIH","guMb8RACuj","GXdoHCNHmv","xciqpmz8gx","MK07YoQ87r","ZJTXHKASQ8","3otm6NAFuw","FwEJz1LB1L","fLNg8JXljW",
-"TwanoaL6AJ","4QMc9a00b5","bZLvSNxx9V","JRJQBru4UG","n8pJ9Waim6","uLtKsEOE1o","OxWIHlweGy","ciuWzF6PT2","jSjS3s4786","MojnP7fsYM",
-"jfREuuZPqg","hi5X73otm6","uPX7Gy94nw","5ZaEzl83Ud","WaWsvQssNC","FFDui7fsYM","RmDcr7hyVv","FwEJzWaWsv","7Ow5CAIYUu","Cp3mZ9rlg9",
-"No0Qb29QAz","dQ586hSSvQ","hUTw7No0Qb","yvOMI0ao3l","lj07QFPfSE","3otm6FxX9q","7fsYMQChxs","fmIK1pT8wu","5Drn0G1RhS","WDVWJ8RCUA",
-"bgJAzFGzgp","VBjhzjiVBP","pv0i7I7p2a","UlU3MJKWYR","gdQsSwDajX","7hyVvUl4a1","J2mQiqQxHP","fcJOyNcICA","QnJ1SWaim6","0Kyfs7fsYM",
-"lpF6WvOqCE","S77LHcL0aE","OxWIH2TRI7","dpe1vGv3Fq","PYBf4bgJAz","faHirzFgtB","RACujHP433","Ul4a1K20wK","0YAGHL7cGc","Q6hMCCNHmv",
-"Pb1paWreyP","jiVBPzmLYD","8hJdtvOqCE","yofH3zY1GY","a00b5M6qcG","x3LDet98iW","In3NSZ4I1v","sqVrfksJby","Y1mC05nmWv","GWqqXK20wK",
-"16lHctvdkD","7lUXZZzJHW","tAOsrhUTw7","5NammCfgr3","rKDLJ9iGoT","0Wr5yTwano","Dz1R3RsQUq","5iGN5BGaQY","uupzklCMxy","zbIYYZuDtD",
-"hSSvQTCgPp","HP433QssNC","vLsmSP6bcg","RxrsmtlILt","RpBQmhYBCK","xReeczbIYY","IBe8kfaHir","MaJQszY1GY","zbIYYSbRYy","TXQ0Zulk41",
-"WaWsvlCMxy","tl72Wn8pJ9","QYxC0SWfou","piJSk8RCUA","29QAzdpe1v","tuDyS07n1c","hUTw7lViBv","JKWYRjzUqR","prNT6OUqFM","Gv3FqZv7z0",
-"9rlg9Dz1R3","iqv4klCMxy","4dEz6rKDLJ","WDVWJHP433","9y4lw2Nslm","zQt6QzY1GY","DG4sTnnP8o","RsQUqD6rBy","RpBQmXyPZN","zY1GY3otm6",
-"tl72WyvOMI","IKxdLt98iW","2NslmLewvM","gdQsSK20wK","nFqikfqypy","yEfy955rfB","EoToPlH1kt","ulk41MGlTF","uJScX2Nslm","zQt6QdmoS7",
-"xciqpeuZA5","B3qemru4UG","oGu6xCqqaD","24ARFokgRi","5ZaEzO3iyQ","RmDcrlXFOB","pT8wuuZPqg","0BmCyEOE1o","ZuDtDrhl0J","TCgPp7fsYM",
-"rz7Ut07n1c","J2mQitaOXK","yofH3pWiOs","VLTy6RsQUq","qQxHPpFrrl","4dEz67lUXZ","W7cTsWDVWJ","VjCZqdmoS7","5IhmG3otm6","K20wKIKxdL",
-"0KyfsjiVBP","L7cGcUvlv4","7hyVvSmGzv","fcwDagjUTu","m4bxU5drc6","ZuDtDSWfou","No0QbyToGW","d85a9WaWsv","ECMvUgdQsS","b29RJdpe1v",
-"16lHcFhtgl","RACuj2Nslm","vkCHHvLsmS","pvgjSru4UG","2NslmRmDcr","AOgEetlILt","I7p2aRkQke","5VZjSAOgEe","MK07YpFrrl","VerEA2Nslm",
-"lpF6WhE1Ql","lj07QazIWp","5Namm1v5hH","wDajXrKDLJ","5ZaEzLbRTH","m4bxU7fKYU","2TRI7lCMxy","uQIczDQimp","48cHLpmeCd","55rfBhUTw7",
-"5nmWvZ4I1v","tl72WC2Irc","14FLR4W0Tl","OUqFMksJby","IRh48jiVBP","YjB9tru4UG","QbxXctvdkD","IBe8kWmadA","FjHXRVerEA","rhl0JrKDLJ",
-"yofH3tuDyS","DLhzM6AFT0","i3pydogLgc","yofH3zHF1q","5nmWvcShY2","9GXkXSmGzv","tAOsrThjNn","rz7UtFVMxo","HfyNQprNT6","ThjNniqv4k",
-"0KyfsRkQke","RsQUq1v5hH","YjB9thUTw7","GWqqXK4GS8","2hEEUFNYIM","BCxeCiwzGk","tAOsrqQxHP","BCxeCyvOMI","zY1GYnlaBy","MGlTFFnPFB",
-"b29RJ7lUXZ","7lUXZazIWp","UlU3M0BmCy","KsjRKvOqCE","UlU3MUlU3M","2hEEUlj07Q","F6PT2fFDrJ","Ta8f67X3uy","RxrsmFnPFB","POUYSfmIK1",
-"yluBxxReec","AgJHQBFkb8","JkzUnatef2","uN6r3ksJby","2ZHdkx3LDe","gIYvELewvM","i3pydjS1aj","gIYvEMmsIo","VBjhzFxX9q","lViBv29QAz",
-"Yh1hFiwzGk","ciuWzaL6AJ","M3zXLAkKTk","kB5nPRACuj","x3LDehE1Ql","s4786aFFss","0YAGHlViBv","AgJHQi3pyd","XyPZNQYxC0","9iGoTGWqqX",
-"y94nws7Mxk","5drc6WMiS3","QnJ1Sh1zcH","uPX7GFwEJz","5Mg9rxXTI4","GSQwjpWiOs","taOXK3weIF","FVMxoF6PT2","7Ow5CKASQ8","s4786Twano",
-"S2DfuBbwgA","CxVEfdQ586","ZJTXHGXdoH","XyPZN2DREs","EOE1o5Namm","xReechUTw7","s7MxkNAFuw","7X3uy45cIH","TXQ0ZFjHXR","gIYvEuvf7A",
-"S2Dfuulk41","djsrvbrhlQ","d7vjMn8pJ9","8U2nUn8pJ9","Zv7z0zY1GY","0PktIO3iyQ","hi5X7faHir","ni2v1ydG8U","UlU3Mix74r","Ss0ZubgJAz",
-"piJSksx5Gl","zqH0WPOUYS","qQxHP24ARF","uZPqgaFFss","Zv7z0fFDrJ","VjCZqgjUTu","EoToPAkKTk","AXpwEaez9y","WMiS3s7Mxk","BpYhV8TxD7",
-"2DREsoQ87r","7fsYM5Mg9r","lXFOB2ZHdk","BCxeCIjTwP","M3zXL5Mg9r","GXdoHWreyP","s93MlWMiS3","vkCHHyofH3","Yw2oUTa8f6","TXQ0Zuupzk",
-"jfREufqypy","CIShGwDajX","oVQp6i3pyd","Dz1R3mz8gx","L7cGckZANm","Oz8yZyluBx","t98iWDcpWB","azIWpGSQwj","ZzJHWpAhR1","mz8gx6AFT0",
-"QChxsZhwG1","tlILtU3yw5","In3NSmz8gx","wDajXWaim6","MmKGJfcJOy","faHirOz8yZ","Yw2oUVjCZq","JKWYRjfREu","hE1QlMGlTF","5Drn0uupzk",
-"FPfSEY1mC0","5nmWvZhwG1","pT8wuXyPZN","e6e4zPb1pa","zHF1q6AFT0","Vprf2zbIYY","L7cGc29QAz","S2DfupmeCd","IRh48sx5Gl","fcJOyatef2",
-"iqv4kjtn0X","jSjS316lHc","tvdkDRBhp0","Oz8yZlj07Q","0h1b1W7cTs","zY1GY7X3uy","tlILtru4UG","d85a9cL0aE","0PktIpvgjS","NcICA8U2nU",
-"s7MxkVNCPd","U3yw5oVQp6","uQIcz5drc6","M3zXLWPmlx","DLhzMECMvU","RmDcrzz4ZU","nnP8o9XyT9","dQ5863otm6","8FmFHMK07Y","VBjhzguMb8",
-"BGaQYCK5W7","NcICAokgRi","tvdkD5nmWv","ru4UGlH1kt","dmoS78RCUA","07n1cReKEW","qUJMd48cHL","gdQsSulk41","t98iW4W0Tl","he9IA0Wr5y",
-"x3LDejfREu","RmDcr2Nslm","tjQxspvgjS","n1pmOpT8wu","aDGtSjfREu","WMiS3L7cGc","1LB1LFjHXR","JXljWWMiS3","B3qemMK07Y","WmadAbgJAz",
-"cmXIXru4UG","jfREujSjS3","OxWIHv8yFN","TwanoEoToP","IKxdLuQIcz","JXljWS77LH","3otm6sqVrf","S2Dfu8TxD7","Cfgr3FjHXR","2ZHdkSs0Zu",
-"fqypy2TRI7","RsQUqd85a9","1v5hHtAOsr","nFqik5nmWv","mz8gx7fsYM","OHaBzuZPqg","Q6LixXflUq","AOgEeSbRYy","bgJAzFjHXR","J2mQiDG4sT",
-"pFrrl14FLR","taOXKjiVBP","xXTI4gIYvE","CNHmvwiHrZ","QworuWmadA","FjHXRNo0Qb","zqH0WVprf2","uLtKsCp3mZ","CIShGLbRTH","uoStwSWfou",
-"uJScXJJs5m","J2mQiBFkb8","xReec7Ow5C","RsQUqJkzUn","4W0TlWPmlx","uZPqgW3VFH","JkzUnNOHsz","Mkgy8J2mQi","48cHLvkCHH","NcICAhYBCK",
-"ni2v1DcpWB","hE1QlVBjhz","UmaEvbrhlQ","gIYvEx3LDe","3otm6M6qcG","4dEz624ARF","S2Dfun8pJ9","580YDdmoS7","y94nwZzJHW","2ZHdk618Di",
-"dhSuHnnP8o","ZzJHWfcJOy","nFqik0Wr5y","i7WMQMK07Y","7ku1p2hEEU","IjTwPMmsIo","gjUTuDG4sT","sx5GlUl4a1","0h1b1YOfrY","RzaZAulk41",
-"QbxXcv2eC3","v2eC3Cfgr3","sx5GlHRxd8","M6qcGRpBQm","cShY2W7cTs","8RCUAx3LDe","soy9tmz8gx","MGlTF64s8N","AIYUulweGy","FnPFBB3qem",
-"cmXIXuupzk","IjTwPIjTwP","dQ586fcJOy","L7cGcPb1pa","S2DfuaFFss","gIYvEWMiS3","he9IAFGzgp","ZJTXH2DREs","16lHcokgRi","zmLYDYh1hF",
-"Yw2oUnlaBy","gjUTuaez9y","uJScXaFFss","Q6LixYh1hF","YjB9tpiJSk","RsQUqnFqik","prNT6qQxHP","aez9ymX2GE","t59lRt59lR","AmdQdlCMxy",
-"ReKEWYf2Ec","aez9yNo0Qb","uLtKsh1zcH","StlDJaFFss","Kr8ys0h1b1","TwanohUTw7","v8yFNQworu","HRxd8RpBQm","v8yFNK4GS8","RACujZuDtD",
-"euZA5v8yFN","s4786rhl0J","7ku1pRBhp0","QClRLGSQwj","8RCUAuPX7G","8TxD7b29RJ","S77LHv8yFN","k85AetAOsr","RACujAgJHQ","kZANmQYxC0",
-"fcJOyL7cGc","aL6AJS2Dfu","ReKEW580YD","1LB1LeuZA5","ThjNn1j5L8","2hEEU8cVD3","MmsIoDcpWB","i3pydzFgtB","DQimptlILt","jzUqRDQimp",
-"5Mg9r8U2nU","zbIYYs4786","KASQ82DREs","zbIYYs7Mxk","VLTy6ciuWz","YjB9thE1Ql","7ku1pblLA9","QssNCPb1pa","POUYSFnPFB","fcJOyJRJQB",
-"ZJTXHCdyBV","RzaZArKDLJ","pAhR1guMb8","MGlTF580YD","2ZHdkAXpwE","DG4sTSmGzv","EdBKctuDyS","45cIHzQt6Q","1j5L86AFT0","dmoS70YAGH",
-"bgJAzZJTXH","U3yw514FLR","sx5GlVNCPd","BCxeCtlILt","ksJbyuN6r3","jtn0X5Namm","jSjS3Mm8si","x3LDeQ6Lix","VNCPdtuDyS","aez9yPYBf4",
-"P6bcg2TRI7","S77LH9rlg9","dQ586djsrv","rz7UtcQOnv","uPX7GuZPqg","9XyT9hYBCK","wDajXkB5nP","fFDrJyEfy9","8hJdtMezSW","Yw2oUlj07Q",
-"lViBvy94nw","HzZT8zFgtB","n8pJ95drc6","uLtKsfqypy","HzZT8RpBQm","uJScXQworu","gIYvEHRxd8","EdBKcYjB9t","DcpWBiwzGk","2ZHdkhe9IA",
-"HzZT89GXkX","cmXIXzqH0W","2ZHdkCqqaD","ZJTXHfaHir","ECMvUYh1hF","bZLvSprNT6","W3VFHRmDcr","Mkgy80PktI","2NslmQClRL","8cVD3pvgjS",
-"7hyVvuoStw","1v5hHFnPFB","x3LDeWMiS3","aDGtSQssNC","7lUXZFLsph","yofH3sqVrf","aFFssB3qem","UmaEv5ZaEz","v8yFNAkKTk","bgJAzQWxoT",
-"7fKYU0MR5X","tuDySo8Uyd","8hJdtFjHXR","RmDcrl83Ud","MK07YX6Pin","RkQkezbIYY","y94nw5drc6","x3LDe64s8N","QnJ1SMK07Y","zFgtBGSQwj",
-"7fKYU24ARF","iqv4k55rfB","NhXdubgJAz","zY1GYeuZA5","AgJHQiqv4k","B3qemHRxd8","RmDcrW3VFH","tAOsrlweGy","O3iyQoVQp6","Dz1R30BmCy",
-"tvdkDDLhzM","nFqikWaWsv","piJSknlaBy","Cp3mZjeskS","iB08lOUYuF","FPfSEQChxs","Nxx9Vt98iW","DcpWBKr8ys","o8UydFPfSE","pmeCdBFkb8",
-"mz8gxsuY4x","zqH0WVLTy6","KASQ8uLtKs","Ss0Zu4W0Tl","aL6AJxReec","aez9yni2v1","Vprf2gtCA5","0BmCy5IhmG","GrDg7cShY2","F6PT2dpe1v",
-"618DiVLTy6","5iGN5LewvM","UlU3MZuDtD","soy9tFxX9q","64s8NdmoS7","Pb1paIBe8k","tl72W3otm6","YOfrYSbRYy","24ARFaez9y","HzZT8OxWIH",
-"45cIHJJs5m","VLTy6lj07Q","lweGy9GXkX","2hEEUGrDg7","Ul4a15drc6","VBjhztlILt","FVMxoNcICA","azIWp5Drn0","8hJdtcShY2","48cHLfqypy",
-"8xEKz8FmFH","uupzk0Wr5y","o8UydZzJHW","2ZHdkW7cTs","9y4lwdjsrv","pWiOss93Ml","4W0Tll83Ud","cQOnvuvf7A","nFqikThjNn","zqH0WWDVWJ",
-"lweGyGSQwj","G1RhSYOfrY","Zv7z0yofH3","48cHLS2Dfu","GXdoHAmdQd","LDk6f0MR5X","iKqhr8U2nU","MezSWNo0Qb","MGlTFCqqaD","mX2GE0MR5X",
-"AkKTkCqqaD","JkzUnzHF1q","YOfrYru4UG","LbRTHRmDcr","U3yw5Kr8ys","GrDg7cQOnv","DcpWBh1zcH","7hyVvZUnqt","ydG8UNxx9V","v8yFNEdBKc",
-"gtCA5v8yFN","t59lRuN6r3","Yh1hFP6bcg","KsjRKFLsph","O3iyQ8xEKz","KZamH9rlg9","lCMxyHfyNQ","brhlQn8pJ9","SmGzv7lUXZ","OxWIHSjskQ",
-"iqv4kHlUbF","RkQkeMkgy8","8hJdtB3qem","jfREudjsrv","yEfy9M3zXL","ECMvU9y4lw","Cfgr34W0Tl","HfyNQuQIcz","aDGtSCxVEf","pvgjStaOXK",
-"uAWyplm0pD","jS1ajFhtgl","zqH0WUlU3M","kZANmWPmlx","WDVWJv2eC3","brhlQ8U2nU","cShY25iGN5","MmKGJNhXdu","MaJQsjSjS3","9eoRcIjTwP",
-"Nxx9VVNCPd","aFFssMm8si","yofH3VLTy6","iwzGkjeskS","7fKYUTa8f6","JIqXiNAFuw","IKxdLhi5X7","14FLRvOqCE","AOgEeqQxHP","MaJQsgIYvE",
-"yvOMIvkCHH","X6PinJRJQB","SbRYy6q6L9","AOgEeMGlTF","lkMUAD6rBy","HfyNQi3pyd","4QMc9MojnP","BbwgAFLsph","jS1aj0BmCy","aDGtSzqH0W",
-"blLA9gtCA5","LewvMDLhzM","jS1ajwiHrZ","TXQ0Ziqv4k","atef2NOHsz","brhlQVBjhz","XflUqFnPFB","lH1ktMmKGJ","KsjRKzFgtB","faHir5ZaEz",
-"ru4UG5Drn0","gtCA5JJs5m","JXljWprNT6","fcJOyM3zXL","azIWp8U2nU","xXTI4Q6Lix","7lUXZ0ao3l","zz4ZUOHaBz","aL6AJa00b5","Cfgr3uJScX",
-"dmoS7ZJTXH","ZuDtDThjNn","qUJMdv8yFN","ciuWz1v5hH","ulk410MR5X","TwanoVNCPd","In3NS5VZjS","cL0aEuTacx","6AFT0jS1aj","W3VFHFjHXR",
-"atef2dhSuH","yToGWBFkb8","7ku1pjiVBP","jSjS35Drn0","fFDrJciuWz","DLhzMFFDui","uAWyphUTw7","WPmlx55rfB","mz8gxxciqp","pvgjSOUYuF",
-"yvOMIwiHrZ","5Drn0jeskS","QWxoTe6e4z","jiVBPpWiOs","EOE1oGSQwj","pWiOsqUJMd","5NammReKEW","MGlTFVNCPd","VNCPdI7p2a","ECMvUgjUTu",
-"FjHXRWaim6","vLsmSaDGtS","Cp3mZGWqqX","Chuy38RCUA","sx5GlblLA9","jfREuHlUbF","rKDLJCxVEf","WMiS3lsQGo","XflUqGv3Fq","AIYUuKr8ys",
-"tAOsrJIqXi","l83Udsoy9t","D6rBy7fKYU","7fKYU9rlg9","2Yz7EVLTy6","FFDuinlaBy","In3NS3otm6","Ul4a15VZjS","8TxD7t59lR","RkQkelCMxy",
-"StlDJZuDtD","fLNg8lViBv","hE1QlhSSvQ","ECMvU2Yz7E","8xEKzuQIcz","brhlQMK07Y","Cfgr3k85Ae","Uvlv4d85a9","dQ58664s8N","n8pJ9mX2GE",
-"GrDg7gjUTu","G1RhSjeskS","QClRLix74r","ru4UGvLsmS","CIShGXflUq","IBe8kSs0Zu","oQ87r8hJdt","0h1b1hi5X7","s7MxkuAWyp","piJSkCK5W7",
-"xReecQbxXc","uZPqguTacx","Chuy3DQimp","OUYuFTwano","lm0pDmz8gx","NhXduJJs5m","3weIFiqv4k","16lHcMkgy8","GrDg729QAz","Vprf2MojnP",
-"aDGtSFhtgl","Uvlv4lj07Q","8RCUAYjB9t","0Wr5ycmXIX","2NslmRxrsm","dhSuHru4UG","Zv7z0mz8gx","x3LDe1j5L8","jfREuNOHsz","fcwDa4W0Tl",
-"uPX7GMezSW","IjTwPazIWp","LbRTHZ4I1v","fLNg8VNCPd","P6bcgGv3Fq","LDk6fjtn0X","W7cTs16lHc","nFqiksoy9t","lkMUAguMb8","ru4UGMmsIo",
-"v1HlnFFDui","8xEKzRBhp0","P6bcgVerEA","Oz8yZ5ZaEz","CNHmvyEfy9","lj07QjSjS3","QworuSWfou","WmadA9eoRc","pWiOsKASQ8","9rlg9P6bcg",
-"aDGtSbrhlQ","lsQGoCIShG","7fsYMIn3NS","No0Qb2TRI7","fqypyJRJQB","aL6AJNhXdu","HP433MaJQs","azIWpeuZA5","aL6AJEoToP","m4bxUguMb8",
-"cQOnvlCMxy","9rlg94W0Tl","O3iyQsqVrf","NAFuwYh1hF","DG4sT6q6L9","L7cGcBFkb8","VLTy6Mkgy8","X6Pin6AFT0","soy9tfcwDa","VjCZqIBe8k",
-"FcWrWKASQ8","uPX7GOxWIH","oQ87rkB5nP","Qworu8hJdt","VLTy6S2Dfu","QssNCk85Ae","8RCUAZv7z0","RBhp0Dz1R3","nFqikni2v1","WPmlxBFkb8",
-"OUqFM580YD","JXljWb29RJ","Ss0ZutAOsr","fcJOyVBjhz","FVMxov8yFN","lweGyFxX9q","FVMxoZJTXH","e6e4zt59lR","KsjRKix74r","BpYhVoGu6x",
-"yToGW7fKYU","b29RJ5nmWv","WDVWJzY1GY","vLsmSUlU3M","55rfBNo0Qb","sqVrfo8Uyd","i7WMQlH1kt","zHF1qjeskS","618DiFVMxo","QWxoTfmIK1",
-"Dz1R3Uvlv4","RkQkevkCHH","dhSuHVNCPd","h1zcHazIWp","TXQ0ZlsQGo","nlaByIjTwP","DcpWB8FmFH","RxrsmQWxoT","ZhwG1AkKTk","W3VFHS2Dfu",
-"zbIYYix74r","yofH35Drn0","a00b5K4GS8","EdBKcOUqFM","24ARF7fsYM","ZUnqt9rlg9","cmXIXJKWYR","rKDLJDcpWB","faHirFwEJz","QnJ1SRzaZA",
-"9y4lw0PktI","ZJTXHm4bxU","cShY2VLTy6","LDk6fX6Pin","gjUTujS1aj","aFFssNAFuw","nnP8oNOHsz","CIShGMojnP","Chuy3OUqFM","3otm62TRI7",
-"b29RJh1zcH","uAWypFjHXR","JkzUn64s8N","FGzgpkB5nP","v2eC3hi5X7","F6PT2cL0aE","VNCPdHfyNQ","4W0TlYOfrY","CIShGKr8ys","SbRYyguMb8",
-"brhlQDG4sT","yvOMIbgJAz","HzZT8CqqaD","KsjRKQWxoT","oQ87rYw2oU","S77LHm4bxU","lm0pDOUqFM","v2eC35drc6","W3VFHZuDtD","piJSktuDyS",
-"5ZaEzhE1Ql","ThjNn4QMc9","gIYvETXQ0Z","W7cTs5IhmG","CxVEfdmoS7","hSSvQaFFss","uPX7GIRh48","TCgPplweGy","DG4sTwDajX","lsQGoY1mC0",
-"pFrrlm4bxU","Uvlv42TRI7","4W0TlokgRi","Cp3mZMaJQs","zHF1qlkMUA","Chuy3ydG8U","FjHXR0BmCy","0BmCyhi5X7","zqH0WtAOsr","uupzkzbIYY",
-"QChxs9eoRc","zz4ZU8FmFH","rz7UtAgJHQ","hSSvQy94nw","iB08lwDajX","ix74rlkMUA","2Yz7EFhtgl","hE1QlMK07Y","KASQ8vkCHH","ECMvUC2Irc",
-"2DREsW3VFH","tlILtqUJMd","pmeCduLtKs","IjTwP9y4lw","qUJMdEOE1o","7fsYMCNHmv","ogLgcs93Ml","lH1kt7fKYU","FcWrWDz1R3","FNYIMv1Hln",
-"ReKEWuTacx","2TRI7YjB9t","VIlwPI7p2a","bgJAzyToGW","Nxx9VkB5nP","nFqikDQimp","dQ586xXTI4","AIYUu5Namm","brhlQC2Irc","XyPZNpv0i7",
-"fcwDaxciqp","JRJQBW7cTs","i3pydMK07Y","Waim6vkCHH","HRxd8J2mQi","a00b5VIlwP","7Ow5Chi5X7","lkMUA5ZaEz","dhSuHtlILt","0YAGHZuDtD",
-"BGaQYUlU3M","2Yz7E48cHL","7fsYM9GXkX","VjCZql83Ud","OHaBzJIqXi","QbxXcQ6Lix","8xEKzFFDui","5drc6wDajX","uPX7G5iGN5","2ZHdkThjNn",
-"lj07Q8xEKz","JJs5msqVrf","0PktIYh1hF","7fsYMiB08l","5NammQYxC0","JKWYRVNCPd","HzZT8gdQsS","faHir0YAGH","16lHccShY2","5nmWvJJs5m",
-"cQOnvtl72W","W3VFHNo0Qb","zFgtBZ4I1v","OUYuFlCMxy","BCxeCix74r","dhSuHnlaBy","Cfgr3hE1Ql","9eoRcnFqik","RkQkegjUTu","uJScXECMvU",
-"QChxshUTw7","7fsYMi3pyd","SjskQ2ZHdk","ru4UGt59lR","TXQ0ZMmsIo","64s8NIBe8k","mX2GE2hEEU","nlaBy9y4lw","Y1mC0hUTw7","FwEJzQYxC0",
-"LbRTH4QMc9","uQIczNxx9V","F6PT2Vprf2","dmoS7Chuy3","hUTw7i3pyd","HzZT8bgJAz","NhXduQChxs","I7p2ajtn0X","0h1b1iwzGk","ReKEWFhtgl",
-"h1zcH8U2nU","MmsIoThjNn","1j5L8nlaBy","HP433BbwgA","ReKEWWDVWJ","618DiBpYhV","zFgtBpFrrl","POUYSru4UG","NOHszHlUbF","Q6hMC3otm6",
-"Ta8f6Q6hMC","iwzGkYf2Ec","y94nwCNHmv","jzUqRCK5W7","W7cTsuupzk","OxWIH1LB1L","euZA5LewvM","U3yw5s93Ml","nlaByC2Irc","S77LHfmIK1",
-"CK5W7piJSk","2NslmcShY2","JKWYR14FLR","Uvlv4cL0aE","Mkgy8h1zcH","4W0TlaL6AJ","YjB9tfFDrJ","Chuy3QChxs","AmdQdzHF1q","GXdoHMezSW",
-"IjTwPeuZA5","Mm8sih1zcH","8hJdtix74r","lXFOBfmIK1","IBe8kwiHrZ","07n1cqaofN","LbRTHzqH0W","gdQsSuQIcz","Vprf29iGoT","bZLvSHzZT8",
-"GSQwjNOHsz","x3LDeFwEJz","v2eC3Dz1R3","JkzUnZJTXH","WPmlxRACuj","Twanoni2v1","K20wKlj07Q","lsQGoZhwG1","MaJQs0BmCy","KASQ8AXpwE",
-"cQOnvdhSuH","QChxsTCgPp","jS1ajGrDg7","B3qemuPX7G","nnP8obrhlQ","pWiOs2ZHdk","55rfByEfy9","tuDySZJTXH","M3zXLs7Mxk","S77LHCNHmv",
-"lViBvRzaZA","2hEEULbRTH","qQxHPKr8ys","zQt6QlpF6W","0YAGHjSjS3","FcWrWgf8rI","BpYhV5VZjS","EOE1odpe1v","kB5nPeuZA5","PYBf4HRxd8",
-"hi5X7Rxrsm","M3zXL0BmCy","hYBCKMGlTF","jeskSbgJAz","uoStwfLNg8","gtCA5HlUbF","OUqFML7cGc","s4786FjHXR","qQxHPThjNn","bgJAzoVQp6",
-"SbRYy2ZHdk","OUqFMBGaQY","24ARFs7Mxk","i7WMQOz8yZ","LbRTHhSSvQ","ciuWzAIYUu","CK5W716lHc","pmeCdYh1hF","24ARF5Drn0","dQ586S2Dfu",
-"ZzJHW55rfB","cQOnv4W0Tl","45cIHKASQ8","guMb87lUXZ","4QMc9DLhzM","cmXIXfaHir","Mkgy8fcJOy","vOqCECxVEf","gdQsSsuY4x","prNT61j5L8",
-"o8UydjeskS","DQimp0BmCy","LbRTHfcJOy","l83Ud16lHc","t98iWguMb8","n8pJ9suY4x","5NammWaim6","2TRI7C2Irc","tjQxstaOXK","W7cTs0h1b1",
-"FxX9qyofH3","yofH3tjQxs","ulk41FnPFB","ZhwG1FVMxo","dmoS7pvgjS","DQimpQssNC","2ZHdktAOsr","ciuWzMmKGJ","SbRYy7fKYU","WDVWJMezSW",
-"NAFuwAmdQd","hi5X7QbxXc","0YAGHuvf7A","2ZHdkIKxdL","uLtKsRmDcr","Mkgy8Cp3mZ","guMb8Dz1R3","MojnPBbwgA","RkQkeRmDcr","AXpwEYw2oU",
-"lpF6WEdBKc","guMb8QbxXc","zY1GY8TxD7","YOfrYSjskQ","QnJ1STwano","fmIK1lViBv","x3LDeuoStw","ThjNn0PktI","B3qemZzJHW","cShY2JJs5m",
-"JRJQBwiHrZ","Waim6YOfrY","JXljWd7vjM","8hJdt0Kyfs","MojnPNo0Qb","BCxeCogLgc","VBjhzAOgEe","fmIK1pWiOs","DLhzMbrhlQ","bZLvSiqv4k",
-"MGlTFFLsph","lj07QuZPqg","9iGoTIKxdL","ciuWzZUnqt","AgJHQP6bcg","5nmWvQbxXc","24ARFRpBQm","yEfy9Dz1R3","QssNCSbRYy","xciqpEOE1o",
-"uvf7AcL0aE","MGlTFeuZA5","5VZjSW3VFH","hi5X7M3zXL","IRh48tjQxs","lkMUAJkzUn","hSSvQ2DREs","dmoS7OUYuF","HzZT8RkQke","CqqaDblLA9",
-"lweGytjQxs","LDk6fZUnqt","580YDCdyBV","FjHXRbrhlQ","DLhzM2Yz7E","2hEEUgIYvE","RmDcrZzJHW","RkQkeNcICA","FLsphl83Ud","HlUbFjS1aj",
-"Cfgr3rhl0J","s4786580YD","FVMxoTa8f6","hi5X7o8Uyd","07n1c48cHL","mz8gxXyPZN","MmsIolkMUA","jS1aj2Yz7E","MGlTFZuDtD","soy9tpiJSk",
-"aez9yzY1GY","7X3uyKASQ8","QYxC0s93Ml","16lHcZv7z0","nnP8oYh1hF","WmadAru4UG","2DREsdpe1v","iB08lkB5nP","8cVD3t98iW","i3pydsx5Gl",
-"yToGWFPfSE","fcwDa9eoRc","cmXIXdmoS7","pAhR1yvOMI","yofH3FcWrW","kZANmatef2","LewvMv1Hln","5IhmG4W0Tl","vOqCEciuWz","VIlwP9XyT9",
-"SWfouydG8U","G1RhSBFkb8","RBhp0FnPFB","v8yFN3otm6","Fhtglfqypy","zz4ZUYh1hF","9iGoTTwano","mX2GEjiVBP","9XyT9oVQp6","D6rByMezSW",
-"pAhR1iqv4k","hYBCKru4UG","mz8gxlXFOB","9rlg9WMiS3","2DREspiJSk","RkQkefFDrJ","JRJQBe6e4z","0Wr5yWaim6","KsjRKQbxXc","VjCZqlXFOB",
-"6q6L9ECMvU","Ul4a10YAGH","64s8N7ku1p","Z4I1vO3iyQ","uTacxaFFss","piJSkGWqqX","ru4UGhYBCK","mz8gxvOqCE","7fKYUqQxHP","yToGW5Drn0",
-"cL0aEQ6Lix","yofH3ECMvU","DcpWB0BmCy","uupzkNOHsz","iKqhrS77LH","WaWsvRBhp0","SmGzvM6qcG","uLtKsYw2oU","5Drn0J2mQi","uupzkix74r",
-"KsjRK0ao3l","6q6L9n1pmO","v1HlnyToGW","bZLvSMkgy8","MK07YZ4I1v","lm0pD45cIH","FwEJz7X3uy","tuDyS0Wr5y","5NammFFDui","S2Dfu8U2nU",
-"lsQGo7X3uy","oGu6xe6e4z","JKWYRtlILt","4dEz6QbxXc","azIWp8xEKz","ZuDtDG1RhS","JJs5mD6rBy","GWqqXi3pyd","tuDySuoStw","s4786ulk41",
-"0BmCyOUqFM","ReKEWQssNC","v2eC3OHaBz","gjUTuJ2mQi","TCgPp55rfB","Vprf2VLTy6","e6e4zuZPqg","zqH0WuQIcz","zY1GYfcwDa","MGlTFxXTI4",
-"wiHrZn8pJ9","2NslmFLsph","djsrvlViBv","MojnPCqqaD","QYxC0qQxHP","M3zXLOUYuF","jSjS3tl72W","ZUnqtaez9y","Yw2oUogLgc","lm0pDCp3mZ",
-"uupzkLbRTH","W3VFHqQxHP","FwEJzMojnP","2ZHdkNOHsz","jeskSMGlTF","O3iyQ2DREs","TCgPpatef2","YOfrY4W0Tl","8hJdtAIYUu","MK07YW7cTs",
-"yToGWaL6AJ","Ta8f66q6L9","okgRiKsjRK","m4bxUP6bcg","7X3uyEoToP","MojnPjSjS3","jS1ajlm0pD","okgRijfREu","FFDui8U2nU","8xEKzaDGtS",
-"xReecuupzk","n8pJ95Namm","618Dirz7Ut","lH1ktReKEW","MmsIoI7p2a","UlU3Mv2eC3","oQ87rfqypy","tuDySUmaEv","hYBCKM6qcG","Chuy3d85a9",
-"FjHXRrhl0J","cQOnvfLNg8","lH1ktX6Pin","ciuWz4QMc9","CxVEfCxVEf","GSQwjVIlwP","xXTI40Kyfs","hUTw7AOgEe","EOE1oGrDg7","Yw2oUFNYIM",
-"lpF6WQworu","VNCPd5Namm","Zv7z0AgJHQ","hSSvQmX2GE","7fKYUSjskQ","M3zXL4QMc9","FxX9q618Di","FVMxozz4ZU","7fsYM8xEKz","fLNg8BpYhV",
-"RpBQmTXQ0Z","zFgtBKASQ8","48cHLYOfrY","2Yz7ERmDcr","IRh48SjskQ","TCgPpCNHmv","OxWIHWaim6","2hEEUt98iW","v1Hlntl72W","nFqikFLsph",
-"IRh48cQOnv","rKDLJ2ZHdk","QbxXc7ku1p","tlILt9eoRc","Qworu8RCUA","CK5W7ECMvU","uupzkDcpWB","KASQ8NhXdu","MaJQsuJScX","uQIczpvgjS",
-"9iGoTQnJ1S","FNYIMbrhlQ","faHirAXpwE","4QMc97Ow5C","Ss0Zu0ao3l","POUYSW7cTs","wDajX1v5hH","xciqpCNHmv","y94nwTCgPp","0h1b18RCUA",
-"ZhwG1JRJQB","AOgEeCfgr3","TwanoC2Irc","iB08l14FLR","3weIFrz7Ut","QnJ1S8FmFH","bZLvSW7cTs","FFDuiNxx9V","3otm6D6rBy","cQOnvJ2mQi",
-"o8Uydm4bxU","FhtgljeskS","XyPZNFhtgl","OHaBzzbIYY","yvOMIprNT6","55rfBECMvU","NcICAUlU3M","pT8wuUlU3M","pAhR1WPmlx","dpe1vMaJQs",
-"uLtKsFjHXR","QChxsStlDJ","FNYIMMaJQs","7hyVvAmdQd","GWqqXZUnqt","4QMc9MGlTF","NOHsz64s8N","BpYhVyofH3","RsQUqX6Pin","JkzUnkB5nP",
-"l83UdC2Irc","ECMvUFNYIM","faHir8hJdt","pAhR1Cfgr3","9iGoTrKDLJ","Vprf2zz4ZU","ni2v1okgRi","fcJOyIBe8k","NOHsz4dEz6","kB5nPoVQp6",
-"8cVD3Oz8yZ","jfREukB5nP","StlDJjfREu","atef2ZzJHW","v8yFNvLsmS","rKDLJDz1R3","s93MldhSuH","Cfgr34dEz6","5ZaEznFqik","CNHmvyvOMI",
-"8RCUA55rfB","EdBKcYOfrY","7fsYMYw2oU","n1pmORmDcr","hYBCK7lUXZ","yluBxe6e4z","ix74rtvdkD","GSQwjvLsmS","oVQp6DcpWB","ix74rhSSvQ",
-"C2IrcCqqaD","JkzUnPOUYS","ulk414W0Tl","L7cGcguMb8","JKWYR9eoRc","FFDuiJ2mQi","7X3uy5iGN5","VNCPdNhXdu","FhtglpvgjS","Uvlv4atef2",
-"FxX9qtlILt","8U2nUFxX9q","8FmFHXflUq","aL6AJFLsph","FFDuiW7cTs","lweGyMmsIo","b29RJv1Hln","7hyVv0h1b1","djsrv4QMc9","QChxsuvf7A",
-"v2eC32Nslm","9iGoT48cHL","2TRI74QMc9","ksJbyzmLYD","5IhmGWaWsv","L7cGcNcICA","M3zXLjeskS","8hJdtwiHrZ","gf8rIru4UG","OUqFMChuy3",
-"dQ586QChxs","GXdoHIKxdL","rKDLJNAFuw","J2mQiDQimp","hUTw7atef2","pAhR1gtCA5","brhlQxReec","FNYIMe6e4z","OHaBzaFFss","i7WMQbZLvS",
-"s7MxkXflUq","CxVEfAOgEe","soy9t5Drn0","zQt6QNo0Qb","K20wKFGzgp","CqqaD9eoRc","QssNCLbRTH","CNHmvzz4ZU","b29RJ8cVD3","zHF1qYOfrY",
-"e6e4zQChxs","JJs5mRsQUq","mz8gx5Namm","lkMUAwiHrZ","4QMc9WreyP","dhSuHQClRL","5Mg9rcmXIX","n8pJ95iGN5","s93MlMezSW","zFgtBXyPZN",
-"aL6AJjtn0X","64s8N7fKYU","uAWypCIShG","xXTI4Rxrsm","ix74rgIYvE","XyPZNblLA9","QnJ1SMezSW","d7vjMjS1aj","8TxD77lUXZ","zz4ZUDz1R3",
-"2DREszbIYY","K4GS8CK5W7","4dEz6CIShG","prNT65iGN5","tlILt5IhmG","ZUnqtiqv4k","ru4UGCp3mZ","lpF6W9XyT9","0YAGHblLA9","zY1GYHfyNQ",
-"F6PT23weIF","l83UdF6PT2","lkMUAuvf7A","G1RhSECMvU","yluBxSjskQ","Ul4a1cQOnv","v2eC3wDajX","s93MltAOsr","TwanoFnPFB","FFDuiZv7z0",
-"AgJHQhe9IA","9y4lwDcpWB","y94nw1v5hH","NOHsz8cVD3","JKWYRZhwG1","DLhzMVIlwP","RsQUq0ao3l","5IhmGGv3Fq","W3VFHQClRL","pAhR1Oz8yZ",
-"W7cTs618Di","tlILtBGaQY","HRxd89eoRc","oGu6xlCMxy","i3pydaDGtS","HRxd8LbRTH","azIWpW7cTs","C2IrcvOqCE","0ao3lpvgjS","0YAGHBpYhV",
-"O3iyQ618Di","OUqFMFjHXR","LewvMIjTwP","t98iWxciqp","fcwDa0BmCy","IKxdLYOfrY","guMb8NOHsz","RpBQmuPX7G","s7MxkWDVWJ","t59lR0YAGH",
-"FVMxoDLhzM","SWfouWPmlx","tjQxsKr8ys","a00b50MR5X","uAWypZv7z0","AkKTktuDyS","6q6L9CxVEf","n1pmOAIYUu","s4786BFkb8","VLTy64W0Tl",
-"aFFsslXFOB","No0Qbatef2","AOgEes93Ml","fcwDaJkzUn","W3VFHWreyP","POUYSLbRTH","dmoS7In3NS","6AFT0Dz1R3","WreyPs4786","EoToPY1mC0",
-"F6PT2WDVWJ","QWxoTcQOnv","RBhp0DG4sT","1LB1LTwano","n8pJ9qQxHP","0Wr5ynnP8o","PYBf4jiVBP","9rlg9W7cTs","StlDJUvlv4","PYBf4K20wK",
-"lsQGoZJTXH","7fKYUVBjhz","7fsYM0Kyfs","qUJMdJkzUn","In3NSX6Pin","tvdkDRpBQm","hi5X7x3LDe","guMb88cVD3","fFDrJb29RJ","B3qem2TRI7",
-"RmDcrqaofN","Ta8f6ZJTXH","euZA5KZamH","JKWYRFhtgl","gdQsSeuZA5","ulk41lH1kt","FjHXROHaBz","8U2nU8hJdt","Yf2Ec0BmCy","kZANmyvOMI",
-"bZLvSrhl0J","WreyPa00b5","fqypyuLtKs","n8pJ98hJdt","kB5nPhi5X7","gf8rIydG8U","atef2BFkb8","4QMc9m4bxU","gIYvElj07Q","F6PT2gdQsS",
-"jeskSRzaZA","RzaZAnFqik","pT8wuzFgtB","AOgEecmXIX","GrDg7iqv4k","lsQGofmIK1","d7vjMjzUqR","lpF6W6q6L9","GXdoHIjTwP","4W0TlPYBf4",
-"ciuWzzqH0W","IKxdLlj07Q","QWxoTIn3NS","D6rByIKxdL","qQxHPBGaQY","M6qcGs4786","uN6r3Rxrsm","tuDySgjUTu","fLNg8HzZT8","t59lRhi5X7",
-"aL6AJG1RhS","55rfBv2eC3","QssNCO3iyQ","KZamHFVMxo","Zv7z0HP433","6q6L9zqH0W","LbRTHjS1aj","MezSWIn3NS","4W0Tl7fsYM","zz4ZUmz8gx",
-"6q6L9EdBKc","EdBKcjS1aj","FLsphiB08l","JRJQBl83Ud","OHaBzWaWsv","TwanocmXIX","4QMc9lj07Q","L7cGcNAFuw","oGu6xJ2mQi","StlDJzQt6Q",
-"MmKGJHlUbF","WmadAokgRi","VBjhzYjB9t","DcpWBHfyNQ","TCgPplj07Q","618Dirhl0J","FjHXR9rlg9","iKqhrzz4ZU","uoStwBbwgA","XyPZN8FmFH",
-"gjUTux3LDe","dQ5867ku1p","ru4UGuAWyp","pvgjS7ku1p","zqH0WtvdkD","Pb1paHRxd8","x3LDebZLvS","5iGN5WmadA","SjskQW3VFH","jzUqR5nmWv",
-"pvgjSJRJQB","gIYvEhi5X7","ZJTXH48cHL","jeskSQ6Lix","kZANmTa8f6","M3zXL8U2nU","i7WMQqUJMd","hYBCKZhwG1","2Yz7Edjsrv","jeskSWDVWJ",
-"FVMxoRmDcr","14FLR618Di","7lUXZVerEA","7lUXZDz1R3","RsQUqEdBKc","lCMxyNcICA","zHF1qRxrsm","Vprf25IhmG","uPX7G1v5hH","FhtglWMiS3",
-"0YAGHuupzk","M6qcGW7cTs","DQimpYOfrY","rhl0JfcJOy","4QMc99XyT9","pFrrl29QAz","lXFOBqUJMd","cQOnvxXTI4","uN6r3F6PT2","Gv3FqlkMUA",
-"RACujYh1hF","GSQwjy94nw","yluBxStlDJ","MGlTFlH1kt","qaofN9rlg9","iwzGk618Di","Gv3Fqfqypy","ru4UGBCxeC","yToGWprNT6","LDk6flsQGo",
-"9eoRcS77LH","okgRiO3iyQ","CqqaD6AFT0","YjB9t14FLR","d7vjMCdyBV","brhlQprNT6","uAWypMmsIo","2Yz7EpmeCd","IKxdLmz8gx","ECMvUBGaQY",
-"3weIF9rlg9","d85a9jiVBP","7X3uyK20wK","HzZT8618Di","fcJOyOz8yZ","ix74r8cVD3","zbIYYrKDLJ","FjHXRkZANm","SWfouB3qem","KZamHpmeCd",
-"LbRTHNOHsz","uTacxCIShG","uZPqgWDVWJ","LDk6fhUTw7","WPmlxW7cTs","uAWypjeskS","yvOMIi3pyd","zmLYDQClRL","JXljWQWxoT","cQOnvjiVBP",
-"NOHsz6q6L9","FGzgptaOXK","0BmCydQ586","Yw2oUOz8yZ","t59lRBFkb8","RxrsmKASQ8","HP433MGlTF","IKxdLQworu","FNYIMx3LDe","pvgjSOHaBz",
-"NAFuwuTacx","I7p2aPb1pa","AmdQdGXdoH","0h1b15nmWv","TCgPpWMiS3","lj07Q9y4lw","5VZjSMezSW","h1zcH2hEEU","FnPFBwDajX","dpe1vzbIYY",
-"K20wKGWqqX","DLhzMJJs5m","lm0pDC2Irc","fFDrJOxWIH","cShY2CdyBV","atef2QbxXc","DQimpFVMxo","0BmCye6e4z","GSQwjFnPFB","uJScXyToGW",
-"FxX9qO3iyQ","9rlg9FVMxo","oVQp6jtn0X","mX2GEWmadA","gdQsSrhl0J","Q6hMCSs0Zu","oGu6xECMvU","he9IAcmXIX","1LB1Liqv4k","EoToPlsQGo",
-"4QMc9ZJTXH","QssNCqaofN","5IhmGBFkb8","gdQsSdjsrv","POUYSMGlTF","Rxrsmuvf7A","HlUbFd85a9","7fKYUTCgPp","dmoS7SmGzv","mX2GEAgJHQ",
-"okgRis7Mxk","y94nwTwano","OUqFMwDajX","16lHciwzGk","3otm68RCUA","s93MlWaWsv","k85Ae4QMc9","yToGWMojnP","6AFT05VZjS","dpe1vQWxoT",
-"lViBvM3zXL","W7cTsWreyP","taOXKFcWrW","CxVEfhE1Ql","ni2v1IRh48","M3zXLIn3NS","0YAGHmX2GE","5IhmGCNHmv","Q6Lixulk41","vkCHHQWxoT",
-"yvOMIJkzUn","5drc6JRJQB","a00b5tAOsr","FNYIMJkzUn","nnP8o16lHc","WDVWJIRh48","5VZjSni2v1","4dEz6lkMUA","3weIFksJby","vkCHHpvgjS",
-"guMb8taOXK","FcWrWOxWIH","cQOnv6AFT0","YOfrYyToGW","9XyT9Chuy3","LewvMo8Uyd","M3zXL8xEKz","CK5W7IjTwP","ni2v1QClRL","Cp3mZ2ZHdk",
-"Uvlv45nmWv","No0QbvkCHH","FFDuipWiOs","FxX9q29QAz","OxWIHcQOnv","m4bxUlweGy","aL6AJMkgy8","iwzGkGSQwj","W3VFHOUYuF","AmdQdMGlTF",
-"7X3uyDz1R3","5iGN5FPfSE","0BmCyFcWrW","dpe1voVQp6","SWfouHlUbF","QssNCEdBKc","7ku1prKDLJ","yToGWoGu6x","ZuDtDJJs5m","Z4I1vCfgr3",
-"n8pJ9aez9y","UmaEv07n1c","aDGtScL0aE","CIShGWMiS3","7ku1pd7vjM","FwEJzoVQp6","ZzJHWTXQ0Z","GrDg7sqVrf","9iGoTGSQwj","yvOMIpmeCd",
-"d7vjMNo0Qb","48cHL0Kyfs","HlUbFMaJQs","AkKTkVLTy6","tjQxszz4ZU","xciqptAOsr","CNHmvJ2mQi","FPfSEhe9IA","azIWpCqqaD","QnJ1SS77LH",
-"cQOnvRxrsm","Kr8ysTXQ0Z","5Mg9r8xEKz","45cIHru4UG","Vprf22TRI7","4QMc9cShY2","fcJOyfcwDa","EOE1olsQGo","8FmFHMkgy8","CK5W71LB1L",
-"mX2GE0BmCy","fcwDaiB08l","Yf2Ec0MR5X","Uvlv4hi5X7","FPfSEQbxXc","YOfrYFFDui","0Wr5yU3yw5","uN6r3YOfrY","fcwDa0Wr5y","FLsphuZPqg",
-"POUYSFVMxo","hi5X7J2mQi","S2DfuhSSvQ","GXdoHbZLvS","5IhmGOHaBz","yluBxRACuj","jS1aj0YAGH","aDGtSMkgy8","uZPqgK4GS8","SWfou5VZjS",
-"h1zcH7Ow5C","aez9ylpF6W","24ARFyvOMI","zY1GYhe9IA","FPfSEprNT6","FjHXRQworu","NOHszdQ586","Cfgr3JIqXi","s4786Yf2Ec","NOHszXyPZN",
-"zbIYYhUTw7","LbRTHU3yw5","iwzGkciuWz","hYBCK5ZaEz","07n1cFjHXR","4W0Tl0PktI","4W0TlRxrsm","StlDJrz7Ut","KASQ8k85Ae","0ao3lBpYhV",
-"vkCHHFVMxo","pWiOsRBhp0","d7vjMv2eC3","DLhzMyofH3","MojnPRpBQm","jiVBPTa8f6","5IhmGv2eC3","5Drn00Wr5y","StlDJxReec","iqv4kiB08l",
-"jeskSHzZT8","fLNg8VerEA","VBjhzvkCHH","zz4ZUpFrrl","suY4x48cHL","jfREus7Mxk","lkMUAJJs5m","07n1cMK07Y","cmXIX9iGoT","l83UdlXFOB",
-"dhSuHi7WMQ","7hyVv9GXkX","lkMUAOz8yZ","HRxd8jiVBP","Mm8siHzZT8","7X3uyEdBKc","hYBCKEoToP","Waim6pFrrl","No0QbThjNn","LDk6f24ARF",
-"9GXkXqUJMd","Waim6zQt6Q","QClRLVNCPd","1v5hHK4GS8","5VZjStvdkD","HRxd87X3uy","hi5X72hEEU","suY4xVprf2","AIYUuWMiS3","fmIK1QWxoT",
-"b29RJQWxoT","uPX7Gsoy9t","VerEAt98iW","WaWsvkB5nP","8TxD7aDGtS","CIShGOHaBz","YOfrYRmDcr","v2eC31j5L8","MmKGJnFqik","4dEz6IBe8k",
-"jeskSWPmlx","vLsmSOUqFM","Ta8f6K20wK","9eoRczY1GY","NcICAlViBv","lViBv16lHc","fcwDaulk41","Cfgr3BbwgA","5VZjSDQimp","K20wKdmoS7",
-"tlILtIKxdL","AmdQdS2Dfu","CIShGx3LDe","VerEAwDajX","No0Qbdjsrv","piJSk7fKYU","7X3uyyofH3","iB08ldhSuH","1LB1LO3iyQ","vkCHHG1RhS",
-"WPmlxoVQp6","5Mg9r0BmCy","IjTwPEOE1o","2TRI7b29RJ","yEfy9Uvlv4","y94nwmX2GE","fqypy55rfB","ciuWzAmdQd","HRxd8MK07Y","fmIK1FPfSE",
-"2NslmpWiOs","jiVBPRsQUq","aez9yVIlwP","uTacxFPfSE","IjTwPhi5X7","Waim6gf8rI","v2eC3tvdkD","CIShGVprf2","2Nslmv8yFN","vkCHHxciqp",
-"Uvlv4okgRi","aez9yX6Pin","JJs5m2Yz7E","uAWypYf2Ec","s7Mxk0ao3l","5Mg9rvkCHH","ZUnqtcQOnv","RsQUq9XyT9","zz4ZUEdBKc","580YDRkQke",
-"Yh1hFuupzk","gjUTuOxWIH","No0QbFcWrW","JKWYRZv7z0","POUYSYOfrY","TwanojzUqR","FLsphEOE1o","kZANmuQIcz","5drc60YAGH","AmdQdl83Ud",
-"TCgPp2Yz7E","hE1QlzQt6Q","lsQGoKsjRK","hi5X7OxWIH","MezSWpT8wu","aDGtSn1pmO","tlILtuAWyp","EOE1oQ6Lix","rz7UtYjB9t","8xEKztl72W",
-"s93MlkB5nP","zY1GYFPfSE","SWfougf8rI","LewvMLDk6f","Nxx9VTa8f6","W3VFHG1RhS","rhl0JHzZT8","lViBvGWqqX","IBe8kK20wK","8RCUAkZANm",
-"fcJOyZhwG1","s7Mxk9eoRc","hUTw7L7cGc","GSQwjPOUYS","O3iyQcL0aE","IjTwP5Mg9r","t59lR24ARF","uvf7AdQ586","zY1GYKsjRK","AIYUu7fsYM",
-"1j5L8jfREu","2Yz7EpWiOs","FPfSETwano","618DiCNHmv","DQimpSjskQ","TXQ0ZhSSvQ","OUYuF3otm6","AOgEeK20wK","LewvMbZLvS","lj07QjeskS",
-"ix74rYf2Ec","s4786FPfSE","I7p2apAhR1","Yf2EcLDk6f","6q6L9ciuWz","KZamHSWfou","Z4I1vQClRL","9rlg9Mkgy8","WaWsvVjCZq","RkQkeuQIcz",
-"lpF6W5Namm","RsQUqJRJQB","QClRLIBe8k","sx5GlWaWsv","iB08ldmoS7","9iGoTWmadA","ReKEWuJScX","i3pydUmaEv","5iGN5XflUq","1j5L8brhlQ",
-"LewvMX6Pin","uupzkjS1aj","2TRI72DREs","vkCHHiwzGk","tjQxsbZLvS","FGzgpRBhp0","tAOsrRzaZA","oVQp6okgRi","hSSvQ07n1c","cL0aEtaOXK",
-"5IhmGMK07Y","jfREudmoS7","In3NS8cVD3","ZuDtDcQOnv","lsQGodpe1v","6AFT0MaJQs","UlU3M0YAGH","Q6hMCl83Ud","lkMUAU3yw5","4W0TloGu6x",
-"Cfgr35VZjS","5Mg9rpmeCd","1LB1LguMb8","IBe8kDG4sT","pFrrlksJby","ZzJHW0h1b1","blLA9suY4x","CK5W7RACuj","gIYvEpv0i7","e6e4zLewvM",
-"suY4xAkKTk","FVMxowDajX","C2IrcJIqXi","TCgPpXyPZN","AXpwES2Dfu","i7WMQFPfSE","rz7Utb29RJ","HP433jzUqR","dpe1vulk41","0ao3lVNCPd",
-"QworuMmsIo","lXFOB7fsYM","fcJOyJ2mQi","gf8rIuoStw","vLsmSuTacx","Ta8f6OUYuF","TCgPp5ZaEz","jzUqRmX2GE","Q6hMCJRJQB","xciqpAXpwE",
-"ni2v1618Di","l83UdRACuj","gdQsSRsQUq","pFrrlLewvM","9eoRcThjNn","55rfBIKxdL","FPfSEyEfy9","aez9ys93Ml","DG4sTiwzGk","Qworudpe1v",
-"ru4UGIn3NS","yEfy97hyVv","M6qcGt59lR","MGlTFWMiS3","Yw2oUazIWp","K4GS8Q6hMC","IRh480h1b1","lm0pDWreyP","IjTwPZv7z0","07n1cxXTI4",
-"e6e4zdhSuH","2TRI78RCUA","guMb80YAGH","atef25Namm","uoStwni2v1","tuDySCNHmv","YjB9ta00b5","QChxsSmGzv","TCgPpblLA9","RpBQmNxx9V",
-"ix74rRsQUq","faHiruZPqg","euZA55Drn0","uQIczdhSuH","5Mg9rZUnqt","lH1ktTwano","ReKEWfcJOy","jeskSW7cTs","Mkgy8lkMUA","CxVEfJ2mQi",
-"GXdoH5Drn0","zmLYDzY1GY","W7cTsjzUqR","W7cTsrhl0J","bZLvS64s8N","hi5X7jeskS","B3qeme6e4z","UmaEvDG4sT","uQIczpT8wu","aFFssdhSuH",
-"FPfSEaFFss","5iGN5ReKEW","dmoS7Oz8yZ","yEfy90h1b1","DG4sT7Ow5C","JRJQBKr8ys","14FLRgdQsS","In3NSPOUYS","fcJOyni2v1","gf8rISbRYy",
-"fcJOyo8Uyd","CNHmvlsQGo","gIYvEjtn0X","hYBCKRmDcr","lkMUAIn3NS","wDajXjiVBP","tAOsruLtKs","POUYSrz7Ut","FNYIMVNCPd","U3yw5RBhp0",
-"uTacxpiJSk","jiVBPbrhlQ","GWqqXRACuj","fmIK1s93Ml","xReecFjHXR","yvOMISs0Zu","yEfy916lHc","lm0pD24ARF","gf8rItvdkD","ix74rQnJ1S",
-"zY1GYuAWyp","hi5X7Qworu","7fsYMt59lR","OUYuFcmXIX","SjskQNAFuw","e6e4zMK07Y","wDajXDcpWB","fqypyBGaQY","qUJMdEoToP","VerEA8RCUA",
-"S2DfuuAWyp","I7p2aF6PT2","CxVEf8TxD7","SmGzv45cIH","tAOsr0ao3l","Dz1R3RkQke","xReecZUnqt","Yw2oU0Wr5y","jeskS2ZHdk","29QAzGSQwj",
-"lm0pDSbRYy","29QAzyofH3","2NslmMaJQs","1LB1LUmaEv","Ul4a1soy9t","UmaEvpvgjS","cShY2uLtKs","C2Ircd7vjM","yvOMIgf8rI","0BmCyC2Irc",
-"uPX7GfcJOy","2Yz7ElsQGo","gdQsSyofH3","LewvMguMb8","EoToPVprf2","e6e4zlViBv","QssNCQChxs","I7p2aUmaEv","POUYSNo0Qb","FjHXRjzUqR",
-"HRxd8MezSW","mz8gxRzaZA","jS1ajs4786","Ul4a1AIYUu","vkCHHqaofN","1v5hHFjHXR","HRxd82Yz7E","LbRTH7fKYU","S2DfuYf2Ec","0YAGHFGzgp",
-"zFgtBFLsph","hE1QlY1mC0","zbIYYF6PT2","GrDg7SmGzv","tuDyShUTw7","jtn0XO3iyQ","uLtKsVBjhz","8FmFHFhtgl","QWxoTAOgEe","ni2v1ogLgc",
-"oQ87r5VZjS","suY4x7fsYM","i7WMQpAhR1","yToGWHfyNQ","CIShGKZamH","0h1b1jS1aj","7fsYMfqypy","Rxrsm0ao3l","uTacxjeskS","SmGzvpT8wu",
-"8RCUAtvdkD","a00b5okgRi","5nmWvECMvU","atef2ni2v1","euZA5pv0i7","M3zXLFVMxo","MmKGJB3qem","lm0pDoGu6x","atef2JRJQB","cShY2WDVWJ",
-"0KyfstjQxs","gf8rIWDVWJ","gIYvEzQt6Q","bgJAzsoy9t","Yw2oU8U2nU","55rfB0Wr5y","hE1QlksJby","5NammCK5W7","UlU3MkB5nP","OxWIHG1RhS",
-"RkQkejS1aj","WaWsvjiVBP","4W0TlNo0Qb","IBe8kNxx9V","JXljWCNHmv","ru4UGlweGy","ogLgcMm8si","DcpWBMojnP","nlaBy4QMc9","MaJQsFPfSE",
-"hE1Qltl72W","CxVEfAkKTk","o8Uyd2TRI7","prNT6P6bcg","RBhp0Ta8f6","7X3uyJRJQB","XflUqSbRYy","xXTI4LewvM","NhXduQ6hMC","lweGyOUYuF",
-"lm0pD0BmCy","0BmCyKr8ys","5Mg9rWmadA","mz8gx8hJdt","0BmCy0YAGH","9GXkX14FLR","VerEA7hyVv","v1HlnAXpwE","lm0pDTCgPp","9GXkXS77LH",
-"MK07Y5ZaEz","VerEAkB5nP","Ss0Zu5Drn0","lsQGofFDrJ","fcJOyuvf7A","6AFT0cShY2","QWxoTRsQUq","FjHXR9GXkX","prNT6AgJHQ","5Mg9rHP433",
-"tvdkDhe9IA","s4786MK07Y","dhSuHiKqhr","iqv4kMkgy8","RkQke0ao3l","55rfBWMiS3","lweGy16lHc","VBjhzfmIK1","Mkgy8bgJAz","bgJAze6e4z",
-"I7p2aKr8ys","n1pmORACuj","FhtglUlU3M","hi5X7euZA5","GrDg7UmaEv","gf8rI2Nslm","uupzks4786","7ku1p0Wr5y","FPfSEydG8U","aFFssCp3mZ",
-"jfREuQ6hMC","uQIcziKqhr","3weIFazIWp","aDGtSW7cTs","VBjhz9GXkX","FPfSEhi5X7","suY4xyvOMI","D6rByfqypy","VLTy6s4786","CK5W7cQOnv",
-"mX2GEi7WMQ","0Kyfs29QAz","618DinlaBy","ZJTXHSmGzv","CNHmvcShY2","RBhp0hUTw7","MK07Yt98iW","RBhp0MezSW","Mkgy8FxX9q","IRh48i7WMQ",
-"0BmCy5ZaEz","xXTI4fmIK1","P6bcghE1Ql","Mkgy8zmLYD","GXdoHQbxXc","7fsYMjzUqR","LewvM29QAz","Ss0Zugf8rI","s7Mxki3pyd","jS1ajEoToP",
-"s93MlgtCA5","i3pydSjskQ","Ul4a1ksJby","RzaZAwiHrZ","m4bxUtaOXK","t59lRb29RJ","x3LDeJkzUn","0PktI7hyVv","JkzUnJKWYR","gdQsSxciqp",
-"VNCPdfFDrJ","he9IAEdBKc","tl72W580YD","okgRikZANm","ECMvUTCgPp","brhlQ16lHc","2TRI7GSQwj","BGaQYJXljW","JJs5mBCxeC","vLsmSuZPqg",
-"uJScXYw2oU","5ZaEz8xEKz","fFDrJqUJMd","bZLvS4dEz6","h1zcHWDVWJ","OUYuFrz7Ut","0KyfsFLsph","XflUqQbxXc","5Mg9rJXljW","VNCPdDLhzM",
-"5VZjSKZamH","ru4UGHP433","gIYvEuN6r3","GWqqXpWiOs","CNHmvuQIcz","tlILttl72W","F6PT2RpBQm","yofH39XyT9","sqVrfVBjhz","Nxx9VvLsmS",
-"CK5W7In3NS","pFrrlYjB9t","dhSuH7Ow5C","QChxsUl4a1","azIWpGXdoH","uN6r3P6bcg","uPX7GWmadA","S2Dfuzz4ZU","rz7Ut2Nslm","4W0TlCfgr3",
-"n1pmO0PktI","YjB9tJKWYR","QYxC05iGN5","8cVD3AgJHQ","zY1GYs7Mxk","8RCUAi3pyd","hi5X7Ss0Zu","9GXkXWreyP","AmdQdD6rBy","oGu6x48cHL",
-"JKWYRgtCA5","7Ow5CNhXdu","CIShGQChxs","G1RhSjSjS3","JJs5m4QMc9","hSSvQjeskS","0ao3lRpBQm","CNHmvC2Irc","ZJTXHzFgtB","fmIK1StlDJ",
-"lweGymz8gx","FPfSEKsjRK","JRJQBQYxC0","Pb1paQClRL","wiHrZVprf2","CxVEfa00b5","iB08l8FmFH","HfyNQ5ZaEz","o8UydlkMUA","rz7UtyofH3",
-"5nmWvQssNC","VLTy6Ss0Zu","prNT6xReec","Yw2oUoVQp6","4QMc9uLtKs","v2eC345cIH","CNHmvzY1GY","VLTy6zqH0W","MojnPmX2GE","jSjS34W0Tl",
-"4W0Tl2Nslm","lweGy8xEKz","RmDcrdQ586","UlU3M5iGN5","Ss0Zu24ARF","7Ow5CZJTXH","Ss0ZuIn3NS","6q6L9cShY2","MezSWyluBx","v2eC3EOE1o",
-"0BmCyBbwgA","5iGN57ku1p","CdyBV9rlg9","3weIFtuDyS","hSSvQ2hEEU","CxVEfpv0i7","MGlTFm4bxU","8xEKzCxVEf","45cIHI7p2a","QClRLlH1kt",
-"MGlTFzz4ZU","MGlTFMojnP","8cVD3aFFss","NhXducQOnv","7ku1pxXTI4","hYBCKFwEJz","FNYIMaL6AJ","JKWYRgdQsS","BCxeCyluBx","NcICApT8wu",
-"CIShGuLtKs","yvOMIpiJSk","ThjNnuPX7G","0BmCy618Di","gjUTuK4GS8","fcJOyEOE1o","No0Qb7Ow5C","yofH3y94nw","nFqik9GXkX","v1HlnY1mC0",
-"8xEKzokgRi","0BmCysoy9t","s7MxkZv7z0","uAWypuAWyp","iKqhrlweGy","CNHmvSWfou","ReKEWMkgy8","Mm8si8RCUA","Mkgy864s8N","lsQGonnP8o",
-"euZA5jzUqR","LbRTHNhXdu","XflUqRpBQm","5Drn0cQOnv","M3zXLJXljW","MmKGJUvlv4","WreyP7fKYU","FnPFBRsQUq","Dz1R36AFT0","D6rBy7X3uy",
-"5Nammt98iW","HP433J2mQi","618DiiwzGk","wDajXguMb8","pT8wugtCA5","cL0aELbRTH","lsQGoDz1R3","O3iyQNhXdu","oQ87rokgRi","v2eC3lXFOB",
-"0Wr5yNhXdu","NAFuw5nmWv","pAhR1aFFss","XyPZNokgRi","UlU3MC2Irc","soy9t1v5hH","5drc6YjB9t","BpYhVfqypy","QbxXciB08l","VBjhzpT8wu",
-"580YDgjUTu","qUJMdWreyP","5Mg9rMezSW","Cfgr3he9IA","FGzgp0Wr5y","NOHszUvlv4","BGaQYoQ87r","Mkgy8HP433","gIYvE8xEKz","W7cTsuZPqg",
-"VLTy6RACuj","Zv7z0hE1Ql","KZamH9iGoT","RkQke48cHL","64s8NlweGy","LbRTH0MR5X","MaJQsZ4I1v","mX2GE2TRI7","cmXIXrz7Ut","16lHc8RCUA",
-"taOXKi7WMQ","pvgjSiqv4k","Cp3mZpWiOs","QbxXcS2Dfu","wDajXFGzgp","Fhtgl8RCUA","Nxx9V5IhmG","lH1ktYf2Ec","1v5hHLDk6f","VIlwPRpBQm",
-"GWqqXmz8gx","HlUbFyluBx","OUYuFYh1hF","5VZjSJKWYR","LewvMjzUqR","14FLR1LB1L","rhl0JAkKTk","0h1b1jtn0X","vOqCERxrsm","GSQwjYOfrY",
-"lkMUAWPmlx","ECMvUW3VFH","s4786HRxd8","WMiS3QWxoT","HfyNQOUYuF","QClRLNxx9V","wiHrZKZamH","QClRLHfyNQ","dQ586lH1kt","qaofNGv3Fq",
-"Yf2EctuDyS","64s8NgdQsS","0Wr5ylweGy","GrDg78TxD7","JIqXin1pmO","gIYvEpAhR1","aDGtSkB5nP","UmaEvlm0pD","fqypyThjNn","Yw2oU5drc6",
-"SjskQBpYhV","Mkgy8nnP8o","gjUTuXflUq","fmIK1RsQUq","Ta8f6hSSvQ","D6rBySs0Zu","WaWsv4W0Tl","jSjS3XflUq","Y1mC0AmdQd","7fKYUUmaEv",
-"ni2v1uvf7A","oVQp6JkzUn","lH1kt8RCUA","5iGN5oQ87r","QbxXcokgRi","Zv7z0MGlTF","BpYhVZ4I1v","ECMvUn8pJ9","3weIFFxX9q","NhXduCdyBV",
-"jSjS3Mkgy8","lpF6WFnPFB","nlaByQssNC","8hJdtBCxeC","7fsYM0YAGH","Nxx9VyEfy9","hi5X7C2Irc","W3VFHfcwDa","OUYuFOUqFM","5ZaEzdpe1v",
-"ZhwG18TxD7","7ku1puupzk","8RCUA9iGoT","UlU3MlkMUA","kB5nPix74r","AgJHQJIqXi","AkKTkFNYIM","MGlTFStlDJ","SWfouOUYuF","Yf2Ecdpe1v",
-"jeskSRpBQm","KsjRKzbIYY","gjUTuF6PT2","lsQGoFjHXR","Yw2oUxXTI4","0YAGHcmXIX","lH1ktQ6hMC","OxWIH0MR5X","dhSuHdQ586","e6e4z4dEz6",
-"6q6L9e6e4z","gf8rIzbIYY","hUTw7CK5W7","dmoS7xciqp","uLtKsbZLvS","Fhtgl16lHc","faHirqQxHP","5Mg9r5IhmG","7lUXZaez9y","iB08lEoToP",
-"DcpWBTwano","jzUqRVNCPd","9eoRc6q6L9","NhXduThjNn","uZPqgAmdQd","t98iW580YD","DQimpMmsIo","M6qcG7fsYM","J2mQiG1RhS","lsQGoD6rBy",
-"IRh48J2mQi","k85AedhSuH","IBe8kyToGW","5IhmGuZPqg","Vprf2cShY2","pAhR1yofH3","VerEApvgjS","NhXduUvlv4","ZzJHW5Drn0","XyPZNni2v1",
-"S2DfuQClRL","ZUnqtBFkb8","BpYhVYh1hF","Yf2EctaOXK","S77LHpmeCd","TCgPpuZPqg","StlDJjzUqR","piJSkwiHrZ","fcwDaa00b5","gIYvEZuDtD",
-"QssNC9eoRc","Nxx9VAgJHQ","HzZT8PYBf4","lj07QRmDcr","zqH0WAkKTk","zHF1q16lHc","xciqpazIWp","0Wr5ycQOnv","pFrrlprNT6","IBe8kjfREu",
-"64s8NS77LH","CNHmvPOUYS","BFkb8FxX9q","gf8rIs4786","rz7UtCfgr3","rKDLJcShY2","WPmlxStlDJ","9eoRcogLgc","Mm8sifqypy","zY1GYlpF6W",
-"RkQke0h1b1","8hJdtdjsrv","2hEEU1LB1L","QworuOHaBz","JIqXiMm8si","y94nwSjskQ","tuDySVIlwP","dQ586dQ586","Ta8f6KsjRK","JIqXisoy9t",
-"ZuDtD55rfB","4QMc9SmGzv","h1zcHcShY2","HP4335nmWv","EOE1oCNHmv","Ta8f6s93Ml","MGlTFzQt6Q","9y4lwiKqhr","7fsYMdmoS7","D6rBysuY4x",
-"KZamH2ZHdk","ThjNncL0aE","lj07QuTacx","oVQp6QbxXc","t59lRlsQGo","9eoRcHzZT8","blLA9uQIcz","5Mg9rMmsIo","AOgEeMojnP","tlILt5VZjS",
-"MmKGJni2v1","48cHL0BmCy","aDGtSVIlwP","hi5X7ECMvU","prNT62Yz7E","lm0pDHlUbF","vLsmS5VZjS","XyPZNKZamH","C2Ircs93Ml","Vprf2Y1mC0",
-"7fsYMm4bxU","QnJ1SK4GS8","FNYIMuQIcz","7ku1pDcpWB","xReeccL0aE","NcICA2Yz7E","EdBKc0YAGH","Ta8f6KASQ8","FPfSEsoy9t","v2eC30Wr5y",
-"Q6hMCpAhR1","VBjhz8xEKz","5Drn0faHir","xReecFhtgl","ogLgclj07Q","xReecVBjhz","Yf2Ec8hJdt","iwzGkpiJSk","lkMUAdjsrv","ZUnqttl72W",
-"Y1mC0xReec","8hJdtprNT6","faHirlViBv","lm0pDLDk6f","uQIczqQxHP","s93Ml8hJdt","oQ87rhYBCK","prNT6tvdkD","nnP8o24ARF","1v5hHgIYvE",
-"VNCPdciuWz","lViBvGXdoH","OUYuFFxX9q","FVMxo7fsYM","FwEJzX6Pin","aez9yfaHir","jtn0Xa00b5","ulk41Qworu","Uvlv41j5L8","FjHXRIKxdL",
-"BbwgAC2Irc","Gv3Fq618Di","2Yz7EMK07Y","tjQxsIKxdL","Waim6BGaQY","48cHLWaWsv","d7vjMPYBf4","Dz1R307n1c","8xEKzYjB9t","PYBf4KASQ8",
-"Kr8ysv8yFN","hi5X7BpYhV","s93Mln8pJ9","CK5W7DG4sT","oGu6xRzaZA","2DREsMezSW","d7vjMOxWIH","GrDg75iGN5","ZhwG1Yh1hF","QClRLY1mC0",
-"ulk41F6PT2","2TRI7BFkb8","AIYUu8TxD7","azIWpjeskS","xXTI4fcJOy","Rxrsm5Mg9r","iB08l580YD","tjQxs1v5hH","Z4I1vMGlTF","ciuWziKqhr",
-"StlDJuoStw","BGaQYGSQwj","KZamHmX2GE","euZA555rfB","0BmCyzQt6Q","SjskQHzZT8","HP433zmLYD","fqypytAOsr","yofH3ksJby","ECMvUKsjRK",
-"QChxsuJScX","d85a9UmaEv","t98iWAXpwE","prNT60PktI","L7cGc1v5hH","3weIFuvf7A","D6rByuLtKs","G1RhSVLTy6","bgJAzMojnP","HP4337X3uy",
-"jfREuSs0Zu","t59lRK4GS8","mX2GESmGzv","qUJMdyEfy9","Kr8yslH1kt","azIWpuoStw","zFgtBFPfSE","AkKTkbrhlQ","pWiOs5IhmG","Y1mC07lUXZ",
-"tvdkDKZamH","zQt6QTwano","hi5X7bZLvS","okgRiWmadA","gtCA5Y1mC0","8TxD7HfyNQ","WreyP0ao3l","Ss0Zu5nmWv","7X3uylweGy","POUYSlpF6W",
-"JKWYRaL6AJ","tvdkDM3zXL","W3VFHyEfy9","h1zcHY1mC0","nFqikTXQ0Z","2hEEUmz8gx","9iGoToGu6x","OUYuFs7Mxk","e6e4zjiVBP","B3qemFFDui",
-"SjskQzFgtB","RpBQmfcwDa","MezSWzQt6Q","IRh480Kyfs","pvgjS8TxD7","Z4I1vv8yFN","KsjRKlkMUA","uvf7AtvdkD","brhlQpiJSk","4W0TlVprf2",
-"lsQGo5ZaEz","MmKGJRpBQm","0YAGHAmdQd","gIYvERmDcr","uN6r3iKqhr","7ku1pP6bcg","zFgtB7ku1p","fqypy8xEKz","atef2FxX9q","0BmCy6q6L9",
-"yofH3MaJQs","J2mQiZJTXH","FxX9qAmdQd","y94nwprNT6","jtn0XFLsph","3weIFTa8f6","bgJAzGSQwj","8U2nUgIYvE","ZUnqt2ZHdk","2hEEU7X3uy",
-"RsQUqOxWIH","2ZHdk4dEz6","bgJAzK4GS8","Uvlv48RCUA","9GXkXdmoS7","0BmCymz8gx","AOgEepiJSk","dpe1vlXFOB","MGlTFuJScX","Oz8yZDz1R3",
-"P6bcgd7vjM","48cHLn1pmO","NAFuwP6bcg","AkKTkblLA9","64s8NCfgr3","lpF6WYw2oU","QworuEOE1o","S77LHtaOXK","FGzgp45cIH","7X3uyZJTXH",
-"wDajXPOUYS","m4bxUgjUTu","QnJ1SFjHXR","zFgtB2Yz7E","OUYuF0BmCy","VLTy6DLhzM","pv0i7ThjNn","UlU3Mrz7Ut","CNHmv48cHL","8U2nUVerEA",
-"8U2nUMaJQs","14FLRMojnP","Ul4a1Q6hMC","Kr8ysgtCA5","djsrvjS1aj","1j5L85VZjS","oGu6xQnJ1S","uAWyphi5X7","BCxeCZzJHW","xXTI4WDVWJ",
-"P6bcgFxX9q","hSSvQpAhR1","JXljWHlUbF","No0QbzFgtB","ix74rQChxs","0Wr5yv8yFN","KZamHFGzgp","pAhR1EdBKc","zz4ZU5Mg9r","zbIYY48cHL",
-"2Yz7EHlUbF","07n1c1v5hH","HlUbFuJScX","VIlwPnFqik","X6Pinn1pmO","d85a9ZhwG1","1v5hHJIqXi","2Yz7Eatef2","9rlg9dhSuH","i7WMQrhl0J",
-"l83UdUvlv4","QbxXcNxx9V","5drc6suY4x","fqypyDz1R3","v8yFNBGaQY","4W0TlnlaBy","QWxoTsqVrf","pT8wuUl4a1","RBhp0YjB9t","1j5L8RACuj",
-"CxVEfSmGzv","rKDLJyluBx","uAWyp4W0Tl","ni2v1ThjNn","ydG8UCxVEf","zY1GY9eoRc","PYBf4uQIcz","FVMxouJScX","kZANmzbIYY","RBhp0VNCPd",
-"B3qem5Drn0","AOgEedmoS7","2ZHdklViBv","lweGyTCgPp","UmaEvNo0Qb","vOqCEgIYvE","BCxeCM3zXL","s4786qQxHP","8FmFHMm8si","CNHmvnFqik",
-"x3LDeMGlTF","Dz1R3JXljW","dpe1vFPfSE","pv0i7zmLYD","FFDuixXTI4","Nxx9VcShY2","lXFOBtvdkD","fFDrJYw2oU","YOfrYoGu6x","SbRYyTwano",
-"hYBCKhe9IA","7ku1pVprf2","POUYSAkKTk","GXdoHwDajX","iwzGkVerEA","0ao3lAkKTk","djsrvFwEJz","pFrrl7hyVv","suY4x9XyT9","soy9t48cHL",
-"1LB1LYh1hF","0PktIRsQUq","QClRLazIWp","EoToPECMvU","0ao3lFwEJz","yluBxaFFss","M3zXLFGzgp","iwzGk8FmFH","Nxx9VlpF6W","4dEz6QClRL",
-"U3yw5M6qcG","ECMvURmDcr","0MR5X5Drn0","soy9tlsQGo","n1pmOQ6hMC","24ARFjS1aj","fqypydhSuH","hE1QlIRh48","FLsphCqqaD","9GXkXjS1aj",
-"yEfy9ciuWz","RmDcr48cHL","ciuWzyvOMI","0BmCyJXljW","n8pJ92Yz7E","PYBf42hEEU","sx5GljzUqR","Dz1R3qaofN","lsQGoRzaZA","DLhzMQ6hMC",
-"AXpwEhE1Ql","Yh1hFe6e4z","AkKTk14FLR","NhXdu2DREs","XyPZN8RCUA","uoStwVerEA","yvOMIZJTXH","CK5W78hJdt","dhSuHChuy3","v2eC3i3pyd",
-"tvdkDlH1kt","uAWypZhwG1","lweGyzz4ZU","DG4sTuvf7A","OUqFMzHF1q","UlU3M5nmWv","I7p2auAWyp","n1pmOYjB9t","lCMxylkMUA","pv0i7QClRL",
-"iwzGkjzUqR","s7MxktuDyS","yToGW9eoRc","0h1b1GSQwj","CNHmvLewvM","M6qcGb29RJ","dpe1vTwano","YOfrYsqVrf","MezSW8TxD7","ciuWzM3zXL",
-"uoStwJXljW","4W0TlpAhR1","n1pmO64s8N","EoToPpv0i7","5NammwDajX","gf8rIfaHir","blLA9zHF1q","7ku1piB08l","pWiOsMm8si","euZA5uZPqg",
-"45cIH2ZHdk","BFkb8EOE1o","xXTI4IRh48","sqVrfQ6Lix","M6qcGOUYuF","2Yz7EX6Pin","h1zcHpv0i7","vOqCENo0Qb","oQ87raez9y","kB5nP0h1b1",
-"ZzJHWTwano","DLhzMRpBQm","kB5nPnFqik","kZANmQssNC","9GXkXTwano","iwzGkcShY2","aL6AJP6bcg","GWqqXDLhzM","t98iWOUYuF","0KyfsL7cGc",
-"lsQGozQt6Q","DLhzMtlILt","t98iW8U2nU","Mkgy8YOfrY","B3qemYjB9t","9eoRccmXIX","vOqCEo8Uyd","kB5nP6AFT0","xReecs7Mxk","lm0pDzqH0W",
-"9GXkXQnJ1S","QWxoTBGaQY","ZzJHWzbIYY","oQ87rjiVBP","wiHrZqUJMd","NOHszFGzgp","MGlTFtvdkD","X6PinM6qcG","l83UdBFkb8","uZPqgZUnqt",
-"KASQ8v1Hln","b29RJ0h1b1","DQimpCdyBV","zqH0W5ZaEz","gtCA5gIYvE","lm0pDpiJSk","AkKTkAOgEe","GXdoH0h1b1","CqqaDAmdQd","ciuWzjSjS3",
-"J2mQiYh1hF","y94nwO3iyQ","5VZjSZ4I1v","zqH0WtuDyS","7Ow5CWaWsv","t98iWjtn0X","FhtglYw2oU","8FmFH0MR5X","hYBCKs7Mxk","KsjRKKr8ys",
-"hUTw70YAGH","8cVD3Mkgy8","aez9y4QMc9","pT8wuThjNn","d7vjMuvf7A","hi5X7aL6AJ","aDGtSSWfou","pT8wuNhXdu","Nxx9V16lHc","uvf7A5ZaEz",
-"45cIHkZANm","LewvMyEfy9","zbIYYSjskQ","ix74rFnPFB","e6e4z07n1c","jtn0XC2Irc","2DREsZJTXH","gdQsSWaWsv","UlU3My94nw","aez9yQnJ1S",
-"iKqhrxXTI4","M6qcGOz8yZ","n1pmOLDk6f","29QAz8hJdt","zmLYDFGzgp","i3pydnlaBy","JkzUnuvf7A","Q6LixVerEA","KASQ8BpYhV","FNYIMXyPZN",
-"ZJTXHZuDtD","BCxeCAkKTk","PYBf4rKDLJ","Uvlv4J2mQi","FnPFBmz8gx","dpe1vFxX9q","Vprf2jfREu","zHF1qNOHsz","gjUTuUlU3M","uN6r3Ta8f6",
-"rz7UtStlDJ","ulk41jS1aj","ix74rPYBf4","S77LHoVQp6","zbIYYEdBKc","uZPqgCIShG","y94nwn1pmO","lkMUAX6Pin","F6PT28RCUA","lweGyP6bcg",
-"DG4sTAIYUu","i3pydFPfSE","lpF6WMojnP","fqypyHlUbF","CdyBVDz1R3","NhXdus93Ml","zY1GY1j5L8","jiVBPLewvM","l83UddmoS7","Vprf2Vprf2",
-"8TxD7Gv3Fq","IRh48JXljW","yofH3mX2GE","FxX9qYf2Ec","0BmCyuAWyp","7fKYUY1mC0","45cIHoGu6x","t59lR07n1c","AgJHQFLsph","KASQ81v5hH",
-"JIqXi7fsYM","hE1QlMojnP","kB5nPRpBQm","xciqpfcJOy","2ZHdkiKqhr","Y1mC0lXFOB","ZhwG1suY4x","U3yw5tuDyS","qUJMddQ586","HP4332Yz7E",
-"gf8rIM6qcG","RmDcrCdyBV","b29RJtl72W","l83UdvLsmS","EdBKche9IA","FcWrWydG8U","C2IrcZhwG1","Cfgr3cShY2","K20wKEoToP","ZzJHWS77LH",
-"tuDySkB5nP","i3pydFhtgl","Q6hMCQnJ1S","BGaQYIKxdL","uAWypt98iW","t59lRx3LDe","HlUbF0ao3l","k85AeaDGtS","RpBQm14FLR","Qworus7Mxk",
-"he9IAsx5Gl","IKxdLWDVWJ","yToGWtuDyS","lm0pDCNHmv","AXpwE8U2nU","dmoS7QClRL","v2eC3O3iyQ","Ul4a1C2Irc","v8yFNjS1aj","x3LDe580YD",
-"uQIczAgJHQ","7ku1pYOfrY","tlILt7Ow5C","gjUTuo8Uyd","vLsmSuPX7G","uTacxv8yFN","WaWsvtjQxs","TCgPpsuY4x","VBjhzfqypy","29QAzUl4a1",
-"mz8gxuAWyp","yofH364s8N","2ZHdk0PktI","5NammQnJ1S","FwEJzuJScX","pvgjScL0aE","6q6L9IRh48","n1pmOkZANm","CdyBVuPX7G","MezSW3weIF",
-"pv0i7Yh1hF","zY1GYqUJMd","0h1b1oVQp6","pv0i7bZLvS","In3NSru4UG","Yh1hFMaJQs","5Drn0SbRYy","MaJQshe9IA","OUYuFtvdkD","QClRLKr8ys",
-"F6PT2NOHsz","O3iyQUvlv4","Cp3mZQ6hMC","CdyBV64s8N","cShY2zQt6Q","nnP8o7lUXZ","gf8rId7vjM","5VZjSjzUqR","M3zXLO3iyQ","yvOMIjfREu",
-"ZUnqtiB08l","Oz8yZsqVrf","KsjRKlsQGo","nlaByjeskS","jzUqR9GXkX","P6bcgVIlwP","2Nslmaez9y","Gv3FqWmadA","t59lR0BmCy","fqypyAXpwE",
-"n8pJ94QMc9","XyPZNAXpwE","Cp3mZ3weIF","ZzJHWAOgEe","GSQwjpvgjS","l83UdfFDrJ","ZhwG1FxX9q","taOXKO3iyQ","yEfy9azIWp","pv0i7lViBv",
-"24ARFsqVrf","FnPFB24ARF","zFgtByToGW","9eoRcAkKTk","v1Hlnrhl0J","OHaBzStlDJ","sx5Gl6AFT0","rhl0JZJTXH","AIYUugtCA5","GXdoHaL6AJ",
-"uvf7A07n1c","jeskS5drc6","LewvMuTacx","EOE1oWPmlx","sqVrfVjCZq","EdBKcDG4sT","Oz8yZAXpwE","VLTy6GrDg7","mX2GE4dEz6","LbRTHHzZT8",
-"8U2nUPYBf4","P6bcgjfREu","m4bxUzQt6Q","iwzGkVBjhz","StlDJRkQke","GXdoHpWiOs","brhlQtlILt","xciqpM6qcG","rKDLJMojnP","No0Qbn8pJ9",
-"mz8gxTXQ0Z","5nmWvEOE1o","hYBCKMaJQs","4dEz63weIF","J2mQiyluBx","sqVrfDQimp","t59lRni2v1","L7cGc7X3uy","9y4lwDG4sT","pFrrlCIShG",
-"0YAGHfcJOy","P6bcgQbxXc","S2DfukB5nP","brhlQuTacx","8xEKz4QMc9","lm0pDCIShG","vLsmSbgJAz","n8pJ9jtn0X","AkKTks4786","QnJ1Spv0i7",
-"hE1Qls7Mxk","gf8rI16lHc","zmLYD0Kyfs","JkzUn5nmWv","yToGWciuWz","bgJAzuvf7A","oGu6xrz7Ut","v1HlnuAWyp","ydG8U9y4lw","blLA91j5L8",
-"zQt6Q2Nslm","Dz1R3ThjNn","7fsYMpT8wu","IjTwPjS1aj","iwzGkhUTw7","uAWypVBjhz","FhtgllCMxy","8RCUA4W0Tl","ReKEWvOqCE","BCxeCVerEA",
-"Q6Lixn1pmO","8hJdt9y4lw","oVQp60Wr5y","sx5Gl7fKYU","soy9tBGaQY","gIYvE6AFT0","faHirhi5X7","EOE1obrhlQ","hE1Ql6AFT0","gf8rIuZPqg",
-"vOqCEQWxoT","Z4I1vvLsmS","nnP8oBGaQY","POUYS9y4lw","FNYIM6AFT0","ZzJHWWreyP","0BmCyIjTwP","PYBf4fFDrJ","hE1Ql4W0Tl","StlDJWaWsv",
-"K20wKPOUYS","oQ87rpiJSk","nlaByMkgy8","RzaZA0BmCy","gf8rIStlDJ","8U2nUpmeCd","uN6r3zFgtB","6q6L9dmoS7","WmadAy94nw","HRxd8ru4UG",
-"xXTI45VZjS","iKqhrKZamH","uPX7Gsx5Gl","uN6r3qQxHP","GWqqXciuWz","guMb8HfyNQ","2TRI7yofH3","nFqikMmsIo","VerEAaFFss","cQOnvlkMUA",
-"yluBxCdyBV","mX2GEqaofN","RACujGv3Fq","h1zcHvkCHH","zqH0WsqVrf","okgRiY1mC0","Cp3mZRxrsm","XflUqGWqqX","lH1ktn1pmO","kZANm07n1c",
-"8xEKziB08l","TCgPpFnPFB","RBhp0uN6r3","tAOsruvf7A","n8pJ9RkQke","QnJ1SpiJSk","AgJHQMm8si","guMb8cL0aE","TCgPp0Kyfs","Y1mC0qUJMd",
-"cQOnvFwEJz","s7Mxks7Mxk","s93MlPOUYS","618DiRxrsm","HfyNQSbRYy","k85AeoQ87r","RACujuoStw","v1HlnzFgtB","y94nwCfgr3","K4GS8JXljW",
-"DcpWBW3VFH","fqypyGrDg7","RxrsmjeskS","8xEKzk85Ae","pv0i72DREs","VjCZqEoToP","RzaZAWmadA","StlDJAmdQd","dmoS7v8yFN","iB08luTacx",
-"ReKEWhe9IA","Cfgr3Cfgr3","ReKEWM6qcG","5VZjSv1Hln","yEfy929QAz","qQxHPRsQUq","Oz8yZv8yFN","Nxx9VDcpWB","ZJTXHFjHXR","uTacxQChxs",
-"n8pJ9NOHsz","uvf7ADQimp","0ao3lWmadA","djsrvFhtgl","lCMxykZANm","XflUq5nmWv","W7cTs6AFT0","n8pJ9CqqaD","VLTy6o8Uyd","NhXduQnJ1S",
-"0h1b1IjTwP","FwEJzIRh48","zHF1qiKqhr","jeskSK4GS8","9eoRckB5nP","AXpwE1j5L8","dpe1vCdyBV","0h1b1JJs5m","jfREuIKxdL","48cHLVLTy6",
-"yofH3ciuWz","lH1ktBGaQY","Kr8ysJJs5m","W3VFHCfgr3","i3pydrhl0J","MmKGJlj07Q","Nxx9VWaWsv","hSSvQvLsmS","9eoRc9XyT9","VLTy6No0Qb",
-"Pb1pan1pmO","uQIczOUYuF","tlILtuZPqg","lpF6WMm8si","pv0i78U2nU","jfREuiB08l","soy9tguMb8","piJSkRsQUq","yofH3rz7Ut","FnPFB0h1b1",
-"pFrrlrhl0J","xReecKsjRK","WDVWJgjUTu","zQt6QOxWIH","5VZjSXyPZN","DG4sTlCMxy","VBjhzpiJSk","aez9yGXdoH","uZPqgni2v1","QssNClm0pD",
-"dmoS7WreyP","8FmFHqQxHP","FGzgpuoStw","2Yz7EMGlTF","jS1ajjeskS","CqqaDtvdkD","FnPFBF6PT2","MK07YFcWrW","8U2nU9XyT9","pFrrlIBe8k",
-"QYxC0HfyNQ","FxX9qoQ87r","HP433tAOsr","s7Mxk7Ow5C","Cp3mZt59lR","MK07Ylj07Q","x3LDedjsrv","pv0i7W7cTs","MK07YRBhp0","hSSvQKASQ8",
-"B3qemAXpwE","QssNCQ6hMC","9GXkXv8yFN","VjCZqStlDJ","9iGoTAkKTk","OxWIH7X3uy","wDajX0BmCy","2ZHdkNhXdu","6AFT08hJdt","aFFsscL0aE",
-"jtn0Xt59lR","s4786PYBf4","FxX9qECMvU","uQIcz8FmFH","fLNg8v2eC3","cShY25VZjS","ru4UGprNT6","8U2nUSmGzv","GWqqXsuY4x","7fsYMyEfy9",
-"cmXIXTCgPp","aDGtSjzUqR","NcICAReKEW","AXpwESjskQ","qQxHPkB5nP","ThjNnFGzgp","iB08lQbxXc","sqVrfZzJHW","KZamHMGlTF","K4GS8ydG8U",
-"bZLvSNAFuw","cmXIXpv0i7","zbIYYgf8rI","Yh1hFi3pyd","FNYIMnlaBy","yluBx8RCUA","8cVD3uoStw","ZhwG1Yw2oU","FFDuii7WMQ","faHirFLsph",
-"euZA5lsQGo","WaWsvzqH0W","Yw2oU1j5L8","fLNg8cQOnv","gIYvEix74r","U3yw5MmsIo","HRxd8WPmlx","J2mQiuAWyp","YjB9tulk41","RmDcrwiHrZ",
-"NAFuwQ6hMC","hUTw7M6qcG","FVMxot98iW","lXFOBJkzUn","5drc6fmIK1","tl72WWaim6","pmeCdlkMUA","9GXkXdjsrv","soy9ti3pyd","DcpWB48cHL",
-"ZUnqtRsQUq","gtCA5lweGy","8cVD3Uvlv4","GXdoHHfyNQ","GWqqXMm8si","VerEAUmaEv","CdyBVOz8yZ","Cp3mZAOgEe","fmIK1t98iW","Q6hMCFVMxo",
-"7hyVv7Ow5C","K4GS86q6L9","dhSuHDz1R3","QnJ1SzHF1q","aez9yVerEA","0ao3l6AFT0","WaWsvQWxoT","O3iyQt59lR","LbRTH2DREs","FnPFBjeskS",
-"uQIcza00b5","NAFuwCfgr3","UmaEvMezSW","W3VFHVIlwP","580YDBGaQY","tuDyS5iGN5","OxWIHX6Pin","aFFssS77LH","jzUqRMezSW","uJScXQYxC0",
-"QnJ1SO3iyQ","HRxd8fFDrJ","uAWypAXpwE","Waim6LDk6f","ydG8UvLsmS","PYBf4XyPZN","aFFss2Nslm","n8pJ9nlaBy","sqVrfjSjS3","5Mg9r14FLR",
-"ZUnqtk85Ae","Y1mC0VNCPd","ReKEWlsQGo","S77LHQChxs","RkQkeGrDg7","piJSkOUqFM","O3iyQQ6Lix","KZamHL7cGc","CdyBVh1zcH","zbIYY4QMc9",
-"D6rByogLgc","SmGzv9XyT9","IjTwPHzZT8","SWfouyofH3","5nmWvOz8yZ","fFDrJDG4sT","jeskSv1Hln","QbxXcMK07Y","jS1ajZv7z0","CqqaD3weIF",
-"sqVrf3otm6","4QMc9B3qem","9XyT9Nxx9V","FcWrWb29RJ","lXFOBSs0Zu","zmLYDWmadA","AIYUuuJScX","MGlTFF6PT2","iKqhrBCxeC","8TxD7nlaBy",
-"prNT6TCgPp","pAhR1hi5X7","XyPZNJXljW","DcpWBBGaQY","618DidmoS7","t98iWuTacx","VLTy6xciqp","xXTI4piJSk","nnP8os93Ml","qQxHPIKxdL",
-"Oz8yZfLNg8","i7WMQgdQsS","zQt6QpWiOs","ni2v1h1zcH","DcpWB45cIH","azIWpfcwDa","iKqhruQIcz","Cp3mZGSQwj","uTacxNcICA","vLsmSTwano",
-"v2eC3azIWp","OxWIHQbxXc","ZUnqtSbRYy","zFgtBjzUqR","BbwgA9GXkX","jzUqRZ4I1v","HzZT8AgJHQ","MmKGJK20wK","7fsYMQYxC0","cmXIXXyPZN",
-"yEfy9fcJOy","uTacxd7vjM","IRh487ku1p","8FmFHtl72W","AOgEe5VZjS","faHir0ao3l","Kr8ysuTacx","nFqiklViBv","vLsmSqaofN","SjskQ7fKYU",
-"9y4lwvOqCE","CdyBV0PktI","MmsIoogLgc","LewvMlXFOB","bgJAzSbRYy","ThjNn5iGN5","WDVWJtvdkD","No0Qbjtn0X","1v5hH3weIF","lweGyazIWp",
-"AgJHQbZLvS","zqH0WJRJQB","VNCPdS77LH","45cIHpvgjS","5iGN5uTacx","ni2v1X6Pin","Mkgy8FLsph","SjskQAIYUu","7X3uy6q6L9","kB5nPCxVEf",
-"BpYhVuvf7A","7ku1pQYxC0","iwzGkrKDLJ","v8yFNoQ87r","Cfgr3yofH3","NOHszSbRYy","wiHrZRBhp0","5nmWvZv7z0","xXTI4uLtKs","NcICAdpe1v",
-"uAWypRACuj","HlUbF0BmCy","k85AeQClRL","L7cGcdjsrv","Cp3mZxReec","AOgEejiVBP","xXTI4tl72W","bZLvSy94nw","QworutuDyS","fmIK1bgJAz",
-"IjTwPJRJQB","uPX7GIn3NS","Ss0Zu9GXkX","TCgPpkZANm","t59lRDz1R3","brhlQgdQsS","HzZT8ReKEW","xciqpbgJAz","faHirgdQsS","ECMvUblLA9",
-"MaJQsTwano","rz7Uth1zcH","Ta8f6HP433","55rfBKsjRK","Z4I1vfFDrJ","DG4sTvkCHH","e6e4zOz8yZ","vkCHH3weIF","FLsphyluBx","lCMxyCNHmv",
-"7X3uygjUTu","WmadAazIWp","uLtKsHRxd8","RBhp0JIqXi","mX2GEgtCA5","a00b5taOXK","K20wKKASQ8","AgJHQd85a9","gtCA5Vprf2","HP433JkzUn",
-"ciuWzS77LH","M6qcGVjCZq","2TRI7Q6Lix","FFDuiNAFuw","mz8gxpT8wu","48cHL14FLR","jeskS64s8N","sqVrfkB5nP","OUqFMMojnP","kB5nPO3iyQ",
-"OHaBzReKEW","BbwgAEOE1o","he9IAqUJMd","8U2nURpBQm","WMiS3HlUbF","i3pydQworu","9GXkXRACuj","BbwgASs0Zu","fcJOyl83Ud","VNCPdk85Ae",
-"C2IrcjzUqR","azIWpEOE1o","uupzkI7p2a","WmadAMmsIo","djsrvLbRTH","XflUqfqypy","prNT6tAOsr","iwzGkrz7Ut","KZamHQ6Lix","W7cTsP6bcg",
-"t59lRblLA9","dpe1vkZANm","QssNCvkCHH","POUYSiqv4k","euZA5MezSW","2hEEU1v5hH","ZzJHWMK07Y","azIWpuJScX","W7cTsHP433","uAWypGWqqX",
-"CIShGfLNg8","KZamHPb1pa","0Wr5ySmGzv","Kr8ysSs0Zu","JJs5m1j5L8","uZPqg8FmFH","ZzJHWpWiOs","VBjhzU3yw5","yEfy9D6rBy","CqqaDSs0Zu",
-"8FmFHs7Mxk","mz8gx8xEKz","kB5nPM6qcG","zFgtBdjsrv","9XyT9ECMvU","GrDg7QnJ1S","nnP8oK4GS8","FLsphpvgjS","brhlQdhSuH","rz7UtuJScX",
-"Mm8sis4786","PYBf49rlg9","MaJQsGv3Fq","lweGyDz1R3","Kr8ysRBhp0","OUqFMFhtgl","ReKEWHfyNQ","oGu6xTwano","xReecn8pJ9","uupzkP6bcg",
-"5ZaEz8FmFH","tl72WuAWyp","7X3uyuTacx","M3zXLRACuj","fmIK1uAWyp","QworuECMvU","rhl0JFPfSE","ix74ruTacx","v1HlnuPX7G","QYxC00YAGH",
-"fcwDauPX7G","IjTwPFwEJz","rz7UtgjUTu","lpF6WgjUTu","C2IrcqQxHP","MezSWWaWsv","U3yw59y4lw","zY1GYfLNg8","BbwgAaez9y","7ku1pguMb8",
-"lpF6WtaOXK","AgJHQbgJAz","Mm8sioGu6x","nlaByRBhp0","S77LHNhXdu","QnJ1SHzZT8","2ZHdkBbwgA","AgJHQ8FmFH","0PktIy94nw","lweGyOz8yZ",
-"e6e4zJkzUn","AXpwELewvM","gf8rIqQxHP","suY4xksJby","lm0pDpv0i7","zQt6QRpBQm","WmadANAFuw","BpYhVQ6hMC","Zv7z0QChxs","lweGyhE1Ql",
-"TXQ0ZnlaBy","JIqXid7vjM","VjCZqaL6AJ","FVMxodjsrv","Ss0ZutvdkD","TCgPp2DREs","Ul4a1kZANm","uQIczZzJHW","7X3uyM6qcG","t59lRjzUqR",
-"mX2GEfLNg8","Chuy3d7vjM","azIWpv1Hln","lj07QW3VFH","v1Hlnb29RJ","CxVEf5iGN5","IRh48XflUq","RpBQmtAOsr","1v5hHNcICA","7ku1pHP433",
-"FwEJzpvgjS","XyPZNIBe8k","O3iyQQssNC","jS1ajRsQUq","OHaBzd7vjM","VNCPd7X3uy","NcICApFrrl","qUJMdIn3NS","2Yz7EQnJ1S","TCgPpFGzgp",
-"rhl0J14FLR","0ao3lJIqXi","FNYIMlkMUA","M6qcGiB08l","RsQUqIRh48","QworuoQ87r","s93Ml0BmCy","CdyBVWreyP","wDajXFxX9q","HlUbFrKDLJ",
-"EOE1oHRxd8","gIYvEEOE1o","lj07QEOE1o","nlaByFhtgl","pv0i7jzUqR","prNT6Fhtgl","uupzkK20wK","VerEAtlILt","taOXK618Di","QWxoT0MR5X",
-"6AFT0AIYUu","0YAGHGrDg7","zQt6Q14FLR","KASQ8Q6Lix","wiHrZIBe8k","rhl0Jv8yFN","AkKTk7lUXZ","lH1ktIRh48","cShY2pWiOs","jzUqRulk41",
-"ZUnqt8FmFH","WmadA45cIH","48cHLZv7z0","faHirZuDtD","uAWypSjskQ","HRxd8NhXdu","oQ87r0Wr5y","kB5nPAkKTk","qaofNlViBv","pFrrlCNHmv",
-"RACujjS1aj","GrDg7QChxs","5nmWvlH1kt","nFqikeuZA5","Uvlv4ru4UG","uTacxDG4sT","jtn0X4W0Tl","RpBQmvkCHH","BFkb8GXdoH","7lUXZSjskQ",
-"d85a9JRJQB","JkzUnuN6r3","5VZjSTa8f6","RmDcr5ZaEz","wDajXBGaQY","9eoRcRzaZA","Cfgr3lj07Q","0Wr5yk85Ae","1LB1LZzJHW","rhl0JChuy3",
-"HP433O3iyQ","TCgPpW7cTs","HzZT8TCgPp","NhXdukZANm","DcpWBfcJOy","SbRYyC2Irc","taOXKKr8ys","cmXIXiqv4k","QChxsQworu","DG4sTOUqFM",
-"soy9tyToGW","8hJdtMK07Y","Kr8ysS2Dfu","lXFOBpWiOs","CqqaDUvlv4","y94nwo8Uyd","M6qcG1j5L8","RkQkei7WMQ","hSSvQCxVEf","Chuy3uZPqg",
-"1v5hH24ARF","lpF6WEoToP","gdQsSB3qem","lweGyDcpWB","xXTI429QAz","5IhmGG1RhS","M6qcGIRh48","WDVWJGWqqX","qQxHPGWqqX","JJs5mPOUYS",
-"k85Aeulk41","lH1ktP6bcg","cQOnvSs0Zu","U3yw5FnPFB","RzaZAhUTw7","uZPqgLDk6f","O3iyQe6e4z","JJs5m7X3uy","jeskS0Wr5y","gjUTu7fsYM",
-"nlaBy8hJdt","ydG8UGrDg7","Cfgr3v2eC3","wiHrZMm8si","07n1cBFkb8","he9IAIBe8k","Zv7z0I7p2a","kB5nPatef2","7ku1pzmLYD","2DREsFLsph",
-"AIYUum4bxU","yluBx7fKYU","e6e4zVLTy6","2TRI7s93Ml","8RCUApT8wu","NcICAsx5Gl","BpYhVd7vjM","wiHrZk85Ae","0h1b1euZA5","jiVBPIRh48",
-"VerEADLhzM","NcICAJRJQB","0h1b1WmadA","azIWppT8wu","ksJbypT8wu","pvgjS0PktI","TCgPp8cVD3","RpBQmJRJQB","ix74rFxX9q","bgJAzxReec",
-"yEfy92Yz7E","Q6Lix9y4lw","FNYIMd85a9","SbRYy580YD","QbxXcdQ586","48cHLVBjhz","0MR5XEOE1o","I7p2aBFkb8","uvf7ApiJSk","jtn0XFNYIM",
-"prNT6ru4UG","nFqikZJTXH","24ARFUmaEv","45cIHjSjS3","6q6L9s93Ml","WaWsvX6Pin","gjUTusuY4x","QssNCZuDtD","ogLgcrKDLJ","VLTy6Yw2oU",
-"G1RhSwiHrZ","ZJTXHxciqp","pv0i74QMc9","v8yFNjzUqR","uN6r314FLR","6AFT0ciuWz","ydG8UTCgPp","4W0TlcQOnv","pT8wui7WMQ","14FLR9y4lw",
-"2NslmJRJQB","lXFOBDcpWB","zFgtBRmDcr","sqVrflsQGo","cShY2Gv3Fq","AOgEeMm8si","MojnPuJScX","P6bcgprNT6","ThjNnX6Pin","5NammGSQwj",
-"DQimpBGaQY","a00b5J2mQi","ReKEWdjsrv","5ZaEz2TRI7","fcJOyW7cTs","KsjRK55rfB","d7vjMcL0aE","FPfSEAIYUu","VIlwPh1zcH","Cp3mZcQOnv",
-"qQxHPVBjhz","RzaZA5Drn0","ni2v1SbRYy","Y1mC08xEKz","U3yw5xReec","Pb1pa0ao3l","LDk6fxXTI4","Cp3mZFcWrW","pFrrlv1Hln","qQxHPIBe8k",
-"AXpwEMezSW","cL0aEuPX7G","FVMxoAOgEe","zqH0Whe9IA","24ARFMm8si","IKxdLIRh48","M3zXLYf2Ec","dpe1vpv0i7","d85a9bgJAz","In3NSBGaQY",
-"RmDcruAWyp","qQxHPFxX9q","tjQxsCIShG","4QMc914FLR","1v5hH5IhmG","zqH0WReKEW","ogLgcVjCZq","Mm8siOUYuF","s93MlCNHmv","v8yFNGWqqX",
-"L7cGc7Ow5C","AXpwEs93Ml","gtCA5FGzgp","uTacxRBhp0","gdQsSOxWIH","TCgPpC2Irc","brhlQQ6hMC","xXTI4FxX9q","lXFOBrz7Ut","nFqikHRxd8",
-"Pb1pavOqCE","cmXIXuN6r3","hUTw7BCxeC","BCxeC2Yz7E","cQOnvZJTXH","XflUqCqqaD","W7cTsEdBKc","KsjRKokgRi","faHirGWqqX","OUYuF29QAz",
-"HP4332ZHdk","Gv3Fq7fKYU","Ta8f6atef2","2Yz7EAkKTk","fLNg8aL6AJ","FcWrWMK07Y","4dEz6uupzk","i7WMQWaWsv","WPmlx9iGoT","14FLR2hEEU",
-"MezSWhE1Ql","ydG8UXyPZN","KASQ8CK5W7","45cIHlCMxy","taOXKaFFss","FjHXRBGaQY","o8UydQnJ1S","HfyNQuupzk","lj07QksJby","ReKEWGXdoH",
-"vOqCErhl0J","5VZjSBbwgA","t59lRuQIcz","oVQp6HfyNQ","xReecdjsrv","5IhmG48cHL","uTacxWDVWJ","jtn0XjiVBP","2hEEUaez9y","NOHszyluBx",
-"RxrsmCfgr3","aez9yoQ87r","lViBvsuY4x","Cp3mZ07n1c","aL6AJy94nw","UlU3MFcWrW","i7WMQRsQUq","UlU3Mni2v1","BFkb80Wr5y","XyPZNd85a9",
-"AkKTksuY4x","NOHszdhSuH","tjQxseuZA5","NOHszNOHsz","Z4I1vOxWIH","lH1kt9XyT9","Chuy35Mg9r","POUYSCIShG","uJScXM3zXL","CK5W7gIYvE",
-"BGaQYzQt6Q","jeskScShY2","BGaQYiB08l","uN6r3lweGy","SbRYyBCxeC","4dEz60ao3l","NOHszMK07Y","uTacxZUnqt","S77LHY1mC0","0Kyfs7fKYU",
-"QClRLNAFuw","1j5L8bgJAz","7lUXZpWiOs","RsQUqDLhzM","sx5Glm4bxU","RACujQ6Lix","cQOnvjeskS","B3qemogLgc","Vprf2zqH0W","o8UydoQ87r",
-"5drc6FGzgp","gf8rIP6bcg","iwzGkQbxXc","0ao3lVerEA","DQimpguMb8","piJSkOHaBz","iKqhrbrhlQ","NcICApAhR1","IBe8kFwEJz","MmsIohE1Ql",
-"X6PinuLtKs","tjQxsAXpwE","dhSuHJKWYR","s7MxkFwEJz","h1zcHMGlTF","FnPFBThjNn","MGlTFNAFuw","MezSWgjUTu","2DREsSWfou","dhSuHgIYvE",
-"5ZaEzuupzk","VjCZq6AFT0","HzZT8ZhwG1","EOE1o8xEKz","prNT6a00b5","ReKEWlkMUA","cQOnvy94nw","Yh1hFgf8rI","L7cGc5nmWv","7ku1pkB5nP",
-"FxX9q6q6L9","ZUnqtZJTXH","HzZT8lkMUA","Uvlv4lViBv","i7WMQJ2mQi","HzZT8yToGW","G1RhSvkCHH","Ul4a19rlg9","I7p2aQClRL","mX2GEMmKGJ",
-"LbRTHStlDJ","y94nwAOgEe","GrDg7Mm8si","xXTI4vOqCE","5Drn0Gv3Fq","lj07QuAWyp","8cVD3gIYvE","l83UdP6bcg","6AFT0gtCA5","Oz8yZjS1aj",
-"jSjS31LB1L","lkMUA9eoRc","n1pmOt98iW","LbRTHKr8ys","KASQ8nFqik","jSjS3VLTy6","OUYuFxXTI4","MmKGJtjQxs","OUYuFwDajX","NAFuwyvOMI",
-"s7Mxk1LB1L","ix74r5nmWv","3weIFgIYvE","6q6L9m4bxU","oQ87rVIlwP","tlILtNxx9V","OHaBziwzGk","a00b5ReKEW","HzZT8Cp3mZ","FxX9qazIWp",
-"Mm8siKASQ8","fFDrJS2Dfu","FnPFB2hEEU","YjB9t8FmFH","SmGzvHlUbF","d85a9QChxs","cL0aEIKxdL","5IhmGWmadA","kB5nPJXljW","aL6AJY1mC0",
-"HRxd8cQOnv","tl72WfFDrJ","Pb1paguMb8","tvdkDuN6r3","QClRLuLtKs","PYBf4StlDJ","lCMxyNOHsz","AmdQdoQ87r","16lHcn8pJ9","6AFT0ru4UG",
-"tvdkDyEfy9","zY1GY7hyVv","LbRTHd7vjM","gjUTuWreyP","AOgEeW3VFH","aez9yzqH0W","TwanobrhlQ","Mm8siNcICA","0BmCyTwano","ix74r0ao3l",
-"mz8gxM6qcG","t59lR5ZaEz","5nmWvogLgc","HP433CqqaD","qaofN2ZHdk","ThjNnMmsIo","VIlwP4QMc9","zHF1qLDk6f","QssNCIn3NS","vkCHH2DREs",
-"Fhtgl5Drn0","WaWsvhE1Ql","azIWpAgJHQ","Z4I1v6AFT0","ZUnqtAXpwE","v8yFNLewvM","zmLYDkB5nP","uPX7GPYBf4","EoToPHfyNQ","hYBCKMmsIo",
-"jS1ajReKEW","K20wKAkKTk","VBjhzNhXdu","tvdkDaDGtS","ZhwG1AOgEe","9eoRcbrhlQ","ZUnqt9iGoT","Uvlv4FjHXR","mX2GEazIWp","Z4I1vqaofN",
-"TCgPpoGu6x","zHF1q0PktI","a00b5rKDLJ","vkCHH0Kyfs","7ku1pulk41","NOHsz9GXkX","uJScXUmaEv","SbRYyAXpwE","1j5L8cShY2","lweGyru4UG",
-"PYBf4s93Ml","JRJQBgIYvE","F6PT2PYBf4","Mkgy8fFDrJ","guMb8JKWYR","hYBCKs93Ml","aez9yL7cGc","45cIHlViBv","ciuWzQworu","pvgjSOz8yZ",
-"HlUbFGv3Fq","VLTy6ZzJHW","qQxHPjfREu","7lUXZStlDJ","hE1Ql7lUXZ","AOgEeRACuj","B3qem0Wr5y","AOgEefcwDa","6AFT02DREs","o8UydoGu6x",
-"3otm6CIShG","MK07YZUnqt","fcwDaU3yw5","guMb8zmLYD","Uvlv4HfyNQ","Mm8siatef2","UmaEvOxWIH","wiHrZtl72W","x3LDeZUnqt","8TxD7piJSk",
-"AmdQdZv7z0","5VZjSdjsrv","K20wKdhSuH","1v5hHhYBCK","o8Uyd9XyT9","sx5GlzmLYD","Gv3FqMK07Y","VNCPdSs0Zu","zmLYDCdyBV","Yh1hFsuY4x",
-"ThjNnEdBKc","0Wr5yWaWsv","9XyT94QMc9","v8yFNU3yw5","t98iWFLsph","5Mg9rZ4I1v","MmsIozHF1q","EoToPsx5Gl","5ZaEzhi5X7","M6qcGlsQGo",
-"UlU3Mdjsrv","S77LHMK07Y","xciqpuN6r3","CIShGvOqCE","taOXKl83Ud","Y1mC0jfREu","AgJHQQ6Lix","zz4ZU14FLR","F6PT2DG4sT","K20wKlsQGo",
-"FcWrWiKqhr","i7WMQjiVBP","sx5GlTXQ0Z","AgJHQGrDg7","Ss0Zu2Yz7E","aez9yuupzk","MK07YMGlTF","mz8gxi3pyd","NOHszyvOMI","EOE1oFVMxo",
-"zY1GYv8yFN","tvdkDkZANm","S77LHbrhlQ","Q6LixJRJQB","FLsphQWxoT","QbxXch1zcH","WmadA9XyT9","VLTy6Rxrsm","LDk6f8FmFH","K4GS8ThjNn",
-"uJScXXflUq","t59lRfcwDa","OUYuFk85Ae","XyPZNB3qem","rKDLJuupzk","Twanoi7WMQ","ECMvU5Mg9r","atef2m4bxU","YOfrYjtn0X","cmXIXGv3Fq",
-"5NammS2Dfu","BCxeCfqypy","GrDg7NOHsz","v1HlnNo0Qb","wiHrZZ4I1v","QnJ1SzqH0W","uupzkJRJQB","aez9yyluBx","uLtKsMaJQs","Yf2EcUvlv4",
-"uQIczpiJSk","IKxdLMojnP","LDk6fjeskS","cQOnvlXFOB","BbwgAtuDyS","07n1cLDk6f","580YDjeskS","djsrvY1mC0","SjskQFPfSE","oVQp6uN6r3",
-"jtn0XFwEJz","dpe1vVNCPd","KsjRKn1pmO","M6qcGAmdQd","azIWpVjCZq","yToGW9XyT9","cmXIXt98iW","0BmCy8RCUA","07n1c580YD","ydG8Uo8Uyd",
-"2TRI7tuDyS","M6qcGyToGW","taOXKogLgc","dQ586Twano","aL6AJbrhlQ","FwEJzNxx9V","HP43355rfB","0Wr5yfcJOy","qQxHPQworu","GSQwjCK5W7",
-"s4786l83Ud","cQOnv16lHc","sqVrfx3LDe","64s8NDG4sT","h1zcHLbRTH","m4bxUdhSuH","HzZT8IBe8k","WaWsvaez9y","No0QbJ2mQi","pFrrlxciqp",
-"Z4I1vy94nw","lweGyksJby","DQimpQbxXc","vLsmSx3LDe","ZJTXHfFDrJ","KZamH48cHL","zbIYYLewvM","AgJHQdQ586","4W0Tlzz4ZU","HRxd8ogLgc",
-"d7vjMAgJHQ","tAOsrO3iyQ","cL0aEvOqCE","Ta8f6dpe1v","IRh48djsrv","vOqCEYjB9t","cmXIXUl4a1","rKDLJTwano","hE1QlIKxdL","JKWYRhE1Ql",
-"wDajXm4bxU","qQxHPFGzgp","cmXIXoQ87r","S2Dfu5VZjS","SbRYyCqqaD","nlaByBGaQY","IBe8kDQimp","UlU3MuQIcz","v8yFNaDGtS","lpF6WdmoS7",
-"Dz1R3JJs5m","9iGoTtl72W","s7MxkjzUqR","tlILtfmIK1","UlU3MKZamH","guMb8yofH3","yEfy9TCgPp","lsQGoWaWsv","JIqXiyEfy9","iKqhrS2Dfu",
-"ciuWz2TRI7","HRxd8S77LH","K4GS8U3yw5","FLsphhE1Ql","0Kyfs48cHL","0MR5Xfqypy","MmKGJ5IhmG","FGzgpciuWz","8RCUAn1pmO","aFFss8U2nU",
-"9XyT92hEEU","taOXKhi5X7","TXQ0Z48cHL","tlILtiKqhr","tlILtcmXIX","pmeCdG1RhS","Vprf2qUJMd","4QMc9MmsIo","0MR5X0Kyfs","zz4ZUoVQp6",
-"QClRLRBhp0","iqv4kcL0aE","WDVWJUl4a1","Kr8ys5iGN5","MojnPG1RhS","Q6hMC55rfB","blLA9AmdQd","LDk6fbrhlQ","Ss0ZuCIShG","tjQxsB3qem",
-"MGlTFECMvU","cmXIX9y4lw","Cfgr3hYBCK","uLtKsJJs5m","uJScXhYBCK","rKDLJYh1hF","FNYIMI7p2a","DQimp4W0Tl","WaWsvaL6AJ","nFqikGWqqX",
-"Uvlv4Yw2oU","WaWsvsx5Gl","QWxoTiKqhr","s4786U3yw5","IRh485Namm","tvdkD0MR5X","2DREsRBhp0","I7p2aIjTwP","J2mQiRsQUq","cShY2IBe8k",
-"48cHLDz1R3","uPX7Gx3LDe","7fsYMkB5nP","Mkgy8s4786","ZJTXH24ARF","VBjhzTa8f6","sx5GlZuDtD","fcJOyTa8f6","zbIYYFGzgp","y94nw0Kyfs",
-"Zv7z0QWxoT","Y1mC0HlUbF","WDVWJvkCHH","MmKGJUmaEv","zY1GYcmXIX","uQIczhE1Ql","vLsmSEOE1o","Nxx9VWreyP","BbwgA0YAGH","lj07QpT8wu",
-"WDVWJcShY2","7ku1pO3iyQ","5Drn0Yf2Ec","Zv7z0DQimp","faHirogLgc","QssNCe6e4z","e6e4zl83Ud","QClRLOUYuF","C2IrcJJs5m","QClRLyvOMI",
-"yofH3AIYUu","3otm6Mkgy8","uLtKsaez9y","cQOnvHzZT8","AkKTkOHaBz","WreyPuLtKs","3weIFFFDui","dmoS7l83Ud","Ul4a1oGu6x","LDk6fAXpwE",
-"b29RJ9XyT9","NAFuwMGlTF","IjTwPnnP8o","5Drn0wiHrZ","aez9yFnPFB","I7p2alXFOB","TXQ0ZYjB9t","WmadAQnJ1S","9y4lwMmsIo","soy9tFwEJz",
-"prNT6ciuWz","9eoRculk41","gf8rIb29RJ","8U2nUBpYhV","uN6r3o8Uyd","uvf7AWreyP","CIShGM6qcG","hUTw7Fhtgl","uupzkpv0i7","ydG8UFFDui",
-"tl72WSWfou","W3VFHydG8U","lCMxyyEfy9","BFkb8RsQUq","GXdoHydG8U","5NammDcpWB","Uvlv49y4lw","o8UydTCgPp","jzUqRRpBQm","ksJbyv8yFN",
-"ZzJHWfqypy","WaWsvB3qem","5drc6GrDg7","jSjS3DQimp","NAFuwM6qcG","uN6r3In3NS","GWqqXMojnP","9rlg9F6PT2","DG4sTaFFss","sqVrfyofH3",
-"J2mQi0Wr5y","YjB9tiwzGk","MmsIos4786","ReKEWXflUq","9y4lwCfgr3","lkMUAzz4ZU","55rfB9eoRc","pmeCdZzJHW","VerEAPb1pa","5nmWvaL6AJ",
-"W3VFHi7WMQ","XyPZNC2Irc","IKxdLJKWYR","aL6AJ0h1b1","e6e4zjeskS","SbRYyCK5W7","XyPZNrKDLJ","ulk41JRJQB","atef2Z4I1v","OxWIH5Mg9r",
-"16lHcIBe8k","blLA9x3LDe","5nmWvWreyP","F6PT2zY1GY","aFFssFLsph","0h1b1Ss0Zu","wiHrZWPmlx","oQ87rYf2Ec","DLhzMfcwDa","FPfSE0Wr5y",
-"vkCHHPb1pa","dhSuHS2Dfu","fFDrJzHF1q","dmoS7iqv4k","DQimpFwEJz","Ta8f6WaWsv","lm0pDtl72W","RACujsoy9t","Kr8ysVerEA","RsQUqEoToP",
-"1LB1LYOfrY","o8Uydjtn0X","tuDySi7WMQ","jzUqRsx5Gl","xReecM6qcG","lm0pD0PktI","x3LDe5nmWv","aez9yl83Ud","Q6LixnlaBy","lpF6WFPfSE",
-"Uvlv4qUJMd","FNYIMPYBf4","oGu6xzmLYD","Mm8siP6bcg","NOHsz5IhmG","F6PT2K20wK","WmadAJIqXi","FPfSEogLgc","uvf7AHzZT8","yEfy9RsQUq",
-"Vprf2Ss0Zu","GSQwjsqVrf","v2eC3dpe1v","Ss0ZucShY2","ulk41CIShG","SWfous7Mxk","AXpwERkQke","qQxHPXflUq","dQ586yluBx","fcJOyDz1R3",
-"YOfrYGXdoH","lH1kt1LB1L","cL0aEpvgjS","YjB9tCp3mZ","v8yFNChuy3","No0QblH1kt","ECMvURpBQm","gIYvEFVMxo","MmsIoTa8f6","TCgPp45cIH",
-"ThjNnyluBx","jzUqRcShY2","t98iWCp3mZ","lH1ktFhtgl","IjTwP0h1b1","4W0TlbZLvS","wiHrZ5nmWv","Nxx9V0PktI","VjCZq2hEEU","L7cGcMK07Y",
-"MaJQsOxWIH","lViBvWPmlx","JIqXiFVMxo","FwEJzJXljW","a00b5Q6Lix","55rfB7fsYM","VLTy6atef2","K4GS8QnJ1S","zz4ZU0ao3l","AIYUu3otm6",
-"l83Udk85Ae","FwEJzlj07Q","IKxdLydG8U","euZA5uJScX","CqqaDzz4ZU","Yh1hFazIWp","TCgPpGrDg7","h1zcHHP433","XyPZNCK5W7","Cfgr3SbRYy",
-"lm0pDS77LH","DLhzM8RCUA","5ZaEzPOUYS","Ul4a1Mm8si","8RCUACIShG","t59lRQssNC","nlaByzFgtB","tAOsrmX2GE","AXpwElkMUA","vOqCEuZPqg",
-"AIYUuAXpwE","e6e4zBGaQY","ni2v1Chuy3","gf8rISs0Zu","e6e4z0h1b1","K20wKjzUqR","VBjhzGSQwj","DG4sTMezSW","Cfgr3n1pmO","VNCPdksJby",
-"lCMxyU3yw5","uoStw7ku1p","fLNg84dEz6","qUJMdFPfSE","VerEA5Drn0","NAFuwgIYvE","aDGtS7hyVv","CdyBVhe9IA","IjTwPvOqCE","oQ87rpT8wu",
-"gtCA5B3qem","5NammDz1R3","QChxslpF6W","zQt6Qd7vjM","atef29eoRc","aez9yNAFuw","NOHszYOfrY","5drc6iKqhr","0KyfspiJSk","Q6LixQssNC",
-"WPmlx5iGN5","XflUqHzZT8","JRJQBiB08l","cShY2HfyNQ","tl72Wrz7Ut","5VZjSuupzk","Vprf20MR5X","8RCUANOHsz","F6PT2JXljW","55rfBOUqFM",
-"PYBf4FcWrW","Dz1R3ix74r","jiVBPJIqXi","ksJbyIKxdL","uTacx2Nslm","SmGzvgIYvE","fFDrJ9eoRc","jeskSRBhp0","PYBf4C2Irc","Pb1pa7lUXZ",
-"gtCA5k85Ae","JXljWFVMxo","ydG8U07n1c","8xEKzoGu6x","K4GS8xciqp","zz4ZUBCxeC","MmKGJMm8si","0PktIbgJAz","EdBKcPYBf4","s93MlQClRL",
-"uTacxo8Uyd","StlDJgf8rI","t98iWxXTI4","FcWrWgjUTu","xXTI4580YD","zmLYDFnPFB","IRh48Q6Lix","iB08lBFkb8","8xEKzRzaZA","5drc6uN6r3",
-"Cfgr3ru4UG","HlUbFtlILt","BGaQYmz8gx","SWfouSmGzv","uvf7AksJby","ulk41AgJHQ","y94nwpFrrl","l83Uduvf7A","FxX9qKASQ8","gf8rIuPX7G",
-"YOfrYpv0i7","8U2nUlH1kt","uAWypazIWp","jeskSd7vjM","VNCPd5IhmG","StlDJFxX9q","POUYS55rfB","6AFT0FxX9q","VIlwP0h1b1","lm0pDVIlwP",
-"BpYhVM6qcG","vOqCEIjTwP","JJs5mTwano","vLsmS16lHc","DG4sTRpBQm","a00b5Fhtgl","YjB9tGSQwj","rKDLJm4bxU","BbwgAvOqCE","aez9ySWfou",
-"2DREsZ4I1v","lH1ktYjB9t","zz4ZUhi5X7","7Ow5CS77LH","WreyPC2Irc","EOE1olweGy","G1RhSxciqp","2NslmCdyBV","FPfSEMmKGJ","qUJMdnlaBy",
-"jzUqRuN6r3","BFkb8ZuDtD","dmoS7BGaQY","FcWrWiB08l","C2Irc1LB1L","BGaQYS77LH","IRh48W7cTs","0PktIAXpwE","hYBCKoQ87r","0KyfsEOE1o",
-"NcICAzY1GY","L7cGchUTw7","In3NSO3iyQ","9y4lwzmLYD","kB5nPqaofN","ZhwG14dEz6","piJSkCxVEf","QClRLrhl0J","Ta8f6uupzk","dhSuH4QMc9",
-"t98iWFwEJz","WPmlxi3pyd","rKDLJAmdQd","Ss0Zu5IhmG","KASQ8b29RJ","fLNg8fmIK1","yluBxlkMUA","vkCHHOUqFM","OUYuFMojnP","NAFuw4dEz6",
-"rhl0JB3qem","tlILtQ6hMC","GSQwjjtn0X","ReKEW4dEz6","LbRTHFwEJz","JkzUnhi5X7","BFkb8uJScX","Chuy3djsrv","mz8gxHRxd8","WPmlxpFrrl",
-"iqv4kFjHXR","1j5L8CK5W7","Mm8si55rfB","jzUqRt59lR","a00b5uZPqg","9y4lwqUJMd","5VZjSRsQUq","5Mg9rSmGzv","djsrv1v5hH","BbwgADQimp",
-"8xEKzCfgr3","VjCZqD6rBy","jzUqRxXTI4","5ZaEzs7Mxk","zQt6Qi7WMQ","JkzUnWMiS3","ni2v1s93Ml","RzaZAjeskS","lViBvoGu6x","uoStwWPmlx",
-"9rlg9ciuWz","ZUnqtDQimp","7Ow5C4QMc9","AIYUujSjS3","qaofNO3iyQ","7X3uy1v5hH","dmoS75Namm","Y1mC0RmDcr","SmGzv5ZaEz","uPX7GNo0Qb",
-"0ao3lUvlv4","BFkb8580YD","JRJQBQClRL","5Drn0hYBCK","lj07QY1mC0","guMb8CK5W7","aDGtSNAFuw","JKWYRWreyP","Zv7z0RpBQm","sqVrfBGaQY",
-"Mm8sijiVBP","JkzUncShY2","rKDLJM3zXL","5drc67fsYM","5iGN5s4786","WmadAYOfrY","Cp3mZ7X3uy","Ta8f6gjUTu","S77LHKsjRK","pvgjSSjskQ",
-"RpBQmIn3NS","QYxC0FcWrW","Q6hMCzFgtB","3weIFCK5W7","uoStwBGaQY","xXTI4lH1kt","blLA9uoStw","Ss0ZuuZPqg","DcpWBhi5X7","zFgtBpWiOs",
-"CNHmvo8Uyd","8RCUACNHmv","SWfouhi5X7","pFrrlFcWrW","8TxD77X3uy","0PktIni2v1","aDGtSOUqFM","mz8gxGrDg7","9GXkXiwzGk","LDk6fiKqhr",
-"AgJHQatef2","uLtKsjtn0X","5Namm0Kyfs","OxWIH2DREs","v1HlnFjHXR","hi5X7jfREu","Rxrsm5Drn0","zqH0WlCMxy","Yh1hFPYBf4","2DREsjtn0X",
-"a00b5FPfSE","RmDcrCIShG","K4GS8v8yFN","U3yw5D6rBy","0ao3lEdBKc","W3VFHHlUbF","ogLgcRBhp0","2ZHdkxciqp","C2Ircs4786","0MR5XKZamH",
-"K4GS8uJScX","2TRI7lsQGo","piJSkTCgPp","xXTI4jzUqR","fqypyQbxXc","CdyBV16lHc","zbIYY07n1c","AkKTk16lHc","uLtKsIRh48","DQimpPOUYS",
-"S77LHQbxXc","FnPFBulk41","Chuy3Mkgy8","VIlwP618Di","HP433y94nw","2ZHdk4W0Tl","vkCHHtuDyS","XflUqaFFss","In3NSzQt6Q","taOXK0Kyfs",
-"v2eC3Q6hMC","o8UydbZLvS","VjCZqdhSuH","VIlwPPOUYS","JXljW8cVD3","29QAzfaHir","mX2GEdjsrv","y94nw8cVD3","Gv3FqG1RhS","0KyfscmXIX",
-"fmIK1P6bcg","HP433ReKEW","vOqCE4dEz6","tAOsrTwano","RpBQmi7WMQ","WaWsvSjskQ","AmdQdmX2GE","IBe8kFcWrW","8hJdtoQ87r","Waim6n8pJ9",
-"jtn0XXflUq","QbxXcStlDJ","JJs5mzQt6Q","XyPZNlkMUA","DG4sTEdBKc","9GXkXYOfrY","ulk41yEfy9","4W0Tls4786","MmKGJsoy9t","iwzGk0YAGH",
-"jS1ajVprf2","J2mQiRpBQm","GXdoH5ZaEz","fqypy8U2nU","FwEJzulk41","yToGWMGlTF","EdBKcQssNC","5iGN5yEfy9","okgRi3weIF","blLA9dQ586",
-"0MR5XeuZA5","nFqik1j5L8","0MR5XlweGy","Pb1paTXQ0Z","lm0pDYw2oU","jiVBPB3qem","xXTI4v1Hln","BbwgAv8yFN","PYBf4PYBf4","9iGoTFhtgl",
-"ulk41t59lR","WPmlxTa8f6","ogLgcuQIcz","S77LHlweGy","YOfrYUvlv4","AmdQdP6bcg","5IhmG0MR5X","7Ow5ClH1kt","JkzUn8RCUA","J2mQinlaBy",
-"aL6AJUlU3M","2ZHdkIBe8k","7X3uyCK5W7","zmLYDjeskS","618DiNxx9V","b29RJhE1Ql","lj07QpmeCd","ZuDtDjfREu","iKqhrlXFOB","tjQxshe9IA",
-"Cfgr31v5hH","HlUbFQYxC0","guMb8LewvM","pmeCd5Namm","DcpWByvOMI","2hEEUAOgEe","VerEAM3zXL","FVMxoCqqaD","AmdQdmz8gx","7fKYUgtCA5",
-"lXFOBHlUbF","ydG8UMmsIo","wDajXfcwDa","brhlQv1Hln","4W0TlzbIYY","sqVrffmIK1","he9IApv0i7","FxX9qChuy3","J2mQilpF6W","64s8NUlU3M",
-"P6bcg45cIH","mz8gxnFqik","7fsYMCdyBV","M6qcGNxx9V","ydG8UuoStw","45cIHuupzk","NhXduFPfSE","lH1ktjfREu","PYBf47Ow5C","tl72W0ao3l",
-"VjCZqO3iyQ","JKWYRzHF1q","580YDk85Ae","uZPqg8TxD7","9rlg94QMc9","rhl0JM6qcG","BFkb8UmaEv","gIYvEogLgc","FcWrWLbRTH","s478624ARF",
-"M3zXLIBe8k","M6qcGlViBv","dmoS7WDVWJ","FVMxoUl4a1","pWiOsi3pyd","Zv7z0Kr8ys","LewvMhSSvQ","pFrrlgf8rI","Pb1paJIqXi","D6rByBpYhV",
-"L7cGcdQ586","VLTy6oVQp6","0Wr5yChuy3","brhlQfmIK1","zHF1qgIYvE","RBhp09iGoT","0MR5XBpYhV","OUYuFogLgc","Nxx9VeuZA5","JKWYRHfyNQ",
-"MezSWzqH0W","n1pmOIn3NS","Kr8ysjfREu","yEfy9Ta8f6","OHaBz4dEz6","0ao3llweGy","wiHrZQ6Lix","RACujgdQsS","16lHcguMb8","O3iyQZzJHW",
-"lCMxyOUYuF","FcWrWPYBf4","ZJTXHzqH0W","S77LHuupzk","Waim6POUYS","KZamH5Namm","4dEz6hUTw7","8hJdtqaofN","ni2v1gtCA5","BpYhVs4786",
-"45cIHK20wK","MojnPCIShG","wiHrZ580YD","i7WMQC2Irc","Yf2EcDcpWB","lpF6Wd7vjM","pWiOsSmGzv","2NslmI7p2a","Ss0Zus7Mxk","zmLYDgf8rI",
-"yluBxNhXdu","24ARFDcpWB","5IhmGciuWz","vOqCEzQt6Q","aez9yDcpWB","ulk41uTacx","EOE1oNhXdu","iKqhr7Ow5C","euZA5IRh48","0BmCy5Namm",
-"JkzUnzz4ZU","ru4UGFjHXR","rhl0J7X3uy","D6rBy7ku1p","IRh48k85Ae","29QAzs93Ml","v1Hlnt98iW","djsrvQ6Lix","FnPFBTCgPp","RxrsmksJby",
-"v8yFNOz8yZ","16lHcYw2oU","cShY2rz7Ut","No0QblweGy","AIYUuKZamH","5VZjSi3pyd","6AFT0Twano","BFkb88FmFH","VjCZqJRJQB","W7cTs5ZaEz",
-"Yf2EchE1Ql","4dEz6Twano","GXdoHNhXdu","HzZT86AFT0","5ZaEzlsQGo","BGaQYVprf2","uZPqgqQxHP","7Ow5Ciqv4k","VNCPd45cIH","JKWYRHlUbF",
-"ciuWzWmadA","580YDydG8U","JRJQBulk41","RpBQmRBhp0","TXQ0ZDG4sT","OxWIHnFqik","aL6AJ7fKYU","nnP8oLewvM","KASQ8hE1Ql","GWqqXNhXdu",
-"NcICAFhtgl","cL0aEuN6r3","VLTy6Nxx9V","d85a9yofH3","ZJTXH580YD","wDajXUlU3M","StlDJlm0pD","gjUTuCIShG","lViBvChuy3","Q6hMCVLTy6",
-"uLtKs16lHc","EOE1oD6rBy","tl72WReKEW","euZA5C2Irc","xReec0h1b1","AmdQdYf2Ec","M6qcGhYBCK","O3iyQFcWrW","FLsphs4786","lpF6WuTacx",
-"hUTw7Ul4a1","jeskS4QMc9","zmLYDCK5W7","xciqpCxVEf","qaofNzFgtB","tvdkDnFqik","a00b5t98iW","Dz1R3i7WMQ","t59lRh1zcH","VerEAhE1Ql",
-"tlILtJKWYR","l83UdlCMxy","mz8gx16lHc","v2eC3JRJQB","yofH3Uvlv4","J2mQi4QMc9","UmaEvhUTw7","K20wKyofH3","FhtglQClRL","DQimpcL0aE",
-"Cfgr3v1Hln","CIShGYh1hF","5drc6ECMvU","Yh1hF16lHc","Uvlv4dmoS7","VIlwPCK5W7","oVQp6AOgEe","rz7UtoVQp6","t59lRpvgjS","5nmWvHP433",
-"Chuy3RpBQm","Kr8ysRsQUq","WmadAblLA9","uQIczdjsrv","kZANmSmGzv","JIqXim4bxU","7X3uycL0aE","5Drn0VLTy6","C2IrcSjskQ","2hEEU3otm6",
-"0h1b1o8Uyd","ZzJHWPYBf4","uvf7AIRh48","7ku1pPYBf4","J2mQiKZamH","JIqXiMkgy8","GWqqXDcpWB","t59lRyvOMI","HfyNQFnPFB","h1zcHXflUq",
-"3otm6ZJTXH","VerEAQClRL","uQIcz29QAz","0Wr5yb29RJ","MaJQssoy9t","hE1Ql7hyVv","KZamHNhXdu","618Dim4bxU","EoToPAXpwE","MojnPWDVWJ",
-"ciuWzMm8si","qQxHP48cHL","e6e4zqUJMd","ru4UGfqypy","o8Uyd64s8N","ulk41xciqp","oVQp6F6PT2","uLtKsOHaBz","9XyT9LbRTH","EdBKcCxVEf",
-"Yf2EcStlDJ","14FLRQnJ1S","s7MxkpWiOs","bgJAzlH1kt","ZUnqtlweGy","MmKGJChuy3","FPfSEjS1aj","Pb1pa9rlg9","FnPFBuoStw","GWqqXVLTy6",
-"FhtglbZLvS","uvf7ASjskQ","C2IrchYBCK","v1HlnVjCZq","bgJAzFnPFB","hUTw7cmXIX","brhlQQ6Lix","UmaEvpv0i7","QbxXcYOfrY","d85a9lsQGo",
-"jeskS5ZaEz","FVMxoFFDui","L7cGcWreyP","P6bcgcmXIX","Zv7z07ku1p","KASQ8DLhzM","MojnP2TRI7","ydG8Uaez9y","Oz8yZMezSW","LbRTHJIqXi",
-"uPX7G0h1b1","gtCA50Kyfs","blLA9GWqqX","9y4lwOUqFM","l83UdfcJOy","zY1GYNOHsz","TXQ0ZDz1R3","CdyBVSs0Zu","QClRLfmIK1","uZPqglsQGo",
-"PYBf41v5hH","5iGN5ZhwG1","7X3uyMGlTF","SmGzvgf8rI","jeskSWmadA","gtCA5t59lR","gdQsSbrhlQ","lH1ktStlDJ","rKDLJRsQUq","bgJAzJIqXi",
-"IjTwPZ4I1v","MojnPS77LH","J2mQiUvlv4","bgJAzUvlv4","zY1GYbrhlQ","2DREsOxWIH","DLhzMpFrrl","cShY2v2eC3","JKWYRAmdQd","vkCHHl83Ud",
-"QworuTCgPp","KASQ8aDGtS","ZJTXHBGaQY","5drc6cShY2","Ss0ZuydG8U","FwEJzzbIYY","pmeCdlpF6W","GWqqX0h1b1","tjQxsdpe1v","wDajX29QAz",
-"OxWIHFhtgl","KASQ8HRxd8","1LB1Ljtn0X","RkQkes93Ml","lweGyGrDg7","Twanom4bxU","WDVWJB3qem","uvf7AwDajX","sx5GlFPfSE","5Drn0qQxHP",
-"hSSvQuPX7G","pvgjSgjUTu","lH1ktY1mC0","6q6L97fKYU","pvgjSgtCA5","azIWplm0pD","0BmCySbRYy","v2eC3SWfou","aez9yrKDLJ","KZamHzFgtB",
-"EoToPh1zcH","uPX7GaFFss","1LB1LQClRL","n8pJ9bgJAz","LbRTHrhl0J","RxrsmwDajX","uPX7GjfREu","lH1ktWreyP","mX2GE29QAz","NhXduQYxC0",
-"3weIF8xEKz","v8yFNaez9y","cL0aEKASQ8","9eoRcSbRYy","OHaBzeuZA5","8FmFHSbRYy","pmeCdl83Ud","SWfouJRJQB","i7WMQnFqik","VNCPdEoToP",
-"zHF1qfqypy","K4GS8JkzUn","8xEKzxReec","oVQp6zbIYY","qaofNlXFOB","zbIYYZJTXH","ReKEWnnP8o","24ARF1j5L8","ZuDtDxXTI4","IRh48d85a9",
-"DG4sThSSvQ","OHaBzguMb8","uupzkrhl0J","aDGtS5VZjS","J2mQiL7cGc","MojnP5Drn0","B3qem5iGN5","F6PT2uZPqg","CIShGk85Ae","5nmWvBGaQY",
-"5IhmGxciqp","FhtgltvdkD","Chuy30h1b1","xXTI4Vprf2","2hEEUaFFss","lm0pDGXdoH","C2IrcPOUYS","ksJby2hEEU","QWxoTHfyNQ","ReKEWjfREu",
-"FhtglYjB9t","EoToP5IhmG","UmaEvMkgy8","9iGoToVQp6","RkQkelpF6W","P6bcgKZamH","LewvMa00b5","sqVrfO3iyQ","FnPFBNOHsz","YOfrYCdyBV",
-"rhl0JRmDcr","UlU3MuJScX","qaofNrKDLJ","jS1ajhUTw7","14FLRiKqhr","aez9yCNHmv","rz7UtBbwgA","7Ow5CJ2mQi","tuDySJJs5m","Ss0ZuHP433",
-"uvf7AyvOMI","uPX7GRBhp0","Pb1paAkKTk","pFrrllweGy","GXdoH4W0Tl","3otm6Q6Lix","7fsYMYjB9t","lkMUAn8pJ9","BCxeCvOqCE","FVMxopmeCd",
-"JRJQBzHF1q","AgJHQksJby","JRJQBiKqhr","GXdoHJJs5m","0BmCybgJAz","sx5GldmoS7","jS1aj7ku1p","24ARF7hyVv","lm0pDpmeCd","48cHLIBe8k",
-"MmKGJs93Ml","BpYhVuZPqg","aFFsstAOsr","AOgEeKZamH","l83UdydG8U","YjB9tAXpwE","Cp3mZRpBQm","GSQwjtuDyS","oGu6xUlU3M","Cp3mZdpe1v",
-"QbxXcP6bcg","oGu6xVIlwP","jiVBPMmsIo","S77LHIBe8k","xReeciB08l","okgRi0Wr5y","S77LHoGu6x","hYBCKKsjRK","BFkb8ni2v1","8TxD7PYBf4",
-"aFFss0h1b1","O3iyQksJby","QClRLTXQ0Z","8TxD7IKxdL","VjCZqxXTI4","GXdoHi3pyd","9rlg9lViBv","StlDJVBjhz","rKDLJnlaBy","blLA9QnJ1S",
-"C2IrcAgJHQ","QworuYw2oU","JkzUnKZamH","iB08l5VZjS","djsrvdpe1v","M6qcG7fKYU","hUTw7y94nw","pvgjSL7cGc","WaWsvEoToP","LbRTHd85a9",
-"lkMUApWiOs","ZUnqtUmaEv","YjB9td85a9","RxrsmDcpWB","BpYhV5drc6","uZPqgwiHrZ","HRxd8hYBCK","VjCZqGSQwj","1LB1L7fsYM","2DREsPYBf4",
-"WmadAk85Ae","9XyT9BbwgA","AOgEeblLA9","7fsYMs7Mxk","5VZjSNcICA","fcwDa8hJdt","ZzJHWksJby","pWiOs8cVD3","QYxC0uPX7G","8U2nU0h1b1",
-"iwzGkvLsmS","5Drn0d85a9","euZA5MmKGJ","sx5GluAWyp","MmKGJPb1pa","TCgPp2Nslm","dhSuHNhXdu","zz4ZUIRh48","ulk41k85Ae","Kr8ysuQIcz",
-"CIShGS2Dfu","5drc6OHaBz","HP433mz8gx","SbRYyjS1aj","WDVWJFxX9q","ulk416q6L9","BpYhVJXljW","Kr8ysJKWYR","FFDui5iGN5","9rlg9UmaEv",
-"64s8Natef2","Yw2oUOxWIH","ulk4129QAz","B3qemOxWIH","FhtglQChxs","NOHsz7hyVv","7ku1psx5Gl","SjskQzY1GY","cShY2Ul4a1","Mkgy8ZhwG1",
-"vkCHHrhl0J","ThjNnRpBQm","5VZjSMmsIo","24ARFyluBx","2ZHdkPYBf4","Z4I1v0YAGH","5Namm2hEEU","9GXkX6q6L9","2hEEUokgRi","zqH0W9eoRc",
-"fLNg88U2nU","4dEz6i7WMQ","Oz8yZ5Mg9r","4W0TlcShY2","W7cTsZhwG1","1j5L8mz8gx","K20wKnlaBy","9XyT9CNHmv","WMiS3FVMxo","aFFss7lUXZ",
-"Dz1R3Gv3Fq","lweGyt98iW","l83UdJRJQB","J2mQijSjS3","GXdoHOHaBz","okgRia00b5","ru4UGVjCZq","kZANmv8yFN","uPX7G5Namm","YjB9tFcWrW",
-"0MR5XfmIK1","okgRi1j5L8","pT8wuFPfSE","MezSWl83Ud","nlaByuupzk","fcwDanFqik","JKWYRThjNn","0Wr5yQ6hMC","lViBvQClRL","jiVBPiwzGk",
-"8hJdtn1pmO","BGaQYcmXIX","Zv7z0iB08l","I7p2aDG4sT","618Dilm0pD","fFDrJWMiS3","BpYhV1v5hH","9XyT9yEfy9","yvOMIfcwDa","Y1mC0FxX9q",
-"6q6L9fcwDa","uZPqg9iGoT","k85AeQworu","In3NS16lHc","suY4xQ6Lix","ciuWz5iGN5","ZhwG1i3pyd","Cp3mZ24ARF","UlU3MSWfou","jfREuAXpwE",
-"WPmlxjzUqR","zHF1qZ4I1v","WDVWJpFrrl","2TRI74dEz6","Q6LixSjskQ","zFgtBt98iW","pWiOsFhtgl","GWqqXCqqaD","QWxoTWPmlx","EdBKcRzaZA",
-"DG4sTU3yw5","8TxD75nmWv","7X3uy9XyT9","NcICAZUnqt","prNT65IhmG","aL6AJwiHrZ","X6PinP6bcg","In3NSWaim6","CNHmvF6PT2","Mkgy8vOqCE",
-"FVMxopiJSk","Ul4a19iGoT","BCxeCRBhp0","cShY22hEEU","yToGWyofH3","48cHL5VZjS","x3LDeDLhzM","euZA548cHL","uQIczEoToP","AXpwEuoStw",
-"ZhwG1bZLvS","xciqp2TRI7","0MR5XhE1Ql","2TRI7yvOMI","jfREuO3iyQ","tAOsr2TRI7","JRJQBOHaBz","M6qcGVLTy6","uPX7GP6bcg","KZamHhi5X7",
-"DQimpyToGW","M3zXLCIShG","FhtglTwano","ni2v1HlUbF","6q6L9GSQwj","s47866q6L9","dpe1vksJby","HzZT8OUYuF","RxrsmUl4a1","jS1ajHlUbF",
-"Zv7z0OxWIH","uoStwDz1R3","GSQwjDcpWB","GSQwjo8Uyd","OHaBzCdyBV","WMiS3jeskS","xXTI4VIlwP","ThjNnzqH0W","zY1GYW3VFH","No0QbC2Irc",
-"MGlTFiqv4k","hE1QllXFOB","2Yz7EVerEA","3otm68hJdt","ZhwG1m4bxU","5nmWvOUqFM","oVQp6v8yFN","m4bxUQ6hMC","U3yw51LB1L","taOXKFGzgp",
-"FGzgpYf2Ec","pWiOsDQimp","QworuuLtKs","IKxdLNo0Qb","2hEEUZ4I1v","yluBxdmoS7","HlUbFW7cTs","OUYuF4dEz6","7Ow5CRBhp0","dpe1vG1RhS",
-"29QAzuPX7G","gjUTufaHir","Cfgr39GXkX","NcICAY1mC0","JIqXixXTI4","16lHc5VZjS","iB08lWaWsv","HP433zQt6Q","VerEAhYBCK","jiVBP2Yz7E",
-"QbxXcThjNn","MezSWSs0Zu","v8yFN0ao3l","Dz1R3JRJQB","iwzGkCqqaD","aDGtSAkKTk","FhtglUl4a1","pT8wu9GXkX","RACujFLsph","xciqpzmLYD",
-"FjHXRiwzGk","zHF1qZhwG1","bgJAzHP433","fmIK1Fhtgl","t59lRLbRTH","FnPFB9y4lw","gIYvE2hEEU","MK07YF6PT2","Nxx9V14FLR","P6bcgL7cGc",
-"he9IAThjNn","8U2nUVprf2","M3zXLSjskQ","GrDg7ZUnqt","6q6L9kZANm","NOHszt98iW","7fsYMRsQUq","9XyT9AIYUu","618DiVerEA","FLsphKZamH",
-"Yw2oUhYBCK","0PktIlXFOB","SbRYyy94nw","VLTy6Q6Lix","JKWYRuN6r3","iKqhrmz8gx","9eoRcRxrsm","h1zcHFjHXR","blLA9bZLvS","FjHXR4W0Tl",
-"fmIK1OHaBz","AOgEeYf2Ec","S77LHlm0pD","AIYUu55rfB","Dz1R3d7vjM","Nxx9VM3zXL","uTacxlm0pD","FVMxoxXTI4","SjskQ580YD","tlILt8U2nU",
-"9XyT9D6rBy","CNHmvNOHsz","G1RhSyToGW","i7WMQDz1R3","Oz8yZDG4sT","uvf7AChuy3","ulk41FGzgp","8xEKzUl4a1","In3NSTa8f6","s7MxkF6PT2",
-"ZJTXHpFrrl","uPX7GzHF1q","FGzgppmeCd","WmadABFkb8","J2mQiBGaQY","jzUqRJkzUn","Q6hMCuupzk","9GXkXgtCA5","FPfSEfqypy","Chuy3Yw2oU",
-"07n1cix74r","NcICATCgPp","TwanoPb1pa","45cIHKsjRK","1v5hHhE1Ql","uAWypEOE1o","i3pydDG4sT","07n1cM3zXL","MmKGJJRJQB","IKxdL48cHL",
-"Ss0ZudQ586","brhlQqUJMd","RzaZAdhSuH","dpe1vKZamH","618DiRzaZA","O3iyQVLTy6","K20wKlweGy","lm0pDDLhzM","GrDg7JkzUn","jtn0XHP433",
-"xReecNAFuw","hYBCKzbIYY","zY1GYuQIcz","lsQGoRBhp0","ECMvUChuy3","MezSWyofH3","0Wr5yWPmlx","uAWypNhXdu","fcwDaSs0Zu","tuDySRACuj",
-"oQ87raFFss","WDVWJFhtgl","4W0Tlgf8rI","QbxXcRBhp0","YjB9tWmadA","16lHc8hJdt","ReKEWrKDLJ","FwEJzBFkb8","3otm6hE1Ql","I7p2aFFDui",
-"MmsIoRACuj","AmdQdMK07Y","vOqCEX6Pin","VjCZquAWyp","W7cTspv0i7","QClRLx3LDe","WaWsvpWiOs","jtn0XFFDui","GWqqXYf2Ec","CNHmv8hJdt",
-"yofH3Cp3mZ","EOE1oB3qem","ydG8UpWiOs","vLsmSy94nw","WreyPdQ586","cmXIXqUJMd","8RCUA64s8N","5VZjSFhtgl","t98iWqaofN","5ZaEzNhXdu",
-"8TxD7Cfgr3","4W0TlVLTy6","n8pJ9MezSW","YOfrY3otm6","45cIHMGlTF","lCMxy2DREs","fcJOyqUJMd","2ZHdkhUTw7","NhXduAgJHQ","MojnPC2Irc",
-"wDajXciuWz","yofH3n1pmO","7hyVvxciqp","JKWYRvLsmS","U3yw5djsrv","lweGy2ZHdk","jfREu9y4lw","HRxd8wDajX","QChxsBGaQY","HfyNQbgJAz",
-"FLsphAIYUu","9GXkXVNCPd","jiVBP9y4lw","8xEKz0YAGH","v1Hln8U2nU","K4GS80MR5X","i3pydzqH0W","StlDJQYxC0","kB5nPiB08l","gtCA5Kr8ys",
-"pv0i7YOfrY","aez9yqUJMd","7ku1pFcWrW","fcJOy618Di","8RCUAU3yw5","tl72W0MR5X","hUTw71j5L8","JkzUnFNYIM","a00b5Yh1hF","v8yFNjiVBP",
-"X6PinqaofN","WmadA1j5L8","AgJHQNxx9V","FnPFBM3zXL","QYxC0Ul4a1","sx5GluN6r3","nFqik5Namm","QYxC0J2mQi","NcICArKDLJ","ksJbyJRJQB",
-"B3qemX6Pin","cmXIXVerEA","QWxoTfcwDa","Cp3mZCxVEf","AgJHQFVMxo","QChxszFgtB","2hEEUYf2Ec","oVQp6W3VFH","5ZaEzhYBCK","8hJdtulk41",
-"Uvlv4LDk6f","i7WMQOxWIH","FxX9q4dEz6","XflUqCdyBV","7ku1p6AFT0","4dEz6jeskS","7fKYUDcpWB","bgJAzW3VFH","l83UdBCxeC","zQt6QAXpwE",
-"rKDLJHzZT8","Kr8yszHF1q","L7cGcStlDJ","uTacxzY1GY","TCgPpVerEA","Z4I1vtl72W","ix74rTa8f6","soy9t07n1c","9eoRcKsjRK","vkCHHyluBx",
-"7fKYUvOqCE","hE1Qli3pyd","EdBKcEoToP","MK07YCIShG","x3LDeQChxs","CK5W7n1pmO","8RCUAUlU3M","fcwDaUlU3M","dhSuHn8pJ9","iqv4kh1zcH",
-"MezSWAOgEe","hE1QlWmadA","CK5W72TRI7","lweGyZv7z0","fLNg8RkQke","0Wr5ySjskQ","lm0pDGrDg7","BFkb8C2Irc","cShY25Mg9r","0YAGHFcWrW",
-"zmLYD8FmFH","VerEADz1R3","lpF6WOUYuF","iKqhrCfgr3","Y1mC0Vprf2","ksJbyfcwDa","fmIK1k85Ae","7ku1plCMxy","BGaQYQbxXc","tvdkDfmIK1",
-"Zv7z0Cp3mZ","0h1b1gf8rI","FwEJzjeskS","CIShGi3pyd","SbRYy0BmCy","pWiOsQChxs","lj07QpAhR1","gf8rI0YAGH","5Drn0BFkb8","M3zXL1LB1L",
-"HzZT8blLA9","Dz1R30PktI","BpYhVuN6r3","7fKYUX6Pin","zbIYYyEfy9","RzaZAlH1kt","BCxeCKZamH","NcICAgtCA5","7X3uyix74r","K4GS8AXpwE",
-"ReKEWFwEJz","uAWypMkgy8","FVMxovkCHH","Q6hMCDG4sT","i7WMQwDajX","6q6L9DG4sT","NAFuwNxx9V","aL6AJZJTXH","6q6L9lsQGo","pFrrl4W0Tl",
-"MK07Yjtn0X","Zv7z0VerEA","FNYIMCp3mZ","d85a9HP433","F6PT2Y1mC0","uTacxx3LDe","Dz1R3s7Mxk","7hyVvJIqXi","Yw2oUxciqp","X6PinSmGzv",
-"HRxd8tuDyS","RkQkeVBjhz","5NammydG8U","guMb8Twano","I7p2aHlUbF","dQ586tAOsr","FxX9qTa8f6","M3zXLru4UG","dmoS7ulk41","lsQGoSWfou",
-"s4786No0Qb","TCgPp9y4lw","MGlTFlj07Q","n1pmOCdyBV","QChxsoGu6x","5Mg9rMm8si","yvOMIs93Ml","hSSvQ2TRI7","UlU3MYOfrY","atef2BbwgA",
-"CdyBVoGu6x","b29RJGXdoH","HzZT8zmLYD","lH1ktaDGtS","dpe1vZuDtD","3weIFSbRYy","48cHLbgJAz","RzaZAzHF1q","kZANmhi5X7","t59lRs93Ml",
-"MmsIoqQxHP","rz7Utaez9y","tvdkDMmKGJ","ogLgcjeskS","t59lRxXTI4","y94nwQYxC0","7fKYUmX2GE","KZamH1LB1L","JXljWlkMUA","AmdQdAgJHQ",
-"xXTI4euZA5","t59lR7Ow5C","ogLgcuTacx","yluBxCfgr3","SbRYyJJs5m","pv0i7OHaBz","ZUnqtqUJMd","lpF6WydG8U","DcpWBJIqXi","fqypyv2eC3",
-"dmoS7GrDg7","NcICAxReec","GrDg7OxWIH","tl72WFPfSE","BGaQYcL0aE","d7vjMxXTI4","SjskQK4GS8","jzUqRMaJQs","48cHLECMvU","piJSkRBhp0",
-"GSQwjhYBCK","KZamHqaofN","ECMvUdQ586","pAhR11j5L8","jS1ajMezSW","BFkb8QbxXc","wDajXsoy9t","07n1c8FmFH","FjHXRtjQxs","pFrrlaez9y",
-"kZANmMaJQs","uN6r3Kr8ys","IjTwPoGu6x","gdQsSTXQ0Z","uupzkHRxd8","nlaByokgRi","FNYIMv8yFN","EdBKcDQimp","0h1b1cQOnv","JXljWSs0Zu",
-"29QAzQbxXc","Cp3mZQnJ1S","EOE1oQssNC","Vprf2Gv3Fq","lpF6WqaofN","cmXIXMaJQs","MezSWdpe1v","ix74r24ARF","cmXIXzQt6Q","NAFuwcQOnv",
-"OxWIHfqypy","nlaBysuY4x","BGaQYzz4ZU","Vprf2vOqCE","8U2nUUmaEv","QWxoTQssNC","jS1ajVerEA","TwanoZUnqt","n1pmOTwano","he9IA4QMc9",
-"WaWsv8cVD3","XflUqeuZA5","Waim6Kr8ys","nnP8o48cHL","B3qemMaJQs","Chuy3Q6hMC","WreyPCp3mZ","5NammxReec","MaJQs8TxD7","2Yz7EvOqCE",
-"Vprf2OHaBz","CNHmvKZamH","RACujQworu","uTacxy94nw","29QAzJJs5m","ydG8UtjQxs","aFFsss4786","Yw2oUTCgPp","rKDLJd7vjM","cQOnv5ZaEz",
-"14FLRzY1GY","W3VFHprNT6","uLtKs5ZaEz","TwanoydG8U","EdBKcOxWIH","pFrrlCfgr3","TwanocShY2","0Wr5ytaOXK","tuDySU3yw5","Q6hMCHfyNQ",
-"brhlQ618Di","he9IA8cVD3","3otm6XflUq","nlaBy1LB1L","ix74roVQp6","2Yz7EJ2mQi","WMiS3s93Ml","yvOMIW3VFH","16lHc5iGN5","5ZaEzVNCPd",
-"Cfgr3lweGy","K4GS88FmFH","NOHsz5Namm","JIqXiI7p2a","SWfoulViBv","Q6hMCJ2mQi","K4GS8o8Uyd","zqH0WJ2mQi","HP433kZANm","2DREsDLhzM",
-"ru4UGRmDcr","prNT69iGoT","MojnPD6rBy","DQimppWiOs","WMiS3JKWYR","dhSuHEdBKc","soy9t29QAz","8U2nU8U2nU","Dz1R3uoStw","LewvM0ao3l",
-"L7cGcEOE1o","zqH0WyToGW","nlaByuAWyp","5iGN5pvgjS","MojnPQbxXc","Nxx9V9rlg9","4QMc9FFDui","IKxdLW7cTs","MmKGJ2Nslm","Ta8f6euZA5",
-"m4bxUDcpWB","WmadAVNCPd","prNT6AOgEe","IRh48NcICA","djsrvYOfrY","GSQwjOHaBz","HzZT8Gv3Fq","DLhzMm4bxU","QClRLksJby","gIYvElkMUA",
-"7fKYUCK5W7","S77LH2Yz7E","7fKYUsqVrf","BCxeC9y4lw","kZANm2DREs","MK07YdhSuH","7X3uyK4GS8","BGaQYQChxs","JJs5mv1Hln","vOqCEWDVWJ",
-"TCgPpStlDJ","8hJdtF6PT2","uupzkxciqp","QssNCFNYIM","D6rByG1RhS","uQIczhSSvQ","5Drn0Ss0Zu","VjCZquQIcz","NAFuwnnP8o","GWqqXcQOnv",
-"GSQwjIKxdL","GrDg75Namm","CdyBVkB5nP","djsrvFjHXR","HRxd8GSQwj","oGu6xs7Mxk","Yf2EcCp3mZ","mX2GExciqp","iwzGk5IhmG","RzaZAtlILt",
-"FGzgp5Mg9r","CdyBVv8yFN","FhtglFcWrW","KsjRKaDGtS","1j5L8uTacx","dmoS7JKWYR","C2IrcCxVEf","lkMUAt59lR","t59lR5Mg9r","Oz8yZ48cHL",
-"cL0aEEdBKc","uupzkzmLYD","uAWypogLgc","IBe8ko8Uyd","45cIH9XyT9","lCMxytuDyS","uvf7A5VZjS","CqqaDix74r","gdQsSJJs5m","vLsmS0Kyfs",
-"CK5W7VerEA","QnJ1SK20wK","FxX9qQssNC","ciuWzciuWz","YjB9tVIlwP","Zv7z0RmDcr","AIYUui7WMQ","n8pJ9zqH0W","NcICAuupzk","AkKTkd7vjM",
-"8cVD3zHF1q","WPmlxKr8ys","NOHsz48cHL","nnP8oFGzgp","t59lRJ2mQi","StlDJYOfrY","AmdQdBpYhV","o8UydHzZT8","zHF1qFVMxo","24ARFVNCPd",
-"POUYSMojnP","h1zcHG1RhS","iB08l7Ow5C","Ul4a1sx5Gl","CxVEfMezSW","0ao3lIRh48","45cIH0YAGH","RzaZAsx5Gl","EdBKc0PktI","m4bxUQClRL",
-"pmeCdyvOMI","oVQp6lXFOB","tl72WGXdoH","MmsIoxXTI4","Oz8yZoQ87r","64s8N3weIF","QClRLtuDyS","okgRifFDrJ","K20wKm4bxU","WPmlx3weIF",
-"BGaQYYw2oU","QnJ1SFGzgp","Ta8f6FLsph","TXQ0ZpAhR1","kZANm6AFT0","lCMxyC2Irc","FLsphogLgc","6AFT0hUTw7","MaJQszQt6Q","SbRYy2TRI7",
-"Mm8siVLTy6","Z4I1vnlaBy","5ZaEz0YAGH","POUYSFjHXR","MmsIo9XyT9","L7cGcs7Mxk","d7vjMoVQp6","rz7UtGSQwj","0YAGHNAFuw","8cVD3dhSuH",
-"i3pyd6AFT0","v8yFNNcICA","v1Hln6AFT0","he9IAZhwG1","xciqp64s8N","Ul4a1ZzJHW","taOXK9y4lw","LDk6fBpYhV","5nmWvfLNg8","Ss0ZuMGlTF",
-"cmXIXdQ586","48cHLMmsIo","8cVD3gdQsS","8xEKz9rlg9","t98iWHfyNQ","UlU3MRmDcr","AkKTk8cVD3","1v5hHlpF6W","RACujCqqaD","Kr8ysMaJQs",
-"W3VFH0Wr5y","hUTw77fsYM","jS1ajYh1hF","tAOsrBGaQY","LbRTHAIYUu","XyPZNjiVBP","QnJ1SvOqCE","JIqXiciuWz","DG4sTrz7Ut","pvgjSWPmlx",
-"Oz8yZkB5nP","jeskSMojnP","B3qem9y4lw","8RCUABCxeC","IRh48HP433","VjCZqlH1kt","t98iWa00b5","In3NSSmGzv","TwanoCfgr3","Q6LixIn3NS",
-"x3LDeSmGzv","AOgEeFcWrW","a00b5G1RhS","FxX9q0MR5X","bgJAzFcWrW","G1RhSiKqhr","vLsmSVerEA","0h1b1In3NS","uPX7G8cVD3","QbxXcrhl0J",
-"QbxXctaOXK","gtCA5M3zXL","EoToPb29RJ","uQIczGrDg7","QWxoTfFDrJ","7lUXZ9y4lw","SWfou7Ow5C","atef245cIH","HlUbFt98iW","7lUXZzHF1q",
-"HP4331v5hH","aL6AJuvf7A","WPmlxJ2mQi","FwEJzsoy9t","48cHLjtn0X","Kr8ysY1mC0","vOqCEECMvU","lsQGomz8gx","jeskSJ2mQi","14FLRlXFOB",
-"lkMUAb29RJ","JJs5m16lHc","lkMUAciuWz","IRh48uJScX","FLsphSs0Zu","JRJQBTCgPp","dQ586iqv4k","a00b5XyPZN","guMb8IKxdL","vLsmSQworu",
-"JRJQBUvlv4","rKDLJuJScX","8U2nUMezSW","AkKTknFqik","xXTI4SmGzv","yEfy9lViBv","16lHc24ARF","sqVrfWMiS3","vOqCENxx9V","hE1QlQChxs",
-"WaWsvbgJAz","QnJ1SReKEW","faHirVerEA","hYBCKdhSuH","pWiOsuoStw","FGzgp7hyVv","Ul4a1RkQke","TwanoLewvM","C2IrcWMiS3","Mm8sivkCHH",
-"HP433brhlQ","KsjRKdpe1v","WreyPFFDui","sx5GllsQGo","uN6r38FmFH","5VZjS5drc6","BGaQYJ2mQi","0BmCy8xEKz","QssNCrhl0J","yvOMI8U2nU",
-"Kr8ysGrDg7","dQ586uN6r3","IRh48ZJTXH","WmadAlH1kt","s93MlReKEW","POUYSFPfSE","tlILtuJScX","POUYSzQt6Q","KsjRKDQimp","Yf2Ecs4786",
-"AOgEeWPmlx","ZhwG1sx5Gl","In3NSLewvM","VjCZqMkgy8","F6PT2DLhzM","fcJOynlaBy","tvdkDJkzUn","t59lRFjHXR","0MR5XWmadA","Cfgr39iGoT",
-"Kr8ys2TRI7","MK07Y0Wr5y","WmadAgf8rI","fmIK19y4lw","FwEJzuZPqg","n8pJ9NAFuw","WPmlx64s8N","lH1ktUlU3M","DQimpzz4ZU","X6PindQ586",
-"J2mQidmoS7","VLTy645cIH","WaWsvNcICA","zHF1qCK5W7","RBhp00BmCy","h1zcHUmaEv","atef24QMc9","VLTy6a00b5","cShY2B3qem","qUJMdeuZA5",
-"Chuy3i7WMQ","VjCZqpAhR1","pT8wuRmDcr","v2eC3fcwDa","NAFuwRmDcr","0PktIhUTw7","P6bcgb29RJ","JkzUniqv4k","ZUnqt8RCUA","2hEEUuAWyp",
-"s4786GSQwj","X6Pin7fKYU","zqH0WlweGy","kB5nP618Di","HP433uoStw","BFkb8SWfou","WPmlxt59lR","s93Ml618Di","KZamHFNYIM","y94nwxciqp",
-"AkKTkTCgPp","h1zcHfLNg8","JIqXifcJOy","l83UdblLA9","16lHcUvlv4","ZUnqtfcJOy","okgRi45cIH","MmsIorhl0J","qUJMdVjCZq","MaJQshSSvQ",
-"tuDySBFkb8","LDk6fFPfSE","Y1mC0MGlTF","gdQsSd7vjM","sqVrf5IhmG","JJs5mFFDui","uN6r3rKDLJ","uTacxaL6AJ","Waim6WreyP","FFDuisx5Gl",
-"8cVD3QWxoT","tjQxsJkzUn","AIYUuAOgEe","Kr8ysyofH3","cmXIXMmsIo","0h1b1UmaEv","Cfgr3RpBQm","lXFOBXflUq","Zv7z0Twano","JXljWiwzGk",
-"EoToPrz7Ut","AOgEemX2GE","FhtglfLNg8","RpBQmHfyNQ","NhXdu8hJdt","lXFOBgtCA5","ZJTXHL7cGc","FcWrW7X3uy","SbRYyzY1GY","FVMxo4W0Tl",
-"QbxXcQWxoT","ni2v1ZUnqt","Ul4a1jeskS","jiVBPni2v1","SWfouuLtKs","B3qemSs0Zu","3otm6zz4ZU","lkMUAKASQ8","Yh1hFYOfrY","fqypyGXdoH",
-"Vprf2Qworu","WDVWJ2TRI7","azIWp2Nslm","Nxx9Vfqypy","No0QbbZLvS","8U2nUK20wK","O3iyQHRxd8","Yf2EcIKxdL","IBe8k14FLR","VjCZq0BmCy",
-"wiHrZyToGW","8xEKzcL0aE","soy9tiB08l","ZzJHWlkMUA","POUYSlsQGo","ix74rRpBQm","Uvlv4pFrrl","Mm8siM6qcG","jS1aja00b5","dhSuHSjskQ",
-"yluBx45cIH","RzaZAn1pmO","HfyNQpT8wu","RpBQm8U2nU","cL0aEZJTXH","n1pmOMGlTF","s4786NcICA","BCxeCFVMxo","fFDrJIRh48","FhtglBGaQY",
-"QClRLtlILt","zFgtBMojnP","xciqpa00b5","VLTy6dQ586","mX2GEFPfSE","oGu6xsx5Gl","lm0pDsuY4x","RsQUqFVMxo","0KyfsFPfSE","RzaZAiKqhr",
-"7lUXZNcICA","QChxsOHaBz","Cp3mZydG8U","oVQp6l83Ud","tlILt9rlg9","nnP8o1v5hH","y94nwVNCPd","1j5L8vkCHH","VBjhzYh1hF","DQimpzQt6Q",
-"t98iWoGu6x","pAhR1NAFuw","MezSWCdyBV","taOXKGWqqX","AgJHQpmeCd","MK07YpmeCd","gjUTuqUJMd","BpYhVyluBx","WaWsvd7vjM","rhl0JaDGtS",
-"2hEEUulk41","lkMUA0Wr5y","MK07YRmDcr","8RCUAuTacx","9XyT97fsYM","fmIK1gjUTu","1LB1LWaWsv","QssNC2ZHdk","HzZT82hEEU","WPmlxaL6AJ",
-"VIlwPBpYhV","xXTI4fqypy","Dz1R3oVQp6","RsQUq5drc6","Waim6P6bcg","pWiOsfLNg8","zbIYYfaHir","K4GS8DcpWB","tjQxsjSjS3","i3pydXflUq",
-"FwEJzECMvU","8hJdtuoStw","EoToPWmadA","5IhmGcQOnv","7lUXZ1LB1L","wDajXt98iW","3otm6Ul4a1","FFDui48cHL","NAFuwazIWp","WreyPfFDrJ",
-"W3VFHZzJHW","fcwDaWmadA","7lUXZlpF6W","2NslmK4GS8","DcpWBRBhp0","B3qemQbxXc","jtn0XSWfou","iqv4kO3iyQ","TwanoVjCZq","4dEz6EdBKc",
-"uQIczHzZT8","tl72WZuDtD","W3VFHbrhlQ","Z4I1vrKDLJ","euZA5X6Pin","TXQ0ZNhXdu","Zv7z0qaofN","Uvlv4uQIcz","ZUnqtZUnqt","uN6r3QChxs",
-"tAOsr0h1b1","b29RJkB5nP","9iGoTmz8gx","NOHszuPX7G","lViBvuN6r3","uAWypgjUTu","8RCUAydG8U","OUYuF7X3uy","1v5hHYf2Ec","rKDLJG1RhS",
-"zY1GYm4bxU","lCMxy6q6L9","ydG8U5Drn0","yofH3cQOnv","IKxdLFNYIM","QworuvLsmS","aez9ydjsrv","h1zcHdhSuH","Q6hMCd7vjM","rhl0JqUJMd",
-"i3pyd0ao3l","AXpwEBFkb8","Ss0ZuhE1Ql","Q6LixBbwgA","29QAzuN6r3","ZuDtD5Mg9r","No0QbDz1R3","oGu6xpiJSk","HRxd8suY4x","StlDJ0MR5X",
-"FVMxocShY2","oVQp6QnJ1S","dmoS71LB1L","iqv4k4W0Tl","4QMc9OxWIH","xReec7lUXZ","uZPqg5ZaEz","SbRYyl83Ud","AmdQdQnJ1S","2ZHdk5drc6",
-"i3pydFwEJz","kB5nPMm8si","fmIK1kB5nP","BFkb8brhlQ","FGzgppWiOs","P6bcgIn3NS","9XyT9xReec","AXpwENhXdu","NhXdu6q6L9","5drc63weIF",
-"kZANmCNHmv","pmeCd0MR5X","yofH3uLtKs","uJScXlm0pD","NAFuw580YD","yToGWvOqCE","48cHL6AFT0","TXQ0ZW7cTs","5VZjSM3zXL","QbxXcuLtKs",
-"45cIHpAhR1","45cIHt98iW","taOXKbrhlQ","0Wr5yyofH3","ECMvUP6bcg","QssNCBpYhV","9y4lwbZLvS","Vprf2zQt6Q","RACujQnJ1S","FjHXRSmGzv",
-"rz7UtZ4I1v","Twano48cHL","GSQwja00b5","8FmFHVjCZq","i3pydrKDLJ","uJScXGWqqX","prNT6v8yFN","l83Ud6AFT0","ZhwG18hJdt","Vprf2iB08l",
-"Cp3mZs7Mxk","yluBxJXljW","VjCZq580YD","F6PT2AIYUu","3otm6P6bcg","BGaQY7hyVv","5VZjS6AFT0","Pb1paqQxHP","Oz8yZStlDJ","5drc6FVMxo",
-"Y1mC0pmeCd","jzUqRGXdoH","blLA9yofH3","lj07QDz1R3","AOgEe2Yz7E","Vprf22DREs","D6rByni2v1","WmadAFPfSE","tlILtAIYUu","IBe8k7Ow5C",
-"IjTwPOz8yZ","7lUXZAmdQd","YOfrYiB08l","HlUbFsx5Gl","jfREuStlDJ","hYBCK9eoRc","lweGyjSjS3","sx5GlPOUYS","VIlwPZhwG1","Kr8ys5Mg9r",
-"h1zcHe6e4z","StlDJDQimp","iKqhrVjCZq","tuDySM6qcG","SbRYygdQsS","qaofNfFDrJ","jfREuMojnP","WDVWJtl72W","azIWpvLsmS","DLhzMhSSvQ",
-"lViBv6AFT0","0Kyfsgf8rI","AgJHQZJTXH","ru4UGjSjS3","suY4x0Wr5y","gIYvEDz1R3","lXFOBFVMxo","0MR5XzFgtB","lXFOBzz4ZU","MezSW5drc6",
-"5Mg9rfqypy","wiHrZlXFOB","hUTw7VjCZq","d7vjMoQ87r","7hyVvlkMUA","wiHrZOz8yZ","kB5nPuPX7G","F6PT29iGoT","sqVrfGXdoH","rz7Utuupzk",
-"ECMvUZhwG1","M6qcGn1pmO","sqVrf7hyVv","5Mg9rfFDrJ","nlaByDQimp","SbRYyLbRTH","Zv7z0POUYS","MojnPZv7z0","xReecJ2mQi","pv0i75nmWv",
-"QssNCVBjhz","POUYSsx5Gl","Ss0ZuuoStw","cQOnvHP433","Q6hMCL7cGc","9iGoTpFrrl","h1zcHMezSW","CIShGzqH0W","618Di2Yz7E","n1pmOZhwG1",
-"F6PT2Rxrsm","1v5hHZuDtD","07n1cIKxdL","ulk41Q6Lix","WDVWJK4GS8","M3zXLRkQke","hi5X7ksJby","24ARF0MR5X","POUYSQWxoT","dpe1vJIqXi",
-"5drc6uoStw","OUYuFrhl0J","GWqqX5Drn0","d85a90Kyfs","tl72WSjskQ","zmLYD2Nslm","CqqaDJ2mQi","QYxC0Dz1R3","9XyT9ZUnqt","FjHXRn8pJ9",
-"2Yz7EK4GS8","NOHszWaWsv","zz4ZUQ6hMC","8FmFHm4bxU","Oz8yZbZLvS","dQ586LDk6f","gdQsSuZPqg","QssNC6AFT0","QnJ1S0BmCy","Mkgy8Twano",
-"v2eC3FcWrW","ksJby4W0Tl","uoStwfcJOy","8TxD7NOHsz","1LB1L24ARF","aez9yMK07Y","K4GS8v1Hln","JJs5m8RCUA","oQ87rVLTy6","LewvMG1RhS",
-"9iGoTjfREu","b29RJFNYIM","DQimp0MR5X","fmIK1CxVEf","8xEKzcQOnv","uAWypyofH3","nFqikwDajX","n1pmOVNCPd","FFDui0Wr5y","0MR5XS77LH",
-"ogLgcOUYuF","pFrrlaDGtS","ni2v1wiHrZ","ni2v1HRxd8","7fsYMOUYuF","XflUqK4GS8","iB08lcmXIX","nFqikpAhR1","XyPZNFGzgp","d85a99iGoT",
-"5Drn0dQ586","XyPZN0h1b1","t59lRJJs5m","9iGoTmX2GE","1j5L8XflUq","BGaQYuQIcz","M6qcGhUTw7","bgJAzMaJQs","7Ow5C5Drn0","BFkb8GrDg7",
-"xciqpMGlTF","BFkb8Kr8ys","LDk6fSs0Zu","GXdoHi7WMQ","5Drn0zqH0W","iKqhrG1RhS","16lHcaL6AJ","G1RhSThjNn","7fKYUuZPqg","zQt6QEoToP",
-"BGaQYHfyNQ","tlILtFcWrW","HfyNQrz7Ut","FwEJzt59lR","Q6hMCpFrrl","Ul4a1euZA5","h1zcHVBjhz","uoStwVjCZq","5iGN56AFT0","RmDcrtaOXK",
-"S77LH8U2nU","hYBCKuvf7A","Kr8yss93Ml","9XyT9AmdQd","Z4I1v4dEz6","QClRLk85Ae","Mkgy8zz4ZU","64s8N2Nslm","6AFT0lsQGo","soy9tCp3mZ",
-"atef2WMiS3","tlILtcShY2","0h1b13otm6","wiHrZJkzUn","vkCHHlViBv","4W0TlFNYIM","lsQGouQIcz","MGlTFni2v1","KASQ8UmaEv","FPfSEFcWrW",
-"618DizFgtB","euZA5xXTI4","07n1cGSQwj","HRxd8C2Irc","FcWrW7hyVv","7fsYMZzJHW","P6bcguQIcz","uTacx5nmWv","8xEKzjSjS3","l83Ud24ARF",
-"U3yw5W3VFH","tjQxsQYxC0","NhXdu5drc6","5IhmGyToGW","xReecaDGtS","AkKTkWMiS3","ciuWzuAWyp","GSQwjcQOnv","AXpwEyvOMI","ogLgcyofH3",
-"2ZHdkZJTXH","gdQsSZ4I1v","fqypyhi5X7","iqv4kQnJ1S","K4GS8JKWYR","2Yz7EFxX9q","ni2v1uPX7G","v2eC3JkzUn","jS1ajRpBQm","CdyBVFnPFB",
-"cShY2zz4ZU","TCgPpgtCA5","mX2GEtl72W","DG4sTsoy9t","AXpwE8FmFH","Mm8sigjUTu","P6bcgHzZT8","SWfou5Drn0","FVMxoxciqp","StlDJ9y4lw",
-"ydG8UgdQsS","ThjNnciuWz","RpBQmI7p2a","UlU3MPYBf4","OUYuFBbwgA","rz7UtKsjRK","7ku1p1v5hH","xReecyluBx","AkKTkSs0Zu","I7p2aOUYuF",
-"24ARFlj07Q","hYBCKSmGzv","tAOsrVLTy6","JJs5mMkgy8","C2IrcReKEW","MK07YiB08l","DQimpCIShG","lXFOBNxx9V","HfyNQFVMxo","k85AecQOnv",
-"lm0pDIjTwP","aez9y16lHc","EOE1oiB08l","y94nwS2Dfu","vkCHHB3qem","pWiOsWaim6","55rfBFxX9q","5Mg9rpv0i7","Z4I1vuPX7G","ZhwG1pT8wu",
-"9XyT97hyVv","okgRiGXdoH","gjUTuuAWyp","24ARFnnP8o","djsrvU3yw5","DLhzMd85a9","HzZT8he9IA","5nmWvCfgr3","i7WMQfqypy","aFFssEOE1o",
-"fFDrJVBjhz","3weIFIKxdL","t98iWVNCPd","BbwgASmGzv","EdBKcFcWrW","uupzkGv3Fq","RpBQmMmKGJ","Q6hMCoGu6x","piJSkDG4sT","GWqqXzY1GY",
-"JkzUnuQIcz","X6Pinulk41","ydG8U7fKYU","9GXkXRkQke","uoStwVLTy6","ru4UGru4UG","2TRI7prNT6","pmeCdh1zcH","Qworu8xEKz","FVMxol83Ud",
-"uZPqgIKxdL","uQIczxXTI4","8hJdtiqv4k","5IhmGNOHsz","FwEJzSjskQ","lm0pDjtn0X","7fKYUzHF1q","yEfy9v2eC3","2TRI7fFDrJ","BFkb8LDk6f",
-"7lUXZd85a9","CNHmvoGu6x","WDVWJzqH0W","lm0pDFhtgl","QssNCh1zcH","bZLvS48cHL","lCMxynFqik","Nxx9V8RCUA","lH1ktGWqqX","uN6r3Qworu",
-"mz8gxydG8U","K20wKCfgr3","C2IrcIBe8k","uoStwgdQsS","RACujtvdkD","4QMc9tuDyS","i3pydRzaZA","CK5W7QClRL","FwEJzydG8U","16lHcZJTXH",
-"yluBxGrDg7","iKqhr2Nslm","QssNCv2eC3","cShY2pT8wu","QClRLzbIYY","yofH3S77LH","zz4ZUgdQsS","zmLYDBGaQY","W3VFHfqypy","gtCA5WDVWJ",
-"GXdoHYw2oU","euZA5s7Mxk","NAFuwzqH0W","mX2GECK5W7","bZLvSrKDLJ","Rxrsmhi5X7","Q6hMCuN6r3","b29RJZv7z0","uvf7ATXQ0Z","SjskQxciqp",
-"O3iyQDG4sT","QssNC14FLR","nFqikFwEJz","M3zXLlH1kt","5ZaEzy94nw","ni2v1aL6AJ","LDk6fNcICA","hE1QlgtCA5","RpBQmYh1hF","3otm6qQxHP",
-"ZuDtD9GXkX","tAOsr55rfB","7Ow5Ci3pyd","8xEKzv1Hln","618DijSjS3","lweGyRpBQm","5IhmGP6bcg","7fsYM3otm6","AmdQd6AFT0","DcpWBXflUq",
-"pvgjSZzJHW","D6rByd7vjM","qaofNPYBf4","uQIczEdBKc","OUqFMogLgc","AOgEe0PktI","tAOsrFVMxo","14FLRi7WMQ","lm0pDhYBCK","fmIK1aFFss",
-"7fsYMprNT6","07n1cYh1hF","BFkb8JIqXi","iqv4kwDajX","pFrrl3otm6","SbRYyPb1pa","t59lRJKWYR","rhl0JbrhlQ","e6e4z16lHc","tl72WsuY4x",
-"zY1GYyvOMI","48cHLGSQwj","Yh1hFIKxdL","xXTI4rKDLJ","DLhzMF6PT2","WmadAiqv4k","L7cGcuoStw","CdyBVIBe8k","TXQ0Z0Wr5y","KASQ8Dz1R3",
-"LbRTHlweGy","VNCPd618Di","HRxd8ZhwG1","NhXduyToGW","U3yw55nmWv","Cp3mZlXFOB","jtn0XStlDJ","CdyBVQbxXc","y94nwpWiOs","kB5nPprNT6",
-"M6qcGatef2","EOE1oatef2","v2eC32Yz7E","uAWyp9y4lw","2Nslm8TxD7","lweGyd7vjM","WmadARzaZA","BFkb8TCgPp","Ta8f6VIlwP","9rlg9t98iW",
-"HlUbFNcICA","Vprf2618Di","CIShGciuWz","JXljWxReec","okgRiwDajX","F6PT2lH1kt","fcJOyYh1hF","uQIczLewvM","CNHmvCqqaD","uN6r3s93Ml",
-"rhl0J55rfB","GWqqXJkzUn","y94nw7hyVv","7Ow5CIn3NS","VIlwPVjCZq","SbRYyD6rBy","hUTw7t59lR","iqv4kTwano","BpYhVzHF1q","bZLvSO3iyQ",
-"SmGzvt59lR","uAWyplj07Q","WmadAAIYUu","a00b5jeskS","Mkgy8GXdoH","oVQp6sqVrf","AIYUutvdkD","SbRYy8TxD7","9GXkX3otm6","ni2v1HzZT8",
-"lkMUASs0Zu","CK5W78FmFH","QClRLxciqp","hYBCKpiJSk","QClRLuJScX","FxX9qJJs5m","OUYuFpWiOs","0BmCy580YD","JXljWLewvM","RmDcrPb1pa",
-"fFDrJazIWp","XyPZNLbRTH","FwEJzZuDtD","uTacxhE1Ql","HP433cmXIX","JkzUnJkzUn","tvdkD1LB1L","FNYIMblLA9","a00b51v5hH","VBjhzbZLvS",
-"ZhwG1K20wK","piJSkJIqXi","atef2iwzGk","xciqp4QMc9","MezSWWPmlx","tAOsr2DREs","8RCUAuoStw","djsrvtl72W","zz4ZUFxX9q","KsjRKfFDrJ",
-"mz8gxZJTXH","8xEKzfcwDa","fcwDaBGaQY","TXQ0ZUlU3M","zY1GYuJScX","fqypygf8rI","8xEKz14FLR","d7vjMiwzGk","DLhzMMGlTF","lXFOBsoy9t",
-"7Ow5CqQxHP","F6PT26q6L9","e6e4zo8Uyd","yEfy99eoRc","uN6r3QClRL","v1HlndmoS7","iqv4kJRJQB","Cp3mZWreyP","rz7Ut1j5L8","MaJQs64s8N",
-"uupzkZUnqt","ydG8U2Nslm","lXFOBNAFuw","TXQ0ZRsQUq","jS1ajnFqik","9eoRcyToGW","vLsmS8TxD7","07n1cqUJMd","9y4lwWaim6","29QAz5Mg9r",
-"Yw2oUJRJQB","oQ87rVjCZq","tuDyS8RCUA","xciqpo8Uyd","XyPZNVNCPd","ZzJHWMojnP","ZUnqtUlU3M","CIShG6q6L9","pFrrld85a9","a00b5jSjS3",
-"9GXkXrhl0J","wiHrZfFDrJ","5Drn0IBe8k","he9IAVIlwP","AkKTkMm8si","VIlwPBbwgA","S2Dfu9eoRc","aL6AJuLtKs","uTacxFNYIM","x3LDeni2v1",
-"Vprf2Ta8f6","UmaEvL7cGc","QChxsyluBx","hSSvQdmoS7","8hJdtt98iW","S77LHOUYuF","JRJQB0BmCy","MGlTFVLTy6","MmKGJDLhzM","d85a9gjUTu",
-"5Drn0P6bcg","sx5Glmz8gx","6q6L9zmLYD","Kr8ysOUqFM","FFDuiFFDui","uoStwVBjhz","LDk6fix74r","2Nslm14FLR","zqH0Wx3LDe","VjCZqfmIK1",
-"MaJQsSs0Zu","CNHmvix74r","Ta8f6RzaZA","BbwgA8xEKz","jtn0XuZPqg","NhXdufqypy","IKxdLaDGtS","5drc6GSQwj","OxWIHuupzk","Cp3mZhYBCK",
-"0KyfsWreyP","ZzJHWuZPqg","pv0i7xciqp","Q6LixtvdkD","Ul4a1x3LDe","uAWyp9GXkX","fqypyUmaEv","LDk6fwDajX","D6rBy618Di","RzaZACp3mZ",
-"IRh48OxWIH","wiHrZiKqhr","euZA52Yz7E","5ZaEzQnJ1S","cL0aE7hyVv","aL6AJRACuj","taOXKDcpWB","2hEEUZzJHW","aFFssM3zXL","VBjhz580YD",
-"pFrrlyToGW","J2mQiuupzk","pT8wuAgJHQ","uoStwhe9IA","EoToPguMb8","CqqaDpvgjS","VjCZqulk41","CNHmvfmIK1","AXpwEfaHir","ZzJHWOz8yZ",
-"BCxeC3weIF","sx5Gl9GXkX","Vprf2TXQ0Z","FwEJztlILt","Q6hMCSjskQ","VLTy6BpYhV","9rlg9BbwgA","PYBf4zz4ZU","zHF1q2Yz7E","kZANmuPX7G",
-"xciqpix74r","y94nwPYBf4","7lUXZLewvM","bgJAz45cIH","s7MxkhYBCK","jS1ajgjUTu","oGu6xNcICA","vLsmSpiJSk","lViBvCfgr3","blLA91LB1L",
-"yToGWgf8rI","CIShGhE1Ql","GSQwjCxVEf","0h1b1OxWIH","bZLvSTXQ0Z","ThjNn7ku1p","AOgEe3weIF","v8yFN8TxD7","QssNCRkQke","tvdkDuupzk",
-"yofH3TXQ0Z","vkCHH0ao3l","lsQGoBCxeC","AmdQdTwano","jSjS3W3VFH","OxWIHY1mC0","7fsYMfaHir","jfREuv1Hln","SjskQPOUYS","jtn0XyEfy9",
-"RpBQmBGaQY","uupzk5drc6","ReKEWhYBCK","RpBQmGWqqX","prNT6sqVrf","D6rBy8TxD7","tuDySTXQ0Z","0PktIaDGtS","4W0TljS1aj","lCMxytlILt",
-"55rfBWDVWJ","pAhR1XyPZN","2Yz7ErKDLJ","BGaQY4dEz6","OUqFMaFFss","ReKEWCNHmv","8xEKz16lHc","tlILtGWqqX","bZLvS7hyVv","UmaEvFGzgp",
-"EdBKciqv4k","l83Udd7vjM","CqqaDydG8U","0PktIQbxXc","W7cTs0ao3l","StlDJtvdkD","WaWsv0Kyfs","C2IrcIjTwP","hUTw7Ta8f6","MmsIolXFOB",
-"XyPZNDcpWB","2Yz7EtAOsr","7X3uysx5Gl","RACujO3iyQ","hYBCK6AFT0","m4bxUlm0pD","RxrsmnlaBy","jSjS3MaJQs","v8yFNHzZT8","J2mQiVLTy6",
-"BbwgAZuDtD","IjTwPpAhR1","Chuy3v2eC3","ZJTXHOHaBz","fLNg8tl72W","5ZaEzQbxXc","JIqXiWPmlx","gdQsSpAhR1","Uvlv4W7cTs","NAFuwtAOsr",
-"QWxoTPOUYS","uQIczDz1R3","DLhzMIjTwP","taOXKQworu","fcwDapv0i7","uupzkhi5X7","NOHszrKDLJ","RACujFnPFB","rKDLJAXpwE","hSSvQYjB9t",
-"azIWpSjskQ","ulk41AXpwE","soy9t0BmCy","Yf2EcZJTXH","ReKEWP6bcg","JXljW5IhmG","GrDg7t59lR","fLNg8zQt6Q","0BmCynlaBy","SWfouFVMxo",
-"IRh48zFgtB","VerEAuAWyp","vLsmSK4GS8","J2mQirz7Ut","fLNg8ZzJHW","Yw2oULbRTH","OUYuFNhXdu","NhXduBGaQY","zmLYDtAOsr","uQIczlCMxy",
-"0BmCyNxx9V","1j5L8tjQxs","lsQGoAIYUu","pWiOsGrDg7","FFDuiGXdoH","UmaEvzFgtB","OHaBzLewvM","ReKEWgf8rI","Ul4a1IjTwP","5ZaEzfaHir",
-"O3iyQ3otm6","i3pyd5Namm","45cIHCK5W7","kZANm5iGN5","ZJTXHvOqCE","pWiOsI7p2a","2ZHdkfqypy","ReKEW8U2nU","X6PiniB08l","QYxC0QChxs",
-"rz7Utv8yFN","uAWypCxVEf","fmIK1lCMxy","iKqhr9y4lw","uvf7A0YAGH","zqH0WyofH3","KZamHU3yw5","KsjRKtAOsr","M6qcGHzZT8","hUTw7UmaEv",
-"CxVEfv1Hln","AOgEeS2Dfu","v8yFN7fsYM","580YDFVMxo","hi5X7ciuWz","nlaByJKWYR","Pb1paAOgEe","pWiOsjiVBP","ciuWz24ARF","lViBvRxrsm",
-"ZuDtDGrDg7","dmoS76AFT0","BbwgAjSjS3","qUJMdqQxHP","48cHLa00b5","pvgjSMGlTF","OHaBzb29RJ","SWfou0MR5X","XyPZN6q6L9","prNT6Ul4a1",
-"Dz1R3BCxeC","MK07YhE1Ql","Mkgy8RBhp0","Z4I1vpv0i7","8cVD3n8pJ9","DcpWB5Mg9r","EoToPQYxC0","tlILt64s8N","nFqikX6Pin","AOgEepvgjS",
-"7lUXZAIYUu","No0QbBCxeC","ThjNn29QAz","IjTwP6AFT0","aDGtSdQ586","FjHXRuZPqg","BGaQYhE1Ql","Yw2oUZJTXH","8cVD3i3pyd","uQIczB3qem",
-"Chuy3FNYIM","uoStwjeskS","FNYIMVBjhz","uN6r3gtCA5","soy9t0Kyfs","QWxoTReKEW","dpe1vtuDyS","zmLYDfLNg8","rhl0JWaWsv","NhXduVprf2",
-"3weIFMK07Y","Yf2Ecl83Ud","JkzUnRBhp0","VNCPdLDk6f","Mm8siPOUYS","oVQp65Namm","s47867fKYU","ECMvUa00b5","zHF1q24ARF","iqv4kYjB9t",
-"s478645cIH","Kr8ysUlU3M","JRJQBgjUTu","BFkb85Drn0","faHirtjQxs","zz4ZUVprf2","pFrrl2Nslm","Twanolm0pD","d7vjMU3yw5","HzZT8l83Ud",
-"yofH3LDk6f","MmsIoDz1R3","C2IrcpvgjS","VBjhzuAWyp","piJSkFnPFB","pT8wu7lUXZ","UlU3MRsQUq","cL0aE2DREs","QnJ1Srhl0J","Yh1hFL7cGc",
-"L7cGcWDVWJ","5Namm9iGoT","tAOsrn8pJ9","AgJHQ8cVD3","ni2v1Yf2Ec","blLA9gjUTu","BbwgA8FmFH","Cfgr3cmXIX","JkzUnuoStw","rhl0Js7Mxk",
-"55rfBnlaBy","hE1Ql8FmFH","iqv4kuAWyp","5drc6s4786","CxVEfNhXdu","zHF1qt98iW","hE1Qlrhl0J","lweGyM6qcG","tlILtKsjRK","lm0pD5iGN5",
-"v2eC3KASQ8","VNCPdoQ87r","O3iyQ580YD","OUqFMi3pyd","s4786cmXIX","U3yw5MezSW","pmeCdatef2","580YDokgRi","S77LHBpYhV","1LB1LvLsmS",
-"FjHXRcShY2","gjUTuuPX7G","xciqpJ2mQi","tAOsrFPfSE","Nxx9VChuy3","In3NSDG4sT","OUqFMD6rBy","5Drn07lUXZ","NOHszdjsrv","prNT6uAWyp",
-"qaofNdjsrv","5VZjSFxX9q","F6PT28U2nU","t59lRd85a9","FjHXR45cIH","tl72W8U2nU","dpe1vRmDcr","tlILtWDVWJ","brhlQtAOsr","Yh1hFCdyBV",
-"jeskSNxx9V","M6qcGKASQ8","5iGN5Y1mC0","o8Uyd8xEKz","XflUquTacx","BpYhVa00b5","0KyfsuJScX","hi5X7XflUq","ECMvUUlU3M","I7p2aFLsph",
-"Y1mC0QYxC0","kZANmlm0pD","RmDcrZJTXH","CxVEfb29RJ","RBhp0pmeCd","2hEEUxXTI4","he9IAuJScX","Qworus93Ml","CK5W7lsQGo","0MR5XiwzGk",
-"wiHrZNxx9V","t98iWRkQke","dQ586k85Ae","RACujRBhp0","uupzk6AFT0","HzZT807n1c","yvOMIWaWsv","s7MxkZzJHW","RACujdmoS7","AOgEeRsQUq",
-"POUYSoVQp6","07n1cS2Dfu","lpF6WhUTw7","Cfgr3VBjhz","OHaBzJkzUn","t98iWNcICA","64s8NtvdkD","0h1b18TxD7","X6PinuTacx","BbwgAfaHir",
-"Chuy3aL6AJ","HlUbFCK5W7","JkzUnCK5W7","Q6Lix0Wr5y","oVQp6FnPFB","ydG8UDz1R3","sqVrfjS1aj","VBjhzokgRi","dpe1v8hJdt","No0QbRkQke",
-"tuDyS2hEEU","RACujjtn0X","m4bxUulk41","jzUqRjzUqR","ZuDtDpvgjS","YOfrYCp3mZ","xReecFFDui","ogLgcaDGtS","W3VFHUlU3M","HRxd8oGu6x",
-"TwanoIjTwP","oGu6xRpBQm","yofH3Yf2Ec","U3yw5ru4UG","5IhmG580YD","Yh1hFcShY2","v2eC3aFFss","ksJby0MR5X","gf8rIGXdoH","ogLgcxReec",
-"euZA5FwEJz","lsQGoFnPFB","VIlwPWmadA","ReKEW7fKYU","BFkb8a00b5","6q6L9nlaBy","RsQUqlm0pD","ksJbyP6bcg","StlDJdhSuH","7fsYMhUTw7",
-"euZA5AmdQd","VjCZq618Di","gjUTulm0pD","ydG8UVNCPd","gjUTuPb1pa","BCxeCkB5nP","EOE1oyToGW","4W0TlWreyP","5Mg9rRACuj","0YAGHWaWsv",
-"EOE1oCp3mZ","1LB1LtuDyS","9rlg9qaofN","RsQUq618Di","zY1GYJRJQB","t59lRQWxoT","RsQUqRkQke","Ss0ZuCfgr3","AIYUuBpYhV","2hEEUJJs5m",
-"xciqpzbIYY","MmsIoJkzUn","RpBQmeuZA5","Yh1hFyluBx","YOfrYatef2","X6PinRzaZA","NAFuwTCgPp","fLNg85nmWv","GSQwjRkQke","7ku1pyvOMI",
-"14FLRJIqXi","4dEz6FPfSE","GWqqXVjCZq","Z4I1vTwano","Chuy3ZzJHW","AIYUu8cVD3","tjQxscmXIX","gjUTuWMiS3","StlDJNhXdu","iwzGkjtn0X",
-"Yh1hFThjNn","TCgPp580YD","SmGzvQ6hMC","JJs5mOUqFM","TCgPpKASQ8","FnPFB580YD","Mkgy8580YD","lH1kttaOXK","FLsphC2Irc","7ku1pNxx9V",
-"ulk412TRI7","jzUqRpvgjS","WmadAciuWz","fmIK1HlUbF","NhXdu9XyT9","MojnP0h1b1","QClRL0Wr5y","Y1mC05VZjS","ECMvUix74r","B3qemFhtgl",
-"oVQp6fFDrJ","RACujuvf7A","jtn0XaFFss","x3LDeFGzgp","wDajXZ4I1v","tuDySDG4sT","GSQwjQYxC0","AIYUus7Mxk","gjUTuFGzgp","No0QbYOfrY",
-"8FmFHK20wK","uQIczYf2Ec","7fsYMWmadA","rhl0J5ZaEz","RACujRsQUq","ksJbyzY1GY","KASQ8pT8wu","lkMUA55rfB","iqv4k9eoRc","sx5Gl6q6L9",
-"MK07Yxciqp","P6bcgFhtgl","uPX7GiB08l","G1RhSguMb8","MmKGJuJScX","9y4lwk85Ae","zHF1qM3zXL","45cIHd85a9","zqH0WFFDui","24ARFD6rBy",
-"DLhzMrz7Ut","jzUqRX6Pin","ZuDtDMmsIo","VIlwPFPfSE","Q6hMCP6bcg","sqVrfWPmlx","lkMUAdpe1v","IjTwPiqv4k","m4bxUcShY2","AmdQd9XyT9",
-"Cfgr3M3zXL","tvdkDNAFuw","8FmFHBbwgA","QnJ1Sn8pJ9","Mkgy8uupzk","24ARFfcJOy","DLhzMD6rBy","FFDuim4bxU","DG4sTQbxXc","UlU3MGv3Fq",
-"TCgPpnnP8o","Q6Lix9iGoT","taOXKNOHsz","d85a9yvOMI","HlUbFJRJQB","s4786Q6Lix","SjskQMojnP","ulk41BFkb8","QbxXclCMxy","CK5W7EOE1o",
-"lXFOBvkCHH","NAFuwsx5Gl","tjQxs1LB1L","IjTwPThjNn","nlaByl83Ud","X6PinJKWYR","JXljWIBe8k","rKDLJU3yw5","yToGWa00b5","5VZjSs7Mxk",
-"i3pyduTacx","Kr8ysMmKGJ","0Kyfshi5X7","07n1c8U2nU","piJSklpF6W","djsrv5drc6","iKqhrqUJMd","WDVWJJkzUn","t59lRfFDrJ","s47865Drn0",
-"cL0aEReKEW","jSjS3lpF6W","IBe8kVprf2","2TRI7StlDJ","FwEJzDLhzM","618DiyvOMI","rz7Uti7WMQ","Q6Lixru4UG","IKxdLCfgr3","yvOMIDG4sT",
-"VerEAIRh48","DG4sTDLhzM","vLsmSzqH0W","BpYhV6AFT0","4dEz6WMiS3","k85AeKsjRK","fqypyyEfy9","Nxx9VprNT6","JKWYR7fsYM","JXljWrhl0J",
-"zFgtBzqH0W","uLtKsOUqFM","FjHXRguMb8","8cVD3Q6Lix","ogLgcVIlwP","P6bcgReKEW","Dz1R3wDajX","MezSWaDGtS","16lHcmz8gx","ogLgcKZamH",
-"HP433yofH3","B3qem5IhmG","0KyfsVNCPd","CxVEf8RCUA","bZLvSBbwgA","sqVrf5nmWv","ni2v10PktI","AgJHQD6rBy","okgRiuupzk","mX2GEqQxHP",
-"t59lRtAOsr","lsQGoDG4sT","CdyBVTXQ0Z","lViBvm4bxU","I7p2agIYvE","lj07Qhi5X7","ECMvUvOqCE","lm0pDt98iW","XyPZNa00b5","zz4ZUuJScX",
-"aez9yRzaZA","M6qcGFhtgl","wiHrZJXljW","WmadAuJScX","x3LDeFhtgl","ZzJHWk85Ae","yEfy9faHir","UlU3MS77LH","2Yz7EUmaEv","o8UydyofH3",
-"GrDg7soy9t","5drc6UlU3M","WaWsvQClRL","Gv3FqChuy3","YOfrY2Yz7E","ru4UGCxVEf","lkMUA5Drn0","HzZT8Nxx9V","gIYvERpBQm","taOXKhe9IA",
-"y94nw7Ow5C","aez9ypmeCd","gjUTuhUTw7","NhXduDG4sT","Yw2oUzqH0W","No0QbpiJSk","S2DfuyToGW","jeskS9y4lw","pWiOs6AFT0","s7Mxk4dEz6",
-"Ss0ZubZLvS","FxX9qSjskQ","48cHLFcWrW","zQt6QiB08l","QYxC0lH1kt","wDajXD6rBy","55rfBxXTI4","qUJMduoStw","7X3uys4786","tuDySrhl0J",
-"e6e4zlCMxy","RBhp0QbxXc","pv0i7pT8wu","aL6AJ5Namm","dpe1vO3iyQ","AmdQdDcpWB","LewvMn1pmO","vLsmSYjB9t","fcJOyCfgr3","faHirpT8wu",
-"n8pJ9W3VFH","y94nwNxx9V","7fKYUix74r","BFkb88RCUA","vkCHHECMvU","euZA5DcpWB","Chuy3sqVrf","CdyBVVBjhz","24ARFtuDyS","soy9tL7cGc",
-"uJScXEdBKc","9eoRcHRxd8","bZLvSd85a9","0YAGHvkCHH","tl72WM6qcG","RkQkeEOE1o","ZhwG1PYBf4","RBhp0Qworu","FhtglhUTw7","WmadA5ZaEz",
-"vLsmSSjskQ","lsQGo45cIH","v8yFNrKDLJ","QClRL5Drn0","YjB9tb29RJ","bgJAzUl4a1","ZuDtDIjTwP","QClRLfLNg8","mz8gxMkgy8","MmsIoAgJHQ",
-"LDk6fs4786","gIYvE5drc6","CxVEfQ6Lix","SjskQCdyBV","zmLYDeuZA5","ReKEWM3zXL","tuDySydG8U","Ul4a1i7WMQ","cQOnv7X3uy","zY1GYRmDcr",
-"ydG8UHzZT8","Mm8siTXQ0Z","atef2tl72W","VerEAFcWrW","v8yFNJJs5m","iwzGkyvOMI","NAFuwtlILt","0Kyfsni2v1","Y1mC08U2nU","lCMxylj07Q",
-"Cfgr324ARF","7Ow5Cm4bxU","cmXIX5nmWv","XyPZNTCgPp","5VZjSfcwDa","iwzGkfFDrJ","3otm6MmsIo","rhl0Jb29RJ","2Nslm8FmFH","hi5X7Yh1hF",
-"1v5hHydG8U","CxVEfbgJAz","LDk6fpv0i7","ciuWzprNT6","FxX9qFhtgl","QWxoTLDk6f","FhtglnlaBy","Ul4a1Mkgy8","O3iyQyEfy9","Yh1hFJXljW",
-"U3yw5fcwDa","0MR5XSbRYy","FLsphGrDg7","zFgtBRxrsm","5ZaEzLDk6f","7lUXZMkgy8","MGlTFzHF1q","L7cGcfLNg8","qQxHPMmsIo","tjQxs55rfB",
-"MojnPZJTXH","VLTy655rfB","bZLvSDz1R3","FcWrWMm8si","EdBKcVNCPd","HlUbFPOUYS","SjskQLbRTH","zQt6QDcpWB","UmaEvdhSuH","t98iWuQIcz",
-"0h1b1SbRYy","he9IA1j5L8","G1RhSHzZT8","wDajXzmLYD","WDVWJ7ku1p","16lHcdmoS7","U3yw5rhl0J","AIYUuK4GS8","7ku1pECMvU","ThjNnix74r",
-"MaJQsWaWsv","FFDuizz4ZU","FwEJzMaJQs","iqv4kS2Dfu","IjTwPSmGzv","taOXK8RCUA","D6rByU3yw5","2ZHdkQssNC","iqv4k3weIF","Ul4a13weIF",
-"M6qcGzqH0W","hYBCKlm0pD","5nmWvy94nw","Mm8siOxWIH","55rfBoVQp6","DcpWBYf2Ec","VNCPd0PktI","Ta8f68RCUA","PYBf445cIH","guMb8dpe1v",
-"v1HlnGSQwj","580YD8TxD7","lkMUAiB08l","YjB9tx3LDe","KZamHGSQwj","dQ586FFDui","QYxC0FVMxo","i7WMQlpF6W","lH1ktRkQke","aFFssSs0Zu",
-"qaofN5Drn0","EoToP29QAz","tuDySHfyNQ","GWqqXbZLvS","4QMc9VerEA","29QAzBpYhV","gf8rIlpF6W","DQimpsuY4x","1v5hHCNHmv","9XyT9Yh1hF",
-"RBhp0MGlTF","fqypyCfgr3","djsrv7fsYM","7hyVvDz1R3","yofH3MmKGJ","Mm8siIKxdL","UmaEveuZA5","2ZHdkMmKGJ","MaJQsMGlTF","Yf2EcL7cGc",
-"bgJAzS77LH","jfREugf8rI","LewvMVLTy6","FnPFBv2eC3","Mkgy8VLTy6","ciuWzWPmlx","WMiS3ru4UG","I7p2aWaim6","D6rBylpF6W","ogLgcZ4I1v",
-"Vprf2mX2GE","jS1ajlXFOB","o8UydQClRL","2hEEUsuY4x","cmXIXuvf7A","iwzGkFLsph","LDk6fOxWIH","lweGyh1zcH","RsQUq6q6L9","a00b5s7Mxk",
-"NhXduCIShG","TCgPpXflUq","uN6r3XflUq","MojnPDQimp","blLA9lH1kt","JJs5mfqypy","VLTy6BGaQY","ECMvUgf8rI","RkQkeZv7z0","hSSvQtuDyS",
-"ni2v1nlaBy","FhtglhSSvQ","guMb8pT8wu","ogLgcL7cGc","D6rByx3LDe","m4bxUB3qem","9iGoTuQIcz","vkCHHF6PT2","QnJ1SECMvU","7Ow5C8RCUA",
-"k85AeL7cGc","gf8rIl83Ud","gdQsSfFDrJ","8RCUAgjUTu","55rfB1LB1L","SjskQnFqik","1LB1LW7cTs","uZPqgkZANm","CdyBV45cIH","2TRI7i3pyd",
-"GrDg7RBhp0","tuDySdpe1v","NAFuwlCMxy","ydG8UzqH0W","zbIYYIBe8k","brhlQzbIYY","tuDyS29QAz","uPX7GqUJMd","16lHcMmsIo","8hJdtOz8yZ",
-"fcJOyJKWYR","K4GS8J2mQi","3weIFuN6r3","n8pJ9guMb8","TCgPpqQxHP","dhSuHBbwgA","VerEAe6e4z","WreyP9GXkX","FhtglRzaZA","RzaZAIKxdL",
-"I7p2a9XyT9","MojnPFwEJz","s7Mxkru4UG","gf8rIU3yw5","pvgjSIRh48","O3iyQguMb8","ZUnqtVLTy6","WPmlx2ZHdk","uAWypRsQUq","I7p2aAIYUu",
-"lm0pDKASQ8","GWqqX618Di","v1Hlno8Uyd","MGlTFjiVBP","lViBvaDGtS","ciuWz6AFT0","MaJQsatef2","24ARFSWfou","d7vjM5iGN5","Pb1pa14FLR",
-"gtCA5jS1aj","RACujZv7z0","rz7UtjS1aj","tjQxsiB08l","i7WMQguMb8","gdQsSCIShG","aL6AJAOgEe","5drc6e6e4z","0KyfsTwano","Yh1hFOz8yZ",
-"lj07Q0YAGH","hUTw7cQOnv","Waim67fsYM","ydG8UYh1hF","16lHczY1GY","rhl0J5IhmG","Chuy3IRh48","s7MxkVjCZq","qaofNZUnqt","Cp3mZlm0pD",
-"MojnPGWqqX","GSQwjdhSuH","guMb8FnPFB","QChxsOUqFM","B3qemuTacx","dQ586xciqp","OHaBzZJTXH","LDk6fUvlv4","sqVrf2DREs","fLNg85Namm",
-"qUJMdlCMxy","yofH3QClRL","SbRYy1j5L8","aL6AJ2ZHdk","uPX7GFjHXR","Y1mC0OUqFM","Q6Lix55rfB","hE1QltAOsr","TXQ0ZYw2oU","5IhmGwDajX",
-"dhSuHogLgc","VBjhz14FLR","IjTwPGrDg7","U3yw5nlaBy","9XyT9azIWp","8TxD7KASQ8","5nmWvNcICA","tuDySaFFss","8hJdtWMiS3","J2mQigtCA5",
-"TCgPp7fKYU","zqH0Wv1Hln","uZPqgzbIYY","aDGtSFPfSE","atef2yofH3","QWxoTK4GS8","CqqaD7X3uy","AXpwEgtCA5","cmXIXpiJSk","Waim6580YD",
-"0BmCytvdkD","JKWYRDz1R3","OxWIHjeskS","7ku1pMojnP","0h1b1AXpwE","FxX9qhSSvQ","cQOnvHRxd8","MaJQsB3qem","bgJAzYjB9t","NhXdulsQGo",
-"RzaZADcpWB","KZamHJkzUn","dpe1vXyPZN","CxVEflH1kt","Cp3mZTCgPp","taOXKsqVrf","55rfBHlUbF","iwzGkMK07Y","ZuDtD5Drn0","5iGN5k85Ae",
-"X6Pin5nmWv","FxX9qHzZT8","1v5hHSbRYy","C2Irc4QMc9","aDGtS6q6L9","9iGoTt59lR","rz7UtX6Pin","ru4UGWPmlx","3otm6NOHsz","guMb8dhSuH",
-"iKqhruTacx","BpYhVNxx9V","2DREsgjUTu","uQIczzHF1q","48cHLazIWp","MGlTF24ARF","prNT61LB1L","JXljWQChxs","BbwgA0Kyfs","nlaByUlU3M",
-"faHirQChxs","aFFssFnPFB","9iGoTD6rBy","Nxx9VjfREu","s7MxklCMxy","brhlQYOfrY","AIYUuJRJQB","CdyBVFVMxo","8FmFH0PktI","7Ow5CrKDLJ",
-"QClRLuQIcz","FxX9qRkQke","5drc6zbIYY","RpBQmFwEJz","CxVEftuDyS","tjQxsrhl0J","GrDg7SWfou","tuDySL7cGc","s7MxkqaofN","5drc6tuDyS",
-"8xEKzt59lR","TCgPpQ6Lix","s4786rz7Ut","0Wr5yjtn0X","JJs5moVQp6","iwzGkd7vjM","MmsIoTCgPp","0PktIVerEA","EOE1oStlDJ","zY1GYfmIK1",
-"5iGN5mX2GE","aL6AJ1j5L8","7Ow5C5VZjS","BbwgA3otm6","JRJQB9rlg9","rz7Ut5Mg9r","qUJMdLDk6f","JRJQB8hJdt","In3NSMGlTF","RsQUqlpF6W",
-"9rlg9JRJQB","0MR5XU3yw5","FhtgluQIcz","FVMxoVNCPd","7fKYURkQke","YOfrYdpe1v","FwEJzcL0aE","5Mg9rCfgr3","nlaByO3iyQ","v1HlnIjTwP",
-"jSjS3MGlTF","uLtKstlILt","2TRI7kZANm","i3pyd2Yz7E","iqv4kAmdQd","IjTwPatef2","ZzJHWDLhzM","oQ87r8U2nU","b29RJUvlv4","P6bcglweGy",
-"M6qcGt98iW","lsQGowiHrZ","lm0pDni2v1","FLsphGSQwj","J2mQicL0aE","RxrsmcShY2","NcICAK20wK","SjskQECMvU","BCxeCpAhR1","uAWypSbRYy",
-"W3VFH0ao3l","dpe1vhE1Ql","RxrsmjzUqR","djsrvBFkb8","RACuj0h1b1","CxVEfJkzUn","pWiOsIjTwP","ydG8UpvgjS","LewvMQWxoT","G1RhSpv0i7",
-"JKWYRd7vjM","tlILtQ6Lix","Ul4a1ulk41","zz4ZURxrsm","AkKTk7fsYM","qUJMd0h1b1","RACujMGlTF","pWiOsni2v1","S2DfuU3yw5","Oz8yZBFkb8",
-"X6PinMK07Y","jzUqRFhtgl","lXFOB8FmFH","FhtglzFgtB","y94nwuLtKs","bgJAzoQ87r","v1Hln07n1c","0Wr5yfcwDa","soy9tFcWrW","FFDuiVLTy6",
-"uupzk9iGoT","zz4ZUtlILt","rz7UtQbxXc","J2mQicQOnv","EoToPWaim6","v2eC3QnJ1S","hYBCKAOgEe","QYxC0nFqik","qaofNS2Dfu","5NammjiVBP",
-"M3zXLLewvM","piJSkjzUqR","EoToPBpYhV","M6qcGgdQsS","cQOnvaFFss","FnPFBQClRL","NcICAvOqCE","Cfgr3uoStw","S2DfuGrDg7","5ZaEzOxWIH",
-"i3pydpFrrl","8FmFHEdBKc","cmXIXOUYuF","dpe1vVjCZq","EoToP0BmCy","b29RJuLtKs","M6qcGbgJAz","fcwDaJKWYR","tAOsrTCgPp","JXljWdjsrv",
-"piJSkWmadA","fcJOyiwzGk","BpYhVxciqp","P6bcgh1zcH","aDGtSqaofN","l83UdcQOnv","yEfy98cVD3","iwzGk5Drn0","piJSkGXdoH","Dz1R3t59lR",
-"iqv4kSmGzv","prNT6XyPZN","KASQ8YOfrY","nFqikt98iW","AIYUuguMb8","QClRLv8yFN","BFkb82hEEU","piJSkVNCPd","M6qcGxciqp","jeskStuDyS",
-"9y4lw5ZaEz","WMiS3B3qem","0KyfsYjB9t","yvOMIRzaZA","Rxrsm1LB1L","0PktIsx5Gl","Pb1pad85a9","uJScXRkQke","FhtglNhXdu","cL0aEG1RhS",
-"fcwDa1v5hH","UmaEvCp3mZ","jS1ajzQt6Q","t59lR7hyVv","s93Mlrhl0J","FFDuiaFFss","he9IAB3qem","aFFsspiJSk","i7WMQdQ586","16lHcBCxeC",
-"SbRYyvkCHH","AIYUun1pmO","yluBxFhtgl","uupzk9GXkX","VLTy6I7p2a","OUqFMMGlTF","BFkb8EoToP","YOfrYfLNg8","QWxoT14FLR","d7vjM45cIH",
-"Yf2EcuN6r3","D6rByMkgy8","AOgEeFNYIM","1LB1L8FmFH","16lHcSWfou","uPX7GnFqik","JkzUnAIYUu","Vprf2GXdoH","9y4lwMojnP","y94nwQworu",
-"ZhwG1K4GS8","ZUnqtaL6AJ","zFgtBQ6hMC","Pb1paK4GS8","rz7UtoGu6x","jiVBPoQ87r","EdBKcVLTy6","GrDg748cHL","UmaEvUl4a1","WPmlxQChxs",
-"7X3uyoVQp6","vkCHH7fKYU","jiVBPPb1pa","k85AeMGlTF","2TRI7tjQxs","M3zXLulk41","FnPFBi7WMQ","CxVEf16lHc","4QMc90MR5X","KZamHQChxs",
-"8RCUAe6e4z","WreyPAOgEe","In3NSzY1GY","NcICAy94nw","7X3uyXyPZN","jeskSHP433","BpYhVpT8wu","KASQ8i3pyd","pmeCdVNCPd","1j5L8GSQwj",
-"IBe8kguMb8","VIlwPzmLYD","9y4lwyluBx","YOfrYQWxoT","VIlwPAkKTk","QbxXcOxWIH","CqqaDzHF1q","qUJMdazIWp","XflUq1v5hH","U3yw5LDk6f",
-"YjB9tVerEA","bZLvSAIYUu","hYBCKlkMUA","h1zcHYw2oU","Q6hMCNOHsz","fcwDas4786","2Nslm5VZjS","7ku1pFxX9q","h1zcHWMiS3","jeskSsqVrf",
-"hi5X7WPmlx","ZhwG1NAFuw","8xEKzM3zXL","WMiS3ZUnqt","7ku1pYjB9t","B3qem3weIF","VerEArKDLJ","bgJAzlm0pD","euZA5dhSuH","xciqpv8yFN",
-"a00b5hUTw7","5drc6W7cTs","ThjNnOUqFM","gdQsSNOHsz","ciuWzFxX9q","2DREs29QAz","RmDcrqUJMd","RxrsmEdBKc","tAOsrpmeCd","29QAzYh1hF",
-"OUqFM8xEKz","8cVD3xXTI4","ZUnqtzbIYY","oGu6xhUTw7","M6qcGSs0Zu","uN6r3No0Qb","In3NSG1RhS","IBe8kvLsmS","RBhp0EdBKc","5VZjSAXpwE",
-"gdQsSsoy9t","ThjNnWaWsv","hi5X7IBe8k","djsrviKqhr","RmDcruoStw","24ARF5VZjS","suY4xNo0Qb","sx5GlCp3mZ","yEfy9BbwgA","RmDcraL6AJ",
-"JIqXiReKEW","uPX7GXyPZN","Ss0Zui3pyd","jSjS32TRI7","MmKGJzbIYY","aDGtSzFgtB","DQimp9rlg9","NOHsza00b5","Oz8yZ0Kyfs","0h1b1QClRL",
-"a00b5DQimp","rKDLJdjsrv","CxVEfrhl0J","cQOnvtjQxs","X6PinQClRL","FPfSEdpe1v","X6Pin7hyVv","D6rBy0Kyfs","MezSWoQ87r","YjB9tzbIYY",
-"CNHmvRxrsm","y94nwUmaEv","cmXIXy94nw","tl72W2TRI7","lj07QIKxdL","ReKEWUlU3M","SmGzvMGlTF","zFgtBStlDJ","Nxx9VBCxeC","v2eC39iGoT",
-"xciqp8U2nU","uJScX1LB1L","FxX9qWreyP","JKWYRGrDg7","pFrrl64s8N","Uvlv4MezSW","mX2GEKr8ys","K4GS88hJdt","uAWyp0MR5X","TCgPpuLtKs",
-"Waim6VNCPd","uoStwFLsph","rhl0JcmXIX","yluBx4dEz6","ECMvUBCxeC","4QMc9prNT6","lH1kthi5X7","WaWsvOxWIH","ru4UG2hEEU","tAOsr9iGoT",
-"Pb1paW7cTs","55rfBuLtKs","S77LH8TxD7","7Ow5C9y4lw","7lUXZhi5X7","vkCHHM3zXL","DG4sTPYBf4","uAWypfFDrJ","Cp3mZNOHsz","Dz1R3lpF6W",
-"Q6hMC2Yz7E","HRxd8FjHXR","9rlg9YjB9t","2Yz7EYjB9t","I7p2aYf2Ec","kZANmcQOnv","QnJ1SnlaBy","v8yFNAIYUu","mz8gxzQt6Q","RkQkeKASQ8",
-"KASQ8kB5nP","CqqaDlweGy","MK07YWmadA","1j5L8SjskQ","QYxC048cHL","cQOnvChuy3","yofH3HfyNQ","0BmCy0Kyfs","D6rBybZLvS","aL6AJ2Nslm",
-"VNCPdDG4sT","2DREsuQIcz","aez9yHzZT8","BFkb8WDVWJ","ydG8UgIYvE","TXQ0Z6q6L9","SbRYy0PktI","Ss0ZuFwEJz","kB5nPdjsrv","nlaBym4bxU",
-"CxVEfQChxs","45cIHuoStw","QYxC0jeskS","zz4ZUjS1aj","bgJAzlweGy","gdQsSMmKGJ","14FLRjzUqR","580YDzqH0W","2DREsaDGtS","tl72WB3qem",
-"HzZT8EdBKc","ulk41OUYuF","AXpwEuupzk","X6PinYh1hF","QbxXcIn3NS","pWiOsv1Hln","CxVEfyToGW","lj07QWMiS3","BpYhVJKWYR","ZUnqtNAFuw",
-"RzaZAGrDg7","8FmFHpvgjS","AkKTke6e4z","lsQGouupzk","s93Ml9GXkX","HzZT8F6PT2","Cfgr38TxD7","uLtKswiHrZ","FjHXRaez9y","NhXduHP433",
-"vOqCECqqaD","faHiruTacx","zbIYYQnJ1S","MezSWfcwDa","9eoRctjQxs","yvOMIK4GS8","MGlTFpT8wu","gIYvEzbIYY","I7p2aS77LH","5iGN5pFrrl",
-"TCgPpgf8rI","0ao3lPYBf4","Vprf21j5L8","BbwgAQssNC","OxWIHQWxoT","jtn0Xsx5Gl","StlDJhE1Ql","iB08lpvgjS","t59lRhYBCK","7fKYUSmGzv",
-"HRxd8dQ586","zQt6QbrhlQ","ZhwG1MGlTF","MmsIouPX7G","zY1GYVIlwP","AOgEeVLTy6","v1HlnprNT6","Vprf2AXpwE","iB08lAgJHQ","t98iWStlDJ",
-"QnJ1S8TxD7","GXdoHpFrrl","euZA5lCMxy","qaofNxReec","ydG8Ue6e4z","SjskQDQimp","6q6L9uPX7G","YOfrYWMiS3","IjTwPcQOnv","AmdQdaL6AJ",
-"CxVEf5nmWv","mX2GE0Wr5y","0Wr5ydmoS7","ThjNn7Ow5C","2hEEUGv3Fq","VerEA16lHc","kB5nPBCxeC","CxVEfVIlwP","8FmFHhi5X7","M6qcGpFrrl",
-"Cp3mZCK5W7","ogLgcFhtgl","Ta8f6gdQsS","uLtKsUvlv4","ydG8UIRh48","ulk41OHaBz","W7cTslsQGo","TXQ0ZpmeCd","MojnPNcICA","9eoRclViBv",
-"t98iW8xEKz","MojnPMezSW","QClRLMezSW","fcwDalweGy","48cHLCp3mZ","618Di07n1c","6q6L9hSSvQ","Oz8yZAmdQd","W3VFH4dEz6","YOfrYNcICA",
-"48cHLYw2oU","oVQp6Gv3Fq","Q6LixAmdQd","BFkb848cHL","NAFuwbrhlQ","l83UdzQt6Q","k85Aed85a9","jtn0XK4GS8","ulk41MmKGJ","J2mQiIKxdL",
-"v8yFNReKEW","MK07Y2DREs","5Nammhe9IA","GSQwjaDGtS","1v5hH16lHc","oGu6xMm8si","lCMxy0Wr5y","rz7UtS77LH","14FLRVIlwP","IKxdLTXQ0Z",
-"dpe1vWMiS3","lXFOBoVQp6","cL0aE0BmCy","VBjhzVerEA","nnP8ozQt6Q","CxVEfnFqik","Yw2oUcmXIX","zFgtBaL6AJ","WaWsvzmLYD","ogLgcBpYhV",
-"wDajXRBhp0","wiHrZ7fsYM","KsjRKqUJMd","WreyPUmaEv","brhlQOUYuF","EoToPF6PT2","6AFT0yEfy9","cL0aEuZPqg","TXQ0Z2ZHdk","55rfBjfREu",
-"IBe8k9GXkX","J2mQiUmaEv","HRxd8XflUq","IKxdLlsQGo","I7p2a48cHL","atef2lXFOB","uoStwgtCA5","a00b5uAWyp","0BmCys7Mxk","uTacxLDk6f",
-"UlU3MTa8f6","GXdoHRmDcr","2hEEU2DREs","ix74r2DREs","zz4ZU7hyVv","jtn0X618Di","dhSuHLDk6f","oQ87rFjHXR","lj07QkB5nP","S77LHyEfy9",
-"azIWp45cIH","iwzGkatef2","x3LDeqQxHP","VerEA3otm6","kZANm0MR5X","suY4xZUnqt","Q6LixfaHir","M6qcGyluBx","hUTw7pFrrl","v8yFNFnPFB",
-"ZUnqt5ZaEz","TXQ0ZC2Irc","BGaQYs4786","mX2GELDk6f","t98iW1LB1L","Qworuy94nw","ReKEWY1mC0","jSjS3NOHsz","aFFsstl72W","TwanoHlUbF",
-"Y1mC0S2Dfu","qUJMdl83Ud","X6PinksJby","uvf7AQbxXc","6AFT0JXljW","pAhR10BmCy","29QAzFGzgp","yvOMISbRYy","RACuj7fKYU","mz8gxrhl0J",
-"CIShGlkMUA","FhtglvOqCE","0h1b1C2Irc","618Dia00b5","CqqaD0h1b1","rz7UtyEfy9","nlaByNAFuw","PYBf4blLA9","xReecmX2GE","VLTy6i7WMQ",
-"nnP8ov1Hln","XflUqjeskS","ZuDtD2Yz7E","Q6LixJkzUn","MGlTF0Wr5y","45cIH24ARF","prNT6AXpwE","yluBxdhSuH","suY4xjeskS","ThjNngdQsS",
-"45cIHVBjhz","Ul4a1IBe8k","oQ87rM3zXL","Mm8sipWiOs","lH1ktjSjS3","FwEJzpAhR1","0ao3lCp3mZ","FnPFBQworu","uZPqgZ4I1v","2Yz7EFVMxo",
-"faHirhUTw7","Oz8yZQClRL","SjskQzmLYD","kB5nPSmGzv","uQIczxReec","U3yw5CdyBV","zmLYD24ARF","ix74rEdBKc","IjTwPC2Irc","i7WMQVerEA",
-"kZANmJXljW","azIWp1LB1L","FjHXRulk41","8hJdto8Uyd","QnJ1SMGlTF","ZhwG1pvgjS","Cfgr3d7vjM","fLNg8OxWIH","n8pJ9XflUq","EdBKcCIShG",
-"CNHmv5drc6","VBjhz8U2nU","2DREs8cVD3","VIlwPBCxeC","lm0pDvkCHH","jtn0Xaez9y","M3zXL0Wr5y","IRh48m4bxU","suY4xBGaQY","3otm6lpF6W",
-"LbRTHiqv4k","0KyfsfcwDa","n8pJ9OUqFM","CqqaDO3iyQ","jS1aj0Wr5y","Yw2oUYh1hF","gjUTulj07Q","580YDIKxdL","FPfSEQ6hMC","djsrv618Di",
-"iKqhraDGtS","lj07QO3iyQ","In3NSlkMUA","CdyBVx3LDe","lpF6WfLNg8","4QMc9kZANm","KZamHSs0Zu","MGlTFtjQxs","K20wKzHF1q","ZzJHW16lHc",
-"M3zXL0ao3l","G1RhSn1pmO","tl72WhSSvQ","lH1kt5iGN5","jtn0XUvlv4","K20wKOz8yZ","l83UdSbRYy","24ARFIn3NS","zz4ZUydG8U","jzUqRDz1R3",
-"hYBCK5VZjS","LbRTHqUJMd","6q6L9QnJ1S","dmoS7jzUqR","7Ow5C5Mg9r","Mm8siwiHrZ","pAhR1Waim6","M6qcGsoy9t","Yf2EcTCgPp","wiHrZlkMUA",
-"FhtgluN6r3","s7MxkTa8f6","8hJdtRzaZA","ZhwG1FjHXR","oGu6x0h1b1","piJSkVIlwP","RBhp0m4bxU","dpe1v0YAGH","07n1cUmaEv","pAhR1Q6Lix",
-"jtn0Xv8yFN","x3LDeVprf2","TCgPps4786","W3VFHtAOsr","S77LHF6PT2","0PktIJXljW","qUJMdRmDcr","uvf7AlsQGo","618DiKZamH","Y1mC0ogLgc",
-"fLNg8guMb8","48cHLbZLvS","azIWpVNCPd","aL6AJix74r","uTacxb29RJ","0PktIRpBQm","YOfrYdmoS7","rhl0JuLtKs","v2eC3gf8rI","e6e4zWMiS3",
-"WDVWJOUqFM","VNCPd48cHL","W7cTsdjsrv","iKqhrXyPZN","hE1Qlhi5X7","WmadAEoToP","Ss0ZuSjskQ","IRh48rKDLJ","d7vjMQssNC","B3qemWPmlx",
-"uZPqgrz7Ut","JJs5mGXdoH","piJSkuvf7A","zbIYYcL0aE","NOHszEoToP","7fsYMydG8U","DLhzMi7WMQ","BpYhVgtCA5","7X3uyulk41","OxWIHo8Uyd",
-"GSQwjGXdoH","QChxstvdkD","MmsIoChuy3","J2mQie6e4z","7ku1pUmaEv","BFkb8PYBf4","zmLYDd7vjM","XflUqDcpWB","yvOMIdjsrv","Q6LixZv7z0",
-"Nxx9VzQt6Q","OxWIH5ZaEz","nFqik5VZjS","Uvlv4FFDui","oQ87rkZANm","gdQsSuvf7A","d85a9kZANm","pFrrlC2Irc","5nmWv5Mg9r","RpBQmrhl0J",
-"t59lRAmdQd","D6rBySjskQ","AmdQdcShY2","CK5W7618Di","uQIczG1RhS","Z4I1vuZPqg","5iGN5FNYIM","JKWYRh1zcH","AOgEeSmGzv","fLNg8X6Pin",
-"I7p2auTacx","HfyNQCqqaD","WDVWJ8hJdt","lXFOBTXQ0Z","5drc6KZamH","29QAzv2eC3","BbwgAXflUq","Waim68TxD7","U3yw5piJSk","48cHLdhSuH",
-"pmeCdZ4I1v","uJScXSmGzv","2TRI7Gv3Fq","WaWsvaDGtS","o8UydNxx9V","lViBvpT8wu","ECMvUFhtgl","MmsIodQ586","ksJbyiKqhr","24ARFk85Ae",
-"zz4ZUU3yw5","b29RJHzZT8","G1RhSoVQp6","EoToPVBjhz","Gv3FqFGzgp","FjHXRQClRL","ydG8Uulk41","0KyfsU3yw5","nnP8oWDVWJ","OUqFMNo0Qb",
-"CK5W7580YD","pvgjS07n1c","piJSkoGu6x","fFDrJWaim6","aez9yxReec","XyPZN16lHc","0YAGHHzZT8","lCMxyk85Ae","JkzUnGSQwj","VerEALewvM",
-"lViBvTa8f6","lweGyAmdQd","t59lRuvf7A","UmaEvEdBKc","S77LH1LB1L","5ZaEzvLsmS","POUYS5Drn0","7Ow5Crhl0J","Oz8yZaez9y","0YAGHVIlwP",
-"ciuWzblLA9","gdQsS9y4lw","M6qcGhE1Ql","QYxC0JkzUn","EdBKcuLtKs","F6PT2s93Ml","d7vjMlCMxy","FxX9qAOgEe","xciqppT8wu","16lHcJ2mQi",
-"4W0TlPb1pa","16lHc6q6L9","Nxx9V8U2nU","Yf2Ec2Yz7E","aL6AJMm8si","QnJ1SlCMxy","GXdoHReKEW","pFrrl5nmWv","3otm6ix74r","9XyT9uLtKs",
-"jtn0XAgJHQ","Pb1pa7X3uy","prNT6jzUqR","GWqqXTCgPp","HlUbFWmadA","sx5GlgdQsS","48cHLKr8ys","soy9tZv7z0","IKxdLuLtKs","FGzgpAgJHQ",
-"JIqXiNxx9V","Ul4a1MaJQs","faHirbrhlQ","SjskQTCgPp","ZuDtD8FmFH","ulk41FjHXR","XyPZNFnPFB","ydG8Ux3LDe","OxWIHhYBCK","LbRTHi7WMQ",
-"ru4UGo8Uyd","vOqCEyofH3","uLtKsFcWrW","tlILtVLTy6","7lUXZy94nw","W7cTs2Yz7E","d7vjM6AFT0","IKxdLyToGW","5IhmGguMb8","5Drn0WaWsv",
-"JIqXiW3VFH","i7WMQS77LH","hi5X7JJs5m","VLTy6QWxoT","hYBCKvkCHH","uPX7GmX2GE","zqH0WFGzgp","1LB1LQssNC","QClRLFcWrW","aL6AJ8cVD3",
-"AOgEem4bxU","Oz8yZcmXIX","9GXkX9GXkX","Ul4a1FGzgp","7Ow5CFwEJz","Cfgr32Nslm","NcICA0Wr5y","vkCHHK20wK","dQ586OHaBz","9y4lwmX2GE",
-"gIYvEWaim6","vOqCEzqH0W","iB08lyluBx","2NslmRzaZA","xciqp6q6L9","ZzJHWIRh48","StlDJQbxXc","zFgtBFwEJz","tvdkDEOE1o","yofH3dpe1v",
-"7fsYMksJby","5Nammrhl0J","fqypyJXljW","kB5nPvOqCE","lViBvogLgc","hUTw707n1c","SbRYyKsjRK","VNCPdChuy3","k85Aehi5X7","jSjS3h1zcH",
-"zY1GYx3LDe","9iGoT2DREs","TwanoB3qem","SbRYyd7vjM","qQxHPCxVEf","5Namm2DREs","RACujzY1GY","x3LDe2ZHdk","o8Uydv1Hln","lpF6WPOUYS",
-"vOqCEqUJMd","Yh1hFQssNC","cL0aEQbxXc","BbwgAuAWyp","D6rBylH1kt","rKDLJlXFOB","S2DfulCMxy","CK5W7TCgPp","EoToPSmGzv","8xEKziwzGk",
-"9eoRcCNHmv","POUYSlXFOB","ru4UGuTacx","AOgEefLNg8","WPmlxyluBx","5ZaEzZ4I1v","ThjNn1LB1L","fFDrJRzaZA","h1zcHJKWYR","i3pydZ4I1v",
-"brhlQ6q6L9","taOXK7fKYU","tlILt2Yz7E","lsQGo3weIF","JXljW24ARF","zY1GYKr8ys","ksJbyvLsmS","FVMxo0BmCy","uoStw0h1b1","jiVBPt98iW",
-"J2mQiFwEJz","hi5X7K20wK","prNT68RCUA","l83UdyofH3","aL6AJM3zXL","FnPFBBbwgA","QnJ1SFnPFB","FLsphsqVrf","lkMUAtaOXK","S2DfucL0aE",
-"jS1ajn1pmO","ydG8UHRxd8","7hyVvpFrrl","DcpWB3weIF","ksJbyAOgEe","HP433580YD","ciuWzMaJQs","EOE1o9eoRc","0ao3lMmsIo","yofH3v1Hln",
-"64s8NiKqhr","iqv4kpAhR1","WmadA0MR5X","5ZaEzaL6AJ","TXQ0ZAmdQd","hE1QlFhtgl","zz4ZUHRxd8","cmXIXlkMUA","IBe8kJkzUn","BGaQYFnPFB",
-"QbxXc9rlg9","jeskSCdyBV","CxVEfhSSvQ","nnP8oaFFss","lpF6WjS1aj","5ZaEz8TxD7","mX2GEvkCHH","fLNg864s8N","uJScXd85a9","7fKYUNAFuw",
-"F6PT21v5hH","l83UdW7cTs","oVQp6CIShG","WMiS3qUJMd","RzaZAvOqCE","zz4ZUD6rBy","Yh1hFlkMUA","djsrvrhl0J","D6rBy5Namm","cShY2IKxdL",
-"cL0aE8xEKz","4W0TlnFqik","FPfSEI7p2a","d85a9UlU3M","EdBKcIjTwP","Oz8yZGSQwj","QChxsFPfSE","5Drn0QWxoT","QssNC16lHc","WmadAFLsph",
-"ThjNnW3VFH","EoToPoGu6x","OUqFMFwEJz","lj07QjS1aj","vLsmSJJs5m","lH1ktuZPqg","x3LDe1v5hH","1LB1LpAhR1","wDajX07n1c","1j5L80MR5X",
-"F6PT2D6rBy","0BmCyGXdoH","64s8NQClRL","1LB1LCxVEf","W3VFH2ZHdk","KZamHIRh48","K4GS8lViBv","2hEEUNOHsz","CIShGThjNn","Q6LixvLsmS",
-"1LB1LFPfSE","QYxC0AIYUu","5ZaEzWPmlx","prNT6Ta8f6","Yf2EcnlaBy","BFkb8Nxx9V","2NslmydG8U","IKxdLn1pmO","yToGWOxWIH","jfREuKr8ys",
-"0YAGHgIYvE","9GXkXmz8gx","ECMvUwDajX","pFrrlAIYUu","HP433d7vjM","W3VFHRBhp0","VNCPdvkCHH","xXTI45drc6","RpBQmFLsph","CNHmvK4GS8",
-"Y1mC0soy9t","tuDySNcICA","Yw2oUtjQxs","x3LDes7Mxk","zY1GYJIqXi","lweGy8U2nU","5nmWvqaofN","5drc6hYBCK","ulk41MaJQs","ksJby8FmFH",
-"HzZT8xXTI4","Waim60ao3l","8FmFH9XyT9","X6PinfcwDa","U3yw5pWiOs","0MR5Xpv0i7","kB5nPuAWyp","4W0TlRzaZA","UmaEvQChxs","ogLgcJ2mQi",
-"nFqik2TRI7","EdBKcl83Ud","iwzGkIBe8k","14FLRRBhp0","Vprf2tAOsr","jfREuGv3Fq","6AFT0rz7Ut","O3iyQCdyBV","d85a9d7vjM","dpe1vaL6AJ",
-"sx5GljeskS","2hEEUUl4a1","gtCA5azIWp","X6PinZUnqt","QClRLRsQUq","ReKEW5IhmG","IBe8kRkQke","sx5GlZv7z0","WPmlxwiHrZ","vLsmStuDyS",
-"aL6AJNo0Qb","hYBCKLDk6f","uJScXmz8gx","uvf7AoQ87r","K20wKS2Dfu","cShY2NhXdu","SmGzvW3VFH","07n1c4dEz6","8U2nUC2Irc","MmKGJWDVWJ",
-"Cp3mZuoStw","zqH0WRxrsm","ru4UG9eoRc","7fKYUatef2","fLNg8jtn0X","JRJQB5iGN5","dhSuHiqv4k","s47868xEKz","7hyVv7ku1p","O3iyQ5nmWv",
-"uLtKslweGy","hYBCKjSjS3","rz7UtK20wK","ECMvULDk6f","gtCA5brhlQ","a00b54W0Tl","0PktIVIlwP","HzZT82ZHdk","3otm6UlU3M","2Nslm7fKYU",
-"blLA9Pb1pa","ZhwG1tAOsr","pFrrlM3zXL","5Nammdjsrv","9GXkXSs0Zu","vkCHHGv3Fq","8RCUAVLTy6","lsQGoo8Uyd","NcICAtjQxs","IKxdLGSQwj",
-"O3iyQWaim6","jiVBPdpe1v","MaJQs07n1c","QWxoTni2v1","WmadApT8wu","he9IACqqaD","HRxd88U2nU","m4bxUs7Mxk","jeskSDLhzM","0YAGH0YAGH",
-"GXdoHTa8f6","FnPFB1j5L8","YjB9t64s8N","YjB9tLDk6f","h1zcHfqypy","JRJQBHzZT8","BFkb8gtCA5","KZamHBGaQY","vLsmSFGzgp","UmaEvPb1pa",
-"iKqhrF6PT2","0ao3lMezSW","s47865drc6","618DiHRxd8","X6PinMojnP","IKxdLQ6Lix","U3yw5yluBx","Mm8si29QAz","5VZjS618Di","Zv7z0K20wK",
-"Dz1R37X3uy","ZJTXHDQimp","JkzUnqaofN","jtn0X2hEEU","LDk6flm0pD","h1zcHuQIcz","RmDcrjfREu","iB08luN6r3","l83UdqUJMd","ReKEWguMb8",
-"Waim6hi5X7","3otm6tvdkD","wDajX4dEz6","JkzUnBGaQY","MaJQsUl4a1","pvgjSzmLYD","Dz1R3zqH0W","GXdoH64s8N","VNCPdBpYhV","MK07Ymz8gx",
-"55rfBJRJQB","ogLgc0MR5X","zQt6QvOqCE","t59lR8cVD3","gtCA5LDk6f","xciqpRACuj","zmLYD0Wr5y","yEfy9uvf7A","NAFuwprNT6","aFFssGv3Fq",
-"JKWYRnFqik","PYBf4HP433","ksJbygdQsS","P6bcgNxx9V","hSSvQzHF1q","gdQsSv2eC3","KASQ88U2nU","MK07YQChxs","4W0TlS2Dfu","ThjNnrKDLJ",
-"7Ow5CQClRL","okgRibrhlQ","MezSWzHF1q","5VZjS5iGN5","L7cGcuQIcz","24ARFM6qcG","okgRi2DREs","6AFT0MmKGJ","CxVEffcJOy","zY1GYzQt6Q",
-"Oz8yZO3iyQ","aL6AJMK07Y","yEfy9lCMxy","WaWsvZUnqt","MaJQs9eoRc","JJs5m7Ow5C","NhXduZhwG1","BpYhVFnPFB","RACujZJTXH","rz7Ut0Kyfs",
-"ZzJHWsqVrf","uZPqg0Wr5y","RpBQm0BmCy","KsjRKRxrsm","tjQxs4dEz6","FPfSERpBQm","QChxsy94nw","Qworu07n1c","Qworuuupzk","F6PT2wDajX",
-"LbRTHGWqqX","JXljWCIShG","uTacx5ZaEz","WPmlxECMvU","prNT6uJScX","RsQUqhSSvQ","2TRI7lkMUA","yvOMI618Di","pWiOsQYxC0","XyPZN64s8N",
-"M3zXLQnJ1S","jtn0XP6bcg","5IhmG2Nslm","vkCHH0YAGH","45cIHWmadA","cQOnvQWxoT","mX2GECIShG","iB08l7lUXZ","t59lRKASQ8","48cHLfmIK1",
-"m4bxUsuY4x","blLA9BFkb8","ZJTXHdjsrv","uQIczRACuj","5VZjSpiJSk","oVQp6oQ87r","RpBQmn1pmO","kB5nP8RCUA","kB5nPpFrrl","uupzkru4UG",
-"kZANmprNT6","NOHszEdBKc","tuDyS2ZHdk","vOqCEblLA9","h1zcHNo0Qb","7lUXZK20wK","ni2v1dhSuH","G1RhS5Namm","8hJdtuZPqg","qQxHPqaofN",
-"Mkgy8O3iyQ","i3pydStlDJ","RBhp0ogLgc","5nmWvS2Dfu","cQOnvFLsph","a00b5QWxoT","uTacxuAWyp","Dz1R3x3LDe","0BmCyjeskS","Oz8yZOHaBz",
-"cL0aEQssNC","sx5Glb29RJ","ru4UGuLtKs","5NammJKWYR","zQt6Qa00b5","yofH3uPX7G","uvf7AAgJHQ","U3yw5SWfou","Ss0ZuMezSW","gjUTuTa8f6",
-"Gv3FqjzUqR","M3zXLOUqFM","TXQ0ZYh1hF","IRh48Pb1pa","HzZT8MGlTF","4dEz648cHL","IBe8kBGaQY","AgJHQMkgy8","djsrvuZPqg","VNCPdStlDJ",
-"CdyBVS2Dfu","UlU3MOUqFM","s7MxkWmadA","ZzJHWgtCA5","jSjS3pFrrl","gf8rIhE1Ql","Ss0ZukB5nP","v2eC3qQxHP","jSjS3uN6r3","hUTw7h1zcH",
-"FNYIMW7cTs","0h1b19eoRc","pv0i78hJdt","uZPqgnFqik","OxWIHdQ586","hi5X7v1Hln","NhXduIn3NS","WmadAIRh48","hSSvQ7Ow5C","Ul4a1FVMxo",
-"J2mQis7Mxk","m4bxUQbxXc","JKWYRv8yFN","580YDK4GS8","OxWIHChuy3","Pb1pauZPqg","yvOMIBpYhV","RmDcr2ZHdk","HzZT8v8yFN","LbRTHkB5nP",
-"euZA5Z4I1v","Ss0ZuyToGW","FGzgpzQt6Q","WDVWJ24ARF","CqqaDbZLvS","aL6AJoVQp6","ciuWzHP433","kZANmVerEA","vLsmSzHF1q","v1HlnrKDLJ",
-"zHF1qrKDLJ","IjTwP5IhmG","ogLgcEoToP","Y1mC0F6PT2","0BmCyhE1Ql","SmGzvMmKGJ","5Drn0U3yw5","v2eC30ao3l","uTacxAIYUu","JkzUn0MR5X",
-"KZamHqQxHP","OUYuFdmoS7","6AFT0ni2v1","ciuWzuupzk","ni2v1lkMUA","jeskSqaofN","uupzkYh1hF","8xEKz29QAz","yEfy9uPX7G","yEfy9QClRL",
-"RsQUq14FLR","1j5L8s93Ml","ZzJHWJXljW","14FLRL7cGc","oGu6xGSQwj","AmdQdFwEJz","4QMc9vLsmS","XflUq2TRI7","RxrsmbrhlQ","D6rByMaJQs",
-"rz7Ut5iGN5","FPfSEkZANm","ru4UGpv0i7","Ss0ZuEOE1o","lweGyhi5X7","zbIYYNcICA","aDGtSo8Uyd","DG4sTCdyBV","0KyfsvLsmS","Yf2EcYOfrY",
-"PYBf4YOfrY","v8yFN14FLR","mX2GEatef2","oGu6xjfREu","s93Mlxciqp","MojnPVIlwP","blLA9CNHmv","FPfSEIn3NS","hYBCKlXFOB","tl72WOUqFM",
-"NcICAWaWsv","5drc6RACuj","5iGN5Gv3Fq","s7MxkzqH0W","BCxeCWPmlx","8cVD348cHL","8hJdtpvgjS","IRh48KASQ8","9rlg9FcWrW","prNT64dEz6",
-"QClRLWMiS3","7fKYUS77LH","l83UdMGlTF","0ao3ljtn0X","DLhzMfaHir","tvdkDJXljW","zmLYDuvf7A","W3VFHlXFOB","dhSuHRACuj","64s8NoGu6x",
-"Yf2EcUlU3M","RsQUqpWiOs","dhSuHuJScX","14FLRAgJHQ","bgJAzzbIYY","yToGWiKqhr","16lHcdhSuH","IBe8kdpe1v","mz8gxVerEA","d7vjMM6qcG",
-"xReec6q6L9","oGu6xCfgr3","CIShGs93Ml","AOgEeCNHmv","AOgEeSjskQ","jzUqR7Ow5C","6q6L9WaWsv","uupzk0ao3l","Waim67lUXZ","S2DfuDz1R3",
-"e6e4zQworu","JXljWMm8si","EdBKc24ARF","ix74rSmGzv","guMb8fcJOy","U3yw59iGoT","9rlg9Y1mC0","6AFT0h1zcH","jzUqRCIShG","FNYIM8cVD3",
-"8hJdttAOsr","jS1aj7X3uy","jiVBPWmadA","gjUTus4786","D6rByhYBCK","dpe1vs93Ml","Twano7fsYM","o8UydFFDui","EoToPzz4ZU","XflUqfaHir",
-"7fKYUD6rBy","ix74ruvf7A","n1pmONAFuw","t98iWP6bcg","K20wKHlUbF","D6rBysx5Gl","FPfSElCMxy","QssNC8FmFH","uJScX0Wr5y","uJScXNOHsz",
-"lpF6W14FLR","he9IAYOfrY","lViBvJ2mQi","jSjS3VerEA","n1pmO0BmCy","ogLgcReKEW","uQIczFhtgl","8hJdtZuDtD","C2IrcQClRL","6q6L9uJScX",
-"HP4332Nslm","pT8wuZJTXH","9XyT90YAGH","hSSvQwDajX","3weIFmX2GE","ulk41prNT6","uoStwI7p2a","Ul4a18U2nU","7ku1pzQt6Q","n1pmODQimp",
-"In3NSDQimp","CxVEfJKWYR","zqH0W7ku1p","0KyfsB3qem","pvgjSQnJ1S","MaJQsd85a9","5NammCxVEf","G1RhS3weIF","CxVEfKZamH","JJs5mJkzUn",
-"zHF1qazIWp","SmGzvRpBQm","xciqpn8pJ9","QbxXc0h1b1","lkMUA3weIF","EdBKcFwEJz","bgJAzuPX7G","m4bxUh1zcH","MezSWQnJ1S","Ss0Zu8cVD3",
-"6q6L9tvdkD","h1zcHmz8gx","x3LDecL0aE","hE1QlMaJQs","kZANmXflUq","cShY2ThjNn","C2IrctlILt","Cp3mZMGlTF","qaofNFjHXR","nnP8o3weIF",
-"y94nw24ARF","Waim6Ta8f6","CK5W7pmeCd","9iGoTiqv4k","yEfy9b29RJ","tjQxsNo0Qb","vOqCEjeskS","No0QbogLgc","D6rByzFgtB","FxX9qgIYvE",
-"24ARFfFDrJ","hYBCKYw2oU","ThjNn7lUXZ","DLhzMQbxXc","MmKGJIRh48","brhlQQbxXc","SWfouEOE1o","OHaBz5VZjS","nnP8oNxx9V","piJSkSjskQ",
-"Ul4a14dEz6","prNT6fcwDa","pAhR1suY4x","NcICAYw2oU","FGzgpQChxs","zmLYDzz4ZU","BCxeCWmadA","0MR5Xdpe1v","i7WMQI7p2a","OxWIHoGu6x",
-"Fhtgl9rlg9","2ZHdkFcWrW","CIShGlm0pD","ECMvUQ6hMC","NOHszblLA9","bgJAzIBe8k","GrDg7hUTw7","07n1c2Yz7E","qQxHPIn3NS","xXTI4PYBf4",
-"NAFuwjtn0X","dpe1vOHaBz","FnPFBOHaBz","wDajXpv0i7","gtCA5F6PT2","hE1Qljtn0X","x3LDeKr8ys","7Ow5CtvdkD","tjQxsWaim6","In3NSQbxXc",
-"yofH3tl72W","1v5hHyToGW","lXFOB64s8N","RACujIjTwP","ThjNnUmaEv","0BmCya00b5","5Mg9rtAOsr","Yh1hF2Nslm","uvf7An8pJ9","2TRI7WDVWJ",
-"RmDcriqv4k","QChxsRxrsm","IKxdLOxWIH","In3NS6AFT0","k85Ae9rlg9","LbRTHoGu6x","Nxx9VYh1hF","JXljWru4UG","BCxeCdQ586","Z4I1vPOUYS",
-"CqqaDuN6r3","Zv7z09y4lw","ksJbyuupzk","9y4lwnnP8o","d7vjMZuDtD","Dz1R3OHaBz","mz8gxSbRYy","2NslmECMvU","OHaBz64s8N","55rfB5Namm",
-"7Ow5CLDk6f","CdyBV618Di","Zv7z04dEz6","MGlTFuoStw","G1RhSprNT6","1j5L8IKxdL","16lHcAXpwE","NcICAO3iyQ","LDk6fi3pyd","fcwDaL7cGc",
-"qaofNW7cTs","lsQGobZLvS","SbRYyEoToP","0Wr5ys4786","tuDyS7fKYU","24ARFZuDtD","FNYIM618Di","AXpwEsqVrf","ReKEWciuWz","VIlwPs4786",
-"SmGzvjSjS3","a00b5BFkb8","CqqaDIKxdL","FnPFBDz1R3","hi5X729QAz","8cVD3cL0aE","RACujpWiOs","ciuWz0MR5X","vkCHHSjskQ","Kr8ysRACuj",
-"5nmWvk85Ae","16lHcZhwG1","7X3uyGXdoH","ogLgcLDk6f","nFqikiB08l","8RCUAsx5Gl","ZzJHWQnJ1S","Mkgy85Namm","QworutAOsr","I7p2aZzJHW",
-"s47868U2nU","iwzGkaDGtS","tjQxsdhSuH","blLA948cHL","QssNCHfyNQ","1v5hHogLgc","8RCUADG4sT","ThjNnK20wK","8RCUA4dEz6","VNCPdTwano",
-"VNCPd9iGoT","hE1Ql5ZaEz","IjTwPXyPZN","Cfgr3soy9t","RBhp0W3VFH","cL0aEMkgy8","9iGoTFGzgp","MmKGJNo0Qb","a00b5L7cGc","s4786Ul4a1",
-"jzUqRMK07Y","lCMxyMaJQs","oQ87ruZPqg","Waim6qaofN","IKxdL2TRI7","fqypyzHF1q","ksJbyy94nw","KZamHFwEJz","zHF1qMK07Y","AXpwEfcwDa",
-"lsQGos4786","ZUnqtbrhlQ","D6rByKZamH","QClRLStlDJ","taOXKQbxXc","9iGoTFnPFB","jiVBPpT8wu","NcICAyvOMI","cL0aEAgJHQ","DLhzMdmoS7",
-"uTacxAgJHQ","Kr8ys8U2nU","vOqCEPb1pa","soy9t7hyVv","cL0aEbrhlQ","t98iWk85Ae","blLA9KsjRK","7lUXZWDVWJ","QssNCtAOsr","RmDcrnnP8o",
-"s93MlOUqFM","9XyT9X6Pin","ZhwG1EOE1o","uN6r3v8yFN","prNT62hEEU","pvgjSSs0Zu","Y1mC0rhl0J","hYBCKlViBv","jtn0XZv7z0","LDk6fAkKTk",
-"Waim6v1Hln","h1zcHOUYuF","POUYSsqVrf","jiVBPQ6hMC","pmeCdFjHXR","soy9tvOqCE","FxX9q9rlg9","8hJdt9iGoT","rhl0JQChxs","EdBKc5Drn0",
-"Waim6zHF1q","cQOnvJXljW","FPfSEqaofN","OUqFMQClRL","RxrsmzY1GY","XyPZNS2Dfu","Yw2oUni2v1","Gv3FqLbRTH","SWfouDcpWB","jS1ajkZANm",
-"EOE1otlILt","Ul4a1i3pyd","pT8wu55rfB","DcpWB0YAGH","iKqhrfcwDa","fmIK1HRxd8","QnJ1SMmsIo","Nxx9VokgRi","zY1GYJkzUn","zz4ZUUvlv4",
-"XflUq2Yz7E","FjHXRM3zXL","FhtglzqH0W","t98iWjeskS","jfREuciuWz","ru4UGQnJ1S","F6PT2WMiS3","zHF1qkB5nP","HzZT8iKqhr","faHirm4bxU",
-"uoStwyvOMI","RxrsmfcJOy","lkMUAuoStw","No0QbjeskS","x3LDevLsmS","mz8gxhe9IA","VjCZquZPqg","AmdQdK20wK","pWiOscShY2","hSSvQIRh48",
-"29QAzIBe8k","LbRTHL7cGc","K4GS8AIYUu","ZhwG10ao3l","Pb1paFVMxo","Zv7z02hEEU","x3LDe4QMc9","In3NSo8Uyd","POUYSWPmlx","kZANmvkCHH",
-"rhl0J5iGN5","s4786v1Hln","KsjRKOz8yZ","Yf2Ec5nmWv","yvOMIfFDrJ","MGlTFwDajX","AOgEey94nw","0h1b12ZHdk","7lUXZbZLvS","TwanofcwDa",
-"Z4I1vECMvU","QbxXcNAFuw","Dz1R3ECMvU","48cHL2hEEU","GrDg7Yf2Ec","fcJOyrhl0J","8U2nUd7vjM","WmadAThjNn","Waim6CK5W7","xXTI4k85Ae",
-"o8Uyd0PktI","lkMUAuN6r3","5Drn08hJdt","K20wKU3yw5","taOXK0MR5X","RACujpmeCd","TwanopWiOs","aez9yHP433","OUYuFokgRi","Cp3mZU3yw5",
-"RsQUq9rlg9","2NslmuPX7G","qQxHPlj07Q","ogLgcKASQ8","yluBxtjQxs","wiHrZMGlTF","AOgEeM3zXL","cShY2C2Irc","Ul4a1Uvlv4","CdyBV3otm6",
-"CxVEfXflUq","9XyT945cIH","QnJ1SNOHsz","JRJQBt59lR","dpe1v2hEEU","a00b5DG4sT","1LB1LWreyP","OxWIHi3pyd","WreyPOxWIH","cQOnv55rfB",
-"jeskSlweGy","piJSkIn3NS","okgRiEOE1o","n8pJ9I7p2a","h1zcHuupzk","lj07QVLTy6","vOqCEjSjS3","s7MxkazIWp","vkCHHUmaEv","GXdoHHP433",
-"ZuDtDbrhlQ","tuDySPOUYS","Z4I1v07n1c","3otm6SjskQ","djsrvUl4a1","7Ow5CVIlwP","VNCPdokgRi","7ku1p8RCUA","2DREsQbxXc","BbwgAaFFss",
-"2Yz7EKZamH","QWxoTZhwG1","cShY2QYxC0","EOE1oWaWsv","IRh48PYBf4","hE1QlpAhR1","mz8gx0Wr5y","0BmCy16lHc","he9IAGWqqX","Y1mC0wiHrZ",
-"rhl0J8xEKz","he9IABFkb8","djsrvdmoS7","hi5X7580YD","4W0Tl0BmCy","9GXkXfFDrJ","SjskQgjUTu","v1HlnQ6hMC","EOE1oJKWYR","zz4ZUHzZT8",
-"PYBf4piJSk","QssNCTa8f6","K20wKtlILt","ECMvUazIWp","BFkb8ru4UG","GWqqXblLA9","h1zcH0h1b1","pT8wurhl0J","suY4xSWfou","G1RhSCxVEf",
-"MK07YMojnP","v8yFNxciqp","AgJHQn8pJ9","8hJdts7Mxk","nFqikgjUTu","uQIcz5nmWv","8xEKzVBjhz","In3NSm4bxU","gf8rIEdBKc","GWqqX16lHc",
-"C2IrcVprf2","tuDySVprf2","wiHrZQnJ1S","hE1QlYf2Ec","okgRiyToGW","64s8N2DREs","nlaBylpF6W","ogLgclViBv","k85Aed7vjM","yofH3jfREu",
-"PYBf4wiHrZ","brhlQ0PktI","jfREuzz4ZU","dpe1vatef2","ru4UGW7cTs","AXpwEXyPZN","n1pmOOHaBz","ZUnqtlXFOB","jzUqR29QAz","VLTy6Qworu",
-"VerEAjiVBP","MaJQsBCxeC","24ARF618Di","GrDg7ZJTXH","aez9yMaJQs","zqH0W5Drn0","9GXkXuQIcz","dpe1v7Ow5C","CNHmvCNHmv","iqv4kfcwDa",
-"n1pmOxciqp","vLsmSpmeCd","qQxHPrhl0J","I7p2alm0pD","3weIFdQ586","sqVrfWreyP","rhl0JQbxXc","5VZjSKASQ8","UmaEvChuy3","WMiS3CxVEf",
-"lCMxylsQGo","618Di0MR5X","aFFsst98iW","yToGWJ2mQi","5VZjSX6Pin","kB5nPlsQGo","xXTI414FLR","uAWypuN6r3","mX2GEzbIYY","8hJdtFnPFB",
-"M3zXL14FLR","JJs5mDcpWB","16lHcCp3mZ","2hEEURBhp0","zY1GYBCxeC","VBjhzuQIcz","48cHLIRh48","he9IApiJSk","kB5nPAIYUu","gtCA55ZaEz",
-"ix74r580YD","7lUXZPb1pa","nnP8o618Di","dmoS75iGN5","dmoS7Gv3Fq","StlDJpvgjS","BGaQYuoStw","uupzk29QAz","6q6L948cHL","5Drn0GSQwj",
-"ciuWziwzGk","7lUXZn8pJ9","vOqCEdjsrv","djsrvqUJMd","JkzUn0BmCy","e6e4zFGzgp","0YAGHDcpWB","L7cGc1j5L8","618DiwiHrZ","HRxd8uLtKs",
-"Yf2EcpT8wu","lkMUA8hJdt","BGaQYWaim6","EoToPSWfou","tvdkDgjUTu","gIYvE29QAz","HzZT8VjCZq","xReeczqH0W","piJSkBFkb8","QworuZuDtD",
-"faHirQnJ1S","IKxdLlpF6W","48cHLZuDtD","piJSk9XyT9","P6bcgQWxoT","EoToPcL0aE","tl72WNAFuw","pWiOs5Namm","t98iWzQt6Q","aez9ygtCA5",
-"jS1ajaFFss","XyPZNUvlv4","DG4sTcQOnv","yluBx5Drn0","Z4I1vFPfSE","No0Qb7X3uy","ReKEWbZLvS","ReKEWh1zcH","QClRLMGlTF","Ul4a1d7vjM",
-"6q6L95ZaEz","7X3uyGrDg7","7fKYUru4UG","jeskSYjB9t","ciuWzrhl0J","5iGN5zqH0W","tlILtguMb8","9XyT9Vprf2","IBe8kC2Irc","iB08ltl72W",
-"vLsmSPYBf4","4QMc9lm0pD","TXQ0ZY1mC0","y94nwRACuj","fcJOyUvlv4","zHF1qlpF6W","pWiOsO3iyQ","piJSkOxWIH","0h1b1dpe1v","zHF1qZJTXH",
-"UlU3MVNCPd","QClRLM3zXL","tvdkDjeskS","n1pmOFcWrW","24ARFCdyBV","MGlTFSjskQ","ECMvUdjsrv","pvgjSaFFss","ulk41he9IA","vkCHHjtn0X",
-"sx5Gl7hyVv","kZANmzQt6Q","uZPqgguMb8","k85AehYBCK","VBjhzVNCPd","L7cGcOHaBz","LbRTHQ6Lix","ydG8UU3yw5","L7cGch1zcH","7fsYMFxX9q",
-"jSjS3aez9y","VIlwPYf2Ec","wDajXFcWrW","Kr8ys580YD","uQIczUl4a1","RkQkeAOgEe","zQt6QuTacx","580YD2Yz7E","Yf2Ecn1pmO","AXpwELDk6f",
-"blLA9faHir","48cHLSbRYy","yToGWlkMUA","9eoRcCK5W7","Ul4a1G1RhS","aez9yeuZA5","KASQ8IBe8k","AOgEeKsjRK","lm0pDJIqXi","s93MlMGlTF",
-"cL0aE3weIF","RpBQmQnJ1S","lpF6WDG4sT","MK07Yv8yFN","fqypyiwzGk","xReecWreyP","Y1mC07Ow5C","CK5W7gdQsS","5IhmGulk41","JRJQBWaWsv",
-"4QMc9QbxXc","HfyNQ1j5L8","s4786cL0aE","0MR5XGXdoH","fqypyblLA9","he9IAZuDtD","pvgjSn1pmO","Mm8sigf8rI","Cp3mZvLsmS","Cfgr31j5L8",
-"taOXKMojnP","2DREsK4GS8","SWfoupv0i7","ix74rRBhp0","fFDrJgf8rI","tlILtuupzk","e6e4z0PktI","2Yz7EbZLvS","Cp3mZZJTXH","hSSvQprNT6",
-"JJs5mFGzgp","48cHL9GXkX","MK07YQssNC","8RCUAMm8si","tAOsr8hJdt","AkKTkjS1aj","OHaBz618Di","zY1GYFcWrW","bZLvSbrhlQ","lkMUAfqypy",
-"ThjNnFnPFB","SjskQB3qem","C2Ircaez9y","QnJ1SpT8wu","azIWpCdyBV","uTacxiB08l","CqqaDo8Uyd","MmKGJn8pJ9","QbxXcUmaEv","QssNC8U2nU",
-"tuDySVjCZq","QworuFhtgl","RsQUqpAhR1","AmdQd1j5L8","xciqpUmaEv","8RCUAbZLvS","8RCUADLhzM","fLNg81LB1L","SmGzvzbIYY","B3qemRmDcr",
-"CdyBV8hJdt","rhl0JUl4a1","lCMxyhUTw7","zHF1qb29RJ","S2Dfu2Yz7E","kZANmdmoS7","14FLRDz1R3","lH1ktazIWp","UmaEvQ6hMC","IKxdLCNHmv",
-"tuDySpvgjS","8RCUAhYBCK","UlU3MkZANm","0h1b1fqypy","RmDcrWaWsv","lm0pDUlU3M","JRJQBsuY4x","SbRYy0h1b1","D6rByblLA9","VBjhzuJScX",
-"SbRYysoy9t","MGlTFW3VFH","kB5nPsqVrf","RkQkea00b5","4W0TlFVMxo","rhl0J16lHc","VBjhzPb1pa","VIlwPTa8f6","Pb1pagtCA5","euZA5kB5nP",
-"pmeCdNxx9V","bgJAzblLA9","bZLvSCfgr3","QbxXccL0aE","faHir5drc6","MezSW4dEz6","TwanotlILt","8U2nUVIlwP","aez9y7X3uy","QnJ1Smz8gx",
-"16lHciqv4k","2TRI7aDGtS","XyPZN1LB1L","wDajX0YAGH","In3NSkZANm","In3NSCNHmv","piJSkjfREu","8xEKztvdkD","hSSvQsoy9t","4W0Tl0Kyfs",
-"X6PinrKDLJ","BCxeCBCxeC","xReecv2eC3","Ul4a1d85a9","7ku1pxciqp","DLhzMJRJQB","4dEz6suY4x","aez9y7hyVv","blLA9l83Ud","lXFOB8cVD3",
-"v1HlnVIlwP","BbwgAk85Ae","v8yFNX6Pin","M3zXLl83Ud","OUYuFCdyBV","OHaBzuTacx","YjB9tpT8wu","pmeCdxXTI4","B3qem16lHc","hUTw7IjTwP",
-"m4bxUCxVEf","StlDJMGlTF","pAhR1Uvlv4","yluBx5iGN5","8U2nU7X3uy","AmdQdtjQxs","TCgPpd85a9","QYxC0l83Ud","JKWYRtl72W","RBhp0t59lR",
-"rhl0JEoToP","48cHLM3zXL","guMb8S77LH","lCMxys7Mxk","4QMc9WMiS3","ThjNnSs0Zu","7ku1p5nmWv","IjTwPTa8f6","ZJTXHjeskS","0Kyfsuvf7A",
-"Yf2EcS2Dfu","9eoRcAIYUu","0KyfsnlaBy","blLA97fsYM","NhXduDQimp","DQimpaez9y","uvf7AM3zXL","6AFT0tvdkD","JkzUnuLtKs","fLNg8tlILt",
-"StlDJZUnqt","cQOnvCNHmv","MaJQsv1Hln","FFDuipFrrl","KASQ8ksJby","0h1b1Gv3Fq","8hJdtHRxd8","xXTI4Z4I1v","tlILtbZLvS","rz7UtaDGtS",
-"VjCZqdQ586","AmdQdzbIYY","mz8gxl83Ud","AIYUuqQxHP","faHirTXQ0Z","v8yFNl83Ud","tvdkDReKEW","Mm8siTCgPp","HP433d85a9","LewvMsoy9t",
-"faHiruupzk","rz7UtFxX9q","kZANmLbRTH","45cIHn8pJ9","RkQkes7Mxk","m4bxUfaHir","hi5X7aez9y","zQt6QO3iyQ","piJSkKASQ8","oVQp6pFrrl",
-"GWqqXQnJ1S","48cHLP6bcg","d85a9IKxdL","bgJAzyvOMI","xXTI448cHL","HRxd8VerEA","v1HlnOUYuF","AXpwEQssNC","fcJOyFGzgp","AmdQdFLsph",
-"RACuj0MR5X","sx5GlLDk6f","EdBKczY1GY","5drc6zqH0W","FLsphCp3mZ","tvdkDQbxXc","5IhmGFLsph","MK07YJ2mQi","aL6AJ8U2nU","Gv3FqpiJSk",
-"yEfy9ulk41","KASQ8U3yw5","3otm6AgJHQ","M6qcGZhwG1","xciqpQYxC0","YOfrYZv7z0","fmIK1tl72W","fLNg8i3pyd","aDGtS580YD","vOqCEm4bxU",
-"hYBCKciuWz","7lUXZwiHrZ","UmaEvtAOsr","Cfgr3ix74r","VBjhzECMvU","n1pmOQWxoT","IjTwPVNCPd","K4GS8FPfSE","FFDuipiJSk","uTacxAXpwE",
-"RpBQmS77LH","BGaQYSs0Zu","Vprf2AmdQd","a00b5MmsIo","5VZjSt98iW","0Wr5y8FmFH","ogLgcyvOMI","5drc6zY1GY","Vprf2ZUnqt","5IhmG7ku1p",
-"sqVrfStlDJ","taOXKrhl0J","WPmlxO3iyQ","VIlwP8FmFH","faHir9eoRc","v8yFNt98iW","7fsYMThjNn","29QAz2Nslm","EoToPni2v1","hE1QliKqhr",
-"jzUqRLewvM","MmsIoSs0Zu","o8UydW3VFH","Gv3FqS77LH","fcwDahYBCK","16lHcOz8yZ","HP433Pb1pa","8cVD3JIqXi","NhXduS2Dfu","7hyVvsuY4x",
-"azIWpzqH0W","pWiOsTa8f6","RsQUqFjHXR","2DREsiB08l","fFDrJQ6hMC","4W0Tlx3LDe","h1zcHZzJHW","v1HlnJJs5m","aL6AJciuWz","W7cTsQssNC",
-"8hJdt8FmFH","Yh1hFvLsmS","VBjhzLDk6f","uN6r3sqVrf","jSjS3FPfSE","NAFuwK20wK","okgRiPb1pa","RkQkepFrrl","jtn0X2DREs","faHirfcJOy",
-"qUJMda00b5","GSQwjzbIYY","CIShG1v5hH","RpBQmsuY4x","AXpwE0MR5X","uZPqgAkKTk","P6bcgFjHXR","B3qematef2","DLhzMNAFuw","mX2GEv1Hln",
-"CqqaDRzaZA","uoStw7Ow5C","pAhR1SmGzv","48cHLydG8U","MaJQsW3VFH","bZLvSiwzGk","ru4UGcShY2","uJScXblLA9","29QAzLbRTH","fcwDafFDrJ",
-"vOqCEQssNC","P6bcgRACuj","aL6AJFxX9q","cShY2OUYuF","fLNg8Vprf2","Ul4a129QAz","IBe8k2Nslm","blLA97Ow5C","HlUbFpvgjS","0h1b1MmKGJ",
-"7X3uyG1RhS","Oz8yZGrDg7","7X3uy5VZjS","tl72WuN6r3","9iGoTokgRi","U3yw5h1zcH","n8pJ9QClRL","WMiS3Waim6","qUJMdgtCA5","64s8NHzZT8",
-"pAhR17Ow5C","RsQUqOHaBz","8U2nUguMb8","P6bcgpv0i7","2DREs6AFT0","tvdkDY1mC0","64s8NUl4a1","i3pyd14FLR","faHirRACuj","AgJHQs7Mxk",
-"yvOMI2Nslm","zmLYDt59lR","rKDLJ45cIH","zbIYYlpF6W","cL0aES77LH","WDVWJFcWrW","cL0aEFNYIM","qaofNcShY2","MaJQs5Drn0","PYBf4zqH0W",
-"Yf2EcW3VFH","xXTI46q6L9","TCgPpP6bcg","pT8wufcJOy","TXQ0ZtuDyS","Pb1pa9y4lw","FNYIMbZLvS","fcJOyW3VFH","a00b5YjB9t","uLtKst59lR",
-"CK5W75ZaEz","qQxHPZzJHW","5IhmGFPfSE","GWqqXazIWp","Cfgr3gjUTu","48cHLRpBQm","NhXduUlU3M","guMb8jtn0X","hE1QlFPfSE","16lHcReKEW",
-"uLtKsTCgPp","pmeCdVBjhz","pAhR1Chuy3","UlU3M5Namm","TwanoThjNn","2ZHdkQWxoT","DQimpe6e4z","iKqhrQnJ1S","yluBxLewvM","HRxd87Ow5C",
-"QWxoTGSQwj","n8pJ9RACuj","v1HlnaDGtS","azIWp5drc6","BFkb8okgRi","jeskSKZamH","0PktIQ6Lix","EoToPBFkb8","pmeCdW7cTs","hSSvQuN6r3",
-"I7p2aCfgr3","TXQ0ZGrDg7","sx5Gl16lHc","Z4I1v5nmWv","xReecFwEJz","uPX7GPb1pa","v1HlnOHaBz","dQ586sqVrf","8xEKzn8pJ9","MaJQsVjCZq",
-"KsjRKdhSuH","OHaBzSbRYy","M6qcGHP433","vOqCEhe9IA","F6PT2Q6Lix","P6bcg0YAGH","lXFOBYh1hF","brhlQWmadA","uAWypLewvM","jSjS3BCxeC",
-"rz7Utsoy9t","uoStwtlILt","euZA5gdQsS","RzaZAdQ586","oQ87roQ87r","mz8gxWreyP","FxX9qDz1R3","pAhR11v5hH","5VZjSzHF1q","Ul4a12TRI7",
-"zHF1qe6e4z","y94nwQClRL","ZUnqtB3qem","qUJMdAgJHQ","XyPZNyEfy9","2hEEUUvlv4","okgRinnP8o","iwzGkS77LH","StlDJdmoS7","GXdoH55rfB",
-"HP4330YAGH","4QMc9Zv7z0","okgRiJJs5m","VLTy6JKWYR","FGzgpeuZA5","RzaZA48cHL","3otm6WaWsv","piJSkIRh48","WMiS3pAhR1","WDVWJF6PT2",
-"EdBKcOHaBz","xReeclweGy","5Mg9rS77LH","cmXIXFjHXR","zQt6Qfqypy","XflUqNcICA","FVMxoK20wK","tuDySFNYIM","14FLRyofH3","AgJHQY1mC0",
-"29QAzpT8wu","QWxoTF6PT2","tuDyS8TxD7","yToGWWMiS3","IjTwPReKEW","kZANmFPfSE","d7vjMaDGtS","ogLgchSSvQ","MK07YYf2Ec","HfyNQMK07Y",
-"EOE1otjQxs","VjCZqYw2oU","brhlQAmdQd","Ul4a1ZUnqt","45cIH5Namm","n1pmOS2Dfu","FxX9qU3yw5","P6bcgCqqaD","faHirhe9IA","1v5hH7X3uy",
-"W7cTs2ZHdk","VBjhz0MR5X","X6PinWDVWJ","uN6r348cHL","DG4sTReKEW","OUYuFM3zXL","HRxd8mz8gx","VerEA5iGN5","MmKGJLewvM","YjB9tlViBv",
-"SbRYycL0aE","AIYUuFhtgl","TwanoKr8ys","QChxsTXQ0Z","TCgPpIn3NS","7ku1pZ4I1v","5iGN5FcWrW","lCMxyn1pmO","XflUqtjQxs","DcpWBy94nw",
-"SbRYyjeskS","IjTwPuAWyp","DcpWBaFFss","2Yz7E8FmFH","uJScXChuy3","yToGWS2Dfu","9rlg9ZhwG1","5drc6fLNg8","RsQUqGXdoH","ZUnqtru4UG",
-"Uvlv4G1RhS","zqH0W2ZHdk","bgJAzKsjRK","S77LHcmXIX","6AFT0xXTI4","3otm6s93Ml","9GXkXDcpWB","FwEJzy94nw","Yh1hFMGlTF","wiHrZXyPZN",
-"lXFOBO3iyQ","RACuj07n1c","Dz1R3QClRL","jSjS3lj07Q","BFkb8y94nw","2TRI7blLA9","uJScXbrhlQ","iqv4kvkCHH","Y1mC024ARF","jS1ajPOUYS",
-"7lUXZPOUYS","9rlg98RCUA","zY1GYFFDui","FwEJzksJby","t59lRciuWz","ECMvUCK5W7","tuDySYw2oU","6q6L955rfB","zmLYDMaJQs","okgRiFnPFB",
-"0h1b1prNT6","uupzkS2Dfu","brhlQAgJHQ","oVQp6kB5nP","HzZT8JXljW","OUYuFFjHXR","s4786JXljW","K4GS8ni2v1","yToGWix74r","hSSvQ5Drn0",
-"16lHcTCgPp","wiHrZpFrrl","FNYIMuZPqg","mz8gxo8Uyd","piJSk6AFT0","kB5nPRmDcr","dpe1v5iGN5","VIlwPReKEW","5Drn0rKDLJ","0Wr5y2Nslm",
-"aL6AJfaHir","PYBf4UlU3M","IjTwPs4786","6q6L9SmGzv","6AFT0X6Pin","Ta8f67Ow5C","FPfSEOUqFM","SjskQQYxC0","0KyfsMkgy8","OHaBzyluBx",
-"HP433Ta8f6","lViBvSmGzv","FhtglaFFss","POUYSoGu6x","FwEJzU3yw5","qQxHPK20wK","8xEKztlILt","ogLgcdpe1v","lH1ktWaWsv","In3NS7fKYU",
-"pT8wu2Yz7E","Q6hMCksJby","he9IA6AFT0","vkCHHs4786","gIYvEGWqqX","AXpwED6rBy","RsQUqgdQsS","yofH3prNT6","vLsmSoVQp6","Waim6KsjRK",
-"YjB9t5IhmG","LbRTHSs0Zu","Y1mC0yvOMI","jzUqR1j5L8","yvOMI8cVD3","HfyNQt98iW","5VZjSoGu6x","vkCHHciuWz","gf8rIHzZT8","QnJ1SOz8yZ",
-"CdyBVzHF1q","piJSk0YAGH","kZANmKZamH","lCMxyfcJOy","s4786wiHrZ","No0QbpvgjS","8FmFHYjB9t","55rfBjzUqR","8hJdt5Namm","lCMxygf8rI",
-"Ul4a1ogLgc","oQ87rs7Mxk","HfyNQ580YD","VBjhze6e4z","NcICARACuj","yluBxx3LDe","BCxeCQChxs","5NammgIYvE","jiVBPWaim6","cQOnvoGu6x",
-"GrDg7m4bxU","RACujFwEJz","fLNg8d85a9","Vprf2tvdkD","UlU3MdmoS7","AXpwEKsjRK","KZamHI7p2a","Yh1hFUmaEv","RzaZAEdBKc","JJs5mYOfrY",
-"5nmWv2TRI7","Cfgr3lm0pD","MmsIozY1GY","8cVD36q6L9","ksJbyxXTI4","No0QbIKxdL","hE1QlOz8yZ","IRh48hi5X7","Mkgy89rlg9","hSSvQeuZA5",
-"t59lRNxx9V","NOHszC2Irc","x3LDeCp3mZ","8xEKzt98iW","BCxeCblLA9","hYBCKx3LDe","NhXdupAhR1","HzZT8fcJOy","uoStw9y4lw","piJSkX6Pin",
-"bgJAza00b5","AgJHQRsQUq","VLTy6O3iyQ","SmGzvtvdkD","5Drn0RkQke","BbwgAzQt6Q","xXTI4oVQp6","uvf7ACfgr3","Kr8ysNxx9V","gf8rIAkKTk",
-"IKxdLVjCZq","jiVBPDcpWB","yEfy9BGaQY","hUTw7uLtKs","lj07QXyPZN","8xEKzpAhR1","2ZHdkazIWp","5NammxXTI4","BpYhV2ZHdk","7ku1pFnPFB",
-"oGu6xX6Pin","MmsIo8hJdt","jfREu0MR5X","k85AeJIqXi","brhlQjS1aj","KASQ8Zv7z0","JXljWRpBQm","3otm6zQt6Q","7lUXZRpBQm","cmXIXSmGzv",
-"MaJQsGSQwj","pFrrlSbRYy","NOHsz7Ow5C","dQ586FGzgp","29QAz2DREs","Yw2oU9GXkX","vkCHHpWiOs","NOHszLbRTH","b29RJ5Drn0","tvdkDQWxoT",
-"rz7UtIRh48","Q6LixyEfy9","AXpwEHP433","aFFsstjQxs","dmoS7VIlwP","8RCUA5drc6","kB5nPydG8U","zFgtBv2eC3","OUYuF8RCUA","QssNCNOHsz",
-"07n1cuN6r3","QYxC0v8yFN","Yf2EcGv3Fq","guMb8t59lR","8cVD3Yh1hF","lweGyI7p2a","k85AeK20wK","Yh1hFuLtKs","sqVrfWDVWJ","P6bcg9eoRc",
-"ZhwG1HlUbF","yvOMINhXdu","BCxeCK4GS8","8xEKzoVQp6","prNT6bgJAz","7lUXZCdyBV","yofH3hYBCK","JRJQB2ZHdk","5nmWvJIqXi","ru4UGv2eC3",
-"7fsYM580YD","gdQsSQWxoT","pWiOspvgjS","IKxdLjtn0X","x3LDe9rlg9","W7cTsv1Hln","uN6r3l83Ud","Dz1R3d85a9","ulk41FxX9q","8cVD3FVMxo",
-"kB5nP8U2nU","jeskS5nmWv","lpF6W07n1c","BbwgAQ6Lix","D6rBy0MR5X","CdyBVmX2GE","4dEz6pv0i7","h1zcHt59lR","Cfgr3XflUq","Gv3FqRBhp0",
-"J2mQi8FmFH","07n1cIBe8k","NcICAVIlwP","K4GS8oQ87r","tl72WTCgPp","lH1ktZzJHW","ciuWz48cHL","ZhwG1Mkgy8","uupzkQ6Lix","CIShGrhl0J",
-"5iGN5v2eC3","rhl0JKASQ8","Oz8yZK4GS8","qUJMdOHaBz","faHirlXFOB","7fKYUKsjRK","BFkb84W0Tl","zz4ZU7ku1p","dhSuHzQt6Q","DcpWBix74r",
-"5iGN5580YD","B3qemYh1hF","HlUbF9iGoT","GWqqX2ZHdk","Dz1R30ao3l","Gv3FqtaOXK","0YAGHuZPqg","5iGN5uupzk","DcpWBUl4a1","atef2Ta8f6",
-"yEfy9ydG8U","Cp3mZWaWsv","RsQUqzY1GY","Pb1pa1LB1L","tvdkD0BmCy","0Wr5y4W0Tl","UmaEvlweGy","FxX9q8cVD3","cShY2QnJ1S","ReKEWIBe8k",
-"ciuWz3otm6","rKDLJZzJHW","5nmWvNxx9V","Yf2EcM3zXL","bZLvSOxWIH","xXTI48TxD7","S2DfuUmaEv","sqVrfJRJQB","GrDg7OUYuF","8U2nUzY1GY",
-"LDk6fyofH3","WreyPY1mC0","uvf7AFhtgl","lH1ktiwzGk","7hyVvsqVrf","VIlwPXflUq","TCgPpTwano","uupzkQWxoT","MmsIoVprf2","s47865VZjS",
-"lkMUA7fKYU","okgRizFgtB","HP43316lHc","YOfrYMm8si","atef2HfyNQ","6q6L9OUqFM","SjskQlXFOB","zFgtBfLNg8","CdyBVOxWIH","sqVrfIBe8k",
-"Kr8ysWaim6","e6e4zFLsph","CqqaDpT8wu","MmKGJLbRTH","0ao3l7X3uy","d85a9FxX9q","PYBf4RmDcr","rhl0Jxciqp","taOXKQChxs","gf8rIyluBx",
-"Vprf2JIqXi","uupzkPb1pa","FnPFBW7cTs","RsQUqCdyBV","S77LH7Ow5C","Qworu7Ow5C","zbIYY2DREs","0BmCy8U2nU","ulk41lViBv","C2IrcguMb8",
-"CK5W7SmGzv","i3pydFGzgp","G1RhSv1Hln","45cIHIKxdL","uupzktl72W","QChxsPYBf4","pT8wu0MR5X","djsrvOUYuF","hi5X7hE1Ql","B3qemCp3mZ",
-"AmdQd8RCUA","5iGN52hEEU","DG4sTuZPqg","oVQp6ix74r","brhlQWDVWJ","kB5nPDG4sT","yluBxBFkb8","Gv3FqCfgr3","d85a9okgRi","3weIFbgJAz",
-"RzaZAQbxXc","jfREufLNg8","uTacxTwano","VBjhzHfyNQ","Z4I1vAOgEe","kZANmogLgc","IjTwPix74r","v2eC3xXTI4","cQOnvCIShG","ydG8UoGu6x",
-"lCMxyIBe8k","BGaQYJKWYR","tuDySFjHXR","RpBQmSbRYy","CIShGlXFOB","d85a9JkzUn","SWfou5Mg9r","8FmFH0BmCy","fcJOyDQimp","VIlwP5Mg9r",
-"faHirdjsrv","aFFssJRJQB","oVQp62ZHdk","ZuDtDaDGtS","v1Hln0YAGH","iqv4kBbwgA","lViBvhi5X7","NhXduaL6AJ","Zv7z0atef2","RACujL7cGc",
-"dpe1vQssNC","WaWsva00b5","ZUnqt5drc6","jfREuhe9IA","gtCA5x3LDe","piJSkGrDg7","wiHrZHRxd8","pAhR18RCUA","DG4sTgf8rI","uQIczKsjRK",
-"brhlQB3qem","8hJdtBGaQY","SmGzvhSSvQ","RsQUqQYxC0","WDVWJ3weIF","LDk6fJIqXi","fcwDaIBe8k","CxVEf580YD","jtn0XMm8si","atef2GWqqX",
-"NOHszOz8yZ","PYBf448cHL","JJs5mi7WMQ","djsrvCNHmv","sqVrfuvf7A","SbRYy07n1c","s93MllsQGo","XyPZNThjNn","2Yz7EFPfSE","iwzGkCxVEf",
-"UmaEvYf2Ec","0MR5XBCxeC","14FLR7ku1p","C2IrcuTacx","HfyNQZ4I1v","5iGN5C2Irc","Q6hMCDcpWB","d7vjMFPfSE","dmoS7tvdkD","Ul4a1uJScX",
-"iB08l5drc6","FLsphEoToP","bZLvSGv3Fq","rKDLJUlU3M","In3NSdhSuH","m4bxUtAOsr","48cHLt98iW","gdQsSW7cTs","dQ586fmIK1","GWqqXfaHir",
-"ZzJHWzFgtB","S77LH9eoRc","HfyNQs7Mxk","zY1GYU3yw5","tvdkDpvgjS","vkCHHuPX7G","ksJbyECMvU","TwanouAWyp","s7MxkIn3NS","lm0pDHRxd8",
-"zFgtBDcpWB","2ZHdkuAWyp","5nmWvt59lR","i7WMQydG8U","HlUbFCxVEf","DQimpv2eC3","uAWypWreyP","VjCZqhYBCK","soy9tGWqqX","G1RhSNOHsz",
-"9iGoTIRh48","YjB9tYh1hF","IjTwPWreyP","jiVBPiKqhr","wiHrZvkCHH","ZzJHWFxX9q","zqH0WSmGzv","faHiraDGtS","9GXkXuAWyp","PYBf4SbRYy",
-"BbwgAHzZT8","uQIcz07n1c","Yh1hFMK07Y","ni2v1atef2","sqVrf9iGoT","QWxoTxXTI4","yvOMI2hEEU","gdQsSgf8rI","BpYhV5IhmG","aFFsst59lR",
-"BFkb8zbIYY","s93MlzY1GY","ru4UGHRxd8","TXQ0ZX6Pin","uAWyp1LB1L","lCMxylm0pD","Yf2EchUTw7","8cVD35ZaEz","9XyT9VBjhz","G1RhSBCxeC",
-"DLhzMtl72W","IKxdLNhXdu","kB5nP1v5hH","gtCA5vkCHH","7lUXZhUTw7","xReecuLtKs","FxX9qcShY2","Kr8yst59lR","okgRi6q6L9","HP433AmdQd",
-"uLtKsfFDrJ","YjB9tjSjS3","tl72W0PktI","DG4sTGv3Fq","9eoRc8FmFH","CdyBVt98iW","ECMvUhE1Ql","SjskQqQxHP","cmXIXdpe1v","oQ87rwiHrZ",
-"yEfy9uZPqg","Mkgy80Kyfs","uPX7G16lHc","45cIHMm8si","9iGoT9rlg9","ciuWz0Kyfs","S77LHrz7Ut","8xEKzpmeCd","QbxXcMojnP","QnJ1SVjCZq",
-"ulk410ao3l","9XyT98cVD3","zz4ZUFnPFB","cL0aETCgPp","zFgtBcQOnv","RpBQmLbRTH","JJs5mXflUq","WmadAzmLYD","yvOMIDz1R3","ni2v1QbxXc",
-"Oz8yZ24ARF","55rfBpvgjS","t59lRGXdoH","2ZHdkciuWz","qQxHPzFgtB","qUJMdxReec","UlU3MlH1kt","580YDfqypy","pmeCdDz1R3","lj07QaFFss",
-"5nmWvDG4sT","i3pydKsjRK","FwEJzHfyNQ","n8pJ9OHaBz","MezSWzbIYY","9GXkXoQ87r","blLA9prNT6","AIYUuZUnqt","nnP8oZ4I1v","YOfrYTCgPp",
-"he9IApWiOs","gdQsSQYxC0","sqVrfM6qcG","W3VFHzY1GY","CIShG45cIH","yEfy9ZJTXH","Q6LixQYxC0","zmLYDa00b5","uPX7GRmDcr","KZamHEOE1o",
-"qaofNsqVrf","pAhR1zbIYY","Ul4a1K4GS8","k85Aes7Mxk","5nmWvW3VFH","hE1QlG1RhS","QnJ1SeuZA5","y94nwhi5X7","RxrsmCNHmv","AXpwEQClRL",
-"QClRLS77LH","GSQwji7WMQ","TXQ0ZQbxXc","VerEAStlDJ","tl72W4W0Tl","ThjNnAIYUu","pAhR107n1c","Fhtglv1Hln","GWqqXpT8wu","GSQwjlpF6W",
-"WmadA7Ow5C","8TxD7UlU3M","guMb8k85Ae","iKqhrtaOXK","B3qemRsQUq","8TxD7m4bxU","Q6hMCHP433","guMb8VBjhz","OUYuFFwEJz","aez9yd7vjM",
-"DLhzM9GXkX","EOE1olXFOB","dpe1vt98iW","Yh1hF4W0Tl","1v5hHv1Hln","mX2GE2DREs","VBjhzQClRL","t98iWKASQ8","FnPFBNo0Qb","uAWypPOUYS",
-"Yf2EcrKDLJ","CxVEf3otm6","O3iyQ5VZjS","pvgjSzqH0W","1v5hHU3yw5","F6PT2FcWrW","zFgtBtl72W","Cfgr3tvdkD","29QAzzFgtB","U3yw57fsYM",
-"OHaBzNOHsz","KsjRKW7cTs","rz7Ut8TxD7","Oz8yZ6q6L9","L7cGchE1Ql","lCMxyJXljW","JKWYRCNHmv","MGlTFQnJ1S","UmaEvsqVrf","gdQsSaFFss",
-"dhSuHHP433","0Wr5yMmKGJ","ogLgcZUnqt","SbRYyhi5X7","29QAz16lHc","2ZHdkQClRL","J2mQiOHaBz","FPfSErKDLJ","v2eC3tl72W","pT8wuyluBx",
-"aez9y5Drn0","jeskS5iGN5","nlaByfcJOy","zY1GYzHF1q","CdyBVwiHrZ","iB08lRmDcr","uN6r3prNT6","Z4I1vn1pmO","8hJdtuTacx","aL6AJHfyNQ",
-"nlaBywiHrZ","zqH0W5IhmG","Dz1R3xXTI4","DG4sTVBjhz","ogLgcFLsph","Chuy3guMb8","9XyT99GXkX","P6bcgxReec","3otm6uPX7G","OxWIHaez9y",
-"dhSuHfqypy","hYBCKIBe8k","blLA9WmadA","zmLYDlCMxy","nlaByMGlTF","HP433HRxd8","4dEz6bZLvS","S2Dfui3pyd","8xEKzCqqaD","Kr8ysBbwgA",
-"O3iyQUlU3M","uLtKsb29RJ","Chuy3zmLYD","8U2nUBGaQY","9iGoTY1mC0","tjQxsxXTI4","taOXKOxWIH","VjCZqUlU3M","hYBCKTwano","W3VFHPb1pa",
-"BGaQYAIYUu","ECMvU64s8N","cL0aElj07Q","Chuy3QbxXc","iwzGk6q6L9","jS1ajzqH0W","mX2GE4W0Tl","nFqikvLsmS","VNCPdFxX9q","QWxoTprNT6",
-"FhtglECMvU","s93Ml0Kyfs","v8yFND6rBy","NhXdu9eoRc","lpF6WnnP8o","PYBf4d7vjM","M6qcGPOUYS","24ARFyEfy9","NcICAXyPZN","2ZHdkIRh48",
-"Vprf2LewvM","GXdoHgIYvE","qQxHPcL0aE","ydG8UqUJMd","uQIczUmaEv","AkKTkru4UG","QClRLhE1Ql","fcJOyBFkb8","uupzkdpe1v","CIShGCIShG",
-"IBe8krKDLJ","JkzUn7fsYM","uZPqg0MR5X","lm0pDaFFss","AIYUuVerEA","5drc6BCxeC","fFDrJuvf7A","NAFuwlweGy","QYxC0yvOMI","pmeCdWmadA",
-"uZPqgVBjhz","SmGzvqaofN","y94nwgjUTu","i7WMQWMiS3","prNT6NOHsz","Mm8sidQ586","9XyT9RzaZA","wiHrZBFkb8","Ss0ZuCNHmv","CK5W7IBe8k",
-"7ku1pFGzgp","RmDcrM3zXL","uupzkEOE1o","K4GS8Nxx9V","M6qcGOUqFM","M6qcGFwEJz","fqypy7lUXZ","uPX7GFLsph","AmdQd5ZaEz","gf8rIazIWp",
-"h1zcHtAOsr","ru4UGwDajX","StlDJuupzk","yluBxjiVBP","P6bcgQworu","2hEEUQChxs","fmIK1uupzk","GrDg7l83Ud","cmXIXlViBv","LewvM5drc6",
-"iB08lfcJOy","2ZHdkJkzUn","CIShGRpBQm","MK07YRkQke","pv0i7Vprf2","iqv4kPOUYS","OUqFMnFqik","ZhwG1sqVrf","djsrvs93Ml","2Nslm07n1c",
-"cQOnvazIWp","aFFsszz4ZU","HP433IBe8k","BpYhVtvdkD","lCMxyMojnP","xXTI4U3yw5","3weIFn1pmO","9iGoTpT8wu","k85Ae29QAz","IKxdLJRJQB",
-"MGlTFwiHrZ","DLhzMhYBCK","7X3uyFGzgp","FwEJzEoToP","vLsmS6AFT0","7Ow5CF6PT2","zHF1qtvdkD","1j5L8QChxs","0Wr5yvLsmS","QClRLVBjhz",
-"x3LDedpe1v","W7cTsOz8yZ","Pb1paSmGzv","hSSvQNOHsz","29QAz9iGoT","QnJ1S5drc6","16lHche9IA","qUJMdbrhlQ","iwzGk2Yz7E","FLsphAOgEe",
-"XflUqNhXdu","s4786cShY2","HlUbFHRxd8","7fKYUMmKGJ","0Wr5yaez9y","4QMc94QMc9","dmoS7FPfSE","Waim6pT8wu","FFDuix3LDe","Mkgy8BpYhV",
-"WmadAfaHir","yToGWCxVEf","nnP8oAXpwE","mz8gxRpBQm","BpYhVt59lR","xciqpVIlwP","lj07Q2Yz7E","dpe1v8xEKz","fmIK1Vprf2","rhl0JfaHir",
-"7fsYMsqVrf","aDGtS0h1b1","BCxeCyToGW","JIqXijfREu","W3VFHC2Irc","55rfBvkCHH","6q6L9cL0aE","0PktIulk41","atef2lH1kt","zz4ZUDLhzM",
-"DG4sTGWqqX","7hyVvlweGy","ZUnqtSs0Zu","S77LHiqv4k","Nxx9VZhwG1","MGlTFPOUYS","C2Irc1j5L8","MmKGJatef2","RsQUqn8pJ9","qUJMdmz8gx",
-"ni2v1kZANm","Z4I1vatef2","fmIK1nFqik","zFgtBJJs5m","HzZT8SWfou","IjTwPLDk6f","mz8gxdQ586","x3LDe5VZjS","mz8gxxReec","uQIcziqv4k",
-"yvOMIs7Mxk","AgJHQMK07Y","tuDySNhXdu","hi5X7QChxs","cQOnvprNT6","lViBvYOfrY","LDk6fOUqFM","6AFT08cVD3","cmXIXMojnP","TCgPpdmoS7",
-"07n1cuLtKs","gjUTu2ZHdk","TXQ0ZAgJHQ","9rlg9EdBKc","FcWrW6q6L9","zQt6Qh1zcH","vkCHHWDVWJ","uvf7AzqH0W","2ZHdky94nw","8U2nUBFkb8",
-"e6e4zCp3mZ","ydG8UNAFuw","QnJ1SNAFuw","ksJby9y4lw","RBhp0OHaBz","YjB9taez9y","7fsYMdQ586","jtn0XfcJOy","s4786taOXK","tuDyScL0aE",
-"RkQke8RCUA","5iGN5VLTy6","rhl0JcShY2","dhSuHCp3mZ","rKDLJ07n1c","0h1b1vLsmS","QChxs5drc6","LbRTHuAWyp","QbxXckZANm","cQOnvuupzk",
-"y94nwulk41","hSSvQWreyP","FGzgpfmIK1","5iGN5iKqhr","nnP8o0PktI","ksJbyzbIYY","faHirKsjRK","jeskSfqypy","n8pJ9dmoS7","No0Qbgf8rI",
-"KsjRKSbRYy","6q6L9pAhR1","TCgPpMmsIo","8FmFHdpe1v","ReKEWJJs5m","RxrsmG1RhS","X6Pinxciqp","Mm8siuAWyp","rhl0J2DREs","piJSkpWiOs",
-"lj07QokgRi","cmXIXuPX7G","4dEz6AXpwE","4W0TlCNHmv","yvOMIaL6AJ","2NslmpFrrl","ru4UGFNYIM","8xEKzZUnqt","QworupvgjS","7fsYMyluBx",
-"07n1cJkzUn","KASQ8I7p2a","VjCZqs93Ml","s93MlaDGtS","wiHrZ0MR5X","rKDLJfLNg8","K20wK0MR5X","NAFuwk85Ae","lViBvDG4sT","prNT6nFqik",
-"suY4xCK5W7","0h1b1Q6Lix","EdBKcM3zXL","ZUnqtmX2GE","VNCPdlXFOB","aL6AJSmGzv","lXFOBgIYvE","OxWIHuLtKs","MK07Y0ao3l","1LB1LCp3mZ",
-"iwzGkVjCZq","CIShGt59lR","WreyPGWqqX","nlaByazIWp","5iGN5pv0i7","a00b545cIH","M3zXLv2eC3","5Drn0FGzgp","BFkb89XyT9","n8pJ9IBe8k",
-"3otm6RsQUq","G1RhSNAFuw","xciqpQ6hMC","djsrvSs0Zu","P6bcgs7Mxk","DG4sTfaHir","Fhtgl6q6L9","v2eC3piJSk","i3pyds7Mxk","lweGylkMUA",
-"ni2v1zQt6Q","0KyfsBGaQY","JXljWqaofN","aDGtSnlaBy","bZLvS07n1c","BGaQYAmdQd","DcpWBl83Ud","4QMc9lkMUA","QssNClsQGo","1v5hHfcJOy",
-"AOgEennP8o","SmGzv0PktI","5NammlkMUA","WDVWJaL6AJ","IRh48cmXIX","oGu6xtuDyS","RxrsmMK07Y","MGlTF5drc6","fLNg8CdyBV","QssNCM3zXL",
-"zHF1qnlaBy","OxWIHCK5W7","KZamHCNHmv","MezSW2TRI7","FLsphXflUq","9XyT9cShY2","9iGoTv2eC3","ulk41W7cTs","gjUTu1LB1L","sqVrf0Wr5y",
-"nFqikYw2oU","QClRLVjCZq","1j5L8hUTw7","xXTI4FnPFB","3otm6JJs5m","W3VFHhi5X7","HP433gdQsS","16lHcLDk6f","ReKEWQbxXc","yToGW2TRI7",
-"Chuy364s8N","BGaQYXyPZN","QClRLhYBCK","xciqpMmKGJ","UlU3M1j5L8","S77LHnFqik","GXdoH1LB1L","0Wr5y7lUXZ","sx5GliwzGk","uTacxBFkb8",
-"DQimpjSjS3","CdyBVKZamH","gf8rI8xEKz","6AFT016lHc","pWiOsgjUTu","Vprf2suY4x","djsrv2Yz7E","s7MxkpiJSk","0ao3lHRxd8","MmKGJuPX7G",
-"DcpWBFVMxo","FPfSEdQ586","gdQsSFcWrW","07n1cQssNC","HlUbF8RCUA","Mkgy8WmadA","K20wKfaHir","0KyfszmLYD","yluBxvLsmS","VLTy6YjB9t",
-"Mkgy8EdBKc","VjCZq07n1c","QYxC02ZHdk","Dz1R3580YD","Gv3Fq4W0Tl","4W0TllCMxy","VIlwPSs0Zu","8hJdtuvf7A","48cHLPOUYS","cShY2Yw2oU",
-"HlUbFk85Ae","ru4UGiqv4k","v2eC3B3qem","Q6LixcQOnv","uTacxiqv4k","ReKEWQ6Lix","VNCPdWmadA","fLNg8SjskQ","aDGtSMm8si","ZzJHWHRxd8",
-"vOqCE5IhmG","VLTy6Fhtgl","zY1GYFGzgp","ZhwG1CdyBV","Ss0ZuOxWIH","s93MlMkgy8","Vprf21LB1L","YOfrYuPX7G","QnJ1SDz1R3","55rfBo8Uyd",
-"iqv4kciuWz","FxX9qCp3mZ","XflUq9rlg9","14FLRRACuj","HfyNQDG4sT","JJs5mnFqik","DLhzMRkQke","GSQwjlj07Q","Cfgr3CqqaD","aez9ynnP8o",
-"Zv7z08RCUA","kZANm7X3uy","9iGoTCxVEf","5ZaEzBbwgA","okgRiyluBx","SWfou6AFT0","pvgjSD6rBy","zHF1q14FLR","No0QbAgJHQ","RACujciuWz",
-"uAWypmz8gx","16lHcl83Ud","l83UdGSQwj","Mkgy8QbxXc","D6rByDLhzM","dmoS7EdBKc","suY4xpAhR1","K4GS81j5L8","6q6L9KASQ8","FFDuiuupzk",
-"jiVBPGrDg7","Yh1hFFVMxo","lkMUAjS1aj","7Ow5Cni2v1","VNCPdm4bxU","In3NS0ao3l","64s8NFcWrW","uJScXfFDrJ","1LB1L5iGN5","RzaZAAXpwE",
-"48cHLO3iyQ","FFDuiDG4sT","RBhp08U2nU","VLTy6HRxd8","lj07Qo8Uyd","x3LDeK20wK","yvOMI7fsYM","piJSk2DREs","AmdQd9iGoT","RmDcrlH1kt",
-"ReKEWwDajX","AgJHQC2Irc","blLA9KZamH","ulk41ZzJHW","FwEJziqv4k","5iGN53weIF","iqv4kdmoS7","FhtglMK07Y","aL6AJZv7z0","ThjNnzbIYY",
-"VjCZqAXpwE","L7cGc5Mg9r","i3pyduAWyp","i3pydQWxoT","OHaBzKZamH","S77LHJkzUn","QChxsUmaEv","B3qemDLhzM","64s8NMK07Y","5iGN5pWiOs",
-"djsrv3otm6","45cIHhUTw7","ReKEWFGzgp","VLTy65Namm","yToGWYh1hF","iwzGkiB08l","ru4UGQbxXc","Ul4a1PYBf4","24ARFEdBKc","Twanod7vjM",
-"zz4ZUi7WMQ","NcICACqqaD","atef2Mm8si","pWiOsC2Irc","lsQGo8cVD3","JRJQBY1mC0","lpF6WTCgPp","YOfrYL7cGc","lCMxyoQ87r","FjHXRRACuj",
-"Y1mC0iKqhr","lCMxy5IhmG","Cp3mZzHF1q","1v5hH6AFT0","gjUTu1v5hH","VBjhzfLNg8","MezSWYf2Ec","zqH0WzHF1q","Ta8f6qQxHP","HP433tlILt",
-"xciqp7fKYU","ZUnqt16lHc","07n1c6q6L9","5Mg9rLewvM","ZhwG1KASQ8","zFgtBAgJHQ","nFqikvOqCE","B3qem9GXkX","7ku1pgf8rI","zQt6Q1j5L8",
-"XyPZNrz7Ut","LDk6fsx5Gl","Uvlv4uTacx","WmadABpYhV","8hJdtuPX7G","RkQkeQworu","s7MxkcShY2","MezSWZv7z0","LDk6fa00b5","ZUnqtAgJHQ",
-"0BmCy5VZjS","zqH0WGWqqX","pT8wuX6Pin","Waim6CdyBV","ZuDtD2hEEU","No0Qb8cVD3","0h1b1CIShG","4W0Tlrhl0J","0BmCyK20wK","e6e4z5ZaEz",
-"D6rByJJs5m","K20wK8xEKz","AmdQdRsQUq","hYBCKdmoS7","3weIF7hyVv","guMb8y94nw","pvgjSpv0i7","BCxeC7fKYU","5Drn0qUJMd","9eoRclH1kt",
-"8cVD3lCMxy","EOE1oX6Pin","FPfSEWMiS3","0BmCyvLsmS","tlILtn1pmO","ksJby9XyT9","prNT6OxWIH","B3qemFPfSE","y94nwSbRYy","0Wr5y5IhmG",
-"M6qcGh1zcH","lH1ktDQimp","uLtKso8Uyd","VIlwPiwzGk","qaofN7hyVv","vLsmSLDk6f","W7cTs3weIF","wiHrZiwzGk","taOXKuN6r3","TXQ0ZHzZT8",
-"MK07YFLsph","JIqXi5drc6","16lHcfmIK1","RxrsmZhwG1","tAOsrZJTXH","CK5W7Ul4a1","5IhmG8hJdt","sx5Gls7Mxk","t98iWKZamH","9y4lwEoToP",
-"nFqikciuWz","OHaBzQWxoT","AkKTkpvgjS","sqVrfuPX7G","AgJHQ2ZHdk","o8UydQWxoT","x3LDev1Hln","t59lRGWqqX","nFqiknFqik","e6e4zkZANm",
-"ciuWzlH1kt","JXljWkB5nP","0YAGHguMb8","FLsphFLsph","K4GS8WDVWJ","Yh1hFOHaBz","7fKYU7X3uy","lsQGouLtKs","07n1c14FLR","o8UydjSjS3",
-"FPfSEnFqik","tuDyS48cHL","lH1ktPOUYS","QnJ1SQ6hMC","Oz8yZzY1GY","ECMvUQbxXc","pFrrlF6PT2","lweGyPb1pa","9XyT9nFqik","WPmlxGv3Fq",
-"Yf2EcKASQ8","GXdoH0PktI","h1zcHlpF6W","ulk41guMb8","zbIYYydG8U","VerEATwano","JRJQBNhXdu","xciqpoQ87r","lH1ktuTacx","7fKYUciuWz",
-"G1RhSVNCPd","ZhwG1BpYhV","zqH0WgIYvE","QnJ1SxReec","S2DfunlaBy","MaJQsRmDcr","DG4sT2TRI7","iKqhrGv3Fq","oQ87rzbIYY","0Wr5yFVMxo",
-"uJScXhE1Ql","s4786jS1aj","yofH3DG4sT","pmeCdKr8ys","taOXKdQ586","vLsmSUvlv4","prNT6gdQsS","O3iyQtjQxs","zQt6QWaWsv","JkzUnfFDrJ",
-"S77LHVprf2","WaWsvIjTwP","zY1GYsqVrf","L7cGcWaWsv","dQ586qQxHP","QnJ1S48cHL","brhlQFxX9q","HlUbFWreyP","9iGoThi5X7","rz7Utv2eC3",
-"nFqikpvgjS","Waim6UlU3M","zbIYYzHF1q","FcWrWbrhlQ","8TxD7Kr8ys","djsrv6q6L9","64s8NFNYIM","5iGN5S2Dfu","HzZT8VNCPd","1j5L8sx5Gl",
-"HRxd84QMc9","9GXkXhUTw7","Vprf2RACuj","yluBxv1Hln","OUqFM0Kyfs","2Yz7E5iGN5","hi5X7P6bcg","y94nwgtCA5","B3qemFLsph","AkKTkuLtKs",
-"uJScXRACuj","ECMvUDcpWB","oGu6xMGlTF","Z4I1vtvdkD","0YAGHgjUTu","a00b5Yw2oU","CqqaDOHaBz","14FLRWaim6","pv0i7jiVBP","tl72WVBjhz",
-"5IhmGDLhzM","sx5Gl7ku1p","l83UdyvOMI","MmsIoprNT6","prNT6Cfgr3","29QAzjiVBP","OHaBzfmIK1","jtn0X3otm6","wDajXmX2GE","HfyNQrhl0J",
-"W3VFHFcWrW","L7cGcGrDg7","jSjS3Chuy3","MmKGJhe9IA","AOgEetl72W","v2eC3uZPqg","xXTI4ECMvU","9rlg9Uvlv4","ZuDtDVIlwP","pvgjS7Ow5C",
-"8xEKz64s8N","LewvMcmXIX","NhXdujeskS","pWiOsVprf2","MojnPVBjhz","6q6L9vOqCE","lXFOBQ6Lix","AXpwEjfREu","lm0pD580YD","uLtKsRzaZA",
-"Kr8ysMmsIo","VBjhz5Namm","k85AeuPX7G","JkzUnCqqaD","7lUXZUvlv4","xXTI4tvdkD","AXpwE0PktI","fLNg8Yf2Ec","d85a9djsrv","W7cTszz4ZU",
-"b29RJEoToP","9iGoT2hEEU","2ZHdkh1zcH","vkCHH7fsYM","jfREuprNT6","Uvlv416lHc","ZJTXH1j5L8","QbxXcoVQp6","m4bxUVjCZq","MaJQsFGzgp",
-"B3qemzFgtB","RBhp0VIlwP","EOE1oiKqhr","JJs5mfaHir","POUYS7ku1p","rKDLJFLsph","NAFuw5Mg9r","AXpwEJ2mQi","OUqFMDz1R3","iB08lVjCZq",
-"lpF6W0PktI","zz4ZUReKEW","gtCA57hyVv","HP433HlUbF","0Wr5y1LB1L","55rfBGrDg7","CK5W7jiVBP","FhtglAXpwE","zqH0WCIShG","bZLvSVBjhz",
-"AIYUuU3yw5","2DREsStlDJ","F6PT2ciuWz","AgJHQcQOnv","jSjS3ksJby","yluBxTCgPp","yofH3ni2v1","wiHrZ5Namm","9y4lwM6qcG","DcpWBIKxdL",
-"wDajX1LB1L","zbIYYVLTy6","1j5L87fKYU","JJs5mkZANm","xReecNOHsz","OHaBzjeskS","MK07YyluBx","i3pydhSSvQ","StlDJQnJ1S","WDVWJAgJHQ",
-"he9IAaL6AJ","NAFuwVjCZq","jiVBPhe9IA","Mm8siUvlv4","IjTwP9iGoT","CqqaDQssNC","RsQUqDG4sT","EOE1oyvOMI","nnP8oTCgPp","s4786tlILt",
-"taOXKLbRTH","ZJTXH1v5hH","NhXdubrhlQ","atef2cQOnv","ksJbyiB08l","ulk41d7vjM","9rlg948cHL","i3pydEOE1o","BCxeCNo0Qb","M6qcGx3LDe",
-"S2DfuFwEJz","rKDLJvkCHH","fLNg83otm6","zbIYYyToGW","S2DfuTCgPp","6AFT0x3LDe","bZLvSiKqhr","4QMc9o8Uyd","nFqiks93Ml","rKDLJXflUq",
-"xciqpC2Irc","yluBxyvOMI","zHF1qFPfSE","l83UdQssNC","jiVBPMm8si","iwzGkmz8gx","uTacx2Yz7E","2ZHdkaez9y","kZANmQWxoT","Q6hMCPYBf4",
-"1LB1LI7p2a","AkKTkbZLvS","ZJTXHPOUYS","MGlTF2hEEU","BFkb82Yz7E","qQxHPdjsrv","U3yw5CK5W7","yEfy99GXkX","7Ow5CwDajX","Ss0ZuKsjRK",
-"I7p2aS2Dfu","WmadANOHsz","MK07Yiqv4k","9rlg9lpF6W","KASQ8GXdoH","4QMc9jfREu","Q6LixTXQ0Z","GXdoHiB08l","Q6hMC8FmFH","DcpWBdjsrv",
-"RACujW3VFH","AmdQdO3iyQ","UlU3MFxX9q","jS1ajs93Ml","B3qemJRJQB","MaJQsydG8U","uoStwJRJQB","uvf7AjzUqR","aDGtSBGaQY","CNHmvfLNg8",
-"Z4I1vZhwG1","iB08lqaofN","VIlwP5Namm","MezSWtAOsr","SjskQZuDtD","J2mQijiVBP","FGzgprhl0J","2NslmfLNg8","2TRI7D6rBy","AkKTkFPfSE",
-"sx5Gl9eoRc","9XyT9WPmlx","ulk41RBhp0","yToGWfmIK1","brhlQ9eoRc","dQ586b29RJ","iKqhruN6r3","6AFT0o8Uyd","WPmlx9y4lw","b29RJzFgtB",
-"WDVWJaez9y","lXFOBLbRTH","L7cGceuZA5","I7p2aK4GS8","uZPqgHfyNQ","Chuy3s93Ml","9XyT9JXljW","dQ5860Wr5y","ni2v1VLTy6","14FLRbZLvS",
-"HfyNQtlILt","CNHmvEoToP","P6bcgIKxdL","Yw2oUQssNC","dmoS7L7cGc","FVMxoAmdQd","pAhR1yEfy9","gjUTuVerEA","RmDcraez9y","dQ586Kr8ys",
-"zz4ZURBhp0","n1pmOuoStw","ZhwG1lXFOB","sx5GlGv3Fq","WreyPQWxoT","DcpWBblLA9","KZamHbgJAz","tjQxsFPfSE","9y4lwDz1R3","ciuWziB08l",
-"xciqpFNYIM","h1zcH4W0Tl","zQt6QEOE1o","FxX9qtuDyS","d85a98TxD7","he9IAgjUTu","DcpWBprNT6","U3yw5WMiS3","Mkgy8oVQp6","OHaBzlH1kt",
-"zHF1qTCgPp","kB5nPoQ87r","m4bxUFcWrW","fLNg8azIWp","4QMc9Gv3Fq","uN6r3FPfSE","FnPFBjiVBP","lH1ktrhl0J","b29RJ64s8N","n1pmOzQt6Q",
-"dQ586G1RhS","cmXIX8U2nU","uvf7AjS1aj","k85AehE1Ql","HzZT8aFFss","b29RJD6rBy","FPfSE1LB1L","UmaEv9XyT9","QnJ1SWMiS3","64s8NTCgPp",
-"MojnPFPfSE","4dEz66q6L9","cShY2d7vjM","yvOMIMezSW","guMb8ReKEW","x3LDeuJScX","pT8wuzHF1q","2DREsb29RJ","oQ87rFPfSE","suY4xh1zcH",
-"3otm6In3NS","24ARFRACuj","Q6hMCMK07Y","BCxeCsx5Gl","8TxD7yluBx","MK07Yl83Ud","2hEEUOz8yZ","ZJTXHMaJQs","Nxx9VVLTy6","Mm8siJIqXi",
-"JXljW0h1b1","Mm8siWmadA","sqVrfpFrrl","nnP8ozY1GY","RpBQmcShY2","xciqp7ku1p","Mm8siYOfrY","FFDuibZLvS","uJScXv2eC3","0YAGHAXpwE",
-"gf8rIlweGy","Cp3mZi7WMQ","cL0aEUvlv4","580YDOUqFM","oVQp68hJdt","ix74rWaWsv","2DREsxXTI4","BGaQYlkMUA","HlUbFRkQke","he9IAjzUqR",
-"NhXduVBjhz","uPX7GpAhR1","Ss0ZuYOfrY","FxX9qzbIYY","Kr8ysydG8U","5nmWvZzJHW","MojnPd7vjM","HzZT8MK07Y","euZA5he9IA","FcWrWVNCPd",
-"RxrsmiKqhr","uTacxwDajX","W3VFHIRh48","lweGyYw2oU","v2eC3GSQwj","uvf7AxXTI4","pv0i7piJSk","hi5X7StlDJ","fcwDaQ6Lix","7fsYMTwano",
-"DcpWBO3iyQ","Gv3FqIKxdL","e6e4zNxx9V","zqH0W7lUXZ","OUqFMNhXdu","FnPFBQWxoT","nnP8oIjTwP","GSQwjK20wK","QbxXcKZamH","jS1ajWmadA",
-"48cHLMmKGJ","1LB1Lrhl0J","brhlQn1pmO","J2mQiuTacx","5VZjS7Ow5C","L7cGcFhtgl","suY4xYOfrY","bgJAzbgJAz","HlUbFpmeCd","2NslmlCMxy",
-"Ss0ZuyvOMI","qQxHPPOUYS","ThjNnqQxHP","Kr8ysEoToP","bgJAzDz1R3","pAhR1qQxHP","Fhtgl9XyT9","7fsYM7Ow5C","BCxeC29QAz","oQ87rCfgr3",
-"No0QbQChxs","lXFOBFxX9q","GrDg7BFkb8","qQxHPv8yFN","8cVD3dQ586","zqH0W0Kyfs","W3VFHMmKGJ","XyPZNdjsrv","qaofNQClRL","SjskQoVQp6",
-"lXFOBogLgc","lCMxyogLgc","cQOnvOz8yZ","fmIK1QChxs","VNCPdzbIYY","VLTy6WMiS3","soy9tjzUqR","zqH0WnFqik","FVMxoRBhp0","JRJQBJJs5m",
-"F6PT2s7Mxk","uJScXCdyBV","P6bcg2hEEU","nnP8os7Mxk","Oz8yZa00b5","LDk6fyToGW","7Ow5CCqqaD","IKxdLlH1kt","Chuy35iGN5","rhl0Jgf8rI",
-"ZUnqtReKEW","euZA51j5L8","aL6AJvOqCE","t98iWMmsIo","HzZT8okgRi","8RCUAHfyNQ","CIShGatef2","2NslmReKEW","0MR5XaDGtS","uupzkUl4a1",
-"ThjNnVIlwP","VBjhzwiHrZ","OUYuFiKqhr","QbxXcjSjS3","CqqaDyToGW","EOE1oRpBQm","s4786Cp3mZ","1v5hHv2eC3","zqH0WprNT6","5Drn0Qworu",
-"azIWpuLtKs","FwEJzMmsIo","Chuy3yvOMI","lm0pD6q6L9","PYBf4fqypy","EoToPfaHir","45cIHRkQke","Vprf24dEz6","OxWIH4QMc9","UmaEvK20wK",
-"i7WMQm4bxU","faHiry94nw","i3pydBCxeC","yToGWQWxoT","NAFuwCdyBV","ZUnqtW3VFH","Yh1hFGrDg7","No0QbfmIK1","8FmFHulk41","FVMxoCxVEf",
-"t98iWx3LDe","L7cGcCdyBV","t59lRjS1aj","jzUqRFNYIM","o8UydBFkb8","9eoRcGSQwj","sx5Gl8hJdt","Cp3mZYOfrY","AmdQdKr8ys","G1RhSix74r",
-"aDGtShSSvQ","S2DfuyofH3","Q6hMCsx5Gl","4W0Tlxciqp","0Wr5y7hyVv","FjHXRMmKGJ","O3iyQHfyNQ","Pb1payofH3","Q6hMC45cIH","Yh1hFpWiOs",
-"n8pJ9tAOsr","FnPFBm4bxU","lpF6WIn3NS","yluBxZzJHW","nFqikCp3mZ","0PktINAFuw","zqH0WNhXdu","AOgEeMezSW","Waim62hEEU","In3NS9rlg9",
-"Fhtglhe9IA","y94nwsqVrf","fcwDaM6qcG","qUJMdzFgtB","7hyVvF6PT2","C2IrcblLA9","Zv7z0hYBCK","MojnPFFDui","5Mg9rOUYuF","aez9ypiJSk",
-"ZUnqtdmoS7","i3pyduQIcz","uQIcz9XyT9","gf8rIix74r","hUTw7HP433","qaofNtaOXK","rKDLJpvgjS","fFDrJ1v5hH","yEfy9oQ87r","5drc6ogLgc",
-"JIqXi8cVD3","fqypy0MR5X","S2DfuFFDui","ciuWzpvgjS","1v5hHBGaQY","S77LHxXTI4","uAWypFPfSE","9y4lwXyPZN","euZA5uoStw","gtCA5O3iyQ",
-"gdQsS5Mg9r","rhl0Jv1Hln","v8yFNXflUq","aL6AJjfREu","3weIFPYBf4","Zv7z0Y1mC0","QWxoTydG8U","WPmlxpAhR1","0YAGHIKxdL","pT8wu0PktI",
-"ix74rVjCZq","n8pJ9zQt6Q","CNHmvaFFss","Ul4a1jzUqR","Y1mC029QAz","HfyNQJ2mQi","uQIczguMb8","JXljWlm0pD","tvdkDcShY2","JkzUnfaHir",
-"9rlg9wiHrZ","taOXKWreyP","7fKYUEOE1o","Vprf2FFDui","djsrvlkMUA","Yw2oU2Yz7E","BFkb829QAz","BGaQYZJTXH","RmDcrSs0Zu","2Nslmulk41",
-"5VZjSJIqXi","KZamHv8yFN","IjTwPG1RhS","x3LDeVIlwP","S2Dfu0h1b1","IRh48aez9y","RACujd7vjM","qQxHPmX2GE","B3qemuoStw","GSQwjTwano",
-"580YDpiJSk","cL0aEn8pJ9","D6rByPYBf4","7fsYMY1mC0","uLtKsazIWp","k85AeQWxoT","GXdoHhi5X7","TCgPppiJSk","Uvlv4FGzgp","FPfSEFwEJz",
-"16lHcS2Dfu","guMb816lHc","GXdoHOUqFM","jtn0X14FLR","VerEACp3mZ","TCgPps7Mxk","EdBKch1zcH","s4786WmadA","BCxeCn8pJ9","SmGzv8FmFH",
-"9rlg9MK07Y","zFgtB6q6L9","iKqhrsoy9t","soy9t4QMc9","e6e4zWDVWJ","D6rByGXdoH","9eoRcFxX9q","lXFOB0BmCy","Ss0ZuBbwgA","XflUqydG8U",
-"hE1QljeskS","2DREsWaWsv","VIlwPRBhp0","v1HlnlpF6W","tjQxsUlU3M","taOXKo8Uyd","Z4I1vQworu","hSSvQAmdQd","FGzgpjSjS3","iB08lBpYhV",
-"7X3uyFhtgl","rz7UtGrDg7","Q6hMCVjCZq","AkKTkO3iyQ","U3yw5ZuDtD","aL6AJzbIYY","rz7UtXflUq","ReKEW9y4lw","zQt6QMezSW","2DREsFnPFB",
-"DcpWBdQ586","ix74rAgJHQ","Q6Lix5IhmG","d85a9Yw2oU","k85Ae8FmFH","BGaQYbrhlQ","Y1mC0jS1aj","uvf7A618Di","zqH0WblLA9","oQ87rHzZT8",
-"MmKGJzmLYD","azIWps93Ml","MGlTFsuY4x","KZamHiKqhr","VjCZqIRh48","Yw2oUO3iyQ","5Mg9rVLTy6","DQimp0YAGH","FNYIMM3zXL","5drc6QbxXc",
-"AgJHQfFDrJ","fLNg8DG4sT","SmGzvuTacx","vOqCE4QMc9","StlDJyluBx","YjB9tjzUqR","S77LHzbIYY","7ku1pfqypy","pFrrlciuWz","IBe8kDLhzM",
-"Zv7z0Ss0Zu","J2mQiOxWIH","suY4xFcWrW","FVMxoZv7z0","SmGzvNxx9V","jSjS3VjCZq","yvOMICp3mZ","suY4xFhtgl","v1HlnFNYIM","48cHLFwEJz",
-"GSQwjgdQsS","lkMUAZUnqt","ydG8UlkMUA","zQt6QVIlwP","VLTy6SmGzv","aDGtSCdyBV","pWiOsDLhzM","9rlg9CqqaD","fLNg8C2Irc","fcJOyaL6AJ",
-"Waim6HP433","prNT6Uvlv4","jSjS3n1pmO","fFDrJJJs5m","Waim6t59lR","jSjS3dpe1v","FPfSEzz4ZU","0ao3lmX2GE","OUqFMGWqqX","dpe1vzHF1q",
-"GSQwj6AFT0","gIYvEd85a9","ZUnqtNxx9V","No0QbWMiS3","AXpwEhSSvQ","kB5nP7lUXZ","lCMxyF6PT2","DG4sTjiVBP","KsjRKbgJAz","AXpwEjSjS3",
-"9y4lwprNT6","BFkb8gIYvE","RpBQmksJby","qQxHPWmadA","8U2nUyluBx","zHF1qEOE1o","CIShGuN6r3","O3iyQS77LH","FnPFBpT8wu","kB5nP0MR5X",
-"6AFT0uTacx","Z4I1vciuWz","JKWYRKZamH","8cVD3ECMvU","OUYuFksJby","i7WMQNhXdu","D6rByatef2","ksJby5Mg9r","Uvlv4Z4I1v","lXFOBl83Ud",
-"JXljWcQOnv","9y4lwBpYhV","zz4ZU0Kyfs","n1pmODz1R3","JIqXi45cIH","6q6L9uAWyp","zHF1qVIlwP","Mkgy8hSSvQ","8xEKzTXQ0Z","64s8NnlaBy",
-"aez9yjfREu","cQOnvJIqXi","2Nslmfqypy","mX2GEGv3Fq","Oz8yZUlU3M","M3zXLUmaEv","QbxXc0PktI","uAWypFFDui","AOgEePb1pa","1v5hHNhXdu",
-"RzaZAi7WMQ","2ZHdkI7p2a","55rfBs7Mxk","1j5L8yEfy9","XyPZNYOfrY","WaWsvlj07Q","wiHrZDcpWB","ydG8U4QMc9","JKWYRWmadA","Kr8ysC2Irc",
-"DLhzMyToGW","1j5L8QbxXc","ciuWzs93Ml","yEfy9fmIK1","wiHrZrz7Ut","PYBf4HfyNQ","rz7Uti3pyd","0BmCyzbIYY","StlDJwiHrZ","5IhmGfqypy",
-"VIlwPYw2oU","s93MlokgRi","cmXIXCfgr3","n8pJ9ZuDtD","iwzGkaez9y","pAhR1bZLvS","uTacxjzUqR","aFFssrKDLJ","zz4ZUi3pyd","uZPqgYOfrY",
-"Yw2oU0YAGH","TwanoWPmlx","OHaBzYf2Ec","9iGoTuoStw","JRJQBn8pJ9","KZamHMm8si","rKDLJuZPqg","t59lRuPX7G","8FmFHO3iyQ","ix74rWPmlx",
-"SmGzvFwEJz","pWiOspiJSk","pT8wuoGu6x","Cp3mZM3zXL","aDGtSRBhp0","dmoS7HRxd8","gf8rIRkQke","AOgEe8U2nU","Mkgy8Chuy3","vLsmS5Mg9r",
-"d85a9D6rBy","zmLYDtl72W","aL6AJsuY4x","0ao3lksJby","45cIHJkzUn","BFkb80h1b1","lkMUAoQ87r","b29RJF6PT2","guMb8pmeCd","qUJMdWDVWJ",
-"ogLgc1LB1L","Q6Lixt59lR","fcJOy9rlg9","Ta8f6AgJHQ","Waim664s8N","yToGWdmoS7","jzUqRuQIcz","MK07YsqVrf","jfREujfREu","7fsYMy94nw",
-"FFDuiAmdQd","Ta8f6FVMxo","FjHXRtlILt","FjHXRKZamH","W3VFHU3yw5","he9IAOUqFM","AmdQdydG8U","zz4ZUQWxoT","BpYhVuLtKs","zqH0WHfyNQ",
-"Waim6SjskQ","jeskSIn3NS","NcICAuoStw","a00b56q6L9","jiVBPv2eC3","NhXduRBhp0","jzUqRv8yFN","0KyfsIjTwP","GSQwj8RCUA","Oz8yZEdBKc",
-"guMb8gf8rI","DLhzMcShY2","No0Qbtl72W","uvf7ACqqaD","6q6L9Waim6","atef2pmeCd","CdyBV5Namm","CdyBVsx5Gl","uN6r3WPmlx","7hyVvcmXIX",
-"uZPqgsqVrf","FNYIMAOgEe","FNYIM2Nslm","0YAGHzHF1q","FjHXR6AFT0","Cfgr37ku1p","MmKGJuupzk","vOqCEWreyP","cL0aE0PktI","5Drn0BbwgA",
-"8RCUAguMb8","WMiS3UlU3M","v1HlnMm8si","ulk410Wr5y","mz8gxy94nw","55rfBgf8rI","U3yw545cIH","8FmFH1j5L8","NcICA07n1c","4dEz65nmWv",
-"7fKYULewvM","Yh1hF9eoRc","AkKTk9iGoT","FcWrWK20wK","Mkgy8sqVrf","nnP8o8hJdt","S77LHFjHXR","lCMxyFxX9q","kZANmJKWYR","jzUqRNAFuw",
-"IBe8k7fsYM","RpBQmnFqik","dmoS716lHc","aDGtSJRJQB","TwanoK4GS8","0YAGHsoy9t","Kr8ysnnP8o","Dz1R38FmFH","5nmWvv2eC3","ReKEWuN6r3",
-"bZLvSDG4sT","jeskS4W0Tl","SWfouAIYUu","NcICAcmXIX","aDGtSfaHir","JKWYRYh1hF","AmdQdRBhp0","NAFuwkB5nP","O3iyQ0ao3l","IRh48gf8rI",
-"In3NSpvgjS","NcICAGWqqX","nFqikZzJHW","lViBvQWxoT","QYxC0pmeCd","LewvMIn3NS","taOXKDQimp","Ta8f68cVD3","OxWIHk85Ae","9rlg9OxWIH",
-"lj07Qs93Ml","9y4lw618Di","jzUqR6AFT0","RBhp0tuDyS","jSjS3Ss0Zu","zFgtByluBx","Kr8ysCxVEf","gIYvEoGu6x","Yw2oUtaOXK","uLtKsxReec",
-"HzZT8t59lR","xXTI40YAGH","iwzGkbgJAz","7hyVvpAhR1","uJScX7Ow5C","0h1b1M6qcG","YOfrYnlaBy","RmDcr0Wr5y","uAWypS2Dfu","iqv4k0Kyfs",
-"gjUTuyToGW","DLhzM2DREs","lkMUA6AFT0","vkCHH5IhmG","Zv7z0ulk41","8FmFH7hyVv","gtCA5D6rBy","0Kyfspv0i7","PYBf4e6e4z","FjHXRVprf2",
-"1v5hHMmKGJ","d85a9pmeCd","rhl0J2Nslm","AkKTkxXTI4","TXQ0ZW3VFH","pmeCdFhtgl","QYxC0FFDui","VjCZqOUqFM","24ARFqQxHP","BCxeCVLTy6",
-"sqVrf2ZHdk","K4GS8jfREu","soy9tNOHsz","IjTwPlH1kt","9XyT9piJSk","yluBxFNYIM","Cp3mZBFkb8","blLA9aDGtS","5IhmG3weIF","Kr8yso8Uyd",
-"JkzUnx3LDe","Kr8ysfcJOy","fcwDa0MR5X","0YAGH618Di","BpYhV48cHL","NcICAfLNg8","7hyVv5Namm","y94nw9rlg9","2hEEUrKDLJ","o8Uydatef2",
-"Mkgy8qQxHP","8xEKzCK5W7","xXTI4QYxC0","v1Hln618Di","VNCPdydG8U","Uvlv40Kyfs","i7WMQYw2oU","0BmCyFxX9q","4W0TlHRxd8","AkKTkGSQwj",
-"zY1GY16lHc","x3LDeb29RJ","2ZHdk2Nslm","zY1GYDz1R3","EOE1ojfREu","qaofN9y4lw","ogLgcFGzgp","SjskQZhwG1","Nxx9V5Drn0","d7vjMru4UG",
-"o8Uydt98iW","tjQxsGSQwj","7Ow5CogLgc","jzUqRRsQUq","IKxdLYw2oU","AIYUuoQ87r","BpYhVVNCPd","gdQsS8TxD7","UlU3MY1mC0","45cIHi3pyd",
-"fcwDayEfy9","rKDLJ0PktI","D6rByOUYuF","FnPFBlCMxy","ix74r14FLR","brhlQVerEA","Ta8f6XyPZN","zQt6QBpYhV","dQ586FxX9q","DcpWBP6bcg",
-"TwanoBbwgA","QYxC0b29RJ","Qworut98iW","8TxD70PktI","zY1GY8U2nU","2Yz7EWaWsv","lXFOByofH3","tAOsrJ2mQi","JXljW5ZaEz","BbwgANOHsz",
-"jeskSb29RJ","9XyT9In3NS","0BmCyru4UG","okgRiI7p2a","YOfrYAgJHQ","ulk41TXQ0Z","5nmWvNAFuw","G1RhSFNYIM","MojnPhSSvQ","1j5L8cQOnv",
-"cQOnv24ARF","TXQ0ZKsjRK","24ARFFNYIM","atef2ECMvU","WMiS3pmeCd","JkzUnSWfou","yEfy9dQ586","3weIFlCMxy","BCxeCDLhzM","mX2GEzY1GY",
-"6AFT0GWqqX","vOqCEOxWIH","9rlg9OUqFM","8U2nUcQOnv","1j5L8X6Pin","SWfouQWxoT","Cp3mZW7cTs","zqH0WNOHsz","Rxrsm8cVD3","45cIHDLhzM",
-"AXpwEQbxXc","iwzGkzmLYD","atef29XyT9","CdyBVlsQGo","IBe8kNo0Qb","vLsmSQChxs","ZUnqtCIShG","uZPqgd7vjM","ru4UGoVQp6","t98iWZzJHW",
-"lCMxy6AFT0","MaJQs5iGN5","tl72WI7p2a","qaofNlkMUA","W7cTs2TRI7","pvgjSokgRi","MGlTFhe9IA","POUYSNhXdu","UlU3MTCgPp","KZamHsoy9t",
-"8cVD3S2Dfu","xReecpv0i7","v8yFNLbRTH","HlUbFHlUbF","7X3uyJXljW","3otm6oVQp6","xReecd85a9","W3VFHVNCPd","Oz8yZ5nmWv","a00b5lj07Q",
-"Vprf2B3qem","BFkb8FcWrW","qQxHP0ao3l","ogLgcOz8yZ","BGaQYJkzUn","IBe8kwDajX","HRxd8K20wK","YOfrYlsQGo","kB5nPa00b5","Q6hMC8U2nU",
-"TCgPpazIWp","rz7Ut5nmWv","Uvlv4CdyBV","2DREsuJScX","2Yz7ECK5W7","OxWIHEdBKc","vkCHHdmoS7","Kr8ysFLsph","EOE1oAkKTk","Pb1paMojnP",
-"tvdkDRACuj","Oz8yZsuY4x","pAhR1bgJAz","kZANm9GXkX","pvgjSVprf2","yofH3C2Irc","ksJbyZzJHW","QClRLpiJSk","cmXIX580YD","uoStwIBe8k",
-"Rxrsmxciqp","SmGzvDQimp","qaofNv1Hln","9eoRchi5X7","JJs5maDGtS","Y1mC0FnPFB","tAOsrlsQGo","580YD0PktI","hYBCK8xEKz","1j5L8M6qcG",
-"9iGoTQworu","KASQ8bgJAz","Q6hMCNxx9V","9rlg9mX2GE","Gv3Fq0h1b1","9iGoToQ87r","HzZT8LDk6f","EoToPVjCZq","QWxoT07n1c","Z4I1v5Mg9r",
-"a00b58xEKz","Vprf2hYBCK","FGzgpTXQ0Z","aL6AJ8TxD7","Waim6FnPFB","YOfrY8U2nU","DG4sT8U2nU","VLTy6Z4I1v","3otm65IhmG","qQxHPUvlv4",
-"Yh1hFprNT6","wDajXYjB9t","pT8wumX2GE","24ARFcL0aE","ThjNn1v5hH","16lHcNhXdu","y94nwZhwG1","8hJdtS77LH","tvdkDI7p2a","oVQp6xReec",
-"5Mg9rLDk6f","8cVD3iqv4k","2ZHdkSmGzv","FNYIMvkCHH","zQt6Q5iGN5","GXdoHnnP8o","guMb8vkCHH","suY4xmX2GE","NhXduQClRL","MmsIouoStw",
-"16lHcOUqFM","JXljWG1RhS","AkKTkQnJ1S","pvgjSbrhlQ","P6bcgfFDrJ","Cfgr3Vprf2","Ta8f6UmaEv","zqH0WEOE1o","JJs5mYf2Ec","n1pmOSbRYy",
-"2hEEUWPmlx","pWiOsRzaZA","U3yw5jeskS","JJs5mZhwG1","rKDLJ9eoRc","POUYSlj07Q","FxX9q0h1b1","CIShGY1mC0","tvdkD29QAz","FjHXRMmsIo",
-"8TxD7ni2v1","14FLRW7cTs","d7vjMUl4a1","mz8gxksJby","45cIHgf8rI","MaJQszHF1q","S2Dfu5ZaEz","uQIczBGaQY","sx5Gl9rlg9","5Mg9rUvlv4",
-"9y4lwNxx9V","qQxHPLDk6f","WMiS3F6PT2","Q6hMCuvf7A","FLsphYOfrY","tjQxscShY2","KsjRKZ4I1v","lpF6WsqVrf","pFrrlFLsph","0h1b1AOgEe",
-"hSSvQUvlv4","WreyP55rfB","azIWpyvOMI","iB08lvLsmS","VBjhzJRJQB","hE1QlaDGtS","fqypyK4GS8","gtCA5J2mQi","QWxoTpiJSk","dhSuHulk41",
-"BCxeCaDGtS","OUYuFOHaBz","QnJ1S8RCUA","O3iyQpiJSk","OUYuFX6Pin","VerEAYh1hF","O3iyQlCMxy","iB08lZUnqt","NcICAK4GS8","GXdoHru4UG",
-"WaWsvzbIYY","Zv7z0FGzgp","TXQ0ZOxWIH","kB5nPCp3mZ","pAhR1J2mQi","sx5Gl14FLR","gjUTuKsjRK","WDVWJNOHsz","RACujHfyNQ","Mkgy8dQ586",
-"QYxC0tuDyS","dhSuHDLhzM","GWqqXcmXIX","NcICA7fKYU","7Ow5C6AFT0","KASQ8LbRTH","RxrsmThjNn","9rlg964s8N","S2Dfu7lUXZ","8FmFHoVQp6",
-"jSjS3QnJ1S","lCMxyMkgy8","L7cGcOUYuF","WPmlx7X3uy","WreyPbZLvS","5iGN5GWqqX","JkzUnGrDg7","FFDuiGv3Fq","nnP8oxXTI4","yvOMIMmsIo",
-"prNT6MGlTF","sx5GlZUnqt","M6qcGQChxs","JJs5ma00b5","ZuDtD0Kyfs","rz7Ut2Yz7E","GSQwjLewvM","lsQGotuDyS","kZANm4dEz6","7hyVvbrhlQ",
-"tuDyS6q6L9","CxVEfhe9IA","8RCUAOHaBz","YOfrY29QAz","MezSWMGlTF","tl72WS77LH","RACujQ6hMC","MmKGJ1v5hH","jtn0X7hyVv","D6rBytaOXK",
-"48cHL8cVD3","Cfgr3X6Pin","Oz8yZF6PT2","ni2v1K20wK","Y1mC0JKWYR","Mkgy8l83Ud","cL0aETwano","MmKGJvLsmS","nFqiklm0pD","oVQp6Yw2oU",
-"hi5X7RkQke","DG4sTaDGtS","AgJHQXyPZN","zmLYDxReec","d85a9atef2","fFDrJ0BmCy","l83Udiqv4k","2DREsi7WMQ","n8pJ9NcICA","RmDcrFVMxo",
-"In3NScQOnv","AgJHQuoStw","AXpwEG1RhS","brhlQTXQ0Z","tuDySKr8ys","WDVWJpWiOs","uupzkgtCA5","yEfy9hi5X7","qaofNChuy3","QnJ1SpWiOs",
-"6q6L9mz8gx","piJSkUvlv4","SbRYySs0Zu","zz4ZUuTacx","IKxdL8FmFH","K20wK7fsYM","W3VFHhSSvQ","B3qemksJby","BpYhVh1zcH","x3LDel83Ud",
-"CdyBVZJTXH","9iGoT5nmWv","nFqikAXpwE","FGzgpa00b5","I7p2apv0i7","2NslmzqH0W","MmKGJRsQUq","AIYUurz7Ut","s93MlazIWp","Y1mC0C2Irc",
-"ZJTXHpvgjS","AXpwEuPX7G","RxrsmWmadA","7lUXZnnP8o","0KyfsuPX7G","6AFT0FcWrW","7X3uyFcWrW","7fKYUNcICA","qUJMdDLhzM","FNYIMni2v1",
-"dmoS7M6qcG","7fsYMQssNC","zqH0WMkgy8","C2IrcPYBf4","7Ow5CBGaQY","Qworu0h1b1","KASQ8tAOsr","fcwDaSmGzv","AIYUut59lR","AkKTk5VZjS",
-"pvgjSmX2GE","cmXIXL7cGc","LbRTHCIShG","KsjRKjtn0X","taOXKK4GS8","NAFuwhSSvQ","lXFOBhe9IA","OHaBzXflUq","Vprf2rKDLJ","I7p2aMmsIo",
-"Gv3Fqtl72W","Kr8ysHfyNQ","FhtgllkMUA","okgRin8pJ9","JRJQBIn3NS","LbRTHbrhlQ","dQ586lCMxy","SjskQh1zcH","I7p2aJRJQB","AIYUuOHaBz",
-"RkQkedQ586","tl72WCIShG","lViBvNo0Qb","lpF6WThjNn","uAWypaDGtS","uN6r3ogLgc","EdBKczFgtB","KASQ8qQxHP","QClRLjSjS3","Dz1R3O3iyQ",
-"IRh48Yf2Ec","nnP8ohe9IA","9iGoTuZPqg","vOqCEFxX9q","7X3uyZv7z0","QWxoT9y4lw","OUqFMEOE1o","dmoS7uJScX","tAOsrAOgEe","lkMUAKZamH",
-"uJScXy94nw","VjCZqCp3mZ","lH1ktYh1hF","Gv3FqX6Pin","S2DfuMGlTF","lXFOBjeskS","7fsYMpmeCd","S77LH4dEz6","TXQ0Z9eoRc","hE1QlrKDLJ",
-"RkQkehUTw7","MojnPTwano","uupzkCNHmv","dpe1vZv7z0","lCMxyiB08l","uPX7GzmLYD","nFqikxciqp","QssNC5drc6","iB08lcQOnv","uQIcz1j5L8",
-"pv0i7i7WMQ","FVMxoGrDg7","FNYIM0Kyfs","taOXKjfREu","P6bcg0h1b1","n8pJ9Kr8ys","SmGzv16lHc","M3zXLvOqCE","5iGN548cHL","QYxC0tlILt",
-"lweGyFNYIM","RBhp0JRJQB","dQ586suY4x","gtCA548cHL","BCxeCPOUYS","aDGtSPYBf4","uvf7Ao8Uyd","cL0aEyvOMI","48cHLRACuj","dhSuHThjNn",
-"vOqCEaFFss","M3zXLK4GS8","AOgEezQt6Q","8TxD7Zv7z0","8xEKzlH1kt","d7vjMhe9IA","prNT6AmdQd","IKxdLxXTI4","7fsYMRxrsm","mX2GECfgr3",
-"HzZT8GSQwj","5drc6wiHrZ","blLA9aL6AJ","HlUbFL7cGc","gf8rIOHaBz","Waim6yEfy9","MmsIoIBe8k","14FLRnFqik","XyPZNO3iyQ","v8yFNDG4sT",
-"uvf7Ah1zcH","b29RJ29QAz","I7p2aQ6Lix","5IhmG5Namm","a00b5yToGW","he9IAfaHir","WaWsvm4bxU","uQIczQssNC","FFDuiBpYhV","Q6hMCiwzGk",
-"uN6r34QMc9","gjUTuWaim6","xciqprz7Ut","fmIK1lsQGo","azIWpd85a9","4W0TltjQxs","aDGtS8hJdt","16lHcVerEA","dhSuHZJTXH","uQIcz45cIH",
-"n1pmONOHsz","djsrvi3pyd","UmaEvfLNg8","GXdoHB3qem","vkCHHprNT6","xXTI4zFgtB","MGlTFnlaBy","8cVD3FwEJz","0BmCyYh1hF","NAFuwrz7Ut",
-"piJSkyofH3","AkKTkJKWYR","pFrrljfREu","8FmFHOz8yZ","Ul4a1Cfgr3","2NslmKASQ8","JkzUn9GXkX","5IhmGyluBx","QWxoTCfgr3","OHaBzC2Irc",
-"LewvMFxX9q","OxWIHBGaQY","a00b5oQ87r","gtCA5Mkgy8","iKqhrFnPFB","QWxoTQYxC0","FVMxo4dEz6","RBhp0pAhR1","e6e4zZv7z0","kB5nPulk41",
-"JIqXiJkzUn","NOHszJIqXi","FwEJzlH1kt","ZhwG1s4786","3otm6wDajX","DcpWBAkKTk","VerEAYw2oU","tvdkDStlDJ","TCgPpKsjRK","qQxHPfcwDa",
-"AIYUujeskS","tl72W29QAz","jiVBPprNT6","Ss0ZuOHaBz","7fsYMVBjhz","Uvlv4m4bxU","0PktIaez9y","FFDuid85a9","LDk6fAmdQd","cQOnvCdyBV",
-"yofH3fFDrJ","yofH3Yh1hF","XflUqmX2GE","WMiS3LbRTH","WreyPuvf7A","AOgEeQ6hMC","FcWrWd7vjM","9XyT9ReKEW","YjB9tuvf7A","wiHrZS2Dfu",
-"fLNg8blLA9","8TxD755rfB","nlaByprNT6","RzaZApiJSk","45cIHv1Hln","t59lRtlILt","s4786fcwDa","StlDJlkMUA","AOgEeU3yw5","wiHrZazIWp",
-"EOE1o5Mg9r","0YAGHM6qcG","WreyPkZANm","QChxs0ao3l","AXpwEIjTwP","n8pJ9OUYuF","5NammQworu","FxX9qUvlv4","Yf2EcfcwDa","prNT6SbRYy",
-"UmaEvSmGzv","ThjNn24ARF","0ao3lni2v1","iwzGkIjTwP","Ul4a1a00b5","C2IrcFcWrW","9XyT9UmaEv","lXFOBKASQ8","RmDcr45cIH","GXdoHS2Dfu",
-"jS1ajIRh48","EOE1om4bxU","wiHrZTCgPp","s93MlDQimp","8cVD3AmdQd","cQOnvwDajX","jzUqRa00b5","hSSvQIn3NS","Mm8sisx5Gl","FPfSEWmadA",
-"rKDLJ14FLR","lsQGoX6Pin","azIWpt59lR","Cp3mZpiJSk","W7cTs7fKYU","14FLRDcpWB","XflUqX6Pin","2hEEUJXljW","AgJHQPYBf4","5IhmGkB5nP",
-"K20wKlpF6W","8hJdtjiVBP","0ao3lZzJHW","SWfouYf2Ec","FnPFBmX2GE","WDVWJ5drc6","QworuyvOMI","8RCUA5Namm","Yh1hF5Namm","WMiS3WMiS3",
-"QnJ1StvdkD","7Ow5CKr8ys","WPmlxDz1R3","K20wK4QMc9","EOE1oazIWp","45cIH7X3uy","hUTw7xReec","RmDcrS2Dfu","AIYUu0BmCy","lXFOB8U2nU",
-"CqqaDulk41","t98iWhE1Ql","IKxdL7Ow5C","W7cTsCdyBV","HP4334QMc9","7Ow5CSmGzv","EoToP2DREs","Chuy3ulk41","prNT6dQ586","FnPFBZhwG1",
-"tvdkDQssNC","zz4ZUFGzgp","2TRI7QssNC","HP433lCMxy","IRh48pmeCd","Pb1paqaofN","618DibgJAz","FFDuiWreyP","iwzGk7fsYM","EOE1ouAWyp",
-"pT8wudpe1v","uJScXt98iW","Twano0ao3l","0ao3l2DREs","FVMxo9eoRc","KZamHgIYvE","nnP8o9GXkX","POUYSgdQsS","Pb1pazFgtB","QnJ1SZzJHW",
-"i3pydDQimp","IKxdLpAhR1","Q6hMC1v5hH","5nmWvnFqik","LewvMd7vjM","5iGN5VerEA","MaJQsiKqhr","lViBvru4UG","Pb1paokgRi","7ku1pFjHXR",
-"GrDg7CNHmv","uQIczUvlv4","n8pJ9JKWYR","8RCUAlpF6W","0Wr5yJKWYR","7hyVv4W0Tl","Y1mC00Kyfs","QWxoTX6Pin","euZA5ZUnqt","RzaZAsuY4x",
-"gf8rI1j5L8","jeskSPb1pa","nnP8ov2eC3","MmsIopWiOs","9iGoTs4786","tAOsrlCMxy","9rlg9Z4I1v","9rlg9jS1aj","Vprf2WDVWJ","5ZaEzMm8si",
-"X6Pin45cIH","uPX7GVLTy6","ZuDtDuvf7A","djsrvprNT6","nlaByJIqXi","wiHrZHzZT8","lViBvUvlv4","Oz8yZZJTXH","hi5X75IhmG","B3qemKASQ8",
-"4QMc9pmeCd","d85a9oQ87r","dpe1vU3yw5","POUYS5IhmG","x3LDetaOXK","pFrrl5VZjS","WMiS3k85Ae","8RCUAYOfrY","pWiOsZJTXH","VLTy6fFDrJ",
-"VjCZqsqVrf","Kr8ysksJby","okgRiQ6hMC","uZPqgFVMxo","U3yw52DREs","Chuy3uQIcz","zqH0W24ARF","VerEAxXTI4","M3zXLSWfou","7Ow5CChuy3",
-"D6rByKASQ8","QssNCFjHXR","9rlg9Kr8ys","euZA5suY4x","D6rByW3VFH","5drc6Q6hMC","nlaBydmoS7","C2IrcRkQke","lXFOBx3LDe","qUJMdS77LH",
-"S2DfuxXTI4","taOXKReKEW","VBjhz7fsYM","KASQ8Qworu","tAOsrFxX9q","i7WMQzQt6Q","ogLgcGrDg7","C2IrcUvlv4","UlU3M24ARF","MK07Yni2v1",
-"9eoRc0Kyfs","BbwgA4QMc9","FwEJzPYBf4","okgRiD6rBy","uupzkS77LH","fFDrJUl4a1","BGaQYMm8si","0ao3luN6r3","nFqikoVQp6","oGu6x1LB1L",
-"2hEEUBpYhV","0Kyfsn1pmO","Q6hMCiB08l","8xEKzM6qcG","Ss0ZuGWqqX","BGaQYD6rBy","Mm8siqUJMd","GXdoHix74r","cmXIX1v5hH","prNT6CdyBV",
-"5Drn0Yh1hF","NOHszPYBf4","dpe1vuLtKs","WPmlxWreyP","VerEApv0i7","6AFT0Pb1pa","zbIYYJ2mQi","HRxd8FPfSE","C2IrcI7p2a","ZhwG1d85a9",
-"zqH0WuN6r3","Gv3FqDLhzM","HlUbFBpYhV","tAOsr45cIH","48cHLTa8f6","3otm6azIWp","FxX9qQChxs","sqVrfFwEJz","U3yw52TRI7","t98iWhe9IA",
-"CxVEfuLtKs","aL6AJgtCA5","CK5W745cIH","2ZHdkgf8rI","b29RJuZPqg","s7MxkKZamH","rKDLJ5drc6","VBjhzQWxoT","mz8gx9GXkX","brhlQSbRYy",
-"s4786IRh48","DG4sTI7p2a","i3pydxReec","nlaBygdQsS","OUYuFgtCA5","iB08lzFgtB","yofH3lj07Q","uJScXaL6AJ","OUqFM5nmWv","ZUnqtF6PT2",
-"brhlQFGzgp","ReKEWJXljW","suY4xG1RhS","piJSkfcwDa","3weIFv8yFN","MK07YTXQ0Z","8FmFHRACuj","mX2GExXTI4","FcWrWPb1pa","YOfrY5IhmG",
-"24ARFLDk6f","uJScXlCMxy","zFgtBKsjRK","K20wKBFkb8","Z4I1vb29RJ","FwEJzQnJ1S","FcWrWru4UG","3otm6KsjRK","MGlTFZhwG1","9y4lwaez9y",
-"xciqpm4bxU","JIqXiix74r","aFFssRpBQm","djsrvjzUqR","faHirt98iW","oQ87rrKDLJ","RsQUqM6qcG","OUYuFAkKTk","Waim6Mm8si","hi5X7nnP8o",
-"YjB9tD6rBy","Dz1R3ciuWz","FLsph0ao3l","uupzkReKEW","QworulsQGo","9y4lwjS1aj","POUYSUvlv4","oVQp655rfB","QnJ1S5Mg9r","J2mQiHfyNQ",
-"7fKYUa00b5","16lHci7WMQ","7hyVvTCgPp","0Wr5ya00b5","RkQkek85Ae","9iGoTSs0Zu","8TxD7uZPqg","Pb1pa8U2nU","Yh1hFWmadA","P6bcgIBe8k",
-"GWqqXMezSW","TCgPpReKEW","7Ow5Cdjsrv","CxVEfqQxHP","ZJTXHRzaZA","iqv4k7ku1p","OUqFMRkQke","FVMxoMm8si","tvdkDIBe8k","4W0TlRpBQm",
-"GXdoHuTacx","zmLYD4W0Tl","d7vjM8FmFH","RkQke5iGN5","qUJMdQbxXc","iqv4kRACuj","gIYvEY1mC0","FLsphpv0i7","ulk41SbRYy","U3yw5lCMxy",
-"gtCA5KsjRK","uupzkM6qcG","d85a9gf8rI","8U2nUPb1pa","9rlg9lj07Q","he9IAuvf7A","MmsIoQ6Lix","m4bxUo8Uyd","HlUbFoVQp6","QChxsYh1hF",
-"ni2v1F6PT2","guMb8he9IA","QbxXcxciqp","yEfy9GXdoH","MaJQst59lR","YOfrYyluBx","Z4I1vYOfrY","FnPFBzFgtB","MGlTFRmDcr","4dEz6jS1aj",
-"AgJHQS77LH","oVQp68RCUA","ReKEWMaJQs","sqVrfTwano","SWfouiKqhr","HfyNQMaJQs","soy9t9eoRc","G1RhSU3yw5","DcpWBx3LDe","Yf2EcSjskQ",
-"FGzgpaFFss","v8yFNd85a9","J2mQiWreyP","In3NSqQxHP","mz8gxQWxoT","mX2GEgdQsS","UmaEvMK07Y","jtn0XEOE1o","Mkgy8i3pyd","vkCHHdhSuH",
-"bZLvSJ2mQi","v1HlnWaWsv","ulk41AOgEe","UmaEve6e4z","tl72WG1RhS","Yw2oUk85Ae","Mm8siqQxHP","n8pJ9YjB9t","iB08l45cIH","FjHXRP6bcg",
-"2TRI74W0Tl","uvf7A5drc6","sx5Gl7X3uy","I7p2aSWfou","hUTw7VIlwP","yvOMIIKxdL","7X3uyECMvU","In3NSs93Ml","uTacxZzJHW","VIlwPNcICA",
-"Mkgy8HRxd8","In3NSprNT6","uPX7G580YD","Twano0Kyfs","DQimp5drc6","uQIczTwano","xXTI4LbRTH","QChxs0PktI","QbxXcdmoS7","RBhp0Cp3mZ",
-"14FLRn1pmO","hYBCKMkgy8","i7WMQ6AFT0","FPfSEHfyNQ","zmLYDuoStw","zqH0Wt59lR","o8UydTXQ0Z","OxWIHh1zcH","uoStwSbRYy","tl72WY1mC0",
-"55rfBnnP8o","TCgPpBFkb8","e6e4zBbwgA","pFrrlkZANm","azIWp9rlg9","Yw2oUnnP8o","Kr8yspWiOs","0YAGHfaHir","djsrvMezSW","9rlg9YOfrY",
-"FPfSE7fKYU","JKWYR6q6L9","Ul4a1nlaBy","fqypyTCgPp","16lHcBFkb8","gtCA5NOHsz","jtn0XprNT6","aez9yv1Hln","618DipT8wu","64s8NnFqik",
-"5nmWvSs0Zu","VBjhzFjHXR","djsrvYjB9t","pmeCdGWqqX","Twanofqypy","k85AelpF6W","BGaQY5Namm","cShY2Q6hMC","jSjS3jeskS","ZUnqt64s8N",
-"faHirWMiS3","O3iyQMGlTF","uN6r3faHir","yEfy9NAFuw","iwzGkxXTI4","64s8NGWqqX","AgJHQWreyP","Yh1hF618Di","L7cGcGv3Fq","MaJQsRzaZA",
-"4dEz6lsQGo","GXdoHWaim6","9iGoTIn3NS","QbxXcyEfy9","BFkb85drc6","djsrvgf8rI","WmadAVIlwP","FwEJzoQ87r","3weIFNcICA","8FmFHCdyBV",
-"F6PT2t59lR","5NammNo0Qb","0BmCyuPX7G","9eoRcQ6hMC","uvf7AZhwG1","OUYuFHP433","6AFT0tAOsr","Mkgy8TXQ0Z","NOHsz0MR5X","ZUnqtCNHmv",
-"5Mg9rVjCZq","ni2v1fcwDa","dhSuHoVQp6","qUJMdVerEA","uLtKsjzUqR","LbRTHThjNn","JkzUnMmKGJ","NAFuwaDGtS","pmeCdWPmlx","uPX7GJkzUn",
-"blLA9cmXIX","MojnP0Kyfs","JXljW7fKYU","48cHLfLNg8","Chuy3uN6r3","y94nwYw2oU","7fsYMJ2mQi","ECMvUfaHir","lViBvFwEJz","hi5X7y94nw",
-"xXTI4iwzGk","8cVD3t59lR","64s8NqUJMd","vOqCElH1kt","lXFOBFnPFB","Oz8yZ7lUXZ","0KyfsLDk6f","1v5hHMm8si","ZzJHWdmoS7","2DREsMaJQs",
-"UlU3Ms93Ml","Kr8ys6AFT0","U3yw5AmdQd","5nmWvRBhp0","zY1GY4dEz6","jS1ajVIlwP","CxVEfnnP8o","Uvlv4ulk41","tAOsrtAOsr","ReKEWAkKTk",
-"lH1ktlm0pD","8RCUArKDLJ","a00b57hyVv","3otm6zHF1q","lweGyTXQ0Z","k85AeTwano","Kr8ysSWfou","29QAzP6bcg","JKWYRiqv4k","hi5X7AkKTk",
-"JJs5mhSSvQ","s7MxklH1kt","tlILtReKEW","mX2GEJIqXi","9GXkXK4GS8","brhlQ9GXkX","7hyVvMmKGJ","JJs5mCfgr3","Waim6pv0i7","ydG8UZJTXH",
-"atef2JXljW","VNCPd8RCUA","K4GS8NhXdu","gIYvEyToGW","0ao3l4W0Tl","jiVBPcShY2","dhSuHcQOnv","YOfrYVLTy6","he9IA14FLR","rhl0J580YD",
-"8RCUAWmadA","L7cGcv8yFN","BpYhVTCgPp","MmsIo5VZjS","HfyNQNcICA","AIYUuNxx9V","pFrrlTCgPp","e6e4zTCgPp","QClRLeuZA5","CdyBVX6Pin",
-"pWiOswDajX","RsQUqVerEA","b29RJSjskQ","uN6r3RsQUq","VNCPdXflUq","gIYvEUmaEv","VNCPdfcwDa","nFqik07n1c","5IhmGBGaQY","BCxeCYOfrY",
-"dmoS7DQimp","Mm8sipT8wu","zQt6Q8hJdt","7fKYUDz1R3","TCgPp8TxD7","S2DfuF6PT2","0KyfshSSvQ","0YAGHtjQxs","aDGtSguMb8","oGu6xiwzGk",
-"AmdQdDLhzM","Y1mC01v5hH","vkCHHzY1GY","lXFOBThjNn","ZzJHWgf8rI","cQOnvFGzgp","FVMxodmoS7","DLhzMOHaBz","k85AefmIK1","ZuDtDQ6Lix",
-"zqH0WNAFuw","JIqXi0PktI","s7Mxkuvf7A","0KyfsjeskS","CqqaDWaWsv","iKqhrC2Irc","yEfy9Q6hMC","cQOnvksJby","Ss0Zu618Di","1j5L8b29RJ",
-"MaJQsEdBKc","29QAzydG8U","DLhzMSs0Zu","IKxdLlViBv","AgJHQxReec","fcwDaAkKTk","P6bcgGSQwj","uZPqgMaJQs","9y4lwZzJHW","nlaBypv0i7",
-"nlaByx3LDe","gtCA564s8N","No0QbP6bcg","NhXduGv3Fq","EoToPtjQxs","CqqaDQWxoT","CIShGNo0Qb","s7MxkWaWsv","pv0i7ix74r","uvf7Ad85a9",
-"pAhR1lCMxy","K4GS8cShY2","CqqaDaFFss","6AFT0RzaZA","Cfgr38U2nU","okgRi2Yz7E","6AFT0lXFOB","gIYvErz7Ut","QWxoTuQIcz","pT8wuStlDJ",
-"Pb1paKsjRK","DQimpUlU3M","EoToPB3qem","Pb1paMGlTF","lj07QfmIK1","jzUqRrhl0J","BCxeCokgRi","0YAGHCdyBV","No0QbBbwgA","b29RJhi5X7",
-"suY4xCIShG","OHaBzMojnP","S77LHCK5W7","K4GS8GrDg7","VjCZqkB5nP","vOqCEJRJQB","9iGoTgtCA5","OHaBzW3VFH","lsQGoBFkb8","2TRI77fsYM",
-"RpBQmIBe8k","RxrsmFcWrW","fqypyEoToP","DQimpZUnqt","UlU3Mn8pJ9","8hJdtx3LDe","I7p2as7Mxk","tl72WjeskS","BCxeCJXljW","MGlTFZUnqt",
-"jeskS2hEEU","jeskSGrDg7","jeskSVerEA","Cp3mZ0BmCy","In3NSs4786","RzaZApv0i7","OxWIHgf8rI","yvOMIcL0aE","L7cGcv1Hln","PYBf4KZamH",
-"MezSWpAhR1","qUJMdLbRTH","uAWyp580YD","hSSvQ6q6L9","gtCA5WmadA","6AFT0uQIcz","KZamHa00b5","dmoS7nnP8o","AmdQdkZANm","O3iyQlweGy",
-"QnJ1Six74r","ydG8Uv2eC3","FPfSEFnPFB","RmDcrEOE1o","VNCPd9rlg9","v1HlnUvlv4","GWqqXTXQ0Z","J2mQiLbRTH","Mkgy8XflUq","2TRI7pv0i7",
-"qUJMdNo0Qb","lkMUAGWqqX","VerEAO3iyQ","9GXkXVIlwP","gf8rIrhl0J","QssNCdmoS7","5drc6WmadA","VerEAMaJQs","azIWpix74r","BCxeCMojnP",
-"Ss0ZupFrrl","Uvlv4Q6Lix","gf8rIHfyNQ","WMiS3DG4sT","CxVEfhYBCK","guMb8nnP8o","6q6L9FxX9q","HzZT8SbRYy","gdQsSa00b5","QChxsyEfy9",
-"JIqXijSjS3","7ku1pjtn0X","WMiS3NcICA","QClRLru4UG","m4bxUAgJHQ","wiHrZXflUq","hE1Qls4786","rKDLJL7cGc","brhlQiKqhr","kZANm9XyT9",
-"s7MxkBFkb8","JkzUntl72W","n8pJ9uZPqg","zbIYY29QAz","AOgEefFDrJ","hUTw7sqVrf","HlUbFdmoS7","9rlg9yToGW","8RCUAfaHir","WaWsv7lUXZ",
-"djsrvCqqaD","nFqikXyPZN","YjB9t5drc6","55rfBTXQ0Z","MmKGJFGzgp","mX2GEMkgy8","pT8wuQbxXc","lj07QyofH3","djsrv5Mg9r","3otm6I7p2a",
-"Dz1R3FLsph","CdyBVJ2mQi","9GXkXdhSuH","tAOsr4dEz6","Kr8ysMkgy8","BGaQYNxx9V","rhl0Jd7vjM","rKDLJ4QMc9","Y1mC0YOfrY","RmDcrRACuj",
-"uAWyp14FLR","EOE1oSmGzv","WaWsve6e4z","zQt6QFPfSE","RACujJRJQB","AkKTkF6PT2","Y1mC0cmXIX","7ku1p9XyT9","CdyBVmz8gx","nFqikWmadA",
-"9y4lwFnPFB","soy9tiKqhr","aez9ylkMUA","lweGyEoToP","o8Uyd5Mg9r","DcpWBZ4I1v","SWfouogLgc","B3qemYw2oU","s7MxkbgJAz","HP433F6PT2",
-"ZhwG1lj07Q","gtCA5ReKEW","blLA9atef2","aFFssM6qcG","yEfy9HfyNQ","fcJOyFLsph","JXljWyvOMI","mX2GEgjUTu","xReecCdyBV","6AFT0qaofN",
-"BCxeCbZLvS","yEfy97ku1p","ni2v1v8yFN","oVQp6580YD","Zv7z0jSjS3","XflUqAIYUu","rKDLJhi5X7","C2IrcjS1aj","B3qemGWqqX","QWxoT7fsYM",
-"FVMxozHF1q","64s8NBGaQY","k85AeS77LH","fFDrJ0PktI","3otm6y94nw","yluBxlXFOB","5Mg9rjiVBP","piJSk7X3uy","XyPZNgjUTu","Rxrsm07n1c",
-"ogLgcK4GS8","AXpwEGSQwj","MGlTF5VZjS","jfREuJkzUn","MK07YMK07Y","v2eC3kB5nP","QYxC0brhlQ","VNCPdDz1R3","24ARFAkKTk","he9IAyEfy9",
-"ReKEWxReec","y94nw2hEEU","zHF1qkZANm","xReecDLhzM","xciqpyofH3","IKxdLPb1pa","7hyVvfcJOy","xReecvLsmS","YOfrYhi5X7","QClRLMkgy8",
-"Pb1pa1v5hH","ogLgcFnPFB","sqVrfMmsIo","7Ow5CSWfou","WDVWJEoToP","Y1mC0CNHmv","rz7UtjzUqR","BGaQYNcICA","4W0TlZUnqt","gjUTutaOXK",
-"WmadAnFqik","D6rByTXQ0Z","CdyBVhUTw7","SWfoutjQxs","uQIczv8yFN","0Wr5y7fKYU","RpBQmtaOXK","LewvMZv7z0","W7cTs7X3uy","P6bcgbZLvS",
-"Z4I1vGrDg7","KZamHqUJMd","iqv4kfcJOy","Nxx9VblLA9","taOXK5Drn0","UmaEvGrDg7","7fsYMXflUq","t59lR9rlg9","JKWYR2ZHdk","VerEASs0Zu",
-"Chuy3D6rBy","tvdkDh1zcH","BpYhVs7Mxk","DLhzMnlaBy","M6qcGWDVWJ","m4bxU55rfB","uQIczYjB9t","KZamH7hyVv","2DREs07n1c","6q6L98xEKz",
-"FLsphCK5W7","QnJ1SkB5nP","ogLgc7hyVv","zFgtB8hJdt","pWiOsatef2","AkKTk48cHL","dQ586qUJMd","DLhzMfmIK1","QnJ1Sv2eC3","ogLgcGSQwj",
-"7hyVvHzZT8","Ss0Zu4dEz6","IjTwPQssNC","AkKTkYf2Ec","mz8gxNo0Qb","qaofNHfyNQ","StlDJ9rlg9","ix74rVprf2","2DREs8hJdt","m4bxUd85a9",
-"rKDLJFwEJz","14FLRAkKTk","IKxdLSWfou","PYBf4t98iW","VerEA55rfB","5ZaEzk85Ae","tvdkDSjskQ","iKqhr55rfB","8hJdtUvlv4","TCgPpL7cGc",
-"xciqpkZANm","nlaByiqv4k","CIShGHRxd8","GSQwjfqypy","kB5nPFFDui","LDk6fFnPFB","HfyNQ0Kyfs","QWxoT5Namm","GrDg7VBjhz","8TxD78U2nU",
-"J2mQi5nmWv","uvf7AUl4a1","07n1cVBjhz","piJSkm4bxU","FNYIMCqqaD","CK5W7taOXK","FwEJzXyPZN","AXpwEEdBKc","MGlTFXflUq","HfyNQChuy3",
-"CNHmvd7vjM","hUTw7FxX9q","AIYUu5VZjS","he9IAuPX7G","WDVWJQWxoT","55rfBSWfou","Q6LixpFrrl","KsjRKNAFuw","lm0pD1v5hH","aFFssoVQp6",
-"HzZT8vOqCE","ciuWz618Di","AXpwElH1kt","Cfgr3CNHmv","iwzGkDQimp","XflUqRkQke","sqVrfFLsph","4dEz6qQxHP","k85AeciuWz","Cfgr3uTacx",
-"DQimp8FmFH","EoToPQClRL","rhl0Jjtn0X","h1zcHNxx9V","SmGzvNhXdu","y94nwru4UG","EOE1oUl4a1","5Mg9rbgJAz","gjUTukB5nP","29QAzZzJHW",
-"9GXkXlH1kt","yEfy9qUJMd","FFDuiKASQ8","dhSuH0MR5X","iKqhrFjHXR","CxVEfMmKGJ","FGzgpHlUbF","bZLvS7ku1p","GrDg78U2nU","gjUTus93Ml",
-"8FmFH3weIF","6q6L9HfyNQ","i7WMQ5iGN5","Mkgy8SjskQ","uupzkoGu6x","wDajXL7cGc","2TRI78TxD7","Ta8f6BFkb8","NhXduiqv4k","In3NStAOsr",
-"0Wr5yrz7Ut","FnPFBiwzGk","qUJMdFNYIM","jSjS3piJSk","v1HlnYjB9t","8FmFHfFDrJ","I7p2atAOsr","BGaQYlpF6W","zY1GYZzJHW","1v5hHDcpWB",
-"RACujtAOsr","F6PT2cmXIX","bZLvSFnPFB","2ZHdk7X3uy","LbRTHO3iyQ","d7vjMnnP8o","yluBxLDk6f","CqqaDQnJ1S","xReecMkgy8","zz4ZUl83Ud",
-"v8yFNRxrsm","AmdQdSs0Zu","ydG8U1LB1L","4dEz6sqVrf","VIlwPsuY4x","iKqhrLbRTH","QnJ1S5Drn0","5VZjSpvgjS","JkzUnmz8gx","5Drn0vLsmS",
-"yToGWQ6Lix","lCMxySs0Zu","G1RhSlViBv","e6e4zIjTwP","uAWyp29QAz","2Yz7Epv0i7","QssNCMmKGJ","VIlwPvLsmS","Oz8yZFPfSE","jiVBPuoStw",
-"ni2v1fqypy","0YAGH580YD","7X3uyWmadA","YjB9tlXFOB","lCMxyRkQke","MezSWd85a9","cQOnvUvlv4","vkCHHatef2","Y1mC0ksJby","v8yFN5IhmG",
-"suY4xCp3mZ","tAOsrNo0Qb","AmdQdRpBQm","CdyBVzY1GY","8cVD3TXQ0Z","8TxD7hE1Ql","CK5W7W3VFH","YjB9ts7Mxk","Q6Lixs7Mxk","lj07QwDajX",
-"HP433JRJQB","yToGWfLNg8","t98iWrhl0J","7X3uypFrrl","guMb83weIF","64s8NvkCHH","BpYhVoVQp6","0MR5XgdQsS","uTacx55rfB","t98iWdhSuH",
-"lH1kt2Yz7E","jeskS7Ow5C","M6qcGRmDcr","No0Qb5ZaEz","l83UdW3VFH","HfyNQix74r","M3zXLCdyBV","4W0Tliqv4k","uZPqgPb1pa","zQt6QRACuj",
-"POUYSjzUqR","d7vjMZUnqt","FFDuiyofH3","jeskSNo0Qb","L7cGcgtCA5","YjB9tJ2mQi","Vprf2MmsIo","0MR5XzY1GY","taOXKpAhR1","6q6L9FFDui",
-"pFrrlOxWIH","5Drn0uN6r3","mX2GEulk41","HP433hUTw7","dpe1viqv4k","FLsphNhXdu","POUYSv1Hln","55rfBguMb8","O3iyQGrDg7","2Yz7EJIqXi",
-"ksJbyuoStw","tl72WUmaEv","9y4lwFFDui","zFgtBaFFss","GXdoHAIYUu","nlaByWreyP","7fKYUuLtKs","uTacx8FmFH","mX2GEFFDui","djsrvpFrrl",
-"fmIK15ZaEz","atef2580YD","uPX7G1LB1L","zz4ZUHfyNQ","jiVBPyToGW","iqv4kVerEA","kZANmoVQp6","TCgPpk85Ae","tvdkDVNCPd","yluBx580YD",
-"euZA5OUqFM","lm0pDpvgjS","e6e4zkB5nP","0BmCyi3pyd","VBjhzFNYIM","7Ow5CyToGW","Oz8yZmX2GE","hUTw7CqqaD","FNYIM7fsYM","B3qem5ZaEz",
-"Cp3mZcL0aE","VBjhz4QMc9","MK07YQ6hMC","UlU3MiKqhr","UlU3MRzaZA","lweGyuPX7G","JIqXizqH0W","9eoRcL7cGc","0KyfswiHrZ","QworuOxWIH",
-"pvgjSsuY4x","y94nwuZPqg","oVQp6lViBv","JKWYRK20wK","JJs5mGrDg7","y94nwnlaBy","zqH0W6AFT0","FxX9qs7Mxk","Ul4a1tl72W","KASQ8MezSW",
-"Ss0ZuhSSvQ","6AFT0SmGzv","BGaQYOz8yZ","uTacxGrDg7","gf8rIYOfrY","RACujOz8yZ","In3NSiwzGk","Y1mC0n8pJ9","L7cGczY1GY","2DREslj07Q",
-"MmKGJokgRi","n8pJ9JRJQB","jfREuFVMxo","bgJAz0YAGH","LDk6f5ZaEz","618DiK20wK","MmsIoOxWIH","5VZjSpWiOs","lH1ktMGlTF","W3VFHWMiS3",
-"azIWpuPX7G","0MR5XWMiS3","FGzgpSbRYy","v2eC37lUXZ","6AFT0jiVBP","HP4335Namm","lweGypv0i7","WPmlxiqv4k","zFgtB2hEEU","CIShG2Nslm",
-"oVQp6vkCHH","KsjRKciuWz","8cVD3GWqqX","HlUbFjtn0X","dpe1v9eoRc","RsQUqCK5W7","FFDui8FmFH","zbIYYFFDui","F6PT2RBhp0","Mm8sigtCA5",
-"GXdoHDcpWB","14FLR5Mg9r","uN6r3tl72W","64s8NzmLYD","suY4xStlDJ","SWfouvOqCE","5iGN59y4lw","1j5L8G1RhS","PYBf4Cp3mZ","ZuDtDjeskS",
-"piJSk8TxD7","4dEz6Yh1hF","BCxeCY1mC0","FjHXRFLsph","cShY2pvgjS","iB08lxXTI4","SmGzvxXTI4","uZPqgOHaBz","24ARFJKWYR","NhXduix74r",
-"LbRTHYOfrY","lsQGoyToGW","5nmWvpAhR1","JkzUnM6qcG","0YAGHPOUYS","2hEEUazIWp","vOqCETCgPp","lsQGoVBjhz","CNHmvjSjS3","lsQGoQbxXc",
-"MmKGJxReec","S77LHZJTXH","8TxD7X6Pin","0MR5XLewvM","6AFT0qQxHP","X6PinhE1Ql","Dz1R32DREs","Vprf2lj07Q","aDGtSa00b5","jzUqRlCMxy",
-"hE1QlUlU3M","4W0Tlrz7Ut","gtCA5aL6AJ","45cIHP6bcg","M6qcGThjNn","l83Udt59lR","oQ87rPb1pa","ZUnqtBpYhV","aFFssMezSW","oVQp6yvOMI",
-"VerEAl83Ud","HzZT8t98iW","jtn0Xdjsrv","mX2GElH1kt","OHaBzLDk6f","s93Ml2DREs","fmIK1GXdoH","KASQ8cQOnv","0YAGH8TxD7","nnP8oCfgr3",
-"9iGoTxReec","SmGzv55rfB","kB5nPuupzk","5ZaEzOz8yZ","7hyVvCp3mZ","zz4ZUJIqXi","HzZT8yofH3","he9IA3otm6","brhlQjfREu","zFgtBQClRL",
-"ZzJHWsoy9t","UmaEvs7Mxk","mz8gxDcpWB","hE1Ql5iGN5","5iGN5CqqaD","WmadADz1R3","yToGWKZamH","VjCZq0YAGH","cmXIXIBe8k","nnP8ogtCA5",
-"ciuWzWMiS3","5ZaEziB08l","fcJOyjS1aj","uN6r3t59lR","JkzUnUmaEv","5VZjSB3qem","pv0i7hE1Ql","UlU3MazIWp","B3qemmX2GE","QbxXcuZPqg",
-"8xEKzWaim6","W3VFHix74r","CIShGChuy3","vOqCEZuDtD","mX2GE8TxD7","8xEKzVprf2","lsQGocShY2","1j5L8zFgtB","SmGzvWMiS3","rz7Ut0Wr5y",
-"Ss0ZuqaofN","dmoS76q6L9","ZzJHW7fKYU","KsjRKi3pyd","qaofNtjQxs","QbxXcFxX9q","CIShGiqv4k","JIqXiSmGzv","MmKGJlCMxy","soy9tulk41",
-"9iGoTKZamH","0YAGHrhl0J","MmsIooVQp6","s7MxktAOsr","CqqaDQbxXc","0YAGHM3zXL","DQimpyEfy9","NcICAcShY2","v8yFNa00b5","PYBf4pT8wu",
-"fcJOyjSjS3","lCMxyTwano","ECMvUxXTI4","sqVrfix74r","ZzJHWNo0Qb","9GXkXfmIK1","IjTwPuoStw","yToGWNhXdu","lweGyThjNn","AmdQdguMb8",
-"ni2v1S2Dfu","cL0aEtlILt","v1Hlns93Ml","FcWrWgdQsS","zFgtBM3zXL","MmKGJh1zcH","AXpwEMojnP","djsrvQssNC","lsQGoMaJQs","QssNCDz1R3",
-"ogLgc0ao3l","9y4lwdhSuH","BFkb8Zv7z0","3otm6OHaBz","5ZaEzzQt6Q","zY1GYjeskS","9XyT9GSQwj","MK07YzHF1q","brhlQ29QAz","uupzkXflUq",
-"jtn0XpWiOs","Mm8siHfyNQ","pAhR17X3uy","14FLRNo0Qb","K20wKFPfSE","oQ87rSjskQ","iqv4kMK07Y","pmeCd3weIF","ru4UGn8pJ9","RsQUqMGlTF",
-"gIYvEBCxeC","K20wKeuZA5","P6bcgtjQxs","RpBQmWDVWJ","i3pydni2v1","SjskQM3zXL","WaWsvfcwDa","ru4UGGv3Fq","pT8wuWaim6","uPX7GqQxHP",
-"yluBxbZLvS","BbwgApv0i7","0h1b1v2eC3","jSjS3M6qcG","s7MxkpmeCd","WMiS3pWiOs","GWqqXoVQp6","VNCPdLewvM","EdBKcblLA9","F6PT2gIYvE",
-"lweGyaDGtS","QbxXcuAWyp","aDGtS0MR5X","s93Mljtn0X","zmLYDEOE1o","bZLvSMm8si","jSjS3JKWYR","lpF6WZuDtD","0h1b1OUqFM","guMb8lkMUA",
-"uupzk0Kyfs","1LB1Lru4UG","Yh1hFsoy9t","X6PinVLTy6","8U2nUcShY2","LbRTHSjskQ","9eoRcECMvU","618DiWmadA","suY4x4W0Tl","Waim6F6PT2",
-"Kr8ysZJTXH","7Ow5CjS1aj","0PktIl83Ud","lj07QYOfrY","taOXK5VZjS","P6bcgDG4sT","tvdkD8FmFH","faHirZUnqt","ZzJHWxReec","P6bcgpFrrl",
-"Oz8yZ1j5L8","Dz1R3AgJHQ","F6PT2QWxoT","blLA9JkzUn","azIWpMojnP","n1pmO5iGN5","07n1cF6PT2","RxrsmeuZA5","GWqqXSs0Zu","CqqaDprNT6",
-"vkCHH0MR5X","RmDcr0Kyfs","euZA5oQ87r","jfREuv8yFN","7fsYMcL0aE","jfREuLewvM","iqv4k7fsYM","MmKGJUlU3M","vOqCEni2v1","pvgjSFPfSE",
-"oQ87rtl72W","Mm8sijS1aj","SbRYyni2v1","EoToPJRJQB","FPfSEe6e4z","MmKGJOHaBz","tvdkDatef2","0PktIX6Pin","ReKEWzHF1q","fcwDaMojnP",
-"CdyBV5iGN5","lpF6W5Drn0","X6PinLbRTH","UlU3MpiJSk","WreyPjzUqR","zY1GYdmoS7","OUqFMOHaBz","qQxHP64s8N","d7vjMAXpwE","SmGzvYf2Ec",
-"azIWpFFDui","gdQsSReKEW","CNHmvuTacx","cL0aEQ6hMC","O3iyQlj07Q","JkzUnlsQGo","brhlQGv3Fq","ZhwG114FLR","uvf7Amz8gx","NhXduRsQUq",
-"zmLYDtaOXK","Dz1R3MaJQs","v1HlnG1RhS","okgRiIBe8k","FnPFBFVMxo","XflUq9iGoT","Uvlv4K4GS8","QYxC0SbRYy","qQxHPOUYuF","8U2nUIn3NS",
-"tuDySJXljW","rz7UtKZamH","FFDuikZANm","CIShGGWqqX","tvdkDsoy9t","M6qcG0YAGH","pT8wuJRJQB","F6PT2euZA5","QChxsiwzGk","3weIFx3LDe",
-"BCxeCpiJSk","rKDLJZuDtD","fcwDaaez9y","ksJbylpF6W","ThjNnTa8f6","Uvlv4Gv3Fq","AXpwE7ku1p","FwEJzfcJOy","wiHrZO3iyQ","azIWprKDLJ",
-"pv0i729QAz","suY4xEoToP","MezSWbZLvS","Ta8f6W7cTs","piJSk16lHc","dpe1v0Kyfs","fFDrJGXdoH","Mkgy8SWfou","rhl0J9GXkX","Dz1R30Wr5y",
-"a00b5d7vjM","QYxC0ZuDtD","CdyBVdQ586","s7MxkI7p2a","yToGWuQIcz","0ao3lVIlwP","14FLR9GXkX","ulk41hYBCK","Pb1paciuWz","ksJbym4bxU",
-"5Mg9rECMvU","AOgEezFgtB","lj07QI7p2a","ZuDtDRxrsm","QnJ1SLewvM","oQ87rgIYvE","JXljW7hyVv","5Drn0OHaBz","lCMxyoGu6x","RsQUqYjB9t",
-"3weIFk85Ae","24ARFUlU3M","07n1coQ87r","4W0TloVQp6","zbIYYZhwG1","t98iWWreyP","07n1cjS1aj","uJScXKASQ8","S2DfuJ2mQi","Uvlv4QChxs",
-"t59lR7fKYU","AXpwEZUnqt","ciuWzB3qem","jtn0XJJs5m","Cp3mZuvf7A","t98iWrKDLJ","1v5hHuJScX","Y1mC0Yf2Ec","VBjhzfFDrJ","JRJQBVjCZq",
-"FjHXRSWfou","IRh48hE1Ql","jfREuVerEA","7ku1pStlDJ","QClRL5iGN5","he9IA5Namm","7lUXZru4UG","tjQxsPYBf4","ZuDtDtAOsr","TXQ0ZJKWYR",
-"OHaBzv8yFN","TXQ0ZfLNg8","RACujrhl0J","hi5X748cHL","Rxrsm9eoRc","blLA96AFT0","uJScX1v5hH","0Kyfs3otm6","e6e4z5drc6","16lHccL0aE",
-"yEfy9L7cGc","StlDJMmKGJ","MmKGJguMb8","xciqpDz1R3","MojnP14FLR","b29RJbgJAz","hSSvQBpYhV","FwEJz1v5hH","ZUnqtuJScX","Gv3Fq4QMc9",
-"DQimp07n1c","DLhzM4dEz6","VNCPdatef2","h1zcHsoy9t","vkCHHxReec","8FmFHbrhlQ","hUTw7Mkgy8","LbRTHpT8wu","Uvlv4JKWYR","No0QblViBv",
-"8hJdtzQt6Q","GrDg7tvdkD","Mm8sifaHir","WaWsvEOE1o","S2DfujiVBP","lm0pDECMvU","kZANms7Mxk","X6PinMmsIo","Uvlv4EoToP","J2mQiTwano",
-"BCxeCCK5W7","Zv7z0W7cTs","yvOMIS77LH","kZANmuupzk","2TRI7Waim6","GSQwj0BmCy","CqqaDFwEJz","CIShGprNT6","fqypyMK07Y","No0QbMm8si",
-"FPfSEFGzgp","L7cGcMm8si","fmIK1qaofN","HlUbF24ARF","ulk41n8pJ9","5iGN5Yw2oU","GWqqXaFFss","Yh1hFgIYvE","lXFOBIKxdL","RACujSs0Zu",
-"8xEKzJJs5m","lCMxy8U2nU","OUqFM3otm6","aDGtSRACuj","I7p2aX6Pin","5iGN5FjHXR","Vprf2s7Mxk","taOXKZhwG1","IKxdL7fKYU","0MR5XFPfSE",
-"Mm8silH1kt","DLhzMKZamH","ni2v1NOHsz","hUTw7FcWrW","5Mg9ri3pyd","tl72W0Wr5y","DG4sToQ87r","BbwgAtl72W","BGaQYYjB9t","CxVEfEOE1o",
-"nnP8ozmLYD","9iGoTThjNn","jeskSh1zcH","lCMxyFVMxo","5NammQbxXc","9XyT914FLR","16lHcx3LDe","vOqCEWMiS3","brhlQzqH0W","GSQwjFFDui",
-"9y4lwB3qem","taOXKPb1pa","CxVEfUlU3M","1LB1L6q6L9","HP433ZJTXH","5VZjSuvf7A","oQ87r5drc6","QChxsXyPZN","D6rByK20wK","PYBf49XyT9",
-"X6Pin29QAz","aFFss2ZHdk","n1pmORsQUq","64s8Nrhl0J","lm0pDbrhlQ","lkMUAZv7z0","Uvlv49GXkX","t98iWBGaQY","14FLRfcJOy","0BmCycmXIX",
-"Yf2EctjQxs","LDk6fprNT6","VerEArz7Ut","bgJAziB08l","ciuWzgdQsS","bZLvSBFkb8","lsQGoVNCPd","YjB9t4dEz6","0PktIFhtgl","2NslmuJScX",
-"RmDcrQYxC0","SbRYy8U2nU","0BmCyCdyBV","Yf2EcIjTwP","F6PT2580YD","KsjRKlj07Q","jS1ajDQimp","uJScXAkKTk","nnP8oWmadA","nlaBy2hEEU",
-"atef2MmsIo","hYBCKFFDui","SWfouFLsph","pv0i7AXpwE","nnP8okZANm","uLtKsWreyP","7hyVvRACuj","VNCPdOxWIH","jS1ajpvgjS","HzZT8W7cTs",
-"iqv4knlaBy","StlDJI7p2a","7lUXZIBe8k","fmIK1pv0i7","JRJQBK4GS8","O3iyQiB08l","ZuDtD7fsYM","7lUXZpvgjS","VIlwPyToGW","9XyT9brhlQ",
-"ydG8USbRYy","MezSWx3LDe","4W0TlksJby","W3VFH9y4lw","i7WMQQ6hMC","ThjNnOUYuF","xXTI4zqH0W","ReKEWCIShG","0MR5XTXQ0Z","8hJdtMkgy8",
-"ru4UGsuY4x","SmGzvhE1Ql","yvOMI2DREs","JkzUnKASQ8","cShY2taOXK","2DREsuN6r3","O3iyQyvOMI","t98iWoVQp6","zqH0WjS1aj","2DREsC2Irc",
-"DQimp2DREs","fLNg8ksJby","vLsmSMmKGJ","KsjRKSmGzv","0BmCyoVQp6","AXpwEn1pmO","IBe8ks7Mxk","h1zcH618Di","aDGtSpT8wu","aFFssOUqFM",
-"KsjRKjiVBP","qUJMdt59lR","uLtKsguMb8","QbxXcOz8yZ","S2DfuNxx9V","x3LDe4W0Tl","dhSuH9y4lw","B3qem0ao3l","5ZaEztjQxs","lH1kt4W0Tl",
-"lXFOBMK07Y","16lHc4QMc9","5iGN564s8N","Dz1R3fqypy","fcJOyEoToP","7lUXZv8yFN","bgJAzK20wK","MmKGJNOHsz","nnP8oOUYuF","vkCHHD6rBy",
-"i3pydVIlwP","Yw2oUStlDJ","EOE1ohSSvQ","l83Ud5nmWv","euZA5CNHmv","dhSuHSmGzv","ZuDtDU3yw5","580YDFFDui","mz8gx4dEz6","aez9yKASQ8",
-"tvdkDpiJSk","CxVEfFPfSE","1j5L8K4GS8","9GXkXCqqaD","mz8gxStlDJ","CxVEfkB5nP","5Drn0QbxXc","AIYUuQClRL","iB08lhi5X7","7hyVvAOgEe",
-"HlUbFRsQUq","VerEAMojnP","XflUqQWxoT","0h1b124ARF","tAOsrRxrsm","Nxx9V618Di","QssNC8cVD3","HRxd8tl72W","yvOMIFLsph","POUYS8U2nU",
-"8cVD3djsrv","a00b5cmXIX","soy9tfaHir","iqv4kMm8si","tl72WCK5W7","QWxoTVjCZq","fcJOyhi5X7","oGu6xqaofN","2Yz7E2Nslm","Zv7z0rhl0J",
-"BbwgAix74r","8RCUApvgjS","sx5Gl8cVD3","FGzgp5iGN5","nlaByCNHmv","5NammQ6hMC","uvf7AJJs5m","FGzgpAkKTk","618Di5Mg9r","oVQp64W0Tl",
-"gjUTupFrrl","6q6L9oGu6x","LewvMkZANm","JIqXiXflUq","DLhzMVBjhz","Ta8f62Yz7E","dpe1vpFrrl","5VZjSMK07Y","580YDIRh48","d85a9RkQke",
-"8TxD70BmCy","s7MxkS77LH","HlUbFzQt6Q","CdyBVJJs5m","Yf2Ec07n1c","blLA9GSQwj","MmKGJThjNn","blLA9DLhzM","NAFuwoGu6x","RzaZAF6PT2",
-"lpF6WWaim6","Cfgr3HzZT8","QClRLZ4I1v","RpBQmlpF6W","8RCUAJIqXi","5nmWvO3iyQ","vLsmSgjUTu","d85a92Yz7E","CIShG7lUXZ","dhSuHWMiS3",
-"ni2v1bgJAz","JkzUn5IhmG","5Mg9r9GXkX","RmDcrhi5X7","DLhzM5iGN5","ReKEW0Kyfs","lH1kt5Mg9r","oQ87r0h1b1","StlDJSWfou","580YDNhXdu",
-"No0QbtvdkD","QbxXcKsjRK","OHaBztaOXK","CK5W7Q6Lix","pT8wus4786","FjHXR5ZaEz","AgJHQ0BmCy","FFDuihE1Ql","jtn0X0BmCy","QbxXcyofH3",
-"pFrrlMK07Y","aez9ykB5nP","45cIHW7cTs","GrDg7Rxrsm","UmaEviKqhr","AOgEeP6bcg","8xEKzQChxs","Pb1pa4QMc9","JRJQBzmLYD","FcWrWW3VFH",
-"XflUq0ao3l","0YAGHMmKGJ","zHF1q9GXkX","aez9y9rlg9","No0QbHzZT8","DG4sTzY1GY","BpYhVvkCHH","lj07QReKEW","iB08lJXljW","AOgEeHRxd8",
-"hE1Qlb29RJ","Yw2oUFFDui","Oz8yZvOqCE","QYxC0zz4ZU","d85a9W7cTs","IjTwPlweGy","HP4330h1b1","mX2GEJRJQB","HlUbFlj07Q","AgJHQQ6hMC",
-"9iGoTd7vjM","qaofNlweGy","t59lRnlaBy","Nxx9V07n1c","6AFT01LB1L","VLTy6IRh48","ReKEWRmDcr","FPfSElkMUA","aFFssS2Dfu","EOE1oK20wK",
-"ZJTXHWaim6","14FLRuN6r3","kB5nPaez9y","CNHmvCfgr3","7ku1pG1RhS","XyPZNgdQsS","dpe1vRxrsm","16lHcqQxHP","ni2v10ao3l","ydG8UIjTwP",
-"MGlTFv2eC3","Kr8ysJkzUn","9GXkXxXTI4","fqypyQnJ1S","zmLYDU3yw5","hSSvQyToGW","Z4I1vru4UG","rKDLJtAOsr","OxWIH5drc6","MezSW4W0Tl",
-"o8Uyd5nmWv","uN6r3fmIK1","5Drn0uTacx","OUYuFBFkb8","CIShGZzJHW","uPX7GGrDg7","MmsIofFDrJ","0MR5XzqH0W","tl72Wxciqp","0Kyfs8cVD3",
-"CxVEfmX2GE","bgJAzNOHsz","fFDrJ4dEz6","cmXIXQWxoT","VBjhzD6rBy","fcJOyt98iW","jiVBPQbxXc","h1zcHWmadA","9iGoTTa8f6","guMb8WreyP",
-"S77LHAXpwE","0BmCycQOnv","rhl0JWPmlx","UlU3MaFFss","FcWrWF6PT2","9GXkXKZamH","jiVBP0MR5X","NOHsz45cIH","zbIYYbrhlQ","ksJbyFhtgl",
-"dpe1vuZPqg","oGu6xatef2","lj07QQbxXc","dpe1vLDk6f","lH1kt5nmWv","qUJMdLewvM","djsrvfcJOy","yluBxNxx9V","fcJOyd7vjM","M6qcGNo0Qb",
-"tuDySlweGy","QYxC0qaofN","QChxsTa8f6","fcJOy1j5L8","faHirdpe1v","DLhzMQClRL","Zv7z0aFFss","JXljWHfyNQ","y94nwRxrsm","fFDrJ1LB1L",
-"dmoS75VZjS","oVQp6zHF1q","ydG8UyofH3","5VZjSNhXdu","oGu6xFhtgl","No0QbtuDyS","zQt6QAgJHQ","GWqqXgf8rI","8RCUAVBjhz","jS1ajqaofN",
-"0YAGH9y4lw","gjUTulsQGo","y94nwZUnqt","14FLRlViBv","RBhp0Fhtgl","Chuy3KsjRK","GSQwj5Mg9r","ECMvUIBe8k","v8yFNZUnqt","VNCPdL7cGc",
-"8RCUAcShY2","W7cTsd85a9","BCxeC4dEz6","8TxD7FjHXR","Mm8si2ZHdk","Yf2Ec5Namm","Pb1pa7Ow5C","uupzkBbwgA","5drc6EdBKc","a00b5n1pmO",
-"zqH0W7X3uy","ksJbyW7cTs","FwEJzRpBQm","HP433SWfou","IBe8ka00b5","nlaByAmdQd","CNHmvcL0aE","SbRYyzbIYY","48cHLL7cGc","FNYIMdQ586",
-"Yh1hFgjUTu","xciqp07n1c","JXljW07n1c","DG4sT2Yz7E","AIYUuZ4I1v","Uvlv4No0Qb","FnPFBMGlTF","Yf2EczmLYD","GWqqXlsQGo","8xEKzdpe1v",
-"ECMvUB3qem","gtCA5BCxeC","4QMc9GXdoH","AgJHQfmIK1","3otm6m4bxU","uZPqggjUTu","2DREszQt6Q","IKxdLNcICA","ix74r5ZaEz","5ZaEzjeskS",
-"fcJOytl72W","MezSWwiHrZ","hUTw7AgJHQ","kB5nPguMb8","5Drn0zz4ZU","9eoRcjeskS","n1pmOrhl0J","UmaEvkB5nP","SWfous4786","7lUXZn1pmO",
-"GWqqXtaOXK","HlUbFXflUq","6AFT0t98iW","jSjS3OxWIH","aFFss9GXkX","lsQGofLNg8","WreyPI7p2a","RzaZAyofH3","SbRYyqQxHP","euZA5pAhR1",
-"0h1b1JXljW","SbRYypv0i7","WmadAcL0aE","LDk6fhi5X7","tuDyS8hJdt","M6qcGBGaQY","QChxsMkgy8","Gv3Fqk85Ae","m4bxUBFkb8","U3yw5y94nw",
-"0BmCyuupzk","vLsmSDG4sT","xciqpOHaBz","FnPFBnFqik","1LB1LZUnqt","5iGN5yvOMI","7Ow5Cs7Mxk","aez9yRpBQm","pAhR1WDVWJ","CdyBV48cHL",
-"mz8gxpv0i7","ru4UGdpe1v","oQ87rO3iyQ","VLTy60YAGH","618DiPOUYS","Q6hMC4dEz6","jzUqRYh1hF","29QAzlkMUA","VLTy6pv0i7","CIShGS77LH",
-"5iGN5K4GS8","IKxdLiqv4k","tvdkDFxX9q","EoToPcmXIX","tAOsrkZANm","m4bxUiKqhr","IRh48C2Irc","SWfou8RCUA","WmadAIjTwP","uN6r38TxD7",
-"qUJMd8cVD3","mX2GEXyPZN","CNHmvjiVBP","RxrsmrKDLJ","GXdoHBpYhV","jSjS3LewvM","ZJTXHKZamH","U3yw5FFDui","FjHXR1LB1L","fFDrJUlU3M",
-"AkKTkBbwgA","jtn0Xk85Ae","lsQGoGv3Fq","8U2nUn1pmO","CIShGlj07Q","In3NSyEfy9","QssNCzHF1q","64s8NokgRi","SmGzvD6rBy","fFDrJpAhR1",
-"mz8gxm4bxU","2Yz7ELewvM","QssNCJJs5m","Z4I1vMaJQs","lm0pDfFDrJ","2ZHdkPb1pa","JKWYRAXpwE","6AFT0OUqFM","lpF6WTXQ0Z","hE1QlCdyBV",
-"NAFuwlpF6W","0PktI5IhmG","ni2v1RACuj","tAOsrPOUYS","pv0i7cQOnv","qQxHPJJs5m","8hJdtDcpWB","FFDuiQnJ1S","bgJAz7ku1p","QnJ1SZUnqt",
-"W7cTslViBv","uPX7GKsjRK","7lUXZY1mC0","CqqaDMGlTF","jzUqRFFDui","lsQGoiwzGk","ZhwG1pWiOs","5Mg9rHRxd8","K20wKwDajX","tuDySOHaBz",
-"7fKYUJJs5m","WMiS3Twano","Ss0ZuksJby","UmaEv0h1b1","cmXIXyEfy9","Q6hMC3weIF","0ao3lxXTI4","nnP8oFnPFB","bgJAzciuWz","wiHrZuN6r3",
-"uJScXuN6r3","AXpwEgf8rI","IjTwP5drc6","fcwDaECMvU","8hJdtLewvM","djsrvs7Mxk","uN6r3HRxd8","4W0TlyEfy9","NcICAxXTI4","x3LDe5Drn0",
-"okgRi4dEz6","9eoRc3otm6","1LB1LUl4a1","guMb8BbwgA","a00b5WDVWJ","VjCZqAOgEe","AgJHQYh1hF","uTacxYh1hF","Uvlv4ciuWz","ZzJHWlj07Q",
-"ogLgc9XyT9","DQimp7hyVv","suY4xReKEW","GrDg7qUJMd","HP433rKDLJ","jSjS3zFgtB","P6bcgguMb8","hSSvQiKqhr","FwEJzJKWYR","4dEz6lCMxy",
-"lH1ktuQIcz","nlaByhYBCK","Q6hMCJkzUn","l83UdAgJHQ","4dEz6IRh48","zY1GYgIYvE","ThjNn0Wr5y","Chuy3EoToP","HfyNQnlaBy","7hyVvDcpWB",
-"Ul4a1lXFOB","QbxXclpF6W","iwzGkHP433","okgRiIn3NS","BpYhVUlU3M","0PktIhSSvQ","GWqqXqUJMd","Q6Lixv8yFN","5VZjSGSQwj","oQ87rFGzgp",
-"d85a9MmKGJ","Oz8yZxciqp","k85AeSs0Zu","wiHrZ2TRI7","KZamHzY1GY","FPfSEoQ87r","GSQwjhSSvQ","d85a9t98iW","Q6hMCtAOsr","k85Aerz7Ut",
-"WPmlxhYBCK","RpBQm0YAGH","MK07Yi3pyd","EoToPWMiS3","MmKGJa00b5","DcpWBuvf7A","K4GS8fmIK1","mz8gx2TRI7","SWfoud7vjM","RkQkerz7Ut",
-"9rlg95IhmG","cShY2GXdoH","RxrsmzbIYY","5Mg9riqv4k","DQimpDG4sT","o8UydZuDtD","n8pJ9TXQ0Z","Q6LixIjTwP","yluBxC2Irc","S77LHP6bcg",
-"jeskSWaim6","RACujazIWp","KASQ8he9IA","7fsYM7fKYU","55rfBni2v1","4dEz6rz7Ut","1LB1LpmeCd","uupzkGrDg7","QYxC0hSSvQ","suY4xgf8rI",
-"ZUnqtsqVrf","iKqhr5iGN5","WDVWJCfgr3","uoStwuAWyp","Kr8ysYf2Ec","iqv4kJJs5m","y94nwYjB9t","he9IAiqv4k","FNYIM9XyT9","KsjRKStlDJ",
-"atef2yvOMI","Ul4a1VjCZq","IKxdLFLsph","jfREuAgJHQ","QbxXciwzGk","3weIFPb1pa","2ZHdkOxWIH","Gv3Fqzz4ZU","prNT6NcICA","hUTw7QnJ1S",
-"t98iWuZPqg","JkzUn14FLR","GrDg7GSQwj","gtCA5pmeCd","uZPqgRmDcr","5ZaEzYh1hF","Z4I1vUmaEv","X6Pin0YAGH","soy9tNxx9V","Ul4a1QnJ1S",
-"MojnP2ZHdk","cmXIXHRxd8","9rlg9Ta8f6","t98iWtaOXK","CNHmvDG4sT","EdBKcUl4a1","O3iyQJIqXi","soy9tzY1GY","5nmWvKASQ8","ZuDtD9eoRc",
-"IKxdLaFFss","qQxHPQnJ1S","55rfBx3LDe","dpe1v9iGoT","2ZHdktuDyS","L7cGcrhl0J","atef2djsrv","JRJQBRACuj","MojnPLbRTH","uJScXyluBx",
-"FjHXRxReec","FhtglgjUTu","iwzGkpFrrl","5VZjSiwzGk","ECMvUVBjhz","s4786ksJby","iqv4kHP433","TXQ0ZWreyP","24ARF4dEz6","suY4xazIWp",
-"6AFT0Waim6","ydG8U8U2nU","0Kyfs0PktI","D6rBy5Mg9r","uN6r3Q6hMC","TXQ0ZgjUTu","FwEJzh1zcH","U3yw5QChxs","brhlQBpYhV","NhXdujtn0X",
-"djsrvfmIK1","RkQkeCxVEf","jzUqR4dEz6","XflUqd7vjM","AgJHQpiJSk","VBjhzM3zXL","v1Hln7X3uy","7ku1pFFDui","x3LDeksJby","jzUqRqQxHP",
-"1v5hHhe9IA","8U2nULbRTH","O3iyQGXdoH","lpF6Wrhl0J","RmDcrLewvM","yofH3ReKEW","YOfrY5ZaEz","lH1ktSmGzv","tAOsr1LB1L","P6bcgiKqhr",
-"dQ586RpBQm","zz4ZUYOfrY","kZANm5Mg9r","v1Hln7ku1p","5IhmGRxrsm","nnP8ozqH0W","ECMvU7hyVv","oGu6xmz8gx","vLsmSAIYUu","t59lRt98iW",
-"HP433RmDcr","29QAziB08l","s7Mxkn1pmO","YjB9tMGlTF","Mm8sinFqik","JRJQBCfgr3","tuDyScmXIX","Twano5Mg9r","RzaZAv8yFN","fLNg8KASQ8",
-"YjB9tDQimp","t59lRfLNg8","o8UydiKqhr","JIqXiCp3mZ","oGu6xpv0i7","HfyNQ5Mg9r","GSQwj2DREs","POUYSZ4I1v","qUJMdMGlTF","sx5GlW3VFH",
-"zY1GY6AFT0","uQIczmX2GE","aez9yFjHXR","2ZHdk8U2nU","RzaZAatef2","lH1kt580YD","lweGyt59lR","MGlTFQWxoT","SjskQMmKGJ","NAFuwVprf2",
-"POUYSRpBQm","yluBxt98iW","3weIFhi5X7","aez9yXyPZN","nFqikIKxdL","WDVWJuLtKs","ZJTXHuAWyp","M3zXLAOgEe","dhSuHs93Ml","6q6L9euZA5",
-"YjB9tRkQke","mz8gxru4UG","fcwDaQ6hMC","xXTI4AkKTk","nlaByRzaZA","HzZT8Yf2Ec","QbxXcpT8wu","bZLvSnFqik","55rfBM6qcG","4W0TluoStw",
-"9eoRcP6bcg","G1RhShi5X7","EOE1oLbRTH","7hyVvlXFOB","9XyT99eoRc","ix74rEOE1o","sqVrffaHir","7Ow5CFGzgp","O3iyQ7ku1p","nlaBy55rfB",
-"uAWyp8TxD7","yvOMIZhwG1","soy9tzFgtB","07n1ck85Ae","7ku1pAgJHQ","AmdQd16lHc","8cVD3azIWp","MGlTFa00b5","hUTw7FVMxo","8U2nUQworu",
-"piJSkbgJAz","8FmFHRzaZA","uZPqgazIWp","pv0i7ZUnqt","iqv4kuPX7G","FwEJziB08l","e6e4z8RCUA","L7cGctlILt","MGlTFZv7z0","4W0Tls93Ml",
-"JJs5m0ao3l","2NslmTa8f6","WmadAdjsrv","0Wr5yI7p2a","FNYIMzbIYY","djsrvP6bcg","5VZjSkZANm","GWqqXStlDJ","Nxx9VyvOMI","AOgEezqH0W",
-"0ao3liKqhr","lViBvEOE1o","S77LHPYBf4","9iGoTHRxd8","9GXkXFjHXR","9XyT9VLTy6","VIlwPbrhlQ","0ao3lrKDLJ","tuDySPb1pa","lweGyzFgtB",
-"MK07YM6qcG","Uvlv4lpF6W","blLA96q6L9","kB5nPgf8rI","yEfy9In3NS","dmoS7ogLgc","hUTw71v5hH","AmdQdxXTI4","mz8gxUl4a1","J2mQi48cHL",
-"WaWsvAOgEe","UmaEvQ6Lix","XflUqbrhlQ","yvOMIFhtgl","NAFuw9XyT9","SbRYymz8gx","aFFssQWxoT","FhtglRkQke","7ku1ptl72W","VIlwPuJScX",
-"0Wr5ycShY2","VjCZqo8Uyd","W7cTsnnP8o","pv0i7IRh48","faHirUlU3M","x3LDeIRh48","CNHmvyofH3","BGaQYFLsph","X6PinRkQke","Cfgr3Kr8ys",
-"29QAzdmoS7","7ku1pru4UG","M6qcGLewvM","QssNCZUnqt","8U2nUyEfy9","s4786BbwgA","8cVD3QbxXc","ECMvUvkCHH","NhXduguMb8","VIlwPQ6Lix",
-"7hyVvWmadA","0ao3loGu6x","M6qcG5ZaEz","BCxeCxReec","64s8NguMb8","soy9tv1Hln","BbwgAEdBKc","RzaZAQWxoT","MojnPS2Dfu","n1pmO16lHc",
-"gjUTufcwDa","RBhp0jfREu","ReKEWRACuj","MmKGJ24ARF","In3NS8RCUA","9iGoTcL0aE","In3NSIjTwP","7fsYMSWfou","VIlwPoVQp6","CNHmvlXFOB",
-"rhl0Jdpe1v","iwzGkRxrsm","v8yFNfaHir","VjCZqHP433","Kr8ysgdQsS","jzUqR5drc6","fFDrJ6AFT0","lpF6WHRxd8","No0Qb8U2nU","zbIYYIRh48",
-"5Drn0MezSW","RkQkeaL6AJ","BCxeCaFFss","PYBf48FmFH","F6PT20Wr5y","IKxdLzQt6Q","7ku1psoy9t","fcwDaRBhp0","WreyPKsjRK","lCMxyQworu",
-"9y4lwzbIYY","UmaEvNxx9V","VerEA9GXkX","guMb8P6bcg","lsQGoFVMxo","RkQkeeuZA5","aFFss0Wr5y","K20wKFLsph","zQt6Qs4786","MmKGJix74r",
-"24ARFStlDJ","1LB1Ln1pmO","K20wK14FLR","0MR5XGSQwj","M6qcGWMiS3","ZhwG19GXkX","Yf2EcuPX7G","ru4UGs7Mxk","DcpWBlsQGo","FFDuiAIYUu",
-"No0QbuLtKs","WmadAyToGW","FjHXRm4bxU","Q6LixSWfou","MGlTFFGzgp","dQ586L7cGc","XflUqpFrrl","zHF1q8U2nU","azIWpyofH3","lpF6WGSQwj",
-"s93Ml16lHc","tjQxs2DREs","6q6L9h1zcH","oQ87r8xEKz","VNCPdX6Pin","7X3uyCNHmv","sqVrfRACuj","VLTy6DG4sT","QssNCJkzUn","kB5nPrhl0J",
-"MojnPQworu","lXFOBAgJHQ","4W0TlprNT6","IBe8klViBv","hi5X77hyVv","KZamHYjB9t","HlUbFmX2GE","fcwDa2Nslm","MaJQsulk41","W3VFHm4bxU",
-"2Yz7Ek85Ae","i7WMQ9eoRc","7fKYURmDcr","VLTy6HzZT8","h1zcHru4UG","JRJQBdjsrv","FcWrWdpe1v","soy9tGrDg7","0ao3ljiVBP","pvgjS7X3uy",
-"UlU3Mgf8rI","tAOsrHfyNQ","tjQxsKASQ8","d7vjMQ6Lix","wiHrZSmGzv","KASQ8rKDLJ","EOE1oRBhp0","he9IApAhR1","SmGzvGv3Fq","FPfSESmGzv",
-"lH1ktdmoS7","0YAGH24ARF","StlDJHfyNQ","cQOnvtAOsr","UlU3MVIlwP","uvf7A0Kyfs","uvf7AuQIcz","a00b53otm6","Waim6RACuj","VBjhz7hyVv",
-"ZUnqt5VZjS","CqqaDuZPqg","AIYUuJIqXi","l83UduPX7G","pvgjS9GXkX","ZzJHWzz4ZU","gjUTuuvf7A","QnJ1Sjtn0X","fcwDa5ZaEz","GWqqXs7Mxk",
-"QChxslkMUA","6q6L90BmCy","14FLRVLTy6","Oz8yZ9GXkX","ZhwG10BmCy","8FmFHzHF1q","JkzUnIBe8k","lpF6WjeskS","S77LHfcwDa","JKWYRyToGW",
-"0MR5XOz8yZ","iKqhrni2v1","azIWpxciqp","QClRLC2Irc","K4GS8M3zXL","AkKTkhe9IA","Mkgy8NOHsz","uZPqgQWxoT","W3VFHMojnP","zHF1q7ku1p",
-"9XyT9pWiOs","Vprf2oGu6x","v8yFNuZPqg","suY4xHlUbF","t59lRRxrsm","lH1ktYw2oU","Uvlv4zmLYD","CIShGFGzgp","07n1cZUnqt","sqVrfUl4a1",
-"t59lRAOgEe","DcpWBv1Hln","jiVBPiqv4k","SjskQF6PT2","QChxsK20wK","JIqXiKASQ8","RmDcrgjUTu","rhl0JZzJHW","guMb8prNT6","W7cTsQChxs",
-"Pb1pabZLvS","J2mQiwiHrZ","hSSvQC2Irc","ix74rFwEJz","FcWrW14FLR","IRh48zqH0W","2TRI7qaofN","RsQUqtlILt","64s8NzY1GY","GSQwjHzZT8",
-"Y1mC0pWiOs","oQ87rZv7z0","rhl0Jix74r","nlaByZ4I1v","SjskQJRJQB","8hJdtS2Dfu","QworuSs0Zu","Pb1paOz8yZ","JKWYRsqVrf","2Yz7Eaez9y",
-"bZLvSvkCHH","n1pmO9iGoT","No0QbgIYvE","Twanotl72W","cShY2ni2v1","yluBx9XyT9","ZzJHWFNYIM","ciuWzhYBCK","Vprf2KZamH","FGzgphYBCK",
-"GWqqXMmKGJ","Y1mC0WreyP","cL0aEpT8wu","DcpWBCIShG","CK5W74QMc9","7fKYUlXFOB","KASQ8Q6hMC","SjskQAOgEe","FcWrW5iGN5","yvOMINo0Qb",
-"5IhmGrKDLJ","7fsYMsoy9t","LewvMM6qcG","GSQwjXyPZN","M6qcGkZANm","fcJOywDajX","GWqqXsx5Gl","5NammZv7z0","QssNCUvlv4","zqH0WbgJAz",
-"ulk41FPfSE","xXTI4O3iyQ","Kr8ys4dEz6","uTacxyvOMI","Dz1R30h1b1","jSjS35drc6","VNCPdpT8wu","HlUbFQWxoT","Gv3FqpmeCd","aFFssC2Irc",
-"7fKYUHlUbF","DQimpyvOMI","AgJHQuLtKs","XyPZNuoStw","FGzgptuDyS","IBe8kBFkb8","QYxC0uoStw","VjCZqI7p2a","HzZT8BpYhV","lViBv45cIH",
-"v1HlnAkKTk","tAOsr9XyT9","Yw2oUGXdoH","5Mg9rTCgPp","pT8wuxXTI4","okgRipmeCd","b29RJQChxs","CIShGGv3Fq","0PktIix74r","Kr8ysvkCHH",
-"07n1cOUYuF","RzaZABpYhV","RxrsmzqH0W","LbRTHJkzUn","7hyVviqv4k","tAOsrM6qcG","ru4UGDQimp","jzUqRBbwgA","h1zcHzHF1q","RzaZAfFDrJ",
-"BpYhV5Drn0","9rlg96AFT0","rhl0JhYBCK","zY1GYFxX9q","ReKEWZ4I1v","v2eC3TXQ0Z","JkzUnhSSvQ","YOfrY45cIH","lm0pDIRh48","fFDrJprNT6",
-"Mm8siQChxs","OUqFMsx5Gl","TXQ0Z5VZjS","rhl0JzFgtB","kZANm580YD","vLsmSFhtgl","Dz1R3mX2GE","QssNC55rfB","DQimp5iGN5","DcpWBbZLvS",
-"L7cGciwzGk","BGaQYBpYhV","s93MlKr8ys","fmIK1AIYUu","sqVrf5iGN5","hYBCKMK07Y","NOHszaFFss","lH1ktDcpWB","VBjhzcmXIX","nnP8osx5Gl",
-"qQxHPfmIK1","pWiOsblLA9","FNYIM7ku1p","yluBxJkzUn","aL6AJPYBf4","yofH3TCgPp","Nxx9ViB08l","JIqXiWmadA","7fKYUFVMxo","ni2v1zFgtB",
-"MGlTFSbRYy","MmsIouupzk","hE1QlHlUbF","4QMc99GXkX","UmaEvDcpWB","GWqqXFPfSE","iKqhrfaHir","FLsph0h1b1","CdyBVtjQxs","pT8wuv8yFN",
-"8hJdtPb1pa","QssNC7hyVv","NcICAStlDJ","TwanozHF1q","WPmlx48cHL","jtn0XAOgEe","580YDfLNg8","pmeCdblLA9","WPmlxmz8gx","QnJ1SJIqXi",
-"tAOsrazIWp","KASQ85Drn0","qQxHPfqypy","t59lRn8pJ9","zz4ZUUlU3M","7Ow5C6q6L9","a00b5GrDg7","FwEJzChuy3","W3VFHdjsrv","TwanopFrrl",
-"fcwDadhSuH","Uvlv4AXpwE","HfyNQ8xEKz","HRxd8WaWsv","45cIHSbRYy","dmoS7CxVEf","FhtglMojnP","aDGtSECMvU","POUYSVprf2","ciuWzFwEJz",
-"atef2Zv7z0","rz7UtZv7z0","3otm6uQIcz","UmaEvrhl0J","MmKGJ7ku1p","gjUTu1j5L8","fqypyuupzk","BGaQYbgJAz","v1HlnDcpWB","uQIcz9rlg9",
-"rKDLJKsjRK","FhtglzQt6Q","s7Mxkdpe1v","EOE1oFFDui","VjCZqlweGy","yluBxd85a9","h1zcHl83Ud","djsrvv2eC3","BCxeCRACuj","iwzGky94nw",
-"RBhp05iGN5","cQOnvCfgr3","618DiDcpWB","dQ586lkMUA","5VZjSYOfrY","SWfouNxx9V","UlU3MFFDui","AIYUu0ao3l","JIqXiRACuj","aL6AJyEfy9",
-"rhl0J5Drn0","jzUqR0Wr5y","jiVBPQWxoT","pvgjSv8yFN","FnPFBlj07Q","WaWsvtuDyS","dhSuHgtCA5","zbIYYlH1kt","dQ5867Ow5C","24ARF9eoRc",
-"StlDJsoy9t","rz7UtRBhp0","nlaByoQ87r","yofH3oVQp6","Oz8yZFVMxo","cShY2nnP8o","mz8gxPb1pa","ciuWzjfREu","VjCZquN6r3","KsjRKNcICA",
-"nFqiklpF6W","Y1mC0lsQGo","fcJOyCxVEf","5ZaEzhe9IA","F6PT25ZaEz","0h1b1618Di","zqH0W8U2nU","FnPFB14FLR","hi5X7FFDui","djsrvXyPZN",
-"MmKGJ16lHc","MmKGJtvdkD","oVQp6RzaZA","SbRYyF6PT2","taOXKsx5Gl","29QAzCp3mZ","2ZHdk5ZaEz","Chuy3yluBx","M6qcGhSSvQ","FLsphIBe8k",
-"FxX9qEdBKc","HlUbFsuY4x","QssNCHzZT8","lsQGov8yFN","pmeCdX6Pin","cQOnvMezSW","VerEAsqVrf","4dEz6NOHsz","FFDuifcwDa","Oz8yZNAFuw",
-"nnP8omX2GE","NcICAsqVrf","Oz8yZM6qcG","GrDg7WDVWJ","TCgPpiqv4k","TCgPpaL6AJ","lweGycShY2","Nxx9VaDGtS","0PktIpv0i7","vLsmSThjNn",
-"14FLRZzJHW","yluBxVLTy6","Zv7z0lm0pD","NcICARpBQm","fLNg8yvOMI","KsjRKSs0Zu","nFqik6q6L9","fFDrJ618Di","WPmlxRkQke","Mkgy8NhXdu",
-"WMiS3S77LH","WreyPS77LH","hSSvQ0Wr5y","EoToP48cHL","K20wKFNYIM","JRJQBOUqFM","ciuWz14FLR","NOHsz0h1b1","FVMxo5nmWv","s4786vkCHH",
-"0MR5XRACuj","y94nwFVMxo","x3LDeFnPFB","GSQwj5drc6","ReKEWs7Mxk","S77LH0YAGH","HRxd8TCgPp","jzUqRCp3mZ","Cp3mZfFDrJ","StlDJt98iW",
-"EdBKcKASQ8","8U2nUuPX7G","7fKYUv2eC3","rKDLJK4GS8","4dEz6Dz1R3","xReecl83Ud","F6PT28FmFH","J2mQilj07Q","kB5nPReKEW","yluBxMm8si",
-"VBjhzJIqXi","7Ow5CcQOnv","bgJAzgf8rI","Mm8siVIlwP","0Kyfsdjsrv","B3qemFxX9q","v8yFNlkMUA","fqypyx3LDe","FnPFBFxX9q","hi5X7NOHsz",
-"5drc6oQ87r","KZamH5nmWv","JRJQBoVQp6","0PktI7Ow5C","SbRYyJKWYR","KASQ80YAGH","6q6L9RmDcr","ni2v15IhmG","7X3uyF6PT2","8TxD7EdBKc",
-"RBhp0uupzk","gf8rIcmXIX","48cHLh1zcH","JKWYRBpYhV","fcJOy8RCUA","Dz1R3KsjRK","dpe1v0MR5X","Kr8ysaL6AJ","HlUbFB3qem","5Mg9r7X3uy",
-"2ZHdkVerEA","t98iWGv3Fq","gIYvEfFDrJ","Uvlv4EdBKc","QnJ1SfaHir","SWfouxciqp","tAOsrbrhlQ","45cIHvLsmS","1v5hHWDVWJ","TCgPpGv3Fq",
-"IRh485ZaEz","DLhzM2ZHdk","Ta8f64dEz6","aFFssgf8rI","uN6r3uLtKs","64s8Nrz7Ut","5iGN5AgJHQ","UlU3Mulk41","uQIczQWxoT","FFDuimX2GE",
-"45cIHo8Uyd","TwanolkMUA","AIYUuxXTI4","v2eC3ZhwG1","hi5X78cVD3","tuDySzHF1q","3otm6FnPFB","lweGyWaim6","D6rByYw2oU","fmIK1yToGW",
-"No0Qbv1Hln","vLsmSPOUYS","5nmWvFwEJz","RzaZA9rlg9","Cp3mZ5iGN5","dQ58624ARF","MezSWZzJHW","Chuy3mz8gx","1j5L8azIWp","8RCUAlXFOB",
-"8cVD3gtCA5","hi5X7Q6Lix","FwEJz8cVD3","F6PT2aFFss","Vprf2ZJTXH","LewvM0Kyfs","B3qemy94nw","Ss0ZuTa8f6","MmKGJ9rlg9","zHF1q5VZjS",
-"EOE1ouZPqg","IKxdLs7Mxk","jfREu0YAGH","atef2TCgPp","BbwgAAXpwE","pmeCdEdBKc","ydG8UWMiS3","7hyVvsoy9t","ogLgcyEfy9","M3zXLpv0i7",
-"uoStwkB5nP","Vprf2LDk6f","t59lR9eoRc","ZzJHWI7p2a","YOfrYFxX9q","FnPFBStlDJ","MGlTFJKWYR","aez9ys7Mxk","X6Pin2ZHdk","D6rBy3weIF",
-"Cfgr3BpYhV","suY4xatef2","D6rByS77LH","ZUnqtSmGzv","nFqiktjQxs","qQxHPHfyNQ","Nxx9VhUTw7","WreyPCqqaD","sx5Gl0BmCy","4dEz6PYBf4",
-"TCgPpK4GS8","48cHLUmaEv","K4GS8Mm8si","RkQkeStlDJ","CxVEfNo0Qb","JkzUnQworu","RmDcr7lUXZ","Dz1R3qQxHP","55rfBReKEW","zz4ZUMGlTF",
-"s93MlXyPZN","55rfBuupzk","bgJAz7lUXZ","Yh1hFVerEA","RsQUqpvgjS","wDajXoGu6x","I7p2aQChxs","gIYvEBFkb8","5IhmGYh1hF","JkzUn0PktI",
-"CNHmvDLhzM","POUYSFLsph","5ZaEzFFDui","7lUXZW7cTs","5drc6tlILt","rhl0JMmsIo","RmDcr6AFT0","AIYUusuY4x","CxVEfvOqCE","ciuWzhe9IA",
-"JKWYRwDajX","taOXKtAOsr","tAOsrPb1pa","dQ586prNT6","IRh48FwEJz","LDk6faDGtS","8FmFHRxrsm","5nmWvOHaBz","tuDySRzaZA","FPfSEGv3Fq",
-"jzUqRjiVBP","uPX7G07n1c","aez9yiKqhr","OUqFMUlU3M","zFgtBxXTI4","FVMxobZLvS","AmdQdjzUqR","gIYvEfmIK1","No0QbhUTw7","J2mQiyofH3",
-"7lUXZDG4sT","tuDySDLhzM","8cVD3gf8rI","s47865Namm","QClRLAmdQd","blLA9MaJQs","lsQGoECMvU","uPX7GhE1Ql","MojnPQYxC0","7X3uyGSQwj",
-"jiVBPciuWz","oQ87rn8pJ9","pmeCdDG4sT","XflUquAWyp","xXTI4Uvlv4","KsjRKpWiOs","zmLYDEdBKc","piJSkFwEJz","ZUnqtfFDrJ","YOfrY6AFT0",
-"WMiS307n1c","i3pydlsQGo","brhlQuJScX","64s8N5nmWv","iB08l1LB1L","jtn0Xn8pJ9","W3VFH1v5hH","WPmlxhUTw7","07n1cGXdoH","AkKTk7hyVv",
-"o8UydUmaEv","qQxHPAOgEe","tjQxsuN6r3","29QAzrKDLJ","9eoRcZv7z0","TwanoCK5W7","0KyfsQnJ1S","s47861j5L8","IBe8k55rfB","AmdQdNOHsz",
-"Chuy3BCxeC","U3yw5aL6AJ","lkMUA2ZHdk","0YAGHb29RJ","5VZjSzFgtB","iB08lb29RJ","MaJQsdjsrv","SjskQulk41","ZhwG16q6L9","lViBvtl72W",
-"WmadAAOgEe","hSSvQFxX9q","AXpwEh1zcH","brhlQuAWyp","8FmFHFNYIM","zY1GYgtCA5","nnP8opiJSk","0ao3lSWfou","HlUbFjzUqR","aFFssfaHir",
-"zz4ZUNo0Qb","CxVEfZzJHW","xciqpEoToP","K20wKi3pyd","YjB9tZJTXH","uTacxS2Dfu","i3pyd2TRI7","lXFOBcQOnv","VIlwP1LB1L","pvgjSWaWsv",
-"0h1b1yToGW","fLNg8Qworu","yofH3MmsIo","fcwDaNhXdu","IjTwPogLgc","3weIFxciqp","NOHszZUnqt","WreyP3otm6","l83Udaez9y","4QMc9QWxoT",
-"14FLRjeskS","SbRYyECMvU","i7WMQaFFss","Yf2EcWmadA","Q6hMCa00b5","i3pydZJTXH","OHaBz7ku1p","FPfSEzQt6Q","uLtKsAOgEe","IjTwPyluBx",
-"P6bcgRBhp0","yvOMIXyPZN","RzaZAs4786","nFqikLDk6f","QWxoT0Wr5y","pAhR1zz4ZU","ThjNnx3LDe","VLTy62Yz7E","yEfy9aFFss","Ta8f6he9IA",
-"CIShGnlaBy","0BmCyrhl0J","n1pmOK4GS8","fcwDaMmsIo","fqypyAOgEe","VjCZqWMiS3","suY4xVLTy6","LbRTHqQxHP","l83Uddpe1v","F6PT2aL6AJ",
-"OUqFMWPmlx","hYBCKBFkb8","gIYvEBpYhV","jSjS3Qworu","Ta8f6hE1Ql","ix74rY1mC0","FNYIMNOHsz","DcpWBNcICA","vOqCEatef2","ZuDtDIRh48",
-"QChxsKZamH","s7MxkW7cTs","cmXIXuTacx","HfyNQJKWYR","n8pJ9Oz8yZ","Ul4a1FNYIM","oQ87rSbRYy","OHaBzfLNg8","pv0i7RsQUq","faHirzz4ZU",
-"VNCPdQWxoT","5ZaEz3weIF","Ul4a1zqH0W","HP433DQimp","AOgEe9XyT9","hSSvQRxrsm","gIYvEFcWrW","FhtglIn3NS","CdyBVGSQwj","0PktI580YD",
-"ThjNnFcWrW","uAWyplpF6W","618DiGXdoH","HRxd8jfREu","yluBxni2v1","hUTw7azIWp","2ZHdkYf2Ec","zz4ZUKZamH","5NammM6qcG","Oz8yZYOfrY",
-"WMiS3ZhwG1","I7p2aFcWrW","Fhtglrz7Ut","iqv4k9iGoT","qaofNReKEW","7fKYUCfgr3","LDk6fEdBKc","MezSWhUTw7","P6bcgpmeCd","7fKYUUl4a1",
-"Yw2oUatef2","0KyfsGSQwj","FxX9qgdQsS","JIqXinnP8o","iqv4kvLsmS","Mm8sitl72W","5VZjSpmeCd","hYBCKdpe1v","prNT6prNT6","IBe8kQssNC",
-"RACujiwzGk","4QMc9uupzk","OxWIHe6e4z","KZamHpiJSk","FxX9qb29RJ","mX2GEEdBKc","RBhp02TRI7","CIShGzmLYD","fmIK1gf8rI","MaJQsDz1R3",
-"kZANmi3pyd","dhSuHlweGy","QnJ1SPOUYS","SmGzvFhtgl","5VZjS48cHL","rKDLJEOE1o","yvOMIHP433","IKxdLVIlwP","CK5W7uN6r3","FNYIMtuDyS",
-"zQt6QFcWrW","9rlg9Chuy3","0Wr5yK4GS8","VNCPd0ao3l","VjCZq7fKYU","tlILtuN6r3","1v5hH8RCUA","QClRLgdQsS","lweGyrhl0J","HlUbFStlDJ",
-"LewvMOz8yZ","UlU3MtaOXK","JIqXirKDLJ","ydG8UlCMxy","ydG8U2ZHdk","i7WMQyofH3","O3iyQ5Drn0","IRh485iGN5","sqVrfUlU3M","GXdoHVBjhz",
-"WreyPKr8ys","vOqCE9y4lw","AgJHQ7fKYU","8TxD7Oz8yZ","5drc6AXpwE","2NslmYjB9t","Uvlv4a00b5","hYBCKkZANm","5drc6uvf7A","lj07QNxx9V",
-"ogLgcIjTwP","In3NS5Mg9r","yofH3ru4UG","SmGzvgdQsS","VBjhzK4GS8","yEfy9zmLYD","F6PT21LB1L","BCxeCpWiOs","MK07YDQimp","rz7UtUmaEv",
-"QYxC0SmGzv","iKqhrguMb8","FnPFBAIYUu","8RCUAcQOnv","KsjRKlCMxy","NOHszKsjRK","5VZjSU3yw5","JKWYRlXFOB","cQOnvcL0aE","ReKEW5Namm",
-"FVMxovLsmS","FnPFB8RCUA","KsjRKLbRTH","AmdQd7hyVv","HRxd89rlg9","aL6AJcShY2","QssNCUlU3M","EoToPiwzGk","4dEz6ZhwG1","wDajXFhtgl",
-"gdQsSK4GS8","gdQsSVjCZq","fLNg8v1Hln","nlaByPOUYS","DQimpksJby","UmaEvzqH0W","MezSWdhSuH","Vprf27X3uy","D6rBy5iGN5","48cHLBbwgA",
-"lXFOBMaJQs","atef2hi5X7","YOfrY7X3uy","GrDg79eoRc","lXFOBIn3NS","s4786ReKEW","lCMxy9XyT9","0h1b1fLNg8","4dEz6ReKEW","29QAzlXFOB",
-"2Yz7EIn3NS","14FLRuvf7A","FnPFBO3iyQ","JIqXiPOUYS","MaJQsLewvM","lViBvgf8rI","NAFuwXyPZN","zmLYDCIShG","kZANmLewvM","In3NSblLA9",
-"jSjS3e6e4z","YjB9tReKEW","C2Irc0BmCy","0PktIQChxs","QssNCQClRL","yToGWWaWsv","dpe1v16lHc","VNCPdMaJQs","GWqqXGSQwj","KZamHXflUq",
-"n8pJ9DG4sT","GrDg70PktI","sqVrfKsjRK","FxX9qMmKGJ","RsQUqCxVEf","AOgEeAgJHQ","iqv4kuoStw","Pb1paBFkb8","cL0aEMaJQs","sx5Gl618Di",
-"0h1b10PktI","No0QbB3qem","S77LHgf8rI","m4bxU48cHL","jS1ajtl72W","MK07YVNCPd","hUTw7m4bxU","iKqhrdmoS7","4W0Tl5ZaEz","7Ow5CgjUTu",
-"JIqXifLNg8","RACujv1Hln","HfyNQCfgr3","uLtKscShY2","AgJHQIBe8k","48cHL2ZHdk","VBjhzqaofN","lpF6WCIShG","prNT6jSjS3","IRh48ogLgc",
-"AgJHQZzJHW","Q6hMCdjsrv","n1pmOlH1kt","DcpWBFhtgl","b29RJazIWp","Cp3mZSjskQ","7X3uyCp3mZ","8hJdtoVQp6","lweGyQ6Lix","1v5hHe6e4z",
-"hYBCKNhXdu","sx5GlYf2Ec","K4GS8ogLgc","oVQp6v1Hln","zY1GYFVMxo","t59lRqQxHP","0MR5XpT8wu","AkKTkU3yw5","wiHrZpv0i7","dpe1vHfyNQ",
-"aL6AJfmIK1","M6qcGMezSW","wDajXO3iyQ","fcJOyLbRTH","TwanoSs0Zu","zHF1qiwzGk","iwzGk9GXkX","9eoRcv8yFN","v8yFNzFgtB","hE1QlzY1GY",
-"Q6LixCxVEf","2NslmZhwG1","GSQwj3otm6","BCxeCgdQsS","StlDJ580YD","cQOnvDG4sT","4W0TlD6rBy","0BmCy0Wr5y","jSjS3rKDLJ","Uvlv4wDajX",
-"Pb1paQssNC","KsjRKRBhp0","FVMxoPOUYS","U3yw5Chuy3","dpe1vW3VFH","s7MxkRpBQm","WDVWJDQimp","i3pydLDk6f","GWqqXvOqCE","6AFT0blLA9",
-"ulk4155rfB","5drc6ReKEW","hSSvQQ6hMC","6AFT0d85a9","EdBKc45cIH","iKqhr0Kyfs","cL0aEK20wK","Ul4a1Dz1R3","rz7UtzbIYY","P6bcgSWfou",
-"iB08lFFDui","K20wKGv3Fq","pv0i7Chuy3","OHaBzVjCZq","M3zXLqUJMd","2ZHdkCIShG","tjQxs2hEEU","hSSvQn1pmO","uZPqgix74r","Kr8ysQWxoT",
-"ciuWzjeskS","Q6hMCzQt6Q","ix74rgjUTu","wDajX0Kyfs","lm0pDAXpwE","HzZT87fsYM","MmsIoMGlTF","vkCHHRxrsm","dQ5865drc6","sx5GljiVBP",
-"F6PT2CK5W7","IKxdL9eoRc","hUTw7WreyP","o8UydpiJSk","fLNg8GWqqX","OUqFMprNT6","h1zcHgjUTu","RpBQmDz1R3","RkQkefqypy","POUYS0PktI",
-"ZJTXHlm0pD","SmGzvEoToP","2TRI7FjHXR","TwanoWMiS3","sqVrfyluBx","yToGWQYxC0","lkMUAmX2GE","xXTI4RpBQm","faHirAOgEe","MmsIoB3qem",
-"GXdoHOxWIH","ulk413otm6","618Dit59lR","XyPZNDQimp","Q6hMCyofH3","gIYvECxVEf","Waim6pAhR1","a00b5uoStw","zFgtBWDVWJ","IKxdL9GXkX",
-"wDajXoVQp6","i7WMQ8xEKz","29QAzYf2Ec","EdBKcOz8yZ","16lHckB5nP","9y4lwThjNn","JIqXiK20wK","HfyNQlH1kt","hSSvQ0YAGH","Qworud85a9",
-"9eoRcWmadA","9XyT9sx5Gl","oVQp6n8pJ9","aFFssuAWyp","5NammMezSW","0YAGHuJScX","IjTwPh1zcH","9iGoTzQt6Q","K4GS8hYBCK","QChxslCMxy",
-"aFFss5nmWv","pAhR1RkQke","GrDg7JXljW","ciuWzSWfou","tjQxssqVrf","KASQ8t59lR","F6PT2618Di","SmGzvfaHir","uJScXFhtgl","lpF6WvkCHH",
-"WMiS3aFFss","8xEKzAmdQd","gtCA5hE1Ql","uN6r3Yf2Ec","FVMxoy94nw","vLsmS9XyT9","qUJMd1j5L8","tvdkD0ao3l","QbxXcQYxC0","oQ87rxReec",
-"zz4ZUFhtgl","FxX9qRpBQm","No0Qb4W0Tl","GSQwj16lHc","suY4xiB08l","lj07QM6qcG","hUTw7D6rBy","aez9ynFqik","qUJMdHfyNQ","lXFOBCfgr3",
-"LbRTHuQIcz","Uvlv4rKDLJ","4QMc9brhlQ","iKqhra00b5","iwzGknFqik","ZhwG1jeskS","1LB1Lx3LDe","nFqikQYxC0","HfyNQHP433","uAWypZUnqt",
-"uJScXlj07Q","RACujS77LH","2NslmlweGy","xciqplkMUA","oVQp61LB1L","0YAGHiqv4k","aL6AJ4W0Tl","2NslmlpF6W","8FmFHTXQ0Z","zY1GYzY1GY",
-"CIShGlH1kt","QChxszHF1q","aFFss0Kyfs","BpYhV4dEz6","uPX7Ggf8rI","pAhR1RsQUq","pT8wuy94nw","ThjNnyvOMI","tAOsr8xEKz","Y1mC0K20wK",
-"FnPFBCIShG","7X3uyPb1pa","8FmFHStlDJ","9iGoTRACuj","1v5hHiqv4k","JkzUnFwEJz","O3iyQKASQ8","piJSkBbwgA","uTacxOUYuF","SjskQuZPqg",
-"DLhzMPOUYS","uupzk64s8N","Ss0ZuWaim6","07n1cVLTy6","Q6hMCwiHrZ","uoStwaFFss","55rfBQChxs","zbIYYW7cTs","jeskS7lUXZ","RsQUqCqqaD",
-"48cHLYh1hF","gdQsSuoStw","No0QbpmeCd","Gv3FqW7cTs","0PktIFFDui","8hJdtfmIK1","2TRI7FxX9q","yluBxJIqXi","vLsmStAOsr","brhlQt98iW",
-"VIlwPzHF1q","rKDLJnFqik","yEfy9dpe1v","O3iyQ0MR5X","zbIYYS77LH","iwzGkY1mC0","Cfgr3VerEA","8RCUAWaWsv","CNHmvChuy3","QworuQbxXc",
-"OHaBz9iGoT","lm0pDAkKTk","yEfy97lUXZ","W3VFHRpBQm","8xEKzUvlv4","euZA5Rxrsm","MezSWM3zXL","1v5hHIn3NS","tjQxsnFqik","zY1GYNhXdu",
-"ZuDtDt98iW","pT8wuOUYuF","uTacxoVQp6","AIYUud85a9","RBhp0QYxC0","Chuy3FjHXR","GrDg7yofH3","aFFss5drc6","lH1ktfaHir","WPmlxYOfrY",
-"CqqaDZuDtD","fcJOyjzUqR","8TxD7nnP8o","S2DfuIn3NS","d7vjMX6Pin","prNT6piJSk","guMb8POUYS","mX2GEJ2mQi","wiHrZ14FLR","07n1ckB5nP",
-"JJs5mx3LDe","lweGyjtn0X","IBe8kGrDg7","0KyfsjfREu","ru4UGnlaBy","KASQ8StlDJ","uZPqglH1kt","WMiS348cHL","XflUqJJs5m","uAWypQbxXc",
-"29QAzFFDui","pmeCdCp3mZ","HlUbFY1mC0","9XyT9n8pJ9","he9IAd7vjM","0Wr5yJ2mQi","Mkgy8I7p2a","soy9tciuWz","MaJQsVprf2","Yw2oUd7vjM",
-"QnJ1SRxrsm","0KyfskB5nP","i3pydFxX9q","tvdkDSs0Zu","LewvM14FLR","RBhp0FFDui","WaWsv8TxD7","AXpwE7lUXZ","d7vjMFjHXR","8cVD3Vprf2",
-"CK5W7ogLgc","0BmCyiqv4k","uupzkVNCPd","Dz1R3GrDg7","1j5L8MmsIo","m4bxUHzZT8","CK5W7CIShG","hE1QlQworu","rz7UtbgJAz","nlaBy0h1b1",
-"WDVWJ5Drn0","ReKEWi7WMQ","BGaQYdQ586","pvgjSGXdoH","DcpWBuQIcz","G1RhSZ4I1v","FhtglKr8ys","OUYuFv1Hln","kB5nPChuy3","s7MxkTCgPp",
-"MojnPZzJHW","FLsphoVQp6","7lUXZokgRi","kZANmD6rBy","WreyPpiJSk","JIqXiWreyP","MezSWcShY2","xciqp2Nslm","JKWYRwiHrZ","xXTI455rfB",
-"TXQ0ZS77LH","b29RJciuWz","WMiS3euZA5","S2Dfu0ao3l","uQIczTa8f6","2TRI7S77LH","Y1mC0Nxx9V","7hyVvM6qcG","oGu6xZhwG1","MezSWSmGzv",
-"sqVrfEoToP","LbRTHbZLvS","NhXduCxVEf","L7cGcyEfy9","LewvM2Yz7E","8FmFHcL0aE","t59lRzz4ZU","BpYhV6q6L9","jeskS7ku1p","nlaBy9XyT9",
-"MGlTFQbxXc","blLA9EOE1o","JIqXitlILt","L7cGculk41","FVMxoWDVWJ","vOqCEM6qcG","NAFuwAOgEe","dmoS7SjskQ","HfyNQfcJOy","jfREu55rfB",
-"2DREs0YAGH","EdBKc64s8N","IRh48IKxdL","1LB1LOHaBz","fmIK1FxX9q","v2eC3zY1GY","qQxHP9GXkX","7lUXZlm0pD","pvgjSVjCZq","v1HlnTCgPp",
-"lweGyPOUYS","K20wKRmDcr","bgJAzpiJSk","Oz8yZMmKGJ","uQIczrKDLJ","aez9yW3VFH","CK5W7QChxs","6q6L9MojnP","F6PT2ydG8U","WPmlxlkMUA",
-"29QAzlsQGo","WaWsvDQimp","Cp3mZyEfy9","2DREs5VZjS","NAFuwFjHXR","D6rBy7lUXZ","16lHcjSjS3","7Ow5C64s8N","BbwgA5drc6","Kr8ysCK5W7",
-"fcwDadpe1v","nlaBykZANm","0h1b1L7cGc","iKqhrk85Ae","uAWyp0YAGH","NOHszRmDcr","kZANmuvf7A","yToGWuAWyp","64s8NYjB9t","F6PT2sqVrf",
-"xReec5iGN5","Yh1hFydG8U","tjQxsDLhzM","o8UydzbIYY","M6qcGWmadA","uZPqg8cVD3","7ku1pm4bxU","bgJAz9eoRc","uAWypL7cGc","KZamHAOgEe",
-"MojnPnnP8o","0BmCy55rfB","VerEAUlU3M","7fsYMLDk6f","a00b5MmKGJ","1LB1LSjskQ","IKxdLUlU3M","ydG8Uh1zcH","5Drn0uJScX","4dEz6uJScX",
-"v1HlnyEfy9","rz7Ut14FLR","AOgEe4W0Tl","2Nslmmz8gx","tlILtm4bxU","K4GS8G1RhS","jzUqRru4UG","gIYvE9eoRc","9XyT9uN6r3","zFgtBChuy3",
-"wiHrZ0Kyfs","2ZHdkaFFss","9iGoTjS1aj","CdyBVo8Uyd","NAFuw0ao3l","pv0i7S2Dfu","Waim6mX2GE","QbxXcCqqaD","OUqFMU3yw5","WPmlxWMiS3",
-"tlILtJIqXi","he9IA0h1b1","JRJQBQChxs","QClRLtvdkD","tvdkDQworu","atef2fmIK1","jiVBPHRxd8","rhl0JFjHXR","WMiS3dmoS7","Q6hMCLewvM",
-"VIlwP5Drn0","OxWIHqaofN","VerEAix74r","BCxeCuoStw","Fhtgla00b5","s7Mxks4786","55rfB2Yz7E","tl72WHP433","Ul4a1okgRi","sqVrfPb1pa",
-"FPfSEZJTXH","FLsphMaJQs","nFqikD6rBy","wDajXNAFuw","lpF6WfcwDa","pv0i77lUXZ","0ao3lK4GS8","faHirDLhzM","yluBxZv7z0","2Nslmn8pJ9",
-"WPmlxuLtKs","xciqpuAWyp","pAhR1WmadA","MojnPYf2Ec","piJSkThjNn","0PktIFwEJz","5VZjSuAWyp","J2mQi7ku1p","YOfrYCK5W7","pv0i7zY1GY",
-"In3NSM3zXL","GrDg7Vprf2","8TxD7Q6Lix","IKxdL14FLR","NcICA7hyVv","JRJQBlm0pD","vOqCERACuj","VLTy6VLTy6","NAFuwSbRYy","uoStwmX2GE",
-"5ZaEz2DREs","iKqhr07n1c","kZANmYh1hF","B3qemqQxHP","lCMxyDLhzM","d7vjMbrhlQ","gdQsSqUJMd","d7vjMqQxHP","OxWIHjtn0X","K20wKF6PT2",
-"EOE1ogf8rI","7ku1pCdyBV","yToGW7X3uy","zbIYYni2v1","FGzgp2ZHdk","MmKGJlpF6W","bgJAzB3qem","9y4lw9iGoT","LbRTHGv3Fq","brhlQMmKGJ",
-"5VZjStjQxs","lsQGoLDk6f","uQIczrhl0J","zQt6QoVQp6","lm0pDcShY2","0Kyfs0BmCy","AIYUuyluBx","FwEJzOUqFM","M6qcG7X3uy","xciqpVLTy6",
-"fcwDaDLhzM","dhSuHsuY4x","7X3uyyEfy9","DcpWBaL6AJ","oVQp6SWfou","uN6r3WaWsv","QYxC0FPfSE","48cHLpAhR1","lpF6WzFgtB","AmdQdpAhR1",
-"nnP8oC2Irc","7Ow5C7ku1p","D6rByTa8f6","pT8wu0ao3l","faHir1j5L8","0Wr5ygdQsS","RBhp0Z4I1v","Z4I1vVerEA","HzZT8580YD","n8pJ9GXdoH",
-"lH1ktuPX7G","ix74rzQt6Q","pmeCdNOHsz","GSQwjFxX9q","2ZHdk7fsYM","GSQwjEoToP","2hEEUYjB9t","HRxd8DcpWB","prNT6618Di","t98iWNOHsz",
-"ECMvUzY1GY","FFDuiReKEW","GXdoHThjNn","QbxXc7fsYM","MojnPhYBCK","cL0aEuvf7A","yToGWd85a9","ix74rJkzUn","VNCPdhSSvQ","AgJHQRxrsm",
-"RzaZAuoStw","JJs5mFPfSE","LewvMCK5W7","qUJMdwDajX","zHF1qYh1hF","s4786WMiS3","jtn0X2Nslm","WmadAX6Pin","ZzJHWru4UG","dmoS7tuDyS",
-"soy9tUmaEv","1v5hHfmIK1","kZANmv1Hln","suY4xsoy9t","lweGy7Ow5C","vkCHH2ZHdk","Vprf2BGaQY","pFrrluTacx","Zv7z0tuDyS","SjskQcQOnv",
-"kB5nPU3yw5","tlILtrKDLJ","tl72WqUJMd","mX2GEVBjhz","PYBf4Kr8ys","ru4UGW3VFH","BpYhVIjTwP","b29RJulk41","VerEAVIlwP","8TxD7jzUqR",
-"7X3uyQYxC0","14FLRYOfrY","gIYvETCgPp","RkQkegtCA5","5ZaEzlCMxy","PYBf4lCMxy","h1zcHTwano","FNYIMYw2oU","IRh4829QAz","G1RhSzFgtB",
-"RACujFNYIM","Ss0Zu2DREs","14FLR7fsYM","ZzJHWYw2oU","4QMc9hSSvQ","FxX9qYjB9t","O3iyQn1pmO","qQxHPuN6r3","D6rByv2eC3","8cVD3MGlTF",
-"G1RhScmXIX","jzUqR4W0Tl","W7cTs7hyVv","MmsIoiqv4k","pWiOsfmIK1","ydG8U29QAz","FPfSEJIqXi","RBhp0tl72W","DLhzMvLsmS","MaJQsX6Pin",
-"BbwgAVBjhz","guMb8mX2GE","7fKYUzQt6Q","ogLgc8FmFH","uAWyptaOXK","t59lRmX2GE","s4786vLsmS","CqqaDhUTw7","Uvlv4GSQwj","iqv4kyofH3",
-"GrDg7jzUqR","PYBf4AmdQd","zqH0W45cIH","14FLR2TRI7","DcpWBqQxHP","s47867lUXZ","pWiOsbZLvS","uQIczQChxs","QssNC45cIH","lH1kt0ao3l",
-"ru4UGMm8si","i7WMQPb1pa","lH1ktFLsph","AgJHQ5nmWv","ZzJHWaDGtS","2TRI7PYBf4","fcwDafaHir","pv0i745cIH","MezSW29QAz","HP433B3qem",
-"uTacxYf2Ec","BCxeCoGu6x","gf8rIIRh48","NhXduvLsmS","RBhp0RACuj","Yh1hFQnJ1S","pAhR1gjUTu","JXljWVBjhz","uoStwFGzgp","FNYIMIn3NS",
-"vOqCEiwzGk","AIYUuKsjRK","P6bcgRxrsm","yEfy9ReKEW","AIYUuYOfrY","gjUTutAOsr","s4786Zv7z0","MK07Y9y4lw","AmdQdNxx9V","X6PinoVQp6",
-"aFFss3otm6","uAWypRBhp0","IBe8k0h1b1","suY4xuPX7G","lj07QlsQGo","FGzgpMK07Y","5drc6Uvlv4","ulk41tuDyS","Mkgy8Waim6","CK5W7lweGy",
-"RsQUqhe9IA","jzUqRaL6AJ","lweGyCxVEf","8xEKzpvgjS","kZANml83Ud","VIlwPCp3mZ","0Wr5yJkzUn","LDk6fZuDtD","JKWYRaDGtS","SjskQFjHXR",
-"ZUnqtoQ87r","i3pydfqypy","AgJHQ55rfB","6q6L96AFT0","ogLgclm0pD","Yw2oUcL0aE","VerEAjS1aj","d7vjM0PktI","wiHrZ48cHL","okgRicmXIX",
-"JXljWVIlwP","FVMxoMezSW","No0QbKZamH","Ta8f6OHaBz","Vprf2fmIK1","2hEEUoQ87r","zbIYY3weIF","IjTwP7ku1p","yofH3s7Mxk","YOfrYRpBQm",
-"0YAGHvOqCE","uvf7AtAOsr","AIYUuaez9y","W7cTsXflUq","gf8rI29QAz","o8UydogLgc","lweGyd85a9","WDVWJOUYuF","GSQwj55rfB","aez9yFPfSE",
-"Yf2EcMmsIo","VIlwP14FLR","gf8rIa00b5","tvdkDksJby","Waim6qQxHP","JkzUnni2v1","vkCHH2TRI7","OUqFMBpYhV","prNT6dpe1v","MojnPiKqhr",
-"64s8Nl83Ud","RkQkeogLgc","fFDrJoGu6x","KASQ8ciuWz","DG4sTni2v1","gdQsS7ku1p","Q6LixKr8ys","yToGWzQt6Q","ulk41jfREu","i3pydv2eC3",
-"WaWsvDz1R3","yvOMIP6bcg","No0QbguMb8","fmIK1xReec","dhSuHMmKGJ","CdyBVSbRYy","sx5GlIRh48","tlILtOUYuF","atef2FLsph","CxVEfCIShG",
-"oQ87r7fsYM","VNCPdiwzGk","Oz8yZ7fsYM","9eoRcdjsrv","2DREsJIqXi","CNHmv5ZaEz","8hJdtgdQsS","Mkgy88TxD7","DQimplweGy","7Ow5C45cIH",
-"2NslmciuWz","yToGWPYBf4","aez9y8U2nU","TwanolViBv","KZamHsx5Gl","Q6hMCYf2Ec","0Kyfs45cIH","CxVEfn8pJ9","1LB1Luvf7A","45cIHuAWyp",
-"0KyfsOUYuF","TXQ0ZVBjhz","HzZT8RACuj","Gv3FqOUqFM","QnJ1SX6Pin","DcpWBUvlv4","Dz1R3v2eC3","CNHmveuZA5","ru4UGO3iyQ","Yw2oUa00b5",
-"Nxx9VyToGW","07n1cjiVBP","CIShGuTacx","jzUqRo8Uyd","MojnPRkQke","okgRiguMb8","JRJQBgtCA5","48cHL8TxD7","iwzGkhYBCK","RsQUqtaOXK",
-"gIYvEL7cGc","euZA52DREs","d7vjMmz8gx","vOqCEMK07Y","Oz8yZ9rlg9","vOqCEVBjhz","yvOMISmGzv","hYBCKW3VFH","AgJHQFjHXR","BFkb8AIYUu",
-"FGzgp0PktI","W3VFHhYBCK","0YAGHlpF6W","U3yw5SjskQ","v2eC3MK07Y","pFrrlo8Uyd","B3qem0MR5X","LDk6fFGzgp","U3yw5WmadA","5Mg9rlpF6W",
-"TCgPpeuZA5","BCxeCzHF1q","ZUnqt3otm6","64s8NLbRTH","3weIFYjB9t","0h1b1pmeCd","X6PindhSuH","zmLYD8hJdt","ni2v1sx5Gl","dpe1vdpe1v",
-"5drc6t98iW","ni2v1U3yw5","RsQUqfmIK1","C2IrctvdkD","Oz8yZm4bxU","uQIczJRJQB","DcpWB2hEEU","o8UydSjskQ","Zv7z0gIYvE","HRxd8euZA5",
-"HlUbFpT8wu","cShY2WreyP","7hyVvoQ87r","yEfy94dEz6","9XyT9kB5nP","uZPqgB3qem","BpYhVSWfou","qUJMdqaofN","CNHmvyluBx","yvOMIyEfy9",
-"QbxXc9XyT9","iB08lCK5W7","C2IrclXFOB","tl72WP6bcg","CIShGgtCA5","e6e4z55rfB","FGzgpMojnP","Yf2Ec64s8N","FnPFBTXQ0Z","CxVEfPYBf4",
-"blLA9bgJAz","580YD5IhmG","9GXkXIRh48","zbIYYKZamH","ThjNnaFFss","5NammGrDg7","uQIczKZamH","B3qem0YAGH","M6qcGFNYIM","BGaQYzFgtB",
-"WDVWJECMvU","07n1cJXljW","CqqaDRACuj","FFDuitl72W","cmXIX0YAGH","7X3uydpe1v","8cVD3lj07Q","ulk41UmaEv","MGlTFChuy3","rKDLJJkzUn",
-"0YAGHyEfy9","v1HlnKsjRK","gdQsSVLTy6","ciuWzzHF1q","azIWp2TRI7","24ARFVBjhz","7lUXZMm8si","FcWrWprNT6","zqH0WLDk6f","580YDX6Pin",
-"fFDrJjS1aj","29QAztjQxs","i3pyd45cIH","kZANmcShY2","9iGoTFFDui","x3LDeMezSW","hUTw70PktI","iwzGkkB5nP","hYBCKIjTwP","he9IAuupzk",
-"9y4lwJIqXi","5NammRBhp0","lkMUAQnJ1S","nnP8oHRxd8","sqVrfFcWrW","7fKYUbZLvS","0h1b1NAFuw","uQIcz7ku1p","fqypyjtn0X","RkQkeCIShG",
-"ZhwG1v2eC3","fLNg8brhlQ","y94nwdmoS7","guMb8Qworu","RBhp0AgJHQ","ZuDtD9rlg9","ZUnqtFhtgl","RmDcrpvgjS","0PktIUmaEv","DG4sTzbIYY",
-"FLsph4QMc9","ksJbyBGaQY","dmoS7Ss0Zu","ReKEWAIYUu","sqVrftjQxs","S2DfuyvOMI","NcICAb29RJ","WmadAC2Irc","h1zcHn8pJ9","QbxXcpvgjS",
-"gdQsS2ZHdk","2ZHdk3otm6","MK07Ym4bxU","Nxx9V5VZjS","FcWrWCfgr3","JRJQByofH3","6q6L92Nslm","dpe1vZhwG1","dmoS7Yw2oU","RmDcryEfy9",
-"JRJQBNxx9V","sx5GlazIWp","UmaEvfqypy","i3pydNOHsz","vOqCE55rfB","ksJbyOxWIH","8FmFH4W0Tl","M3zXLQWxoT","k85AeNOHsz","OUYuFv8yFN",
-"uQIczjS1aj","vkCHHd7vjM","Oz8yZjzUqR","iKqhrprNT6","iKqhrzbIYY","DcpWBFFDui","v1Hln7Ow5C","v2eC3Rxrsm","o8UydYf2Ec","RzaZAmX2GE",
-"fLNg8YOfrY","jtn0XciuWz","OHaBzQbxXc","7hyVvFcWrW","HzZT87lUXZ","B3qemLewvM","AgJHQ8RCUA","GXdoHazIWp","HlUbFksJby","8cVD3ZzJHW",
-"oGu6xM6qcG","QChxsIjTwP","gIYvEpWiOs","ydG8UyluBx","BpYhVsqVrf","uLtKsOxWIH","5Drn0ZuDtD","yvOMIx3LDe","M6qcGJ2mQi","7fKYUMojnP",
-"ZzJHWpvgjS","d85a9OUqFM","DQimpStlDJ","FnPFBogLgc","CxVEfReKEW","lm0pD0Kyfs","ECMvUJ2mQi","ydG8UsuY4x","yvOMIv8yFN","QClRLNo0Qb",
-"zmLYD5Namm","Q6hMCYOfrY","RzaZA8RCUA","uLtKsMmKGJ","BFkb8i7WMQ","JkzUnfmIK1","iwzGkkZANm","B3qem7ku1p","lweGyVjCZq","n1pmObrhlQ",
-"ogLgc7ku1p","45cIHpT8wu","n8pJ9kB5nP","RmDcrFnPFB","7X3uyMojnP","gf8rIxciqp","he9IA9rlg9","d7vjMJRJQB","zFgtB4dEz6","lweGyHlUbF",
-"JRJQByToGW","lweGyhSSvQ","djsrvTXQ0Z","hUTw78FmFH","SWfounFqik","sx5Gl8U2nU","FPfSENcICA","0ao3l5iGN5","618DiB3qem","ni2v1cmXIX",
-"cShY2SbRYy","GWqqXNAFuw","Kr8ysyEfy9","NhXdupWiOs","AkKTkuAWyp","blLA90Kyfs","CK5W7QWxoT","WreyPQbxXc","uZPqgMojnP","M3zXLhE1Ql",
-"CK5W7O3iyQ","k85AeIRh48","uTacxpmeCd","he9IAAOgEe","yToGWpAhR1","Yw2oUFPfSE","uZPqgThjNn","hE1QlKsjRK","ZJTXHvkCHH","tlILtdmoS7",
-"dQ586zmLYD","AmdQdMaJQs","xReecuTacx","EOE1o1v5hH","dQ586faHir","JJs5mPYBf4","ciuWzBCxeC","BGaQYMmKGJ","IjTwP1LB1L","P6bcgDQimp",
-"ZhwG15iGN5","NAFuw5VZjS","J2mQi2Nslm","s93MloQ87r","RsQUqS2Dfu","wDajX580YD","a00b5fFDrJ","uvf7AVBjhz","JkzUnuPX7G","BpYhVYOfrY",
-"PYBf407n1c","HlUbFGXdoH","lViBvBGaQY","FFDuiulk41","HzZT88RCUA","CK5W7vkCHH","uvf7AS77LH","zbIYYtuDyS","n1pmOoVQp6","aFFssGrDg7",
-"ulk410BmCy","JXljWa00b5","BbwgABFkb8","fqypymX2GE","24ARFFwEJz","t98iWzY1GY","55rfBGSQwj","x3LDewDajX","y94nwX6Pin","Yh1hFWPmlx",
-"8RCUAPOUYS","UmaEv7Ow5C","KsjRK2TRI7","2TRI7tAOsr","taOXKaL6AJ","ix74rzqH0W","tvdkDDQimp","ECMvUjSjS3","uoStwrz7Ut","2Yz7EzmLYD",
-"No0QbjiVBP","FhtglCNHmv","pAhR1cmXIX","pAhR1WMiS3","6AFT0Yw2oU","h1zcHjS1aj","uPX7GS77LH","EdBKcLbRTH","QnJ1SOUYuF","b29RJPb1pa",
-"rhl0Jn8pJ9","07n1c7fKYU","cQOnvuJScX","pT8wuokgRi","FFDuiQYxC0","suY4xi3pyd","NOHszMmKGJ","0YAGHDLhzM","gIYvEulk41","1v5hHB3qem",
-"pmeCdSmGzv","ZuDtDsuY4x","JKWYR6AFT0","tlILtGrDg7","7ku1p5drc6","lXFOBlsQGo","Ss0Zuulk41","AIYUuuLtKs","F6PT2Zv7z0","14FLRoVQp6",
-"MK07YvkCHH","he9IAY1mC0","Ul4a1WMiS3","2Yz7Es7Mxk","ZUnqtzFgtB","FNYIMKr8ys","FcWrWXflUq","Z4I1vJRJQB","Yf2EcQssNC","0BmCyd7vjM",
-"s93Ml6AFT0","yofH3K20wK","iwzGkIn3NS","RACujM6qcG","CIShGzz4ZU","brhlQ6AFT0","cL0aE8TxD7","XyPZNRpBQm","BCxeClj07Q","JkzUn16lHc",
-"W7cTsNcICA","pAhR1uAWyp","vkCHHQChxs","xReeccQOnv","kB5nPokgRi","5drc6QssNC","CqqaD618Di","oVQp6bZLvS","piJSkMmKGJ","XflUqe6e4z",
-"atef2s93Ml","sx5GlprNT6","7fsYMjeskS","8RCUApv0i7","S2Dfu9y4lw","wiHrZX6Pin","uN6r3kB5nP","okgRi8cVD3","Mkgy84dEz6","1LB1LHRxd8",
-"pv0i7pvgjS","OUYuFStlDJ","FxX9qPb1pa","nlaByulk41","EdBKc8hJdt","HP433v8yFN","zHF1qtl72W","RxrsmXyPZN","QWxoTd7vjM","tl72W0YAGH",
-"FFDuihi5X7","CK5W7bZLvS","jeskSt98iW","1v5hHh1zcH","euZA54QMc9","1v5hHHP433","LDk6fFxX9q","atef25Drn0","OUqFMLbRTH","FFDuiTa8f6",
-"zz4ZUulk41","GrDg7WaWsv","ciuWzDQimp","1j5L8pAhR1","iwzGkG1RhS","M6qcGgf8rI","WPmlxTXQ0Z","HP433pWiOs","5Drn0SmGzv","W7cTs1v5hH",
-"v8yFN0Wr5y","Chuy3atef2","HzZT8POUYS","POUYSZhwG1","guMb8PYBf4","y94nwxXTI4","zQt6QDQimp","gIYvEC2Irc","n1pmO24ARF","CK5W7JkzUn",
-"he9IADz1R3","xXTI4Q6hMC","fLNg8Z4I1v","rhl0JCp3mZ","e6e4zHzZT8","QClRLAIYUu","8RCUAHRxd8","kB5nPnlaBy","n8pJ9blLA9","Yf2EcXflUq",
-"24ARF29QAz","Q6Lixlj07Q","cShY2aFFss","SWfouBpYhV","JIqXifqypy","sx5GlXyPZN","aDGtSuupzk","dmoS7y94nw","fmIK1wiHrZ","7fKYU1j5L8",
-"WreyPNAFuw","lj07QDQimp","RpBQmni2v1","4dEz6zbIYY","uLtKsZuDtD","oVQp6ciuWz","v2eC3QssNC","F6PT2FFDui","RACujtlILt","pAhR1AOgEe",
-"yvOMIRBhp0","iqv4kzY1GY","nlaByyEfy9","jiVBPMkgy8","TwanoMGlTF","L7cGcL7cGc","d7vjMuAWyp","Mkgy8RACuj","P6bcgCdyBV","NOHszlViBv",
-"EOE1osqVrf","CqqaD55rfB","QssNCFFDui","cQOnvpAhR1","Dz1R3pvgjS","cmXIXHlUbF","lkMUACp3mZ","vkCHHpv0i7","9GXkXJKWYR","BFkb8EdBKc",
-"CK5W7KASQ8","t98iWL7cGc","16lHcOxWIH","0ao3lZv7z0","QbxXc4dEz6","suY4xhe9IA","Ta8f65IhmG","I7p2a3otm6","rz7UtlH1kt","faHircmXIX",
-"EoToP1j5L8","s93Mllm0pD","No0QbgtCA5","IRh48lpF6W","2Yz7EMezSW","JXljWQbxXc","FjHXRIRh48","lkMUAlj07Q","3otm6atef2","7lUXZFjHXR",
-"ru4UG7fKYU","x3LDesqVrf","s4786Y1mC0","FVMxozqH0W","Zv7z0okgRi","lweGyblLA9","3otm6jzUqR","e6e4zHP433","DG4sTK20wK","mX2GEYf2Ec",
-"k85AeoGu6x","iwzGk14FLR","pT8wuKsjRK","RsQUqv1Hln","dmoS7KsjRK","GSQwjaez9y","NcICAD6rBy","Ta8f6n1pmO","BFkb8Gv3Fq","ksJbyk85Ae",
-"bgJAz16lHc","Z4I1viKqhr","NAFuwXflUq","IjTwP8U2nU","WaWsvzHF1q","SWfoupFrrl","PYBf4brhlQ","AmdQdDQimp","IBe8k1LB1L","ciuWzNhXdu",
-"AkKTkyToGW","zFgtBtuDyS","S77LH14FLR","OHaBznnP8o","RzaZA5iGN5","EdBKcFLsph","Mm8siAgJHQ","sx5GlQClRL","mX2GEK4GS8","FcWrWNxx9V",
-"lH1ktOz8yZ","AgJHQpv0i7","prNT6RzaZA","b29RJblLA9","rKDLJQChxs","iqv4kd7vjM","Oz8yZZ4I1v","6q6L9bgJAz","WMiS3uAWyp","M6qcGjtn0X",
-"LewvMZ4I1v","taOXKIn3NS","9iGoT4W0Tl","uPX7Gulk41","MK07YZv7z0","piJSkU3yw5","LewvMuoStw","9rlg9FNYIM","580YDWaWsv","ydG8UDG4sT",
-"ZuDtDuQIcz","lkMUAFNYIM","kZANmSs0Zu","X6Pini3pyd","0BmCy45cIH","brhlQRmDcr","In3NS2Yz7E","s7MxkIjTwP","ECMvUlsQGo","48cHL7fsYM",
-"yluBxzHF1q","Waim6zFgtB","cShY2wiHrZ","mz8gxt98iW","K20wKO3iyQ","YOfrY1LB1L","RsQUq9eoRc","24ARF1LB1L","WaWsvtlILt","yluBxciuWz",
-"5ZaEzQYxC0","uQIczuLtKs","8cVD30PktI","M3zXLjzUqR","iqv4ktvdkD","8hJdtkZANm","2TRI7ThjNn","dhSuHfFDrJ","fLNg8LDk6f","5iGN5vOqCE",
-"k85AeOHaBz","6AFT0FnPFB","0YAGHtuDyS","VBjhzuTacx","LDk6fRzaZA","QChxsHP433","he9IA0MR5X","zQt6Q0PktI","hi5X7uPX7G","P6bcg4W0Tl",
-"Q6hMCK4GS8","Pb1paDG4sT","0MR5X2DREs","tvdkDL7cGc","M3zXLmz8gx","uLtKsrz7Ut","JKWYRRACuj","oGu6xzHF1q","Waim63weIF","HP433XyPZN",
-"HfyNQzY1GY","0BmCys93Ml","tjQxsIBe8k","LewvMlweGy","dpe1vJ2mQi","tl72WzmLYD","GrDg7y94nw","uTacx0ao3l","QbxXce6e4z","zY1GYCp3mZ",
-"atef2O3iyQ","CdyBVTa8f6","U3yw5sqVrf","GXdoHOUYuF","prNT6KASQ8","NOHszF6PT2","xXTI4VLTy6","s7MxknFqik","NhXduEOE1o","8cVD3rz7Ut",
-"In3NS0Wr5y","Ta8f6pT8wu","8xEKzKsjRK","uTacxRkQke","e6e4ze6e4z","m4bxUwiHrZ","Gv3Fq2DREs","EOE1oe6e4z","prNT6Vprf2","2Yz7E5Namm",
-"gjUTuJRJQB","8U2nUuN6r3","VLTy6UmaEv","yToGWzY1GY","euZA5ciuWz","AOgEee6e4z","zqH0W4dEz6","LbRTH7lUXZ","soy9tEoToP","BpYhVvOqCE",
-"S77LHMezSW","ZzJHWfLNg8","2NslmHzZT8","MojnPMaJQs","yofH3kB5nP","7Ow5CYh1hF","EoToPiqv4k","4dEz6zHF1q","HRxd8GWqqX","Q6LixnnP8o",
-"dmoS75Mg9r","PYBf4i3pyd","4W0Tl9eoRc","fcJOyuPX7G","FjHXR5IhmG","AIYUuQWxoT","9iGoTfFDrJ","lweGyAkKTk","9GXkXW7cTs","1j5L8Gv3Fq",
-"uvf7ADLhzM","AOgEe7hyVv","FjHXRyofH3","Q6hMCOUqFM","WmadAS2Dfu","HfyNQkB5nP","9eoRcUmaEv","t59lRUl4a1","Vprf2rz7Ut","ulk41mX2GE",
-"QClRLprNT6","0BmCyS2Dfu","lH1ktpvgjS","2Yz7EZ4I1v","ydG8UiB08l","iqv4kCK5W7","7X3uybrhlQ","K20wKfcJOy","aDGtSChuy3","ni2v1RzaZA",
-"MaJQs0ao3l","IBe8kJKWYR","QworuBCxeC","IKxdLy94nw","s93MlP6bcg","MK07YjeskS","S77LHgdQsS","EoToPQWxoT","ReKEWiwzGk","SjskQbZLvS",
-"jSjS324ARF","lpF6WoVQp6","8hJdtkB5nP","U3yw5JIqXi","i7WMQStlDJ","MaJQsDG4sT","O3iyQzz4ZU","1j5L8BGaQY","No0QbMmsIo","HfyNQHRxd8",
-"SmGzv7fKYU","Y1mC0IjTwP","WDVWJiKqhr","bgJAzvLsmS","HfyNQuLtKs","WDVWJzHF1q","guMb8ogLgc","ECMvUOxWIH","v2eC3VBjhz","WMiS3pT8wu",
-"07n1ccQOnv","pmeCdazIWp","yvOMIlkMUA","BbwgAGrDg7","uPX7GBGaQY","580YDuZPqg","yofH3YOfrY","GWqqXgdQsS","45cIHe6e4z","5drc6O3iyQ",
-"qQxHPW7cTs","OUqFMBbwgA","hYBCKrz7Ut","Q6hMCQworu","PYBf4WreyP","QClRLLbRTH","0MR5Xsoy9t","UmaEvBpYhV","zz4ZUiqv4k","VNCPdzQt6Q",
-"s93MliB08l","uN6r3he9IA","TwanoAmdQd","YOfrYCIShG","GXdoHZJTXH","DLhzMtvdkD","nFqiknlaBy","wiHrZwiHrZ","Kr8ysYOfrY","tlILtqaofN",
-"qQxHP618Di","wiHrZKr8ys","Mm8siFxX9q","29QAzHzZT8","guMb8cQOnv","s93MlY1mC0","M6qcGNAFuw","iB08lBbwgA","0PktIjiVBP","7hyVvdhSuH",
-"dQ586P6bcg","RsQUqlsQGo","5VZjSJRJQB","WPmlxciuWz","iB08lDz1R3","2ZHdkhi5X7","5IhmGYw2oU","t59lRW7cTs","d7vjMMezSW","0MR5XCNHmv",
-"fqypypFrrl","jzUqRbgJAz","x3LDepFrrl","x3LDeuTacx","SmGzvMaJQs","FFDuizbIYY","QssNCFLsph","azIWp8FmFH","Nxx9Vaez9y","ksJbymX2GE",
-"rz7UtFNYIM","EoToPcShY2","0BmCyChuy3","0KyfsOUqFM","Ta8f6CK5W7","t98iWW3VFH","RkQkeHP433","RpBQmW7cTs","iqv4kfmIK1","azIWpwiHrZ",
-"s93Ml8xEKz","0MR5XVprf2","2ZHdkBpYhV","b29RJ8xEKz","gdQsSrz7Ut","Yh1hFIBe8k","M3zXL8RCUA","tuDyStl72W","16lHcsoy9t","55rfBUmaEv",
-"IRh48Yh1hF","SjskQ6AFT0","qaofN45cIH","DG4sTX6Pin","TCgPppWiOs","uPX7Gjtn0X","NAFuwTa8f6","uJScXdjsrv","gIYvE4QMc9","aFFssBCxeC",
-"e6e4zpAhR1","BbwgAFFDui","FwEJzC2Irc","Q6hMCx3LDe","yvOMIpv0i7","iqv4kzz4ZU","0KyfsaFFss","suY4xWPmlx","8RCUA14FLR","GXdoHcQOnv",
-"o8UydxXTI4","tvdkDCIShG","wDajXtAOsr","h1zcHuZPqg","Z4I1vxciqp","NcICAtaOXK","jeskS16lHc","zqH0WJIqXi","cShY2bZLvS","8U2nUFNYIM",
-"gtCA57lUXZ","n1pmOECMvU","5drc6fqypy","UlU3MnFqik","IRh48aDGtS","ReKEWYjB9t","MmKGJ7Ow5C","KZamH0YAGH","9y4lwcShY2","mX2GERkQke",
-"Kr8ysHRxd8","CIShGy94nw","W3VFHUmaEv","DLhzMEoToP","Yh1hFSs0Zu","he9IAO3iyQ","CdyBVrz7Ut","TwanowiHrZ","29QAzoGu6x","FjHXRZuDtD",
-"MaJQsn1pmO","uLtKslkMUA","FGzgpd85a9","CK5W7NhXdu","0Kyfsiqv4k","0Wr5yl83Ud","S2Dfu6q6L9","jzUqRprNT6","5VZjSCdyBV","QClRLogLgc",
-"S77LH580YD","BbwgAjzUqR","yluBx8FmFH","0KyfsCIShG","MmKGJkZANm","JKWYRjeskS","8RCUA7lUXZ","ZhwG18cVD3","uTacxsuY4x","TCgPptjQxs",
-"Yf2EcHP433","QClRLAOgEe","bZLvSpiJSk","faHirL7cGc","FPfSE9iGoT","K4GS8UlU3M","tjQxsC2Irc","GXdoHU3yw5","NcICAqaofN","oGu6xiB08l",
-"BpYhVUl4a1","JkzUni3pyd","1LB1LIKxdL","2DREsfFDrJ","BCxeC8U2nU","OHaBzG1RhS","tjQxslkMUA","nnP8oFNYIM","jiVBP0Wr5y","FGzgpPb1pa",
-"jiVBPNhXdu","M6qcGWPmlx","nlaByZUnqt","HRxd8IKxdL","kZANmlpF6W","dpe1vM6qcG","CIShGKsjRK","Kr8yskB5nP","SmGzvPb1pa","ZUnqt07n1c",
-"4W0TlNcICA","SmGzvZ4I1v","OUqFMnlaBy","MGlTFtAOsr","pv0i7cL0aE","hYBCKStlDJ","uoStwcShY2","FPfSELbRTH","6q6L9DQimp","64s8N6AFT0",
-"ZhwG1FGzgp","3weIFIn3NS","Oz8yZazIWp","qQxHPUmaEv","5NammuZPqg","FcWrW29QAz","7fKYUuQIcz","s4786ciuWz","SjskQSjskQ","prNT68hJdt",
-"oVQp6bgJAz","8TxD7RsQUq","t59lRdmoS7","JJs5mDLhzM","Waim6FFDui","In3NSQ6Lix","FFDuiZJTXH","9eoRc0Wr5y","cmXIXuoStw","GXdoHlsQGo",
-"FwEJzM6qcG","jeskS5IhmG","0PktIcQOnv","1LB1LlweGy","Qworu1j5L8","pvgjSWaim6","cShY2hi5X7","ECMvU6AFT0","8FmFHmX2GE","BGaQYGv3Fq",
-"jzUqRJ2mQi","8TxD79iGoT","618Di48cHL","RzaZAgIYvE","rKDLJhUTw7","0h1b15VZjS","v2eC3iKqhr","Yf2Ecs7Mxk","6q6L9tjQxs","cmXIXPb1pa",
-"pvgjSQClRL","1LB1L1v5hH","zbIYYdmoS7","9eoRcjiVBP","6AFT0CxVEf","9XyT9MmKGJ","No0QbCxVEf","GrDg7uupzk","RpBQmix74r","Oz8yZ0PktI",
-"d7vjMvkCHH","YOfrYQnJ1S","rKDLJzqH0W","uZPqgQnJ1S","soy9tPb1pa","jS1aje6e4z","JIqXiHfyNQ","pvgjSyvOMI","CxVEfOUYuF","UmaEvBFkb8",
-"LbRTHMK07Y","t98iWxReec","nnP8ojfREu","8RCUAtaOXK","qUJMdlH1kt","RACujJIqXi","uvf7AJKWYR","gIYvEZ4I1v","s7Mxkb29RJ","K4GS8pT8wu",
-"t98iW29QAz","Yf2EclweGy","S77LHVIlwP","I7p2ai7WMQ","atef2J2mQi","1j5L88FmFH","BpYhVuQIcz","Vprf29y4lw","l83UdvkCHH","L7cGc9y4lw",
-"WaWsvBCxeC","BpYhVksJby","XyPZN9rlg9","ZUnqtnlaBy","8TxD7v8yFN","MmsIoZhwG1","CK5W7EdBKc","SbRYyBFkb8","AkKTkZUnqt","kZANmQbxXc",
-"uN6r3dpe1v","nlaByTXQ0Z","7ku1pVNCPd","Z4I1vMmKGJ","CqqaDJkzUn","gtCA5BpYhV","uupzkm4bxU","DQimppFrrl","RACujCK5W7","gjUTuB3qem",
-"IKxdLyofH3","suY4xHRxd8","LDk6fQWxoT","uN6r3Y1mC0","3otm6RpBQm","gtCA53otm6","jfREuP6bcg","Mm8siSWfou","45cIHQ6hMC","IBe8kM6qcG",
-"DG4sT2ZHdk","8U2nUv2eC3","AIYUuReKEW","pAhR1HzZT8","uZPqgsx5Gl","MaJQsEoToP","DG4sTAXpwE","h1zcH1v5hH","0h1b1ZuDtD","HP433KZamH",
-"ZJTXHEdBKc","nnP8oUvlv4","3weIFuQIcz","kB5nPQYxC0","bgJAzDLhzM","xReec5Namm","Gv3FqVerEA","uoStwU3yw5","Cfgr31LB1L","sqVrfYh1hF",
-"1LB1L8xEKz","Nxx9V9GXkX","vOqCEXflUq","EOE1oWreyP","TCgPpGWqqX","2Yz7Eh1zcH","VerEAh1zcH","ksJbyfcJOy","h1zcHgtCA5","CdyBVokgRi",
-"tjQxsRkQke","POUYS7Ow5C","a00b5Cfgr3","9eoRcOz8yZ","GSQwjMmKGJ","8cVD3qaofN","QworujzUqR","7ku1ppmeCd","Nxx9VWaim6","6q6L9ZzJHW",
-"aDGtS5Mg9r","I7p2aWreyP","bZLvSStlDJ","aL6AJ9XyT9","7lUXZuN6r3","2NslmPYBf4","PYBf4oVQp6","580YDMojnP","8FmFHzmLYD","a00b5DcpWB",
-"AkKTkuZPqg","t98iWhYBCK","pFrrl5Namm","GWqqXbrhlQ","7Ow5CVerEA","AXpwE2TRI7","FjHXR07n1c","StlDJ9GXkX","6AFT0tlILt","D6rByuJScX",
-"jS1ajMmsIo","YjB9taFFss","BGaQYvLsmS","Yw2oUZ4I1v","7fKYU48cHL","zmLYDi7WMQ","FnPFBOxWIH","lj07QJXljW","QbxXccmXIX","d7vjMAIYUu",
-"uQIczZUnqt","Z4I1voQ87r","v2eC3RzaZA","NcICAtuDyS","tuDySZUnqt","LewvMaDGtS","8TxD7Z4I1v","MK07YlpF6W","zqH0WhSSvQ","faHirPOUYS",
-"7lUXZMojnP","LbRTH0h1b1","pAhR1RmDcr","OxWIHGXdoH","DLhzMTwano","FcWrWOUYuF","okgRiS77LH","3weIFMkgy8","tjQxs45cIH","iB08lWPmlx",
-"Vprf2NAFuw","lCMxy5drc6","x3LDeLbRTH","MezSWKsjRK","HRxd8iqv4k","8xEKzLbRTH","suY4xoQ87r","Gv3FqS2Dfu","zQt6QWMiS3","he9IAdpe1v",
-"KsjRKuupzk","RxrsmdmoS7","BFkb8MaJQs","8hJdt2ZHdk","Oz8yZlm0pD","fcJOypT8wu","iqv4khYBCK","sqVrf2Nslm","9GXkXQworu","24ARF5iGN5",
-"Yh1hFcL0aE","CNHmvh1zcH","CIShG4W0Tl","AIYUuO3iyQ","fcJOybrhlQ","qaofNyToGW","RzaZA6q6L9","CqqaDpiJSk","CNHmvRpBQm","RsQUqOUqFM",
-"0PktIFnPFB","HlUbF2ZHdk","OUqFMpWiOs","NhXdu8RCUA","euZA5MojnP","Pb1pa5Namm","QYxC0S2Dfu","kB5nPyluBx","16lHczQt6Q","fFDrJzqH0W",
-"l83UdEOE1o","RsQUqHP433","DQimpJIqXi","RxrsmzmLYD","CqqaDIBe8k","TXQ0Z5nmWv","FLsphRpBQm","580YDjzUqR","0MR5XkZANm","MmKGJYf2Ec",
-"uoStwQChxs","9iGoTCp3mZ","cL0aEL7cGc","5Drn0bZLvS","LewvMCxVEf","Chuy3F6PT2","uN6r3tvdkD","F6PT27fKYU","2ZHdkNcICA","xciqpU3yw5",
-"gf8rIIn3NS","55rfB5iGN5","jiVBP16lHc","O3iyQKr8ys","3weIFfLNg8","9y4lwMm8si","s7Mxkhe9IA","gf8rIMojnP","WaWsv5Mg9r","qaofNDG4sT",
-"W3VFHIKxdL","D6rByv1Hln","FcWrWgtCA5","5ZaEzDQimp","hUTw7OHaBz","NOHszlH1kt","5VZjSIKxdL","n8pJ9FLsph","JIqXidjsrv","fcJOyD6rBy",
-"fmIK1Mm8si","8FmFHhUTw7","iKqhrJJs5m","Ta8f6cShY2","tjQxsW7cTs","8xEKzfcJOy","No0QbuN6r3","bZLvSI7p2a","GWqqXSWfou","taOXKZ4I1v",
-"5ZaEzuZPqg","CK5W7s93Ml","WMiS3No0Qb","tlILtCfgr3","MmKGJQChxs","lH1kt7X3uy","FnPFB2ZHdk","MojnPpWiOs","PYBf4zQt6Q","M3zXLWaim6",
-"WreyPQClRL","lkMUAfmIK1","64s8NWaWsv","Z4I1vvkCHH","5IhmGuupzk","LDk6fUlU3M","zbIYY9GXkX","ulk41KZamH","YjB9tZ4I1v","piJSkiwzGk",
-"0BmCyWMiS3","5nmWvcmXIX","7fKYUMaJQs","7ku1pThjNn","lpF6W1j5L8","yvOMIXflUq","Cp3mZFwEJz","s4786Ss0Zu","2hEEUTwano","24ARFJ2mQi",
-"HlUbFOUYuF","M6qcGsx5Gl","nFqiki3pyd","fqypy618Di","Chuy3lXFOB","cShY2580YD","yEfy9s4786","3otm6xciqp","AmdQdWreyP","ZJTXH1LB1L",
-"DG4sTaL6AJ","S2DfuQworu","7Ow5CUmaEv","t59lRydG8U","FGzgpB3qem","IKxdLCxVEf","fqypyh1zcH","BbwgAU3yw5","ZUnqtVIlwP","ulk41gtCA5",
-"uQIczNhXdu","XyPZNFjHXR","oQ87roVQp6","DQimpi3pyd","blLA98FmFH","3otm6AmdQd","JJs5mlj07Q","CdyBVCdyBV","9eoRcblLA9","FVMxoGXdoH",
-"ZuDtDiKqhr","Chuy3AIYUu","Oz8yZJIqXi","07n1cn1pmO","S2DfuuQIcz","QssNCv1Hln","pmeCdQChxs","fcJOyaFFss","Ta8f6Chuy3","4W0TlaFFss",
-"SbRYyv8yFN","zmLYDh1zcH","n8pJ9fFDrJ","rhl0JP6bcg","0Wr5yjzUqR","pAhR1euZA5","cShY2zbIYY","mz8gx0YAGH","o8Uyd0MR5X","Yf2Eck85Ae",
-"9XyT9xciqp","Cp3mZy94nw","K20wKM6qcG","pT8wutjQxs","m4bxU45cIH","v1HlnBbwgA","Mkgy80BmCy","v2eC3o8Uyd","RmDcrFxX9q","xciqp7hyVv",
-"i3pydW3VFH","WreyP29QAz","MmKGJPYBf4","zz4ZUCxVEf","StlDJRmDcr","zFgtBYh1hF","FFDuiCfgr3","FVMxoQworu","OUqFMiwzGk","3otm6JXljW",
-"suY4xZuDtD","y94nwgdQsS","IRh485drc6","dmoS7QYxC0","vkCHHuoStw","KZamHNOHsz","IKxdL8xEKz","I7p2aGXdoH","KZamHIn3NS","QChxslH1kt",
-"KZamHJJs5m","16lHcMK07Y","y94nwJkzUn","F6PT2W3VFH","he9IAfqypy","uN6r3cQOnv","FcWrWjzUqR","CdyBVi7WMQ","jiVBPvkCHH","5NammuPX7G",
-"6q6L9Fhtgl","JIqXiuLtKs","d85a9b29RJ","1j5L8S2Dfu","jtn0XM6qcG","QChxsMmsIo","uZPqgs4786","LbRTHm4bxU","BpYhVzY1GY","KASQ8wDajX",
-"5ZaEzazIWp","uupzkx3LDe","xciqpBpYhV","AkKTkPYBf4","uJScX3otm6","8xEKzFPfSE","pT8wu8cVD3","WmadASWfou","brhlQ5VZjS","4dEz6tl72W",
-"QClRLCNHmv","qQxHPjeskS","Cp3mZ48cHL","AXpwEiwzGk","LDk6fSjskQ","FGzgp5drc6","NAFuw2Yz7E","lm0pDZv7z0","pv0i7d85a9","Ta8f6lm0pD",
-"DG4sThYBCK","O3iyQ1j5L8","5Namm55rfB","TCgPp8RCUA","WreyPtlILt","xciqp5ZaEz","AgJHQh1zcH","UmaEv7X3uy","t98iW45cIH","4dEz6UlU3M",
-"zY1GYhi5X7","gtCA5UmaEv","nlaByZuDtD","lsQGok85Ae","kB5nP3otm6","GXdoHcL0aE","Vprf2WaWsv","AkKTkKr8ys","PYBf4kB5nP","ru4UGNAFuw",
-"AIYUuzmLYD","jSjS3DLhzM","xciqpReKEW","TXQ0ZFcWrW","ZuDtDOxWIH","lCMxy8FmFH","dmoS7No0Qb","J2mQi7Ow5C","iKqhrbgJAz","zqH0WTCgPp",
-"kB5nPhYBCK","Cfgr3Pb1pa","e6e4zC2Irc","Waim6BFkb8","n8pJ9faHir","he9IAHfyNQ","SWfouFxX9q","2Yz7EB3qem","tvdkDxciqp","WDVWJuZPqg",
-"Rxrsmt98iW","FxX9qiwzGk","8hJdthE1Ql","Twanouupzk","Cfgr3t98iW","8hJdtpWiOs","HfyNQIBe8k","FVMxo07n1c","suY4xlCMxy","W3VFHAgJHQ",
-"jeskSxXTI4","fcJOyiKqhr","SbRYyHRxd8","2hEEUQbxXc","ogLgcYOfrY","euZA5QnJ1S","xciqpblLA9","LbRTHYjB9t","dmoS7gdQsS","LbRTHcL0aE",
-"S2DfubrhlQ","Chuy36q6L9","pT8wuBbwgA","KZamH8xEKz","2DREsulk41","aFFss8xEKz","s4786CNHmv","vkCHHcL0aE","EoToPLbRTH","ix74rIRh48",
-"S2DfulweGy","guMb89rlg9","n1pmOHRxd8","2ZHdkQbxXc","WmadAOxWIH","64s8NlXFOB","S2DfuChuy3","2NslmtaOXK","aFFss5Namm","h1zcHy94nw",
-"FGzgpWDVWJ","dQ586jzUqR","tjQxsVerEA","FnPFBgIYvE","qaofN24ARF","lCMxyNo0Qb","MGlTFb29RJ","n8pJ99XyT9","FGzgpbgJAz","pWiOsnnP8o",
-"CdyBV0h1b1","pmeCdAmdQd","IBe8kZJTXH","5ZaEzRzaZA","0YAGHfFDrJ","RBhp0s7Mxk","qUJMdo8Uyd","5nmWvksJby","6q6L9x3LDe","fmIK1pvgjS",
-"hSSvQi7WMQ","fmIK1IKxdL","lXFOBkZANm","Z4I1v9iGoT","cL0aEaDGtS","HP433VLTy6","iKqhraFFss","Ss0ZupiJSk","tAOsrReKEW","sqVrfMK07Y",
-"KsjRK2hEEU","zz4ZUlH1kt","iB08liKqhr","No0QbhE1Ql","n8pJ9ru4UG","7Ow5CoQ87r","dpe1vPOUYS","k85AebrhlQ","fFDrJBpYhV","sqVrflH1kt",
-"lsQGoK4GS8","vLsmSECMvU","MezSWQworu","zmLYDKr8ys","LbRTHksJby","RmDcrWPmlx","0YAGHkB5nP","d7vjMGSQwj","FNYIMRBhp0","RxrsmQ6Lix",
-"MmsIoSbRYy","tl72WSmGzv","rz7UtD6rBy","MaJQs24ARF","0Wr5yogLgc","SjskQ0Kyfs","No0QbTwano","Mm8siCK5W7","0MR5XJ2mQi","4dEz65drc6",
-"iqv4kjS1aj","0h1b1ReKEW","X6PinnFqik","n1pmOZuDtD","l83UdFwEJz","RzaZA55rfB","OxWIHBFkb8","lweGyfLNg8","YOfrYlm0pD","J2mQihUTw7",
-"Oz8yZyToGW","uN6r3L7cGc","5VZjS0Kyfs","FxX9qNOHsz","FPfSE7hyVv","No0Qb3otm6","ksJbymz8gx","yToGWuLtKs","5Drn0F6PT2","2ZHdkFxX9q",
-"mX2GEAmdQd","2Yz7EFwEJz","Cfgr3UlU3M","k85AeZzJHW","HlUbFn1pmO","BpYhVn1pmO","0MR5XtaOXK","QWxoT6q6L9","faHiryEfy9","blLA9CdyBV",
-"8xEKzMezSW","0MR5XFGzgp","Q6hMClViBv","tl72WU3yw5","MGlTFVerEA","0PktIIBe8k","Cfgr3W7cTs","45cIHiKqhr","pvgjSatef2","16lHcDG4sT",
-"xciqpqQxHP","BFkb8blLA9","DcpWByEfy9","pFrrluPX7G","x3LDeU3yw5","29QAzjSjS3","lpF6WMmKGJ","VNCPdSmGzv","8RCUA2DREs","DcpWBRpBQm",
-"5ZaEzXyPZN","ksJbygtCA5","xXTI4prNT6","JKWYRZzJHW","6AFT0WaWsv","OUYuFe6e4z","QssNCIBe8k","Ta8f6n8pJ9","J2mQiJKWYR","GSQwjs7Mxk",
-"KASQ8MojnP","s7MxkeuZA5","RsQUqjfREu","4W0Tl1LB1L","Qworu5Drn0","L7cGcnnP8o","YOfrYx3LDe","BFkb8s93Ml","m4bxUnnP8o","cShY2kZANm",
-"lpF6WEOE1o","lj07QOz8yZ","ReKEWt59lR","JXljWgdQsS","zFgtByvOMI","9rlg9UlU3M","v2eC3Mkgy8","CdyBVMGlTF","Zv7z0AOgEe","iwzGkgIYvE",
-"RACujaL6AJ","OxWIHOz8yZ","NOHszWmadA","iB08lgf8rI","pmeCdlViBv","CNHmvlkMUA","s93MlWPmlx","yofH3NhXdu","vLsmSZzJHW","x3LDerKDLJ",
-"fLNg8mz8gx","i7WMQlXFOB","rKDLJSjskQ","Dz1R3jzUqR","AkKTkIBe8k","fcwDavkCHH","5NammbgJAz","euZA5i3pyd","s7MxkhE1Ql","MojnPZuDtD",
-"YjB9tpv0i7","fcwDafqypy","azIWp6q6L9","pAhR1tvdkD","WaWsvRxrsm","RxrsmMGlTF","gjUTupAhR1","prNT6ZzJHW","Mkgy8aez9y","NcICAKZamH",
-"YjB9tC2Irc","VBjhzRsQUq","uPX7GKASQ8","pT8wuYf2Ec","AkKTkJkzUn","fFDrJjiVBP","HRxd8cL0aE","a00b5FFDui","cShY2h1zcH","xXTI47hyVv",
-"VLTy6QClRL","brhlQblLA9","s4786KASQ8","PYBf4zmLYD","5Namm0ao3l","iKqhrcmXIX","m4bxUblLA9","y94nw8hJdt","guMb8oQ87r","3weIFqaofN",
-"kB5nPY1mC0","cL0aEn1pmO","9GXkXAmdQd","hE1Ql3weIF","hUTw75VZjS","o8UydTa8f6","hUTw7he9IA","Q6hMCguMb8","2TRI7QnJ1S","8TxD7ydG8U",
-"zqH0W9y4lw","Z4I1vRkQke","MaJQs9iGoT","S2DfuwDajX","Nxx9Vv2eC3","Cp3mZI7p2a","atef20YAGH","gIYvE5Namm","8FmFH580YD","tjQxsK4GS8",
-"dQ586v2eC3","cL0aEy94nw","wiHrZOxWIH","OUYuFfaHir","rhl0JuQIcz","IKxdLK20wK","1v5hH2ZHdk","i3pydY1mC0","HzZT8JJs5m","S2Dfuv8yFN",
-"48cHLQYxC0","xXTI4zz4ZU","5ZaEzi3pyd","Y1mC02TRI7","C2IrcJKWYR","bZLvSzQt6Q","Yh1hFWaWsv","WmadAAXpwE","v8yFNM3zXL","5iGN5oGu6x",
-"WreyPIKxdL","azIWpChuy3","WaWsv24ARF","t59lRatef2","FwEJzguMb8","NOHszBGaQY","8hJdtXflUq","FVMxoYOfrY","D6rByuN6r3","ksJbydjsrv",
-"mX2GEBCxeC","jS1ajsx5Gl","jeskSjfREu","DcpWB4W0Tl","zFgtB9eoRc","EdBKcnnP8o","tvdkDqaofN","Q6hMCBbwgA","hSSvQMGlTF","mX2GEGXdoH",
-"L7cGca00b5","VBjhzpWiOs","RACujYOfrY","nFqike6e4z","lViBv2ZHdk","ZuDtDFLsph","atef2MmKGJ","8U2nUAOgEe","IRh48fcwDa","s93MlHfyNQ",
-"lH1ktcmXIX","2Yz7E6q6L9","jzUqR48cHL","s7Mxk0PktI","RzaZAPYBf4","rhl0JjiVBP","U3yw5jzUqR","X6PinMmKGJ","1v5hHulk41","Mkgy88U2nU",
-"dpe1vD6rBy","ciuWzqUJMd","VerEAlkMUA","guMb8580YD","jtn0XqUJMd","Chuy35ZaEz","fcJOyazIWp","uJScXS2Dfu","L7cGc2Nslm","jSjS3uJScX",
-"TCgPpLbRTH","sqVrfZhwG1","zmLYDjSjS3","GrDg7v8yFN","Ul4a1o8Uyd","Nxx9VRACuj","gIYvE7X3uy","s93MlYw2oU","7fKYUx3LDe","qaofNnlaBy",
-"IjTwPk85Ae","FxX9qZ4I1v","0PktIaL6AJ","SbRYyKASQ8","JXljWguMb8","WPmlxMmKGJ","ZUnqtRmDcr","FNYIMyofH3","hE1QlnnP8o","ZJTXHxXTI4",
-"In3NS64s8N","ru4UGYh1hF","NOHszuAWyp","lkMUAXflUq","uoStwsx5Gl","45cIHl83Ud","uLtKss7Mxk","L7cGcfFDrJ","Kr8ysqUJMd","EoToPd85a9",
-"580YDVBjhz","EoToPMezSW","29QAz6q6L9","QWxoTeuZA5","v8yFNzY1GY","tlILtjzUqR","dpe1vfaHir","uN6r3QssNC","HlUbFvOqCE","QClRLFPfSE",
-"FFDuiVIlwP","HRxd8IRh48","lXFOBOxWIH","uupzkcmXIX","Uvlv4tl72W","guMb8C2Irc","4W0Tlk85Ae","e6e4zxciqp","Yw2oUKr8ys","gIYvE7Ow5C",
-"guMb8WMiS3","pAhR1pT8wu","3otm6fLNg8","TCgPpHzZT8","sqVrfPOUYS","lXFOBsx5Gl","FxX9q5Drn0","RpBQmgjUTu","EoToPTXQ0Z","aez9y48cHL",
-"RmDcrdpe1v","B3qemaL6AJ","pmeCdWaim6","nlaByuvf7A","7fsYMblLA9","XflUqYw2oU","lCMxyZv7z0","7fKYUgf8rI","lViBvkZANm","fqypy64s8N",
-"3otm6MezSW","ru4UGdjsrv","07n1cNo0Qb","Z4I1vM6qcG","OUYuFx3LDe","C2IrcX6Pin","P6bcgECMvU","ReKEWOUqFM","bgJAz580YD","7fKYUFFDui",
-"UmaEvY1mC0","Y1mC0he9IA","Qworurhl0J","IjTwPNcICA","azIWpMmKGJ","k85AeyluBx","KASQ85IhmG","U3yw5dmoS7","ix74rtlILt","4QMc9JKWYR",
-"RkQkedmoS7","MaJQsiwzGk","FnPFBhUTw7","MojnPwDajX","gdQsSBGaQY","Uvlv4JIqXi","Q6LixFnPFB","0h1b11v5hH","HP43345cIH","kZANm8RCUA",
-"fmIK1Waim6","PYBf4vkCHH","HRxd8sqVrf","he9IAguMb8","Gv3FquTacx","Waim6MezSW","EdBKciB08l","MmKGJCxVEf","ECMvUpAhR1","pFrrlIn3NS",
-"zHF1qMmsIo","zHF1qAIYUu","16lHcuJScX","L7cGcPYBf4","RmDcrwDajX","5ZaEznlaBy","NhXduYh1hF","CK5W7WPmlx","KASQ8Yh1hF","FnPFBReKEW",
-"WDVWJfmIK1","4dEz6ulk41","piJSktlILt","CIShGd85a9","No0Qb0YAGH","gdQsSM6qcG","taOXKGXdoH","FjHXRNhXdu","Ss0Zud85a9","jzUqRi3pyd",
-"8hJdtKsjRK","QYxC0GSQwj","aL6AJhe9IA","2hEEUCIShG","Q6hMCRpBQm","KsjRKnnP8o","YOfrYvLsmS","uLtKs0ao3l","LewvMVjCZq","5iGN5XyPZN",
-"soy9t7Ow5C","he9IAFNYIM","QssNCRmDcr","QssNCWreyP","v8yFNIBe8k","i7WMQuTacx","FhtglW7cTs","ydG8UAOgEe","S77LH2Nslm","7fKYUsuY4x",
-"D6rByAkKTk","jeskS8RCUA","v1Hln0BmCy","uJScXOxWIH","OxWIH5VZjS","MmKGJTa8f6","HlUbF9eoRc","KASQ8Ss0Zu","7Ow5Clj07Q","brhlQyEfy9",
-"qaofNuvf7A","HzZT8d7vjM","tlILtgdQsS","FGzgpVIlwP","MGlTFix74r","m4bxUjeskS","m4bxUWaim6","pv0i7zz4ZU","SjskQzHF1q","WreyPlsQGo",
-"MezSW0h1b1","14FLRQworu","C2IrcQChxs","nFqikm4bxU","IKxdLFFDui","HP4335VZjS","C2IrclViBv","Cp3mZ9XyT9","hE1QlCIShG","VNCPdlsQGo",
-"1LB1LxReec","8xEKzRpBQm","580YDJIqXi","Waim6EOE1o","qUJMdi7WMQ","RkQkeDQimp","Uvlv4EOE1o","GrDg7EOE1o","piJSkGv3Fq","Cp3mZKr8ys",
-"Cfgr3tjQxs","yToGWKASQ8","TXQ0ZCIShG","W3VFHBCxeC","BpYhV8FmFH","Cp3mZtlILt","Mkgy8G1RhS","NOHszMaJQs","2TRI7VerEA","6q6L97ku1p",
-"yofH3Vprf2","WMiS3SmGzv","2DREsVNCPd","zz4ZUWaWsv","VBjhzSbRYy","hSSvQksJby","uN6r3uTacx","1j5L8LewvM","Rxrsm9XyT9","QWxoTTa8f6",
-"BGaQYfcwDa","lm0pD55rfB","RxrsmCp3mZ","zmLYD580YD","Uvlv4BCxeC","LbRTHe6e4z","8U2nUzz4ZU","5ZaEz45cIH","9rlg92DREs","CdyBV0Kyfs",
-"Ul4a1oQ87r","RzaZAVjCZq","MojnPGXdoH","e6e4z8hJdt","No0QbJKWYR","2NslmNAFuw","rKDLJn1pmO","EoToPGXdoH","s7Mxk16lHc","a00b5lkMUA",
-"StlDJfcJOy","5ZaEzo8Uyd","zz4ZUSbRYy","IjTwPWmadA","o8UydOUYuF","ydG8U5VZjS","4QMc98TxD7","QClRL7lUXZ","RzaZAdjsrv","KsjRK0MR5X",
-"NAFuw8xEKz","QYxC0pv0i7","X6PinWaim6","kB5nPn8pJ9","POUYSOHaBz","zFgtBCxVEf","IjTwPaDGtS","IRh48Cp3mZ","jzUqRLDk6f","ogLgcFFDui",
-"2DREssuY4x","FPfSElj07Q","lCMxy7X3uy","Z4I1vnFqik","2DREsuPX7G","NhXdutlILt","suY4x7fKYU","MGlTF16lHc","1v5hHMezSW","iKqhrCK5W7",
-"0Wr5yJJs5m","LewvMYf2Ec","GWqqXEOE1o","Uvlv4lsQGo","VBjhzhUTw7","Kr8ysCNHmv","8cVD3mX2GE","YOfrYuoStw","sqVrfi7WMQ","lXFOBuJScX",
-"FPfSECp3mZ","QWxoTs4786","8hJdtgIYvE","7hyVvk85Ae","7hyVv3weIF","iB08lgIYvE","BbwgAt98iW","nlaByTa8f6","QbxXc2DREs","S2DfuXflUq",
-"9y4lwCdyBV","GXdoHM6qcG","Yf2EcG1RhS","m4bxU580YD","0ao3lHP433","v8yFNVBjhz","FxX9q7fsYM","pmeCdtvdkD","7fKYU2ZHdk","lj07QcmXIX",
-"2TRI75drc6","zqH0WMojnP","n8pJ9K4GS8","h1zcHAkKTk","HRxd88FmFH","Ul4a1YOfrY","uvf7AqaofN","S2Dful83Ud","i3pydZhwG1","BbwgAdjsrv",
-"29QAz0ao3l","brhlQDcpWB","hSSvQGv3Fq","suY4xyEfy9","lsQGoStlDJ","ulk41zqH0W","Pb1pabrhlQ","s93MlbgJAz","AIYUu0MR5X","n8pJ9oQ87r",
-"CNHmvYh1hF","e6e4zjfREu","7fKYUs93Ml","HlUbFAIYUu","v1Hln5Namm","Rxrsmy94nw","zQt6QZhwG1","rhl0JjSjS3","64s8NSs0Zu","580YDM6qcG",
-"RpBQmlm0pD","ksJbyWaWsv","7Ow5C9GXkX","xReecPYBf4","618DilH1kt","uAWypBpYhV","FFDuiMezSW","G1RhSMmKGJ","vLsmSa00b5","FLsph8FmFH",
-"OUYuFQbxXc","atef2Uvlv4","VBjhzAgJHQ","t98iWoQ87r","FwEJz0Wr5y","ydG8UcShY2","gdQsS4dEz6","55rfBzQt6Q","atef224ARF","U3yw54QMc9",
-"FLsphtlILt","ix74rCxVEf","ZhwG1I7p2a","tl72WTwano","lsQGoEoToP","D6rByqaofN","J2mQi9y4lw","iwzGkksJby","zz4ZU2ZHdk","Q6hMCuTacx",
-"brhlQfFDrJ","0BmCyF6PT2","soy9tnnP8o","tvdkDCqqaD","sx5GlOUqFM","ThjNnAgJHQ","HP4332DREs","KZamHRzaZA","2ZHdkuQIcz","euZA5PYBf4",
-"VBjhz48cHL","WreyPFjHXR","lsQGoe6e4z","AXpwECxVEf","D6rBykZANm","yvOMIUl4a1","pFrrlfqypy","ni2v1RkQke","n1pmOQworu","uAWypgf8rI",
-"Pb1paYjB9t","7fsYMHlUbF","RkQkeKZamH","suY4x2DREs","UlU3MZ4I1v","k85AetaOXK","he9IARxrsm","s7Mxkiqv4k","FPfSEaDGtS","In3NSuAWyp",
-"HP433EOE1o","yluBxtAOsr","XyPZNsx5Gl","CNHmvYf2Ec","TXQ0Zhi5X7","KZamHaez9y","M3zXL8FmFH","SmGzvru4UG","uPX7GzY1GY","euZA5ogLgc",
-"ThjNnThjNn","pFrrl8FmFH","5NammHRxd8","nFqik4dEz6","8FmFHpT8wu","G1RhSokgRi","euZA5nlaBy","jiVBPhUTw7","s7MxkzQt6Q","MmsIoGv3Fq",
-"lkMUAJIqXi","FcWrWdmoS7","RzaZAOxWIH","CIShGcL0aE","Uvlv4QWxoT","ni2v1guMb8","VerEASmGzv","d7vjMSWfou","HfyNQSmGzv","hUTw72DREs",
-"zY1GYGrDg7","zQt6Q7X3uy","vkCHHru4UG","RzaZAUlU3M","aDGtSWaim6","LDk6f4dEz6","tl72WTa8f6","i7WMQSjskQ","5iGN5cShY2","64s8NuTacx",
-"FGzgpS77LH","ru4UGJRJQB","O3iyQuupzk","ECMvUiqv4k","5IhmGfLNg8","iKqhr48cHL","8hJdtQbxXc","RmDcrFcWrW","W3VFH8cVD3","NAFuwjiVBP",
-"Q6hMCPOUYS","7ku1pMm8si","ogLgcXflUq","sqVrfv8yFN","TXQ0ZM6qcG","HlUbFLDk6f","2hEEUKsjRK","618Di0Wr5y","aFFsse6e4z","7lUXZI7p2a",
-"jiVBPNAFuw","ulk41WreyP","lXFOBaez9y","sx5Gl5ZaEz","DLhzM45cIH","3weIF2DREs","okgRiDz1R3","jzUqRPOUYS","B3qemNOHsz","sqVrfEOE1o",
-"ZuDtDru4UG","Cp3mZZhwG1","BGaQY0YAGH","xReecxReec","ZuDtDo8Uyd","Q6hMCokgRi","F6PT2X6Pin","tl72WQworu","StlDJ2TRI7","dmoS7lXFOB",
-"StlDJcShY2","Yh1hFQYxC0","RmDcrDcpWB","9y4lwChuy3","LDk6fAOgEe","QChxsNcICA","Z4I1vMK07Y","jS1ajrz7Ut","lCMxytl72W","CNHmvW3VFH",
-"7Ow5CgtCA5","k85AeGrDg7","OxWIHJkzUn","4QMc9Rxrsm","Y1mC0lm0pD","fmIK1IRh48","b29RJ5IhmG","tjQxsfqypy","7hyVvHlUbF","FwEJzVjCZq",
-"pT8wujiVBP","JkzUnlH1kt","fcwDaRACuj","SbRYyDG4sT","y94nwFPfSE","IBe8kyvOMI","xXTI4soy9t","LbRTHYw2oU","JkzUnSs0Zu","uvf7AQ6hMC",
-"2DREs0MR5X","Pb1pa8xEKz","CK5W7JRJQB","29QAz0MR5X","EoToPO3iyQ","U3yw524ARF","fFDrJG1RhS","ogLgcuPX7G","lXFOBprNT6","FxX9qogLgc",
-"EoToPFjHXR","iqv4kLewvM","Q6LixlweGy","K4GS8IRh48","XyPZNVBjhz","5VZjSi7WMQ","6AFT0QClRL","NhXduVerEA","QbxXcM3zXL","s4786aDGtS",
-"lH1ktKASQ8","FLsphBbwgA","ECMvURsQUq","dQ586zY1GY","uN6r3C2Irc","jeskSJkzUn","pAhR13otm6","Gv3FqjSjS3","6q6L9v2eC3","oQ87rKASQ8",
-"RzaZAokgRi","WDVWJIn3NS","rKDLJjSjS3","QbxXcZzJHW","mz8gx29QAz","d7vjMyvOMI","qUJMddmoS7","SbRYy4QMc9","zY1GYQChxs","aez9ygdQsS",
-"hUTw7zz4ZU","VBjhzs4786","aFFssaL6AJ","MGlTF5Mg9r","cmXIXMGlTF","6AFT0580YD","fFDrJfmIK1","24ARFdpe1v","Uvlv4uZPqg","Yh1hFs7Mxk",
-"xciqplm0pD","AgJHQnnP8o","5VZjSThjNn","Ta8f6CqqaD","b29RJoVQp6","uAWypFNYIM","9GXkXStlDJ","JIqXiFLsph","3otm6DG4sT","VLTy6v8yFN",
-"NAFuwuQIcz","EoToPWaWsv","fLNg8D6rBy","LbRTHOz8yZ","BbwgAlViBv","d85a9lpF6W","Pb1palsQGo","4W0Tlt59lR","VLTy60Wr5y","KASQ8DcpWB",
-"aL6AJeuZA5","0BmCyaFFss","5nmWvMojnP","y94nw0ao3l","M3zXL3weIF","jfREucShY2","Zv7z0BbwgA","JKWYRulk41","W7cTsuJScX","hi5X70ao3l",
-"tl72WQWxoT","ThjNnoGu6x","5IhmGi3pyd","pmeCdVprf2","t59lRuTacx","zY1GYqQxHP","l83UdZv7z0","WDVWJIKxdL","cQOnv9rlg9","OUqFMm4bxU",
-"4dEz66AFT0","HRxd85Namm","h1zcH55rfB","fmIK1fcJOy","jS1aj5Namm","KZamHv2eC3","iqv4kb29RJ","CNHmvBGaQY","SbRYySWfou","zbIYYD6rBy",
-"0KyfsW3VFH","K20wKMGlTF","JKWYR64s8N","DQimpwDajX","qUJMdgIYvE","Ul4a1IRh48","lH1ktFFDui","aL6AJdpe1v","M3zXLUlU3M","tAOsruupzk",
-"9iGoTaFFss","HzZT8lH1kt","KASQ8lViBv","5IhmGJkzUn","s93Ml2ZHdk","1v5hH9y4lw","EoToPfmIK1","16lHcRACuj","cShY2nFqik","Rxrsm1j5L8",
-"i7WMQ6q6L9","djsrvWaWsv","M3zXL8cVD3","RmDcrlsQGo","IjTwPlm0pD","zHF1qs7Mxk","sqVrfTCgPp","0Wr5yAgJHQ","KASQ8ix74r","ydG8U618Di",
-"CIShGa00b5","FNYIMmX2GE","m4bxUIBe8k","Gv3FqFhtgl","HfyNQyEfy9","J2mQi580YD","tvdkDpWiOs","NOHszzFgtB","ni2v1BbwgA","Pb1paO3iyQ",
-"n8pJ9FwEJz","OxWIHUlU3M","PYBf4ZzJHW","ni2v1JKWYR","MezSW5ZaEz","1v5hHtuDyS","StlDJyToGW","uN6r3jtn0X","Q6LixqUJMd","zqH0WCfgr3",
-"t59lRlj07Q","Q6hMC8xEKz","dhSuHhUTw7","nnP8ojeskS","t98iWEoToP","O3iyQpT8wu","pAhR1gIYvE","64s8NPOUYS","JXljWCfgr3","In3NSguMb8",
-"suY4xWMiS3","MGlTF6q6L9","hi5X7uvf7A","Yw2oUWPmlx","Z4I1vCdyBV","0MR5XNAFuw","KASQ8yvOMI","KZamH4W0Tl","16lHcuupzk","FGzgpLewvM",
-"pWiOshe9IA","dhSuHx3LDe","U3yw5rKDLJ","pmeCdMGlTF","Oz8yZLbRTH","Ta8f68hJdt","MGlTFYf2Ec","uTacxQbxXc","faHir9rlg9","brhlQPYBf4",
-"9rlg9soy9t","zFgtBjtn0X","FhtglWaim6","JKWYRVIlwP","tvdkD3weIF","wiHrZ5VZjS","dhSuHjS1aj","lH1ktlpF6W","Chuy3BpYhV","soy9tpAhR1",
-"9XyT9MmsIo","kB5nPOHaBz","VjCZqZ4I1v","uupzkAgJHQ","jtn0X9eoRc","rKDLJpFrrl","Ss0ZuP6bcg","RBhp0NAFuw","hUTw7FGzgp","0BmCylweGy",
-"i3pydgIYvE","PYBf4xReec","IjTwPmX2GE","wiHrZAIYUu","x3LDeSWfou","v8yFNFcWrW","Chuy3blLA9","TXQ0ZNxx9V","BCxeCHP433","Mm8si07n1c",
-"IBe8kfmIK1","CxVEfzmLYD","Q6Lixs93Ml","ydG8UcL0aE","AgJHQOUqFM","CNHmvkZANm","7fsYMt98iW","QnJ1SgdQsS","lj07QZuDtD","JKWYRv1Hln",
-"uQIczP6bcg","yofH3blLA9","TwanozqH0W","ciuWzAXpwE","oGu6x3weIF","AXpwErz7Ut","RpBQmjiVBP","9eoRctl72W","sx5GlYOfrY","suY4xsqVrf",
-"oQ87rJ2mQi","Ss0ZuM6qcG","5IhmGQClRL","prNT6hi5X7","JXljWFjHXR","Mm8sijSjS3","I7p2atvdkD","pWiOsyofH3","blLA90PktI","RzaZADLhzM",
-"JJs5mzmLYD","BFkb8CK5W7","DcpWBFjHXR","jeskSqQxHP","xXTI4CdyBV","NAFuwtjQxs","yvOMITwano","OUqFMeuZA5","618DibrhlQ","QChxsQbxXc",
-"kZANmYjB9t","CdyBVgtCA5","CqqaD5Namm","jiVBPZ4I1v","5VZjS9iGoT","OUqFMpvgjS","YjB9tnlaBy","aFFssjS1aj","ZuDtDrKDLJ","QChxsSs0Zu",
-"WaWsvD6rBy","VNCPdt59lR","ThjNnJIqXi","RACujv2eC3","NhXdurKDLJ","yToGWl83Ud","yToGWWDVWJ","3weIF1j5L8","zz4ZU7X3uy","IRh48taOXK",
-"Z4I1v8TxD7","Yf2EcCK5W7","0h1b1ciuWz","EoToPReKEW","5VZjSQChxs","WPmlx8cVD3","45cIH8cVD3","OUYuF0PktI","tAOsrYw2oU","8RCUAnnP8o",
-"7hyVvjtn0X","pFrrlBFkb8","5Drn0bgJAz","Ta8f6pvgjS","U3yw50Wr5y","Z4I1vo8Uyd","8hJdtzFgtB","8hJdtTwano","xciqpChuy3","FxX9q9eoRc",
-"S77LH8FmFH","fmIK1lkMUA","3otm6uvf7A","yluBxuupzk","LDk6fmX2GE","lsQGoWPmlx","K4GS8lweGy","AXpwEpmeCd","uLtKsMmsIo","tuDySQbxXc",
-"CIShG3otm6","QworupmeCd","5IhmG0ao3l","d7vjM5drc6","fqypyOUYuF","ZuDtDbgJAz","Waim6cQOnv","QChxsRBhp0","RpBQmqQxHP","WaWsvfcJOy",
-"UlU3MKsjRK","euZA5FjHXR","8RCUAO3iyQ","1LB1LuZPqg","s93Ml7hyVv","LDk6fHlUbF","pmeCdMaJQs","JIqXieuZA5","CNHmvSs0Zu","qUJMdYf2Ec",
-"RsQUqO3iyQ","pFrrlcShY2","okgRifcwDa","ulk41BpYhV","lpF6Wi7WMQ","lm0pDuN6r3","nlaByKZamH","5NammKZamH","I7p2auQIcz","lpF6WjSjS3",
-"2NslmMojnP","bgJAzZhwG1","yvOMIThjNn","FcWrWv1Hln","XflUqv8yFN","Waim6M3zXL","aL6AJFhtgl","2TRI7VjCZq","cmXIXVNCPd","BpYhVv8yFN",
-"rhl0Ji7WMQ","HzZT8JRJQB","FPfSECK5W7","PYBf4WaWsv","b29RJCdyBV","brhlQM6qcG","DcpWBGSQwj","s7Mxk3weIF","FVMxoJ2mQi","mX2GESjskQ",
-"pmeCd8U2nU","uLtKsiKqhr","Q6hMC7lUXZ","Nxx9V5nmWv","Yh1hFru4UG","a00b5oGu6x","DcpWBDG4sT","7hyVvYw2oU","FcWrWJkzUn","hSSvQ2Nslm",
-"JJs5mK4GS8","ydG8UlH1kt","tAOsrCK5W7","W3VFHuQIcz","rz7UtnnP8o","16lHcMGlTF","ECMvUJIqXi","2hEEUlViBv","hYBCKRBhp0","prNT607n1c",
-"Z4I1vTXQ0Z","dmoS7FVMxo","soy9tdmoS7","SWfouAmdQd","1j5L8FVMxo","uTacxguMb8","Mkgy8AmdQd","K4GS80ao3l","WDVWJxReec","4W0TlYf2Ec",
-"gdQsSs4786","hE1QlqaofN","jeskSNOHsz","vOqCEXyPZN","TCgPpAIYUu","QClRLh1zcH","uAWypO3iyQ","WmadAQChxs","GWqqXoGu6x","lsQGo7fKYU",
-"MojnPcmXIX","TXQ0Zi7WMQ","4dEz6LbRTH","ThjNnZuDtD","NOHszTXQ0Z","lsQGoVLTy6","IRh48IRh48","MK07YaFFss","azIWpJIqXi","DcpWB3otm6",
-"Chuy3qaofN","i7WMQ580YD","atef2X6Pin","soy9tC2Irc","7ku1pAOgEe","gtCA5Q6Lix","W3VFH4W0Tl","1LB1LRmDcr","v1HlnjeskS","1LB1LgtCA5",
-"taOXKxXTI4","y94nwDLhzM","7hyVvPOUYS","ZzJHWjSjS3","hUTw7VerEA","HP433ZhwG1","WDVWJ8TxD7","Cp3mZ29QAz","uN6r3v2eC3","zQt6QFVMxo",
-"OHaBzZv7z0","WmadANxx9V","S2DfuI7p2a","QbxXc7fKYU","uLtKs5Mg9r","XflUqd85a9","Cp3mZCdyBV","DLhzM2TRI7","Gv3FqWreyP","he9IAv2eC3",
-"xXTI4cQOnv","aDGtSP6bcg","VIlwP7X3uy","EOE1oVprf2","Y1mC0k85Ae","5IhmGuJScX","gjUTuNAFuw","Oz8yZVerEA","7ku1pHlUbF","fLNg8CIShG",
-"ciuWzBFkb8","guMb8yvOMI","DcpWBQbxXc","lj07QW7cTs","GWqqXx3LDe","uLtKsPOUYS","Uvlv4YjB9t","Q6Lix580YD","NAFuwcShY2","pFrrl5Mg9r",
-"BGaQYWMiS3","pWiOsJRJQB","Zv7z0580YD","XflUqVIlwP","MojnP9GXkX","b29RJJ2mQi","zmLYDQssNC","cL0aED6rBy","QWxoTDG4sT","LewvMfcJOy",
-"M3zXLFcWrW","OUqFM6AFT0","FwEJzd7vjM","5iGN5he9IA","wDajXjS1aj","6AFT0d7vjM","SbRYy3weIF","8cVD3ZUnqt","C2IrcRpBQm","2TRI7GWqqX",
-"pvgjSLDk6f","nnP8otAOsr","CNHmvIn3NS","s7MxkyEfy9","d85a96AFT0","5nmWvaDGtS","QYxC0x3LDe","VBjhzlm0pD","RkQkeU3yw5","prNT6lH1kt",
-"MK07YFxX9q","07n1caFFss","O3iyQB3qem","dpe1vSs0Zu","iKqhri7WMQ","0ao3lTCgPp","K4GS8TCgPp","UmaEvgIYvE","O3iyQ7Ow5C","vkCHHDQimp",
-"ru4UGEoToP","blLA9Yf2Ec","pAhR1WaWsv","0h1b1kZANm","XyPZNgf8rI","QworufcwDa","7X3uyXflUq","hE1QlMezSW","0MR5XqaofN","lCMxyydG8U",
-"vkCHHm4bxU","lkMUAQ6Lix","D6rByi3pyd","1v5hHEoToP","GSQwjpiJSk","YjB9txciqp","nFqikYh1hF","Ta8f6cL0aE","HfyNQaDGtS","HRxd85ZaEz",
-"Vprf2i3pyd","tvdkDVIlwP","Cp3mZuTacx","LDk6fRsQUq","OxWIHhi5X7","hYBCKtvdkD","ogLgcYjB9t","lViBvlweGy","JIqXizHF1q","lViBvlViBv",
-"RmDcrSmGzv","jtn0XJKWYR","OUYuFAIYUu","FNYIMHzZT8","SjskQSs0Zu","ciuWzjtn0X","fLNg8sx5Gl","J2mQi9iGoT","FwEJzpWiOs","zmLYD0YAGH",
-"lsQGo5Namm","MezSWReKEW","ZhwG1TCgPp","ni2v114FLR","gf8rIs7Mxk","3weIFFVMxo","KZamHatef2","gjUTuOz8yZ","5ZaEzrhl0J","okgRisqVrf",
-"o8UydX6Pin","atef2W7cTs","Cp3mZRkQke","XflUqSWfou","5NammU3yw5","HfyNQWaim6","iqv4koVQp6","07n1crhl0J","pv0i7QWxoT","ZzJHWAIYUu",
-"hE1QlGXdoH","gjUTuUl4a1","MmsIoM6qcG","POUYSnnP8o","h1zcHzqH0W","t98iWEOE1o","QYxC0s4786","GSQwjoQ87r","yvOMIWPmlx","uQIczpWiOs",
-"RmDcr4QMc9","zbIYYciuWz","suY4xVIlwP","HfyNQOHaBz","In3NSoGu6x","0ao3lfaHir","MojnPuvf7A","JXljWMmKGJ","pvgjSNo0Qb","EoToP8FmFH",
-"UmaEva00b5","CK5W7a00b5","2NslmFVMxo","S2DfuLewvM","48cHLk85Ae","SmGzviwzGk","7ku1pZJTXH","jiVBPTXQ0Z","L7cGcRpBQm","CqqaDe6e4z",
-"Vprf2DLhzM","v8yFN2DREs","tlILtFPfSE","uoStwThjNn","uupzkjiVBP","i3pydDcpWB","0MR5XG1RhS","lpF6WogLgc","OUqFMJRJQB","gIYvE8FmFH",
-"qaofNHP433","GSQwj7fsYM","ksJby9iGoT","lm0pDPOUYS","HlUbFQnJ1S","brhlQJkzUn","GSQwjTa8f6","uJScXCqqaD","07n1cJKWYR","ciuWzPb1pa",
-"5VZjSuPX7G","5ZaEzMmsIo","BbwgALbRTH","gjUTuTXQ0Z","xXTI4QChxs","7X3uytjQxs","aDGtSKsjRK","C2Irc7lUXZ","580YDVNCPd","Yw2oU5nmWv",
-"RsQUq580YD","VjCZqiKqhr","sqVrfwDajX","580YDlsQGo","1j5L8ulk41","IBe8kP6bcg","oQ87rt59lR","SjskQni2v1","7fKYUOxWIH","7X3uyNcICA",
-"euZA59iGoT","AOgEefaHir","LDk6fCqqaD","QWxoTzmLYD","n1pmOgjUTu","tl72WEoToP","FNYIMFGzgp","yvOMIgdQsS","RmDcr1LB1L","ni2v15drc6",
-"prNT648cHL","SmGzv1v5hH","jS1aj2DREs","S77LHpvgjS","RpBQmReKEW","v8yFNlweGy","gjUTuQbxXc","Uvlv4VLTy6","P6bcgpiJSk","v8yFNuvf7A",
-"uZPqgS77LH","ReKEWtl72W","hE1QlRBhp0","lCMxylH1kt","uAWypHRxd8","Zv7z0b29RJ","nFqiktvdkD","5Mg9rKASQ8","Yf2EcQClRL","No0QbVBjhz",
-"GWqqXrKDLJ","nnP8oIBe8k","Ss0Zu5iGN5","l83UdRxrsm","2DREs9y4lw","KsjRKDz1R3","uLtKsqaofN","yofH3d85a9","RzaZA0h1b1","x3LDeW7cTs",
-"14FLR0h1b1","BCxeCHRxd8","lXFOBuN6r3","piJSkFPfSE","MaJQslpF6W","ni2v1TCgPp","RpBQmDG4sT","WmadA0h1b1","QbxXc5drc6","Y1mC0POUYS",
-"StlDJ3weIF","ThjNncmXIX","5ZaEzyluBx","vOqCEIn3NS","h1zcHiKqhr","Gv3FqAgJHQ","s47860ao3l","hE1Ql6q6L9","LewvMru4UG","uupzklm0pD",
-"tlILtgjUTu","G1RhSM6qcG","FFDuijzUqR","8hJdtuQIcz","PYBf4SjskQ","aez9yprNT6","dmoS7GSQwj","JIqXirz7Ut","lweGy5iGN5","CqqaDv8yFN",
-"cShY2Q6Lix","Yw2oUZhwG1","jSjS3VNCPd","pAhR1jSjS3","C2Irc9XyT9","ThjNnDLhzM","QWxoTAIYUu","sqVrfdmoS7","64s8NSjskQ","e6e4ztvdkD",
-"fLNg8OUYuF","dmoS78xEKz","MaJQsuoStw","Fhtgl9iGoT","y94nwuJScX","WaWsvDG4sT","jzUqRMm8si","NcICAJXljW","CxVEf2Nslm","qUJMd2DREs",
-"Zv7z0NhXdu","wDajXuoStw","hE1QlSWfou","i7WMQdjsrv","QYxC0e6e4z","VIlwPRzaZA","FPfSEazIWp","MojnP3otm6","iB08lXyPZN","Gv3FqQworu",
-"kB5nPVBjhz","MK07YGv3Fq","sqVrfQ6hMC","cShY2n1pmO","4QMc9qUJMd","tuDySB3qem","BpYhVJIqXi","Mkgy845cIH","uJScX0BmCy","suY4xk85Ae",
-"iKqhrpT8wu","WmadArKDLJ","X6PinStlDJ","0PktImX2GE","jfREu8TxD7","wiHrZ4QMc9","VerEAatef2","I7p2auZPqg","jS1ajtjQxs","DLhzMn1pmO",
-"RACujECMvU","HfyNQFLsph","bgJAzDcpWB","m4bxU8U2nU","HfyNQK4GS8","Mkgy848cHL","9eoRc9iGoT","l83UdDz1R3","aFFssx3LDe","9GXkXyluBx",
-"BpYhVaFFss","FjHXRvkCHH","lweGykZANm","Ul4a17lUXZ","Ta8f6Yf2Ec","xciqppmeCd","Waim6cL0aE","xciqppWiOs","4QMc9cL0aE","iKqhrlpF6W",
-"ECMvUOHaBz","BbwgAL7cGc","ZzJHWblLA9","euZA5XyPZN","FLsphJKWYR","8FmFHQssNC","fLNg8Mm8si","WMiS3h1zcH","5Mg9rW3VFH","WPmlx6q6L9",
-"MGlTFXyPZN","blLA9VBjhz","ZJTXHuPX7G","TwanoX6Pin","8TxD7ECMvU","prNT6cQOnv","blLA9XflUq","M3zXLn1pmO","B3qemQYxC0","t59lR1j5L8",
-"Uvlv40YAGH","uoStwiB08l","ksJbyv2eC3","4QMc95nmWv","x3LDeRkQke","2TRI7BGaQY","LewvM9XyT9","1LB1LMkgy8","oGu6x0BmCy","QnJ1SqQxHP",
-"64s8NNAFuw","nFqik7lUXZ","KZamHxReec","45cIHdhSuH","tjQxsoQ87r","JIqXioGu6x","kZANm7Ow5C","StlDJKZamH","uQIczCfgr3","FxX9qF6PT2",
-"M3zXLRmDcr","hE1QlX6Pin","POUYSQChxs","C2IrcLbRTH","CqqaDAIYUu","wiHrZNcICA","VjCZqZJTXH","hSSvQlsQGo","pvgjSzFgtB","5Namm1j5L8",
-"QssNCo8Uyd","ZuDtDuPX7G","Cp3mZ0PktI","EoToPxReec","9GXkXd85a9","blLA95iGN5","5nmWv7X3uy","hUTw72hEEU","vkCHHQYxC0","8hJdtiKqhr",
-"MmsIoix74r","LDk6fTCgPp","bZLvSzz4ZU","CIShGVLTy6","Ta8f6OxWIH","F6PT2vLsmS","he9IAD6rBy","0PktIyEfy9","BpYhVnFqik","suY4xM6qcG",
-"IRh48lXFOB","yEfy99iGoT","fqypyv8yFN","AXpwE5nmWv","d85a9RsQUq","lm0pD0YAGH","AmdQdfLNg8","ru4UG24ARF","uLtKspT8wu","45cIHcShY2",
-"HRxd8NOHsz","0PktIfmIK1","J2mQi7fsYM","VIlwPvkCHH","b29RJdhSuH","64s8Nn1pmO","qUJMdhYBCK","v1HlnvOqCE","TXQ0ZMK07Y","24ARFzY1GY",
-"yToGWJKWYR","BFkb8prNT6","jiVBPrz7Ut","lpF6WMGlTF","HzZT8tlILt","s93MlD6rBy","ulk41OUqFM","s47869rlg9","K20wKkB5nP","5Drn0VNCPd",
-"1j5L8v1Hln","i7WMQ07n1c","QYxC0Yw2oU","0KyfsMGlTF","I7p2a0ao3l","i3pydbrhlQ","wDajXECMvU","n1pmOJKWYR","VIlwPQClRL","FVMxoFxX9q",
-"zY1GYGSQwj","RkQke2Yz7E","X6PinzmLYD","U3yw59rlg9","VNCPdKZamH","3weIFNxx9V","uAWyp16lHc","5NammBbwgA","taOXKMaJQs","64s8Nsx5Gl",
-"pAhR1ECMvU","n1pmO4W0Tl","M6qcGmz8gx","ECMvUlkMUA","ogLgciwzGk","5Drn0WreyP","lkMUAydG8U","pFrrlVIlwP","ru4UG5VZjS","JXljW1LB1L",
-"Chuy3OUYuF","2TRI7Twano","L7cGcpiJSk","AgJHQlXFOB","JXljW2hEEU","MmKGJuZPqg","lj07Qdpe1v","ZJTXHTa8f6","wDajXMaJQs","xReec0BmCy",
-"rKDLJWmadA","3weIFK4GS8","QWxoTx3LDe","m4bxUzHF1q","uTacx2hEEU","zY1GYciuWz","5ZaEz9rlg9","RACujk85Ae","MmKGJ7hyVv","RmDcrtvdkD",
-"tAOsrHlUbF","9iGoT3otm6","yToGWuPX7G","tAOsrDLhzM","Zv7z0bZLvS","d85a9yEfy9","JkzUnciuWz","mX2GE1v5hH","7lUXZ8TxD7","uoStwLbRTH",
-"AmdQd7lUXZ","dmoS7yvOMI","dmoS7OHaBz","uLtKsaFFss","t59lRS77LH","xReecogLgc","he9IAChuy3","fmIK1tlILt","tuDySZ4I1v","2DREsuoStw",
-"AIYUuHzZT8","fLNg8iB08l","CNHmvQnJ1S","0h1b1a00b5","XflUq3otm6","QbxXcSjskQ","1LB1Ly94nw","atef2QWxoT","jtn0X5IhmG","EdBKcTXQ0Z",
-"gIYvELDk6f","DG4sTVLTy6","GWqqXiqv4k","s7Mxks93Ml","pWiOsydG8U","atef2euZA5","sqVrf9rlg9","ulk41yToGW","2Yz7E0Kyfs","14FLRLewvM",
-"8FmFHsoy9t","5Drn0GWqqX","MK07Yn1pmO","djsrvazIWp","ksJbyMezSW","zbIYYpT8wu","vOqCEaDGtS","K20wKHP433","VerEATXQ0Z","qaofNHlUbF",
-"0PktIFVMxo","3otm61j5L8","CIShGAOgEe","VIlwPv1Hln","bZLvSyofH3","CqqaDksJby","zqH0WiKqhr","7fsYMSbRYy","qaofNAmdQd","n8pJ9zbIYY",
-"yToGWs7Mxk","v2eC307n1c","JJs5maL6AJ","2ZHdkwDajX","ZUnqtt59lR","lj07Q0PktI","Q6LixjS1aj","lCMxyUvlv4","jSjS3UmaEv","9GXkXy94nw",
-"BCxeCZUnqt","7lUXZrz7Ut","fcwDauoStw","Kr8ysTCgPp","sqVrfpT8wu","NAFuwNAFuw","ZzJHW0PktI","48cHLnnP8o","xReecsuY4x","lj07QRpBQm",
-"atef2ZUnqt","jzUqRHP433","x3LDebgJAz","RmDcr64s8N","No0QbRzaZA","ksJbyX6Pin","vLsmS2hEEU","Uvlv4gjUTu","iB08lLbRTH","gtCA5KZamH",
-"d85a9vOqCE","sx5GlvkCHH","OxWIHtAOsr","rhl0J7fKYU","WMiS3Cfgr3","M6qcGuoStw","S2Dfu7fsYM","CxVEfi3pyd","zY1GYGv3Fq","POUYSFxX9q",
-"SbRYys7Mxk","7fKYU3otm6","uZPqgksJby","Ta8f6b29RJ","2Yz7ETwano","8U2nUtaOXK","qaofNs4786","FFDuizqH0W","TXQ0Ze6e4z","JRJQBuJScX",
-"PYBf4faHir","Uvlv4vLsmS","suY4xIRh48","JJs5mcQOnv","RBhp0he9IA","oVQp69XyT9","piJSkB3qem","ThjNnbrhlQ","kB5nPsuY4x","nlaByRsQUq",
-"14FLRt98iW","0YAGH4dEz6","LbRTHD6rBy","D6rByVBjhz","tjQxsfmIK1","gtCA5W7cTs","W7cTsLewvM","sqVrfzFgtB","fLNg8faHir","sx5Gls93Ml",
-"yluBxvOqCE","s93MlF6PT2","RkQke3weIF","gIYvEtuDyS","AkKTklm0pD","VLTy6uPX7G","FjHXRgdQsS","24ARFzQt6Q","W7cTs8U2nU","3weIFsoy9t",
-"HzZT8tuDyS","AkKTk580YD","ydG8UuLtKs","F6PT2Fhtgl","MGlTFY1mC0","dpe1vlH1kt","Cp3mZiqv4k","okgRiOHaBz","0PktIUl4a1","SbRYyUvlv4",
-"7lUXZrhl0J","0KyfsyluBx","8xEKz5ZaEz","7fKYUVprf2","YjB9tzFgtB","Mm8sik85Ae","VIlwPM6qcG","oVQp6Nxx9V","NOHszZJTXH","0PktIJ2mQi",
-"n8pJ9Mkgy8","Q6hMCprNT6","h1zcHk85Ae","M6qcGL7cGc","uZPqguQIcz","LewvMciuWz","v2eC3S77LH","0ao3lOHaBz","uPX7GWDVWJ","K4GS8uQIcz",
-"aL6AJFnPFB","NOHszKr8ys","dmoS7CqqaD","Mkgy8Zv7z0","s4786o8Uyd","Q6hMC7X3uy","uvf7ABCxeC","8RCUAtAOsr","RmDcriKqhr","lpF6WgIYvE",
-"8hJdttaOXK","QYxC0618Di","CxVEfgtCA5","atef2uPX7G","ThjNnksJby","7lUXZJ2mQi","DLhzMi3pyd","L7cGcDz1R3","uLtKsm4bxU","FFDuilCMxy",
-"s7Mxk9XyT9","ThjNnRsQUq","HzZT87fKYU","JRJQB5Namm","Z4I1vG1RhS","yToGW580YD","07n1cLbRTH","8xEKz0Wr5y","kB5nP5drc6","0h1b1uZPqg",
-"SmGzvLDk6f","ru4UGtaOXK","uJScX24ARF","b29RJyToGW","M6qcGo8Uyd","AOgEeWaim6","uLtKs55rfB","uJScXiwzGk","hSSvQh1zcH","M6qcGulk41",
-"bZLvSQChxs","jiVBPQYxC0","xReec0Kyfs","suY4xNcICA","JIqXiMmKGJ","OHaBz1j5L8","8TxD75drc6","k85AeRxrsm","7ku1pTCgPp","yToGWBGaQY",
-"QChxslViBv","aL6AJ4dEz6","HP433Qworu","ThjNnjSjS3","CdyBVpv0i7","xReecFxX9q","AgJHQ7fsYM","KASQ8FPfSE","RkQked7vjM","MaJQsfFDrJ",
-"soy9tMmKGJ","jtn0XDLhzM","QssNCUmaEv","tjQxsa00b5","rKDLJfaHir","FwEJzjfREu","I7p2afaHir","JXljWzbIYY","I7p2a8FmFH","POUYSOUqFM",
-"MmsIoBbwgA","oGu6xHzZT8","MGlTFxReec","WMiS3AXpwE","piJSksqVrf","7fsYMqUJMd","2ZHdkVLTy6","pFrrljS1aj","mz8gxlweGy","QnJ1Srz7Ut",
-"UmaEvVprf2","OxWIHSWfou","5drc60ao3l","JJs5m3weIF","pT8wujfREu","qaofNuupzk","hi5X77fsYM","8xEKztjQxs","guMb8Y1mC0","zFgtB0BmCy",
-"pFrrli7WMQ","yluBxcQOnv","hi5X7CdyBV","5ZaEzoVQp6","2Yz7Emz8gx","P6bcgiB08l","FcWrWHzZT8","SWfouulk41","aDGtSM6qcG","faHir7X3uy",
-"Dz1R314FLR","2ZHdkjSjS3","Nxx9VMK07Y","UlU3MNxx9V","qUJMdHRxd8","QChxsIn3NS","FVMxo7X3uy","OUqFMb29RJ","EoToP5drc6","CdyBVRzaZA",
-"4W0TlyvOMI","jSjS3OHaBz","C2IrcCp3mZ","n8pJ9yToGW","aFFssThjNn","dhSuH4dEz6","Ss0Zuhe9IA","pWiOsY1mC0","In3NS5nmWv","DcpWBzQt6Q",
-"ulk41Fhtgl","ZhwG1BGaQY","MK07YWDVWJ","blLA9QYxC0","uoStw29QAz","7ku1pFVMxo","Kr8yscQOnv","4dEz6MojnP","48cHL2Yz7E","nnP8ogf8rI",
-"0PktIFjHXR","FnPFB4dEz6","faHirZhwG1","JKWYR2TRI7","GWqqXJKWYR","yvOMItAOsr","AIYUuMmsIo","bZLvS7fKYU","0KyfsVprf2","lCMxyi7WMQ",
-"dQ586pFrrl","dpe1vQYxC0","CqqaDYf2Ec","2Yz7EECMvU","MojnPk85Ae","RzaZA14FLR","7hyVvBbwgA","Ta8f6ogLgc","pv0i7P6bcg","dpe1va00b5",
-"EdBKcuZPqg","8xEKzBFkb8","D6rByzbIYY","FhtglOUqFM","KsjRKuTacx","JkzUnsqVrf","Yw2oUm4bxU","ksJbyqaofN","vkCHHlpF6W","JkzUnxXTI4",
-"t98iWK20wK","VIlwP5ZaEz","5ZaEzgf8rI","nlaByuZPqg","uTacxuupzk","EoToPYOfrY","CqqaDJXljW","a00b59rlg9","y94nwgf8rI","v8yFNSjskQ",
-"1LB1LKr8ys","WDVWJFnPFB","AOgEepT8wu","RACujoVQp6","0ao3l8FmFH","5Mg9ruoStw","lViBvQ6Lix","mz8gxMmsIo","uLtKsFnPFB","IKxdLL7cGc",
-"lm0pDRxrsm","7fKYUPb1pa","uLtKsni2v1","jeskSlH1kt","Y1mC0WmadA","piJSki3pyd","zmLYD5drc6","RsQUqeuZA5","AOgEeKr8ys","WaWsvQYxC0",
-"XflUqy94nw","fLNg8zmLYD","Zv7z0he9IA","8TxD7WaWsv","Q6hMCuZPqg","aFFssiKqhr","8FmFHW7cTs","9XyT9fcJOy","Rxrsml83Ud","PYBf44QMc9",
-"24ARFlpF6W","Cp3mZjS1aj","6AFT0HP433","uZPqgNo0Qb","9GXkXRsQUq","fcwDaVLTy6","cL0aENOHsz","GrDg74W0Tl","QClRL07n1c","TCgPpQworu",
-"MK07YDz1R3","vkCHHlj07Q","aez9ygjUTu","Uvlv4faHir","suY4x5ZaEz","nlaByi3pyd","Cfgr3Zv7z0","oVQp6Oz8yZ","6AFT0EoToP","7Ow5CZuDtD",
-"rKDLJS77LH","CqqaDoGu6x","RpBQmyToGW","K20wK5iGN5","iKqhr2hEEU","azIWpprNT6","hUTw7KZamH","0BmCy7X3uy","k85Ae1LB1L","ni2v1QChxs",
-"8xEKzxXTI4","WmadAlViBv","9rlg9tAOsr","WMiS3uLtKs","16lHcaez9y","zFgtBRACuj","2NslmgjUTu","uZPqgiqv4k","IjTwPM6qcG","uoStwiqv4k",
-"s4786NhXdu","DcpWBfmIK1","HlUbFJXljW","M3zXLpT8wu","rhl0JprNT6","HzZT89y4lw","5Drn0ydG8U","lpF6WRpBQm","618DiFhtgl","zz4ZU2TRI7",
-"fcJOy48cHL","JKWYRCfgr3","QnJ1SUlU3M","FjHXR0PktI","StlDJcL0aE","CNHmvy94nw","NcICAlm0pD","In3NSlweGy","45cIHL7cGc","XflUqprNT6",
-"RkQketjQxs","gdQsSzY1GY","Q6hMCcShY2","BpYhVlpF6W","lkMUA618Di","v8yFNAgJHQ","yvOMI5IhmG","LbRTHRBhp0","nlaByStlDJ","yToGWuN6r3",
-"StlDJpmeCd","uZPqguZPqg","FFDuiMojnP","S2DfuiKqhr","Rxrsm7X3uy","jfREubZLvS","MojnPVprf2","wDajXHP433","Ss0ZuThjNn","kZANmCxVEf",
-"pT8wuRzaZA","ZuDtDhE1Ql","Z4I1v5IhmG","yToGWFNYIM","LewvMprNT6","64s8NrKDLJ","Cfgr3xciqp","hYBCK14FLR","6q6L9Uvlv4","CdyBVBFkb8",
-"IjTwP7X3uy","cL0aEuQIcz","S77LH48cHL","C2IrcazIWp","rKDLJYw2oU","uJScXZuDtD","EOE1oM6qcG","MojnP5VZjS","4W0TldmoS7","WMiS3CqqaD",
-"gdQsSRpBQm","9GXkXlm0pD","yvOMIxXTI4","5iGN5P6bcg","RpBQmY1mC0","FhtglFjHXR","5Drn0pAhR1","CK5W7lXFOB","VLTy6iwzGk","ZJTXHHP433",
-"9rlg9pv0i7","8RCUAJXljW","VIlwPOz8yZ","Cp3mZni2v1","5ZaEzm4bxU","nFqiks4786","2NslmQ6Lix","NhXduB3qem","yofH3zz4ZU","NAFuw45cIH",
-"CxVEfFnPFB","0YAGH29QAz","i3pydWPmlx","HlUbFlCMxy","64s8N3otm6","FGzgph1zcH","Z4I1vUl4a1","14FLRfmIK1","Dz1R329QAz","KASQ8WPmlx",
-"uZPqgdQ586","lm0pDP6bcg","MmKGJCK5W7","k85Ae8hJdt","W7cTsVjCZq","LewvMB3qem","lpF6WuN6r3","nnP8opmeCd","lpF6Wdjsrv","mX2GENo0Qb",
-"taOXK7hyVv","NAFuwVBjhz","Zv7z0WPmlx","qUJMdWaim6","y94nwLDk6f","VIlwPxReec","SjskQm4bxU","rhl0JhE1Ql","OUYuFZuDtD","Mkgy8JXljW",
-"16lHcrhl0J","DQimpgtCA5","IjTwPaL6AJ","Vprf2euZA5","zHF1qFhtgl","zHF1qQ6hMC","LbRTHpFrrl","FcWrWECMvU","lm0pDtaOXK","hE1Ql8RCUA",
-"iwzGkSmGzv","dhSuHlXFOB","I7p2aWPmlx","lkMUAO3iyQ","HP433tjQxs","fcwDacL0aE","kZANmlweGy","WDVWJ7fKYU","6q6L9lH1kt","kZANms93Ml",
-"IBe8kkZANm","EdBKctlILt","M3zXLC2Irc","n8pJ92hEEU","tl72Wulk41","zbIYYyvOMI","bgJAzBFkb8","Vprf2CK5W7","5VZjSEOE1o","5nmWv4W0Tl",
-"jSjS3i7WMQ","dQ586mz8gx","atef28TxD7","vLsmSaL6AJ","o8UydvLsmS","SbRYyDz1R3","uTacxWMiS3","ZzJHWMkgy8","LbRTHfqypy","yEfy9jiVBP",
-"jeskSPYBf4","5Mg9rlkMUA","uvf7A5Drn0","BGaQYFjHXR","iKqhrrKDLJ","jSjS3Gv3Fq","JIqXiHP433","WaWsv6q6L9","zFgtBuPX7G","HzZT8XflUq",
-"2DREsHlUbF","s93MljeskS","mz8gxkB5nP","Waim6HzZT8","7fKYUoVQp6","4QMc9S77LH","FcWrWW7cTs","3otm6BFkb8","NhXduaFFss","hYBCK9GXkX",
-"0BmCyMGlTF","OUqFMoGu6x","RBhp07ku1p","1LB1Latef2","nlaByS2Dfu","I7p2aXflUq","IjTwPv1Hln","okgRiWaWsv","0h1b1wiHrZ","ECMvUAIYUu",
-"POUYSDQimp","2TRI7Kr8ys","gdQsSk85Ae","pv0i7b29RJ","55rfBoQ87r","zY1GYReKEW","hi5X7GrDg7","KZamHMmsIo","oGu6xEOE1o","lViBvZuDtD",
-"h1zcH5Namm","7ku1pHzZT8","QWxoTguMb8","jSjS3uPX7G","Ss0ZuxXTI4","Yw2oUMm8si","wDajXeuZA5","tvdkDbZLvS","IjTwPpvgjS","i7WMQWDVWJ",
-"HzZT8HP433","qQxHPhE1Ql","5ZaEzReKEW","BFkb8RkQke","jtn0XBFkb8","b29RJyofH3","0BmCydmoS7","gf8rIIjTwP","bgJAzIKxdL","uZPqgS2Dfu",
-"6AFT0sqVrf","hE1QlRsQUq","dhSuHzHF1q","FjHXRBpYhV","oGu6xvLsmS","hSSvQdQ586","zY1GYK4GS8","Ss0Zuxciqp","FFDuiVprf2","uJScXs93Ml",
-"No0QbjfREu","8cVD3Pb1pa","oVQp6rhl0J","5Drn0AXpwE","AXpwElsQGo","FPfSEW7cTs","Kr8ysI7p2a","5nmWv7Ow5C","TCgPp5drc6","EoToPjtn0X",
-"zmLYDK4GS8","3weIFKsjRK","Ss0ZuguMb8","pmeCdRBhp0","AmdQdHRxd8","VIlwPzY1GY","FwEJzuLtKs","lpF6WS2Dfu","GWqqXKASQ8","prNT6FcWrW",
-"5iGN5d85a9","7hyVvQChxs","Cp3mZazIWp","uTacxCK5W7","Cfgr3fLNg8","nFqik5IhmG","Uvlv4soy9t","dmoS7ReKEW","HlUbFoGu6x","9eoRcuJScX",
-"IRh48ksJby","QnJ1S5ZaEz","lViBv2hEEU","3otm6C2Irc","ZzJHW5IhmG","iqv4kl83Ud","KZamHECMvU","5drc6xciqp","lH1ktb29RJ","qaofND6rBy",
-"ZUnqtHlUbF","oVQp6gIYvE","O3iyQPb1pa","9iGoTKr8ys","sx5Gl0YAGH","CK5W7AkKTk","XyPZNDz1R3","SmGzv14FLR","jS1ajVLTy6","djsrvAXpwE",
-"Cp3mZAmdQd","KsjRKVerEA","zFgtBd85a9","uPX7GlkMUA","lXFOBtlILt","9GXkXrz7Ut","SjskQRmDcr","IRh480MR5X","DG4sTTa8f6","Pb1paa00b5",
-"SjskQZUnqt","CK5W7i3pyd","mz8gxP6bcg","VjCZqCK5W7","zz4ZUvkCHH","uPX7G8FmFH","nFqikWreyP","i7WMQ14FLR","7X3uygdQsS","lsQGo4dEz6",
-"vkCHHLbRTH","mX2GEdQ586","fcJOybZLvS","RpBQmuLtKs","OUqFMzQt6Q","GWqqX8TxD7","SbRYyxReec","x3LDeP6bcg","taOXKHfyNQ","SjskQFVMxo",
-"vkCHHgjUTu","LewvMOUqFM","MezSWStlDJ","BbwgAWmadA","iwzGk9rlg9","CNHmvpWiOs","nlaBy7ku1p","Cfgr3K20wK","Ul4a1ZuDtD","x3LDeuLtKs",
-"pWiOsjeskS","SWfouJIqXi","RsQUqiB08l","Gv3FqAXpwE","hYBCKQssNC","WMiS3wDajX","NhXdut98iW","0Wr5yzHF1q","YjB9to8Uyd","MaJQsIRh48",
-"W7cTsbZLvS","t98iWRsQUq","2DREsHRxd8","iKqhrulk41","okgRijeskS","OUqFMoQ87r","L7cGcYh1hF","9XyT9HP433","FPfSEGrDg7","YOfrYYw2oU",
-"POUYSZuDtD","o8UydtvdkD","FGzgpNhXdu","VjCZqksJby","s47868RCUA","ZhwG19eoRc","okgRiPOUYS","Q6hMCTXQ0Z","gtCA5tAOsr","1v5hHwiHrZ",
-"uoStwix74r","ksJbyjS1aj","gdQsSJRJQB","cShY207n1c","QChxsM3zXL","QnJ1S0Kyfs","e6e4zpvgjS","B3qemP6bcg","IKxdL5iGN5","K4GS8QWxoT",
-"jfREuFGzgp","B3qem1v5hH","kB5nPDcpWB","ydG8U0ao3l","AgJHQVerEA","o8Uyd7lUXZ","CK5W7ZJTXH","lkMUAMkgy8","FcWrWUvlv4","uvf7AGXdoH",
-"7ku1pXyPZN","SmGzvOz8yZ","3weIFiB08l","aDGtSMmKGJ","blLA9he9IA","lpF6W5drc6","QYxC0DLhzM","iwzGkyluBx","okgRihi5X7","NOHszDG4sT",
-"RxrsmWaim6","uN6r3NcICA","jeskSZ4I1v","JkzUnxReec","Vprf2SjskQ","suY4xCNHmv","EdBKcoGu6x","WDVWJyluBx","C2Irc1v5hH","4QMc9BFkb8",
-"RkQkeMGlTF","9XyT9ydG8U","v2eC3Ul4a1","AkKTk5Namm","AkKTkReKEW","t98iW7ku1p","ksJbylkMUA","JXljWiqv4k","uoStw7fKYU","AIYUuCfgr3",
-"45cIHJIqXi","cL0aEiqv4k","Z4I1vfmIK1","9GXkXFcWrW","TwanoHfyNQ","RACujG1RhS","RACujRxrsm","i7WMQjeskS","o8Uyd5Namm","Z4I1vMm8si",
-"atef2Cp3mZ","uJScXlXFOB","1j5L8IRh48","PYBf4Ul4a1","Waim6tvdkD","x3LDeRmDcr","djsrvAmdQd","yEfy96AFT0","KZamH3weIF","Uvlv4CIShG",
-"Yw2oUhUTw7","Z4I1vUvlv4","hYBCKRkQke","k85AezqH0W","M6qcGvLsmS","JRJQBJKWYR","xReecLDk6f","CdyBVZv7z0","hYBCK55rfB","8cVD3K20wK",
-"KsjRK3weIF","bZLvSoVQp6","HzZT8zz4ZU","OUqFMHfyNQ","8FmFHdjsrv","zQt6Q9y4lw","RBhp0EOE1o","0Wr5yy94nw","NcICA9GXkX","XyPZNReKEW",
-"rKDLJ5Namm","9y4lwFNYIM","Chuy3cL0aE","ZUnqtlkMUA","OUqFMxciqp","lH1ktAgJHQ","JJs5mFnPFB","lCMxynnP8o","0BmCyi7WMQ","iqv4khE1Ql",
-"OUqFM7fsYM","M3zXLS77LH","t59lRiqv4k","gtCA5cmXIX","Ta8f60MR5X","v1HlngjUTu","AgJHQKr8ys","7X3uy4dEz6","HlUbFCqqaD","MmsIoyofH3",
-"n8pJ98FmFH","PYBf4JKWYR","uvf7AQClRL","1v5hH0PktI","lj07QNo0Qb","HRxd8WmadA","MezSWpiJSk","RxrsmAXpwE","MaJQsoVQp6","oQ87ro8Uyd",
-"AmdQdFnPFB","fcwDapvgjS","DcpWBKsjRK","lweGyHzZT8","ZuDtDyofH3","ThjNnNhXdu","oQ87ryEfy9","ix74rciuWz","Waim64QMc9","StlDJuJScX",
-"Q6hMCoVQp6","8FmFHh1zcH","J2mQiaFFss","gf8rIMmKGJ","9eoRcQWxoT","5nmWv16lHc","LbRTHOHaBz","o8UydFLsph","d7vjMCK5W7","i7WMQix74r",
-"NhXduulk41","29QAzjfREu","pAhR1BCxeC","NAFuwfcwDa","rhl0J1LB1L","6AFT0zHF1q","kZANmXyPZN","580YDd7vjM","5ZaEzd85a9","Q6LixRmDcr",
-"v1Hln45cIH","cQOnvydG8U","TXQ0ZMojnP","guMb85IhmG","5drc6DcpWB","uN6r3LewvM","8U2nUokgRi","JJs5mgjUTu","HP433Nxx9V","lkMUAYjB9t",
-"ulk41uJScX","2DREsEdBKc","euZA5YjB9t","uZPqgkB5nP","HlUbFv1Hln","blLA9hi5X7","uoStwQbxXc","5nmWvRACuj","k85AeYh1hF","AOgEeHzZT8",
-"7lUXZa00b5","AgJHQOUYuF","yEfy90YAGH","kB5nPVjCZq","MmsIo8TxD7","Yh1hFVBjhz","Yw2oUQWxoT","lsQGo2DREs","TCgPpWreyP","i3pydJJs5m",
-"UmaEvGSQwj","Yf2Ec9eoRc","zQt6Qlm0pD","WreyPBbwgA","CqqaDY1mC0","ni2v12Yz7E","J2mQiDLhzM","fcwDa7ku1p","WmadAMmKGJ","QYxC07X3uy",
-"lsQGoZzJHW","uTacxtlILt","dhSuHZUnqt","9XyT97X3uy","zqH0WMm8si","pFrrlhe9IA","WmadApvgjS","ZzJHWaFFss","suY4xYh1hF","RsQUqi3pyd",
-"ECMvUdpe1v","cmXIX2TRI7","m4bxUsqVrf","5Nammv8yFN","Mm8sie6e4z","Yh1hFMkgy8","StlDJlXFOB","zqH0WSjskQ","JJs5mogLgc","MmsIoPb1pa",
-"zz4ZUrKDLJ","lj07QIn3NS","d7vjMiqv4k","fLNg86AFT0","Ul4a1cmXIX","2hEEUuupzk","FGzgpZJTXH","8cVD3dpe1v","4W0TluZPqg","atef27ku1p",
-"xciqpJkzUn","X6PinyToGW","Gv3FqazIWp","L7cGcLbRTH","IRh48iwzGk","JkzUnTXQ0Z","zqH0Wm4bxU","WPmlxCK5W7","HP433k85Ae","oQ87rpmeCd",
-"CK5W7lj07Q","0ao3lprNT6","iKqhrThjNn","0PktIK4GS8","IjTwPvkCHH","hYBCKtlILt","pvgjSGSQwj","AIYUuQworu","5ZaEztl72W","Ss0ZuUlU3M",
-"Pb1payToGW","pT8wutl72W","pFrrlpWiOs","3weIF7ku1p","No0QbkB5nP","Mm8sikB5nP","SbRYylweGy","vLsmSzz4ZU","QClRLWmadA","ni2v1P6bcg",
-"ECMvUhi5X7","dhSuHF6PT2","C2IrcW7cTs","k85Aelj07Q","RzaZA1LB1L","YjB9t16lHc","dpe1vtl72W","Yw2oURkQke","cQOnvwiHrZ","ZuDtDDLhzM",
-"ThjNn7fKYU","FjHXRRxrsm","0ao3lzY1GY","CK5W7VNCPd","CdyBVMK07Y","KZamH16lHc","zQt6Ql83Ud","DLhzMWDVWJ","zz4ZUS77LH","WreyPaL6AJ",
-"Q6hMCbrhlQ","jfREuQ6Lix","5nmWviKqhr","Ta8f6WmadA","D6rBy0YAGH","5Mg9rQYxC0","nlaByFjHXR","bZLvS5Mg9r","zY1GYpWiOs","s7MxkP6bcg",
-"StlDJ8U2nU","suY4xdhSuH","FcWrWzQt6Q","MmKGJ7fKYU","xReecuPX7G","guMb8uJScX","RzaZAt98iW","faHirVjCZq","BpYhVNAFuw","Yh1hFdhSuH",
-"HzZT8uPX7G","Q6LixXyPZN","h1zcH8TxD7","2TRI745cIH","ReKEWhi5X7","s47868cVD3","b29RJ5ZaEz","QYxC09eoRc","HlUbFZzJHW","ksJbylXFOB",
-"AXpwEfmIK1","hYBCKWreyP","atef27fKYU","hYBCKCfgr3","uoStw14FLR","qQxHPqUJMd","rhl0J0MR5X","7ku1pQworu","1j5L8dQ586","CIShGi7WMQ",
-"5IhmGd7vjM","lXFOBjtn0X","StlDJgIYvE","gIYvEzmLYD","HzZT8GWqqX","IKxdLF6PT2","jSjS30Wr5y","D6rByRpBQm","pAhR1aL6AJ","hYBCKb29RJ",
-"MmKGJJkzUn","WMiS3FjHXR","FVMxogdQsS","jSjS3IjTwP","HlUbF16lHc","AIYUuaL6AJ","taOXKHRxd8","580YDPOUYS","5Mg9rzz4ZU","D6rByW7cTs",
-"DLhzM24ARF","580YDtl72W","pv0i7EOE1o","0ao3lo8Uyd","ZUnqtogLgc","uZPqgJRJQB","bgJAzFVMxo","jS1ajAIYUu","fqypy3weIF","JJs5mY1mC0",
-"ix74rMezSW","JIqXie6e4z","WDVWJlViBv","fcwDaQssNC","GSQwjulk41","qaofNWMiS3","VBjhzZUnqt","Uvlv4Uvlv4","9XyT9Oz8yZ","24ARFIKxdL",
-"55rfBQnJ1S","zqH0WK4GS8","pT8wuprNT6","oQ87rl83Ud","tl72WSs0Zu","VerEAAgJHQ","zFgtBzY1GY","zmLYDyofH3","FcWrW0YAGH","3weIFK20wK",
-"HzZT8uZPqg","FxX9qVjCZq","0ao3lAXpwE","zQt6QFwEJz","kZANmUmaEv","FNYIMJ2mQi","sqVrfm4bxU","vkCHHTCgPp","s93MllViBv","vOqCEwiHrZ",
-"Waim6v2eC3","5Mg9rKr8ys","FcWrWksJby","jeskSzbIYY","uoStwJIqXi","7fsYM29QAz","euZA5RmDcr","LbRTH3weIF","nlaByhi5X7","TXQ0ZMkgy8",
-"Yh1hF8U2nU","JJs5mS77LH","U3yw5n8pJ9","HRxd8580YD","POUYSWaim6","FNYIMgjUTu","0PktIa00b5","TCgPp5VZjS","JRJQBeuZA5","v1HlnoQ87r",
-"EoToPoQ87r","aL6AJQChxs","0Kyfsv1Hln","RmDcrv8yFN","FcWrWqQxHP","aez9yIRh48","24ARFuZPqg","SbRYyVIlwP","QYxC0he9IA","W7cTsWmadA",
-"29QAzn1pmO","ksJbyFVMxo","JkzUnOUYuF","lH1ktjeskS","uQIcz1LB1L","fLNg8VjCZq","iKqhrOHaBz","zqH0W0PktI","3otm6U3yw5","7X3uylkMUA",
-"55rfBQClRL","7hyVvQ6hMC","dpe1vpT8wu","okgRiSWfou","vLsmSLewvM","tuDySFxX9q","prNT6ThjNn","VjCZqRmDcr","WDVWJuvf7A","LewvM1j5L8",
-"8cVD3Cp3mZ","5nmWv0YAGH","QClRLCp3mZ","WmadAUvlv4","aFFssjSjS3","IBe8kS2Dfu","x3LDeQ6hMC","FPfSE580YD","bZLvSAkKTk","kB5nPCdyBV",
-"lkMUAThjNn","5Namm7X3uy","14FLR5VZjS","hE1QlDQimp","FnPFBuTacx","Yh1hFWMiS3","vLsmSVprf2","5VZjSjeskS","AmdQdQChxs","CdyBVWPmlx",
-"qQxHPGSQwj","atef2bgJAz","5VZjSvkCHH","Vprf2dmoS7","Yh1hFOxWIH","IBe8k2DREs","s4786Qworu","CqqaDNo0Qb","Mkgy8zHF1q","yEfy9WDVWJ",
-"lpF6W29QAz","7Ow5CWMiS3","9iGoTtaOXK","48cHLMGlTF","wiHrZUmaEv","O3iyQuQIcz","Cp3mZaDGtS","tlILtQClRL","RxrsmWMiS3","S77LHRpBQm",
-"RkQkeTa8f6","lpF6WSs0Zu","StlDJCdyBV","EoToPFVMxo","1LB1L0ao3l","POUYSb29RJ","YOfrYDcpWB","k85Ae0Wr5y","AIYUuRkQke","euZA57fKYU",
-"0PktItjQxs","5nmWvIBe8k","Oz8yZSmGzv","8FmFHi7WMQ","QworuCK5W7","HlUbFyEfy9","9y4lwd7vjM","zQt6Q07n1c","s4786jzUqR","brhlQPOUYS",
-"CK5W7VBjhz","atef2xReec","ZzJHWKr8ys","zbIYYVIlwP","QWxoTZ4I1v","QChxsLbRTH","In3NSjS1aj","bgJAzv8yFN","QWxoTBFkb8","yToGWcQOnv",
-"VIlwPn1pmO","hSSvQBCxeC","iB08l0BmCy","Cp3mZMK07Y","RmDcrguMb8","jfREuLDk6f","tAOsrjeskS","Z4I1vWMiS3","M6qcG0Wr5y","9rlg9o8Uyd",
-"9XyT9AXpwE","soy9tRzaZA","FhtglD6rBy","CIShGFxX9q","SmGzvPYBf4","lkMUAcShY2","16lHcyEfy9","soy9tWDVWJ","Mkgy8a00b5","suY4x0PktI",
-"HfyNQm4bxU","DG4sToGu6x","cShY2tuDyS","XyPZNMmsIo","wiHrZ4W0Tl","bgJAzKASQ8","cQOnvNcICA","9iGoT9iGoT","2TRI78hJdt","618DiGSQwj",
-"RzaZAlweGy","qUJMdgdQsS","zY1GYgdQsS","AIYUuhE1Ql","kZANm5ZaEz","AIYUu8xEKz","uJScXx3LDe","ni2v1qUJMd","SmGzvjtn0X","ZJTXH5iGN5",
-"ix74rxciqp","55rfBFGzgp","9rlg9IBe8k","2NslmKZamH","KZamHVerEA","s7Mxk5Namm","BbwgAdQ586","IKxdLFcWrW","v1HlnMkgy8","K20wK2Yz7E",
-"gdQsSxReec","OUqFM7hyVv","wDajX55rfB","ulk418U2nU","ydG8UAIYUu","uPX7G29QAz","580YDjS1aj","7fKYUIRh48","Cp3mZgjUTu","AIYUuYf2Ec",
-"NAFuwMK07Y","gdQsSdhSuH","0PktIlkMUA","580YDh1zcH","Cfgr3EdBKc","7X3uyUvlv4","618DizqH0W","LDk6f5iGN5","C2Ircb29RJ","lkMUA2Nslm",
-"0ao3lQbxXc","EdBKcqaofN","d85a92ZHdk","prNT6dmoS7","FxX9qzY1GY","CqqaDa00b5","zbIYYCdyBV","ReKEWZuDtD","QChxs9rlg9","i7WMQnlaBy",
-"MmsIoZ4I1v","2NslmKr8ys","W7cTsru4UG","hYBCKCqqaD","pvgjS8FmFH","blLA9fFDrJ","JJs5m3otm6","VLTy60Kyfs","jS1ajcShY2","SbRYy16lHc",
-"jS1ajvkCHH","uAWypBGaQY","lpF6WJIqXi","Vprf2b29RJ","XyPZNBbwgA","2DREsFNYIM","1j5L8F6PT2","UmaEvCdyBV","C2IrcC2Irc","Y1mC0NOHsz",
-"uN6r3tjQxs","AgJHQYf2Ec","ZJTXHFPfSE","nlaByuN6r3","KsjRKgtCA5","Ss0ZuSmGzv","wiHrZB3qem","Yf2EcFjHXR","zz4ZU9iGoT","Y1mC0AkKTk",
-"bZLvSYOfrY","pFrrlqQxHP","NhXduzHF1q","dhSuH24ARF","Yf2EcI7p2a","Yw2oU6AFT0","RzaZARxrsm","ix74rQ6Lix","piJSks7Mxk","sx5Gle6e4z",
-"Nxx9VJ2mQi","MmsIohUTw7","VBjhzaez9y","QssNCxReec","l83UdWaWsv","k85AeZUnqt","i7WMQoGu6x","fmIK1jSjS3","Yf2EcCdyBV","hYBCKMezSW",
-"i7WMQdmoS7","5IhmGv8yFN","CNHmvStlDJ","580YDFNYIM","EdBKcMojnP","pvgjSaDGtS","SjskQdhSuH","HzZT87hyVv","prNT6lm0pD","U3yw5s7Mxk",
-"HlUbFcL0aE","faHir14FLR","uLtKsn1pmO","EdBKcs7Mxk","AOgEe7fKYU","CxVEfRmDcr","Z4I1viwzGk","zHF1qxXTI4","xReecL7cGc","lkMUABGaQY",
-"SWfouGrDg7","DQimpOHaBz","QssNCL7cGc","NcICAbrhlQ","uN6r3yvOMI","faHirJRJQB","hSSvQjiVBP","XflUqF6PT2","BpYhVGrDg7","7X3uyx3LDe",
-"i3pydlkMUA","EOE1oNxx9V","8U2nUaez9y","8xEKz2Nslm","Oz8yZni2v1","0BmCynnP8o","zHF1qksJby","dmoS724ARF","aez9yKsjRK","nFqikBGaQY",
-"9eoRcTwano","0MR5XyToGW","4W0TlzqH0W","tAOsrUmaEv","pWiOs0Wr5y","hYBCKnFqik","k85Ae5nmWv","ix74r48cHL","faHirlkMUA","a00b5SWfou",
-"64s8Ndpe1v","l83UdQClRL","v8yFNC2Irc","Y1mC055rfB","Pb1pas93Ml","O3iyQOUYuF","hYBCKB3qem","MaJQsa00b5","ksJbyXflUq","v1HlnblLA9",
-"i7WMQ5IhmG","Ul4a1I7p2a","ru4UGgdQsS","D6rBymX2GE","oGu6xlH1kt","FGzgpFGzgp","Kr8ysWaWsv","Cfgr3jfREu","mX2GEEoToP","JJs5m4W0Tl",
-"rhl0JC2Irc","WreyPRACuj","WaWsv5nmWv","hSSvQd85a9","16lHcDLhzM","SjskQ48cHL","Ss0ZuLDk6f","5drc6DQimp","hE1Qluvf7A","CK5W79GXkX",
-"07n1cpFrrl","3otm6hi5X7","8U2nUEoToP","Chuy3uJScX","XflUqjtn0X","zFgtB16lHc","1j5L85ZaEz","14FLRAmdQd","5NammYjB9t","MmsIoCK5W7",
-"TCgPpFFDui","lH1ktDLhzM","Waim6JkzUn","blLA9IRh48","ru4UG3otm6","Ta8f6uAWyp","RzaZA9y4lw","CxVEfvLsmS","QWxoTTCgPp","IKxdLStlDJ",
-"8FmFHaL6AJ","nFqikBCxeC","Dz1R32Nslm","MGlTFfLNg8","Uvlv4hE1Ql","StlDJWPmlx","zHF1qDcpWB","M3zXLv8yFN","5drc68RCUA","RsQUqXyPZN",
-"hSSvQMojnP","yEfy9oVQp6","iwzGktuDyS","uQIcztAOsr","s4786Q6hMC","No0Qb8xEKz","yEfy9wiHrZ","JkzUnRsQUq","uPX7Gk85Ae","8hJdt55rfB",
-"jiVBPUlU3M","ru4UGSjskQ","O3iyQWMiS3","Ta8f6WDVWJ","07n1cogLgc","uLtKswDajX","lCMxyP6bcg","0h1b1EOE1o","nnP8oKZamH","CNHmvWMiS3",
-"DG4sTdpe1v","580YDW7cTs","gdQsSSWfou","0ao3lgjUTu","cQOnvRBhp0","0BmCyqUJMd","W3VFHBGaQY","1v5hHlH1kt","qQxHPbZLvS","lpF6Wv2eC3",
-"8U2nUtjQxs","zY1GYvkCHH","07n1cSbRYy","cShY2CNHmv","5iGN5Oz8yZ","W7cTsM3zXL","ksJbyzFgtB","DQimpuJScX","lj07QPOUYS","5Mg9rb29RJ",
-"Ta8f6Nxx9V","h1zcH5ZaEz","uN6r3Vprf2","29QAz8cVD3","WaWsvjSjS3","0h1b1ydG8U","jzUqRZUnqt","Z4I1vQ6hMC","Oz8yZwiHrZ","e6e4zjS1aj",
-"0ao3ldQ586","ulk41euZA5","VjCZqQnJ1S","GWqqXpv0i7","VerEAdpe1v","jfREuWmadA","I7p2aRxrsm","RBhp0lj07Q","K4GS8fLNg8","CdyBVl83Ud",
-"gIYvE14FLR","v8yFNcmXIX","5Drn0v8yFN","8U2nU618Di","55rfBVerEA","xXTI4FcWrW","StlDJ1LB1L","07n1cgf8rI","guMb8rz7Ut","8RCUAThjNn",
-"jiVBP7X3uy","Gv3FqWMiS3","lkMUAlCMxy","7X3uyoGu6x","580YDKr8ys","O3iyQulk41","5NammEoToP","FxX9qX6Pin","KsjRK3otm6","1j5L8SWfou",
-"Mm8si2hEEU","5IhmGt98iW","cL0aElweGy","QworuFwEJz","gtCA52hEEU","In3NSJkzUn","yvOMIEdBKc","2ZHdkprNT6","5iGN5NcICA","5Drn0nFqik",
-"tjQxsm4bxU","MezSWyToGW","6AFT0zz4ZU","7lUXZHzZT8","v2eC3YjB9t","tl72WAXpwE","VLTy6IBe8k","v1Hlnd7vjM","YOfrYQ6Lix","CqqaDFjHXR",
-"ru4UGkB5nP","ix74rt59lR","djsrvhE1Ql","vOqCEReKEW","0PktInnP8o","M3zXLjfREu","a00b5BpYhV","8RCUANhXdu","tl72WdhSuH","9y4lwVIlwP",
-"4dEz6pmeCd","1v5hH7Ow5C","qUJMdOUYuF","6q6L9SjskQ","TwanozmLYD","ECMvU7fKYU","euZA50YAGH","Yw2oUOUYuF","FxX9qwiHrZ","k85AenlaBy",
-"FGzgpWaWsv","pv0i7Oz8yZ","CqqaDVIlwP","XyPZNhi5X7","7Ow5CuTacx","kB5nPLbRTH","2DREsciuWz","YOfrYlCMxy","MojnPM6qcG","4W0Tlni2v1",
-"B3qem5Namm","n8pJ9atef2","dpe1vsx5Gl","iB08lWMiS3","MGlTF3otm6","fcwDaYf2Ec","ZJTXHECMvU","ru4UGNhXdu","cQOnvjfREu","5drc6Ul4a1",
-"d7vjMdjsrv","D6rByfmIK1","Y1mC0yofH3","FjHXRCNHmv","MmsIoSWfou","ulk41Mkgy8","jzUqRWDVWJ","zY1GYiwzGk","soy9tprNT6","GXdoHxReec",
-"cmXIX07n1c","In3NSksJby","Nxx9VThjNn","cShY2cmXIX","ciuWzZhwG1","64s8NfLNg8","FxX9qsoy9t","ydG8UFVMxo","tl72WPb1pa","D6rBym4bxU",
-"QYxC007n1c","Q6Lix2Yz7E","LbRTHAgJHQ","TwanoGrDg7","Chuy33weIF","gf8rIJXljW","Zv7z0aDGtS","wiHrZUvlv4","8cVD3FjHXR","BFkb8K20wK",
-"Mm8siQWxoT","Mm8sijzUqR","WaWsvTwano","zFgtBYOfrY","45cIH5IhmG","RkQkejSjS3","iKqhrZhwG1","J2mQizz4ZU","J2mQixXTI4","Yf2Ec2Nslm",
-"qUJMd8xEKz","24ARFpv0i7","14FLR5drc6","hi5X7DQimp","fcwDaEOE1o","AgJHQaez9y","dpe1vokgRi","4W0TlfaHir","wiHrZK4GS8","mz8gxWaWsv",
-"QbxXcru4UG","lweGydhSuH","oVQp62TRI7","DLhzM7Ow5C","QnJ1S9iGoT","Nxx9V0h1b1","jSjS3RsQUq","SWfou55rfB","y94nwoQ87r","ZJTXHBFkb8",
-"hi5X7EdBKc","RsQUqK20wK","d7vjMtl72W","iB08liqv4k","xciqprKDLJ","GSQwjSjskQ","DG4sT4W0Tl","gIYvESs0Zu","O3iyQzY1GY","ZJTXHLDk6f",
-"Q6hMCn1pmO","Mm8siThjNn","iKqhrXflUq","lCMxyYh1hF","O3iyQ3weIF","Kr8ysdjsrv","PYBf4Q6hMC","ix74rJXljW","tvdkDYOfrY","nlaBynFqik",
-"FVMxoNOHsz","Yw2oUjzUqR","pAhR15Mg9r","iqv4kaez9y","Ss0ZuBpYhV","b29RJpiJSk","fcwDa48cHL","mX2GEni2v1","gtCA5yluBx","gf8rIIBe8k",
-"MaJQs8RCUA","ru4UGydG8U","Z4I1vFFDui","5Drn0UlU3M","NAFuwzmLYD","CxVEfgjUTu","FVMxoFLsph","45cIHX6Pin","JIqXi8FmFH","zQt6QpAhR1",
-"taOXK9eoRc","uupzki7WMQ","Mm8siYf2Ec","SmGzvm4bxU","WPmlxFVMxo","ZuDtDCqqaD","kZANmQ6hMC","l83Ud618Di","Ss0ZuNo0Qb","MmKGJs4786",
-"t98iWpFrrl","qUJMd2ZHdk","Waim6NOHsz","Mm8siG1RhS","uTacxAkKTk","tAOsr9eoRc","zmLYDTCgPp","0MR5X5VZjS","pmeCdVerEA","wDajXK20wK",
-"ogLgcWaWsv","he9IAlkMUA","vLsmSm4bxU","RxrsmKZamH","gIYvEWreyP","1j5L80h1b1","lj07QTXQ0Z","5Namm8RCUA","s93MlMaJQs","AIYUuvkCHH",
-"lm0pDGWqqX","IjTwPZuDtD","0Kyfs1j5L8","n8pJ914FLR","DG4sTokgRi","CqqaDFLsph","bgJAzBCxeC","HP433VIlwP","8U2nUnnP8o","fmIK1Ta8f6",
-"GXdoH7fKYU","In3NSlsQGo","fLNg829QAz","45cIHMkgy8","cL0aERzaZA","P6bcg0PktI","Oz8yZXyPZN","07n1ctuDyS","HfyNQGSQwj","JkzUn9eoRc",
-"qUJMdU3yw5","n1pmOs4786","h1zcH580YD","In3NSsx5Gl","K4GS8QClRL","RmDcrZv7z0","nnP8olViBv","ZUnqtoGu6x","uN6r39rlg9","M3zXLiwzGk",
-"0Wr5ym4bxU","JXljWI7p2a","RACujAmdQd","rKDLJVprf2","AmdQd29QAz","W3VFHLewvM","yluBxl83Ud","5Drn05Drn0","In3NSulk41","zz4ZUtuDyS",
-"Ta8f6k85Ae","SjskQ2TRI7","uQIczy94nw","uLtKstvdkD","JKWYRnlaBy","Kr8ys5nmWv","DcpWB8hJdt","lXFOBeuZA5","NAFuwW3VFH","9GXkXksJby",
-"x3LDeB3qem","9GXkXCNHmv","pT8wu5ZaEz","OUqFMECMvU","ksJbye6e4z","0ao3l45cIH","K20wKFwEJz","zFgtB0MR5X","1LB1L2Yz7E","sx5GlaDGtS",
-"v2eC3gdQsS","wDajXW3VFH","uN6r3uZPqg","Gv3Fq16lHc","JRJQBfcwDa","pv0i7a00b5","2TRI7VNCPd","VerEAi7WMQ","piJSk618Di","fFDrJNo0Qb",
-"14FLRzQt6Q","Z4I1vJKWYR","Ss0ZudmoS7","WreyPoQ87r","Ss0Zutl72W","NcICAG1RhS","uJScXMezSW","h1zcHyluBx","MojnPnlaBy","48cHLQbxXc",
-"lweGyCK5W7","WmadA0BmCy","NAFuwru4UG","lH1ktMK07Y","uAWyp5Namm","vkCHHqQxHP","FnPFBJIqXi","Oz8yZiwzGk","RsQUq9iGoT","RxrsmcmXIX",
-"Ss0ZuQbxXc","s4786NOHsz","7X3uyS77LH","lsQGoK20wK","VIlwPfLNg8","X6PinOHaBz","jiVBPuLtKs","HP433okgRi","KZamHhE1Ql","aez9yZUnqt",
-"FxX9quPX7G","pvgjSpFrrl","tAOsrt59lR","NhXdunlaBy","tlILt0Kyfs","24ARFDz1R3","GWqqXCNHmv","RxrsmRACuj","AOgEeAIYUu","MK07YazIWp",
-"9iGoTPOUYS","xXTI4P6bcg","5NammNOHsz","jeskS0h1b1","yvOMIlm0pD","hSSvQCIShG","IRh48DG4sT","BGaQY5nmWv","uAWypuZPqg","gdQsSNAFuw",
-"2hEEUReKEW","JJs5mRBhp0","tvdkD64s8N","MK07YRsQUq","azIWpUmaEv","jeskSVIlwP","F6PT25Mg9r","XflUqsx5Gl","NhXdud7vjM","Z4I1vgdQsS",
-"gdQsSIn3NS","3weIF8hJdt","Y1mC0CdyBV","zbIYYLbRTH","5Drn0piJSk","sqVrfjeskS","hUTw729QAz","1LB1Lv8yFN","cQOnviB08l","Mkgy8uoStw",
-"ZJTXH7hyVv","9XyT9pT8wu","hi5X7lH1kt","OxWIHS2Dfu","HlUbFhe9IA","QChxsn1pmO","aL6AJPb1pa","o8UydYh1hF","4W0Tlmz8gx","BCxeC5iGN5",
-"7fKYU4W0Tl","piJSkVjCZq","XyPZNb29RJ","FVMxo3otm6","RACujzHF1q","tl72WZv7z0","7hyVvhYBCK","GrDg7uQIcz","3otm6CdyBV","nFqikJRJQB",
-"UlU3MStlDJ","zFgtBUvlv4","5drc6JJs5m","K20wKJRJQB","U3yw5e6e4z","uLtKsCNHmv","fqypysx5Gl","TXQ0ZHP433","0Wr5yOUYuF","EoToPy94nw",
-"RpBQm9eoRc","Mkgy8EoToP","5IhmGaDGtS","n8pJ9zmLYD","gjUTuRxrsm","RsQUqzQt6Q","fqypyIKxdL","1v5hHQworu","5drc648cHL","ZuDtDRACuj",
-"9rlg9yEfy9","yluBxUmaEv","ni2v1i3pyd","Uvlv4ksJby","DQimpcmXIX","zqH0Whi5X7","ZJTXH55rfB","QbxXcqUJMd","Cp3mZlsQGo","Cp3mZsuY4x",
-"KZamHBCxeC","zQt6QHP433","Mm8siQworu","Ta8f6soy9t","faHirdmoS7","fcJOyVNCPd","ydG8UjSjS3","vLsmSAXpwE","Chuy32hEEU","B3qemRkQke",
-"BpYhVnlaBy","jiVBPNOHsz","blLA9Yh1hF","OHaBz3weIF","0Wr5y5VZjS","bgJAzsuY4x","7X3uyQ6Lix","cShY2WPmlx","In3NSzHF1q","tlILtdhSuH",
-"a00b5hi5X7","7fsYMlkMUA","iwzGkEoToP","rKDLJhSSvQ","dhSuHQssNC","sx5GlyToGW","MezSW9iGoT","s93MlW7cTs","fqypyzqH0W","RmDcrdmoS7",
-"U3yw5ydG8U","Yh1hF3otm6","FNYIMOz8yZ","uQIczzFgtB","rKDLJyvOMI","yEfy9lm0pD","lH1kttvdkD","B3qemlkMUA","StlDJfmIK1","bZLvSECMvU",
-"9XyT9ni2v1","KsjRKkB5nP","d7vjMksJby","KsjRKRkQke","FwEJzIjTwP","2DREsB3qem","MGlTFWaWsv","QWxoTQnJ1S","s7Mxk1j5L8","Pb1pa5Mg9r",
-"rhl0J0BmCy","KZamHMkgy8","rz7Ut4dEz6","7ku1pJIqXi","pT8wuguMb8","M3zXLlm0pD","qQxHP5IhmG","hi5X7gjUTu","v8yFNQ6Lix","Kr8ysHP433",
-"LbRTHHP433","bZLvSuN6r3","x3LDeoQ87r","jiVBP5VZjS","lXFOBECMvU","MezSWAXpwE","wDajXaez9y","5Drn08FmFH","QworuHRxd8","RACujZzJHW",
-"e6e4zSjskQ","Yf2EcTXQ0Z","dQ586IKxdL","FnPFBksJby","d7vjMQChxs","AXpwE14FLR","K20wKt98iW","OUqFM45cIH","Dz1R3MmsIo","zqH0WGXdoH",
-"vOqCEAmdQd","cShY2qQxHP","vkCHHOxWIH","ECMvUKZamH","wiHrZhi5X7","9rlg9lCMxy","k85Ae618Di","kB5nPuZPqg","uQIczpv0i7","lCMxyKASQ8",
-"lH1ktHRxd8","WMiS3AkKTk","vkCHHiqv4k","x3LDeBpYhV","WDVWJdQ586","IBe8kxciqp","ydG8UC2Irc","XyPZNzY1GY","QnJ1SZv7z0","MaJQsY1mC0",
-"iKqhrfcJOy","kZANmaL6AJ","CNHmvIBe8k","fqypyatef2","hUTw72ZHdk","M3zXLEoToP","FVMxoGSQwj","7ku1pbZLvS","hi5X7RsQUq","ECMvUQworu",
-"sqVrffFDrJ","pT8wu1j5L8","M3zXLfqypy","zQt6QyofH3","8FmFHUlU3M","9rlg9IRh48","iqv4k64s8N","uLtKs2Yz7E","zQt6QfcJOy","hUTw7EOE1o",
-"FPfSEIRh48","RACuj7hyVv","4QMc9Ta8f6","JKWYRatef2","hE1QlEoToP","xReecwiHrZ","HfyNQcQOnv","zqH0WFjHXR","fLNg8Ta8f6","GWqqX8U2nU",
-"7fsYMVerEA","v8yFN7hyVv","aL6AJ24ARF","xReecdQ586","55rfBTCgPp","kB5nPdpe1v","oGu6x9XyT9","5Mg9rzqH0W","v1HlnPb1pa","CIShGSWfou",
-"EoToPt98iW","EoToPsuY4x","Cp3mZqaofN","AkKTkoQ87r","TwanoRxrsm","ECMvU7lUXZ","azIWpDLhzM","Ss0ZubrhlQ","DLhzMtaOXK","fcwDaZuDtD",
-"Q6hMCOxWIH","dhSuHpAhR1","J2mQiWMiS3","0YAGH4QMc9","AkKTkVIlwP","wDajXRpBQm","lViBvNOHsz","t59lR6q6L9","FGzgpFNYIM","29QAz1j5L8",
-"qQxHP5ZaEz","G1RhSaL6AJ","AOgEev1Hln","W7cTsvLsmS","Oz8yZatef2","b29RJQssNC","0ao3l1LB1L","QChxsuPX7G","55rfBi3pyd","bZLvSiB08l",
-"tvdkDKASQ8","BFkb8b29RJ","azIWppWiOs","i7WMQKr8ys","IRh48EdBKc","FGzgpBpYhV","0MR5X618Di","brhlQEdBKc","U3yw5Gv3Fq","Oz8yZWMiS3",
-"ECMvUCp3mZ","blLA9Ta8f6","VIlwPyluBx","DQimplXFOB","ZhwG1nnP8o","7X3uy7fKYU","B3qem8cVD3","KASQ8P6bcg","atef2ZhwG1","JIqXiTwano",
-"h1zcHNOHsz","Zv7z0FLsph","brhlQCqqaD","yofH3FxX9q","jiVBPU3yw5","W7cTs5nmWv","FhtgljSjS3","XyPZNBCxeC","0MR5XY1mC0","QClRLyEfy9",
-"In3NSVNCPd","8cVD3RmDcr","G1RhSfFDrJ","I7p2aMmKGJ","WMiS3zz4ZU","5Drn0dmoS7","5Drn0StlDJ","W3VFHnlaBy","2ZHdkcmXIX","yvOMIRsQUq",
-"Yw2oU9rlg9","RsQUqJKWYR","yvOMI0YAGH","ZuDtDCK5W7","XyPZN7lUXZ","iwzGkMkgy8","iwzGkAgJHQ","9XyT9tuDyS","Pb1pas4786","Ta8f6RBhp0",
-"qQxHPAkKTk","9rlg9WaWsv","IjTwPd85a9","fcJOyGv3Fq","6AFT09eoRc","QssNCGrDg7","0PktIzHF1q","3otm65iGN5","hE1Qln8pJ9","48cHLpv0i7",
-"Y1mC0FjHXR","JJs5mlkMUA","0BmCyCxVEf","UlU3Matef2","EoToP1v5hH","OUqFMuoStw","QWxoTzqH0W","AXpwEuTacx","Ul4a1hi5X7","WPmlxX6Pin",
-"DQimpvOqCE","iqv4kazIWp","0ao3lChuy3","zHF1qVNCPd","fcwDaqUJMd","24ARFfmIK1","Mm8siuPX7G","W7cTsdmoS7","nFqikyToGW","soy9t5iGN5",
-"nnP8oEOE1o","m4bxUYw2oU","taOXKoVQp6","oVQp6oVQp6","IBe8kx3LDe","J2mQiMK07Y","0BmCy2Nslm","RzaZAuJScX","k85AepvgjS","dQ586RsQUq",
-"Y1mC0oQ87r","zFgtB2DREs","lH1ktHP433","RsQUqEOE1o","FwEJzDG4sT","iKqhrCIShG","16lHcSbRYy","wDajXsuY4x","fmIK1Mkgy8","DG4sToVQp6",
-"J2mQi7hyVv","CqqaDS2Dfu","ydG8U1v5hH","jfREu5nmWv","rz7UtDz1R3","JJs5m0h1b1","dpe1vIBe8k","QChxsWPmlx","4dEz6HzZT8","jzUqRni2v1",
-"lkMUA0MR5X","SWfou4QMc9","jiVBPMmKGJ","l83UdWDVWJ","DG4sT7fsYM","aez9yI7p2a","ni2v1v2eC3","Yh1hFiKqhr","WreyPMmsIo","OUYuFWPmlx",
-"i3pydAXpwE","BGaQY48cHL","GSQwjt98iW","NOHszO3iyQ","jiVBPlViBv","QssNC0YAGH","GrDg7aFFss","cL0aEcmXIX","uPX7GY1mC0","lsQGoB3qem",
-"8FmFHfLNg8","618DiJKWYR","cmXIXgtCA5","uJScXjfREu","GWqqXn8pJ9","ru4UG1LB1L","JKWYRCp3mZ","zHF1q2Nslm","9GXkXMojnP","WMiS39y4lw",
-"tuDySQworu","VIlwPiB08l","rKDLJHP433","tjQxsciuWz","uAWyptl72W","9XyT9WMiS3","ZuDtDcShY2","KsjRKW3VFH","Q6Lixix74r","Pb1pazz4ZU",
-"8U2nUMGlTF","euZA5piJSk","J2mQiksJby","2TRI7QClRL","DLhzMFPfSE","AXpwE9eoRc","UlU3MsqVrf","FxX9qMmsIo","faHirx3LDe","29QAzpmeCd",
-"6AFT0C2Irc","o8Uydrz7Ut","0h1b1ix74r","ZUnqtAIYUu","TCgPpcQOnv","9GXkXZJTXH","8cVD3WPmlx","dQ586hi5X7","he9IAciuWz","6q6L9rz7Ut",
-"mX2GE9iGoT","9eoRcWPmlx","blLA9wDajX","2hEEUGWqqX","ulk41atef2","ZJTXHs93Ml","aez9yZv7z0","uAWyp3weIF","7X3uytlILt","9XyT9lViBv",
-"FGzgplH1kt","O3iyQTwano","yToGWulk41","pT8wuRkQke","OxWIHiwzGk","XflUqaDGtS","HRxd8uZPqg","i3pydyToGW","9eoRcXflUq","VIlwPD6rBy",
-"v2eC3F6PT2","7Ow5C2DREs","7hyVv45cIH","SbRYyeuZA5","HlUbFa00b5","NAFuwrhl0J","Z4I1vbgJAz","5IhmGOUYuF","vkCHHIRh48","JRJQB2Yz7E",
-"9XyT9ogLgc","uupzk16lHc","lpF6Wmz8gx","pWiOsCxVEf","WmadApAhR1","fcJOyO3iyQ","CdyBVFcWrW","IRh48s93Ml","nnP8oRxrsm","pFrrlVerEA",
-"vOqCEOz8yZ","7Ow5Ct59lR","6q6L90Wr5y","QChxsD6rBy","DLhzMMkgy8","pv0i7YjB9t","MmKGJyluBx","4W0TlEOE1o","Dz1R3NcICA","uZPqgXyPZN",
-"W3VFHjSjS3","gjUTusx5Gl","WmadASjskQ","WmadAaDGtS","FNYIMQChxs","uPX7GtaOXK","HzZT8WDVWJ","OxWIHlCMxy","bgJAzdpe1v","5nmWvYf2Ec",
-"pT8wu2ZHdk","x3LDeeuZA5","7lUXZQssNC","AIYUuVprf2","QClRL4QMc9","GWqqXTa8f6","tl72WIBe8k","gjUTuhi5X7","piJSkCqqaD","KASQ82TRI7",
-"JXljWatef2","CdyBVlXFOB","oVQp6hE1Ql","v1HlnWPmlx","pT8wuiwzGk","suY4x9y4lw","LewvMZzJHW","taOXKWMiS3","Ta8f6aDGtS","RBhp0Yw2oU",
-"ulk41DLhzM","9XyT9lH1kt","dpe1vhi5X7","Q6LixaL6AJ","ZzJHWRxrsm","jtn0Xulk41","55rfBVprf2","5nmWvKZamH","CNHmvdjsrv","W7cTsEoToP",
-"hYBCKlCMxy","J2mQit59lR","GSQwjHfyNQ","uTacxEOE1o","HRxd8IjTwP","Zv7z0uPX7G","euZA5fmIK1","uZPqgtuDyS","fcwDa0h1b1","Ul4a1hUTw7",
-"B3qemlXFOB","CIShG7ku1p","BCxeCChuy3","rKDLJuvf7A","NhXdu5Namm","Uvlv4PYBf4","kB5nPWaWsv","CK5W7OUYuF","1j5L8zY1GY","7lUXZzQt6Q",
-"vkCHHVerEA","Oz8yZSbRYy","RxrsmYw2oU","tjQxs4W0Tl","taOXKcL0aE","WreyP7fsYM","guMb8x3LDe","brhlQkB5nP","8xEKz1v5hH","s7MxkyofH3",
-"0YAGHHfyNQ","Yh1hF64s8N","RsQUqdQ586","BpYhVW3VFH","oGu6xhi5X7","LbRTHBGaQY","WmadAZJTXH","BbwgAfFDrJ","JIqXid85a9","QClRLZUnqt",
-"8hJdtFLsph","9GXkX0ao3l","FNYIM3weIF","WmadAoGu6x","jtn0XRsQUq","mz8gxlViBv","oGu6xNo0Qb","LDk6fCK5W7","2hEEUBFkb8","hi5X7SbRYy",
-"fLNg82ZHdk","hUTw7hi5X7","CqqaDgtCA5","M3zXLFxX9q","zY1GYxReec","faHirK20wK","FjHXRdmoS7","n1pmOKASQ8","2ZHdkJRJQB","8U2nUfmIK1",
-"HP4339XyT9","DLhzM7fsYM","9GXkXNAFuw","MmKGJyEfy9","1v5hHpT8wu","D6rBySbRYy","X6PinTXQ0Z","KASQ8QssNC","uoStwsuY4x","zz4ZUFLsph",
-"fmIK1QbxXc","kB5nPjiVBP","VIlwPlpF6W","Chuy3JKWYR","qQxHP16lHc","0BmCyPb1pa","9rlg9tvdkD","2Yz7E07n1c","LDk6fECMvU","AmdQdpFrrl",
-"pFrrlTXQ0Z","lj07QYf2Ec","8cVD3VLTy6","Vprf2KASQ8","cShY2iqv4k","uvf7Aatef2","gjUTu4dEz6","vLsmSOz8yZ","5ZaEz5nmWv","FFDuiIRh48",
-"lkMUAhi5X7","vOqCEpWiOs","0KyfsoVQp6","i3pydOUqFM","d7vjMnlaBy","gtCA5pFrrl","Waim6AOgEe","guMb8JIqXi","cShY2nlaBy","MojnPv8yFN",
-"HRxd8zY1GY","k85AeHfyNQ","iqv4kxReec","YOfrYogLgc","gIYvEsuY4x","dhSuHFNYIM","W7cTscShY2","dQ586uoStw","bZLvSQClRL","M6qcGVerEA",
-"okgRiYh1hF","X6PinyluBx","LbRTHv8yFN","Q6Lix7fKYU","Y1mC0aFFss","Cp3mZdhSuH","lweGyHfyNQ","QChxsi7WMQ","uN6r3ZuDtD","XyPZNXyPZN",
-"bZLvSCdyBV","KZamHxciqp","2hEEU5ZaEz","xciqpLbRTH","Yh1hFuQIcz","iB08lFwEJz","0BmCyWmadA","2DREsLbRTH","0BmCyRkQke","ru4UG9y4lw",
-"8hJdtpmeCd","lCMxycmXIX","euZA5oVQp6","cL0aE1j5L8","VerEAni2v1","CNHmvQ6hMC","lkMUAQWxoT","gf8rITwano","WDVWJSjskQ","C2IrcFNYIM",
-"lweGy3weIF","m4bxUPOUYS","BbwgA45cIH","TCgPp8U2nU","zbIYYPYBf4","POUYSuTacx","Chuy3Kr8ys","Q6hMCh1zcH","0BmCyTa8f6","OUqFMuTacx",
-"aez9y5Mg9r","v1HlnfaHir","Vprf2nnP8o","Nxx9VRBhp0","KASQ8JXljW","qaofNDQimp","3otm6YjB9t","F6PT2tvdkD","sx5Glo8Uyd","FPfSEHzZT8",
-"nlaByYf2Ec","tl72WCfgr3","qQxHPRBhp0","Mkgy8NcICA","lm0pDiB08l","d7vjMlm0pD","blLA9AgJHQ","hUTw7FLsph","yToGWTwano","UmaEvFcWrW",
-"RpBQmMm8si","nlaBylkMUA","Nxx9VRxrsm","DG4sTCxVEf","AIYUudpe1v","5ZaEzS2Dfu","K20wKVjCZq","d85a9ciuWz","Q6LixUl4a1","2TRI7cL0aE",
-"FhtglRxrsm","gtCA5b29RJ","QClRLxReec","FPfSE4dEz6","CxVEf8hJdt","fFDrJS77LH","hSSvQhi5X7","QworutjQxs","8RCUA45cIH","0YAGHJIqXi",
-"IKxdLgIYvE","5ZaEzFcWrW","LbRTHyToGW","cL0aEVjCZq","qQxHPFVMxo","JJs5mbgJAz","okgRisx5Gl","Mm8sizQt6Q","CK5W7FnPFB","zbIYYOz8yZ",
-"YjB9tTwano","NhXduxReec","24ARFgdQsS","YOfrYSmGzv","CqqaDkB5nP","TXQ0Z2TRI7","QChxsuQIcz","zY1GYGXdoH","ix74ruJScX","lsQGo14FLR",
-"VBjhzW3VFH","oQ87rGv3Fq","s7Mxkuupzk","CxVEfW3VFH","7hyVvy94nw","ReKEWDQimp","AXpwENo0Qb","t59lRMmKGJ","QClRL5drc6","azIWpWaim6",
-"zFgtBi7WMQ","KsjRK7ku1p","Mm8si24ARF","BpYhVMmsIo","atef2XyPZN","Ta8f6NcICA","MojnPrhl0J","8TxD7VjCZq","CNHmvQssNC","NOHszlm0pD",
-"sqVrfFNYIM","5VZjSK20wK","uQIcz0ao3l","CK5W7QnJ1S","64s8N8RCUA","NOHszMojnP","e6e4zYh1hF","kZANmFLsph","tvdkDPb1pa","Zv7z0uupzk",
-"Mm8siLDk6f","qUJMduJScX","uN6r3zY1GY","ru4UGQChxs","BFkb8bZLvS","AgJHQUmaEv","taOXKgjUTu","NOHszLDk6f","uZPqg618Di","W3VFH0Kyfs",
-"JKWYRoVQp6","aFFssnFqik","SmGzvlsQGo","aez9yv2eC3","lj07QJJs5m","sx5GlHfyNQ","ZUnqt5IhmG","RzaZAtaOXK","AkKTkIjTwP","55rfBblLA9",
-"M3zXLlXFOB","OUYuFRpBQm","wiHrZjS1aj","WDVWJrz7Ut","zHF1qSWfou","okgRiMojnP","fLNg8WaWsv","55rfB8FmFH","FNYIMazIWp","he9IAVprf2",
-"JIqXicQOnv","b29RJnnP8o","3weIF2TRI7","ECMvUqUJMd","EoToPrhl0J","DLhzMhE1Ql","618DiMezSW","FGzgpwiHrZ","5Drn0KZamH","WMiS355rfB",
-"pFrrlhYBCK","prNT6qUJMd","2hEEUiwzGk","64s8NpFrrl","kZANmpvgjS","Waim6RsQUq","VIlwPnlaBy","vLsmSTCgPp","bgJAzJKWYR","IKxdLFxX9q",
-"Mm8siuoStw","KZamHpAhR1","X6PinKZamH","580YD0BmCy","nnP8okB5nP","y94nwaDGtS","ReKEWPYBf4","uQIcz8RCUA","cShY2RkQke","n1pmOQnJ1S",
-"Mm8sikZANm","i3pydqaofN","5NammWDVWJ","ni2v1G1RhS","FhtglMmsIo","AOgEeRxrsm","5nmWvm4bxU","Mm8siWreyP","zHF1qIjTwP","Q6hMCYw2oU",
-"he9IAAXpwE","yofH35ZaEz","6q6L9DcpWB","uN6r36AFT0","uN6r3uN6r3","FGzgpGXdoH","xciqpFhtgl","Z4I1v48cHL","zQt6Qjtn0X","Pb1paxReec",
-"5Mg9rnlaBy","ix74rsoy9t","d7vjM4dEz6","Cfgr3OHaBz","pFrrlzqH0W","DQimpd85a9","0Kyfs9eoRc","kB5nPLDk6f","MojnPM3zXL","suY4xB3qem",
-"M6qcGjzUqR","Cp3mZnlaBy","WDVWJjtn0X","jtn0XMmKGJ","14FLRxReec","VjCZqzmLYD","FLsphLDk6f","OUYuFrKDLJ","KZamHZUnqt","IBe8kTCgPp",
-"K20wKMezSW","0YAGHLDk6f","Chuy3POUYS","yvOMIuupzk","8FmFHNOHsz","ogLgcQssNC","CqqaDvOqCE","0ao3lnlaBy","GSQwjhi5X7","X6PinMGlTF",
-"K4GS8CIShG","mX2GEHzZT8","Q6Lix0Kyfs","0PktIDG4sT","580YDaFFss","zz4ZU24ARF","t98iWtlILt","yofH30BmCy","9eoRcW3VFH","hYBCKlpF6W",
-"kZANm2hEEU","brhlQxXTI4","5VZjSlj07Q","dmoS7ZzJHW","RACujEdBKc","29QAzsuY4x","MojnPxciqp","ru4UGi3pyd","2Yz7EZzJHW","Z4I1vbrhlQ",
-"jtn0Xi7WMQ","FcWrW8xEKz","pWiOsi7WMQ","gf8rItl72W","29QAz55rfB","GXdoHWMiS3","tvdkDfLNg8","MezSWQWxoT","LewvMQworu","guMb8gdQsS",
-"GXdoHStlDJ","ECMvUHlUbF","2DREsJ2mQi","VIlwPF6PT2","oVQp6TXQ0Z","LewvM618Di","Q6hMCNhXdu","vLsmSvOqCE","t59lRI7p2a","lsQGoTCgPp",
-"Dz1R3EOE1o","jiVBPhSSvQ","MGlTFFxX9q","wiHrZ7lUXZ","G1RhSGXdoH","RzaZAPb1pa","ZuDtDCp3mZ","d7vjMsqVrf","uvf7AoGu6x","uJScXoGu6x",
-"FnPFBHP433","VBjhzDQimp","hi5X7VjCZq","2TRI716lHc","tuDyS8U2nU","m4bxUa00b5","MGlTFP6bcg","JkzUniKqhr","0BmCyVerEA","wDajXtl72W",
-"Cp3mZlViBv","qUJMdogLgc","a00b52hEEU","tlILtS77LH","5ZaEzTCgPp","lViBvYjB9t","iqv4kWmadA","fmIK1GSQwj","LbRTH45cIH","a00b5jS1aj",
-"580YDGSQwj","x3LDedhSuH","MK07Y1j5L8","NhXduzqH0W","jzUqROz8yZ","S77LHcQOnv","lkMUAtjQxs","pT8wu2TRI7","v1HlnydG8U","7hyVvn8pJ9",
-"okgRiXyPZN","mz8gxLbRTH","8FmFHKsjRK","nlaByzHF1q","ciuWzCp3mZ","DQimpqQxHP","uJScXhSSvQ","taOXKUvlv4","9eoRciqv4k","M6qcGblLA9",
-"cmXIXhi5X7","RxrsmqaofN","FFDuid7vjM","DG4sTtuDyS","5VZjSrhl0J","XflUqiB08l","zFgtBnlaBy","uN6r3jiVBP","Cfgr35Namm","8TxD7sx5Gl",
-"lsQGogjUTu","GrDg7FLsph","kB5nP4W0Tl","CqqaDqUJMd","m4bxUpv0i7","29QAzuAWyp","ECMvUyluBx","IRh48WreyP","cShY2aDGtS","FwEJzQbxXc",
-"FhtglVNCPd","2Yz7ElViBv","StlDJzqH0W","pv0i7PYBf4","okgRisuY4x","UlU3MW3VFH","ZUnqtv1Hln","7ku1p2DREs","Y1mC0azIWp","cQOnvK4GS8",
-"jS1ajAmdQd","ulk41NhXdu","Ul4a1EdBKc","jSjS3iwzGk","Gv3FqQ6hMC","WDVWJwiHrZ","1j5L8uN6r3","8FmFHcmXIX","MmsIot98iW","Mkgy8B3qem",
-"Z4I1vpvgjS","tAOsrUl4a1","EOE1opv0i7","IKxdLLbRTH","9XyT9Waim6","zz4ZUIBe8k","DG4sT07n1c","jS1ajsuY4x","gtCA5zz4ZU","Gv3FqFLsph",
-"uLtKsjfREu","FVMxoiqv4k","ydG8Uuupzk","SmGzvW7cTs","HRxd8zqH0W","uupzk4QMc9","CIShGn8pJ9","zbIYYUmaEv","soy9tQworu","ECMvUoQ87r",
-"UmaEv9GXkX","jS1ajCNHmv","D6rByru4UG","ru4UGRsQUq","fLNg8hUTw7","prNT6t98iW","StlDJK4GS8","m4bxUyToGW","AkKTk2Yz7E","8RCUAwDajX",
-"ydG8UOz8yZ","48cHL4QMc9","MaJQsIKxdL","C2IrcdhSuH","jeskSTa8f6","VIlwPjzUqR","5drc6NcICA","hE1QlpvgjS","TXQ0Z7ku1p","Vprf2O3iyQ",
-"29QAz4dEz6","45cIH2Nslm","Q6hMCgjUTu","aFFss7ku1p","lsQGoeuZA5","atef2dmoS7","jSjS3S77LH","cL0aEnlaBy","fLNg8jS1aj","WmadAMaJQs",
-"oQ87rvOqCE","ZhwG1zbIYY","jeskSuLtKs","Yh1hFJkzUn","gIYvEm4bxU","Zv7z02ZHdk","oVQp6iwzGk","O3iyQ8RCUA","MojnPnFqik","vkCHH3otm6",
-"0MR5XdhSuH","FLsphfLNg8","IjTwPY1mC0","BpYhViqv4k","9GXkXiqv4k","xXTI4BpYhV","ECMvUogLgc","tl72WDcpWB","FGzgp4W0Tl","VBjhzJKWYR",
-"0h1b13weIF","FhtglZ4I1v","FLsphL7cGc","d85a9JIqXi","4QMc93weIF","XyPZNfmIK1","hi5X7W3VFH","piJSk64s8N","IjTwPD6rBy","fqypyGv3Fq",
-"tl72W2Nslm","WMiS3BGaQY","qaofNd7vjM","pAhR1Ss0Zu","euZA5RzaZA","Fhtgl8cVD3","pAhR1qaofN","ECMvUQClRL","aDGtSYw2oU","5ZaEzpFrrl",
-"uoStwMaJQs","9XyT9AgJHQ","7X3uyaFFss","soy9tD6rBy","lViBvcmXIX","CdyBVtlILt","2TRI7MGlTF","faHirLbRTH","RsQUq7fKYU","S77LHKZamH",
-"pv0i7tlILt","ulk41MezSW","zz4ZUTwano","6AFT0vLsmS","JkzUndhSuH","zmLYDnlaBy","MaJQs2ZHdk","o8UydUvlv4","l83Ud7Ow5C","EoToPxXTI4",
-"sx5GlIjTwP","lj07Qs7Mxk","9XyT9GrDg7","U3yw5JJs5m","VBjhzix74r","jtn0XcmXIX","tlILtNhXdu","VLTy6d85a9","hYBCKGSQwj","prNT6FxX9q",
-"CdyBVcQOnv","uPX7G0BmCy","9iGoTK4GS8","Cp3mZQYxC0","ThjNnJkzUn","yluBxTXQ0Z","sqVrfAOgEe","gtCA57Ow5C","2ZHdknnP8o","BFkb8jSjS3",
-"yluBx0ao3l","cQOnvdpe1v","MojnP618Di","64s8NOUYuF","ThjNnIKxdL","NhXduZJTXH","tlILtY1mC0","IBe8kUl4a1","jSjS3lweGy","IjTwPn1pmO",
-"MaJQsdmoS7","wDajXWmadA","vLsmS0BmCy","16lHcWPmlx","MaJQsjeskS","t98iW2ZHdk","uoStwUmaEv","TCgPpWaim6","JXljWOz8yZ","tl72WVprf2",
-"ThjNna00b5","sqVrfzqH0W","HRxd8aez9y","HP433SbRYy","rKDLJ5Drn0","No0QbD6rBy","4dEz614FLR","SjskQIRh48","fcwDapFrrl","suY4xt59lR",
-"B3qemuN6r3","mX2GEGWqqX","YOfrYoQ87r","oGu6xy94nw","ydG8UprNT6","Cp3mZ5ZaEz","jiVBP4W0Tl","uTacxmz8gx","aL6AJVprf2","2TRI7QbxXc",
-"0YAGH6q6L9","KsjRKhUTw7","Q6LixuJScX","b29RJni2v1","xciqpBGaQY","B3qemFGzgp","OUYuF5Drn0","MmKGJTCgPp","QworuWPmlx","3weIFXyPZN",
-"gf8rIRzaZA","sqVrfMm8si","B3qemo8Uyd","taOXKJRJQB","v1HlnogLgc","FwEJz8FmFH","t59lRSbRYy","hi5X7FGzgp","Yw2oUYjB9t","hE1QljzUqR",
-"cmXIXzz4ZU","jfREutlILt","GWqqX5IhmG","1v5hHiwzGk","BFkb8FVMxo","MojnPlkMUA","QClRLPb1pa","O3iyQrhl0J","aez9y07n1c","uupzkuAWyp",
-"Dz1R37Ow5C","uPX7GYw2oU","9XyT9cmXIX","o8UydCxVEf","BFkb8Cfgr3","Kr8ysaez9y","RsQUqQ6hMC","4W0Tl8TxD7","RsQUqgtCA5","aL6AJMmKGJ",
-"dQ586MGlTF","nnP8o07n1c","bgJAzqQxHP","0Wr5yqQxHP","a00b5aDGtS","jtn0XW3VFH","lkMUAMm8si","yEfy9WaWsv","P6bcgYh1hF","uvf7AnnP8o",
-"CIShG14FLR","FhtglzHF1q","NcICAzbIYY","lm0pDrz7Ut","MezSWBGaQY","K20wKpWiOs","5nmWvyToGW","fFDrJB3qem","4QMc9oQ87r","a00b5s4786",
-"MezSWni2v1","5nmWvuAWyp","t59lRtuDyS","5iGN5CxVEf","7Ow5CK4GS8","0h1b1sqVrf","FGzgp16lHc","GSQwjOUqFM","MmsIocL0aE","2TRI7n1pmO",
-"M3zXLRBhp0","0Kyfsd7vjM","s7Mxkm4bxU","cQOnviqv4k","0h1b1WreyP","4QMc9ogLgc","WaWsv5IhmG","OUYuFChuy3","fqypypAhR1","ksJby5iGN5",
-"djsrvHRxd8","FnPFBCNHmv","EdBKclweGy","4QMc9FPfSE","v8yFNiB08l","BFkb8uoStw","DcpWB5Namm","Yh1hFOUYuF","X6Pin5drc6","7fsYMaez9y",
-"48cHLIjTwP","dhSuHjzUqR","EoToPLewvM","fqypyfaHir","16lHc9rlg9","Gv3FqSs0Zu","HRxd8yEfy9","P6bcgiwzGk","nlaByUmaEv","pmeCdP6bcg",
-"JkzUnG1RhS","s7MxkOUqFM","cmXIX4W0Tl","YOfrYJXljW","8TxD7VBjhz","HzZT8ECMvU","MmsIo2Yz7E","VjCZqMm8si","jfREuIRh48","lViBvX6Pin",
-"lkMUA8xEKz","Mkgy82ZHdk","BbwgA5Drn0","9GXkXOUqFM","v1Hlnpv0i7","S2DfuS2Dfu","Q6LixMkgy8","faHiryofH3","TXQ0ZaL6AJ","9eoRcpvgjS",
-"tuDySs4786","7lUXZaL6AJ","oVQp67fKYU","fcwDa9XyT9","IKxdL0ao3l","oQ87rRxrsm","XflUqQYxC0","G1RhSDz1R3","bZLvSvLsmS","SjskQOxWIH",
-"CqqaDgIYvE","rKDLJRzaZA","tuDySMK07Y","zFgtBmX2GE","faHir8FmFH","5IhmGHfyNQ","jzUqREdBKc","YjB9tiB08l","07n1cXflUq","ix74rC2Irc",
-"OUqFMzmLYD","5ZaEzIn3NS","tuDySoGu6x","faHirDG4sT","CdyBVxReec","C2Irc14FLR","M6qcG2hEEU","AmdQdjtn0X","n8pJ9uvf7A","0YAGHn8pJ9",
-"v1Hlnlj07Q","5VZjS2TRI7","JRJQBSs0Zu","zFgtB7lUXZ","5Drn0VerEA","2ZHdkCfgr3","1LB1L7lUXZ","s47861v5hH","5VZjSrKDLJ","s93Ml7Ow5C",
-"DLhzMpAhR1","VIlwPlCMxy","FVMxoOz8yZ","0MR5XjS1aj","aFFssxXTI4","yluBxNcICA","iB08lk85Ae","3weIFAmdQd","IRh48AXpwE","o8UydRxrsm",
-"mz8gxmz8gx","4dEz6O3iyQ","kB5nPS2Dfu","ni2v1CIShG","2hEEUblLA9","5VZjSMGlTF","PYBf45ZaEz","pWiOsd85a9","M3zXLCK5W7","Pb1paC2Irc",
-"n8pJ95Mg9r","JXljW4dEz6","s7Mxkgf8rI","wiHrZYw2oU","YjB9t8RCUA","FGzgpNcICA","jzUqRStlDJ","7fsYMOUqFM","gdQsSIBe8k","FjHXRs7Mxk",
-"64s8NEoToP","a00b5zY1GY","HzZT8IKxdL","0YAGHpFrrl","0ao3lIjTwP","POUYSyofH3","3otm6lsQGo","iqv4kuvf7A","tAOsr618Di","e6e4zlkMUA",
-"vLsmSblLA9","b29RJBGaQY","aFFssFjHXR","9eoRc4dEz6","M3zXLuQIcz","64s8Niqv4k","24ARF5drc6","FxX9qWMiS3","piJSkhi5X7","VBjhzM6qcG",
-"lpF6WCfgr3","B3qemdhSuH","ulk41faHir","HzZT88U2nU","GSQwjiwzGk","AmdQdIn3NS","QbxXcyToGW","FLsphNcICA","C2Irchi5X7","MGlTFRBhp0",
-"uupzkulk41","MmsIoBFkb8","pWiOsrhl0J","pvgjSIKxdL","euZA5sqVrf","VBjhzSmGzv","ksJbyd85a9","uPX7Guvf7A","WmadAlj07Q","QClRLfqypy",
-"EoToPxciqp","K20wKs7Mxk","xciqpStlDJ","OUqFMCp3mZ","J2mQiAmdQd","lm0pDqQxHP","I7p2aCK5W7","Gv3FqfaHir","s93MlFxX9q","zY1GY5Namm",
-"2ZHdkAIYUu","kZANmydG8U","FcWrWSjskQ","GSQwjF6PT2","7lUXZsqVrf","OUYuFZv7z0","cQOnvpvgjS","vOqCElweGy","fFDrJNhXdu","Pb1paYh1hF",
-"oGu6x5IhmG","TwanoTa8f6","gtCA5Nxx9V","AgJHQhi5X7","Chuy3s7Mxk","zHF1q7lUXZ","L7cGc9iGoT","Cfgr37fKYU","9GXkX07n1c","5Drn0Zv7z0",
-"Mm8siiqv4k","gIYvEuoStw","rhl0JRzaZA","6AFT0zbIYY","l83Udulk41","RzaZAzFgtB","KZamHZJTXH","UlU3M0MR5X","uAWypVjCZq","0ao3lvkCHH",
-"rz7UtQworu","WDVWJZUnqt","9XyT9SbRYy","QYxC0FNYIM","gjUTus7Mxk","OxWIHsoy9t","5VZjS0Wr5y","ix74rMaJQs","gtCA5kB5nP","QssNClH1kt",
-"tAOsrLewvM","ZuDtDO3iyQ","TwanouTacx","VLTy69rlg9","IBe8k0PktI","DcpWBlXFOB","MaJQstuDyS","EoToPXyPZN","Twano5VZjS","Oz8yZRsQUq",
-"9rlg9nlaBy","HRxd8Uvlv4","2NslmqQxHP","zmLYDzFgtB","EoToPFwEJz","oQ87rIKxdL","Yh1hFzQt6Q","LDk6fEOE1o","MmsIoSmGzv","NcICAnlaBy",
-"he9IAPYBf4","AkKTk2Nslm","Q6hMCjiVBP","CdyBV8cVD3","gIYvEt59lR","dpe1vM3zXL","fmIK1CIShG","ru4UGCIShG","LDk6fpmeCd","8cVD3Twano",
-"ru4UGxReec","pWiOs9GXkX","lH1ktv2eC3","zqH0WaFFss","ulk41QWxoT","piJSk45cIH","prNT6JRJQB","zmLYD8U2nU","RsQUqd7vjM","QChxsRzaZA",
-"WaWsv9XyT9","6AFT0s93Ml","8RCUAX6Pin","WDVWJNcICA","uPX7GFhtgl","0PktIv1Hln","a00b5Pb1pa","uZPqgtjQxs","ZJTXHzz4ZU","hSSvQ4dEz6",
-"pv0i7oVQp6","QnJ1S4QMc9","3weIFFnPFB","P6bcghi5X7","QClRLzY1GY","GXdoHSjskQ","SjskQ9eoRc","uZPqgP6bcg","FjHXRAXpwE","LewvMhE1Ql",
-"45cIHcQOnv","v1HlnRACuj","k85AeBGaQY","rhl0JNhXdu","azIWp0h1b1","iKqhrZzJHW","RACujzqH0W","0PktI2Nslm","vkCHHk85Ae","gIYvEOUYuF",
-"i3pydn1pmO","hE1Qlmz8gx","W7cTszHF1q","KASQ8CNHmv","WDVWJgdQsS","24ARFjeskS","LewvMNhXdu","KsjRKFFDui","LewvMni2v1","9iGoTs93Ml",
-"iwzGkvkCHH","LbRTHni2v1","ru4UGzqH0W","Pb1paSjskQ","sqVrfMmKGJ","OHaBzECMvU","lj07QMmsIo","6AFT0gdQsS","rKDLJcL0aE","618DiNOHsz",
-"FcWrWTXQ0Z","AmdQdaez9y","B3qemZv7z0","wiHrZIjTwP","bZLvS14FLR","hYBCKzmLYD","CK5W7Ss0Zu","he9IAZzJHW","0KyfsM6qcG","Ta8f63otm6",
-"yluBxrKDLJ","Ul4a1dmoS7","M3zXLix74r","brhlQ45cIH","7lUXZOz8yZ","HRxd8zz4ZU","Vprf2o8Uyd","kZANm618Di","14FLROUqFM","jtn0XFGzgp",
-"yToGWAkKTk","5nmWvFPfSE","No0QbOz8yZ","uJScXOUqFM","zFgtBJKWYR","DLhzMVerEA","tuDySqUJMd","5NammuQIcz","1LB1L29QAz","jeskSLewvM",
-"1LB1LogLgc","xReectlILt","M3zXLdQ586","kZANmhSSvQ","mz8gxlH1kt","07n1cvLsmS","FVMxoQWxoT","WDVWJFVMxo","tAOsrSjskQ","pFrrlsuY4x",
-"d7vjMS77LH","P6bcgYw2oU","pT8wuWDVWJ","FPfSExciqp","U3yw5tjQxs","wiHrZCxVEf","Q6hMCtl72W","YjB9tlH1kt","fmIK1sqVrf","t59lRVLTy6",
-"2hEEUtuDyS","soy9tsuY4x","wDajXBpYhV","VIlwPVerEA","6q6L9o8Uyd","55rfB0Kyfs","Ta8f6XflUq","cQOnvW7cTs","ReKEWRzaZA","wDajXi7WMQ",
-"tjQxspFrrl","RACuj2Yz7E","prNT6v2eC3","K4GS8QbxXc","BGaQYgjUTu","I7p2a5nmWv","Q6LixDz1R3","TCgPpogLgc","FcWrWl83Ud","16lHcKASQ8",
-"JkzUnNAFuw","yluBxi3pyd","uN6r3lXFOB","bgJAzI7p2a","OUYuFpv0i7","Gv3FqhUTw7","xciqp16lHc","MezSWfFDrJ","IBe8khe9IA","OHaBzKASQ8",
-"5Drn0RACuj","JXljWFFDui","hi5X7RACuj","VIlwP9GXkX","1j5L8tl72W","4W0TlfcwDa","yToGWC2Irc","s93MlVBjhz","jS1ajcL0aE","iB08lJJs5m",
-"zFgtBKZamH","2Yz7Ei7WMQ","faHirMaJQs","cShY25Drn0","ydG8UcmXIX","zqH0WmX2GE","0MR5XMm8si","iKqhryvOMI","KZamHUvlv4","HRxd8lweGy",
-"5VZjSBpYhV","HRxd8Yf2Ec","ni2v1WMiS3","jiVBP5ZaEz","RACuj580YD","gf8rIBCxeC","16lHcuvf7A","TCgPplViBv","CqqaDStlDJ","NAFuwksJby",
-"FPfSED6rBy","5iGN58xEKz","4W0TlazIWp","MK07YqaofN","v2eC3AmdQd","vOqCEFLsph","CqqaDThjNn","MK07YL7cGc","sx5GlQ6hMC","NAFuwMojnP",
-"ZhwG12Yz7E","oGu6xd85a9","aFFssCdyBV","Ta8f6cmXIX","ix74rZUnqt","wDajXdjsrv","CxVEf9y4lw","prNT6RmDcr","5Drn0jzUqR","Q6hMCru4UG",
-"GWqqXjfREu","ydG8UvkCHH","lH1kt5Drn0","l83UdYh1hF","Chuy3KASQ8","5ZaEzlH1kt","G1RhSbZLvS","a00b5ru4UG","KsjRKTCgPp","D6rByY1mC0",
-"WmadA5nmWv","SjskQjSjS3","ZJTXHGrDg7","KZamHMmKGJ","9rlg9In3NS","ni2v1uZPqg","0Wr5yPOUYS","9XyT9RpBQm","RACuj8RCUA","LewvMaFFss",
-"yToGW2Nslm","IBe8kZUnqt","soy9tiwzGk","n8pJ9pv0i7","v2eC3WaWsv","xXTI49GXkX","ru4UGqUJMd","uupzk9rlg9","8cVD3qQxHP","e6e4zRmDcr",
-"x3LDe48cHL","iwzGk45cIH","QChxscL0aE","C2Irc8xEKz","48cHLwDajX","Yw2oUWaim6","oQ87r55rfB","jSjS3Uvlv4","No0QbqaofN","oGu6xpFrrl",
-"Cp3mZh1zcH","TXQ0ZFPfSE","5VZjSQ6Lix","v2eC3HfyNQ","h1zcHQ6Lix","tlILtSs0Zu","k85AedQ586","7ku1ptaOXK","X6Pin7lUXZ","VBjhzvLsmS",
-"fcwDaO3iyQ","gtCA5FnPFB","OUqFMK4GS8","0ao3lECMvU","QnJ1SDG4sT","VjCZqru4UG","SbRYyfmIK1","0Wr5ytuDyS","DcpWBfFDrJ","2TRI7OxWIH",
-"ZJTXH8U2nU","fFDrJCqqaD","hYBCKzY1GY","xReeclm0pD","VerEAiqv4k","ogLgcChuy3","nlaByYw2oU","vkCHHDLhzM","uZPqgfmIK1","aL6AJfFDrJ",
-"8FmFHAkKTk","Z4I1vuLtKs","NhXdujfREu","Pb1paY1mC0","Oz8yZIBe8k","aFFssGWqqX","WPmlxRpBQm","qQxHPJKWYR","KASQ8BGaQY","8cVD37fsYM",
-"Rxrsms93Ml","ZhwG1gdQsS","Cp3mZ5Namm","Kr8ysrhl0J","lm0pDG1RhS","SmGzvfcJOy","G1RhSlCMxy","1v5hHuvf7A","7X3uyWreyP","HzZT85VZjS",
-"VIlwP3otm6","8TxD7AOgEe","v8yFNzqH0W","FwEJzprNT6","CIShGt98iW","7Ow5C0h1b1","lpF6W16lHc","9y4lwQnJ1S","xReecTXQ0Z","djsrvKASQ8",
-"cL0aEtjQxs","GSQwjDG4sT","YOfrYIRh48","Oz8yZKsjRK","tlILtMmsIo","0YAGHOUYuF","8TxD7lXFOB","JRJQBRBhp0","SjskQlpF6W","ciuWzxciqp",
-"dQ586ReKEW","9XyT9FNYIM","BbwgAiB08l","DcpWB6q6L9","SbRYyMaJQs","DQimpzFgtB","HfyNQd85a9","TCgPpUlU3M","I7p2aP6bcg","sqVrftvdkD",
-"nFqikmX2GE","bgJAzuoStw","5NammoQ87r","n1pmOOUqFM","CqqaD0PktI","guMb8KASQ8","C2IrctaOXK","yEfy9CqqaD","8TxD7FLsph","YjB9tIjTwP",
-"MojnPzbIYY","wiHrZRACuj","9eoRci3pyd","FnPFBsqVrf","guMb8e6e4z","lCMxyJ2mQi","Gv3Fq3otm6","AIYUuFcWrW","24ARFW7cTs","MojnP4dEz6",
-"cQOnvGXdoH","7X3uyYw2oU","uTacxYjB9t","YOfrYnnP8o","lkMUAaDGtS","n8pJ9VerEA","0KyfsOz8yZ","iB08l8hJdt","NAFuwRzaZA","F6PT2ZJTXH",
-"8FmFH0Wr5y","KZamHulk41","7ku1p24ARF","ZuDtDYw2oU","gjUTuiqv4k","VerEAHP433","mX2GEkB5nP","LewvMFFDui","l83UdhSSvQ","jeskSfmIK1",
-"LewvMJXljW","l83UdMmKGJ","lweGyxXTI4","0KyfstlILt","VBjhzv8yFN","NcICAYOfrY","KASQ82hEEU","BpYhVRkQke","4dEz6cmXIX","WDVWJ16lHc",
-"J2mQiprNT6","NAFuwlH1kt","okgRizmLYD","TwanoyEfy9","wiHrZSWfou","euZA57ku1p","Pb1paL7cGc","6q6L9rhl0J","CK5W7vOqCE","lXFOBuoStw",
-"yvOMIyvOMI","zbIYYYw2oU","MK07Y3otm6","RACujbrhlQ","618DiuLtKs","8cVD38TxD7","6AFT0MmsIo","P6bcgRsQUq","Dz1R3WDVWJ","ciuWzsqVrf",
-"lm0pDVjCZq","55rfBtuDyS","7lUXZtuDyS","2hEEUfmIK1","a00b5soy9t","lkMUAiwzGk","hE1QlogLgc","CIShGQbxXc","KASQ8gjUTu","FcWrWa00b5",
-"VerEAWMiS3","Gv3FqRkQke","HRxd80MR5X","5ZaEzLewvM","uJScXrz7Ut","1v5hHsqVrf","v8yFN0Kyfs","AXpwEFGzgp","aL6AJRkQke","9rlg9KASQ8",
-"FhtglnnP8o","hSSvQNo0Qb","QYxC0LbRTH","hYBCKd7vjM","QChxsXflUq","WMiS3soy9t","X6PinfmIK1","qaofNOUqFM","uupzk9y4lw","ciuWzzbIYY",
-"4W0Tlv1Hln","kB5nPhSSvQ","pvgjSwDajX","RkQkeAXpwE","d7vjMtjQxs","O3iyQjS1aj","X6PinFLsph","GrDg7jtn0X","48cHLx3LDe","IBe8kStlDJ",
-"tl72WFVMxo","JXljWaFFss","OxWIHLDk6f","RsQUqlXFOB","XflUqsoy9t","gjUTuPYBf4","iwzGk7ku1p","jiVBP29QAz","0h1b1bZLvS","C2IrcK20wK",
-"WMiS3JRJQB","aL6AJbZLvS","jS1ajiB08l","Yw2oUCxVEf","tvdkDjtn0X","n1pmOK20wK","o8UydnFqik","aFFssMmKGJ","XyPZNLDk6f","dQ586In3NS",
-"SmGzvtAOsr","MGlTFqaofN","lH1kt8FmFH","ru4UGQssNC","S77LHhi5X7","fFDrJSs0Zu","7Ow5C2ZHdk","WaWsvOHaBz","7lUXZi7WMQ","S2DfuVBjhz",
-"a00b5iqv4k","dhSuHStlDJ","RsQUq64s8N","VIlwPi3pyd","zqH0WDz1R3","dQ586M6qcG","UlU3Msoy9t","cShY2xReec","pWiOsWaWsv","jtn0XGWqqX",
-"dpe1vv8yFN","Mkgy8hE1Ql","n1pmOLbRTH","VerEAgIYvE","rhl0JzQt6Q","ydG8UYOfrY","e6e4zFhtgl","MmKGJ2TRI7","Waim6ogLgc","WPmlx07n1c",
-"yEfy95ZaEz","piJSkRACuj","uTacxjfREu","uZPqglkMUA","cL0aEciuWz","blLA95ZaEz","s93Mlru4UG","Z4I1v16lHc","okgRiCfgr3","7lUXZRACuj",
-"zmLYDciuWz","ThjNnG1RhS","0ao3lIBe8k","LbRTHQnJ1S","OxWIHPb1pa","VerEAQbxXc","mz8gxMm8si","jS1ajM3zXL","sqVrfsx5Gl","OxWIHhUTw7",
-"5drc6l83Ud","SWfouguMb8","ZJTXHQbxXc","ZhwG1FLsph","dpe1v2TRI7","NAFuws93Ml","JKWYRbgJAz","uQIczdQ586","wDajXDQimp","fcwDa9rlg9",
-"zQt6QOHaBz","AOgEeAXpwE","sqVrfeuZA5","HfyNQOUqFM","EOE1oYOfrY","pvgjShi5X7","Waim655rfB","YOfrYa00b5","Zv7z0gf8rI","HRxd8vOqCE",
-"C2Irc9rlg9","K20wKoQ87r","RsQUqjeskS","7fsYMv1Hln","m4bxU4dEz6","tuDyS2Yz7E","uupzkWPmlx","ReKEWZUnqt","tlILt24ARF","7Ow5CNcICA",
-"Rxrsmrhl0J","DQimpK4GS8","K4GS8mX2GE","G1RhS5iGN5","iB08lfmIK1","K20wKs4786","h1zcHuN6r3","07n1cNOHsz","QssNCJKWYR","uN6r3i7WMQ",
-"oGu6xuoStw","RsQUqhi5X7","Ss0Zu0Kyfs","oVQp6ru4UG","W7cTsaL6AJ","iKqhr580YD","yvOMIuAWyp","BbwgA0PktI","O3iyQBpYhV","VNCPdh1zcH",
-"brhlQI7p2a","Gv3FqQ6Lix","RACuj8FmFH","7X3uyrKDLJ","3otm6nnP8o","5ZaEzUvlv4","yEfy9uupzk","pWiOsCdyBV","rKDLJbZLvS","VIlwPFNYIM",
-"NOHszhSSvQ","QClRL9rlg9","kZANmIKxdL","vLsmSlkMUA","cQOnvNOHsz","RsQUq24ARF","JRJQBjfREu","W7cTsb29RJ","8RCUA0BmCy","pvgjSEOE1o",
-"jeskS9XyT9","s93Ml55rfB","vLsmSVIlwP","t59lRpFrrl","pT8wuBFkb8","cmXIXWmadA","0h1b1RBhp0","fLNg8lkMUA","Kr8ysCqqaD","IBe8k4dEz6",
-"C2IrcWDVWJ","Q6hMCSbRYy","J2mQiRACuj","8RCUAs7Mxk","P6bcghe9IA","0PktIrKDLJ","9XyT92ZHdk","gf8rIDz1R3","Pb1pav1Hln","4W0TlZuDtD",
-"K4GS8IBe8k","5IhmGblLA9","JRJQBMm8si","pvgjSB3qem","7fKYUrz7Ut","pFrrlChuy3","qQxHPmz8gx","NcICAfqypy","5VZjS8cVD3","JkzUnbgJAz",
-"580YDMm8si","pT8wu7X3uy","ThjNnpiJSk","OUYuFm4bxU","29QAzSs0Zu","7Ow5CtaOXK","rKDLJEdBKc","WPmlxvOqCE","FhtglReKEW","SmGzvAOgEe",
-"B3qemtAOsr","zz4ZUcQOnv","t59lRUvlv4","FhtglGXdoH","Chuy3Ta8f6","O3iyQVerEA","jfREuD6rBy","XflUq8hJdt","euZA5FcWrW","zFgtBK20wK",
-"Waim69rlg9","AXpwERACuj","rKDLJuLtKs","pFrrluQIcz","K20wKuLtKs","0YAGH1j5L8","NhXduokgRi","MaJQs0YAGH","QbxXcaez9y","Gv3FqSWfou",
-"VBjhzyofH3","QnJ1S2hEEU","taOXKOUqFM","BGaQY8cVD3","5NammYw2oU","fLNg85ZaEz","yToGWDz1R3","m4bxUIjTwP","gIYvEni2v1","IKxdLlCMxy",
-"POUYSNcICA","zQt6Qhi5X7","SWfouaL6AJ","guMb8MmsIo","qUJMd55rfB","cShY2yvOMI","AOgEeSs0Zu","d85a9hSSvQ","aez9yfmIK1","DQimpa00b5",
-"Q6hMCqaofN","P6bcgNAFuw","WDVWJ7lUXZ","NhXduwDajX","JXljWU3yw5","ni2v15Mg9r","Mm8siuJScX","Ta8f6nlaBy","GSQwj0h1b1","gf8rIfcJOy",
-"FxX9qNAFuw","WDVWJ2hEEU","oVQp6m4bxU","618DiFwEJz","ReKEW1LB1L","2hEEUAXpwE","Chuy329QAz","yofH3QYxC0","n1pmOfcwDa","CqqaDhYBCK",
-"K4GS85iGN5","d85a9sqVrf","29QAzhe9IA","ogLgcoGu6x","HfyNQ1v5hH","yvOMIFGzgp","uJScXFwEJz","0YAGHWmadA","2TRI7HzZT8","aez9yUl4a1",
-"l83UdpAhR1","MmKGJQworu","wDajXHfyNQ","MK07YMmsIo","NAFuwiqv4k","uAWypx3LDe","lH1kt5VZjS","xReecThjNn","b29RJk85Ae","TCgPpF6PT2",
-"4dEz6m4bxU","yvOMIzFgtB","5Mg9r5Mg9r","MezSWuN6r3","dpe1vTXQ0Z","TwanoDQimp","F6PT2uJScX","zbIYYFnPFB","pvgjSQworu","16lHclm0pD",
-"SmGzvkZANm","3otm6qUJMd","b29RJpWiOs","Yf2EcRBhp0","DG4sTM3zXL","pvgjS9XyT9","7Ow5C7fsYM","aDGtSQ6hMC","2ZHdkD6rBy","lXFOBxReec",
-"K20wKsuY4x","IKxdLWaWsv","n1pmO1v5hH","x3LDeRxrsm","8hJdtIjTwP","OHaBzVBjhz","fcJOyFVMxo","OUqFMlH1kt","POUYSIBe8k","atef216lHc",
-"YjB9tbrhlQ","LDk6f9rlg9","uJScXpmeCd","FGzgpNOHsz","jfREucL0aE","9y4lw5nmWv","JkzUnzmLYD","xciqpTCgPp","Waim6qUJMd","24ARFO3iyQ",
-"580YDFjHXR","zmLYD4QMc9","lj07Q9iGoT","lweGyIKxdL","8hJdtG1RhS","lj07QQClRL","cmXIXIjTwP","FVMxod7vjM","oGu6xaez9y","2ZHdkCdyBV",
-"fcJOylj07Q","VLTy6618Di","v1HlnQ6Lix","RsQUqt59lR","iB08lSs0Zu","NAFuwaez9y","FhtglaDGtS","NhXduM3zXL","yEfy9OxWIH","pmeCdEOE1o",
-"EdBKcGv3Fq","XyPZN7fKYU","tjQxsOUqFM","IKxdLuupzk","QnJ1Sv1Hln","5nmWvblLA9","QnJ1SiKqhr","VIlwPZJTXH","aFFssCNHmv","16lHcIjTwP",
-"29QAzi7WMQ","i7WMQdpe1v","lj07QvLsmS","D6rBycmXIX","prNT6C2Irc","2ZHdkWaWsv","guMb8QWxoT","VIlwPlm0pD","k85AeMojnP","zbIYYuupzk",
-"RpBQmCdyBV","S77LHAkKTk","Y1mC0OHaBz","brhlQWreyP","bgJAztl72W","WDVWJtuDyS","l83UdK4GS8","jiVBPpvgjS","8TxD7BbwgA","FPfSEzY1GY",
-"2DREshe9IA","v1HlnJIqXi","Q6hMCtjQxs","ThjNnSbRYy","KsjRKgf8rI","m4bxUMezSW","QClRLMojnP","AOgEeQbxXc","HRxd8xXTI4","FwEJzDcpWB",
-"F6PT2YOfrY","dmoS7SWfou","FjHXRTa8f6","wDajXfcJOy","FVMxoBpYhV","Cp3mZCIShG","5VZjSHlUbF","Yw2oUrhl0J","i3pyd8RCUA","iKqhrDz1R3",
-"aDGtSoVQp6","vLsmSMkgy8","2NslmOxWIH","KASQ8FxX9q","k85Ae9eoRc","qQxHPpT8wu","8xEKzWDVWJ","fFDrJd85a9","hE1QlLDk6f","d7vjMYf2Ec",
-"tvdkDFGzgp","9rlg9ZzJHW","fmIK1SWfou","dpe1vguMb8","8cVD3uJScX","AkKTkMojnP","wiHrZBCxeC","HlUbFQ6hMC","uoStwx3LDe","uJScXlH1kt",
-"pFrrlJ2mQi","7Ow5Cl83Ud","OUYuF45cIH","YOfrYHRxd8","hSSvQRkQke","W7cTsn8pJ9","wDajXgIYvE","FVMxofmIK1","1j5L8PYBf4","pv0i7soy9t",
-"RsQUqU3yw5","45cIH0Kyfs","ogLgcjfREu","jzUqR5VZjS","ni2v1tAOsr","S2DfuZUnqt","RACujy94nw","jfREuUl4a1","cL0aEoVQp6","t59lRJIqXi",
-"8TxD7yEfy9","VLTy6HP433","5iGN5wDajX","zmLYDpiJSk","pmeCdMK07Y","ZzJHWtjQxs","ogLgcCK5W7","9XyT9tjQxs","DcpWBIn3NS","rhl0JSjskQ",
-"v2eC3oVQp6","9GXkXLbRTH","Cfgr316lHc","faHirnFqik","jfREuHzZT8","cmXIXXflUq","hSSvQuZPqg","5drc6CNHmv","LDk6ffaHir","gf8rI7Ow5C",
-"GXdoHXflUq","sqVrf5drc6","jSjS34QMc9","618DiIBe8k","s4786HlUbF","7fsYMlXFOB","s7MxkCfgr3","xciqpZUnqt","DLhzMe6e4z","pAhR19iGoT",
-"8FmFH9rlg9","Ta8f6guMb8","a00b5pWiOs","2DREsWPmlx","zQt6Q8FmFH","guMb87fKYU","9XyT9lj07Q","64s8NkB5nP","0h1b1yEfy9","jfREurz7Ut",
-"BpYhVtlILt","lViBvzFgtB","hYBCKtAOsr","IKxdLDG4sT","OUYuFlViBv","wDajX7hyVv","Ul4a1CxVEf","WDVWJOxWIH","ru4UGaFFss","QClRL2Nslm",
-"5drc6VLTy6","UlU3MRxrsm","VIlwPlsQGo","EOE1oDLhzM","hE1QlDz1R3","tl72Wiqv4k","Mkgy8rz7Ut","OxWIHgjUTu","KZamHlm0pD","oVQp6zz4ZU",
-"lweGyJRJQB","y94nwCIShG","9GXkX9iGoT","LDk6f3otm6","QnJ1SGSQwj","Ul4a1aDGtS","5Drn0RmDcr","jeskSdmoS7","QnJ1SEoToP","TCgPp0h1b1",
-"OUqFMcmXIX","pFrrlyluBx","gtCA5RACuj","X6Pintl72W","uoStwpFrrl","MGlTFl83Ud","kB5nPDLhzM","0YAGHRACuj","fmIK1hSSvQ","5Nammdpe1v",
-"VBjhzk85Ae","nlaBypAhR1","n1pmOuLtKs","YOfrYe6e4z","nlaByzz4ZU","jfREuuQIcz","29QAzzz4ZU","uQIczzY1GY","Zv7z0yluBx","2NslmbZLvS",
-"9y4lwS77LH","hi5X7iB08l","MezSWPYBf4","KZamHMojnP","FwEJzGWqqX","lkMUAVjCZq","7hyVvAgJHQ","jiVBPiB08l","dQ586FVMxo","KsjRK5Mg9r",
-"zmLYD7ku1p","HfyNQ4W0Tl","zqH0WcShY2","Q6hMC2Nslm","ciuWzjS1aj","4W0TlVBjhz","ogLgc64s8N","RzaZAWreyP","EOE1oiqv4k","uZPqgCNHmv",
-"WreyPKZamH","8hJdtQYxC0","SbRYyaDGtS","RkQke8FmFH","TCgPpYOfrY","fcwDacmXIX","fcJOyRpBQm","CdyBVW7cTs","nnP8oVerEA","fmIK1W3VFH",
-"I7p2aaez9y","jfREupmeCd","Qworui7WMQ","gIYvERsQUq","prNT6lXFOB","Kr8ys9rlg9","SbRYyblLA9","WmadAwiHrZ","No0QbvOqCE","3otm6GXdoH",
-"6q6L9qUJMd","W3VFHsx5Gl","qaofN5IhmG","YjB9tUl4a1","pT8wuLDk6f","lXFOBnFqik","fcwDa580YD","9eoRcaL6AJ","0h1b1zbIYY","FjHXR7fKYU",
-"G1RhSni2v1","QssNCpiJSk","7X3uymz8gx","brhlQdpe1v","2hEEUhUTw7","4dEz6KsjRK","7fKYU5Mg9r","8RCUA2Nslm","No0QbiKqhr","JIqXi5ZaEz",
-"9GXkXMmKGJ","64s8Nk85Ae","MmKGJzQt6Q","prNT6ReKEW","dpe1vBpYhV","jzUqRUmaEv","vkCHH6q6L9","K4GS8XflUq","7fKYU0YAGH","C2Ircv2eC3",
-"WmadAK20wK","45cIHuLtKs","MojnPuZPqg","zY1GYxciqp","wDajXsx5Gl","dpe1vv1Hln","G1RhSjzUqR","5Drn09eoRc","pWiOsjzUqR","KZamH618Di",
-"29QAzksJby","64s8NJRJQB","Ul4a1gdQsS","8cVD3qUJMd","v2eC3fLNg8","7fsYM64s8N","xReecW3VFH","ZuDtDnlaBy","W3VFHAIYUu","7lUXZjeskS",
-"MaJQsQssNC","lH1kt7fsYM","ciuWz7hyVv","pv0i7HzZT8","HfyNQVerEA","G1RhSUvlv4","9GXkXs93Ml","DQimpVBjhz","EOE1opFrrl","d85a9RpBQm",
-"taOXKpFrrl","7ku1pogLgc","l83Ud2TRI7","y94nwv8yFN","rhl0JStlDJ","hE1QlZ4I1v","WaWsvv2eC3","5IhmGhYBCK","0BmCy2TRI7","pT8wufaHir",
-"CIShGCK5W7","MK07YLDk6f","xciqp8RCUA","TCgPpdhSuH","FnPFBP6bcg","y94nwBbwgA","OUqFMrz7Ut","QChxsYw2oU","AmdQdo8Uyd","brhlQStlDJ",
-"EOE1o7fsYM","LbRTHcQOnv","TwanoGSQwj","BpYhVRmDcr","DcpWBcShY2","ZuDtDNOHsz","WMiS3cQOnv","ZzJHW8RCUA","RACujlpF6W","ZuDtD5Namm",
-"W7cTsNAFuw","BpYhVFwEJz","WDVWJCdyBV","ni2v1suY4x","jiVBPcL0aE","48cHLxReec","zqH0WDLhzM","ciuWz0PktI","tjQxsDQimp","QChxsAXpwE",
-"mX2GE8hJdt","EdBKcAgJHQ","FFDuiWPmlx","rhl0JguMb8","qQxHPQssNC","BbwgA0Wr5y","bZLvS9y4lw","uupzkOz8yZ","cShY2YjB9t","taOXKpiJSk",
-"pvgjSCdyBV","K20wKWaim6","uTacx4QMc9","4W0Tl29QAz","v1Hln8TxD7","hUTw7fqypy","lweGyix74r","KsjRKKsjRK","v2eC3BGaQY","xReecydG8U",
-"rz7UtmX2GE","FVMxosx5Gl","hUTw71LB1L","0Wr5y2TRI7","uQIczjtn0X","O3iyQ2Yz7E","pFrrloQ87r","l83UdiB08l","atef2Kr8ys","WMiS3oQ87r",
-"guMb8fcwDa","IBe8kVNCPd","cShY2kB5nP","b29RJdQ586","mz8gx3weIF","xReeczQt6Q","uJScXpvgjS","48cHLvLsmS","wDajX16lHc","NAFuwYOfrY",
-"HP4338RCUA","s93MlDLhzM","uupzkNcICA","RmDcrulk41","i7WMQQssNC","soy9ttaOXK","OxWIH618Di","MmKGJLDk6f","AkKTkDz1R3","bZLvSuJScX",
-"Z4I1v64s8N","EoToPpvgjS","WaWsvY1mC0","wiHrZ9eoRc","4W0TlSWfou","aDGtSMaJQs","d7vjM64s8N","RpBQmHzZT8","Chuy39XyT9","Pb1patl72W",
-"7ku1p5IhmG","JKWYRFPfSE","6AFT0iB08l","VNCPdVLTy6","2hEEU5nmWv","RmDcrokgRi","Z4I1vXyPZN","W7cTsUlU3M","cQOnvXyPZN","yofH3qUJMd",
-"uoStw8U2nU","zz4ZUtjQxs","gtCA5JkzUn","Oz8yZy94nw","RsQUqKASQ8","gf8rIcShY2","uupzkCIShG","JJs5mfLNg8","FwEJzI7p2a","rhl0JpvgjS",
-"NAFuwuoStw","s7Mxk2DREs","DcpWBZJTXH","hUTw7FnPFB","RpBQm8RCUA","CxVEfoGu6x","uLtKsK4GS8","JXljWnlaBy","7fsYMfcwDa","uoStw2Nslm",
-"8cVD3uZPqg","vLsmSRxrsm","8hJdt8RCUA","I7p2aAXpwE","k85AeECMvU","DQimpbgJAz","qUJMdru4UG","CNHmvReKEW","AgJHQuZPqg","HP4330ao3l",
-"iKqhrFVMxo","sx5GlvLsmS","faHirpvgjS","M6qcGEOE1o","dpe1vCxVEf","kB5nP5Drn0","NAFuwBpYhV","RsQUqVNCPd","2NslmFwEJz","zz4ZUksJby",
-"5NammMK07Y","WmadAjiVBP","lpF6W5VZjS","LDk6fDLhzM","FGzgpMaJQs","k85AeydG8U","W3VFHHzZT8","YjB9tuJScX","ciuWzjiVBP","MaJQsVerEA",
-"BbwgAKASQ8","G1RhSRpBQm","Mm8si5drc6","ni2v1RpBQm","P6bcgU3yw5","TwanokZANm","Chuy3G1RhS","Mkgy8fmIK1","4dEz6DQimp","gtCA5MmsIo",
-"4W0Tl7X3uy","suY4xCqqaD","RxrsmLbRTH","JRJQBn1pmO","hi5X7SWfou","v2eC3VjCZq","uvf7AVNCPd","qUJMdECMvU","i7WMQpT8wu","a00b5gdQsS",
-"zbIYYokgRi","BGaQYVerEA","RsQUq0Wr5y","3weIFRmDcr","7Ow5CAOgEe","Waim6NAFuw","7lUXZguMb8","SjskQYjB9t","wDajXbrhlQ","lpF6WFxX9q",
-"2NslmVerEA","tlILtQYxC0","2hEEUcL0aE","uQIczv1Hln","xXTI4K4GS8","Gv3Fq1LB1L","hi5X70BmCy","8FmFHrz7Ut","tjQxszmLYD","GSQwjcmXIX",
-"k85Aea00b5","ydG8UmX2GE","VerEAP6bcg","MmsIo64s8N","0Wr5yaFFss","zbIYYJkzUn","rKDLJZJTXH","GXdoHFPfSE","8U2nUuJScX","SbRYyHfyNQ",
-"fLNg8xReec","WMiS3FPfSE","0h1b1cL0aE","YjB9tiqv4k","VjCZqC2Irc","n8pJ9In3NS","pFrrlDQimp","SmGzvpAhR1","Cfgr32Yz7E","taOXK8cVD3",
-"EoToPnlaBy","WDVWJQbxXc","BFkb89rlg9","Dz1R3QbxXc","IBe8kGXdoH","QnJ1Sulk41","45cIHF6PT2","K20wKbZLvS","wDajXIRh48","IBe8kVjCZq",
-"jfREuuN6r3","BCxeCRxrsm","guMb8StlDJ","lViBvnnP8o","t98iWBFkb8","M6qcG2TRI7","0MR5XpvgjS","1LB1LzmLYD","gdQsSFwEJz","lm0pDM3zXL",
-"gtCA50MR5X","jS1ajyluBx","MK07YQnJ1S","FcWrWCp3mZ","hE1QlbrhlQ","lweGyJJs5m","FFDuiWDVWJ","CxVEfRxrsm","tvdkD7fsYM","tuDySVNCPd",
-"TXQ0ZpWiOs","Gv3FqMkgy8","VIlwPQssNC","EOE1oix74r","pFrrl48cHL","qaofNQYxC0","ReKEWBFkb8","ZUnqt5nmWv","UmaEvMmsIo","8RCUAIBe8k",
-"ix74rGSQwj","n1pmOgdQsS","DLhzMAOgEe","MmsIo9iGoT","he9IAoGu6x","uTacxfcwDa","X6PinJkzUn","8TxD7CK5W7","8FmFHlpF6W","ZJTXH9y4lw",
-"0Kyfslm0pD","pmeCdDQimp","m4bxUoVQp6","Kr8ys8cVD3","S2DfuJJs5m","o8UydIBe8k","cQOnvIn3NS","uZPqgdhSuH","Fhtglt59lR","sqVrfNAFuw",
-"sx5GlC2Irc","nFqikAOgEe","StlDJjtn0X","AmdQdSmGzv","nlaByWMiS3","5nmWvCIShG","oGu6xfqypy","AIYUuprNT6","7Ow5Cv1Hln","uvf7AsqVrf",
-"9rlg9Q6Lix","FnPFBtlILt","vOqCEQ6hMC","8xEKzEdBKc","oGu6xIRh48","24ARFtlILt","3otm6kB5nP","e6e4z2DREs","ECMvU45cIH","x3LDeHfyNQ",
-"hUTw75drc6","OxWIHM3zXL","JkzUnIn3NS","9XyT99iGoT","prNT6s93Ml","uQIczZv7z0","d85a9suY4x","uAWyppWiOs","GrDg745cIH","StlDJlsQGo",
-"QssNC4QMc9","3otm6jiVBP","s4786yofH3","QssNChe9IA","fcJOyFPfSE","lweGylpF6W","okgRiTwano","vkCHHVBjhz","dQ586uJScX","uLtKsQYxC0",
-"M6qcGJKWYR","C2Irch1zcH","i7WMQXflUq","2Yz7E5drc6","GXdoHLDk6f","PYBf4pv0i7","uvf7AyEfy9","ZUnqttAOsr","GSQwjWmadA","ZhwG1M6qcG",
-"yluBxYw2oU","2ZHdklCMxy","B3qemgIYvE","In3NSSjskQ","2Yz7Eni2v1","xXTI4rhl0J","W3VFH5Drn0","NhXduMmsIo","2hEEUdjsrv","9XyT9Rxrsm",
-"RBhp07X3uy","OUYuFaDGtS","OUYuFWMiS3","qUJMddpe1v","aL6AJqaofN","n8pJ964s8N","ix74rOz8yZ","xReecoGu6x","QnJ1SAgJHQ","dQ586BpYhV",
-"jeskSB3qem","AIYUuFFDui","2Yz7EgdQsS","s47867Ow5C","BCxeCfaHir","HfyNQSWfou","Q6hMCQClRL","9iGoTvOqCE","MmsIowiHrZ","2TRI7he9IA",
-"brhlQv8yFN","ix74rd85a9","M6qcGqUJMd","uupzkLewvM","45cIHprNT6","P6bcg6AFT0","C2IrcqaofN","hSSvQFNYIM","POUYSkZANm","DLhzM0ao3l",
-"Kr8ysqaofN","5IhmGM3zXL","uLtKsRACuj","StlDJQ6Lix","Kr8ysS77LH","OHaBz0Wr5y","pvgjSZv7z0","zFgtBVNCPd","WPmlxyEfy9","pvgjSUlU3M",
-"JXljWDz1R3","FnPFBazIWp","uTacxrKDLJ","Pb1paoVQp6","YOfrYh1zcH","Chuy3HP433","DLhzMjzUqR","NcICA2Nslm","i3pyd1j5L8","i7WMQF6PT2",
-"MGlTFtaOXK","KASQ8zQt6Q","fmIK1lXFOB","TXQ0Zuvf7A","F6PT224ARF","FNYIMhUTw7","EdBKcpWiOs","tl72WHzZT8","POUYSguMb8","8FmFH9y4lw",
-"rhl0JazIWp","gIYvEhe9IA","rhl0JI7p2a","2hEEUuZPqg","uN6r33weIF","i3pydQnJ1S","5VZjShYBCK","5Drn0CxVEf","bZLvSVLTy6","oQ87rFcWrW",
-"QClRLi7WMQ","e6e4zguMb8","BGaQYPYBf4","7Ow5C14FLR","soy9tuJScX","5ZaEzW7cTs","qUJMdoQ87r","e6e4zEOE1o","9y4lw0MR5X","1j5L8KZamH",
-"2hEEUyEfy9","6AFT0HlUbF","lViBvlCMxy","nlaByFLsph","gdQsSFNYIM","07n1cB3qem","ZUnqt24ARF","FGzgpQ6hMC","Yh1hFmX2GE","MGlTFGXdoH",
-"U3yw5Pb1pa","LewvMWMiS3","v2eC3ru4UG","aez9yiqv4k","jS1ajbgJAz","4QMc9soy9t","HP433MK07Y","2hEEUxReec","uLtKsDG4sT","sx5Glk85Ae",
-"B3qemix74r","HRxd8nlaBy","t98iWuPX7G","0h1b1FPfSE","pWiOs5drc6","IBe8k5Mg9r","i3pyd2Nslm","7hyVv6q6L9","O3iyQ6q6L9","NhXduQssNC",
-"brhlQaDGtS","suY4xgdQsS","azIWp0ao3l","UlU3MfFDrJ","4dEz6SWfou","QWxoTZv7z0","ZuDtDDQimp","rz7UtAmdQd","hYBCKtjQxs","8FmFHFcWrW",
-"euZA5L7cGc","RpBQmi3pyd","tvdkDPYBf4","yToGW5iGN5","M3zXLgjUTu","MojnP2Nslm","RACuj55rfB","F6PT2prNT6","JkzUnIjTwP","vLsmS1j5L8",
-"HzZT8lCMxy","gjUTuvOqCE","lkMUAAkKTk","guMb8W7cTs","FNYIMsuY4x","EOE1oLewvM","580YD14FLR","pmeCdvOqCE","uvf7AMkgy8","piJSkd85a9",
-"Cp3mZOz8yZ","9eoRcBFkb8","LDk6fdjsrv","CqqaD7fsYM","LewvMVIlwP","K20wKOUYuF","8hJdtnnP8o","gf8rIX6Pin","ulk41XflUq","No0QbnlaBy",
-"F6PT2AgJHQ","uJScX55rfB","6q6L9yluBx","tl72WRpBQm","MK07Y2Yz7E","l83Ud8hJdt","Yf2EcuQIcz","SbRYytvdkD","0KyfsUlU3M","zFgtB580YD",
-"wDajXvLsmS","qUJMdy94nw","n8pJ9hE1Ql","aL6AJRBhp0","d7vjMRBhp0","Uvlv4Zv7z0","dhSuHPb1pa","W7cTspmeCd","pvgjS5ZaEz","Z4I1v0Wr5y",
-"CNHmvY1mC0","2Nslme6e4z","qQxHP5VZjS","gf8rIuTacx","sqVrf45cIH","kZANmOUYuF","AgJHQW7cTs","2Yz7E1LB1L","Chuy3VIlwP","tjQxsDz1R3",
-"2Yz7E7X3uy","OUYuFB3qem","atef2IRh48","kB5nPzz4ZU","oGu6xuupzk","s4786s93Ml","0MR5X3otm6","ydG8UAmdQd","cL0aEpv0i7","cShY2OHaBz",
-"7fsYMatef2","mz8gxgjUTu","suY4xZJTXH","BpYhVdpe1v","FLsphjSjS3","XflUq07n1c","ZzJHWn1pmO","MK07Y64s8N","gtCA5nlaBy","yofH3Oz8yZ",
-"TwanouLtKs","8TxD7Chuy3","s4786nlaBy","lViBv48cHL","0YAGH7ku1p","5IhmG7lUXZ","s7MxkMojnP","J2mQiAgJHQ","MmsIoh1zcH","Vprf2ThjNn",
-"jtn0XRzaZA","L7cGcYjB9t","zQt6QYh1hF","8hJdtThjNn","5ZaEzCK5W7","JXljWOxWIH","jzUqRqUJMd","uZPqg0Kyfs","EoToP8hJdt","Nxx9VMmKGJ",
-"YOfrYFVMxo","W7cTsUmaEv","Kr8ysFwEJz","jzUqR7fKYU","FwEJzhi5X7","yToGWpiJSk","soy9tjfREu","iqv4kAXpwE","2DREsNOHsz","WMiS3zHF1q",
-"KsjRKGXdoH","L7cGcEoToP","SmGzv2Nslm","0YAGH7fsYM","KZamHCIShG","45cIHlweGy","zQt6Qrz7Ut","uvf7ANhXdu","rz7Ut5Drn0","zqH0Wd7vjM",
-"2DREsWreyP","JIqXipWiOs","MmKGJO3iyQ","8RCUAQssNC","FVMxoCNHmv","8FmFHFjHXR","Ss0ZuaL6AJ","s93MlCfgr3","AkKTkb29RJ","aez9yPb1pa",
-"cShY2S2Dfu","C2Irc2DREs","wDajXTwano","ZUnqtGWqqX","RsQUqYw2oU","suY4xS2Dfu","x3LDeYOfrY","8xEKzKZamH","LewvMWreyP","Y1mC0rz7Ut",
-"WPmlxs7Mxk","e6e4zZzJHW","QworuyofH3","AIYUubZLvS","7fsYMcShY2","RzaZAFhtgl","djsrv9y4lw","suY4xcmXIX","taOXKnnP8o","1LB1LksJby",
-"uJScXjiVBP","s7MxkVprf2","W7cTsXyPZN","a00b5lpF6W","pT8wu0h1b1","Yw2oURzaZA","1v5hHJ2mQi","2DREslsQGo","kZANmfaHir","tlILt0YAGH",
-"uTacxvkCHH","Z4I1vZJTXH","ZzJHWbrhlQ","1LB1LK4GS8","ECMvU2hEEU","9rlg9fcwDa","atef2k85Ae","7hyVvs7Mxk","rz7UthUTw7","580YDb29RJ",
-"BbwgA1j5L8","lweGy5Mg9r","jiVBPcmXIX","RsQUqMmsIo","8cVD3zY1GY","OUYuFC2Irc","SjskQy94nw","v8yFNguMb8","3otm6PYBf4","IKxdLHRxd8",
-"x3LDeLDk6f","soy9tVIlwP","yofH3soy9t","I7p2aRmDcr","taOXK29QAz","WDVWJ64s8N","ZuDtDKsjRK","uoStwIjTwP","aez9yuLtKs","8cVD31v5hH",
-"x3LDeUmaEv","ciuWz9XyT9","8FmFHzz4ZU","FnPFBRACuj","WaWsvBFkb8","ydG8UwiHrZ","Zv7z0hi5X7","G1RhSVerEA","GSQwjfLNg8","MezSWEdBKc",
-"BbwgAwiHrZ","QChxsZ4I1v","W3VFH618Di","zQt6QaDGtS","ThjNnqUJMd","suY4xhSSvQ","IKxdLtAOsr","Ss0ZuPOUYS","he9IA0Kyfs","piJSkjSjS3",
-"tvdkD8xEKz","4W0Tl8cVD3","lpF6W2Nslm","HfyNQCdyBV","RsQUq1j5L8","zmLYD3weIF","3otm6ulk41","v2eC3AOgEe","6q6L9ZhwG1","MmKGJ5Mg9r",
-"ECMvU4QMc9","azIWp5ZaEz","dQ586IjTwP","0KyfsBpYhV","Cp3mZokgRi","jS1ajpAhR1","faHirlweGy","64s8NtuDyS","Dz1R3s4786","YOfrYhe9IA",
-"dpe1vrKDLJ","RxrsmyofH3","sx5GlaFFss","In3NSZhwG1","9XyT9Dz1R3","8hJdtDz1R3","hSSvQWDVWJ","4dEz6v2eC3","5drc6qQxHP","2Yz7EAgJHQ",
-"ZuDtD29QAz","s7MxkblLA9","RzaZA8TxD7","CxVEfgf8rI","uPX7GqaofN","v1HlnFhtgl","okgRiblLA9","5NammsqVrf","IKxdL0Kyfs","cL0aEpiJSk",
-"JJs5mzz4ZU","XyPZNFPfSE","7hyVvvLsmS","yEfy9FnPFB","Zv7z0fqypy","jeskSQbxXc","RxrsmlCMxy","he9IACp3mZ","W3VFHpWiOs","Kr8ys4QMc9",
-"MK07YtuDyS","uoStw9eoRc","QChxstjQxs","e6e4zb29RJ","WMiS3LDk6f","pmeCd8FmFH","pv0i7Fhtgl","CxVEfK20wK","9GXkXaFFss","Q6hMCCK5W7",
-"MojnPB3qem","uZPqgl83Ud","zFgtBblLA9","YjB9tZuDtD","IBe8kgdQsS","8TxD7MojnP","0ao3lzmLYD","5nmWvNo0Qb","JkzUnChuy3","tjQxsuupzk",
-"YjB9twiHrZ","fcJOyzz4ZU","b29RJzY1GY","2NslmOUYuF","y94nwNhXdu","Nxx9VgtCA5","bZLvS7X3uy","7X3uyt59lR","fLNg82DREs","rKDLJ9y4lw",
-"QnJ1StlILt","rhl0JMkgy8","7ku1pK20wK","8FmFHt98iW","lViBv5iGN5","Dz1R3jfREu","JIqXitjQxs","pv0i7MK07Y","FnPFBt59lR","blLA9FxX9q",
-"C2IrcMGlTF","8cVD39rlg9","pv0i7ogLgc","nnP8odmoS7","FFDuidpe1v","o8Uyd9rlg9","wiHrZydG8U","uN6r3MGlTF","CNHmvFFDui","oQ87rpvgjS",
-"OxWIH2Nslm","Z4I1vQnJ1S","O3iyQjSjS3","tl72Waez9y","uTacxM6qcG","euZA507n1c","SmGzv0YAGH","uZPqgyluBx","QnJ1ScShY2","9GXkX2TRI7",
-"MojnPQChxs","L7cGcGXdoH","e6e4zRpBQm","QssNCGWqqX","EoToPBGaQY","oQ87r9rlg9","fmIK1K20wK","P6bcgtlILt","i7WMQ7X3uy","LbRTHyEfy9",
-"K4GS8hE1Ql","RACujMK07Y","xciqpIjTwP","ZJTXHOz8yZ","pAhR1he9IA","FGzgpWaim6","oVQp6x3LDe","pWiOszbIYY","jfREu0PktI","pvgjSAmdQd",
-"wDajXZv7z0","zY1GY1v5hH","5drc6BpYhV","2ZHdkDcpWB","NOHsz7X3uy","dpe1vFcWrW","RmDcrzFgtB","AOgEe0Kyfs","yToGW8U2nU","x3LDemX2GE",
-"SmGzvKZamH","5ZaEzFVMxo","pWiOs24ARF","7fsYMMK07Y","HP433NOHsz","vOqCECK5W7","D6rByQYxC0","aFFssRsQUq","y94nwfcwDa","6AFT0SbRYy",
-"ulk41SmGzv","JRJQBCK5W7","l83Ude6e4z","Dz1R3Pb1pa","ksJbyx3LDe","3otm6CqqaD","2ZHdkUl4a1","QbxXcQssNC","9y4lwfqypy","S2DfuZzJHW",
-"yToGWZv7z0","EoToPqQxHP","KZamHmz8gx","8TxD7fcJOy","gf8rI5nmWv","5VZjSAIYUu","9rlg98TxD7","RkQke9iGoT","ZzJHW4QMc9","ReKEWFLsph",
-"nlaBypvgjS","Yh1hFl83Ud","GrDg7JJs5m","Gv3FqbZLvS","o8Uydx3LDe","B3qemQWxoT","7fKYUdpe1v","ReKEWVLTy6","i3pydFLsph","k85AeLbRTH",
-"hi5X7zY1GY","fFDrJCp3mZ","jS1ajxciqp","blLA9ThjNn","HzZT8pWiOs","h1zcHK4GS8","a00b5QbxXc","pFrrliB08l","kB5nP580YD","gdQsS9rlg9",
-"JkzUnyEfy9","ZUnqt1LB1L","8FmFHvLsmS","pWiOsLewvM","OxWIHRkQke","RsQUquN6r3","9GXkXJ2mQi","6AFT0e6e4z","AIYUuazIWp","yluBxrhl0J",
-"64s8NFPfSE","MmsIoQChxs","jfREuatef2","K4GS8dQ586","oVQp6TCgPp","StlDJGrDg7","IKxdLM6qcG","Gv3FqlCMxy","JXljWi3pyd","jSjS3JXljW",
-"Z4I1vBGaQY","ix74rIjTwP","AgJHQSmGzv","Cp3mZB3qem","TXQ0ZazIWp","7fsYM7X3uy","7lUXZ580YD","GSQwjrhl0J","0BmCyiB08l","5VZjSqUJMd",
-"5Drn0dhSuH","euZA5JRJQB","RmDcr0MR5X","RACujv8yFN","lpF6W7Ow5C","8xEKze6e4z","StlDJuLtKs","jzUqRZJTXH","07n1c29QAz","AXpwE9GXkX",
-"8hJdtyluBx","B3qemtaOXK","k85Aehe9IA","TXQ0ZP6bcg","FNYIMsqVrf","9y4lwzHF1q","DcpWBWmadA","rhl0JlweGy","G1RhSCfgr3","SbRYyfFDrJ",
-"iqv4kDLhzM","HlUbF2Yz7E","0MR5XaFFss","8xEKzcmXIX","WreyP6AFT0","QYxC0RACuj","48cHLOUYuF","he9IA2DREs","pAhR1CNHmv","MojnPZ4I1v",
-"vkCHHPYBf4","Ta8f6VerEA","MojnPMGlTF","fcJOyxciqp","Ta8f61v5hH","ZuDtDwDajX","NOHszJRJQB","dhSuH580YD","2Yz7EVNCPd","Dz1R3W7cTs",
-"IBe8kmX2GE","piJSk1LB1L","Q6LixReKEW","pT8wuTCgPp","tvdkDJ2mQi","VerEA0BmCy","HP433Yf2Ec","KASQ8WMiS3","5Drn0NcICA","Zv7z02TRI7",
-"x3LDeVLTy6","rhl0JWaim6","s4786hSSvQ","lm0pDHP433","0ao3lBbwgA","zqH0WCdyBV","bgJAz1j5L8","cmXIXVjCZq","QnJ1SAmdQd","HfyNQ5Namm",
-"3otm60Wr5y","tlILt5iGN5","6q6L9fcJOy","lCMxy2Nslm","580YDulk41","TXQ0Zl83Ud","dpe1vQworu","7X3uyk85Ae","bgJAz8hJdt","QbxXcjfREu",
-"zmLYDzbIYY","2TRI7UmaEv","WmadA3weIF","LDk6fsoy9t","CxVEfZUnqt","5nmWvK20wK","9iGoTNhXdu","HP433Fhtgl","VLTy6pT8wu","d7vjMZv7z0",
-"pT8wulH1kt","hYBCKdQ586","9XyT9guMb8","EdBKcuN6r3","LewvM8xEKz","tAOsryofH3","m4bxUk85Ae","sx5GlyluBx","ix74rfcwDa","IBe8kCK5W7",
-"UlU3M5Drn0","pvgjSRxrsm","yofH3nnP8o","y94nwpAhR1","aL6AJEdBKc","sx5GlFxX9q","RACuj14FLR","DcpWBpvgjS","bZLvSOHaBz","YOfrYwiHrZ",
-"iwzGkLDk6f","Kr8ysazIWp","BbwgAuZPqg","XflUqaez9y","fFDrJOUYuF","lj07QL7cGc","14FLR4QMc9","HfyNQUl4a1","HRxd8SmGzv","MK07Yrz7Ut",
-"d85a9No0Qb","zQt6Q4QMc9","pFrrlFnPFB","9XyT9iB08l","BFkb8S77LH","UlU3MF6PT2","7lUXZksJby","IRh48e6e4z","9XyT9Twano","StlDJTCgPp",
-"lsQGoWDVWJ","X6PinHzZT8","FcWrWVIlwP","8FmFHU3yw5","VLTy69GXkX","ECMvUuJScX","b29RJru4UG","hUTw7X6Pin","oQ87ruupzk","hi5X7wDajX",
-"EOE1osx5Gl","fqypyyvOMI","uTacxSs0Zu","nFqikIn3NS","NAFuw1v5hH","VjCZq5IhmG","S2DfuRACuj","blLA9BbwgA","2Yz7EnnP8o","tlILtpiJSk",
-"5ZaEzQ6hMC","TCgPpxXTI4","yToGWMmsIo","8TxD7K4GS8","ZzJHWvLsmS","MK07Y2Nslm","7fsYM4dEz6","SjskQSWfou","Dz1R3n1pmO","okgRiDLhzM",
-"MojnP8U2nU","fFDrJZJTXH","v2eC3XyPZN","1v5hHvkCHH","QYxC0IBe8k","JIqXiWaWsv","UmaEvpiJSk","5VZjSe6e4z","tvdkDP6bcg","0BmCyokgRi",
-"aL6AJDLhzM","QWxoTXflUq","2hEEUksJby","QworulViBv","Cp3mZPb1pa","MojnP1v5hH","BCxeCqaofN","24ARFJkzUn","I7p2aKsjRK","FjHXRTCgPp",
-"QnJ1SjSjS3","RmDcrsuY4x","OHaBz0MR5X","5IhmG9XyT9","S2DfuRBhp0","d7vjMFFDui","5Mg9rhYBCK","tlILtKr8ys","16lHcHRxd8","8xEKzCp3mZ",
-"vOqCEogLgc","DLhzMrKDLJ","qUJMdThjNn","5VZjSy94nw","atef2SbRYy","9y4lwYjB9t","Yh1hFGSQwj","ZzJHWLbRTH","tvdkDazIWp","OUYuF6AFT0",
-"8RCUA8xEKz","VNCPdRBhp0","K4GS8suY4x","L7cGcjeskS","nlaBy9GXkX","S77LHt59lR","v2eC3yEfy9","EOE1oAmdQd","618DiZhwG1","Chuy3fqypy",
-"NOHszgf8rI","uPX7GAgJHQ","VjCZqJIqXi","K4GS845cIH","DG4sTRkQke","0ao3lm4bxU","o8Uydi7WMQ","kZANmZv7z0","y94nw5IhmG","7fKYUReKEW",
-"S77LHTCgPp","HRxd8yluBx","J2mQiXflUq","BCxeC14FLR","2ZHdkpiJSk","suY4xJXljW","YjB9tnFqik","b29RJK20wK","t59lRQ6Lix","ni2v1rhl0J",
-"qaofNjfREu","Cfgr3uvf7A","9rlg9he9IA","MmsIoRkQke","64s8N2hEEU","SbRYyW7cTs","0Wr5ybZLvS","SmGzvs93Ml","uLtKsnnP8o","VIlwPFnPFB",
-"DLhzM580YD","uLtKsa00b5","JJs5mfcJOy","HzZT8J2mQi","cmXIX7fKYU","IBe8kYf2Ec","Yh1hFYjB9t","C2IrcLewvM","MaJQsd7vjM","9XyT9k85Ae",
-"S2Dfu1LB1L","n1pmOLewvM","580YDJRJQB","4dEz60h1b1","fcJOyNhXdu","0BmCyUmaEv","e6e4zS77LH","RpBQmblLA9","5iGN5ciuWz","cShY2MK07Y",
-"0PktIHRxd8","jiVBP5drc6","FwEJzgjUTu","DG4sTCp3mZ","5drc6zQt6Q","Ta8f648cHL","618DiQ6Lix","ZuDtDtaOXK","ZUnqtMGlTF","iqv4kcmXIX",
-"IKxdLazIWp","OxWIHnlaBy","TXQ0ZciuWz","VIlwPprNT6","StlDJQssNC","MmKGJsx5Gl","MmsIo4QMc9","3otm6xXTI4","7fsYMPOUYS","ZuDtDjS1aj",
-"BpYhVCNHmv","MojnPy94nw","i7WMQ1LB1L","AgJHQwiHrZ","D6rByjeskS","2Nslm7X3uy","EOE1os4786","ksJbyHzZT8","d85a9Mkgy8","FcWrWKr8ys",
-"jS1ajVBjhz","7fsYMCfgr3","P6bcgzqH0W","n1pmO5Namm","VerEAtvdkD","GSQwjRmDcr","EoToPjfREu","RzaZAnlaBy","uTacx3otm6","zFgtBpT8wu",
-"fqypykB5nP","MmKGJC2Irc","FGzgp7fKYU","PYBf4RACuj","RACujzmLYD","b29RJoGu6x","In3NS0Kyfs","16lHcyvOMI","Pb1paQbxXc","W7cTsZzJHW",
-"brhlQQssNC","guMb8QChxs","hE1QlQssNC","i3pydiB08l","uAWypuoStw","FVMxoulk41","U3yw5faHir","yToGWUmaEv","7fsYMazIWp","JXljWLDk6f",
-"HlUbFjfREu","gf8rIAmdQd","zqH0WcL0aE","RBhp0Q6Lix","IRh48ZhwG1","fLNg8hYBCK","nlaBytAOsr","HP4337fsYM","OUqFMvOqCE","CdyBVWaim6",
-"brhlQv2eC3","HfyNQv2eC3","9rlg9uvf7A","jzUqRQYxC0","FwEJz14FLR","MmsIoHfyNQ","yofH3BGaQY","nFqikOUqFM","MmKGJAXpwE","m4bxUOz8yZ",
-"fFDrJ5Namm","yluBxi7WMQ","lXFOByvOMI","QYxC0EdBKc","9GXkXSbRYy","tvdkD45cIH","hYBCK0PktI","SmGzvyEfy9","DcpWBFwEJz","Zv7z0uN6r3",
-"2TRI7zmLYD","StlDJ8hJdt","2hEEU48cHL","QbxXc618Di","Fhtgl8xEKz","o8UydtjQxs","5NammzFgtB","dmoS7KZamH","m4bxUGSQwj","guMb8xciqp",
-"5IhmGzY1GY","Rxrsmh1zcH","jzUqRBFkb8","iqv4kmX2GE","ZuDtDyToGW","UmaEv29QAz","fcJOyDLhzM","zmLYDulk41","hSSvQyluBx","QClRLd7vjM",
-"Waim65drc6","I7p2ajzUqR","VerEACxVEf","rKDLJFnPFB","zQt6QL7cGc","FwEJzgtCA5","M6qcGS2Dfu","TXQ0ZQssNC","AmdQd14FLR","hUTw7JkzUn",
-"jtn0Xrz7Ut","n1pmOBGaQY","prNT6cL0aE","jSjS3BGaQY","5nmWvFcWrW","pvgjSWmadA","WmadAP6bcg","ni2v1XyPZN","5nmWvaFFss","J2mQiRBhp0",
-"MmKGJlm0pD","RxrsmBpYhV","a00b5rhl0J","VjCZq7X3uy","I7p2afcJOy","48cHLEoToP","Cp3mZksJby","v1HlnzmLYD","JIqXizFgtB","brhlQzY1GY",
-"RsQUqGv3Fq","LewvMHfyNQ","QWxoTiwzGk","In3NSMmsIo","jfREuGXdoH","8RCUAfcwDa","v8yFN8RCUA","9iGoT9XyT9","JKWYR4dEz6","9rlg9xciqp",
-"lkMUAM3zXL","4dEz664s8N","zHF1qaFFss","CNHmv2DREs","POUYSFcWrW","9y4lwpiJSk","gIYvEnnP8o","Mm8siFhtgl","sqVrfuQIcz","0ao3llCMxy",
-"OUqFMMaJQs","0YAGH7X3uy","TXQ0ZgIYvE","NAFuwMmsIo","WaWsvulk41","iwzGkOxWIH","FPfSE0Kyfs","AkKTki7WMQ","JXljWBpYhV","mz8gxjSjS3",
-"RxrsmlViBv","oVQp62hEEU","Vprf2MGlTF","Dz1R3B3qem","QClRL64s8N","zz4ZUaez9y","K4GS8S77LH","Ss0ZuI7p2a","uupzkiwzGk","zFgtBnnP8o",
-"iqv4kLbRTH","WPmlxThjNn","FhtglpiJSk","RmDcruJScX","xXTI4mz8gx","0Wr5yFxX9q","fcJOyzY1GY","XflUqhSSvQ","GXdoHhe9IA","fLNg8h1zcH",
-"VIlwPHfyNQ","iB08lKsjRK","P6bcgt59lR","tlILtVBjhz","gdQsSKZamH","pT8wugjUTu","oQ87rM6qcG","lH1ktC2Irc","MGlTFBFkb8","taOXKcmXIX",
-"ru4UGsoy9t","hUTw7tlILt","e6e4zCdyBV","lm0pDv2eC3","FVMxon1pmO","nFqikbrhlQ","ciuWzhSSvQ","MaJQsMezSW","JIqXiYh1hF","FGzgpyEfy9",
-"MK07YG1RhS","B3qemtuDyS","7lUXZyvOMI","b29RJbZLvS","DcpWBVprf2","CxVEfMmsIo","Mkgy8uTacx","lH1ktK20wK","lm0pDKsjRK","Dz1R32Yz7E",
-"BpYhVAkKTk","2hEEUTCgPp","G1RhSTXQ0Z","zY1GYY1mC0","MK07YCfgr3","AIYUublLA9","lXFOBCp3mZ","uPX7GHRxd8","i3pydFjHXR","5iGN5DcpWB",
-"BbwgAzbIYY","XflUqRACuj","0MR5Xhe9IA","Chuy3GSQwj","S77LHlsQGo","CxVEfHRxd8","tl72WFFDui","IjTwPy94nw","Uvlv4QClRL","MojnPuQIcz",
-"a00b5Mm8si","FnPFBDLhzM","rhl0JCNHmv","Waim6AgJHQ","azIWp0YAGH","gIYvE5iGN5","X6PinkB5nP","IRh481LB1L","lweGyBFkb8","CqqaDrKDLJ",
-"y94nws4786","NAFuwDQimp","RmDcrSbRYy","CIShGOUqFM","lXFOBpv0i7","RxrsmOz8yZ","5IhmGC2Irc","VerEA07n1c","GXdoHuAWyp","k85AennP8o",
-"ru4UGb29RJ","QYxC0cL0aE","JJs5mzHF1q","5drc6M3zXL","HzZT8VIlwP","uLtKs6q6L9","Pb1paFwEJz","I7p2aokgRi","QYxC0Waim6","FjHXRxXTI4",
-"X6PinEdBKc","16lHc29QAz","580YDbgJAz","okgRi29QAz","MGlTFlweGy","DQimpKASQ8","Pb1paNo0Qb","MmsIoDLhzM","tuDySQnJ1S","fqypyhe9IA",
-"lCMxyQ6Lix","CxVEfLewvM","Waim6cShY2","JXljWoQ87r","Dz1R3yvOMI","VBjhzRzaZA","U3yw5dhSuH","EoToPoVQp6","CqqaD5IhmG","he9IAe6e4z",
-"KASQ8uvf7A","rz7Utrz7Ut","FxX9qrKDLJ","s93Mlrz7Ut","7ku1p7hyVv","WDVWJHRxd8","7Ow5CBbwgA","W7cTsdQ586","NcICAChuy3","NAFuwGrDg7",
-"CxVEf0ao3l","ZJTXH0PktI","yEfy9Twano","yToGW5Mg9r","jtn0Xh1zcH","lm0pD48cHL","4dEz6guMb8","pWiOsKZamH","K4GS8RmDcr","FVMxo580YD",
-"NhXduzmLYD","FLsph7fKYU","AkKTklkMUA","5Namm8cVD3","5drc6aDGtS","cL0aEJRJQB","AgJHQl83Ud","Ss0ZunFqik","Cp3mZ5Mg9r","Yh1hFpmeCd",
-"hYBCKaFFss","dhSuH9XyT9","K20wKazIWp","3weIFMojnP","mX2GES2Dfu","ni2v1Uvlv4","yToGWpFrrl","zmLYDdhSuH","Mkgy8xciqp","nFqik0Kyfs",
-"uvf7ApFrrl","hYBCKk85Ae","GSQwjXflUq","Cfgr3MezSW","KASQ8Nxx9V","F6PT2xciqp","qUJMd9XyT9","OxWIHuQIcz","gIYvEEoToP","nFqikv1Hln",
-"Zv7z00PktI","uLtKsoGu6x","k85AePYBf4","bgJAzlCMxy","sqVrfogLgc","EoToPfqypy","In3NSFhtgl","s7MxkIKxdL","jtn0X2TRI7","hi5X7prNT6",
-"zmLYDbZLvS","fFDrJZuDtD","qaofNGXdoH","ix74rWmadA","nFqiktl72W","ru4UGReKEW","rz7UtJ2mQi","0h1b1IBe8k","lsQGoZv7z0","BGaQY0BmCy",
-"Yh1hFI7p2a","DQimpRmDcr","e6e4zfcJOy","GWqqXlj07Q","lweGyzQt6Q","IRh48WDVWJ","nlaByZhwG1","rz7UtNcICA","RBhp0euZA5","yEfy9d7vjM",
-"No0QbaDGtS","Fhtgl2Nslm","0BmCyyluBx","FwEJzfLNg8","5Mg9rlH1kt","14FLRv1Hln","pvgjSYjB9t","2ZHdkHlUbF","8U2nUCfgr3","Yf2EclsQGo",
-"EdBKclH1kt","9rlg9gdQsS","Yh1hFFGzgp","Chuy3ZuDtD","FcWrWi7WMQ","Waim6kZANm","aDGtSuZPqg","CdyBV2hEEU","lkMUAAOgEe","DcpWB8xEKz",
-"n8pJ9Q6hMC","BFkb8MmKGJ","FFDui8RCUA","qQxHPtuDyS","8RCUAECMvU","o8UydFNYIM","JIqXivOqCE","HP433pFrrl","1j5L8RpBQm","64s8NJKWYR",
-"SmGzvdmoS7","xciqpBbwgA","5ZaEzSmGzv","5VZjS0BmCy","NAFuwDcpWB","8TxD77hyVv","zqH0WpiJSk","UmaEvSbRYy","lm0pDOz8yZ","WmadA8U2nU",
-"KZamHGrDg7","jS1ajm4bxU","FxX9qbrhlQ","uN6r31v5hH","16lHcrKDLJ","4W0TlZzJHW","JXljWbZLvS","rhl0JDcpWB","azIWpaL6AJ","YjB9t5VZjS",
-"SjskQuLtKs","jS1ajiwzGk","gf8rIBFkb8","0MR5XFNYIM","Y1mC09eoRc","DLhzMXyPZN","tjQxsEoToP","CdyBVRxrsm","nFqikNAFuw","JkzUnd85a9",
-"jzUqRhYBCK","WMiS3m4bxU","FxX9qxciqp","HzZT8VLTy6","s7Mxk8FmFH","ZzJHWGSQwj","0BmCyWPmlx","Ss0ZuzbIYY","t98iWO3iyQ","FjHXRX6Pin",
-"y94nwrhl0J","8cVD3HfyNQ","oQ87rguMb8","IBe8kG1RhS","pFrrlP6bcg","9rlg9FLsph","lpF6WVprf2","No0QbkZANm","dpe1vb29RJ","ru4UGGSQwj",
-"qUJMdiKqhr","RsQUqtjQxs","DcpWBazIWp","ni2v1tjQxs","4W0TlkB5nP","zqH0WX6Pin","UlU3MRkQke","C2IrcfcwDa","HzZT8zHF1q","7fsYM7fsYM",
-"jiVBPzbIYY","2TRI7kB5nP","uQIczHRxd8","2Yz7E5Drn0","WPmlx8RCUA","4QMc9tAOsr","v8yFNsx5Gl","2TRI7JIqXi","uoStwbZLvS","FPfSEfFDrJ",
-"NOHszi7WMQ","tAOsrcQOnv","NAFuwciuWz","i3pydCNHmv","cmXIX4dEz6","lweGyKZamH","v2eC3tjQxs","uoStwAOgEe","uZPqg4dEz6","5IhmG9GXkX",
-"29QAzgjUTu","n8pJ9HzZT8","5IhmGcmXIX","8xEKzYw2oU","Kr8ysK4GS8","oVQp6C2Irc","MaJQslkMUA","ZhwG1zmLYD","lXFOB0PktI","7fKYUogLgc",
-"JIqXiDQimp","0BmCyM3zXL","X6Pina00b5","zbIYYnnP8o","0BmCypWiOs","HlUbFlH1kt","lsQGoxReec","wiHrZAgJHQ","ZUnqtFcWrW","0ao3luvf7A",
-"BGaQYzqH0W","QnJ1SlXFOB","CqqaD24ARF","DG4sTC2Irc","aFFsslkMUA","lj07Q8U2nU","OxWIHWmadA","No0QbIRh48","0YAGH2hEEU","vkCHHpT8wu",
-"Ss0Zu4QMc9","RkQke29QAz","ReKEW0h1b1","azIWpzz4ZU","SjskQv8yFN","jzUqRK4GS8","iqv4kQChxs","W3VFH16lHc","yToGWzFgtB","U3yw5SmGzv",
-"uLtKsBFkb8","sx5Glru4UG","SjskQRzaZA","Q6LixfmIK1","yEfy98RCUA","FjHXRblLA9","yofH3WMiS3","ix74rSs0Zu","hE1QlgjUTu","NhXduRpBQm",
-"0Wr5y5Namm","m4bxURBhp0","GrDg7ni2v1","RsQUqdhSuH","iKqhrgjUTu","fcwDaNOHsz","BpYhVMojnP","vLsmS8xEKz","Vprf2lkMUA","gdQsShe9IA",
-"uvf7AMmKGJ","RmDcrGrDg7","8U2nUWmadA","6AFT0piJSk","O3iyQlkMUA","hUTw7taOXK","ReKEWl83Ud","i3pydFcWrW","vOqCE8U2nU","U3yw5lj07Q",
-"uZPqgn1pmO","OHaBzokgRi","0Wr5yZUnqt","FjHXRsoy9t","vkCHHb29RJ","2hEEUtAOsr","b29RJFxX9q","iB08lfaHir","zz4ZUdpe1v","zFgtBcmXIX",
-"JKWYRrhl0J","2ZHdkCxVEf","8cVD3X6Pin","DQimpAmdQd","aL6AJVNCPd","e6e4zDz1R3","5nmWvPYBf4","SjskQHlUbF","nFqikPb1pa","zqH0W3otm6",
-"Y1mC0wDajX","FVMxoWMiS3","8xEKzqUJMd","OUqFMhi5X7","euZA545cIH","brhlQSjskQ","55rfBOHaBz","FcWrWVBjhz","DG4sTBbwgA","WreyPuPX7G",
-"YjB9tqaofN","C2IrcwiHrZ","fLNg87ku1p","JKWYRUl4a1","JRJQB2DREs","WaWsvxciqp","QbxXc2ZHdk","zFgtBJkzUn","rhl0JWMiS3","2NslmJKWYR",
-"aFFssZJTXH","yToGWe6e4z","tvdkDPOUYS","tuDyS0h1b1","8U2nUDQimp","pT8wuYjB9t","rhl0J2Yz7E","dmoS7StlDJ","Ta8f6lsQGo","oVQp6Q6Lix",
-"S77LHWaim6","9eoRcxciqp","jS1ajoGu6x","uJScXZUnqt","xciqpS2Dfu","L7cGc6AFT0","WPmlxd85a9","t98iWnFqik","lH1kt4QMc9","8U2nUB3qem",
-"8RCUA7Ow5C","SmGzvJkzUn","lweGyL7cGc","W7cTsiwzGk","fFDrJWreyP","F6PT2d85a9","dmoS7SbRYy","mz8gx0Kyfs","JXljWkZANm","YjB9tVLTy6",
-"piJSkfFDrJ","G1RhSStlDJ","29QAznlaBy","ZzJHW5Namm","mz8gxXflUq","9iGoTbgJAz","0Wr5yvkCHH","fmIK1SjskQ","hi5X7sqVrf","xciqpK20wK",
-"K4GS87X3uy","AmdQdAmdQd","G1RhSVIlwP","uJScXIjTwP","HlUbFuLtKs","8cVD3Ta8f6","BGaQYAkKTk","W3VFHguMb8","Yw2oUNo0Qb","Q6hMC2hEEU",
-"ZzJHWUmaEv","2TRI7TCgPp","cL0aE14FLR","OUqFMVNCPd","dhSuHblLA9","In3NSpAhR1","ulk41RkQke","b29RJFwEJz","IjTwPuJScX","2Yz7EK20wK",
-"DLhzM9eoRc","9y4lwBCxeC","45cIHfaHir","v8yFNlH1kt","oVQp6Ta8f6","QClRL9XyT9","Nxx9VRkQke","IjTwPOHaBz","VLTy6ECMvU","RmDcrZ4I1v",
-"qQxHPru4UG","ReKEWsoy9t","s4786pvgjS","6q6L92TRI7","BCxeCBpYhV","fmIK1rhl0J","fmIK1rz7Ut","sx5GlWDVWJ","QChxsOxWIH","s7MxkFxX9q",
-"jS1ajzmLYD","dQ586hUTw7","pmeCdKsjRK","jtn0Xs4786","618DiZuDtD","iqv4kzqH0W","NhXduCqqaD","t98iWlj07Q","dhSuHWaim6","VNCPdmz8gx",
-"rhl0JnFqik","Chuy3t59lR","MaJQsaez9y","8TxD7soy9t","JKWYR0PktI","n1pmOuAWyp","prNT6v1Hln","5drc6X6Pin","hSSvQ24ARF","FnPFB6q6L9",
-"G1RhSoGu6x","FNYIMmz8gx","7hyVv7lUXZ","QClRLgjUTu","Ta8f60h1b1","O3iyQi7WMQ","uPX7GOHaBz","wiHrZtaOXK","jtn0XD6rBy","0KyfsZv7z0",
-"euZA5uLtKs","JIqXiuJScX","KASQ8guMb8","he9IAMmsIo","OUqFMtjQxs","Yw2oUtuDyS","TXQ0ZRkQke","M3zXLoGu6x","uupzkFGzgp","hUTw7b29RJ",
-"OxWIH48cHL","GWqqXIn3NS","FGzgpBCxeC","sqVrf48cHL","fmIK1cmXIX","fLNg80ao3l","fmIK1lweGy","gf8rIxXTI4","9rlg9aDGtS","uAWypThjNn",
-"SWfouatef2","NcICASmGzv","QnJ1SRACuj","VerEAK20wK","vLsmSMojnP","HP4339rlg9","MaJQsS77LH","MGlTFuupzk","5drc6Zv7z0","0PktIY1mC0",
-"zHF1qsoy9t","EdBKcG1RhS","uN6r3JKWYR","lCMxyaL6AJ","WreyPCfgr3","vkCHHhSSvQ","jfREuEOE1o","v1HlnQworu","ZzJHWkB5nP","QYxC0FnPFB",
-"hi5X7VBjhz","CK5W77ku1p","h1zcHJkzUn","EoToP45cIH","soy9tLewvM","IKxdLtjQxs","ECMvUpT8wu","2ZHdkm4bxU","RBhp0v8yFN","k85Aek85Ae",
-"VBjhzSs0Zu","uTacxs7Mxk","ThjNnHzZT8","BGaQY2ZHdk","iKqhrvLsmS","FPfSEnnP8o","lj07QFLsph","HzZT8yEfy9","gjUTuoGu6x","euZA52hEEU",
-"9XyT9FPfSE","dpe1vOz8yZ","GSQwjDz1R3","uTacxulk41","zbIYYazIWp","Yf2Ec1v5hH","kB5nP7fKYU","NhXdu14FLR","CIShGgdQsS","uTacxJKWYR",
-"pAhR1gdQsS","2DREsOUYuF","FLsphWreyP","2Yz7EcmXIX","uPX7GcL0aE","n1pmO48cHL","uTacxMK07Y","xXTI4hYBCK","CIShGulk41","iB08ltAOsr",
-"JJs5mQssNC","Y1mC0U3yw5","2hEEU8xEKz","DQimpv1Hln","faHiriqv4k","JXljWe6e4z","a00b5DLhzM","No0QbFGzgp","pmeCdY1mC0","i3pydv1Hln",
-"prNT6cmXIX","v2eC3iqv4k","jtn0XZhwG1","Mkgy8djsrv","HlUbFy94nw","iwzGkKsjRK","JJs5mG1RhS","5VZjSdpe1v","fcwDajtn0X","8RCUAAmdQd",
-"ZuDtDPOUYS","FPfSEFhtgl","5Mg9rm4bxU","OUqFM24ARF","lj07QlViBv","5NammnFqik","zY1GYRACuj","0BmCyNAFuw","EOE1oMojnP","cmXIX0Wr5y",
-"S77LH1v5hH","OUYuFjeskS","JXljWD6rBy","lweGyIBe8k","RBhp0h1zcH","16lHcydG8U","sx5GlK20wK","RBhp0GrDg7","aDGtSJIqXi","CqqaDGrDg7",
-"VLTy6hUTw7","FnPFBuZPqg","O3iyQhUTw7","CxVEfx3LDe","s7MxkuPX7G","dhSuHpT8wu","ru4UGYw2oU","JJs5mW3VFH","s7MxkMmKGJ","lH1ktJIqXi",
-"Dz1R3J2mQi","9XyT9yvOMI","y94nwn8pJ9","i3pydEdBKc","tAOsr7hyVv","RmDcre6e4z","gf8rIfFDrJ","Y1mC0cShY2","FjHXRtaOXK","dmoS7WPmlx",
-"LDk6fZJTXH","VBjhz0Wr5y","ru4UGYOfrY","S77LHuLtKs","NOHszfmIK1","UmaEvCxVEf","EOE1oVIlwP","OxWIHEOE1o","xReecOHaBz","tuDySksJby",
-"XflUqjfREu","Y1mC08TxD7","GXdoHAOgEe","vLsmShe9IA","OUYuFVLTy6","nnP8oWMiS3","jS1ajGSQwj","ZhwG1IKxdL","WaWsvix74r","3otm6FcWrW",
-"o8UydFGzgp","taOXKXyPZN","Q6LixQWxoT","3weIFCp3mZ","ZuDtD5nmWv","FNYIMfcJOy","J2mQi1v5hH","Twano2DREs","64s8NVprf2","dmoS7lsQGo",
-"Dz1R3lweGy","JXljWRxrsm","jSjS3SmGzv","SmGzvlkMUA","0KyfsPOUYS","8TxD7NcICA","rKDLJYf2Ec","LewvMmz8gx","GrDg7G1RhS","WaWsvM3zXL",
-"hUTw7gjUTu","55rfBtjQxs","S77LHGWqqX","SbRYy1LB1L","hUTw7mz8gx","cQOnvLewvM","PYBf43otm6","yEfy9fqypy","JKWYRuQIcz","BCxeCS2Dfu",
-"wiHrZpiJSk","ZzJHW8hJdt","YOfrYn1pmO","7X3uySs0Zu","ogLgcZhwG1","0h1b1lXFOB","5VZjSciuWz","fcJOyKZamH","QChxsEoToP","I7p2aVprf2",
-"lsQGoW3VFH","pT8wucL0aE","gdQsSRxrsm","7ku1pQbxXc","BGaQY0MR5X","pFrrlwDajX","2hEEUWmadA","JkzUn2DREs","0PktI9y4lw","5IhmGiwzGk",
-"h1zcHBGaQY","8FmFH618Di","DG4sTZJTXH","HzZT8HRxd8","7ku1plH1kt","2DREszqH0W","k85Aeb29RJ","9rlg9zz4ZU","5iGN5JXljW","FVMxoEdBKc",
-"ZUnqtBGaQY","RBhp0MK07Y","OxWIHDQimp","HP433C2Irc","4W0TlFGzgp","RxrsmzHF1q","1v5hHEdBKc","jzUqRZv7z0","9iGoT5VZjS","l83UdHfyNQ",
-"KASQ8iB08l","55rfBQssNC","brhlQFNYIM","Ul4a15IhmG","cL0aEFxX9q","Fhtgli7WMQ","ECMvUNxx9V","QClRLbrhlQ","0Wr5ymX2GE","VIlwPOUYuF",
-"rKDLJW7cTs","euZA5JXljW","cShY2pFrrl","BCxeC5Drn0","8RCUACK5W7","5drc6rhl0J","piJSkblLA9","5nmWvZuDtD","4W0TloQ87r","jtn0X6q6L9",
-"pmeCdb29RJ","n1pmOMmsIo","pvgjS7fKYU","dmoS7lm0pD","BpYhVOz8yZ","ZJTXHYOfrY","x3LDeOxWIH","DcpWBMGlTF","W7cTsi7WMQ","zbIYY5IhmG",
-"kZANmuAWyp","7lUXZ2hEEU","lXFOBdpe1v","CIShGhe9IA","kZANmRBhp0","Ul4a1piJSk","0ao3lQssNC","y94nwlCMxy","X6PinDG4sT","RpBQmQworu",
-"iKqhrJkzUn","Yh1hFksJby","zQt6QhSSvQ","EoToPGSQwj","blLA9QbxXc","4QMc9dhSuH","FLsphlpF6W","AmdQdpT8wu","RxrsmoQ87r","azIWpKsjRK",
-"QYxC0HlUbF","5ZaEzHlUbF","kB5nPM3zXL","2DREsdjsrv","NhXduk85Ae","RkQkeChuy3","BFkb8HP433","fqypy5nmWv","soy9tDQimp","GrDg70YAGH",
-"okgRi0BmCy","RxrsmqUJMd","5NammzbIYY","580YDsoy9t","FVMxopv0i7","CxVEfX6Pin","o8UydGSQwj","hYBCKYjB9t","MK07YIKxdL","MmKGJBCxeC",
-"iwzGkCdyBV","yToGWzmLYD","JKWYRzz4ZU","jS1aj5iGN5","xReecYOfrY","Yf2EctlILt","lViBv1LB1L","faHirxXTI4","uAWyp2ZHdk","JRJQBlH1kt",
-"mX2GERpBQm","AmdQdQ6Lix","oGu6xXflUq","y94nwSmGzv","nnP8ouupzk","7fsYMlH1kt","TwanoQbxXc","16lHcaFFss","S2DfuMojnP","y94nwwDajX",
-"QWxoTFwEJz","pFrrlMmsIo","MezSWCIShG","ulk41iKqhr","suY4xlViBv","iwzGkl83Ud","fcJOy2Nslm","2ZHdkF6PT2","l83UdQbxXc","kZANm8hJdt",
-"L7cGcx3LDe","fcJOyTwano","tjQxsMK07Y","Ss0Zuix74r","v1Hln5Mg9r","7ku1pSbRYy","G1RhS0ao3l","KASQ8xReec","VNCPdpmeCd","B3qemzY1GY",
-"HRxd8RBhp0","AXpwE0Wr5y","uupzk8xEKz","hSSvQ7hyVv","MmsIoRsQUq","zqH0W5nmWv","Kr8ysyToGW","FnPFBGrDg7","ni2v1FwEJz","5ZaEzVIlwP",
-"he9IAdmoS7","d85a9Yf2Ec","hE1Ql1LB1L","brhlQvOqCE","GrDg7fmIK1","pmeCdNcICA","55rfBRBhp0","G1RhSlpF6W","HlUbFi7WMQ","Qworu24ARF",
-"UmaEvsuY4x","tjQxs9XyT9","qaofNSWfou","zmLYD1j5L8","RzaZAblLA9","yluBxKr8ys","EOE1oWmadA","blLA9s4786","JJs5mF6PT2","48cHLt59lR",
-"7lUXZix74r","i3pydHP433","2DREsi3pyd","qUJMdQworu","W3VFHNhXdu","WMiS3VerEA","ZUnqti7WMQ","0BmCyyvOMI","MaJQsfmIK1","yofH3CIShG",
-"i7WMQfLNg8","euZA5yluBx","7ku1p5Namm","Chuy3uTacx","7hyVv8U2nU","8U2nU48cHL","nlaBypWiOs","DLhzMs7Mxk","BGaQYxXTI4","KASQ8ZuDtD",
-"S2Dfusx5Gl","ReKEW5drc6","e6e4zDG4sT","55rfBaDGtS","8xEKzVIlwP","pFrrl7Ow5C","Dz1R3CNHmv","lkMUAdQ586","5drc6o8Uyd","yToGWFxX9q",
-"EdBKcHfyNQ","HlUbFU3yw5","QClRLW7cTs","uQIczECMvU","HRxd8M3zXL","jeskSprNT6","bgJAzQworu","vOqCE48cHL","tl72W5ZaEz","07n1cVerEA",
-"LDk6frKDLJ","DcpWBChuy3","VIlwPTCgPp","v1Hlnx3LDe","lm0pDMkgy8","i7WMQuAWyp","dhSuHxciqp","AOgEejfREu","qaofNpFrrl","WDVWJ7X3uy",
-"4W0TlKASQ8","Chuy3lj07Q","ZuDtDXflUq","n1pmOKZamH","5NammdQ586","WmadAQ6hMC","lm0pD8FmFH","VerEAKASQ8","guMb8AgJHQ","RzaZAcL0aE",
-"rz7UtDG4sT","W7cTsguMb8","HlUbFDLhzM","zHF1qtAOsr","oVQp6DG4sT","aFFss8cVD3","MojnPIn3NS","s7MxkJkzUn","Z4I1vhUTw7","Z4I1vDQimp",
-"ciuWz9y4lw","OUYuFS77LH","d85a907n1c","BbwgApFrrl","ZzJHWlH1kt","xXTI4ZhwG1","lCMxypWiOs","okgRiSjskQ","uLtKsqQxHP","lweGyX6Pin",
-"JXljW5Mg9r","gtCA5CxVEf","zz4ZUSjskQ","2hEEUF6PT2","iKqhrCxVEf","dpe1vOxWIH","fmIK1NhXdu","jiVBPFNYIM","dhSuHfcJOy","Nxx9Vni2v1",
-"VerEARpBQm","Chuy3FxX9q","qQxHPRmDcr","Chuy3No0Qb","uoStwFFDui","8RCUAlCMxy","JRJQB7X3uy","WMiS3DLhzM","DG4sTMm8si","RACujYw2oU",
-"vkCHHlweGy","2NslmFnPFB","Q6LixVIlwP","WmadAMGlTF","qaofNIjTwP","jzUqRtjQxs","qaofNcmXIX","VBjhzAkKTk","n1pmOJkzUn","K4GS80PktI",
-"7lUXZDcpWB","t59lRQChxs","8cVD3hYBCK","FcWrWpvgjS","Ss0ZuD6rBy","3otm6JRJQB","rhl0JeuZA5","n8pJ91j5L8","zbIYYtl72W","AgJHQZv7z0",
-"P6bcgGrDg7","TXQ0ZjSjS3","QYxC0L7cGc","MaJQs5Mg9r","pvgjSNhXdu","7fsYMCp3mZ","AXpwEtl72W","Dz1R3ni2v1","HP433i7WMQ","QnJ1SbrhlQ",
-"B3qemRBhp0","16lHcuQIcz","Z4I1vK20wK","iKqhrVerEA","nFqikcShY2","VerEAfcwDa","nlaByVprf2","sx5Gl48cHL","wiHrZQbxXc","tuDySbrhlQ",
-"lpF6WBFkb8","WPmlxHlUbF","No0QbZuDtD","5ZaEzNo0Qb","qaofNFVMxo","HfyNQSs0Zu","HfyNQyluBx","taOXKZUnqt","9GXkX2DREs","UmaEvjiVBP",
-"MezSWm4bxU","618DiMmKGJ","CqqaDWaim6","Nxx9VVIlwP","5ZaEzAkKTk","IKxdL8cVD3","hE1QljfREu","fcwDagtCA5","jfREuS77LH","8hJdtsx5Gl",
-"sqVrf0MR5X","he9IA16lHc","6q6L9suY4x","prNT6O3iyQ","0ao3lSmGzv","iwzGktaOXK","B3qemtl72W","No0QbcQOnv","16lHc9eoRc","QbxXcRkQke",
-"OHaBz8hJdt","FNYIMQ6hMC","uoStwhi5X7","ni2v1tvdkD","xReecjzUqR","W7cTsl83Ud","0PktIiqv4k","0PktIQssNC","guMb8fLNg8","1v5hH29QAz",
-"Dz1R3RzaZA","b29RJcL0aE","7Ow5CcL0aE","lXFOBSWfou","yToGWEOE1o","YOfrYzbIYY","W3VFHhUTw7","HP433DcpWB","taOXKLDk6f","cL0aERkQke",
-"zz4ZULDk6f","OHaBzM3zXL","GWqqXJIqXi","tAOsr5nmWv","taOXKhE1Ql","FNYIMd7vjM","AkKTkfqypy","CdyBVhYBCK","fcJOys93Ml","FGzgpoVQp6",
-"oQ87rzqH0W","7Ow5CfcwDa","uPX7G7Ow5C","cL0aEru4UG","FnPFBbZLvS","s4786b29RJ","Yw2oUWMiS3","ZhwG1ksJby","d7vjMogLgc","dQ586HlUbF",
-"8FmFH5drc6","NAFuwiKqhr","zqH0WQ6hMC","uupzklViBv","LDk6ftaOXK","CIShGMK07Y","MojnPsoy9t","StlDJqUJMd","Q6LixKZamH","QClRLuTacx",
-"s93MlQworu","xciqpCqqaD","bZLvSlweGy","W7cTsy94nw","vLsmSzmLYD","Mkgy8CNHmv","zqH0WwDajX","Oz8yZOz8yZ","i7WMQulk41","pWiOsAOgEe",
-"JJs5mHlUbF","DQimpIBe8k","MojnPn1pmO","uTacxtvdkD","0BmCyyEfy9","Yf2EcMGlTF","AmdQdFGzgp","oGu6xoVQp6","9y4lwK4GS8","rz7Utuvf7A",
-"Chuy3Oz8yZ","RkQke8cVD3","Waim6X6Pin","azIWpqaofN","mX2GEtAOsr","qaofNlCMxy","FNYIMvOqCE","Yf2Ec16lHc","MmKGJv2eC3","JKWYRJ2mQi",
-"NOHszzY1GY","IKxdLCK5W7","ix74ryluBx","GWqqX6AFT0","jfREuguMb8","FGzgpv2eC3","VLTy6JRJQB","zmLYDStlDJ","64s8ND6rBy","G1RhS9GXkX",
-"9XyT9mz8gx","wiHrZiB08l","LDk6fMezSW","L7cGcUl4a1","kB5nPFLsph","GXdoH7hyVv","0PktIvLsmS","pFrrltl72W","Pb1pal83Ud","Nxx9VI7p2a",
-"FVMxorz7Ut","LbRTHEOE1o","yEfy9pT8wu","tjQxsMGlTF","Cp3mZblLA9","Cfgr3DLhzM","jSjS30YAGH","TCgPpzQt6Q","AXpwEMmKGJ","wiHrZwDajX",
-"JkzUn3weIF","2ZHdk0Kyfs","EOE1oKASQ8","7fKYUFcWrW","8TxD76AFT0","Q6Lixs4786","iB08lWDVWJ","zmLYDjiVBP","BCxeCIn3NS","Twano29QAz",
-"No0Qbzz4ZU","tuDySQ6hMC","t98iWpT8wu","MGlTFjfREu","tlILtpWiOs","lpF6W4QMc9","AmdQd9GXkX","HP433GSQwj","No0Qb2DREs","6AFT04dEz6",
-"xReecCfgr3","y94nwgIYvE","GrDg7W3VFH","BpYhVe6e4z","8U2nU5drc6","M3zXLVprf2","RxrsmlXFOB","MmKGJMGlTF","G1RhS5drc6","VLTy6taOXK",
-"7fsYM16lHc","8hJdtfqypy","5IhmGd85a9","QbxXcni2v1","XyPZNvLsmS","HzZT80BmCy","JkzUnXflUq","4W0TlUlU3M","FhtglQWxoT","4QMc99iGoT",
-"rhl0JcL0aE","5Nammt59lR","oGu6xThjNn","Chuy3vLsmS","bgJAzt59lR","fmIK1MmKGJ","4W0TlQClRL","GWqqXzFgtB","QWxoTHlUbF","uPX7G2ZHdk",
-"GSQwjWPmlx","FPfSEReKEW","0MR5XuPX7G","8hJdtbgJAz","IjTwPFGzgp","uLtKsGWqqX","prNT6tl72W","Yh1hFoVQp6","aez9yFwEJz","rhl0JJRJQB",
-"Vprf2Q6hMC","I7p2a07n1c","jeskSoVQp6","fcwDaWaWsv","MojnPTCgPp","16lHcCqqaD","dmoS7RzaZA","JRJQBjeskS","h1zcHRpBQm","QYxC0CIShG",
-"wDajXU3yw5","hSSvQAOgEe","MmKGJVprf2","MGlTFbrhlQ","CxVEfd7vjM","ZzJHW0MR5X","L7cGcaez9y","bZLvSQssNC","F6PT2VerEA","MmsIo2hEEU",
-"2hEEU14FLR","Waim648cHL","aL6AJgIYvE","Yf2Ecsoy9t","RACujMezSW","MmKGJiKqhr","WaWsvJXljW","WDVWJsuY4x","JKWYRfcJOy","sqVrfhi5X7",
-"W7cTs14FLR","lweGyYf2Ec","BbwgA5nmWv","tlILtzmLYD","EoToPOHaBz","CIShGZv7z0","fcJOySmGzv","TCgPpgjUTu","nnP8oKsjRK","DLhzMuoStw",
-"StlDJrKDLJ","Mkgy8ogLgc","oGu6xFNYIM","1v5hHpiJSk","WaWsv5ZaEz","pmeCdLbRTH","4W0Tl0h1b1","5Drn0ZJTXH","zmLYDsuY4x","lpF6WciuWz",
-"45cIHuJScX","VNCPdjS1aj","jzUqRiKqhr","AgJHQmX2GE","wDajXuN6r3","Q6hMCgIYvE","WDVWJPb1pa","lj07Quvf7A","6AFT0y94nw","pmeCdfmIK1",
-"In3NS2DREs","s7MxkQYxC0","IjTwPKZamH","YOfrYyofH3","8cVD3QssNC","DG4sTjS1aj","gIYvEcShY2","UmaEvJIqXi","MK07Yulk41","jSjS38xEKz",
-"fmIK1618Di","azIWpFhtgl","uoStwkZANm","guMb8BpYhV","RzaZAUl4a1","EOE1ozqH0W","fcwDa2Yz7E","FnPFBMmKGJ","bgJAzLewvM","HzZT8ZJTXH",
-"aL6AJChuy3","FPfSEtjQxs","yToGWUlU3M","FGzgpQbxXc","ReKEWAgJHQ","6AFT0W7cTs","zHF1q0Wr5y","M3zXLuvf7A","qaofNKASQ8","S2DfuRzaZA",
-"lm0pDxXTI4","atef21LB1L","zHF1qKsjRK","S2DfuO3iyQ","W3VFHuAWyp","uZPqgjeskS","uupzkoQ87r","zY1GYfqypy","pv0i7Pb1pa","vkCHH2Nslm",
-"xReec3weIF","Ul4a107n1c","mX2GEuZPqg","uJScXQChxs","VLTy6pmeCd","FwEJzWDVWJ","4QMc9HfyNQ","s4786oQ87r","OxWIHQ6Lix","zFgtBUmaEv",
-"pmeCd8RCUA","5NammlViBv","ZzJHWyEfy9","Zv7z0hUTw7","qUJMdCxVEf","VIlwPW7cTs","CdyBVbZLvS","guMb89GXkX","AgJHQDG4sT","8hJdtcmXIX",
-"h1zcHCIShG","qaofNaFFss","ZUnqtpv0i7","pvgjSGv3Fq","580YDQ6Lix","s93MlkZANm","W3VFHDLhzM","KZamHgtCA5","Nxx9VFnPFB","SbRYy2Yz7E",
-"1v5hHd7vjM","pv0i7CK5W7","AIYUuWDVWJ","16lHczbIYY","ogLgcLbRTH","580YDZuDtD","FwEJzEOE1o","pFrrl6q6L9","WreyP9eoRc","fLNg8QbxXc",
-"SjskQFhtgl","AIYUuatef2","QYxC0F6PT2","aFFsswiHrZ","K4GS8piJSk","45cIHMojnP","AXpwEWPmlx","BpYhVfcwDa","LDk6fzQt6Q","ciuWzpFrrl",
-"5Mg9ruQIcz","ZhwG1taOXK","5NammdhSuH","2TRI7t98iW","EdBKclm0pD","F6PT2zQt6Q","jeskSOUYuF","Q6Lix8cVD3","8TxD7jfREu","K4GS88RCUA",
-"BCxeCni2v1","oQ87rOHaBz","2Yz7EWaim6","d85a9qaofN","qUJMdJIqXi","4dEz69GXkX","CIShGIBe8k","2TRI7e6e4z","m4bxUG1RhS","kB5nPMK07Y",
-"7Ow5COUYuF","OxWIHQYxC0","POUYSRsQUq","jiVBP14FLR","gtCA5QssNC","Q6LixOHaBz","uZPqguLtKs","M3zXLeuZA5","piJSkXyPZN","U3yw5tvdkD",
-"JIqXibZLvS","cmXIXRkQke","FLsphQssNC","ZhwG1BFkb8","d85a9m4bxU","rhl0J0Wr5y","i3pydazIWp","n8pJ9dhSuH","ECMvUVerEA","Ta8f62ZHdk",
-"azIWpJKWYR","ThjNnlXFOB","zqH0W5VZjS","uPX7GwiHrZ","9eoRcd7vjM","DG4sTl83Ud","5NammSbRYy","WPmlxReKEW","zY1GY9iGoT","kB5nPhe9IA",
-"ciuWz5Mg9r","o8Uyd9iGoT","hi5X76q6L9","2Yz7Eiqv4k","qQxHP45cIH","uAWypY1mC0","M3zXLYh1hF","RzaZADG4sT","6AFT0K20wK","fFDrJI7p2a",
-"ru4UGdQ586","FPfSEQnJ1S","kZANm5Namm","l83UdHRxd8","qUJMdt98iW","ru4UGlXFOB","DcpWBoVQp6","gIYvE580YD","FwEJzAIYUu","7ku1pIjTwP",
-"n1pmOt59lR","Waim6ReKEW","6AFT0NhXdu","M6qcGi7WMQ","1j5L8fFDrJ","CdyBVtaOXK","BGaQYVBjhz","jSjS3Kr8ys","LDk6fhE1Ql","G1RhSUmaEv",
-"CIShGBbwgA","cL0aElViBv","b29RJtlILt","7hyVvYjB9t","yluBxgjUTu","zbIYYStlDJ","580YDgIYvE","ix74rs7Mxk","MK07YCqqaD","O3iyQK4GS8",
-"14FLRReKEW","Ul4a1FLsph","7hyVvaez9y","uQIcz5VZjS","QWxoTblLA9","FnPFByofH3","FFDuiZ4I1v","IKxdLIBe8k","7lUXZ16lHc","AkKTkaez9y",
-"7ku1pqQxHP","uZPqgFwEJz","I7p2ajeskS","K20wK8RCUA","oGu6xRBhp0","pvgjSguMb8","1j5L8MojnP","bgJAzzHF1q","0KyfsC2Irc","gtCA5uPX7G",
-"oGu6xSmGzv","okgRiXflUq","b29RJGrDg7","POUYSjfREu","VBjhz6q6L9","9y4lwbgJAz","piJSkl83Ud","pT8wu4dEz6","3otm6gf8rI","W3VFHuLtKs",
-"DQimpWmadA","bZLvSGWqqX","Pb1pauQIcz","CNHmvWPmlx","SjskQG1RhS","CxVEf5VZjS","Chuy3StlDJ","hSSvQReKEW","EOE1oZzJHW","zHF1qi7WMQ",
-"I7p2aW3VFH","yofH3IRh48","zbIYY2Nslm","suY4xfqypy","y94nwFcWrW","VBjhzS77LH","dhSuHhSSvQ","8cVD39iGoT","W3VFH6q6L9","8cVD3uTacx",
-"Twano0PktI","taOXKJIqXi","Waim6dmoS7","618Di2DREs","uoStwFxX9q","2TRI7oVQp6","dQ5860PktI","ru4UGiB08l","8TxD7XyPZN","0KyfsTXQ0Z",
-"JKWYRSs0Zu","NAFuwokgRi","hUTw7RpBQm","xciqplsQGo","XflUqUmaEv","qaofNNOHsz","fFDrJdhSuH","uLtKsC2Irc","0ao3ldmoS7","Y1mC0uJScX",
-"euZA5VLTy6","aFFss7fsYM","OxWIHFNYIM","GrDg7C2Irc","No0Qb16lHc","uAWypqQxHP","suY4xTwano","ciuWznFqik","Zv7z0NAFuw","9XyT9dpe1v",
-"CIShGTXQ0Z","taOXKRkQke","lH1ktZuDtD","ZUnqtokgRi","CdyBVStlDJ","UmaEv0PktI","CxVEfWaim6","ix74rrz7Ut","9GXkXkB5nP","5VZjSn1pmO",
-"i7WMQlsQGo","GXdoHBGaQY","F6PT2x3LDe","L7cGc45cIH","7hyVvi3pyd","FPfSE7X3uy","8FmFH7Ow5C","euZA59rlg9","POUYSKASQ8","uTacxdjsrv",
-"lkMUAEoToP","FcWrWGrDg7","nlaByEOE1o","mX2GEvLsmS","8U2nUogLgc","64s8NM6qcG","9XyT9cL0aE","FnPFBMaJQs","7hyVvjSjS3","O3iyQaez9y",
-"Rxrsmiqv4k","Ul4a1EoToP","KsjRKwDajX","VerEAzmLYD","2DREsd85a9","14FLRy94nw","HP433sx5Gl","B3qempiJSk","l83Udn8pJ9","CNHmvAIYUu",
-"faHirWaWsv","WDVWJ1LB1L","dpe1vazIWp","fcJOyydG8U","xXTI4tuDyS","jiVBPIjTwP","7ku1pMmKGJ","UlU3MQworu","BbwgAkZANm","Chuy3cQOnv",
-"Q6LixzqH0W","lkMUAVNCPd","JIqXiUlU3M","POUYSblLA9","5IhmGjtn0X","AmdQduN6r3","rhl0JYOfrY","5Drn0ZUnqt","FFDuiWMiS3","rhl0J5nmWv",
-"MK07Y3weIF","uQIczDLhzM","ECMvUStlDJ","SjskQs93Ml","d85a9ThjNn","hYBCKKr8ys","CIShGCdyBV","QWxoTlkMUA","8TxD7Ta8f6","DLhzMGrDg7",
-"5iGN52ZHdk","vOqCE2Nslm","M6qcG9eoRc","ECMvUReKEW","UmaEvFnPFB","faHirb29RJ","CIShG4QMc9","RmDcr5Namm","qQxHPdQ586","L7cGce6e4z",
-"AXpwE0ao3l","2Yz7EGv3Fq","uZPqgvLsmS","DQimpCxVEf","DLhzMCK5W7","Y1mC0K4GS8","SmGzvMK07Y","FhtglEdBKc","5nmWvdQ586","suY4xOUYuF",
-"FxX9q2TRI7","ZzJHW2TRI7","Dz1R3oQ87r","1v5hHTCgPp","ix74rBbwgA","16lHcuZPqg","1j5L89XyT9","hYBCKBpYhV","QworuaL6AJ","1LB1LQworu",
-"WreyPCK5W7","rhl0JW7cTs","OxWIHSmGzv","5Namm0YAGH","580YD55rfB","pv0i78FmFH","euZA5DQimp","S77LH7hyVv","IRh48lCMxy","hi5X7Mm8si",
-"he9IAJKWYR","ru4UGHzZT8","zQt6Q2DREs","pWiOsaFFss","n8pJ9iB08l","Dz1R3nFqik","3weIFkZANm","FNYIMQbxXc","KASQ8S77LH","MmKGJSs0Zu",
-"9y4lwcL0aE","lH1ktVjCZq","pFrrliKqhr","fmIK1fcwDa","t59lRyluBx","gf8rIlj07Q","SmGzvIRh48","GXdoHyofH3","FcWrWaFFss","VIlwPPb1pa",
-"sqVrffqypy","Dz1R3IKxdL","BCxeCfFDrJ","rhl0JjfREu","K20wKgdQsS","qaofNdmoS7","UlU3Mfqypy","kZANmFhtgl","jeskShe9IA","oQ87rGrDg7",
-"WDVWJDcpWB","aez9ylH1kt","y94nw580YD","Waim64W0Tl","LewvMrhl0J","PYBf4QYxC0","Zv7z0v2eC3","JKWYRuoStw","aL6AJL7cGc","i7WMQ5Drn0",
-"fFDrJy94nw","fFDrJjeskS","suY4xRmDcr","XflUqAmdQd","RACujIKxdL","hUTw7C2Irc","SWfouS2Dfu","lm0pD9GXkX","cShY2prNT6","Cfgr3jtn0X",
-"8RCUAblLA9","Zv7z0CxVEf","OUYuFoGu6x","W7cTsyvOMI","6AFT0Qworu","zbIYYfLNg8","zY1GYlCMxy","lpF6WO3iyQ","zQt6QReKEW","Cfgr3ECMvU",
-"K20wKgtCA5","fcJOyuN6r3","VerEA1j5L8","1j5L8GrDg7","DLhzMWaim6","RmDcryvOMI","uQIczWaim6","EdBKcn1pmO","TwanoAkKTk","QYxC0blLA9",
-"NhXduOz8yZ","8U2nUNcICA","gIYvEcmXIX","JKWYRTCgPp","n8pJ9KsjRK","hSSvQEdBKc","nnP8o7ku1p","Mm8sit98iW","Gv3FqAkKTk","AmdQd0PktI",
-"W3VFHFhtgl","RmDcrbrhlQ","Ta8f6gf8rI","v2eC3M6qcG","pv0i7lpF6W","MaJQsm4bxU","vOqCEZ4I1v","ReKEWuAWyp","fmIK1jeskS","oGu6x5drc6",
-"3weIFPOUYS","s4786tjQxs","ECMvUJXljW","Mkgy8mX2GE","Y1mC0i3pyd","gjUTuiB08l","RACujTa8f6","aDGtSvkCHH","s7MxkDG4sT","qQxHPdhSuH",
-"WDVWJuoStw","oGu6xrKDLJ","SmGzvjS1aj","d85a9Rxrsm","QworuL7cGc","GXdoHzz4ZU","lViBvI7p2a","tjQxs07n1c","K4GS88cVD3","hYBCKCxVEf",
-"RpBQmFNYIM","F6PT2Nxx9V","Mkgy8DG4sT","JKWYRy94nw","h1zcHXyPZN","MezSW1LB1L","QssNCjzUqR","Mm8siyEfy9","x3LDeqUJMd","7ku1pHfyNQ",
-"WaWsvMojnP","iqv4kFFDui","t98iWOz8yZ","uAWypi7WMQ","lCMxyOz8yZ","guMb85nmWv","FPfSEDz1R3","48cHLv8yFN","FhtglBpYhV","JIqXiv8yFN",
-"IBe8kXflUq","8U2nUVNCPd","uvf7Aru4UG","Waim6FGzgp","07n1ctjQxs","RmDcrAgJHQ","jSjS3FwEJz","8U2nUSjskQ","lViBvhUTw7","EoToPD6rBy",
-"WPmlxv1Hln","Vprf2dQ586","sqVrf0BmCy","24ARFECMvU","9rlg9rhl0J","ulk419XyT9","ksJbyYh1hF","oQ87rD6rBy","QworupT8wu","ni2v1CdyBV",
-"fFDrJ5IhmG","NhXdu64s8N","HRxd8kB5nP","ZUnqt48cHL","JXljW2DREs","TwanoazIWp","hYBCKFxX9q","uJScXSjskQ","RmDcrLDk6f","5IhmGCqqaD",
-"9y4lwtlILt","jfREuoGu6x","POUYSmX2GE","djsrvuQIcz","bgJAzaFFss","ZUnqt618Di","zY1GYRxrsm","pAhR1ZJTXH","vLsmShUTw7","v8yFN3weIF",
-"16lHcPYBf4","gdQsSdQ586","xReecs4786","OHaBzSjskQ","uQIczydG8U","BGaQYn8pJ9","he9IAzz4ZU","Z4I1vkB5nP","nlaBySs0Zu","s93MllweGy",
-"WmadAs7Mxk","6q6L9JIqXi","07n1cPb1pa","oQ87r618Di","ZJTXHx3LDe","FFDuiuQIcz","yEfy9IBe8k","EOE1oMezSW","9y4lwVprf2","RBhp0lm0pD",
-"lViBvhSSvQ","pWiOsHP433","Waim6Gv3Fq","Ta8f6ReKEW","GXdoHCdyBV","ciuWz8RCUA","uQIczx3LDe","JXljWzQt6Q","4W0Tlulk41","AkKTkokgRi",
-"brhlQWPmlx","XflUqYf2Ec","GXdoHHlUbF","0Wr5yLDk6f","iB08lx3LDe","aL6AJIKxdL","MGlTFCK5W7","8xEKz5nmWv","GSQwj7lUXZ","RACujvOqCE",
-"gIYvE3otm6","1j5L8Ta8f6","Gv3FqRsQUq","ix74rAOgEe","P6bcgYOfrY","0MR5XbZLvS","W3VFHIn3NS","2hEEU5Drn0","RxrsmaDGtS","7fsYMMmsIo",
-"0YAGHEOE1o","d85a9FjHXR","Rxrsmv1Hln","CqqaDOxWIH","2DREsx3LDe","prNT63otm6","M3zXLoVQp6","0MR5XFxX9q","AXpwEU3yw5","brhlQaez9y",
-"iqv4k618Di","HlUbFQworu","JXljWZ4I1v","fLNg8NOHsz","zbIYYPb1pa","lpF6WCNHmv","5IhmGZuDtD","zFgtBydG8U","2Nslmsx5Gl","S2DfuGXdoH",
-"lm0pDnlaBy","CK5W7I7p2a","uQIczCNHmv","hi5X7RBhp0","vLsmSs7Mxk","CK5W7RBhp0","UlU3Ma00b5","DG4sTJXljW","n1pmOjSjS3","yvOMIlH1kt",
-"euZA5i7WMQ","2DREszY1GY","Oz8yZYh1hF","8cVD3HP433","QClRLgtCA5","n1pmO2hEEU","Ta8f6blLA9","QbxXclm0pD","SmGzv4QMc9","IBe8kQbxXc",
-"o8UydqQxHP","he9IA8hJdt","iKqhrIBe8k","0MR5XVBjhz","l83Udix74r","yofH3ogLgc","3weIFzbIYY","fmIK1G1RhS","zqH0WYjB9t","7ku1pyofH3",
-"C2Irci7WMQ","MezSWECMvU","DLhzMVjCZq","kZANmVprf2","gjUTuIKxdL","S2Dfugf8rI","HzZT8hYBCK","sqVrflj07Q","faHirlm0pD","8RCUAW7cTs",
-"07n1cW7cTs","pT8wuMm8si","euZA5ZuDtD","lsQGoM3zXL","RkQkeKsjRK","XyPZNZuDtD","ni2v1ReKEW","AmdQdY1mC0","yEfy9GrDg7","iwzGkpv0i7",
-"ogLgczFgtB","KASQ8cL0aE","9eoRc618Di","cL0aEVBjhz","soy9tzmLYD","8RCUAKASQ8","PYBf4rhl0J","qaofNAOgEe","WmadAyEfy9","MGlTF618Di",
-"cL0aECfgr3","dmoS7D6rBy","2ZHdkRBhp0","7fKYUkZANm","6AFT0wDajX","Zv7z0GXdoH","CIShGzQt6Q","9eoRczbIYY","BFkb87ku1p","2DREsRxrsm",
-"48cHL0YAGH","J2mQi0BmCy","Dz1R3yluBx","azIWp7lUXZ","cShY2LDk6f","3weIFwDajX","K20wKe6e4z","HfyNQM3zXL","pmeCduN6r3","8U2nUnFqik",
-"zmLYDwDajX","FnPFBXyPZN","WaWsvNxx9V","v1HlnhUTw7","7fsYM7ku1p","StlDJqaofN","y94nwatef2","d7vjMNOHsz","YOfrYMmKGJ","BFkb8iwzGk",
-"NOHszGWqqX","WmadAnlaBy","pv0i7WmadA","ogLgc8hJdt","9GXkXqQxHP","nFqikQClRL","d85a9ReKEW","8xEKzJ2mQi","tlILtfcJOy","FNYIM45cIH",
-"CdyBVBCxeC","Twanoo8Uyd","lH1ktbZLvS","FcWrWi3pyd","pFrrlaFFss","FnPFB6AFT0","RACujjzUqR","Mkgy8tjQxs","NAFuwv2eC3","L7cGc2DREs",
-"FwEJzfcwDa","ECMvUt59lR","WMiS3U3yw5","tlILtFLsph","Q6hMC5ZaEz","0ao3lO3iyQ","Q6Lixaez9y","iKqhrVNCPd","zHF1qbZLvS","FcWrWsx5Gl",
-"KsjRKFGzgp","guMb88hJdt","K20wKzbIYY","ZUnqtWaim6","nFqikwiHrZ","nnP8oGv3Fq","y94nwtAOsr","64s8NAXpwE","14FLRWreyP","tuDySQClRL",
-"0YAGHsqVrf","tlILtNcICA","gtCA5I7p2a","8xEKz4W0Tl","MmsIojeskS","jeskSDz1R3","AgJHQm4bxU","29QAzFjHXR","2Nslm2TRI7","LDk6fQYxC0",
-"tAOsrMaJQs","S77LHK20wK","Nxx9Vrz7Ut","RkQkeNxx9V","lweGyWDVWJ","TwanodhSuH","WDVWJfcwDa","blLA9IBe8k","xReecDQimp","Ta8f6Waim6",
-"7fKYUgIYvE","FPfSEsuY4x","16lHcCIShG","euZA5uupzk","K20wKQssNC","pmeCdHRxd8","5IhmGru4UG","ru4UGzQt6Q","uPX7GLewvM","5IhmGFnPFB",
-"zHF1qL7cGc","uvf7AblLA9","qQxHPEoToP","7X3uyIBe8k","UlU3MHfyNQ","Q6LixuAWyp","fcJOyvOqCE","16lHcuoStw","CK5W7pT8wu","QClRLlsQGo",
-"QYxC0mz8gx","Oz8yZlXFOB","djsrvgjUTu","HRxd8piJSk","45cIHlkMUA","Yh1hFRpBQm","jtn0XzmLYD","hUTw7DG4sT","uQIczI7p2a","dmoS7lweGy",
-"n8pJ9d85a9","Ss0Zuv2eC3","faHirni2v1","Nxx9VrKDLJ","QnJ1SzbIYY","qaofNS77LH","hYBCKZJTXH","hYBCK7X3uy","Uvlv4xciqp","3weIFNAFuw",
-"1v5hHJkzUn","JKWYR1j5L8","t59lRCqqaD","TwanooVQp6","fqypySs0Zu","lpF6WBCxeC","pAhR1MGlTF","6AFT0PYBf4","AOgEesx5Gl","ulk41ciuWz",
-"aDGtSC2Irc","Yf2EcHfyNQ","euZA59XyT9","dQ5862TRI7","M3zXLQClRL","7X3uyRkQke","aL6AJuAWyp","HP433GWqqX","cmXIXOHaBz","9eoRcJkzUn",
-"n1pmOn8pJ9","6AFT08RCUA","Yh1hFMmsIo","LDk6fFcWrW","ru4UGVBjhz","ulk41Yw2oU","tlILtAOgEe","brhlQhYBCK","zqH0WQssNC","jS1ajoQ87r",
-"uoStwHRxd8","tjQxs7ku1p","UlU3MHRxd8","JIqXi5nmWv","iwzGkWaim6","gf8rIJ2mQi","DLhzMpv0i7","ni2v1AgJHQ","48cHLMkgy8","iB08lpT8wu",
-"0YAGHuLtKs","oGu6xUmaEv","UmaEv2hEEU","ciuWzatef2","YjB9tMm8si","9GXkXFxX9q","HlUbFhYBCK","Y1mC0vOqCE","2TRI7pvgjS","5iGN5pmeCd",
-"rhl0JUmaEv","P6bcgdpe1v","fLNg8QssNC","5iGN5jeskS","45cIHnlaBy","VBjhz55rfB","Oz8yZFnPFB","faHiriB08l","0KyfsOHaBz","zqH0WlsQGo",
-"vLsmSd85a9","Nxx9VjS1aj","tlILtCNHmv","IRh48brhlQ","QClRLGrDg7","b29RJ8TxD7","djsrvmX2GE","tAOsr7fsYM","7X3uy3otm6","t98iWi7WMQ",
-"gIYvEDG4sT","bgJAz55rfB","Cfgr3QWxoT","16lHccmXIX","6q6L9hYBCK","Y1mC0FwEJz","dQ586C2Irc","9eoRce6e4z","gjUTuCp3mZ","AmdQdIRh48",
-"Ta8f6GXdoH","AXpwEuZPqg","tjQxszQt6Q","bZLvSdQ586","zQt6QlkMUA","djsrvnlaBy","fqypyi7WMQ","lViBvFLsph","lkMUA1j5L8","nnP8o8RCUA",
-"580YDI7p2a","WmadASbRYy","Ta8f6t98iW","X6PinKr8ys","HlUbFVLTy6","Q6LixkB5nP","rz7Ut9y4lw","iqv4kVprf2","tlILtulk41","SWfouUlU3M",
-"pFrrlFVMxo","uLtKsyvOMI","aL6AJVIlwP","VjCZqqaofN","aez9yKZamH","cL0aEfLNg8","0KyfsaL6AJ","7X3uyVLTy6","jSjS3WmadA","1LB1LHlUbF",
-"5Drn0t59lR","Ss0ZuHfyNQ","pv0i7Dz1R3","3otm6K20wK","5Drn0C2Irc","brhlQjzUqR","8cVD3AkKTk","ZUnqthi5X7","y94nwqQxHP","GSQwjHP433",
-"pv0i7ZuDtD","LDk6fYjB9t","djsrvZuDtD","IBe8k2ZHdk","oVQp67ku1p","SjskQ9GXkX","HzZT8UmaEv","0PktIHP433","sx5GlRmDcr","prNT6lj07Q",
-"tjQxsQnJ1S","FNYIMQ6Lix","zqH0Wru4UG","hSSvQ9eoRc","oQ87rNo0Qb","uoStwjSjS3","mz8gxIBe8k","5IhmG5Drn0","jS1aj14FLR","Cp3mZF6PT2",
-"24ARFGSQwj","0PktIMmKGJ","kZANmIRh48","VNCPdSbRYy","ni2v1ZuDtD","qaofNAXpwE","Oz8yZ9XyT9","v8yFNKASQ8","soy9tOUqFM","zY1GYfcJOy",
-"v1HlnWaim6","a00b5gf8rI","FhtglDLhzM","QClRLS2Dfu","iKqhr0h1b1","618Di2ZHdk","0KyfsD6rBy","uupzkjSjS3","aFFssPb1pa","vOqCEb29RJ",
-"FwEJzxReec","9GXkXpT8wu","6AFT0fmIK1","rz7UtcL0aE","HfyNQ9eoRc","v1Hln0Kyfs","dmoS7s4786","e6e4zM3zXL","vLsmShSSvQ","Yw2oUIjTwP",
-"uLtKsprNT6","8U2nUWaWsv","JXljWsqVrf","brhlQYw2oU","mX2GEHfyNQ","mz8gxWPmlx","b29RJfqypy","QbxXc7lUXZ","fcJOyiqv4k","0MR5Xv2eC3",
-"uN6r3POUYS","v8yFNMojnP","s47865ZaEz","lkMUA64s8N","hUTw78cVD3","X6Pin618Di","HfyNQs4786","prNT6t59lR","0YAGHU3yw5","4QMc9k85Ae",
-"v2eC3LDk6f","YOfrYeuZA5","2hEEUvLsmS","LewvMS2Dfu","J2mQi1LB1L","iqv4ks4786","BCxeC7ku1p","iKqhrpAhR1","NOHszd85a9","YOfrYQChxs",
-"NhXduRmDcr","kB5nPWmadA","K20wKcmXIX","FVMxoWPmlx","sx5GldhSuH","zHF1qMm8si","I7p2a55rfB","sqVrfpv0i7","Mkgy87hyVv","CxVEf0YAGH",
-"FnPFBh1zcH","8hJdtfaHir","ydG8UDcpWB","nlaBySmGzv","kZANmI7p2a","s4786lViBv","tAOsryvOMI","FNYIMCxVEf","gf8rIQChxs","IBe8klH1kt",
-"lsQGogdQsS","Dz1R3KZamH","29QAzTa8f6","BbwgAS2Dfu","Yf2Ec8RCUA","QbxXcsqVrf","HP433aFFss","FGzgpi3pyd","piJSkZUnqt","AIYUuHfyNQ",
-"TXQ0ZrKDLJ","jSjS3qQxHP","s93Ml580YD","OxWIH8hJdt","9y4lwwDajX","MojnPCNHmv","tjQxsjS1aj","OUYuFsqVrf","YjB9tMezSW","tuDySn8pJ9",
-"pv0i7HfyNQ","okgRijzUqR","BpYhVpFrrl","TXQ0Z1j5L8","Z4I1vChuy3","uoStwRsQUq","SmGzv3weIF","Kr8ysulk41","QYxC0QClRL","hSSvQVBjhz",
-"HfyNQtaOXK","fLNg8qUJMd","14FLRvkCHH","pWiOsK20wK","jfREudhSuH","14FLRJkzUn","fmIK1i3pyd","ru4UGgIYvE","2DREslpF6W","7hyVvrKDLJ",
-"TwanouJScX","zmLYDTXQ0Z","dpe1vyToGW","WmadA7X3uy","dmoS7jiVBP","Waim6h1zcH","fFDrJC2Irc","P6bcgtAOsr","XyPZNVIlwP","5VZjS3weIF",
-"tvdkDs4786","IBe8ksuY4x","hYBCK3weIF","pAhR12hEEU","pFrrliqv4k","FxX9q0Kyfs","W3VFHKsjRK","0KyfsqaofN","i7WMQM3zXL","4W0TlgIYvE",
-"dpe1vWaWsv","QClRLECMvU","yEfy9RzaZA","tlILtSmGzv","Yf2EcVprf2","lH1kt1j5L8","WPmlxKsjRK","L7cGcTCgPp","oGu6xVjCZq","ZUnqtFLsph",
-"ciuWzFNYIM","ZuDtDvkCHH","t98iWCK5W7","aDGtS7fsYM","BbwgAl83Ud","xXTI4W3VFH","Vprf2JXljW","VIlwPrKDLJ","OHaBzAIYUu","aFFssZv7z0",
-"rhl0Juvf7A","DQimpvkCHH","C2IrcoVQp6","iKqhriKqhr","VBjhzqQxHP","k85AeyToGW","0Wr5y3otm6","uupzklkMUA","zY1GY5Mg9r","sx5Glatef2",
-"cShY2qaofN","8FmFH2Nslm","xXTI4WreyP","OUYuFWaim6","Ul4a1uoStw","OHaBzFwEJz","S2Dfuxciqp","3otm6OUYuF","UlU3MyvOMI","VLTy65iGN5",
-"gdQsSmz8gx","14FLRZJTXH","zqH0Wn1pmO","QssNC9iGoT","AOgEejzUqR","bgJAzKZamH","Chuy3RzaZA","I7p2a7fsYM","QYxC0ECMvU","x3LDeuQIcz",
-"0Kyfsm4bxU","WMiS3ZzJHW","CqqaDs4786","LewvMHzZT8","n8pJ9MK07Y","5NammChuy3","n1pmOMmKGJ","C2IrcuZPqg","v2eC3MmKGJ","wDajXiwzGk",
-"AmdQdtaOXK","7X3uyKsjRK","GSQwjJRJQB","lXFOBlViBv","KZamH2TRI7","FGzgpNo0Qb","AkKTkbgJAz","aDGtSlH1kt","cShY2StlDJ","QYxC0yToGW",
-"RkQkeFhtgl","QssNCWPmlx","VNCPdkZANm","StlDJdjsrv","uZPqg5iGN5","zmLYDMkgy8","5IhmGNcICA","7ku1pNhXdu","MGlTFDQimp","cL0aEbZLvS",
-"AIYUuZzJHW","s93MlIKxdL","G1RhS9eoRc","pv0i7RzaZA","48cHLcQOnv","ThjNn8U2nU","7ku1pL7cGc","K4GS8tAOsr","GrDg7MmKGJ","4QMc9ksJby",
-"zqH0Wsoy9t","OUYuFECMvU","ydG8UMezSW","Ta8f6RmDcr","B3qemAkKTk","7Ow5CRpBQm","uoStw0YAGH","DLhzMDQimp","KsjRKMojnP","VNCPdru4UG",
-"0PktIThjNn","iKqhrPYBf4","jSjS39iGoT","6q6L9ix74r","FjHXRoGu6x","FGzgpCNHmv","atef2OUqFM","yToGWFwEJz","55rfBiB08l","Y1mC0JRJQB",
-"vLsmSZ4I1v","wDajXcL0aE","X6PinpiJSk","vOqCE14FLR","FjHXRhE1Ql","9eoRc8U2nU","ksJbyFwEJz","618DiyToGW","cL0aEzQt6Q","Vprf2xReec",
-"7hyVvZv7z0","EoToPEOE1o","FjHXR1v5hH","a00b5jzUqR","0YAGHNOHsz","FxX9qStlDJ","9rlg9FxX9q","AIYUuMezSW","TXQ0ZFFDui","G1RhSPb1pa",
-"pFrrl9iGoT","Mkgy8M3zXL","pvgjScmXIX","RpBQmXflUq","QworuQnJ1S","Waim6aL6AJ","FPfSElH1kt","SjskQC2Irc","uJScXNhXdu","2ZHdkyluBx",
-"i3pydKASQ8","zbIYYmX2GE","zY1GYyToGW","h1zcHFxX9q","AgJHQaL6AJ","k85AeRACuj","x3LDeX6Pin","WMiS3Kr8ys","Ss0ZuQssNC","AmdQdgdQsS",
-"45cIHsuY4x","X6Pinaez9y","soy9tUl4a1","IKxdLRxrsm","9rlg98FmFH","HRxd82ZHdk","NhXduVIlwP","pFrrlDG4sT","9GXkX580YD","zQt6QU3yw5",
-"Q6hMCxXTI4","Q6LixAgJHQ","MmsIoKZamH","7fKYUpT8wu","cQOnvZzJHW","64s8NRpBQm","0h1b1uupzk","djsrvHzZT8","1v5hHXyPZN","iqv4k5nmWv",
-"WPmlxFcWrW","AIYUuulk41","SjskQPb1pa","jeskS3weIF","pmeCdzHF1q","5IhmGn8pJ9","blLA9tjQxs","pT8wu5IhmG","ciuWzUl4a1","3otm69iGoT",
-"zz4ZUk85Ae","rKDLJbgJAz","KZamHRBhp0","hE1QlHRxd8","v8yFNJRJQB","zz4ZUQYxC0","i7WMQZ4I1v","7fKYUiqv4k","0YAGHy94nw","fcwDas7Mxk",
-"mX2GE8FmFH","yToGWuoStw","tAOsrlViBv","k85AecL0aE","xciqpOz8yZ","aez9yokgRi","yluBxfmIK1","HlUbFd7vjM","RBhp064s8N","HfyNQQ6hMC",
-"nFqik8TxD7","atef2CNHmv","lViBvS77LH","NAFuw4W0Tl","7X3uyhYBCK","t59lRv1Hln","KASQ8m4bxU","VIlwPDG4sT","he9IAUmaEv","gf8rIYf2Ec",
-"uAWypQYxC0","S77LHRmDcr","7ku1pYw2oU","RACujNo0Qb","IBe8klCMxy","UlU3MtlILt","qQxHPnlaBy","OUqFMQbxXc","AgJHQ48cHL","GWqqXfcwDa",
-"5nmWvFjHXR","ZhwG164s8N","wDajXSWfou","5nmWvd85a9","bZLvSSmGzv","suY4x2hEEU","CqqaDM3zXL","Nxx9Vsx5Gl","ni2v1LDk6f","I7p2aChuy3",
-"fcJOyRACuj","QssNCI7p2a","yofH30YAGH","v8yFNWDVWJ","fmIK1nnP8o","zY1GYzFgtB","zz4ZU2hEEU","prNT6QbxXc","Cfgr3nlaBy","0h1b1d85a9",
-"lViBvLbRTH","lXFOBZhwG1","lpF6WCdyBV","SmGzvXflUq","iqv4kReKEW","Chuy3aFFss","WaWsvuupzk","tjQxs2Nslm","o8UyduLtKs","IBe8kQWxoT",
-"B3qemciuWz","7fsYMuLtKs","dhSuHSWfou","7ku1pXflUq","AmdQdfmIK1","CxVEf0Wr5y","UlU3MJkzUn","uoStwwiHrZ","lViBvDz1R3","UlU3MD6rBy",
-"ksJbyIBe8k","2hEEUpWiOs","lj07QRzaZA","xReecgjUTu","ni2v1iwzGk","YjB9tkB5nP","RpBQm8FmFH","8cVD3Cfgr3","8cVD34dEz6","SmGzvRmDcr",
-"mX2GE6q6L9","Q6Lix45cIH","djsrvMaJQs","UmaEvOUqFM","0PktIcmXIX","fmIK1POUYS","yToGW0Kyfs","pmeCdTXQ0Z","Mkgy8IRh48","soy9tPOUYS",
-"Yh1hFBpYhV","xXTI424ARF","SjskQzQt6Q","POUYSMmsIo","ZuDtDCdyBV","xciqpRBhp0","6AFT05Drn0","3otm6yofH3","FPfSEfmIK1","D6rBymz8gx",
-"dmoS7cL0aE","QnJ1SJ2mQi","2Yz7EyEfy9","MmKGJuoStw","618DilXFOB","Gv3Fq1j5L8","FFDuini2v1","NOHszGXdoH","oVQp69iGoT","qQxHPtl72W",
-"Zv7z0HlUbF","DcpWBRACuj","qUJMd07n1c","MojnP07n1c","hi5X7JRJQB","uN6r3SbRYy","uAWypgIYvE","l83Ud2Nslm","uQIczAOgEe","yvOMIjzUqR",
-"lpF6W1v5hH","faHirpFrrl","CqqaD9y4lw","O3iyQHzZT8","zmLYD9iGoT","OHaBzWaim6","D6rByOz8yZ","v2eC3K20wK","jSjS37Ow5C","BbwgAZhwG1",
-"S77LHiB08l","ksJbyF6PT2","cL0aETa8f6","zmLYDguMb8","JJs5mjiVBP","LDk6f55rfB","BGaQYRsQUq","HP433In3NS","WDVWJRzaZA","0h1b1sx5Gl",
-"8xEKzU3yw5","y94nwAmdQd","0YAGHTCgPp","XyPZNP6bcg","XyPZNLewvM","piJSk7fsYM","AmdQdzqH0W","IKxdLQYxC0","ru4UGyvOMI","YOfrY64s8N",
-"7fKYUFGzgp","lsQGo9XyT9","cQOnvDLhzM","uZPqg7Ow5C","HP433I7p2a","Z4I1v0ao3l","Q6LixD6rBy","hSSvQxciqp","uPX7G7fsYM","tvdkDhE1Ql",
-"BFkb87X3uy","FLsphgjUTu","hi5X7Twano","uupzkIKxdL","jeskSmX2GE","n8pJ9CK5W7","4W0TlCxVEf","FFDuihYBCK","dpe1vYf2Ec","M3zXLIKxdL",
-"WMiS3hi5X7","iqv4kJKWYR","LDk6f3weIF","16lHcEOE1o","LDk6fzz4ZU","0BmCynFqik","64s8Nhe9IA","kZANmjtn0X","RACuj64s8N","Vprf2F6PT2",
-"jiVBP7lUXZ","pv0i7G1RhS","jS1ajlViBv","FnPFBaez9y","9eoRctvdkD","MGlTFlpF6W","dhSuHazIWp","NcICAOUYuF","JIqXipmeCd","9GXkXGWqqX",
-"jtn0X4QMc9","qUJMdksJby","s7MxkpT8wu","MmKGJ8xEKz","1v5hHrKDLJ","OUqFMv2eC3","uupzkyvOMI","s7Mxkk85Ae","FnPFBbrhlQ","Mkgy8M6qcG",
-"AXpwEjtn0X","MojnPNOHsz","fcJOyKr8ys","uPX7G24ARF","fFDrJdmoS7","POUYSKr8ys","5Drn0Kr8ys","Kr8ysRpBQm","FFDuiKr8ys","djsrvoQ87r",
-"CIShGZ4I1v","NAFuw0h1b1","QssNCS77LH","QWxoTkZANm","e6e4zbrhlQ","cmXIX8TxD7","uZPqg24ARF","Yf2EcQ6Lix","Vprf264s8N","RBhp0RBhp0",
-"vOqCEfmIK1","nnP8oWPmlx","RzaZAxciqp","29QAztuDyS","cQOnvv8yFN","F6PT2tAOsr","azIWplCMxy","8TxD7WreyP","n1pmOMaJQs","lH1kth1zcH",
-"Yw2oUZzJHW","d7vjM9y4lw","yofH3gdQsS","azIWpsx5Gl","yofH38FmFH","0YAGHDz1R3","iwzGkn1pmO","nFqikjeskS","HfyNQJJs5m","blLA9WMiS3",
-"OHaBzjSjS3","Oz8yZnlaBy","yvOMIwDajX","MmKGJrz7Ut","UlU3MZv7z0","F6PT2uoStw","OxWIHblLA9","cQOnvYf2Ec","fFDrJzmLYD","29QAz29QAz",
-"lj07QOUYuF","MmsIoBGaQY","b29RJqQxHP","48cHLAkKTk","ECMvUCIShG","tuDySMGlTF","6AFT0ydG8U","DQimpFnPFB","LDk6fcQOnv","YOfrYFPfSE",
-"KsjRKdQ586","5IhmG4dEz6","sqVrfcShY2","RsQUqyEfy9","pFrrlvLsmS","IKxdLBFkb8","h1zcHF6PT2","v1HlnJKWYR","RpBQmy94nw","hi5X7uAWyp",
-"AgJHQqaofN","s7Mxk1v5hH","ECMvURkQke","zz4ZUAkKTk","K20wKIRh48","2Yz7E1j5L8","lkMUADQimp","lViBv4QMc9","mz8gxd85a9","zHF1q7fsYM",
-"9rlg9tjQxs","azIWp2DREs","RkQkejeskS","B3qemqaofN","VLTy6Oz8yZ","EoToPa00b5","iB08lpmeCd","KsjRKlweGy","yEfy9Kr8ys","b29RJMm8si",
-"AgJHQpWiOs","5Mg9rPOUYS","LDk6fTwano","NhXdu0Wr5y","YOfrYb29RJ","RmDcreuZA5","qUJMdDcpWB","5nmWvQ6Lix","MmKGJNxx9V","aDGtSStlDJ",
-"C2IrcIn3NS","5Mg9rVNCPd","KASQ8LDk6f","zmLYDfmIK1","ciuWzFVMxo","uLtKsx3LDe","IjTwPWaim6","0ao3liqv4k","RBhp0CxVEf","lkMUAlm0pD",
-"6q6L9JKWYR","YOfrYcmXIX","QChxsM6qcG","cShY21LB1L","NcICA55rfB","SWfoue6e4z","L7cGcyToGW","piJSkZv7z0","t59lRzbIYY","JIqXiGrDg7",
-"FPfSETa8f6","l83UdEdBKc","QClRLhe9IA","yluBx64s8N","DG4sTOxWIH","he9IAyvOMI","Ss0ZutlILt","MezSWuPX7G","0Wr5yt59lR","tlILteuZA5",
-"5Drn0i3pyd","xReecFLsph","FxX9qPYBf4","DQimpWDVWJ","iB08lL7cGc","vLsmStjQxs","7ku1pOxWIH","Kr8ysLbRTH","VerEAcShY2","CIShGCfgr3",
-"AOgEeK4GS8","B3qemsoy9t","d85a9jtn0X","s93Mldjsrv","v2eC3SjskQ","9iGoTyToGW","NOHsz8U2nU","C2IrcZUnqt","jS1ajfcwDa","8hJdtKASQ8",
-"0h1b10YAGH","i3pydvLsmS","B3qemhe9IA","D6rByVerEA","JKWYREoToP","DLhzMy94nw","qaofNI7p2a","VjCZqHzZT8","RkQkeVjCZq","SmGzvStlDJ",
-"9XyT9OHaBz","guMb85VZjS","dmoS7DLhzM","UlU3MWMiS3","brhlQuLtKs","zQt6QpiJSk","uJScXwDajX","0ao3lCqqaD","zY1GYlH1kt","oVQp6qQxHP",
-"5Mg9rtlILt","ZUnqti3pyd","5iGN5dpe1v","0BmCyb29RJ","yofH3ZJTXH","fFDrJZUnqt","1v5hHEOE1o","xciqplpF6W","FxX9qFNYIM","atef20ao3l",
-"ECMvU9XyT9","FxX9q1j5L8","AmdQdFPfSE","Chuy3lm0pD","DQimpEOE1o","LbRTHhE1Ql","64s8NWreyP","uTacxrhl0J","hSSvQ5nmWv","ciuWz64s8N",
-"Z4I1vVIlwP","hYBCKU3yw5","Mm8sizqH0W","zmLYDiKqhr","yluBx4W0Tl","Waim6okgRi","oVQp6KZamH","qQxHPB3qem","zmLYDAkKTk","zmLYD2Yz7E",
-"gjUTudQ586","VIlwPAmdQd","pmeCd24ARF","uPX7GIjTwP","suY4xd85a9","TCgPp9GXkX","FGzgppFrrl","a00b5FnPFB","gjUTuuZPqg","NcICA8cVD3",
-"QbxXcGSQwj","2hEEUThjNn","Nxx9V5drc6","L7cGcfaHir","FGzgps93Ml","lpF6WkZANm","nFqikFcWrW","W3VFHaez9y","taOXKa00b5","lpF6WECMvU",
-"K20wKaDGtS","Z4I1v8cVD3","BpYhVZzJHW","IjTwPs7Mxk","29QAzRmDcr","S2Dfulj07Q","2Nslm4QMc9","8FmFHWaim6","9y4lwEOE1o","7lUXZxXTI4",
-"gf8rI0BmCy","HzZT8i7WMQ","suY4x64s8N","MGlTFnFqik","WMiS3tvdkD","1v5hHW3VFH","RxrsmZUnqt","9y4lw9y4lw","atef2uJScX","kB5nPOUYuF",
-"pAhR1lsQGo","fFDrJEOE1o","AIYUu7ku1p","D6rBycL0aE","faHirB3qem","nnP8oiqv4k","8hJdtaez9y","Twanoru4UG","blLA95Namm","8TxD7JRJQB",
-"lm0pDOxWIH","zmLYDm4bxU","YOfrY2Nslm","8hJdtjS1aj","D6rByqUJMd","QbxXctAOsr","7ku1pQnJ1S","qUJMdRACuj","8U2nUCxVEf","ni2v1pvgjS",
-"cmXIXcmXIX","NAFuwvkCHH","kB5nP8FmFH","gtCA5uZPqg","QbxXcJkzUn","iwzGk4W0Tl","3weIF5ZaEz","Mkgy84QMc9","TCgPpVLTy6","AXpwEX6Pin",
-"wDajX8hJdt","618DiW3VFH","Yf2Ecrhl0J","G1RhS2ZHdk","8FmFHydG8U","i3pydOxWIH","Yf2EcVLTy6","FhtglM3zXL","vLsmS5drc6","pT8wuk85Ae",
-"POUYSyEfy9","3otm6RzaZA","S77LHkZANm","RkQkeblLA9","JIqXiQYxC0","jzUqRKsjRK","2DREs5drc6","gjUTuYh1hF","LDk6fvOqCE","UlU3M64s8N",
-"MGlTFU3yw5","piJSkpmeCd","U3yw5iKqhr","fLNg8OHaBz","DG4sTydG8U","FGzgp1j5L8","FcWrWZJTXH","8RCUAK4GS8","SjskQuN6r3","S77LHdQ586",
-"ydG8UFjHXR","VjCZqzY1GY","QssNC618Di","J2mQieuZA5","NAFuwiB08l","In3NSDcpWB","zHF1q1LB1L","i3pydfcJOy","07n1clH1kt","pvgjSC2Irc",
-"aFFss16lHc","pmeCdyofH3","5drc6GWqqX","NcICAtvdkD","ydG8UnlaBy","jSjS3brhlQ","lsQGo5VZjS","lH1ktCK5W7","zbIYY4W0Tl","n8pJ9WmadA",
-"atef2Fhtgl","vkCHHJXljW","lViBvnFqik","iKqhrwDajX","580YDe6e4z","okgRiK4GS8","v1HlnFGzgp","hUTw7ZUnqt","CIShGxReec","SWfouoQ87r",
-"aFFssSjskQ","jiVBPWDVWJ","nFqik9y4lw","CK5W7X6Pin","Zv7z0oQ87r","LDk6fUmaEv","HRxd8lj07Q","IBe8kzFgtB","o8UydQbxXc","07n1ctlILt",
-"lweGyS77LH","RsQUqSbRYy","7lUXZ2DREs","lj07Qlm0pD","qQxHP4QMc9","b29RJgIYvE","guMb80h1b1","cShY216lHc","MK07YVerEA","O3iyQ7X3uy",
-"hYBCKs4786","3weIFS2Dfu","ZJTXHgtCA5","6q6L91LB1L","zHF1qLewvM","LewvM3weIF","qQxHPpWiOs","Vprf2Waim6","8cVD3atef2","WDVWJ0Wr5y",
-"jeskS2Yz7E","Ss0Zu3otm6","fcJOydQ586","BFkb8tvdkD","iKqhrHfyNQ","lsQGo0h1b1","SmGzvGrDg7","d85a9x3LDe","Nxx9V24ARF","14FLRRsQUq",
-"qUJMdciuWz","BFkb8VLTy6","F6PT2RzaZA","s93MlZv7z0","GXdoHJ2mQi","gdQsSFxX9q","lsQGoQClRL","QbxXchSSvQ","dpe1v5Mg9r","QbxXcgf8rI",
-"7fKYU7fsYM","lH1kto8Uyd","7hyVvLbRTH","In3NSpiJSk","MezSW5IhmG","Z4I1vcShY2","8xEKzhi5X7","Mm8sioQ87r","7fsYMs4786","JJs5mzY1GY",
-"gIYvEs93Ml","e6e4zQ6hMC","pAhR1k85Ae","MGlTF5nmWv","ZzJHWVjCZq","QYxC0uvf7A","G1RhSWreyP","h1zcHZhwG1","GWqqXNo0Qb","cmXIXYjB9t",
-"5ZaEzlpF6W","d85a9uJScX","i7WMQ0Wr5y","wiHrZrKDLJ","XflUqUlU3M","FwEJzVerEA","RzaZA0PktI","ZuDtDmX2GE","wDajXe6e4z","J2mQiv1Hln",
-"oQ87rCNHmv","MaJQsF6PT2","JKWYRFwEJz","kZANmFnPFB","xciqpQworu","GSQwj24ARF","8cVD3FNYIM","D6rByJXljW","jfREuhUTw7","n1pmOmz8gx",
-"G1RhSWmadA","RpBQmK20wK","0Wr5yVjCZq","IBe8kpT8wu","K20wKCNHmv","MmsIoyvOMI","iwzGkJ2mQi","pv0i75Mg9r","tjQxslm0pD","JXljWulk41",
-"dQ586h1zcH","pvgjS2TRI7","2NslmfcwDa","WPmlx0Kyfs","Uvlv4cQOnv","QClRLQnJ1S","I7p2av1Hln","jtn0XBpYhV","B3qemAOgEe","prNT67hyVv",
-"JIqXiVerEA","jtn0XVerEA","tvdkDiB08l","uQIczyofH3","7ku1pv8yFN","blLA9Q6hMC","tuDySBpYhV","xciqpxciqp","uoStwIRh48","OUqFM2hEEU",
-"Waim6WDVWJ","WDVWJs7Mxk","jfREu2hEEU","C2IrcZuDtD","U3yw5ThjNn","s93MloVQp6","AmdQdStlDJ","dmoS7M3zXL","uLtKs8FmFH","KsjRKGv3Fq",
-"aFFssdjsrv","ZuDtDlsQGo","nFqikhi5X7","gdQsSF6PT2","zqH0WCxVEf","Uvlv4suY4x","5IhmGnlaBy","ydG8UpFrrl","POUYSx3LDe","tuDySIKxdL",
-"BbwgAB3qem","ulk41YjB9t","Cp3mZECMvU","RsQUquQIcz","WMiS3CIShG","WPmlxTwano","jfREuNAFuw","8RCUAtjQxs","aL6AJ8hJdt","J2mQiZ4I1v",
-"FGzgpTa8f6","vLsmSKZamH","HlUbFWaim6","HRxd8bgJAz","fFDrJqQxHP","soy9tGXdoH","l83UdtAOsr","WPmlxb29RJ","JKWYR3weIF","rz7Utn1pmO",
-"In3NSIKxdL","lViBvReKEW","guMb8n1pmO","UlU3MuPX7G","jSjS3pvgjS","sx5Gldjsrv","GWqqXIBe8k","uoStwb29RJ","e6e4z7fKYU","M6qcGtaOXK",
-"9rlg9WreyP","lCMxygdQsS","taOXK3otm6","he9IAl83Ud","Pb1pam4bxU","Gv3FqcQOnv","ZJTXHYw2oU","Ul4a13otm6","GSQwjRpBQm","SmGzvMezSW",
-"FhtglQssNC","7fsYMNcICA","FcWrWuQIcz","0BmCyl83Ud","9iGoTCdyBV","fcwDaix74r","lH1kt07n1c","s7Mxk2hEEU","Ss0ZuX6Pin","FwEJzKr8ys",
-"tlILtSbRYy","fqypy5IhmG","i7WMQ7lUXZ","2Yz7EguMb8","1LB1Lhi5X7","KsjRK4W0Tl","16lHcJIqXi","zHF1qlH1kt","0Wr5yCqqaD","uupzkpAhR1",
-"W3VFHChuy3","fqypyLewvM","yofH3QChxs","7fKYUfLNg8","8cVD3DG4sT","JKWYR48cHL","WDVWJTwano","7fKYUpAhR1","MaJQs0h1b1","7lUXZKr8ys",
-"GWqqXlkMUA","5drc6F6PT2","prNT60Wr5y","hE1QlzmLYD","IRh48hUTw7","0h1b1Mkgy8","S2DfuThjNn","Ta8f6wiHrZ","lCMxyWMiS3","hSSvQFjHXR",
-"lXFOBi3pyd","dQ5865Namm","zbIYY45cIH","zHF1qyEfy9","Dz1R3CxVEf","piJSkTwano","LbRTHwDajX","9iGoTWDVWJ","QworuZJTXH","hYBCKtaOXK",
-"uPX7GdhSuH","yToGWGXdoH","BpYhVpv0i7","LewvMe6e4z","v2eC39GXkX","i7WMQx3LDe","NcICA14FLR","h1zcHI7p2a","s93MlIjTwP","uPX7Grhl0J",
-"zQt6QjeskS","0h1b1MK07Y","5IhmGIBe8k","QWxoTVBjhz","MmsIoFFDui","2Nslm8RCUA","4W0TlIKxdL","lXFOBhUTw7","VerEAVprf2","ksJbyjfREu",
-"J2mQiWaWsv","BCxeCJKWYR","tAOsrdhSuH","jfREuL7cGc","4QMc907n1c","WPmlxBCxeC","2DREsFVMxo","LDk6flCMxy","G1RhS8U2nU","gjUTuX6Pin",
-"Cfgr3SWfou","piJSkLDk6f","lkMUAWreyP","piJSk5iGN5","hUTw7zHF1q","zmLYDv2eC3","pvgjSM3zXL","uJScXDG4sT","P6bcg9iGoT","0BmCywDajX",
-"DG4sTYjB9t","a00b5pmeCd","5Drn0HfyNQ","Waim65VZjS","8TxD75Drn0","X6PinCK5W7","jfREuDQimp","IjTwP9GXkX","lm0pDW3VFH","9y4lwlH1kt",
-"DG4sTWreyP","L7cGcFNYIM","Oz8yZdhSuH","hYBCKpvgjS","Zv7z0YOfrY","CIShGsoy9t","NcICAa00b5","OUqFMMmsIo","JKWYRLewvM","Ul4a1hE1Ql",
-"EOE1onnP8o","Yw2oUlm0pD","S77LHSjskQ","M3zXLlpF6W","X6PinokgRi","618Di5nmWv","tlILtcL0aE","Cfgr3C2Irc","MGlTFuN6r3","CxVEfGSQwj",
-"5Mg9rJkzUn","MezSWVjCZq","jfREuJ2mQi","tvdkDyluBx","t59lRCp3mZ","zz4ZUjeskS","TwanoFjHXR","VIlwPBFkb8","hSSvQRpBQm","YjB9txReec",
-"0Wr5yEoToP","SWfouwDajX","uoStwMm8si","MezSWlCMxy","RzaZA2Nslm","CdyBVReKEW","2hEEUpmeCd","fcJOyhUTw7","sqVrfJkzUn","zqH0WhUTw7",
-"5VZjSIRh48","ECMvUI7p2a","S77LH9GXkX","3otm6l83Ud","dQ586oGu6x","oVQp6pT8wu","oGu6xb29RJ","KASQ8VerEA","dQ586Ss0Zu","QYxC0IjTwP",
-"Yw2oU4dEz6","Yw2oUv1Hln","5NammRxrsm","WaWsvwDajX","FFDuiS77LH","kZANmlXFOB","hi5X7yluBx","Pb1paogLgc","CK5W7aDGtS","LDk6fnFqik",
-"NAFuwYf2Ec","O3iyQ5iGN5","lpF6WZhwG1","cShY2hUTw7","zbIYYIKxdL","OxWIHn1pmO","Fhtglk85Ae","M6qcGuPX7G","0ao3l64s8N","lj07QMaJQs",
-"4W0TlwDajX","Cfgr3ZUnqt","JKWYRpv0i7","C2IrcwDajX","l83UdAkKTk","4W0TlbrhlQ","nFqikK4GS8","faHirZzJHW","AXpwEVjCZq","kB5nPEOE1o",
-"wDajXQWxoT","guMb8b29RJ","Q6LixS77LH","AOgEeaez9y","2Nslmgf8rI","14FLRdhSuH","1j5L8zQt6Q","lj07QHfyNQ","ulk41618Di","QworuuoStw",
-"lj07QzQt6Q","brhlQ2hEEU","YjB9tmz8gx","ECMvU7X3uy","kB5nPdmoS7","BFkb8BbwgA","sqVrfOz8yZ","1v5hHpFrrl","K4GS848cHL","LbRTH7ku1p",
-"LewvMlH1kt","FcWrW4dEz6","DQimpSbRYy","QClRL2ZHdk","16lHc5nmWv","MGlTFgf8rI","Mkgy8DQimp","WmadA8hJdt","BFkb8d85a9","LbRTHMezSW",
-"NhXdujiVBP","FnPFBru4UG","Q6Lix5drc6","v2eC3ECMvU","vOqCE5Namm","dmoS7iB08l","zHF1qlm0pD","cL0aEM6qcG","CIShGblLA9","xXTI4Waim6",
-"IjTwP9XyT9","7hyVvS2Dfu","cShY21v5hH","5Drn09GXkX","L7cGcHfyNQ","yluBxReKEW","5IhmGtvdkD","FPfSEa00b5","RkQkeX6Pin","TCgPpqUJMd",
-"BCxeCEOE1o","tlILtzbIYY","rKDLJ24ARF","QnJ1S4dEz6","MmsIofmIK1","07n1cPYBf4","tuDySuN6r3","x3LDeSs0Zu","a00b5guMb8","vLsmSgdQsS",
-"b29RJUlU3M","RpBQmyofH3","uLtKs0Kyfs","PYBf4AXpwE","SbRYyGrDg7","FLsph6q6L9","No0Qb8TxD7","aFFssXflUq","XyPZNQbxXc","ulk41GSQwj",
-"fqypy9y4lw","Mkgy8Nxx9V","dQ586U3yw5","tAOsrhe9IA","lViBvi7WMQ","he9IAfFDrJ","gf8rID6rBy","yToGWk85Ae","16lHc0Kyfs","SWfouZhwG1",
-"ZUnqtQbxXc","vkCHHguMb8","8xEKzYOfrY","jSjS37X3uy","RzaZA7X3uy","GrDg7TXQ0Z","HP433soy9t","yluBxcShY2","ZuDtDi7WMQ","Kr8ys64s8N",
-"uN6r3zHF1q","FwEJzJRJQB","d85a9M6qcG","wDajXfFDrJ","blLA9JIqXi","lH1kt8U2nU","Q6Lixsoy9t","k85AeuJScX","dhSuH6AFT0","NcICAM6qcG",
-"StlDJix74r","Fhtgldpe1v","n1pmOlCMxy","pFrrlS77LH","Yf2Ec9GXkX","t59lRFGzgp","WaWsv2Nslm","WreyPW7cTs","Mm8sib29RJ","qaofNsx5Gl",
-"h1zcHLewvM","ZzJHWwDajX","RpBQmQWxoT","7fKYUQChxs","7Ow5ClpF6W","hi5X7v2eC3","FjHXRfqypy","VLTy6X6Pin","MojnPlCMxy","I7p2ahi5X7",
-"QYxC0I7p2a","ydG8Ugf8rI","JKWYR3otm6","nlaByuQIcz","8xEKzsuY4x","i7WMQnnP8o","Rxrsm9iGoT","x3LDeazIWp","s7MxkRxrsm","uoStwuZPqg",
-"fcJOyQ6Lix","VerEAYOfrY","fFDrJ7fsYM","AOgEerhl0J","uQIczSbRYy","Yh1hFyofH3","W3VFHZUnqt","W7cTsuPX7G","UmaEvMm8si","zY1GYZUnqt",
-"gf8rIQworu","Yw2oUvOqCE","taOXKFPfSE","zY1GYXyPZN","xXTI4pFrrl","IRh48DcpWB","guMb8uPX7G","uvf7Alm0pD","tuDyS45cIH","EOE1o7lUXZ",
-"GrDg7OUqFM","16lHcFVMxo","LewvMokgRi","RpBQmlH1kt","TwanoJkzUn","uPX7GVIlwP","i7WMQ9y4lw","yvOMIgtCA5","uoStwi7WMQ","BGaQYdmoS7",
-"zHF1q4dEz6","dhSuHW7cTs","2TRI7F6PT2","n1pmOZv7z0","SmGzvaez9y","HlUbFHfyNQ","blLA9a00b5","gdQsSiB08l","BpYhVfmIK1","blLA99iGoT",
-"yEfy9IRh48","GXdoHHRxd8","xXTI4G1RhS","suY4x14FLR","9iGoTQChxs","Yf2Ec2TRI7","GWqqXuvf7A","CIShGdhSuH","HfyNQBbwgA","14FLRtlILt",
-"NAFuwv1Hln","P6bcgVNCPd","yluBx5nmWv","KZamHs7Mxk","WaWsv7ku1p","b29RJxciqp","lXFOB9iGoT","UlU3M0h1b1","QworuaFFss","1v5hHAkKTk",
-"8RCUA2hEEU","tjQxskZANm","LDk6fuPX7G","8xEKzFcWrW","ZhwG1Chuy3","FhtglhYBCK","gIYvEoVQp6","07n1cWmadA","0ao3lWaim6","bgJAz2DREs",
-"Pb1paVerEA","xXTI4sx5Gl","Yh1hFgdQsS","7fsYMogLgc","8RCUAGv3Fq","cmXIXQnJ1S","okgRiLbRTH","faHirzmLYD","S77LHX6Pin","piJSkqQxHP",
-"Z4I1vgtCA5","h1zcHThjNn","sqVrfdhSuH","EdBKcqUJMd","ReKEWs4786","ni2v1IKxdL","ciuWzmz8gx","Q6LixNcICA","M6qcGIBe8k","ix74raFFss",
-"s93Ml0h1b1","BbwgASbRYy","CK5W7VjCZq","4W0TlqUJMd","taOXKD6rBy","S2Dfu45cIH","ZuDtDuLtKs","tjQxsiKqhr","Waim6Twano","K4GS8hi5X7",
-"MGlTFEoToP","RACujCdyBV","1LB1LCqqaD","uJScXzz4ZU","In3NSoQ87r","MGlTFFVMxo","MojnPEdBKc","DQimpKZamH","zFgtBGv3Fq","I7p2aaFFss",
-"FxX9qn8pJ9","gjUTu5drc6","m4bxU9GXkX","WMiS30Kyfs","sx5GlSs0Zu","uLtKs5Drn0","dhSuHaFFss","nlaBymz8gx","WMiS3uTacx","MaJQslweGy",
-"jzUqRFnPFB","RmDcrD6rBy","wDajXlCMxy","S77LHiKqhr","AgJHQgtCA5","QClRLW3VFH","ksJbyChuy3","FnPFBG1RhS","2hEEUJKWYR","580YDGWqqX",
-"2ZHdkzqH0W","bgJAzBpYhV","AkKTk45cIH","brhlQatef2","MGlTFZ4I1v","iKqhr9rlg9","yToGWrhl0J","lCMxyUmaEv","rhl0JFGzgp","okgRirhl0J",
-"o8UydbgJAz","VjCZqTwano","rhl0J8FmFH","Rxrsmtl72W","fFDrJuLtKs","OUYuF7Ow5C","QworuFNYIM","JRJQBogLgc","1v5hHHRxd8","580YDzbIYY",
-"AXpwE5Drn0","Nxx9VlXFOB","8xEKzl83Ud","8TxD7HlUbF","MK07Yfqypy","C2IrcOUYuF","dpe1vAgJHQ","ZJTXHHlUbF","zFgtBFcWrW","RxrsmO3iyQ",
-"qQxHP7fKYU","DLhzM8xEKz","ECMvUNo0Qb","cQOnv0Wr5y","Dz1R39rlg9","5Drn0oQ87r","24ARFTwano","ZuDtDJIqXi","aL6AJCxVEf","2Yz7E6AFT0",
-"NOHszBbwgA","VIlwP1v5hH","jtn0XwDajX","W7cTsaFFss","NhXdum4bxU","0YAGHC2Irc","lsQGoUmaEv","2hEEUSs0Zu","aDGtSs7Mxk","J2mQiKr8ys",
-"M6qcGKZamH","3otm6djsrv","7fsYMMGlTF","WDVWJM6qcG","8FmFHJXljW","yToGWlpF6W","07n1cC2Irc","NcICASjskQ","2TRI7uAWyp","xciqpCIShG",
-"dpe1vX6Pin","faHirguMb8","QssNCKsjRK","tlILtUl4a1","zmLYDMmsIo","FjHXRFPfSE","J2mQi5IhmG","Ul4a1SmGzv","aez9yyofH3","W3VFH1j5L8",
-"GrDg7B3qem","Chuy32TRI7","Zv7z0pAhR1","EdBKcJ2mQi","FVMxoBGaQY","y94nw2Nslm","IKxdLm4bxU","2NslmHRxd8","ZzJHW7lUXZ","K20wKaFFss",
-"5drc68FmFH","NhXduW3VFH","CxVEflViBv","e6e4zqaofN","XflUqnnP8o","7lUXZt59lR","QnJ1SjfREu","C2Irc2ZHdk","rKDLJgjUTu","ru4UGatef2",
-"CIShGydG8U","BFkb8xXTI4","v2eC3SmGzv","tlILtfaHir","M3zXLzY1GY","iwzGkDLhzM","Y1mC02DREs","pAhR1ogLgc","AmdQddjsrv","OHaBzWDVWJ",
-"6q6L9U3yw5","piJSkcQOnv","i7WMQDLhzM","aDGtSdmoS7","0BmCyv8yFN","nlaBylm0pD","9XyT9IKxdL","P6bcgvkCHH","ksJby5nmWv","jS1ajfFDrJ",
-"lweGyv2eC3","tl72WUl4a1","pFrrlFxX9q","iqv4kzHF1q","xReecWDVWJ","In3NSy94nw","Mm8siGrDg7","pvgjSU3yw5","ksJbyHRxd8","xXTI4cShY2",
-"LbRTHguMb8","UlU3MgtCA5","FFDuiuvf7A","P6bcgpWiOs","KASQ8G1RhS","FnPFBn8pJ9","1j5L88RCUA","9GXkXO3iyQ","RsQUqzz4ZU","vkCHHdpe1v",
-"tl72WJKWYR","Cp3mZ3otm6","ZJTXHgf8rI","suY4xP6bcg","VjCZqrhl0J","BFkb8i3pyd","D6rByNo0Qb","BCxeCFFDui","AgJHQtlILt","ru4UGBbwgA",
-"4dEz6RBhp0","pWiOsoGu6x","5IhmGjS1aj","cQOnv8xEKz","7hyVv7fKYU","I7p2alj07Q","Pb1paUvlv4","hUTw75Drn0","9iGoTVLTy6","tAOsrru4UG",
-"lm0pDD6rBy","ZuDtDGXdoH","hSSvQYw2oU","hE1QlW3VFH","NcICAX6Pin","uQIcz3otm6","MojnP8RCUA","SmGzvHRxd8","5VZjSVNCPd","L7cGcY1mC0",
-"IKxdLs93Ml","mX2GEZJTXH","DQimpoQ87r","Yf2Ecm4bxU","BFkb8x3LDe","vLsmSbZLvS","JKWYRbrhlQ","uoStwd85a9","yToGWMm8si","K20wKQworu",
-"okgRiKZamH","gIYvEfcwDa","CK5W7WmadA","taOXKEdBKc","jzUqRReKEW","piJSkK20wK","VerEApT8wu","JXljWGv3Fq","Y1mC014FLR","Mkgy86AFT0",
-"CdyBVW3VFH","RACujRACuj","K4GS87fKYU","In3NSnlaBy","RpBQm45cIH","LbRTH5IhmG","jiVBPgjUTu","Zv7z0ThjNn","uoStwM6qcG","9GXkXsuY4x",
-"1j5L8gjUTu","TCgPpyvOMI","zHF1qsx5Gl","5Mg9rrhl0J","vLsmS0h1b1","7Ow5CRxrsm","dhSuHkZANm","RkQkeYf2Ec","ogLgcciuWz","BbwgAfcwDa",
-"djsrvW3VFH","7Ow5CFFDui","VerEA580YD","jzUqRW3VFH","QYxC0lXFOB","YOfrYqaofN","kZANmlj07Q","lm0pDIBe8k","jeskSxciqp","MGlTFrKDLJ",
-"pmeCdVjCZq","DLhzMO3iyQ","pmeCdJIqXi","y94nwB3qem","uLtKszbIYY","9XyT9dmoS7","RzaZAYh1hF","brhlQQnJ1S","SjskQt59lR","1LB1LfcwDa",
-"FcWrWk85Ae","NhXduMojnP","d85a9ZzJHW","uTacx8xEKz","dQ586AOgEe","pWiOstl72W","vkCHH9rlg9","2DREscmXIX","RmDcrNhXdu","EdBKc2Yz7E",
-"jiVBPlweGy","QClRLK20wK","9GXkXuJScX","s4786bZLvS","CdyBV6AFT0","TXQ0ZFVMxo","8FmFHkZANm","dmoS75IhmG","uoStwAkKTk","n8pJ9qaofN",
-"24ARFi3pyd","9GXkXv1Hln","iB08lKZamH","7hyVvXyPZN","y94nwjiVBP","zbIYYC2Irc","Z4I1vzFgtB","WreyPlpF6W","QnJ1SfcJOy","qaofNDz1R3",
-"0Kyfs9y4lw","i3pydO3iyQ","O3iyQtvdkD","2hEEUx3LDe","VerEA5IhmG","LbRTHpWiOs","QWxoTSs0Zu","9XyT9fmIK1","G1RhSt59lR","lm0pDTwano",
-"9y4lwNOHsz","4W0TlZhwG1","1j5L8Qworu","OUqFM8cVD3","cQOnvVjCZq","0h1b1cShY2","gtCA59iGoT","gjUTuZUnqt","bZLvSTwano","KASQ81LB1L",
-"JIqXiVBjhz","VLTy6tl72W","oGu6xhYBCK","580YDprNT6","5NammfaHir","fmIK1EdBKc","OxWIHt59lR","VIlwPjiVBP","55rfBM3zXL","yEfy9Mm8si",
-"DQimp7fsYM","5NammW3VFH","U3yw5ReKEW","0MR5X0ao3l","bgJAzMmKGJ","RsQUqo8Uyd","2ZHdkk85Ae","RsQUqrKDLJ","JkzUnuAWyp","h1zcHGSQwj",
-"hSSvQ5iGN5","dQ586VBjhz","K20wKFcWrW","Mm8siUmaEv","6q6L9MGlTF","QssNCi7WMQ","tvdkDs7Mxk","djsrv55rfB","vOqCEOHaBz","FNYIMRzaZA",
-"8cVD3uAWyp","o8Uyd9y4lw","rz7UtsuY4x","Dz1R3lj07Q","BbwgAW3VFH","CNHmvEdBKc","ix74rLewvM","d85a9zbIYY","EOE1oxXTI4","Vprf2BCxeC",
-"uJScXatef2","BCxeCpv0i7","vkCHHTXQ0Z","vLsmSEoToP","pv0i7v2eC3","uPX7GZuDtD","4QMc9SWfou","QnJ1SYh1hF","cShY2ZhwG1","d7vjMUvlv4",
-"BGaQYni2v1","iwzGkqQxHP","QYxC0tvdkD","pAhR1ydG8U","rhl0JyvOMI","xciqpOUqFM","uJScX7fKYU","dQ586No0Qb","hUTw7ru4UG","580YDVjCZq",
-"FnPFB5Drn0","zmLYDS2Dfu","NAFuwIjTwP","lweGylj07Q","mz8gxazIWp","618DiAXpwE","CxVEfuupzk","QWxoTdhSuH","FLsphJIqXi","uoStwM3zXL",
-"gjUTuAOgEe","8xEKzzQt6Q","yEfy9580YD","ni2v1jeskS","NOHszhYBCK","dpe1vWPmlx","In3NS48cHL","t59lRa00b5","soy9tKASQ8","8U2nU45cIH",
-"CxVEfcShY2","MGlTFzmLYD","TwanookgRi","yEfy9yofH3","MaJQsSbRYy","3otm6lXFOB","pv0i7IBe8k","Ul4a12ZHdk","dmoS77fKYU","C2IrcFnPFB",
-"lXFOBF6PT2","prNT69eoRc","W7cTsjtn0X","uAWypxXTI4","uvf7A7hyVv","StlDJs7Mxk","yToGWVIlwP","tlILtWreyP","FVMxo45cIH","WreyPn1pmO",
-"Yf2EcprNT6","LDk6f7Ow5C","pAhR1F6PT2","WMiS3OUqFM","6AFT0dpe1v","zqH0W0ao3l","OUYuFgIYvE","hi5X7aDGtS","WreyP4W0Tl","MezSW618Di",
-"fcwDa618Di","jfREuuJScX","JKWYROUYuF","NcICALDk6f","U3yw5Yh1hF","gIYvEkZANm","FPfSEJXljW","guMb8XyPZN","FFDui2TRI7","ZzJHW8xEKz",
-"zHF1q0h1b1","RxrsmAgJHQ","LbRTH9eoRc","ydG8Ujtn0X","L7cGcokgRi","x3LDetuDyS","xXTI4S2Dfu","bZLvSi7WMQ","KZamHrKDLJ","dhSuHX6Pin",
-"JIqXiCNHmv","3weIFVLTy6","ZUnqtFnPFB","dQ586zz4ZU","StlDJt59lR","prNT6brhlQ","O3iyQlsQGo","5Drn0tuDyS","Nxx9VFNYIM","Rxrsm2TRI7",
-"OUYuFTCgPp","zY1GY4QMc9","pAhR1WreyP","uupzk8FmFH","ThjNnyofH3","WaWsvRsQUq","G1RhSuTacx","IRh48IjTwP","Yw2oU2hEEU","djsrvReKEW",
-"7Ow5C5IhmG","X6Pinv2eC3","bgJAzQnJ1S","ksJbyIn3NS","HlUbFYf2Ec","pmeCdpmeCd","oVQp6zFgtB","sx5GlVBjhz","3weIFtaOXK","I7p2ahYBCK",
-"45cIHlpF6W","I7p2aoVQp6","azIWp0Kyfs","KASQ8yofH3","ciuWzCfgr3","wiHrZ6q6L9","64s8NxReec","tl72WjS1aj","FnPFBQYxC0","fLNg8MojnP",
-"ni2v1W7cTs","Zv7z05Drn0","uZPqg7lUXZ","nnP8oLbRTH","DQimpn8pJ9","14FLR7X3uy","16lHcLewvM","D6rByZzJHW","7fsYM7lUXZ","gIYvEZUnqt",
-"FGzgpv8yFN","fmIK1TXQ0Z","kB5nPHfyNQ","x3LDeiqv4k","y94nw5iGN5","XflUq8U2nU","7lUXZKZamH","s93MlGXdoH","F6PT2pv0i7","AOgEeWmadA",
-"AgJHQyofH3","NOHszTCgPp","YjB9tguMb8","LDk6fgjUTu","soy9tsx5Gl","HlUbFfaHir","Ul4a19y4lw","piJSkIKxdL","VLTy68RCUA","FFDuiGWqqX",
-"Ss0ZuWreyP","v1HlndhSuH","StlDJ7hyVv","ksJbytl72W","he9IAGSQwj","0Wr5y48cHL","XflUqBpYhV","EOE1oKZamH","vOqCEJKWYR","zbIYYOHaBz",
-"CqqaDMmKGJ","o8UydWreyP","GWqqXuJScX","pAhR1JkzUn","OHaBzS77LH","C2IrczY1GY","PYBf49y4lw","jSjS32ZHdk","fqypy7ku1p","7lUXZCK5W7",
-"djsrv0h1b1","5Mg9rX6Pin","RzaZABCxeC","wiHrZHP433","GSQwjCp3mZ","580YD7lUXZ","dhSuHksJby","AOgEeFjHXR","BGaQYPOUYS","v8yFNprNT6",
-"IRh48M3zXL","tAOsrVNCPd","S2Dfu16lHc","MaJQsgtCA5","HP433uupzk","7Ow5CGv3Fq","jiVBP2Nslm","FFDuiprNT6","7X3uyokgRi","6q6L9blLA9",
-"YjB9tL7cGc","pmeCdlCMxy","VerEAYf2Ec","D6rBy580YD","Y1mC0oGu6x","zQt6QZv7z0","0h1b1F6PT2","lCMxy9GXkX","IBe8kQnJ1S","VjCZqb29RJ",
-"0YAGHVprf2","ydG8UjfREu","BCxeCpvgjS","TXQ0Zaez9y","lm0pDThjNn","AOgEetaOXK","yEfy9ru4UG","NcICA7Ow5C","W7cTsRpBQm","FcWrWM6qcG",
-"YjB9tokgRi","9y4lwn8pJ9","vkCHHlsQGo","QClRLiB08l","yofH30Kyfs","vkCHHKr8ys","VBjhzdQ586","cmXIXFxX9q","kB5nPRBhp0","cmXIXAmdQd",
-"WDVWJuQIcz","pWiOsStlDJ","Ul4a1NAFuw","e6e4zmX2GE","t98iWbrhlQ","i7WMQCqqaD","uZPqgDLhzM","pvgjSnlaBy","piJSk8xEKz","BpYhVru4UG",
-"dhSuHUlU3M","OHaBztvdkD","YjB9tSmGzv","qQxHPrKDLJ","OHaBzfqypy","rz7UtNhXdu","JkzUn8FmFH","t98iWksJby","8TxD7D6rBy","i7WMQs4786",
-"2hEEUwiHrZ","RsQUqOz8yZ","X6Pins93Ml","1v5hH48cHL","Ta8f60Kyfs","QClRLwDajX","9y4lwAIYUu","lweGyKsjRK","bgJAzjiVBP","pWiOsuTacx",
-"gIYvEO3iyQ","QWxoTgtCA5","azIWpnFqik","M3zXLoQ87r","bZLvSwDajX","d7vjMIjTwP","iB08l5Namm","4W0TlG1RhS","HzZT824ARF","rhl0JydG8U",
-"cL0aEJJs5m","taOXK8U2nU","RzaZAKASQ8","5Mg9rEOE1o","8xEKzUmaEv","WreyPQworu","uupzkFxX9q","bgJAzeuZA5","FLsphyofH3","pT8wuogLgc",
-"BGaQYHP433","POUYS9XyT9","iqv4ktjQxs","0Wr5yYjB9t","45cIHOUqFM","uupzkBCxeC","ydG8UgtCA5","4dEz6CNHmv","a00b5I7p2a","d7vjMpFrrl",
-"yEfy948cHL","jtn0XEoToP","0YAGHBFkb8","0Wr5yNcICA","zmLYDcShY2","qaofNv8yFN","0YAGHF6PT2","pAhR1aez9y","W3VFHQYxC0","zbIYYGrDg7",
-"14FLRVBjhz","ulk41jiVBP","IjTwPMojnP","3otm6zFgtB","Gv3Fqxciqp","1v5hHCqqaD","nFqikRkQke","ydG8UKASQ8","vkCHHQbxXc","In3NSvkCHH",
-"QChxs48cHL","tl72WQYxC0","AXpwExReec","9GXkXnlaBy","0YAGHs93Ml","jzUqRgtCA5","IKxdLzz4ZU","t59lR2hEEU","D6rByQworu","yToGWlXFOB",
-"zbIYYCfgr3","ZzJHWAmdQd","FhtglIKxdL","aL6AJSs0Zu","2Nslm9iGoT","S2DfuFjHXR","BpYhVMmKGJ","HlUbFhE1Ql","AkKTk2TRI7","0YAGHt59lR",
-"lkMUAfcJOy","bgJAzpWiOs","JKWYR7lUXZ","tuDySThjNn","DLhzMl83Ud","FjHXRLbRTH","rKDLJ0Kyfs","RsQUqQnJ1S","3otm62hEEU","AkKTkv2eC3",
-"DcpWBs93Ml","2ZHdkZhwG1","Ss0ZuIKxdL","RBhp0AIYUu","QWxoTDz1R3","aez9yYjB9t","5ZaEz7fKYU","CqqaDlj07Q","FLsphjeskS","1LB1LFhtgl",
-"CxVEfAgJHQ","JKWYRiKqhr","i3pydciuWz","SbRYyFnPFB","taOXKBFkb8","Waim6IBe8k","ZuDtDa00b5","14FLRmz8gx","yofH3uQIcz","C2Irc7fsYM",
-"2hEEUlsQGo","O3iyQFPfSE","U3yw5soy9t","Qworu4QMc9","SjskQVBjhz","Q6LixHfyNQ","29QAzuQIcz","Yw2oUhSSvQ","gIYvEjeskS","Yf2EcEdBKc",
-"5Drn0B3qem","07n1c618Di","tjQxsrKDLJ","SmGzvYh1hF","K20wKrKDLJ","VerEATCgPp","HRxd8lkMUA","s7MxkYjB9t","UmaEv9iGoT","djsrvjSjS3",
-"5iGN5uLtKs","7hyVvi7WMQ","GWqqXrhl0J","m4bxUpWiOs","fLNg88xEKz","5nmWvuJScX","AkKTk29QAz","JIqXiWDVWJ","lm0pDK4GS8","VNCPd1j5L8",
-"m4bxUJ2mQi","0YAGHx3LDe","Chuy35Drn0","OUYuFmX2GE","JKWYRLDk6f","yluBxOUYuF","QnJ1S45cIH","Y1mC0RpBQm","rz7UtpiJSk","16lHcWDVWJ",
-"JkzUn2TRI7","fcwDatlILt","CK5W7JXljW","zHF1qP6bcg","YjB9t29QAz","9XyT9M3zXL","7X3uyJ2mQi","FnPFBOUYuF","s4786piJSk","7Ow5CiKqhr",
-"7hyVvSjskQ","KsjRK5ZaEz","uoStw0ao3l","Q6hMCCfgr3","Dz1R3Zv7z0","faHiriwzGk","WDVWJgtCA5","MaJQsPOUYS","pFrrlpvgjS","vkCHHlm0pD",
-"v2eC3WPmlx","9GXkXOz8yZ","7Ow5CDG4sT","yluBxBpYhV","Uvlv4JkzUn","In3NS07n1c","FGzgp7lUXZ","xXTI4WmadA","K20wKSs0Zu","uupzkZJTXH",
-"nFqikUl4a1","guMb8FjHXR","a00b5LewvM","bgJAzazIWp","yofH3euZA5","Yf2EcQworu","GSQwjjeskS","DQimpeuZA5","Waim62DREs","pFrrlAgJHQ",
-"0BmCyQYxC0","FhtglNo0Qb","Z4I1vFLsph","fcJOyZ4I1v","d85a9KsjRK","CK5W75IhmG","JRJQBFNYIM","jzUqRhE1Ql","Chuy3BbwgA","tuDySKsjRK",
-"pT8wu8FmFH","nnP8oG1RhS","ZhwG1xXTI4","F6PT2S77LH","v2eC30MR5X","NcICAU3yw5","jzUqRFGzgp","64s8NRkQke","fFDrJ2ZHdk","Gv3FqPb1pa",
-"e6e4zlj07Q","AOgEeD6rBy","v8yFNiwzGk","dQ586uTacx","ZJTXH8xEKz","M3zXLJ2mQi","8TxD7fcwDa","J2mQi3weIF","NOHszbZLvS","uvf7AgIYvE",
-"dQ586s4786","a00b5xciqp","LewvMzFgtB","uQIcz2ZHdk","ZhwG1Dz1R3","WPmlxDG4sT","F6PT2bZLvS","GSQwjtAOsr","Waim6e6e4z","tuDySS77LH",
-"soy9tWMiS3","iqv4k6q6L9","qQxHPl83Ud","618DiZzJHW","taOXK8xEKz","JKWYRTXQ0Z","7X3uyBFkb8","JXljWKr8ys","5Mg9rP6bcg","Nxx9VGWqqX",
-"v1Hln5Drn0","uN6r32Nslm","oGu6xjtn0X","WmadA4QMc9","Mm8sidjsrv","BFkb8dQ586","pv0i7FVMxo","Ss0ZuogLgc","HzZT8bZLvS","OUqFMZhwG1",
-"x3LDeQWxoT","VerEApWiOs","lViBvUlU3M","TCgPpGSQwj","lj07QPYBf4","8hJdtEOE1o","mX2GEOUYuF","ZUnqtvOqCE","vkCHHYf2Ec","oVQp6Yf2Ec",
-"G1RhSogLgc","wDajXlpF6W","i7WMQZJTXH","CdyBV7X3uy","5IhmGh1zcH","5Mg9rlCMxy","2NslmdhSuH","L7cGcuN6r3","9y4lw6AFT0","CqqaDdjsrv",
-"nFqikaFFss","ReKEW7Ow5C","5Mg9rYjB9t","tlILtAXpwE","In3NSTwano","Oz8yZnFqik","uvf7AVerEA","JRJQB9XyT9","45cIHaFFss","y94nwOHaBz",
-"WreyP2hEEU","CIShGtvdkD","QClRL0YAGH","atef2n1pmO","n8pJ955rfB","pv0i7FGzgp","JkzUnyToGW","9eoRcpWiOs","Yh1hFjeskS","ksJby9GXkX",
-"ulk41oGu6x","pvgjSlXFOB","7ku1pEdBKc","mX2GE7lUXZ","Q6LixtuDyS","uPX7GFxX9q","B3qemFjHXR","MojnPSs0Zu","0KyfsP6bcg","zY1GYpiJSk",
-"e6e4zy94nw","yvOMIIn3NS","W3VFHTwano","1LB1LbgJAz","lpF6WblLA9","2hEEUTXQ0Z","jSjS3L7cGc","Vprf2GWqqX","fcJOyWreyP","Mkgy8v8yFN",
-"lpF6WgdQsS","AXpwEKZamH","D6rByMK07Y","ReKEWMm8si","mX2GE55rfB","pAhR15Drn0","SjskQogLgc","gtCA5soy9t","7hyVveuZA5","2TRI7IRh48",
-"HP433Twano","Zv7z0JRJQB","l83UdRkQke","hi5X71j5L8","TCgPpWaWsv","qaofNBbwgA","W3VFH3weIF","uvf7A8cVD3","RsQUqZzJHW","zbIYYzQt6Q",
-"FLsphQnJ1S","14FLRlCMxy","nFqikLbRTH","MaJQsRBhp0","OUqFMtAOsr","U3yw5v1Hln","v1Hlnh1zcH","piJSkBpYhV","jtn0XcShY2","euZA5WMiS3",
-"F6PT248cHL","guMb8LbRTH","HRxd8y94nw","I7p2aKZamH","prNT6POUYS","pmeCdi3pyd","Mm8siI7p2a","pmeCdPb1pa","e6e4z9y4lw","lweGyeuZA5",
-"XyPZNX6Pin","i7WMQ2Yz7E","lm0pDuPX7G","xciqpsoy9t","5Nammd7vjM","CdyBVksJby","mX2GEjeskS","RkQkeJJs5m","14FLR9rlg9","WMiS3QssNC",
-"CdyBV9eoRc","lCMxylCMxy","J2mQijS1aj","29QAzuvf7A","zz4ZUkZANm","nlaByv8yFN","AmdQdlweGy","XflUqv2eC3","zQt6Qgf8rI","m4bxUy94nw",
-"Zv7z0OUqFM","G1RhSiB08l","X6PinciuWz","nnP8olH1kt","Nxx9VFxX9q","UlU3M8FmFH","fmIK124ARF","S77LHS77LH","ECMvUlj07Q","QssNCcmXIX",
-"P6bcgHfyNQ","b29RJFPfSE","5iGN5wiHrZ","iqv4kB3qem","8hJdtVjCZq","zHF1qhe9IA","jS1ajWMiS3","QnJ1SvkCHH","i7WMQCK5W7","8cVD3Dz1R3",
-"1LB1L7Ow5C","B3qemTa8f6","soy9tSmGzv","bgJAz5drc6","oVQp60ao3l","ECMvU2ZHdk","8cVD30MR5X","9rlg9uJScX","uPX7G7ku1p","0KyfseuZA5",
-"rKDLJ48cHL","wiHrZzHF1q","d85a9xReec","Mm8sizY1GY","NAFuwOUYuF","Q6Lix8TxD7","Yf2EctvdkD","MmKGJcL0aE","qUJMdGrDg7","kZANmuTacx",
-"AgJHQJXljW","MezSWQClRL","Nxx9VPb1pa","QChxsGrDg7","9XyT95IhmG","Mkgy8yluBx","8cVD3he9IA","JJs5mxciqp","oVQp6zqH0W","StlDJgtCA5",
-"L7cGczmLYD","AmdQdqaofN","UmaEvSjskQ","prNT6L7cGc","s4786dmoS7","SbRYyuJScX","BCxeCEdBKc","8cVD3a00b5","JKWYRhUTw7","29QAzFLsph",
-"pvgjS6q6L9","euZA57Ow5C","jzUqRBCxeC","EOE1ofcwDa","uJScX9y4lw","Ul4a18RCUA","FnPFBrhl0J","mz8gx0h1b1","suY4x5IhmG","nFqikaL6AJ",
-"14FLRuTacx","3weIFZuDtD","0YAGHFwEJz","lH1kt8hJdt","JJs5mTCgPp","CIShGAgJHQ","2hEEUn8pJ9","a00b524ARF","WDVWJRpBQm","G1RhS29QAz",
-"azIWpFnPFB","jeskS8xEKz","IRh48Qworu","1LB1Li3pyd","RACujjfREu","GXdoHsuY4x","M3zXLtlILt","azIWppiJSk","HzZT8W3VFH","MmsIoXyPZN",
-"a00b5XflUq","CK5W7lpF6W","LbRTHfFDrJ","yofH3v8yFN","dhSuH8U2nU","ThjNn7hyVv","9GXkXYw2oU","ReKEWa00b5","oGu6xciuWz","x3LDe07n1c",
-"DLhzMCIShG","HlUbF5VZjS","okgRiKr8ys","Mm8sifFDrJ","Cfgr3e6e4z","faHirlsQGo","RxrsmUvlv4","8TxD7Yf2Ec","7lUXZSbRYy","tjQxscQOnv",
-"Uvlv4Vprf2","NOHsz2DREs","FPfSE1j5L8","QChxsLewvM","KASQ8QClRL","dmoS7yEfy9","nFqikVerEA","IBe8kbgJAz","l83UdpmeCd","07n1cFLsph",
-"uN6r3O3iyQ","W3VFHZJTXH","VjCZqpiJSk","FcWrWqUJMd","CxVEf8FmFH","lViBv5Mg9r","5ZaEzRkQke","iKqhr1j5L8","gtCA5zY1GY","7fKYULbRTH",
-"IjTwPRBhp0","9rlg9mz8gx","uTacxX6Pin","6q6L94dEz6","NhXdufaHir","8FmFHAXpwE","he9IAIjTwP","DQimpDcpWB","oVQp6MezSW","JIqXib29RJ",
-"QYxC0uLtKs","t98iWgf8rI","RACujNOHsz","iwzGkFNYIM","aDGtSSmGzv","JXljW0Wr5y","RACujaDGtS","n8pJ9Chuy3","ksJbys7Mxk","yEfy9AmdQd",
-"lweGyFcWrW","W3VFHNxx9V","hUTw7tjQxs","faHirbgJAz","D6rByCfgr3","lCMxy7hyVv","v8yFNLDk6f","hYBCKAIYUu","sx5GlS2Dfu","0MR5XYjB9t",
-"CIShG7fKYU","hYBCKzqH0W","tAOsrVBjhz","FnPFBcL0aE","WMiS3FcWrW","EdBKczmLYD","oVQp6fLNg8","dhSuH5ZaEz","StlDJJKWYR","CK5W79rlg9",
-"BFkb8jS1aj","KsjRKnlaBy","Oz8yZS77LH","07n1cFFDui","POUYSQYxC0","WmadARpBQm","W7cTs9eoRc","cShY25Namm","FPfSEXyPZN","yToGWjzUqR",
-"cShY2aez9y","0MR5XMK07Y","GrDg7IRh48","dmoS7IRh48","LDk6f6q6L9","64s8NFjHXR","v8yFNv1Hln","ydG8UThjNn","8cVD3StlDJ","Pb1pauTacx",
-"CK5W7dmoS7","OHaBzPOUYS","X6Pinni2v1","MK07YblLA9","QClRLpWiOs","MGlTFo8Uyd","blLA9kZANm","64s8N29QAz","vOqCEdQ586","lkMUApFrrl",
-"vOqCEU3yw5","I7p2a5drc6","oVQp6QYxC0","4W0TlCdyBV","48cHL7X3uy","uQIczEOE1o","FPfSEMojnP","IKxdLFwEJz","QWxoTCIShG","QYxC0RzaZA",
-"BCxeCgtCA5","uoStwFNYIM","JIqXiO3iyQ","6q6L9CK5W7","D6rByHRxd8","hi5X7KASQ8","ReKEWEOE1o","tvdkD8U2nU","AOgEemz8gx","07n1cbgJAz",
-"fFDrJGSQwj","zmLYD8cVD3","PYBf4XflUq","EOE1ohe9IA","k85AeJXljW","PYBf4AOgEe","HlUbFJKWYR","Vprf2VerEA","lCMxy5nmWv","EoToPWDVWJ",
-"gtCA5rKDLJ","CNHmvVLTy6","Pb1paCp3mZ","4W0TljiVBP","Q6LixbgJAz","faHirfmIK1","0Wr5yt98iW","Dz1R3UlU3M","VjCZqrz7Ut","yvOMIdpe1v",
-"NOHszFNYIM","8xEKzbgJAz","hi5X7FPfSE","hUTw7SjskQ","zHF1qzFgtB","9y4lwQworu","2Yz7EVIlwP","jtn0XG1RhS","bgJAzbrhlQ","SWfou2ZHdk",
-"IRh48soy9t","fLNg8StlDJ","No0Qb64s8N","Nxx9VCp3mZ","AIYUuogLgc","BbwgA16lHc","aL6AJFwEJz","8TxD7RkQke","7fKYUuPX7G","n8pJ9jSjS3",
-"FVMxoRxrsm","Gv3Fq9GXkX","RkQkelsQGo","RzaZA0MR5X","VerEA7fKYU","5ZaEzvOqCE","yluBxWreyP","4W0Tl7fKYU","djsrvmz8gx","gdQsSfcwDa",
-"LbRTHtl72W","SmGzvulk41","ZhwG1lH1kt","CIShGZuDtD","OUYuFMaJQs","CNHmvRkQke","rKDLJ5Mg9r","uLtKssx5Gl","zmLYDDz1R3","16lHczmLYD",
-"618DiLewvM","5NammhYBCK","QworubZLvS","FFDui8cVD3","nnP8o7hyVv","D6rBy8cVD3","U3yw5HfyNQ","9rlg9fFDrJ","9eoRc8xEKz","GSQwjX6Pin",
-"gIYvEdjsrv","Z4I1v14FLR","CIShGazIWp","O3iyQFFDui","a00b52Nslm","fqypyPOUYS","okgRiEdBKc","e6e4zyToGW","hi5X7U3yw5","djsrvhSSvQ",
-"Q6hMCuAWyp","fcJOyHfyNQ","1j5L8uvf7A","FNYIMAXpwE","zmLYDrKDLJ","9GXkXprNT6","piJSkNAFuw","uAWypa00b5","iwzGkuJScX","rKDLJTCgPp",
-"GrDg7Q6hMC","a00b5S2Dfu","fqypygIYvE","aDGtSt98iW","45cIHyluBx","6AFT0NOHsz","0Wr5y0h1b1","07n1c8RCUA","LDk6f8hJdt","3otm60YAGH",
-"Mkgy8aDGtS","FFDuiEoToP","5drc6KsjRK","I7p2a6AFT0","DQimpS77LH","Ta8f6s7Mxk","AIYUu8U2nU","StlDJC2Irc","ksJbyXyPZN","2NslmZUnqt",
-"BGaQYFVMxo","SbRYyMGlTF","D6rByDz1R3","FVMxoMaJQs","Y1mC0lH1kt","FPfSEpmeCd","Mm8siuQIcz","3otm6lj07Q","lH1ktOHaBz","EOE1oZUnqt",
-"pAhR1zqH0W","jtn0Xs7Mxk","YOfrYblLA9","gtCA5DLhzM","2TRI7rhl0J","GSQwjUmaEv","HRxd81j5L8","qUJMd5Namm","rz7UtUvlv4","UlU3Mhi5X7",
-"3weIFsqVrf","yvOMIn1pmO","Yw2oUhE1Ql","HRxd8pmeCd","gdQsSb29RJ","45cIHGrDg7","SjskQQssNC","16lHcpiJSk","Z4I1vStlDJ","SbRYytuDyS",
-"FcWrWfqypy","7hyVvDG4sT","P6bcgBFkb8","MezSWSbRYy","45cIHSs0Zu","taOXK45cIH","7ku1pDQimp","2hEEU5iGN5","29QAzulk41","vkCHHazIWp",
-"VNCPd580YD","m4bxUTXQ0Z","vOqCEksJby","VerEAKZamH","5Mg9ruJScX","MmsIoOz8yZ","8cVD3s4786","QClRLs4786","K20wK45cIH","4dEz6Kr8ys",
-"4W0TlRBhp0","X6PinUl4a1","8RCUAjS1aj","FxX9qyvOMI","lH1ktI7p2a","P6bcgBGaQY","oVQp6In3NS","v8yFN5Drn0","MmsIorz7Ut","XflUqEdBKc",
-"TwanoxReec","OUYuFuLtKs","qaofNlpF6W","Ta8f6tvdkD","QssNChYBCK","KsjRKKZamH","Yf2EciKqhr","In3NSlj07Q","aFFssl83Ud","Oz8yZFGzgp",
-"gjUTuDLhzM","6AFT0tl72W","h1zcHpiJSk","gdQsSSs0Zu","zbIYY8hJdt","uJScXU3yw5","n8pJ97ku1p","RzaZAHzZT8","GSQwjzmLYD","GXdoHUl4a1",
-"AgJHQmz8gx","jSjS3cmXIX","IjTwPTCgPp","cL0aEhe9IA","ulk41OxWIH","zmLYDSbRYy","he9IADcpWB","wiHrZhe9IA","MojnPciuWz","uPX7GoVQp6",
-"iwzGkWmadA","NOHszvOqCE","AXpwEI7p2a","zY1GY618Di","dpe1vgtCA5","8cVD31LB1L","2TRI70YAGH","gjUTutjQxs","RpBQmd85a9","EdBKcNo0Qb",
-"ZuDtDKASQ8","Cfgr3ulk41","JXljWCqqaD","aez9yStlDJ","X6PinogLgc","lXFOBJ2mQi","lj07QB3qem","yofH3OxWIH","RpBQmCNHmv","24ARFt98iW",
-"xXTI4MmsIo","BCxeCCqqaD","45cIHM6qcG","uLtKs9eoRc","CqqaD1j5L8","9rlg9jzUqR","9iGoTe6e4z","pWiOsVerEA","5IhmGWMiS3","SWfoumX2GE",
-"RACujAOgEe","DcpWBv8yFN","ksJbyZv7z0","mz8gxK20wK","oGu6xs4786","LewvM2TRI7","CqqaDJJs5m","K4GS8CqqaD","MezSW7Ow5C","uAWypNOHsz",
-"5IhmGUl4a1","pvgjSHzZT8","lsQGoS2Dfu","F6PT2he9IA","HRxd8POUYS","OUqFMW3VFH","hi5X764s8N","W7cTsuAWyp","F6PT29eoRc","OUYuFFhtgl",
-"EOE1osoy9t","SjskQsqVrf","Cp3mZguMb8","JIqXiQChxs","2hEEUjeskS","lViBvOHaBz","RBhp0S2Dfu","vOqCE2Yz7E","55rfBDcpWB","EdBKciKqhr",
-"TXQ0Zjtn0X","zHF1qC2Irc","TXQ0ZOUYuF","yEfy9cmXIX","MaJQsk85Ae","Zv7z0uTacx","ZUnqtHRxd8","zbIYYd85a9","hUTw714FLR","8U2nUS2Dfu",
-"uN6r3FFDui","lViBvVjCZq","HRxd8DLhzM","JkzUna00b5","d85a9GXdoH","v1HlnPOUYS","6AFT0WreyP","e6e4zMezSW","gIYvEh1zcH","RkQkeAmdQd",
-"gtCA5v2eC3","Kr8ysKsjRK","OUqFMl83Ud","2DREsJJs5m","n8pJ96q6L9","WmadAM3zXL","Pb1paMm8si","2NslmC2Irc","QbxXc55rfB","5nmWvsx5Gl",
-"hE1QlHP433","ni2v1dQ586","nnP8ozbIYY","M6qcGaDGtS","aFFssuN6r3","lViBvFcWrW","CdyBVHP433","W3VFHzbIYY","s93MlCdyBV","Uvlv4lweGy",
-"oGu6x2TRI7","Oz8yZuJScX","v8yFN2ZHdk","EoToPJIqXi","jfREuVjCZq","mX2GESWfou","pv0i73weIF","hi5X7vLsmS","uvf7Ani2v1","oQ87rX6Pin",
-"TXQ0ZAXpwE","ix74rMK07Y","0Kyfs0h1b1","6q6L9J2mQi","uN6r3gIYvE","suY4x0BmCy","5Mg9r64s8N","Kr8ysFFDui","RBhp0fmIK1","prNT6ZJTXH",
-"L7cGcIjTwP","jtn0XqQxHP","d85a9S2Dfu","vkCHHAgJHQ","BGaQYC2Irc","Fhtgl4W0Tl","hE1QluLtKs","OHaBzYOfrY","ksJbyaFFss","fmIK1JRJQB",
-"QbxXcHzZT8","07n1cuJScX","Q6hMCKr8ys","AOgEeb29RJ","vLsmSv2eC3","EdBKcy94nw","NcICAeuZA5","aDGtShi5X7","BCxeC0BmCy","Gv3FqVIlwP",
-"Yf2Ec5IhmG","KsjRKPYBf4","iqv4k9y4lw","hi5X7Cfgr3","NcICA0PktI","Waim6hE1Ql","Waim6RmDcr","NcICAWreyP","LewvMSWfou","Yh1hFpAhR1",
-"uQIczoQ87r","qQxHPhYBCK","EOE1oCK5W7","SjskQEdBKc","BpYhV24ARF","prNT6suY4x","1LB1L0Kyfs","CxVEf5Mg9r","OUqFMlm0pD","1j5L8gtCA5",
-"MGlTFRsQUq","s7Mxkt59lR","v1HlnQnJ1S","HRxd8m4bxU","1v5hHjfREu","WmadALDk6f","ZzJHWaL6AJ","7hyVv7X3uy","s93MldmoS7","RACuja00b5",
-"lH1ktCNHmv","i3pydWaim6","2Yz7E618Di","CqqaD64s8N","TCgPpmX2GE","W3VFHK20wK","RACuj5drc6","t98iWqUJMd","yToGWVBjhz","Ta8f6v1Hln",
-"uupzkiB08l","iqv4kzQt6Q","7X3uy5nmWv","29QAzECMvU","cmXIXyluBx","uvf7ASmGzv","3weIFpT8wu","KASQ8s4786","5Mg9r3otm6","8hJdti3pyd",
-"he9IASmGzv","xXTI45Drn0","VNCPdG1RhS","sx5GloVQp6","hSSvQvkCHH","CdyBVQYxC0","DG4sThE1Ql","S77LHFLsph","gjUTuMK07Y","1LB1L07n1c",
-"qaofNRmDcr","W3VFH8RCUA","brhlQCxVEf","rz7UtwDajX","AkKTkNOHsz","h1zcHuoStw","7hyVvv1Hln","HP433aDGtS","EdBKc29QAz","VLTy6GSQwj",
-"FVMxoMGlTF","JRJQB8cVD3","cQOnv9y4lw","hE1QlNAFuw","1v5hHRpBQm","jeskSv8yFN","5NammgjUTu","RsQUqVLTy6","EOE1odhSuH","lpF6WcQOnv",
-"ydG8U16lHc","uPX7GK20wK","tlILtWMiS3","Kr8ysogLgc","Ta8f6LbRTH","XyPZNiqv4k","Cfgr30PktI","oQ87r9GXkX","FNYIMMojnP","dmoS7zY1GY",
-"HRxd8Q6Lix","Yf2EcMezSW","soy9tNcICA","X6Pin0MR5X","NcICAoQ87r","tl72WOUYuF","FwEJzSWfou","jSjS3rz7Ut","piJSkCfgr3","MezSWyEfy9",
-"JKWYR0Wr5y","X6Pinuvf7A","ECMvU0h1b1","nnP8oVIlwP","GrDg7EdBKc","Q6hMCC2Irc","7hyVvNo0Qb","Y1mC0ix74r","WmadAoQ87r","7lUXZuupzk",
-"AmdQd3weIF","IBe8kuZPqg","ksJbyrhl0J","azIWpZ4I1v","yToGWM3zXL","In3NS5Drn0","fqypys4786","ciuWzaez9y","CxVEf1v5hH","5drc6lpF6W",
-"HlUbFvLsmS","guMb89y4lw","OHaBz0PktI","48cHLReKEW","L7cGczHF1q","8U2nUzHF1q","rhl0JuZPqg","CxVEfKASQ8","NOHsz16lHc","azIWpblLA9",
-"PYBf4F6PT2","BpYhVD6rBy","zz4ZU2Yz7E","FFDuipv0i7","gjUTugtCA5","9eoRcJJs5m","aDGtS8RCUA","lViBvTwano","SbRYydQ586","yofH3qaofN",
-"lCMxy1j5L8","IKxdLMm8si","HzZT8HfyNQ","pAhR1uLtKs","K4GS8IjTwP","oQ87r1v5hH","2NslmChuy3","jS1ajmX2GE","pT8wubZLvS","8hJdtW7cTs",
-"Q6Lixtl72W","0KyfszHF1q","8xEKzfaHir","uAWyp7lUXZ","uPX7GWMiS3","7ku1pPb1pa","zQt6QoGu6x","EdBKcjfREu","JRJQB0h1b1","FcWrWRpBQm",
-"QssNCMm8si","7X3uytaOXK","hUTw7P6bcg","LbRTHB3qem","2ZHdklH1kt","RpBQmRmDcr","7fKYUfqypy","ksJby16lHc","hYBCKIRh48","oVQp6GSQwj",
-"jiVBP0YAGH","2NslmMezSW","OUYuFru4UG","QChxsKASQ8","8hJdty94nw","LDk6f0ao3l","s93MlVNCPd","zqH0Wmz8gx","uZPqgRACuj","OUqFMX6Pin",
-"v8yFNtuDyS","ksJbydmoS7","QbxXcTCgPp","45cIHk85Ae","MmKGJFNYIM","dQ586WMiS3","soy9tLDk6f","faHirQClRL","FcWrWCxVEf","dpe1vRACuj",
-"LbRTHQssNC","qUJMdnnP8o","Vprf2EdBKc","0PktIqaofN","5drc60BmCy","0PktILbRTH","FjHXRprNT6","rz7UtFFDui","7Ow5CeuZA5","m4bxUlXFOB",
-"Yh1hFuTacx","RACujCIShG","hi5X714FLR","L7cGcVIlwP","ni2v14W0Tl","M3zXLJkzUn","JRJQB64s8N","ix74r4dEz6","HRxd8Z4I1v","i7WMQfcwDa",
-"QYxC0RmDcr","FcWrWpv0i7","48cHLCdyBV","fLNg8FNYIM","QbxXcbZLvS","9y4lw07n1c","S77LHJKWYR","GSQwjjSjS3","YOfrYs7Mxk","RxrsmTwano",
-"GSQwjP6bcg","rhl0JgtCA5","8FmFHyEfy9","prNT68FmFH","UmaEvStlDJ","9XyT9tl72W","Q6LixpmeCd","24ARFBCxeC","ThjNnQClRL","JKWYRgf8rI",
-"XflUqa00b5","zY1GYtvdkD","8FmFHNo0Qb","kB5nPKr8ys","M3zXLZzJHW","pmeCdydG8U","VNCPdF6PT2","s7MxkVIlwP","jeskSYOfrY","pmeCdMm8si",
-"uZPqgUlU3M","MmsIoQWxoT","bZLvS6q6L9","HlUbF2TRI7","NcICAm4bxU","rz7UtRpBQm","uQIczBFkb8","WDVWJuupzk","jS1ajlpF6W","YOfrY55rfB",
-"9iGoTlCMxy","2Yz7EZuDtD","vkCHHnnP8o","StlDJFNYIM","RmDcrM6qcG","IjTwPzbIYY","e6e4z8cVD3","2ZHdkoVQp6","No0QbM6qcG","ydG8UCIShG",
-"2NslmVBjhz","07n1cprNT6","9eoRcQbxXc","GWqqXFVMxo","9GXkXfqypy","FxX9qHfyNQ","JkzUnsuY4x","fFDrJhYBCK","zmLYDnFqik","0Wr5yFjHXR",
-"mz8gxFjHXR","CNHmvx3LDe","9iGoTDG4sT","ZhwG1Gv3Fq","MojnP8TxD7","EdBKcjeskS","0MR5XXyPZN","KZamHHzZT8","KsjRKMK07Y","atef27hyVv",
-"O3iyQW3VFH","5iGN5Twano","JRJQBoQ87r","d85a99XyT9","fcJOy4dEz6","BGaQYY1mC0","29QAzdhSuH","7lUXZFcWrW","FnPFBzQt6Q","FGzgpRsQUq",
-"DcpWByofH3","DQimpQworu","YjB9tvkCHH","yluBxuN6r3","piJSkW7cTs","W3VFHRkQke","5VZjSt59lR","Zv7z0SjskQ","55rfBMm8si","uTacxYw2oU",
-"8xEKzSjskQ","No0Qb2ZHdk","FGzgpXyPZN","4QMc9he9IA","v8yFNs93Ml","tuDySGrDg7","JIqXiY1mC0","e6e4zhSSvQ","lweGyS2Dfu","wDajX2Yz7E",
-"d7vjMsuY4x","jS1ajCqqaD","cQOnvt59lR","WmadA14FLR","zY1GYWMiS3","qQxHPUlU3M","e6e4zQYxC0","OHaBzzmLYD","faHirzqH0W","jzUqRk85Ae",
-"fqypyLDk6f","JRJQBgdQsS","HfyNQjfREu","HRxd8s7Mxk","AmdQd9rlg9","5iGN5ogLgc","LbRTHIKxdL","yEfy9suY4x","U3yw5G1RhS","pWiOs0Kyfs",
-"fmIK16AFT0","nFqikDLhzM","guMb8Ss0Zu","mX2GEguMb8","JkzUnHlUbF","Rxrsm0Kyfs","uLtKspvgjS","FLsphtvdkD","JJs5mAmdQd","2hEEUWaWsv",
-"Oz8yZWPmlx","pT8wuydG8U","RxrsmXflUq","zQt6QWaim6","4QMc9lCMxy","WaWsvK4GS8","piJSk2TRI7","LDk6fgtCA5","rz7UtvkCHH","QnJ1Ss93Ml",
-"Ta8f6SmGzv","QWxoTvLsmS","tlILtpvgjS","2DREsJRJQB","Zv7z0MK07Y","FNYIMyvOMI","FPfSEs93Ml","lpF6WJkzUn","rhl0JOUqFM","X6PinPb1pa",
-"2hEEUP6bcg","EdBKcJJs5m","1v5hH2TRI7","WmadAdpe1v","5ZaEzGv3Fq","0Kyfsru4UG","0Wr5yHzZT8","vkCHHTwano","lj07Q0Kyfs","Uvlv4zqH0W",
-"jiVBPVIlwP","HzZT8Pb1pa","NAFuwjSjS3","14FLRM3zXL","SmGzviB08l","jS1ajlsQGo","7fsYMVNCPd","cQOnvY1mC0","580YDn8pJ9","tvdkDciuWz",
-"EdBKchUTw7","MmKGJKZamH","dmoS70h1b1","WreyPs93Ml","aez9yvLsmS","OUYuFFPfSE","ZUnqt2DREs","JXljWHP433","d7vjMK4GS8","7hyVvSWfou",
-"t59lR8FmFH","hi5X7CIShG","BCxeCBGaQY","HRxd8atef2","Zv7z0lViBv","1j5L8pvgjS","uZPqg1v5hH","Uvlv4IBe8k","zFgtBdpe1v","tl72WNxx9V",
-"lsQGodjsrv","Chuy3GWqqX","KsjRKHfyNQ","JKWYRcQOnv","zqH0WBbwgA","rz7UtqaofN","JRJQBrhl0J","Qworu29QAz","SjskQCNHmv","U3yw5v8yFN",
-"8TxD7BGaQY","CxVEfC2Irc","4dEz6blLA9","mz8gxTa8f6","azIWpVLTy6","8xEKzuvf7A","0h1b1gtCA5","uPX7GTa8f6","Fhtgl64s8N","SbRYyCxVEf",
-"9eoRcCxVEf","VerEAaDGtS","CxVEfWPmlx","K4GS8Uvlv4","tuDyStlILt","Nxx9VlsQGo","XyPZN7hyVv","SmGzvCdyBV","5Drn0WPmlx","0Wr5y8RCUA",
-"QnJ1SF6PT2","aL6AJru4UG","dhSuHM6qcG","cmXIXblLA9","piJSkiB08l","IRh48Q6hMC","kB5nPMojnP","qaofNSjskQ","tl72WydG8U","oGu6x5ZaEz",
-"HP433aL6AJ","aDGtSpiJSk","aFFssY1mC0","NcICAix74r","ulk41hE1Ql","dhSuHZ4I1v","pT8wujSjS3","xXTI4W7cTs","ThjNnVBjhz","oVQp60BmCy",
-"5NammvOqCE","guMb8LDk6f","JIqXiQWxoT","0Wr5yatef2","tvdkDvLsmS","wDajX7Ow5C","okgRigdQsS","MmKGJ45cIH","D6rByprNT6","DQimpgjUTu",
-"pWiOsbrhlQ","i7WMQP6bcg","M6qcGC2Irc","tl72Wi7WMQ","aez9ytaOXK","2Yz7EkZANm","JIqXiK4GS8","yToGWi7WMQ","GWqqXD6rBy","Q6LixNOHsz",
-"BpYhVP6bcg","zY1GYwiHrZ","2hEEUVjCZq","yEfy9Waim6","ECMvU0BmCy","djsrvtuDyS","GSQwjn8pJ9","lXFOBHP433","Chuy3rKDLJ","NcICA8FmFH",
-"azIWpF6PT2","5Drn0NOHsz","24ARF0Wr5y","KsjRKuPX7G","faHirDQimp","b29RJjSjS3","8TxD7KZamH","0YAGHW3VFH","TCgPpFcWrW","fcwDannP8o",
-"Yf2EcZhwG1","pmeCdIjTwP","3otm6VjCZq","QnJ1SpFrrl","brhlQK20wK","FwEJzS77LH","X6Pin7Ow5C","tuDySRpBQm","MK07YThjNn","LDk6fPb1pa",
-"5Drn05nmWv","CNHmvguMb8","VIlwPSWfou","ThjNnBpYhV","cQOnvWPmlx","i7WMQjtn0X","P6bcgEdBKc","okgRilm0pD","DQimpCfgr3","aez9yVLTy6",
-"RsQUqgIYvE","yofH3ZuDtD","FwEJzFhtgl","rhl0JiwzGk","hUTw7l83Ud","16lHc4dEz6","I7p2as93Ml","5Mg9rY1mC0","2Nslmt98iW","KsjRKblLA9",
-"FcWrW2TRI7","K4GS85drc6","fqypyhUTw7","KZamHuAWyp","Y1mC0kB5nP","6AFT0JKWYR","FwEJzdQ586","J2mQipFrrl","DQimpPb1pa","guMb8FPfSE",
-"Rxrsmmz8gx","0MR5X1v5hH","pvgjScShY2","MmKGJru4UG","0BmCyAXpwE","brhlQpmeCd","lXFOBNOHsz","GXdoHlm0pD","fcJOylm0pD","0h1b1rhl0J",
-"64s8NTa8f6","yvOMIuvf7A","i3pydRkQke","fmIK10YAGH","SWfouTXQ0Z","BGaQY64s8N","iqv4k0BmCy","5nmWvuQIcz","W3VFHL7cGc","uTacxS77LH",
-"F6PT2JJs5m","he9IAIn3NS","cL0aEiKqhr","v1HlnNxx9V","WPmlxAmdQd","yEfy9SbRYy","xciqpAIYUu","lH1ktWmadA","Ta8f6AOgEe","AIYUuVIlwP",
-"Ta8f6QbxXc","Ss0ZuUl4a1","WmadA9y4lw","WreyPVjCZq","5nmWvtlILt","3weIF5Drn0","cmXIX0h1b1","fFDrJ0ao3l","RmDcrhSSvQ","X6PinNo0Qb",
-"taOXKS2Dfu","Q6hMCyEfy9","SWfouUmaEv","Q6hMCtlILt","WaWsv3otm6","aDGtSAIYUu","XflUq5Drn0","8xEKz0BmCy","64s8NlH1kt","7hyVvni2v1",
-"9y4lw7fKYU","suY4xXflUq","uoStwTwano","16lHcpvgjS","SbRYyDLhzM","5Mg9rAXpwE","iwzGk5ZaEz","yToGWB3qem","0BmCyoQ87r","lweGygIYvE",
-"d7vjMjtn0X","TCgPpiKqhr","B3qemzmLYD","5iGN514FLR","7fKYUaL6AJ","kB5nP5Mg9r","EoToPVerEA","CK5W7zFgtB","PYBf4S77LH","AIYUut98iW",
-"0BmCyVLTy6","k85Aeni2v1","jiVBPulk41","D6rBy5drc6","CqqaDBbwgA","No0QbfFDrJ","Cfgr3Y1mC0","uLtKskZANm","fqypytaOXK","S2DfuDLhzM",
-"CK5W72ZHdk","QWxoTjS1aj","RxrsmjiVBP","8RCUA7hyVv","he9IAtAOsr","Waim645cIH","IRh48fmIK1","No0QbpWiOs","CqqaDguMb8","uN6r3ThjNn",
-"taOXKgf8rI","fFDrJ8hJdt","h1zcHsuY4x","gdQsSVBjhz","0ao3lix74r","YOfrYlXFOB","euZA5BpYhV","9GXkX8TxD7","CqqaDGXdoH","tuDyS9GXkX",
-"a00b514FLR","Qworun1pmO","pv0i75IhmG","nlaByru4UG","blLA9CqqaD","xciqpCK5W7","WPmlx1LB1L","UmaEvvLsmS","WreyPVIlwP","gf8rIRsQUq",
-"0PktIgtCA5","48cHLAmdQd","AkKTkS2Dfu","KASQ8ZUnqt","6AFT09GXkX","hUTw7t98iW","guMb82DREs","LDk6fCxVEf","sqVrfUmaEv","LbRTHru4UG",
-"WDVWJGXdoH","WaWsvRmDcr","WMiS3hSSvQ","Uvlv4oQ87r","iB08lGSQwj","Q6LixlH1kt","dmoS7jtn0X","y94nwECMvU","zHF1quTacx","29QAzlpF6W",
-"618DiFjHXR","5Drn0CdyBV","MmKGJAgJHQ","MmsIox3LDe","BFkb8TXQ0Z","7ku1pCIShG","jzUqR7lUXZ","ix74rPOUYS","cShY2FxX9q","48cHLl83Ud",
-"s7MxkbZLvS","F6PT2bgJAz","5drc607n1c","FwEJzzY1GY","Pb1pa7hyVv","07n1cOxWIH","b29RJfFDrJ","P6bcgX6Pin","MojnPlH1kt","W7cTsVBjhz",
-"RxrsmDz1R3","Nxx9VfaHir","HfyNQcShY2","ECMvUVprf2","lsQGobrhlQ","pvgjSdhSuH","fcJOyuZPqg","Z4I1vsuY4x","pT8wuUmaEv","djsrvo8Uyd",
-"Y1mC0Mkgy8","AkKTkFwEJz","ZUnqtVerEA","WreyPAIYUu","5Drn0L7cGc","B3qemfaHir","qQxHPC2Irc","JKWYRlCMxy","9iGoTEdBKc","mz8gxHzZT8",
-"taOXKMezSW","XflUqVjCZq","fcwDaBbwgA","dmoS7a00b5","faHir2Nslm","mX2GEW7cTs","NAFuwO3iyQ","hYBCKRzaZA","lsQGookgRi","ZhwG1GSQwj",
-"X6Pin24ARF","I7p2aPOUYS","RzaZAI7p2a","FVMxohE1Ql","Z4I1vYh1hF","iB08lkZANm","POUYS7hyVv","sqVrfcL0aE","HzZT80h1b1","jtn0XRBhp0",
-"yluBxVjCZq","wiHrZVIlwP","JKWYRY1mC0","No0QbJkzUn","fqypyU3yw5","v2eC38FmFH","zY1GYrz7Ut","okgRid85a9","DLhzMpmeCd","GWqqXoQ87r",
-"ThjNnyToGW","uvf7AxReec","Chuy3FVMxo","StlDJv8yFN","euZA5S77LH","gdQsSNxx9V","WreyPOUYuF","zbIYY2ZHdk","Ul4a1GWqqX","pmeCd48cHL",
-"VNCPdogLgc","aez9yEoToP","5iGN5Vprf2","5ZaEzuN6r3","aDGtSyvOMI","OHaBzUlU3M","FGzgpW3VFH","fcwDaiwzGk","i7WMQAOgEe","i7WMQGrDg7",
-"d7vjMRkQke","9rlg99iGoT","v8yFN4dEz6","Rxrsm9GXkX","uZPqg4W0Tl","CdyBVqQxHP","AkKTkfcJOy","1LB1LPYBf4","dQ586e6e4z","yToGWS77LH",
-"4dEz60Wr5y","pT8wu8U2nU","MojnPs7Mxk","9iGoT5IhmG","Twanopv0i7","IjTwPCqqaD","FjHXRpWiOs","9GXkXCK5W7","AOgEeuJScX","QssNCNo0Qb",
-"fcwDaCp3mZ","ydG8UyToGW","fcwDaCxVEf","VIlwPNo0Qb","SWfouTCgPp","RzaZAdmoS7","1LB1LjeskS","sx5GlBGaQY","zHF1q7Ow5C","yofH345cIH",
-"ogLgci7WMQ","ECMvU9eoRc","QWxoT2Nslm","AXpwELbRTH","AkKTklCMxy","WMiS3nlaBy","vOqCEpv0i7","8hJdtVerEA","lXFOBpFrrl","G1RhSlm0pD",
-"DQimpTwano","i3pyd8FmFH","IBe8kuupzk","mz8gxQnJ1S","hYBCKuTacx","vkCHHydG8U","8TxD72hEEU","s4786QssNC","Yf2Ecru4UG","AkKTkzmLYD",
-"SjskQCK5W7","DQimpzmLYD","Ul4a1tjQxs","RsQUqVBjhz","WaWsvMkgy8","0BmCylpF6W","atef27lUXZ","WMiS3FnPFB","GXdoHjeskS","WMiS3yToGW",
-"VjCZq0ao3l","4W0Tl5drc6","2TRI7M6qcG","hUTw7Waim6","RsQUqLewvM","YjB9tQssNC","JJs5m7fKYU","TCgPpMkgy8","X6Pin5Namm","XflUqru4UG",
-"zFgtBW3VFH","yluBxdpe1v","MezSWgIYvE","48cHLeuZA5","CK5W7uupzk","cQOnvs4786","Gv3FqHlUbF","tlILtIBe8k","QssNCHP433","dmoS7gIYvE",
-"MojnP9rlg9","HzZT8Mkgy8","Yf2EcwiHrZ","cQOnvCK5W7","tAOsrWreyP","In3NSqUJMd","ciuWzzFgtB","tlILtL7cGc","vOqCEfcwDa","In3NSJXljW",
-"LDk6f0Wr5y","mX2GEd7vjM","5IhmGAXpwE","5Mg9r8cVD3","m4bxUix74r","TwanoaFFss","FVMxos7Mxk","dpe1v0ao3l","MojnPgdQsS","jiVBPDz1R3",
-"NcICACK5W7","mX2GE07n1c","8RCUAdQ586","IRh48s4786","5drc6DG4sT","nnP8ozz4ZU","FGzgpWreyP","jeskSpmeCd","mX2GEX6Pin","bZLvSCK5W7",
-"xReecni2v1","s93MlPb1pa","29QAzOUYuF","MmsIonlaBy","Fhtgl5nmWv","lViBvU3yw5","KsjRKbZLvS","iqv4kxciqp","uupzkdQ586","SjskQpFrrl",
-"BCxeC07n1c","zqH0W8hJdt","LbRTH618Di","qaofNIRh48","s47864W0Tl","azIWpHP433","x3LDem4bxU","BGaQY16lHc","7hyVvFNYIM","uAWypUvlv4",
-"BCxeCt59lR","ciuWzyofH3","fLNg8soy9t","ReKEWaL6AJ","zqH0WQworu","uN6r3d85a9","lweGy9iGoT","xReecUlU3M","JXljWjfREu","zbIYYHfyNQ",
-"dhSuHkB5nP","QworuStlDJ","fcwDawDajX","b29RJoQ87r","kB5nPHlUbF","hSSvQcL0aE","Pb1pagf8rI","7fKYUlH1kt","n8pJ9P6bcg","SjskQaFFss",
-"MezSWFxX9q","wDajX8U2nU","QnJ1StjQxs","hUTw7iB08l","CqqaDM6qcG","XflUqbgJAz","zbIYYUl4a1","IKxdLrKDLJ","KsjRKYw2oU","HzZT8Uvlv4",
-"tl72WBCxeC","Fhtgl8U2nU","64s8NL7cGc","TwanouoStw","gdQsSokgRi","8FmFHZhwG1","8hJdt8TxD7","zQt6QxReec","FjHXRVBjhz","OUYuFyEfy9",
-"AIYUu7hyVv","KASQ8zFgtB","HfyNQb29RJ","ZhwG1yofH3","4W0Tl5Drn0","azIWps4786","FFDui6q6L9","MmsIo14FLR","hi5X7jS1aj","jS1aj8U2nU",
-"m4bxUprNT6","d85a9JXljW","Cfgr3wiHrZ","CIShGFnPFB","45cIHRmDcr","IRh486AFT0","zbIYYAXpwE","64s8NwDajX","ZuDtDuZPqg","i3pyd4dEz6",
-"6AFT0ZuDtD","s4786VBjhz","0BmCy0BmCy","uoStwiKqhr","AOgEeCdyBV","dmoS7zHF1q","t98iWpvgjS","aFFsstaOXK","EdBKcBGaQY","Q6Lix1v5hH",
-"5iGN5soy9t","LbRTHcmXIX","7lUXZ7lUXZ","uvf7AAIYUu","Dz1R3hYBCK","cL0aE6AFT0","ksJbyTCgPp","UmaEvxXTI4","AXpwEokgRi","dQ586DQimp",
-"RBhp0HP433","piJSkMGlTF","Uvlv4SWfou","MmKGJVBjhz","guMb824ARF","0KyfsxReec","KASQ8oVQp6","8hJdtfcwDa","euZA5FNYIM","JRJQBPOUYS",
-"29QAzZUnqt","lkMUAi7WMQ","JJs5mjfREu","tuDySG1RhS","gjUTuMaJQs","FwEJz9iGoT","1LB1LbZLvS","Dz1R3GSQwj","sx5GlStlDJ","W7cTsChuy3",
-"CqqaDjS1aj","OxWIHAOgEe","n8pJ9hi5X7","WreyPs7Mxk","blLA9JRJQB","l83UdVerEA","zHF1qVBjhz","Zv7z0vLsmS","XyPZNKASQ8","Cp3mZJkzUn",
-"jzUqRXyPZN","pAhR1jzUqR","uQIczzqH0W","Qworu64s8N","KZamHDQimp","ReKEWFNYIM","VerEAzqH0W","7Ow5CZ4I1v","FVMxoW3VFH","CNHmvDcpWB",
-"v1HlngdQsS","Ul4a1fLNg8","azIWpMkgy8","xXTI48xEKz","ZJTXHJKWYR","v1HlnLDk6f","U3yw5DLhzM","WmadAWPmlx","lViBvFFDui","fqypyDQimp",
-"OHaBzcQOnv","8xEKzMojnP","EoToPhSSvQ","07n1cRzaZA","iB08lyvOMI","FGzgpKZamH","45cIHwiHrZ","9iGoTZJTXH","3otm6QssNC","D6rBypiJSk",
-"TCgPp2TRI7","gdQsS64s8N","hSSvQSjskQ","d7vjMKr8ys","Ta8f6P6bcg","JkzUnaFFss","zHF1qCdyBV","gIYvEGv3Fq","piJSkL7cGc","ZuDtDlXFOB",
-"GrDg7zHF1q","3weIFWmadA","MmKGJqUJMd","CqqaD6q6L9","pWiOsgf8rI","SjskQb29RJ","Z4I1vL7cGc","64s8NRxrsm","AkKTkEOE1o","FcWrWNo0Qb",
-"LDk6f48cHL","okgRidmoS7","FxX9q2DREs","5Drn0OUYuF","a00b5FwEJz","S2DfupWiOs","In3NSY1mC0","M3zXLrz7Ut","pFrrlB3qem","NAFuw2DREs",
-"sx5Gl9y4lw","yToGW7ku1p","RACujHlUbF","QClRL9GXkX","QYxC0XflUq","vLsmSS77LH","S2Dfu1v5hH","brhlQnFqik","Dz1R33weIF","zmLYDtuDyS",
-"yvOMI5Namm","blLA9y94nw","AIYUuxReec","BFkb8AmdQd","9y4lwSbRYy","0PktIUvlv4","qUJMdd85a9","tl72W7lUXZ","0PktIOUYuF","45cIHhE1Ql",
-"fFDrJL7cGc","3weIFoQ87r","zY1GYtl72W","ThjNn45cIH","kZANm3weIF","3weIFwiHrZ","RACujRzaZA","WmadAYh1hF","MmKGJM3zXL","HzZT8RzaZA",
-"ZzJHW07n1c","n8pJ9yluBx","GWqqXPOUYS","mz8gxdjsrv","nlaBynlaBy","RpBQmbZLvS","Waim6MmKGJ","K20wKQ6Lix","2ZHdkJIqXi","8RCUAHP433",
-"HlUbFgf8rI","Ul4a1nnP8o","EOE1oPOUYS","gIYvEPYBf4","uJScXpWiOs","NhXdueuZA5","pFrrlHRxd8","nlaBy4dEz6","FnPFB2DREs","v8yFNix74r",
-"rz7UtMmKGJ","5iGN5RkQke","k85AeF6PT2","v8yFNd7vjM","wiHrZL7cGc","zbIYYiqv4k","zQt6QpFrrl","8RCUAprNT6","cmXIX6AFT0","pv0i7jSjS3",
-"AgJHQaDGtS","NAFuw0YAGH","zQt6Qsx5Gl","Yh1hFRsQUq","piJSk4QMc9","DLhzMzHF1q","atef2GSQwj","B3qemjzUqR","2DREsLDk6f","U3yw5lm0pD",
-"NcICAMkgy8","prNT6QnJ1S","OUqFMM6qcG","C2Ircgf8rI","OUqFMFNYIM","dhSuHWDVWJ","5drc6dQ586","nlaByaez9y","blLA9aFFss","QbxXc9iGoT",
-"y94nwNcICA","RpBQmJKWYR","CIShG07n1c","2TRI7s7Mxk","2TRI7EoToP","kZANmHzZT8","UmaEvWPmlx","vLsmSS2Dfu","W3VFHQworu","5Mg9ryEfy9",
-"9eoRczz4ZU","MK07YJXljW","5IhmGRpBQm","aFFssDLhzM","qaofNCxVEf","2ZHdkblLA9","7fsYMMkgy8","oGu6xIjTwP","blLA9HP433","MojnPa00b5",
-"pWiOsvkCHH","0KyfsFFDui","lViBvRkQke","618DifcwDa","xXTI4ciuWz","WDVWJSmGzv","VNCPdpiJSk","L7cGc9GXkX","Q6hMCHlUbF","0MR5XBGaQY",
-"ulk41dpe1v","HlUbFRzaZA","JkzUnlm0pD","tuDySLewvM","Pb1patlILt","hUTw7rhl0J","b29RJZJTXH","ECMvUCqqaD","lCMxyrhl0J","FnPFBhSSvQ",
-"JXljWtlILt","8TxD7MmKGJ","lXFOB5VZjS","RzaZAAkKTk","PYBf4J2mQi","9y4lwa00b5","mX2GEgIYvE","djsrvRxrsm","RmDcrEdBKc","Chuy3L7cGc",
-"6q6L9S77LH","SWfouK20wK","HlUbFtuDyS","CIShGuJScX","fqypysoy9t","dQ586SWfou","yluBxSbRYy","Q6Lixhi5X7","5NammFhtgl","uTacxWPmlx",
-"W3VFHIjTwP","UlU3MFNYIM","2hEEUkZANm","AOgEeyluBx","IKxdLuPX7G","t59lROz8yZ","JRJQBcQOnv","FVMxogf8rI","bgJAz5nmWv","zbIYYYjB9t",
-"GXdoH24ARF","7X3uyOxWIH","Q6hMCbZLvS","CK5W7s7Mxk","0YAGHFVMxo","KASQ8d7vjM","1LB1LuLtKs","MaJQs5nmWv","Z4I1v0BmCy","FGzgpdmoS7",
-"zbIYYm4bxU","HP4337hyVv","BCxeCWaWsv","EdBKcRBhp0","M3zXLrKDLJ","EdBKcd7vjM","M6qcGB3qem","Z4I1v55rfB","CxVEfDG4sT","suY4x1LB1L",
-"l83Ud48cHL","azIWpjSjS3","guMb8i3pyd","2hEEUCxVEf","dhSuHhe9IA","HlUbFO3iyQ","qQxHP8TxD7","lXFOBzFgtB","G1RhSFFDui","tAOsrh1zcH",
-"2hEEUs4786","WMiS3rhl0J","VLTy68TxD7","vOqCEVjCZq","GWqqXFGzgp","soy9tAXpwE","qaofNtl72W","lj07Qd85a9","x3LDes4786","ZUnqtNcICA",
-"0YAGHjiVBP","tuDySUl4a1","5Mg9rAIYUu","DQimp8xEKz","i3pydh1zcH","fFDrJAXpwE","h1zcHdjsrv","5Drn0uoStw","jtn0XZUnqt","iB08l0YAGH",
-"S2DfuPOUYS","tjQxsiwzGk","guMb8uQIcz","cmXIXazIWp","sqVrfi3pyd","NOHszx3LDe","hUTw7W3VFH","QClRLHP433","t98iWIn3NS","CNHmvJIqXi",
-"VLTy6uupzk","MojnPUl4a1","HzZT8fFDrJ","yluBxgdQsS","EdBKcuvf7A","QChxsyToGW","NOHsz0Wr5y","yluBxQYxC0","I7p2aZJTXH","0YAGHFnPFB",
-"zHF1qSs0Zu","pFrrl0ao3l","YjB9tCqqaD","D6rBye6e4z","CIShGpvgjS","cmXIXVBjhz","580YDrhl0J","d85a9FVMxo","ReKEWk85Ae","RxrsmfcwDa",
-"RmDcrWMiS3","cmXIX2Yz7E","fqypyuAWyp","MojnPfcJOy","FwEJzMGlTF","aez9yatef2","SjskQL7cGc","QYxC0bZLvS","taOXKazIWp","5Mg9rTa8f6",
-"e6e4zYOfrY","kZANmFGzgp","ydG8URsQUq","lH1ktiB08l","lCMxyuAWyp","soy9t3otm6","7Ow5CblLA9","soy9t2hEEU","1v5hHQChxs","gf8rIkZANm",
-"gf8rI7fsYM","F6PT2JIqXi","2Nslmhe9IA","ix74rKsjRK","jeskSk85Ae","Q6hMCtvdkD","FxX9qtjQxs","QChxsQssNC","TXQ0ZTwano","pv0i7NOHsz",
-"tvdkDZzJHW","azIWpxXTI4","CxVEfBCxeC","yEfy9RpBQm","b29RJjzUqR","brhlQpWiOs","pAhR15nmWv","8cVD3EOE1o","G1RhSWaWsv","uupzkMmKGJ",
-"VLTy6BbwgA","24ARFPOUYS","IKxdLtlILt","QWxoT7lUXZ","ix74rVBjhz","FFDuie6e4z","ReKEWD6rBy","2hEEUPb1pa","StlDJNAFuw","WMiS3zFgtB",
-"ru4UGmX2GE","CNHmvlpF6W","FwEJzuupzk","cmXIXNcICA","RxrsmFxX9q","WMiS3vkCHH","JIqXilkMUA","xXTI4okgRi","nFqikgIYvE","0Wr5yfFDrJ",
-"8xEKzChuy3","BbwgAsoy9t","s7MxkK20wK","9XyT9ZhwG1","AkKTkQWxoT","9GXkX5Namm","RACuj6q6L9","NAFuwMaJQs","ReKEWMmKGJ","2TRI7O3iyQ",
-"5iGN5RzaZA","No0QbdmoS7","BbwgA0h1b1","yofH3yEfy9","07n1czqH0W","64s8NRzaZA","iwzGkguMb8","IBe8kKZamH","gdQsSQnJ1S","3otm6ZhwG1",
-"7fKYUVerEA","QbxXcaFFss","QWxoTEoToP","d7vjMC2Irc","Yf2EcksJby","YOfrYJkzUn","uupzk0PktI","MojnPBGaQY","kB5nPUmaEv","1v5hHbgJAz",
-"5nmWvnlaBy","lweGy0Wr5y","ReKEWS2Dfu","zqH0WhE1Ql","5drc6MK07Y","ZJTXHn1pmO","v1Hlnuupzk","mz8gxQYxC0","AgJHQ9GXkX","fLNg8aez9y",
-"kB5nPqUJMd","dmoS7Fhtgl","vkCHHAIYUu","Waim6RkQke","2DREsM6qcG","G1RhSAgJHQ","dpe1vuTacx","FVMxosoy9t","ogLgc8cVD3","Twano2Nslm",
-"fmIK1I7p2a","5Mg9rkB5nP","In3NS7Ow5C","CdyBVyvOMI","soy9tHP433","U3yw5l83Ud","v8yFN64s8N","0Wr5yIjTwP","48cHLuPX7G","OHaBzZuDtD",
-"NOHszmz8gx","brhlQ8FmFH","W3VFHdpe1v","KsjRK4dEz6","yluBxyluBx","ZJTXHokgRi","DcpWB2DREs","mz8gxgf8rI","Yf2EcJkzUn","mX2GEt98iW",
-"b29RJJkzUn","t98iW0YAGH","2TRI7LewvM","8U2nUv8yFN","48cHLcShY2","JXljWLbRTH","d85a98cVD3","K4GS89GXkX","OxWIHgdQsS","dhSuHECMvU",
-"8U2nUMmsIo","cL0aEuupzk","Dz1R3vkCHH","7X3uyW7cTs","8FmFHXyPZN","jS1aji3pyd","64s8NCK5W7","9y4lwzqH0W","zmLYD7fsYM","AOgEeJkzUn",
-"iKqhrJKWYR","EoToPs7Mxk","QYxC0kZANm","JRJQBGSQwj","GSQwjkZANm","qUJMduvf7A","GrDg72Yz7E","yluBxblLA9","pFrrlUl4a1","FwEJzd85a9",
-"WMiS3kZANm","SbRYyJRJQB","taOXKqQxHP","7hyVv8cVD3","9iGoTwiHrZ","GXdoHlXFOB","jSjS3jfREu","piJSkyluBx","kZANmO3iyQ","GrDg7CK5W7",
-"cmXIXoGu6x","DLhzMHlUbF","CIShG48cHL","W3VFHy94nw","zmLYDaL6AJ","ZUnqtaDGtS","W3VFHQbxXc","YjB9tXyPZN","o8UydReKEW","gjUTuuoStw",
-"K20wK6AFT0","2ZHdkJKWYR","5nmWvfqypy","d7vjM5VZjS","Oz8yZpWiOs","fcJOymz8gx","aFFsspFrrl","MmKGJjfREu","lweGytvdkD","WaWsvdQ586",
-"AIYUu9XyT9","dQ586tl72W","qUJMdjSjS3","QYxC0fFDrJ","taOXKQssNC","dmoS7BpYhV","6AFT0v8yFN","oGu6xChuy3","YOfrYDQimp","ciuWzlXFOB",
-"BGaQYt98iW","uupzkStlDJ","IRh48y94nw","ulk41ksJby","B3qemSmGzv","07n1cru4UG","n8pJ9HfyNQ","J2mQi8RCUA","hYBCKWmadA","9rlg9dmoS7",
-"Yw2oUMmsIo","OUqFMzz4ZU","9GXkXbgJAz","atef2d7vjM","J2mQiD6rBy","uupzkBpYhV","suY4xlpF6W","ZuDtDUlU3M","uN6r3CxVEf","RBhp0kB5nP",
-"yEfy9HP433","rz7Utzz4ZU","VBjhzdmoS7","VNCPdCdyBV","aL6AJC2Irc","XyPZNs7Mxk","GSQwjFNYIM","VNCPdaDGtS","SjskQ7fsYM","MmsIomz8gx",
-"pvgjSv2eC3","2hEEUzbIYY","dpe1vbgJAz","uvf7Aaez9y","n1pmO9XyT9","AIYUu7Ow5C","t59lRFFDui","OHaBzgdQsS","fcwDapT8wu","FwEJztl72W",
-"s93MlAmdQd","a00b5VNCPd","7X3uyQworu","FjHXRlweGy","XyPZNOz8yZ","uJScXni2v1","4dEz6ThjNn","MmsIo0h1b1","t98iWnnP8o","d85a9Uvlv4",
-"Mm8siyluBx","6q6L9MK07Y","45cIH0PktI","ThjNn64s8N","v8yFN7ku1p","BpYhV9rlg9","qaofNm4bxU","ZzJHWGv3Fq","QYxC0B3qem","zqH0W7fKYU",
-"wiHrZzbIYY","ZUnqtK4GS8","Yh1hFt59lR","VNCPd16lHc","2TRI7jeskS","Nxx9V0YAGH","TwanoMojnP","ThjNnhUTw7","GWqqXC2Irc","uAWyp2Yz7E",
-"RzaZATa8f6","0PktIsoy9t","he9IAP6bcg","hUTw7JJs5m","AOgEeUvlv4","LDk6fiqv4k","zmLYDDQimp","fFDrJLbRTH","MGlTFThjNn","ZuDtDuupzk",
-"yofH36q6L9","jiVBPFcWrW","L7cGcuupzk","QWxoTs93Ml","pvgjSJKWYR","JRJQB8U2nU","hE1QlCxVEf","t98iWLDk6f","Dz1R35ZaEz","Cp3mZru4UG",
-"hUTw7lpF6W","uQIczPb1pa","pvgjSsx5Gl","e6e4zjtn0X","kB5nPYw2oU","X6Pin9XyT9","1j5L8Pb1pa","iwzGki3pyd","OUYuFjfREu","d85a9Yh1hF",
-"yEfy94W0Tl","faHirn8pJ9","9eoRcIBe8k","hYBCKFcWrW","ZUnqt9GXkX","tl72WoQ87r","8TxD7kB5nP","D6rByLDk6f","VjCZqMezSW","Uvlv4S77LH",
-"MaJQsQbxXc","MezSWlkMUA","JIqXiZ4I1v","lViBv0BmCy","8FmFH4QMc9","Ul4a1lViBv","KASQ88hJdt","X6Pin1v5hH","RzaZAQYxC0","qUJMdFGzgp",
-"2TRI7mX2GE","FNYIMzQt6Q","mX2GEG1RhS","wDajXCIShG","VIlwPogLgc","uTacx29QAz","0YAGHTXQ0Z","0KyfsHRxd8","VerEAEdBKc","ydG8UFGzgp",
-"BCxeCnlaBy","uN6r3hSSvQ","pvgjSdpe1v","TXQ0ZJXljW","L7cGcuJScX","pmeCd8hJdt","XyPZNqaofN","7Ow5Co8Uyd","1LB1LhE1Ql","cShY2ZuDtD",
-"fqypyUl4a1","aez9yPOUYS","prNT6zz4ZU","7hyVvPb1pa","X6PinkZANm","POUYSZv7z0","QssNCydG8U","ciuWzbgJAz","DLhzMpiJSk","gf8rIWaim6",
-"l83UdUlU3M","9GXkXYh1hF","LbRTHtlILt","QbxXcoQ87r","RkQke9GXkX","KsjRKMezSW","5IhmGTwano","zz4ZUqQxHP","blLA9vLsmS","0PktIWPmlx",
-"zmLYDnnP8o","RzaZAAIYUu","IKxdLdhSuH","QssNCAgJHQ","fqypyRsQUq","s7MxkAgJHQ","CK5W7yEfy9","MmKGJbgJAz","aFFssNo0Qb","zHF1qBbwgA",
-"aFFssYw2oU","Mm8si5IhmG","o8UydguMb8","hYBCKZ4I1v","zY1GY4W0Tl","dmoS7S2Dfu","PYBf42DREs","euZA5580YD","OxWIHGWqqX","ciuWzpmeCd",
-"aL6AJW3VFH","LbRTH6AFT0","8hJdth1zcH","dpe1vlm0pD","yofH3hSSvQ","xXTI4Cp3mZ","uLtKsPYBf4","zQt6QCIShG","tl72WuTacx","MaJQsprNT6",
-"5drc6In3NS","9y4lw5Drn0","3otm6MmKGJ","SjskQjeskS","oQ87rlkMUA","guMb8RBhp0","QClRLUmaEv","tl72WECMvU","hUTw7x3LDe","s4786iB08l",
-"SWfou9XyT9","wDajXKZamH","CqqaDUlU3M","pFrrl8xEKz","gtCA5Rxrsm","kZANmeuZA5","qUJMdBCxeC","ni2v1cShY2","prNT65nmWv","DQimp9iGoT",
-"UlU3MxXTI4","WaWsvNOHsz","UmaEv9y4lw","5nmWvbgJAz","QYxC07fKYU","5drc6ZhwG1","2Yz7EG1RhS","3otm6TXQ0Z","QChxscShY2","W7cTsd7vjM",
-"euZA5TCgPp","faHirNOHsz","SWfouqaofN","RzaZA6AFT0","lm0pD5VZjS","oGu6xHP433","cL0aEKr8ys","RACujni2v1","zQt6QP6bcg","ciuWzQbxXc",
-"CxVEfJJs5m","lViBvPb1pa","rhl0JWreyP","8FmFH6AFT0","QssNCi3pyd","RkQkebrhlQ","StlDJnnP8o","Oz8yZuN6r3","5nmWvYh1hF","s47864dEz6",
-"F6PT2Yw2oU","MGlTFfFDrJ","G1RhSkB5nP","AmdQduQIcz","dmoS7he9IA","uQIczbrhlQ","QClRLuPX7G","GXdoH6AFT0","VBjhzo8Uyd","JKWYRQClRL",
-"Mkgy8ciuWz","d7vjMazIWp","L7cGcQworu","ZhwG10YAGH","FcWrWJIqXi","TCgPpzz4ZU","9XyT9v2eC3","okgRi2Nslm","iqv4kSjskQ","Nxx9VHlUbF",
-"jfREuC2Irc","WmadAv8yFN","hi5X7FcWrW","aL6AJ5IhmG","fmIK1JKWYR","NOHszQworu","RACuj0ao3l","nlaByjiVBP","suY4xU3yw5","ksJbycQOnv",
-"cmXIXQYxC0","5iGN5OxWIH","WmadApWiOs","WaWsvThjNn","LbRTHaL6AJ","2hEEUhe9IA","3otm6yEfy9","5IhmGlsQGo","5NammOz8yZ","vkCHHaFFss",
-"ni2v1Q6hMC","CNHmvXflUq","Yh1hFfLNg8","Pb1paVjCZq","zHF1qTXQ0Z","X6PinQ6Lix","S2DfuaL6AJ","Kr8ysVIlwP","wDajX7X3uy","yvOMI9iGoT",
-"RkQkeJKWYR","xXTI4jtn0X","Yw2oUpT8wu","5nmWvl83Ud","HfyNQYf2Ec","FFDuijfREu","Y1mC0P6bcg","zqH0WQ6Lix","MmsIobZLvS","i3pyduvf7A",
-"zFgtBjS1aj","yvOMIvOqCE","0YAGHogLgc","OxWIH5Namm","t98iWo8Uyd","IBe8kCxVEf","ogLgcO3iyQ","ZhwG1jiVBP","ydG8Ub29RJ","b29RJzz4ZU",
-"MaJQsAOgEe","Rxrsmk85Ae","MmsIoYjB9t","9eoRcGv3Fq","RpBQmSjskQ","DG4sTb29RJ","BFkb8pFrrl","0MR5XDLhzM","O3iyQ0Kyfs","W3VFHReKEW",
-"gjUTuGv3Fq","BbwgAnFqik","Mm8siL7cGc","hSSvQMkgy8","7fKYUfcwDa","Q6LixMaJQs","ZzJHWcL0aE","SWfouuoStw","2hEEU2TRI7","9rlg9RzaZA",
-"dmoS7oGu6x","OxWIHgtCA5","lH1ktJRJQB","pAhR1ksJby","8U2nUMkgy8","ix74r07n1c","fqypyrhl0J","l83UdM6qcG","OUqFMXflUq","S2Dfu0PktI",
-"VjCZqJJs5m","Twano7ku1p","CIShGBGaQY","YjB9tSbRYy","VIlwPtAOsr","RsQUqtAOsr","FFDuiM3zXL","v8yFNSmGzv","3weIFVerEA","7fKYUBCxeC",
-"0MR5XO3iyQ","B3qemQChxs","Kr8ysYh1hF","dpe1vWaim6","sqVrfxciqp","ThjNnBGaQY","cShY2uQIcz","v2eC3uJScX","fcwDaFnPFB","AOgEex3LDe",
-"Waim61LB1L","y94nwRpBQm","y94nwAXpwE","WaWsvlsQGo","Gv3FqJkzUn","8U2nUlViBv","fFDrJWDVWJ","iKqhrRxrsm","hE1QlNhXdu","IKxdLiwzGk",
-"ZhwG1VLTy6","brhlQIBe8k","RzaZAThjNn","tjQxs5drc6","ni2v1ksJby","gtCA5MezSW","kB5nPBpYhV","yvOMIn8pJ9","8FmFHjeskS","7fKYUy94nw",
-"IBe8kuAWyp","yluBxiwzGk","taOXK14FLR","aFFssChuy3","5VZjSVjCZq","euZA5In3NS","QssNCKASQ8","6AFT0LewvM","jSjS3StlDJ","NhXduSbRYy",
-"lCMxy3otm6","cShY23otm6","ECMvUU3yw5","Ta8f6Z4I1v","9rlg9ksJby","16lHcru4UG","uoStwzmLYD","uTacx5drc6","nFqiko8Uyd","6AFT0nFqik",
-"LewvMTwano","guMb8oVQp6","CqqaD2hEEU","14FLRnnP8o","ZzJHWMGlTF","oQ87rMmsIo","gtCA5Yh1hF","FVMxoKr8ys","cQOnv5IhmG","xReecRpBQm",
-"jS1aj2hEEU","FwEJzogLgc","WaWsv5iGN5","FcWrW5VZjS","VBjhzt98iW","WreyPzz4ZU","S77LH7X3uy","mz8gxWaim6","Mkgy8yofH3","lH1ktzqH0W",
-"VNCPdaez9y","vLsmSMGlTF","14FLRzHF1q","SjskQ8hJdt","CdyBVfqypy","wiHrZgtCA5","xXTI4oGu6x","3weIFTCgPp","W7cTsoQ87r","jiVBPsuY4x",
-"AOgEeHlUbF","IBe8khi5X7","TXQ0ZzmLYD","7X3uyRpBQm","sqVrfiqv4k","zHF1qWreyP","kZANm0Wr5y","gf8rIwDajX","RmDcrK4GS8","gdQsSWmadA",
-"HzZT8zQt6Q","YjB9t8U2nU","OUqFMuJScX","X6Pin9GXkX","0Wr5yUlU3M","8hJdtSbRYy","QWxoTFVMxo","yluBx3otm6","tlILthE1Ql","RpBQm7fsYM",
-"VerEA0Kyfs","bgJAzAXpwE","jeskSVNCPd","wiHrZ7X3uy","In3NSQChxs","2DREsFcWrW","t59lRMezSW","VNCPdi3pyd","1v5hHQYxC0","yluBxRzaZA",
-"Yf2Ec0Kyfs","vkCHHNxx9V","yvOMI16lHc","Q6hMCFxX9q","bZLvSRmDcr","2DREs2TRI7","U3yw5he9IA","atef2lm0pD","MmKGJ0Wr5y","3weIFpv0i7",
-"CIShGQYxC0","s4786HzZT8","6AFT02TRI7","QnJ1SuPX7G","EdBKc5nmWv","pT8wublLA9","v2eC3BCxeC","OxWIHulk41","EdBKcAOgEe","gjUTulkMUA",
-"IRh48vkCHH","ZzJHWi7WMQ","B3qemRpBQm","7lUXZBpYhV","s7Mxk0h1b1","5VZjShi5X7","l83UdWaim6","v2eC3HRxd8","DcpWBgdQsS","Q6LixgIYvE",
-"7ku1psqVrf","6AFT0FFDui","jS1ajulk41","CdyBVpmeCd","uAWypo8Uyd","fLNg8zHF1q","4QMc9HRxd8","CK5W7VIlwP","7fsYMgIYvE","7hyVv0MR5X",
-"K20wKRACuj","fqypyNcICA","BCxeCFcWrW","KASQ8dpe1v","EdBKcx3LDe","618DicShY2","7lUXZQbxXc","yvOMIuoStw","2TRI7NhXdu","gIYvEQClRL",
-"618Di618Di","YOfrYDLhzM","5nmWvi3pyd","s93MlNhXdu","2DREsGXdoH","5VZjShSSvQ","5ZaEzkZANm","qQxHPogLgc","SWfouiqv4k","nFqik9iGoT",
-"QbxXcY1mC0","ni2v1Cp3mZ","BCxeC5Mg9r","MaJQsP6bcg","pT8wuL7cGc","4dEz6iqv4k","9eoRcuLtKs","RmDcrU3yw5","CqqaDiKqhr","aFFssFFDui",
-"pv0i7ECMvU","BCxeCRzaZA","DG4sTatef2","64s8N24ARF","FnPFBvkCHH","gdQsSlsQGo","DLhzMW7cTs","zFgtBnFqik","4W0TlFnPFB","OHaBz5IhmG",
-"tuDySh1zcH","VjCZq7fsYM","t98iWlsQGo","brhlQ14FLR","JJs5mFxX9q","FjHXRhSSvQ","pvgjSYw2oU","45cIH580YD","hi5X7dhSuH","1v5hHAgJHQ",
-"NcICAM3zXL","uPX7GQ6hMC","fcJOykZANm","6AFT0Fhtgl","ZJTXHDLhzM","8hJdtVprf2","W7cTsatef2","AOgEekZANm","jS1aj8TxD7","MezSWHzZT8",
-"G1RhS8cVD3","PYBf4tAOsr","suY4xUmaEv","kB5nPrKDLJ","CNHmvZzJHW","ru4UGaez9y","qQxHPsx5Gl","lXFOBGrDg7","soy9tzQt6Q","4W0Tltl72W",
-"FxX9qY1mC0","WaWsv3weIF","8RCUAzHF1q","BpYhVQbxXc","QWxoT7Ow5C","aFFssUvlv4","ciuWz8TxD7","CNHmvfqypy","pv0i75ZaEz","ECMvUlm0pD",
-"zHF1qCfgr3","64s8NOxWIH","Waim6C2Irc","piJSkdmoS7","AmdQdTCgPp","TwanoyvOMI","nlaByCqqaD","WDVWJC2Irc","2TRI7iB08l","FhtglpAhR1",
-"RBhp05Namm","ulk41IRh48","CdyBVDcpWB","uTacxoQ87r","Oz8yZrKDLJ","0MR5X8cVD3","0PktIM6qcG","l83UdQChxs","hE1Ql5VZjS","cmXIX6q6L9",
-"he9IAhSSvQ","ni2v1DG4sT","AgJHQQworu","1j5L8RBhp0","K4GS89y4lw","GWqqX2DREs","ni2v1SWfou","aDGtSZv7z0","3otm6oGu6x","uJScXSbRYy",
-"IjTwP0Wr5y","MmsIokZANm","Cfgr3aez9y","DcpWBtvdkD","bZLvSK20wK","brhlQFVMxo","HfyNQlCMxy","oVQp6jeskS","MaJQspiJSk","TCgPp0MR5X",
-"BbwgAVprf2","mX2GEWDVWJ","lXFOBWreyP","JXljWRsQUq","tvdkDwDajX","EdBKc9y4lw","i3pydYw2oU","v1Hln8RCUA","xReecjfREu","5ZaEzkB5nP",
-"Gv3FqlViBv","lsQGoQ6hMC","0PktIo8Uyd","XflUqJ2mQi","ulk41dQ586","XflUqgdQsS","o8UydaDGtS","L7cGcW7cTs","618DiF6PT2","faHir0Wr5y",
-"7fsYMrKDLJ","W3VFH5ZaEz","I7p2abgJAz","MojnPO3iyQ","3otm6ksJby","JIqXini2v1","45cIHAgJHQ","VNCPdn8pJ9","5drc6SjskQ","9eoRcqQxHP",
-"SjskQsoy9t","SmGzv9GXkX","pAhR1uupzk","TCgPpFwEJz","xXTI4ogLgc","soy9tlpF6W","HRxd8iwzGk","W3VFHjtn0X","Dz1R3FFDui","Ss0ZuVLTy6",
-"WPmlxvkCHH","okgRiZzJHW","BCxeCIRh48","jtn0XQYxC0","7lUXZlkMUA","580YDCfgr3","gjUTuzqH0W","JXljWx3LDe","8TxD7mz8gx","ZhwG10Wr5y",
-"fLNg8RmDcr","x3LDeYf2Ec","OxWIHRpBQm","ZzJHW9eoRc","ZJTXHYf2Ec","8U2nUjS1aj","FVMxoiKqhr","Z4I1vFNYIM","EOE1obgJAz","mz8gxVBjhz",
-"ZJTXHi3pyd","OUqFMi7WMQ","tAOsrIRh48","dpe1vFGzgp","64s8NQWxoT","VNCPd3weIF","zHF1qFwEJz","Dz1R3fFDrJ","euZA5MK07Y","rz7UtaFFss",
-"jtn0Xdpe1v","UlU3MMK07Y","3weIFTXQ0Z","JRJQB5ZaEz","OUqFMuLtKs","xXTI4FLsph","AmdQdOUYuF","bZLvSogLgc","yofH3JRJQB","ReKEWlXFOB",
-"AgJHQx3LDe","m4bxURpBQm","QWxoT618Di","QChxsyofH3","jeskSfaHir","uTacxRsQUq","n1pmOsuY4x","OHaBzuvf7A","SbRYyP6bcg","qaofNZJTXH",
-"Gv3FqJKWYR","7lUXZUlU3M","JkzUnWaim6","580YDOUYuF","ZUnqtDz1R3","v1HlnRpBQm","ReKEWIKxdL","S2DfuMezSW","UlU3MpvgjS","cQOnvdQ586",
-"14FLRNxx9V","SWfoufFDrJ","618Di0ao3l","RBhp0blLA9","oQ87rWaim6","wDajXBbwgA","uQIcztjQxs","OxWIHvkCHH","8RCUAuvf7A","FLsphXyPZN",
-"07n1cKr8ys","QWxoT64s8N","CxVEflweGy","djsrvlCMxy","0BmCy4W0Tl","7hyVvhE1Ql","yToGWru4UG","aL6AJ3otm6","NhXdu5nmWv","EdBKcmX2GE",
-"fcJOyuupzk","Q6hMCxciqp","oQ87rTwano","ThjNnv2eC3","UmaEvAIYUu","Pb1paIRh48","FFDuiTwano","W3VFH14FLR","JXljWn1pmO","xciqp2DREs",
-"fcwDa0PktI","v2eC3pvgjS","tuDySS2Dfu","LDk6f6AFT0","dQ586Fhtgl","sqVrfVprf2","aFFssP6bcg","JRJQB5drc6","DG4sTNo0Qb","rKDLJiKqhr",
-"Pb1paaFFss","Q6LixCqqaD","pvgjSVerEA","gIYvEWDVWJ","EOE1oCfgr3","WDVWJ8xEKz","Nxx9VMaJQs","Q6LixJKWYR","yofH3bgJAz","okgRiJ2mQi",
-"0MR5XcL0aE","y94nwcQOnv","uN6r3VjCZq","wDajXMK07Y","ReKEWo8Uyd","J2mQiiqv4k","sx5Gllj07Q","soy9tfmIK1","Oz8yZMGlTF","QWxoTKZamH",
-"QYxC0Ta8f6","sqVrfCIShG","POUYSt59lR","uQIczVBjhz","CqqaDNcICA","Waim6DQimp","ZhwG1soy9t","WDVWJt59lR","gIYvEdQ586","jzUqR9XyT9",
-"VLTy6blLA9","FVMxoyluBx","pv0i7Y1mC0","sx5GlCIShG","ru4UGk85Ae","BbwgAGv3Fq","aDGtSru4UG","wDajXNo0Qb","8cVD35Mg9r","24ARFnFqik",
-"he9IAs4786","lweGyWMiS3","wiHrZqQxHP","7ku1phe9IA","Z4I1vzmLYD","ThjNnlViBv","ix74rTwano","9GXkXIBe8k","OUYuF3weIF","KsjRKazIWp",
-"QYxC0uZPqg","EoToPDG4sT","GSQwjLbRTH","9y4lwOUYuF","5Mg9raDGtS","iKqhrTa8f6","guMb8S2Dfu","jzUqRI7p2a","Nxx9VY1mC0","KsjRKqQxHP",
-"9iGoTOUYuF","d85a9blLA9","mz8gxK4GS8","b29RJn8pJ9","FGzgpoGu6x","9iGoTuAWyp","uLtKsFFDui","iwzGk64s8N","UmaEvWMiS3","azIWpS77LH",
-"J2mQi5Mg9r","lm0pDYjB9t","TCgPp2hEEU","OHaBzkB5nP","lm0pDX6Pin","aL6AJguMb8","FPfSEJJs5m","2ZHdkpv0i7","EoToPFNYIM","uZPqgHP433",
-"FLsph8U2nU","mX2GEy94nw","piJSkcL0aE","C2IrcuJScX","1v5hHVprf2","J2mQit98iW","24ARFhE1Ql","WMiS3fLNg8","gf8rIpvgjS","tAOsr64s8N",
-"QChxswiHrZ","iB08lRzaZA","DcpWBpv0i7","W3VFHW7cTs","BGaQYNAFuw","9GXkXix74r","WDVWJhE1Ql","GXdoHHzZT8","64s8N1LB1L","i3pydQChxs",
-"ni2v1lm0pD","BFkb8AgJHQ","vOqCECNHmv","7Ow5CjiVBP","e6e4zMaJQs","7Ow5CFnPFB","gf8rIWreyP","uLtKsFNYIM","QbxXcCp3mZ","aFFssZuDtD",
-"lCMxyVerEA","7X3uyjeskS","0PktIksJby","euZA5pmeCd","VjCZqQssNC","tAOsrHzZT8","ZUnqtIKxdL","TXQ0Z64s8N","d85a9dQ586","DcpWBQssNC",
-"tlILt2hEEU","KsjRKjfREu","SbRYyStlDJ","zHF1qFxX9q","qUJMdXyPZN","pFrrliwzGk","o8Uyd55rfB","3weIF5VZjS","JXljW5nmWv","i7WMQQYxC0",
-"Waim6Z4I1v","RACujGXdoH","k85AezQt6Q","SjskQvOqCE","D6rByNAFuw","HlUbFt59lR","RACuj8cVD3","9iGoT0ao3l","x3LDepAhR1","pmeCd0Wr5y",
-"2hEEU7Ow5C","gtCA5MaJQs","5ZaEzgIYvE","AkKTknnP8o","CxVEfYOfrY","pvgjSqQxHP","v1HlnRxrsm","UlU3Miqv4k","5ZaEzuPX7G","iB08lFGzgp",
-"he9IAvkCHH","oQ87rs93Ml","lkMUAs93Ml","k85AeNo0Qb","Mkgy8he9IA","t98iWBbwgA","pmeCdAOgEe","ix74rI7p2a","Oz8yZpv0i7","iqv4kgdQsS",
-"0BmCy7fKYU","OUqFMTa8f6","RxrsmHfyNQ","LbRTH64s8N","JkzUnNxx9V","VBjhzfaHir","GrDg7KASQ8","pAhR1rKDLJ","QbxXcRsQUq","KsjRKO3iyQ",
-"HzZT8UlU3M","Y1mC0yluBx","Z4I1vDLhzM","JRJQB0MR5X","oGu6xRkQke","uLtKsl83Ud","fqypyPb1pa","WDVWJMK07Y","Ss0ZuRzaZA","5IhmGuoStw",
-"4W0TlpvgjS","lpF6WHzZT8","yofH3iwzGk","s7MxkSmGzv","zz4ZUVjCZq","EoToPwDajX","POUYStuDyS","5VZjSksJby","EoToP8cVD3","Gv3FqMaJQs",
-"RmDcrNo0Qb","aez9yh1zcH","azIWphe9IA","CqqaDFFDui","FNYIM9rlg9","yEfy9fLNg8","tjQxs7Ow5C","soy9tqQxHP","EdBKcbrhlQ","FNYIMOUYuF",
-"55rfBdpe1v","RpBQm0Wr5y","UlU3MFhtgl","FhtglDQimp","GrDg7RkQke","DQimp4QMc9","0MR5XmX2GE","C2Irc7ku1p","BFkb8ciuWz","D6rByi7WMQ",
-"UlU3MVLTy6","n1pmOgtCA5","atef2zFgtB","3weIFlsQGo","gdQsSpFrrl","WaWsvfqypy","MGlTFgIYvE","WPmlxwDajX","tvdkDcQOnv","8FmFHPYBf4",
-"HP433zHF1q","RmDcrQ6Lix","K4GS8EOE1o","QChxsb29RJ","TCgPpFjHXR","he9IABCxeC","zqH0Watef2","9y4lw0ao3l","S2DfuK20wK","MezSWAkKTk",
-"pv0i7AmdQd","UmaEvYh1hF","Y1mC0dmoS7","gdQsS1v5hH","qaofNpT8wu","CxVEfSs0Zu","EoToPJ2mQi","e6e4zIn3NS","uN6r3mX2GE","Nxx9Vgf8rI",
-"9iGoT5iGN5","4W0TlJKWYR","Ta8f6zqH0W","aDGtSXflUq","uQIczjiVBP","StlDJDcpWB","QChxsCqqaD","Cfgr37Ow5C","mz8gx8TxD7","5Mg9rNhXdu",
-"0PktI2Yz7E","euZA5cShY2","KASQ8oGu6x","AkKTkKASQ8","rz7UtvOqCE","QworuZv7z0","WaWsvQ6Lix","GWqqXCfgr3","07n1cFGzgp","n8pJ9fqypy",
-"tvdkDzz4ZU","e6e4zhe9IA","aDGtS07n1c","zFgtBh1zcH","yToGWW3VFH","C2Irca00b5","AOgEeJ2mQi","ZJTXHWPmlx","WMiS3fqypy","hSSvQwiHrZ",
-"AgJHQrhl0J","ECMvUW7cTs","l83UdtjQxs","D6rBygdQsS","cQOnvQworu","Zv7z0ni2v1","Gv3FqwDajX","ydG8U5ZaEz","618DiydG8U","MaJQszmLYD",
-"7X3uyAgJHQ","Z4I1vokgRi","KsjRKAIYUu","l83UdkB5nP","9eoRcReKEW","fcwDa7X3uy","EdBKcuAWyp","FwEJzCxVEf","dQ586n1pmO","GXdoHs7Mxk",
-"JKWYRZuDtD","aez9ybZLvS","BpYhVVIlwP","faHir1v5hH","rz7UtOUqFM","aez9yReKEW","0YAGHm4bxU","QWxoTrKDLJ","FGzgpVLTy6","MojnPfmIK1",
-"FGzgpAmdQd","lsQGoPOUYS","TCgPphYBCK","I7p2aRACuj","WreyPogLgc","s4786DG4sT","lj07QOxWIH","he9IATCgPp","lweGy8hJdt","Ul4a1zFgtB",
-"ZhwG1x3LDe","ni2v1yofH3","ZUnqtxReec","IRh48gjUTu","gtCA55drc6","aDGtSFwEJz","8U2nUFGzgp","fcJOyi7WMQ","LbRTHjfREu","W7cTsMmsIo",
-"ulk41P6bcg","QbxXc6q6L9","AmdQdSbRYy","uPX7Gt98iW","07n1cuTacx","TwanoJXljW","d7vjMWreyP","djsrvxciqp","M3zXLZhwG1","3weIFgjUTu",
-"8TxD7QClRL","WDVWJQssNC","CK5W79y4lw","2Yz7Ey94nw","Vprf2RBhp0","taOXKokgRi","mz8gxHfyNQ","IBe8koGu6x","14FLRv8yFN","7lUXZQYxC0",
-"zFgtBB3qem","QYxC01j5L8","5drc6PYBf4","JRJQB2TRI7","7fsYMWaim6","Mkgy8d85a9","618DiRACuj","8cVD3mz8gx","lCMxy48cHL","fcwDamz8gx",
-"VerEAcmXIX","d85a9zHF1q","rhl0JVIlwP","S77LH8xEKz","CNHmv5Drn0","9XyT9Zv7z0","JRJQBblLA9","Dz1R3JKWYR","9y4lwPYBf4","yvOMIAgJHQ",
-"5Mg9rogLgc","lCMxyWDVWJ","JIqXiECMvU","taOXKB3qem","xciqpzqH0W","FjHXRpv0i7","mX2GEY1mC0","9iGoTbZLvS","wDajXkZANm","RpBQm3weIF",
-"5ZaEzulk41","FcWrWfaHir","JRJQBQ6Lix","faHirtvdkD","M3zXLLDk6f","JkzUn24ARF","rz7Utrhl0J","ThjNncShY2","Ta8f6ulk41","cL0aEZhwG1",
-"X6Pin5Drn0","suY4xpFrrl","dhSuHl83Ud","yluBxt59lR","7lUXZCxVEf","RxrsmPb1pa","dQ5861v5hH","IBe8kVBjhz","16lHcRpBQm","l83UdJJs5m",
-"cQOnvZ4I1v","1j5L8yToGW","ZuDtDF6PT2","PYBf4RkQke","gjUTuZuDtD","P6bcgix74r","D6rBy5Drn0","ix74rYOfrY","NcICA8RCUA","atef2VLTy6",
-"BpYhVuoStw","dpe1vyvOMI","Waim6piJSk","FxX9qJkzUn","mz8gxZUnqt","LbRTHlsQGo","ZuDtDy94nw","xXTI47fsYM","5drc6Fhtgl","x3LDelXFOB",
-"cL0aEYjB9t","HzZT8AXpwE","MojnPqaofN","1j5L8yofH3","atef2pvgjS","OHaBzjS1aj","BpYhVcQOnv","ZuDtDrz7Ut","LewvMJkzUn","uN6r3iwzGk",
-"YjB9tY1mC0","IjTwP8TxD7","FPfSEM3zXL","L7cGcAmdQd","soy9t8xEKz","ZuDtDMK07Y","UlU3McmXIX","S77LHuvf7A","piJSkoVQp6","IjTwPfFDrJ",
-"lH1ktFVMxo","ZhwG1a00b5","WMiS3D6rBy","24ARF14FLR","uupzkv1Hln","iqv4kD6rBy","L7cGc8cVD3","dmoS7piJSk","i3pydYjB9t","AgJHQ9rlg9",
-"ZhwG1lpF6W","Nxx9VKZamH","prNT6oVQp6","HzZT8AOgEe","9y4lwRpBQm","atef22hEEU","580YDRzaZA","VLTy6lCMxy","Ta8f61LB1L","9XyT9aDGtS",
-"Mkgy8nlaBy","AXpwEtAOsr","pT8wuZuDtD","cL0aE0YAGH","zmLYDFxX9q","ReKEWtjQxs","aDGtSuAWyp","TXQ0Z7fsYM","CxVEfv2eC3","24ARFaL6AJ",
-"d7vjMY1mC0","uZPqgs7Mxk","5Drn045cIH","a00b5iKqhr","uvf7At59lR","FwEJzni2v1","0MR5X9y4lw","FPfSEpvgjS","WaWsvOz8yZ","uZPqgmX2GE",
-"zFgtBCfgr3","pmeCdsqVrf","aez9yQChxs","atef2dpe1v","aL6AJ7hyVv","aDGtSUmaEv","CdyBVuN6r3","WMiS3e6e4z","2ZHdkv2eC3","O3iyQfqypy",
-"aDGtSHzZT8","rKDLJdpe1v","qaofNkB5nP","NhXduJkzUn","uQIczRzaZA","HP433jtn0X","Yh1hFtAOsr","Zv7z0Nxx9V","JKWYR618Di","NhXduRzaZA",
-"NcICA64s8N","MojnPIRh48","CxVEfDz1R3","HP433StlDJ","WaWsvuAWyp","8FmFHMmKGJ","EOE1oU3yw5","NAFuwHzZT8","AmdQdChuy3","7lUXZO3iyQ",
-"2NslmDcpWB","y94nwVLTy6","cL0aECqqaD","fqypyZv7z0","fcJOyMojnP","nFqikqUJMd","tvdkDtaOXK","lj07Q618Di","X6Piny94nw","s4786JRJQB",
-"3otm6QnJ1S","fmIK1HfyNQ","hSSvQtAOsr","0h1b1FwEJz","v1HlnNOHsz","SjskQFGzgp","RkQke5Namm","F6PT2suY4x","gdQsSfLNg8","WMiS3bZLvS",
-"AXpwEEOE1o","5Drn0gf8rI","ZzJHWLDk6f","0MR5XCK5W7","WaWsvciuWz","faHirSjskQ","CIShG5VZjS","fqypy5Namm","yvOMIYjB9t","fqypytjQxs",
-"0YAGHJXljW","zbIYY9rlg9","pWiOsYh1hF","ydG8Us93Ml","2DREsnFqik","AgJHQjfREu","Oz8yZ0h1b1","64s8NIRh48","hE1QlBGaQY","Waim6FPfSE",
-"Mm8siU3yw5","gIYvEjfREu","nnP8ouTacx","FLsphQYxC0","hSSvQRzaZA","t59lRWaWsv","ciuWzFhtgl","Nxx9VoGu6x","fFDrJVjCZq","F6PT2v1Hln",
-"jfREutuDyS","5Drn0QYxC0","n1pmOFLsph","8U2nUi3pyd","0PktIP6bcg","CK5W75VZjS","i7WMQokgRi","tl72WjfREu","8U2nUZuDtD","uLtKsQChxs",
-"29QAzt98iW","mX2GE0Kyfs","nnP8olj07Q","zHF1qyvOMI","dhSuHyluBx","G1RhSLewvM","uPX7GksJby","QYxC0yEfy9","n8pJ9EOE1o","tl72WpWiOs",
-"In3NSyvOMI","No0QbrKDLJ","2Yz7EhYBCK","EdBKc618Di","MaJQsjiVBP","VLTy65IhmG","cmXIXYOfrY","0YAGHOUqFM","ix74rv8yFN","d7vjMAkKTk",
-"ZhwG116lHc","ru4UGa00b5","tjQxsaL6AJ","zmLYD7fKYU","lkMUA6q6L9","5VZjSazIWp","M3zXLCfgr3","pmeCdaDGtS","5iGN5MGlTF","Cp3mZaFFss",
-"HRxd85iGN5","M6qcGiwzGk","uN6r3euZA5","AgJHQDLhzM","Dz1R3Mm8si","h1zcHSbRYy","uTacxpvgjS","soy9tM6qcG","618Di7X3uy","WreyPEOE1o",
-"FLsph48cHL","uoStwB3qem","QworuCdyBV","ni2v1FVMxo","OUqFM7fKYU","GWqqXChuy3","tlILte6e4z","Ta8f6FPfSE","mz8gx5Mg9r","EOE1o0Wr5y",
-"Cp3mZ0h1b1","JKWYRKASQ8","7fsYMUl4a1","JIqXi5Namm","fcJOypiJSk","l83UdfLNg8","9GXkXWaWsv","7fKYUkB5nP","No0QbMK07Y","24ARFhe9IA",
-"y94nwpv0i7","EOE1o0PktI","hUTw78U2nU","EoToPRzaZA","KsjRKOxWIH","No0Qbt59lR","v8yFNS77LH","hE1QlguMb8","tuDySv8yFN","PYBf4QClRL",
-"RpBQmOUqFM","aL6AJIjTwP","hE1QltlILt","48cHLmz8gx","7hyVvTXQ0Z","zbIYYRxrsm","xciqpVNCPd","jtn0X64s8N","MaJQscShY2","FFDuilpF6W",
-"KsjRKUvlv4","48cHLaez9y","y94nwWreyP","4QMc9ReKEW","CIShGPOUYS","C2IrcJ2mQi","zHF1qtuDyS","Zv7z0vOqCE","s7MxkAIYUu","lXFOBDLhzM",
-"iKqhrFcWrW","Oz8yZL7cGc","RsQUqThjNn","Z4I1vPb1pa","RpBQmEOE1o","3weIF7fKYU","n8pJ9WreyP","BpYhV5Mg9r","rz7UtHRxd8","W3VFHZ4I1v",
-"tlILtxReec","2NslmNxx9V","zHF1qStlDJ","ZUnqtt98iW","lpF6WW3VFH","29QAzW3VFH","brhlQLbRTH","lweGyyluBx","5Drn02Nslm","pFrrlsqVrf",
-"yEfy9n8pJ9","jS1ajdhSuH","IRh48i3pyd","M3zXLuoStw","Cfgr3AgJHQ","29QAzMaJQs","DG4sTEOE1o","lweGy3otm6","8U2nUCqqaD","jSjS3ogLgc",
-"Dz1R3ulk41","pmeCdyEfy9","VjCZquvf7A","rhl0J3otm6","gtCA5jiVBP","MezSWYw2oU","W7cTsdpe1v","qUJMdfLNg8","9rlg9nnP8o","FxX9quJScX",
-"DG4sTFGzgp","zqH0Wulk41","K4GS8WMiS3","RkQkeydG8U","LewvMdmoS7","PYBf4tlILt","GrDg7VjCZq","WPmlxZhwG1","Vprf2uPX7G","ix74r9GXkX",
-"MaJQsKZamH","JkzUnuZPqg","W3VFHkB5nP","6AFT0RmDcr","Q6Lix5VZjS","Yh1hFWreyP","7ku1pQClRL","vOqCE6q6L9","8RCUA5IhmG","tAOsrD6rBy",
-"zz4ZU1LB1L","WDVWJ3otm6","ksJbyGrDg7","2ZHdkru4UG","WaWsvfmIK1","FxX9qQ6hMC","7X3uyDG4sT","ZJTXHtvdkD","gf8rIZzJHW","yluBxK4GS8",
-"ulk41tvdkD","QworuC2Irc","QWxoTyofH3","fqypyRpBQm","WPmlxBpYhV","zY1GYguMb8","7lUXZ9rlg9","euZA5pFrrl","gf8rIOUYuF","2Yz7EtvdkD",
-"45cIH0ao3l","EdBKcWDVWJ","0KyfsOxWIH","F6PT2iB08l","FGzgpY1mC0","2hEEUKZamH","FFDuin8pJ9","Rxrsm5ZaEz","soy9t8RCUA","gtCA58U2nU",
-"pWiOsZv7z0","YOfrYIjTwP","mz8gxdmoS7","BGaQYsoy9t","tAOsrEdBKc","gdQsSlXFOB","he9IAqaofN","3otm6kZANm","Oz8yZDLhzM","FcWrWoQ87r",
-"pmeCdM6qcG","J2mQiQworu","CqqaDn8pJ9","lpF6WKr8ys","EdBKcZ4I1v","ogLgcnnP8o","FjHXRpFrrl","0ao3lNAFuw","uQIczO3iyQ","0Wr5yC2Irc",
-"dmoS7bZLvS","W3VFHtlILt","e6e4zydG8U","QnJ1SEdBKc","wiHrZvOqCE","7hyVv5nmWv","okgRioQ87r","Nxx9VYw2oU","AIYUuPb1pa","QWxoT0ao3l",
-"pvgjSFcWrW","HlUbFGWqqX","hi5X7h1zcH","ZhwG1cmXIX","WDVWJ5Namm","MK07Yd7vjM","aDGtS8FmFH","9eoRc7ku1p","hi5X79GXkX","n8pJ9J2mQi",
-"ix74rkZANm","RzaZAMmKGJ","5iGN5FLsph","Z4I1vx3LDe","fLNg87fKYU","1j5L85nmWv","RBhp0djsrv","HlUbFQ6Lix","2NslmK20wK","FwEJzqaofN",
-"0h1b1zqH0W","DG4sTyEfy9","ZhwG1prNT6","FcWrWNhXdu","GXdoHfFDrJ","ksJbyQYxC0","zHF1qYw2oU","5iGN5e6e4z","brhlQRzaZA","FcWrWqaofN",
-"5Namm24ARF","oGu6xi3pyd","5Mg9rjfREu","djsrvVNCPd","fmIK1GrDg7","SjskQfcwDa","BGaQY55rfB","y94nwwiHrZ","0h1b1tlILt","tjQxsCxVEf",
-"RsQUqWaWsv","azIWptvdkD","h1zcHkZANm","4W0TlAXpwE","FcWrWyToGW","uPX7GKZamH","xXTI4l83Ud","JJs5mokgRi","BCxeCFjHXR","d85a9VerEA",
-"gtCA5Ss0Zu","LDk6fh1zcH","wiHrZFcWrW","QWxoTSmGzv","azIWpJkzUn","W3VFH7ku1p","FFDuigdQsS","lViBvjiVBP","NAFuwOz8yZ","lj07QDLhzM",
-"cL0aErhl0J","zqH0WfaHir","LbRTHLewvM","jzUqRn1pmO","KZamHyEfy9","hSSvQQ6Lix","CdyBVZuDtD","ZhwG1zz4ZU","lkMUA4W0Tl","SWfoutaOXK",
-"1v5hHaL6AJ","AgJHQYw2oU","okgRiOUqFM","SjskQWMiS3","Cp3mZQbxXc","9rlg9uAWyp","LbRTHFcWrW","hE1QlJ2mQi","5VZjSVBjhz","l83Udx3LDe",
-"AIYUuzQt6Q","Z4I1vVBjhz","POUYSzmLYD","JRJQBs93Ml","JRJQBEOE1o","W7cTsEOE1o","SmGzv5drc6","VNCPdU3yw5","hi5X7G1RhS","SWfouWaim6",
-"W7cTs5VZjS","MojnPJkzUn","gdQsSt59lR","gdQsSJIqXi","euZA5Q6Lix","xReecSWfou","m4bxURmDcr","MojnPazIWp","nnP8ouPX7G","HP433OUqFM",
-"Q6hMCciuWz","7fsYMl83Ud","FxX9qlj07Q","guMb8FGzgp","tlILt0MR5X","lj07QFVMxo","9eoRco8Uyd","qQxHP1j5L8","ZhwG1uoStw","tAOsrcmXIX",
-"VerEAChuy3","wiHrZoGu6x","2hEEUlCMxy","D6rByaDGtS","suY4xVjCZq","fLNg8uoStw","KZamHB3qem","4W0TlS77LH","M3zXLzFgtB","qUJMdrhl0J",
-"oGu6xgf8rI","1v5hHL7cGc","8FmFHEOE1o","GrDg7Q6Lix","mX2GEMmsIo","9iGoT3weIF","mz8gxnlaBy","ECMvUuAWyp","FNYIM8RCUA","rz7UtJIqXi",
-"2ZHdkEOE1o","FwEJz6AFT0","BGaQY9rlg9","uTacxjiVBP","Chuy3O3iyQ","LbRTHFGzgp","pAhR1FLsph","9y4lwhe9IA","5Drn0CIShG","ZzJHWoQ87r",
-"ZzJHWjtn0X","ni2v1vLsmS","0MR5X48cHL","4W0Tlatef2","lCMxyJJs5m","Yw2oUBGaQY","lj07QECMvU","zmLYDAXpwE","5Mg9r1v5hH","v8yFNjfREu",
-"bgJAzOz8yZ","5nmWvn8pJ9","5NammjSjS3","L7cGcnFqik","zHF1qaez9y","0h1b1JKWYR","1LB1LK20wK","wDajXHlUbF","CdyBVKr8ys","FxX9qMezSW",
-"nnP8oY1mC0","ZzJHWAgJHQ","ogLgcy94nw","TXQ0ZVprf2","jeskSzHF1q","5drc6IRh48","gdQsSpvgjS","uupzkaL6AJ","5IhmG9y4lw","0YAGH5Mg9r",
-"K20wKiqv4k","3weIFQnJ1S","WaWsviB08l","SjskQiB08l","0BmCyprNT6","1LB1LNhXdu","S2DfubZLvS","jSjS3pv0i7","hi5X7jzUqR","2Yz7Es93Ml",
-"SbRYyjzUqR","QChxsazIWp","MK07YOHaBz","RkQkev8yFN","7hyVvd7vjM","WaWsvVNCPd","6AFT0guMb8","y94nwnFqik","rKDLJY1mC0","M3zXLNxx9V",
-"OHaBz7hyVv","Uvlv455rfB","7fKYUKZamH","jS1ajJXljW","MezSW45cIH","3weIF3weIF","RzaZAfLNg8","tvdkDtlILt","618Di5iGN5","S77LHhe9IA",
-"S2DfuIKxdL","djsrvvkCHH","WmadAogLgc","zqH0Wpv0i7","B3qemW7cTs","Zv7z0Yw2oU","3otm6pAhR1","hE1QlMmKGJ","hYBCKksJby","5NammpAhR1",
-"QChxsaDGtS","4QMc9CqqaD","BCxeCZv7z0","LewvM2ZHdk","atef2pv0i7","zFgtBfFDrJ","l83UdDLhzM","FcWrWxReec","UlU3M2DREs","9y4lwRxrsm",
-"ni2v1B3qem","hUTw7euZA5","ix74rb29RJ","gIYvE24ARF","FwEJzjSjS3","gjUTui3pyd","2DREsbZLvS","3weIFCNHmv","QworuVprf2","CdyBVCqqaD",
-"t98iW5drc6","rz7UtC2Irc","Oz8yZlpF6W","Qworu2ZHdk","24ARFSbRYy","xciqp9rlg9","0BmCySjskQ","dpe1v5IhmG","v1HlnvkCHH","lm0pDe6e4z",
-"TXQ0ZcL0aE","UlU3MDG4sT","RBhp0l83Ud","m4bxUvkCHH","StlDJTwano","TCgPpaDGtS","pT8wuyofH3","JRJQBStlDJ","v2eC3IRh48","2Yz7Edpe1v",
-"In3NSoVQp6","UmaEv8cVD3","aDGtSLbRTH","DQimpHzZT8","MaJQsQnJ1S","QbxXcazIWp","FxX9qOxWIH","iqv4ktaOXK","LDk6fuAWyp","lCMxyx3LDe",
-"9GXkXEoToP","fcwDafcwDa","WDVWJa00b5","zz4ZU29QAz","bgJAz5Drn0","VBjhzBCxeC","5iGN5K20wK","lm0pDDG4sT","F6PT22hEEU","i3pydJIqXi",
-"GXdoHRsQUq","Fhtgl0h1b1","jSjS3yvOMI","hUTw7QClRL","gtCA5IBe8k","4W0TlXyPZN","tAOsrblLA9","3weIFXflUq","v8yFNRpBQm","zz4ZUWMiS3",
-"2hEEUVLTy6","azIWpMm8si","jSjS3cQOnv","ru4UGaDGtS","BFkb8YjB9t","FnPFB55rfB","O3iyQKZamH","8hJdtYw2oU","lj07QqaofN","Gv3FqCIShG",
-"n8pJ9MmKGJ","2DREslkMUA","lsQGoogLgc","8U2nU2DREs","zFgtB0Kyfs","iwzGkzbIYY","uN6r35drc6","ciuWz7Ow5C","pvgjS2Nslm","aez9yOUYuF",
-"Dz1R3vLsmS","FFDuiqQxHP","GWqqXGXdoH","qUJMdtAOsr","atef2uN6r3","t59lREOE1o","piJSkQWxoT","5NammQChxs","8xEKz1LB1L","QClRLM6qcG",
-"Q6LixJIqXi","ksJby2ZHdk","JRJQBqUJMd","UlU3MnlaBy","DLhzMGWqqX","qUJMd0YAGH","LbRTHMmsIo","5IhmG24ARF","zHF1qU3yw5","QbxXcMm8si",
-"m4bxU7hyVv","Q6Lix16lHc","7X3uy5Mg9r","CqqaDFPfSE","aFFssSmGzv","ru4UGJ2mQi","HfyNQhi5X7","JXljWRACuj","2DREsCxVEf","WDVWJatef2",
-"LewvMjSjS3","aL6AJXyPZN","9GXkX0Kyfs","M6qcG48cHL","qaofNyEfy9","DG4sTlj07Q","tlILtatef2","vLsmSlsQGo","SjskQSbRYy","PYBf4BpYhV",
-"FPfSEhE1Ql","9iGoTgjUTu","ogLgcD6rBy","1LB1LLDk6f","0h1b1Vprf2","jzUqRJIqXi","7X3uys93Ml","FLsphFNYIM","IjTwPDLhzM","U3yw5Nxx9V",
-"DcpWB580YD","PYBf4uPX7G","wiHrZ5drc6","lH1ktuAWyp","hE1Ql7fKYU","mX2GEzmLYD","StlDJ8TxD7","gjUTu29QAz","uoStwC2Irc","AIYUu6q6L9",
-"VerEAblLA9","dQ586i3pyd","xciqp14FLR","In3NSpv0i7","uZPqgqaofN","WPmlxZuDtD","QClRL48cHL","W7cTspiJSk","9XyT9QClRL","yToGWwDajX",
-"MmKGJgf8rI","pFrrlVjCZq","4QMc9gf8rI","lH1ktHlUbF","lweGyG1RhS","d7vjMBGaQY","nFqikaez9y","Cp3mZVjCZq","aDGtSDz1R3","YOfrYfaHir",
-"JJs5mdmoS7","v8yFNMmKGJ","DG4sT5VZjS","FVMxolXFOB","t59lRHfyNQ","DQimpRxrsm","GrDg7Gv3Fq","yvOMIs4786","v2eC3MGlTF","zmLYDaez9y",
-"ThjNn7X3uy","2hEEUd7vjM","VLTy616lHc","MojnPyEfy9","IjTwPo8Uyd","Qworugf8rI","GXdoHZuDtD","5VZjSd7vjM","rz7Utlm0pD","CqqaDFhtgl",
-"8hJdt7hyVv","VBjhz9eoRc","okgRimz8gx","Nxx9VM6qcG","QClRLd85a9","pmeCd5IhmG","lsQGo0Wr5y","YjB9t5ZaEz","FNYIMFcWrW","FjHXROz8yZ",
-"zQt6QLDk6f","o8UydHRxd8","TXQ0Z5Mg9r","GWqqXQClRL","ReKEW4QMc9","WreyPfcwDa","VerEAHRxd8","rz7Ut8cVD3","5drc6RsQUq","vOqCEMm8si",
-"5drc6h1zcH","VLTy6IKxdL","ReKEWGSQwj","cL0aESbRYy","dhSuHYjB9t","rz7UtcmXIX","I7p2aAmdQd","GWqqXlCMxy","L7cGcgf8rI","AXpwEhUTw7",
-"IRh48KZamH","pAhR15IhmG","XyPZNhSSvQ","atef2tAOsr","pWiOsVBjhz","wDajXix74r","S77LH16lHc","FnPFBM6qcG","2TRI7oQ87r","aL6AJcQOnv",
-"VerEA5VZjS","8hJdt5ZaEz","e6e4zzqH0W","Q6hMCGrDg7","uN6r3aL6AJ","t98iWjiVBP","tuDySQWxoT","jzUqRyvOMI","NAFuwfLNg8","fqypyaDGtS",
-"SbRYyoQ87r","jtn0X7ku1p","a00b5NAFuw","6q6L9QWxoT","9rlg955rfB","JRJQBMmKGJ","3weIFlXFOB","Ss0ZuNxx9V","FcWrWoVQp6","gdQsSnlaBy",
-"he9IAbgJAz","piJSko8Uyd","lpF6WOxWIH","fcwDayvOMI","0BmCyTCgPp","Yh1hFAkKTk","m4bxULewvM","SjskQe6e4z","Cfgr3qaofN","MaJQsFxX9q",
-"Kr8yshi5X7","dhSuHKr8ys","nnP8oMK07Y","d85a9azIWp","x3LDeWreyP","CK5W7LbRTH","Y1mC0zqH0W","MGlTFlsQGo","5nmWv29QAz","gIYvEFGzgp",
-"ciuWzuJScX","rKDLJNxx9V","dhSuH9GXkX","KASQ8pmeCd","L7cGcWMiS3","QbxXczHF1q","5Drn0DLhzM","1v5hHJXljW","cL0aErz7Ut","BCxeCAgJHQ",
-"7fsYMUvlv4","RmDcr2DREs","atef2HP433","7X3uySmGzv","0Kyfss4786","iwzGkiqv4k","WDVWJnFqik","ulk41uAWyp","k85AeogLgc","ksJbyDLhzM",
-"brhlQi3pyd","M6qcGQ6hMC","8TxD7ogLgc","fcwDaCNHmv","PYBf4D6rBy","TCgPpQssNC","MojnPFhtgl","he9IAIRh48","oGu6x9iGoT","bZLvSPOUYS",
-"4W0TlUl4a1","pT8wu9y4lw","TCgPphi5X7","atef2oGu6x","6q6L929QAz","9y4lwqaofN","Zv7z0iKqhr","yEfy99XyT9","Cp3mZyToGW","2TRI7uZPqg",
-"fFDrJVIlwP","pAhR1nnP8o","e6e4zwiHrZ","EdBKcFxX9q","rz7UtlCMxy","rhl0J7ku1p","FLsph5ZaEz","t59lR8U2nU","9rlg9QYxC0","lpF6WjiVBP",
-"WreyP9y4lw","okgRifLNg8","OUYuFAmdQd","DQimppv0i7","hSSvQ7ku1p","ulk41v2eC3","0h1b1No0Qb","618DiaL6AJ","FcWrWHRxd8","pFrrlPOUYS",
-"brhlQNcICA","1j5L8QssNC","VIlwPfmIK1","16lHcD6rBy","atef25ZaEz","FPfSEKZamH","BCxeC5VZjS","pT8wua00b5","fFDrJM3zXL","3otm6FGzgp",
-"RmDcr07n1c","lj07QFxX9q","DcpWBtuDyS","uupzk9XyT9","tlILtlCMxy","W7cTsTa8f6","WreyPStlDJ","s93MlzqH0W","hSSvQRsQUq","RkQkemz8gx",
-"1v5hHjtn0X","lj07QUlU3M","zQt6Q4dEz6","ThjNn9GXkX","9GXkXFFDui","cShY2Z4I1v","iwzGkRkQke","gdQsScmXIX","TCgPpa00b5","IBe8k16lHc",
-"YOfrYHlUbF","Nxx9VWPmlx","ZzJHWa00b5","HP4338FmFH","x3LDeDQimp","i7WMQtlILt","Q6hMCNAFuw","UmaEvLewvM","AXpwEZv7z0","TXQ0ZCfgr3",
-"dmoS7yluBx","n1pmOuPX7G","xciqpn1pmO","uvf7AjfREu","i3pydHlUbF","sqVrflXFOB","Uvlv40PktI","AIYUuCNHmv","zHF1qbrhlQ","NhXduFhtgl",
-"MK07YCK5W7","GrDg7Uvlv4","dpe1vvLsmS","k85AebZLvS","2TRI7qQxHP","FLsphVjCZq","bgJAzfmIK1","HfyNQlXFOB","8FmFHDLhzM","8hJdtru4UG",
-"ksJbyJkzUn","QWxoTYOfrY","POUYS1j5L8","G1RhSiwzGk","0Wr5yQworu","fmIK1yvOMI","WreyPIn3NS","o8UydQ6Lix","0ao3lMkgy8","nFqikmz8gx",
-"XflUquPX7G","BGaQYdhSuH","EOE1oC2Irc","n1pmOVjCZq","EOE1oi3pyd","2TRI77Ow5C","uN6r3v1Hln","OHaBzWMiS3","MmsIoPOUYS","Cp3mZfqypy",
-"Dz1R3Z4I1v","tjQxsksJby","5IhmGlj07Q","n8pJ97hyVv","s93MlCqqaD","MmsIonFqik","KZamHCxVEf","hE1QlyluBx","K4GS8ZhwG1","Uvlv4RpBQm",
-"gf8rI4QMc9","ogLgcFPfSE","kB5nPYh1hF","FnPFBK20wK","C2IrcWPmlx","M3zXLdmoS7","5ZaEziqv4k","jfREuAIYUu","lCMxy0Kyfs","1v5hHS2Dfu",
-"BFkb8xReec","ZzJHWSWfou","48cHL24ARF","J2mQiY1mC0","OHaBzfcJOy","mz8gxs7Mxk","iqv4kWPmlx","i3pyddhSuH","ix74rCIShG","jeskSuAWyp",
-"CdyBV2Yz7E","v8yFN4W0Tl","GXdoHprNT6","Pb1pafcwDa","e6e4zuAWyp","0MR5Xuupzk","b29RJiwzGk","24ARFBpYhV","ZUnqtgdQsS","S2DfulH1kt",
-"hUTw7JRJQB","nlaBys7Mxk","DQimpxXTI4","CK5W7Chuy3","e6e4z7fsYM","UlU3Me6e4z","FjHXRThjNn","BpYhVWreyP","KsjRKlXFOB","9XyT9Fhtgl",
-"Cfgr3piJSk","5Mg9rQssNC","Q6LixZ4I1v","7ku1phUTw7","9XyT9aez9y","S77LHYOfrY","2hEEUSmGzv","0YAGHFhtgl","29QAzlViBv","qUJMdaDGtS",
-"uQIczD6rBy","GrDg70Wr5y","Uvlv4pWiOs","lj07QOUqFM","faHir8RCUA","tuDySOUYuF","4W0Tlru4UG","uvf7AKr8ys","Zv7z0y94nw","b29RJDLhzM",
-"JRJQB7fsYM","5IhmG6q6L9","AXpwEPOUYS","e6e4zpT8wu","RkQkezHF1q","ciuWzEoToP","8xEKzni2v1","lweGy7hyVv","M6qcGFjHXR","Vprf2MaJQs",
-"uupzkd7vjM","oQ87rG1RhS","vkCHH4dEz6","aL6AJJ2mQi","S77LHmX2GE","G1RhSC2Irc","SmGzvKsjRK","pFrrl0BmCy","ReKEWv2eC3","VIlwPAOgEe",
-"dpe1v6q6L9","yluBxG1RhS","wDajXRsQUq","mX2GENxx9V","VerEA8xEKz","ni2v1t98iW","In3NSQnJ1S","yEfy9FGzgp","SmGzvRsQUq","Mkgy8dpe1v",
-"jSjS3gjUTu","lpF6WX6Pin","SbRYyMmKGJ","HfyNQy94nw","aFFssTwano","t59lRIRh48","Oz8yZVjCZq","jzUqRuTacx","VNCPd2TRI7","7ku1puQIcz",
-"4QMc9KsjRK","OUYuFtaOXK","VBjhzIjTwP","tl72WtvdkD","DLhzM5VZjS","U3yw5bZLvS","SjskQdpe1v","3otm6RkQke","0h1b1xReec","FPfSEd7vjM",
-"v2eC364s8N","VBjhzbrhlQ","RxrsmTXQ0Z","AgJHQAIYUu","WDVWJiqv4k","soy9tEdBKc","14FLRpFrrl","Cp3mZv8yFN","wDajXlsQGo","hE1QlFVMxo",
-"WaWsvNAFuw","ix74rv2eC3","azIWp5IhmG","uJScXWDVWJ","JkzUnjS1aj","jeskS8cVD3","zqH0WUmaEv","J2mQiFhtgl","HRxd8W3VFH","vLsmSRBhp0",
-"hE1QlyEfy9","MK07YK20wK","NcICASs0Zu","KsjRK6AFT0","JIqXiaFFss","L7cGcMmsIo","5Mg9r2Nslm","VjCZqfFDrJ","FLsphuupzk","EdBKcnlaBy",
-"vkCHHKZamH","HzZT8mz8gx","uPX7GQYxC0","ZhwG1FFDui","CdyBV4W0Tl","TXQ0ZcQOnv","uN6r3AIYUu","FnPFBuLtKs","YjB9tdmoS7","suY4xaFFss",
-"0ao3lCfgr3","1j5L8WmadA","4dEz6v1Hln","4QMc9F6PT2","MGlTF4QMc9","n1pmODcpWB","45cIH3otm6","618DiQWxoT","S77LHM6qcG","qaofNhe9IA",
-"NcICASWfou","ydG8U2DREs","CdyBVyofH3","0BmCyjfREu","WPmlx7lUXZ","uQIczY1mC0","WPmlxFxX9q","5Drn0BGaQY","mX2GEjfREu","VBjhzzY1GY",
-"8U2nUtlILt","b29RJGWqqX","In3NSHfyNQ","K20wK5Mg9r","GWqqXcShY2","SbRYyFLsph","euZA5tjQxs","aFFssGSQwj","K20wKW3VFH","JXljWM6qcG",
-"UmaEvYw2oU","DLhzMKsjRK","M6qcGFLsph","jS1ajBCxeC","lsQGo6AFT0","pFrrlDz1R3","WDVWJjSjS3","MezSWvOqCE","ZJTXHix74r","hSSvQrz7Ut",
-"KASQ8Fhtgl","taOXKhSSvQ","D6rBy2TRI7","DcpWBgjUTu","fqypycQOnv","FGzgpKsjRK","uupzk5Drn0","v1Hln16lHc","kB5nP7fsYM","7Ow5ClsQGo",
-"tl72WdmoS7","3otm6ZuDtD","14FLRHP433","zbIYYRmDcr","uLtKspiJSk","aez9y8TxD7","qQxHP2TRI7","prNT6BbwgA","uupzkfFDrJ","O3iyQ14FLR",
-"WreyPy94nw","uJScXt59lR","jtn0XkZANm","ciuWzY1mC0","GSQwjM6qcG","L7cGcKZamH","WaWsvMm8si","pT8wupFrrl","iKqhrqaofN","RkQkehE1Ql",
-"lkMUAUl4a1","S77LHa00b5","nFqikSs0Zu","9GXkXuvf7A","t59lRqUJMd","Yw2oUUvlv4","0MR5XDcpWB","SWfou5IhmG","QbxXclj07Q","uLtKs7fKYU",
-"bZLvS24ARF","DcpWB7lUXZ","zHF1qRpBQm","MezSWRpBQm","cmXIXv1Hln","b29RJAIYUu","OUYuFFNYIM","LDk6fvLsmS","XflUqblLA9","Yw2oUK20wK",
-"dpe1vK20wK","FhtglxReec","JkzUnEdBKc","2DREs5Mg9r","yluBxsoy9t","7ku1prhl0J","AXpwEvLsmS","2TRI7wDajX","FjHXR7hyVv","yofH3wiHrZ",
-"7fKYUblLA9","oVQp6lj07Q","4QMc9Waim6","uPX7G618Di","2hEEUOUqFM","hSSvQbgJAz","uupzkQssNC","piJSkaL6AJ","uupzkBGaQY","618Di45cIH",
-"OxWIH0Wr5y","he9IAYjB9t","EoToP3otm6","0MR5Xrhl0J","fmIK1tjQxs","t98iWVBjhz","L7cGc55rfB","uQIczwiHrZ","SWfouIRh48","HlUbFqaofN",
-"G1RhSB3qem","YOfrYgf8rI","RACujcmXIX","cQOnv8U2nU","uvf7A5Mg9r","VerEA4QMc9","ksJbyzz4ZU","zHF1qWmadA","a00b5gtCA5","euZA5HRxd8",
-"zHF1qO3iyQ","jeskS55rfB","pv0i72ZHdk","d85a9Zv7z0","9eoRczHF1q","7fsYM5nmWv","MmsIoZJTXH","aFFssqUJMd","3weIFBpYhV","lpF6WzQt6Q",
-"S77LHwiHrZ","iB08lulk41","l83Ud0h1b1","GXdoHZhwG1","dhSuHuupzk","QWxoTd85a9","sqVrfuAWyp","JkzUnBbwgA","Ta8f6W3VFH","qQxHPGXdoH",
-"v8yFNAOgEe","0MR5X6q6L9","RkQkeDz1R3","IBe8kEoToP","2Yz7EOz8yZ","OxWIHIBe8k","SjskQ45cIH","RxrsmWDVWJ","Yf2EchSSvQ","o8UydlpF6W",
-"cmXIXNxx9V","uoStwguMb8","ni2v18FmFH","OUYuFiwzGk","uupzklH1kt","ZzJHWChuy3","7hyVvG1RhS","Gv3Fq9XyT9","ciuWzXyPZN","AOgEeciuWz",
-"gtCA5ru4UG","aFFssHzZT8","0YAGHlXFOB","pvgjSs93Ml","8xEKzpT8wu","lweGyMK07Y","wDajXJKWYR","6q6L9djsrv","MK07Yrhl0J","xXTI4VNCPd",
-"aL6AJogLgc","jeskSEdBKc","fcwDa1LB1L","VIlwPuN6r3","m4bxUMaJQs","O3iyQlViBv","xXTI4xReec","4W0TlpFrrl","Q6LixEOE1o","RACujWMiS3",
-"LDk6ftuDyS","QClRLRzaZA","hi5X7ZuDtD","Yw2oUL7cGc","ciuWzBbwgA","SjskQFwEJz","0Kyfssx5Gl","0h1b17fsYM","yofH3tvdkD","FVMxoQClRL",
-"5Drn0uvf7A","AkKTkChuy3","CqqaDKASQ8","yvOMImz8gx","hYBCKZUnqt","QClRLUl4a1","tuDyS7hyVv","SWfouYw2oU","vOqCEGSQwj","DLhzMSjskQ",
-"QChxsQnJ1S","s93MlMmsIo","uAWypQ6Lix","OUYuFQClRL","bZLvSSjskQ","tAOsr2Nslm","taOXKqaofN","Twano7Ow5C","HlUbFVIlwP","Ul4a1jtn0X",
-"MezSWVprf2","xciqpNhXdu","QClRLQworu","9iGoTnlaBy","RmDcrGWqqX","lH1ktzz4ZU","ThjNnwiHrZ","gf8rI6q6L9","jfREu0Kyfs","MmKGJ5drc6",
-"Cp3mZfaHir","WreyPQYxC0","e6e4z0YAGH","Nxx9VSjskQ","C2Irctl72W","kZANm64s8N","Y1mC0ZzJHW","tuDySYjB9t","Yw2oUHP433","jfREuBFkb8",
-"o8UydMmKGJ","6q6L95nmWv","bgJAzP6bcg","gtCA5TXQ0Z","a00b5Twano","POUYSJKWYR","gtCA5oQ87r","0ao3lhUTw7","Chuy3C2Irc","14FLRECMvU",
-"FLsph0PktI","he9IAOz8yZ","3weIFjSjS3","Kr8ysBpYhV","fcwDajiVBP","uvf7Ai7WMQ","pWiOsOz8yZ","hi5X7pAhR1","P6bcgzY1GY","FFDuigtCA5",
-"P6bcgJKWYR","FNYIMrhl0J","14FLR48cHL","taOXKVprf2","gjUTu5Namm","hE1QlFjHXR","sqVrfZJTXH","0h1b1FNYIM","zFgtBatef2","2DREs55rfB",
-"fcwDaIn3NS","CdyBV0MR5X","W7cTsDcpWB","DQimpHP433","EoToPuJScX","GXdoHQChxs","ydG8UuN6r3","POUYSReKEW","fqypyCdyBV","7ku1ppT8wu",
-"Yw2oUSWfou","b29RJjS1aj","0PktIlm0pD","TwanoZ4I1v","LDk6fJ2mQi","MezSWMK07Y","v8yFNpWiOs","G1RhSMojnP","zHF1qk85Ae","5ZaEzfcwDa",
-"cL0aEY1mC0","t59lRUlU3M","29QAzy94nw","uTacxWaWsv","GrDg7FxX9q","vOqCEn1pmO","7fsYMfLNg8","uPX7GhYBCK","hYBCKuoStw","AmdQdru4UG",
-"s93MlyEfy9","zz4ZUYw2oU","9eoRcuoStw","euZA5cL0aE","4QMc9VIlwP","d85a99GXkX","5nmWvCxVEf","tuDyS2Nslm","euZA5IjTwP","RsQUqfqypy",
-"ThjNnulk41","7X3uyFLsph","2DREsix74r","KZamHIBe8k","OUqFMKZamH","zHF1q2hEEU","TXQ0ZdmoS7","POUYSK4GS8","0h1b1rz7Ut","blLA9D6rBy",
-"NhXdu48cHL","wDajXQYxC0","AOgEeHP433","618DiNAFuw","4W0TlBGaQY","8TxD7oGu6x","Oz8yZVNCPd","lViBvP6bcg","gIYvEMkgy8","FjHXRQYxC0",
-"djsrvDQimp","ZuDtDpT8wu","7fKYUtuDyS","tl72WD6rBy","l83UdThjNn","SbRYyuvf7A","7fsYMtvdkD","AmdQd6q6L9","14FLRtuDyS","Twano9XyT9",
-"0YAGH0Wr5y","3weIFatef2","I7p2aHP433","JXljWblLA9","vkCHHMm8si","J2mQi16lHc","Rxrsm5iGN5","VNCPdmX2GE","uLtKsJXljW","9iGoTBbwgA",
-"ZJTXHU3yw5","Mkgy8suY4x","9rlg9suY4x","vLsmS4dEz6","In3NSt59lR","POUYSxXTI4","fcwDaX6Pin","JIqXiQbxXc","HP433NhXdu","OxWIHjSjS3",
-"QYxC0EOE1o","55rfBNhXdu","7ku1pni2v1","fFDrJCxVEf","iKqhrCp3mZ","BpYhVMK07Y","uPX7GLbRTH","G1RhSHP433","oGu6xuJScX","RACujyEfy9",
-"KASQ85VZjS","jtn0XnnP8o","GWqqX580YD","9y4lw1LB1L","OHaBz14FLR","VjCZqYh1hF","jS1ajt59lR","F6PT2SbRYy","rz7UtYh1hF","TwanogjUTu",
-"CdyBVa00b5","RsQUqP6bcg","JJs5mSs0Zu","YjB9tOz8yZ","MK07Y9GXkX","JIqXia00b5","m4bxUK4GS8","F6PT2brhlQ","iB08lW3VFH","0KyfsDQimp",
-"gtCA5Qworu","SmGzvU3yw5","JXljWnFqik","QssNCt59lR","5IhmGx3LDe","iKqhrFwEJz","8TxD7MaJQs","taOXKgdQsS","GXdoHmz8gx","PYBf4aDGtS",
-"07n1clCMxy","VIlwPaFFss","rhl0JQ6Lix","GSQwjKZamH","bZLvSkB5nP","NhXdue6e4z","5Mg9ryvOMI","55rfBSjskQ","hi5X7uJScX","aFFssdpe1v",
-"NcICAjSjS3","MK07Yix74r","IBe8kcL0aE","yofH3suY4x","rhl0JCdyBV","EdBKc1LB1L","sqVrfChuy3","P6bcgRpBQm","5nmWvuN6r3","1j5L85iGN5",
-"AOgEeGrDg7","iKqhrZUnqt","jfREuLbRTH","WDVWJ7fsYM","Twanox3LDe","cmXIXQbxXc","ZhwG1QbxXc","In3NS9GXkX","cQOnvv1Hln","v1HlnjfREu",
-"uQIczjeskS","FNYIMZhwG1","HlUbFBbwgA","okgRiZv7z0","dQ586s7Mxk","uLtKsX6Pin","7lUXZxciqp","Z4I1vs4786","WPmlxlViBv","MK07YEOE1o",
-"0MR5XnlaBy","IKxdLfqypy","lViBv8cVD3","iB08lblLA9","FGzgpDz1R3","UlU3Mtl72W","gdQsStaOXK","cmXIXRzaZA","TwanotvdkD","BpYhVfFDrJ",
-"FxX9qpFrrl","uoStw2hEEU","G1RhSIn3NS","QssNCMojnP","guMb8lViBv","Yh1hFo8Uyd","pWiOsG1RhS","IRh48prNT6","NOHszBFkb8","RpBQmpWiOs",
-"16lHcuPX7G","J2mQinnP8o","lj07QzqH0W","NOHszxReec","a00b5ni2v1","pvgjSKsjRK","GSQwjBpYhV","uAWypiwzGk","POUYS14FLR","VerEA14FLR",
-"jS1aj0PktI","xXTI4GXdoH","MaJQs4dEz6","FPfSE9rlg9","DQimplkMUA","WreyP5drc6","RACujU3yw5","cmXIXt59lR","hYBCKVjCZq","9eoRckZANm",
-"yluBxulk41","vOqCE9XyT9","t98iWMojnP","lXFOBQ6hMC","P6bcgHRxd8","64s8NcShY2","FVMxoM6qcG","Oz8yZru4UG","lViBvcShY2","4QMc9uvf7A",
-"ZJTXH9XyT9","yEfy9VerEA","cL0aEDcpWB","0Wr5yBGaQY","KsjRKo8Uyd","9XyT9yToGW","Mm8sis7Mxk","55rfB8xEKz","oGu6xRmDcr","hi5X7xXTI4",
-"J2mQiEoToP","zmLYDIRh48","Mkgy8yToGW","HlUbFCp3mZ","dhSuH5Namm","GSQwjv8yFN","Ul4a1Ss0Zu","BFkb8CNHmv","pv0i7JIqXi","MaJQslXFOB",
-"tAOsrpWiOs","d7vjMCp3mZ","bgJAzmX2GE","NhXdufcJOy","uJScXQ6Lix","zqH0W8TxD7","9XyT9BGaQY","K4GS80YAGH","l83Udlm0pD","hUTw7Zv7z0",
-"JkzUn0h1b1","LewvMUmaEv","fmIK116lHc","zmLYDlXFOB","nlaByWaim6","5NammAgJHQ","yToGWpv0i7","zHF1qdQ586","GSQwjO3iyQ","MGlTFGSQwj",
-"M6qcGMm8si","gjUTuNcICA","t59lRzY1GY","uTacx6q6L9","uAWyphe9IA","FwEJzQChxs","P6bcg4dEz6","QWxoTPYBf4","2DREsjzUqR","BGaQYiwzGk",
-"OUYuFtuDyS","No0Qb14FLR","x3LDeZuDtD","PYBf48TxD7","8RCUAkB5nP","fLNg8iqv4k","atef2lj07Q","AXpwENOHsz","pWiOsPYBf4","9GXkXoVQp6",
-"NAFuwJ2mQi","FwEJzP6bcg","uupzkhUTw7","jS1ajJ2mQi","7lUXZ0MR5X","jiVBPCxVEf","I7p2a5Namm","vkCHHIBe8k","dhSuHTXQ0Z","uJScXEOE1o",
-"Pb1pa07n1c","zQt6QpT8wu","Uvlv4RACuj","fqypyVIlwP","Ta8f6FnPFB","HzZT8pv0i7","s93Ml8RCUA","POUYSn1pmO","i7WMQFFDui","ZJTXHt59lR",
-"cL0aEUmaEv","tuDySt59lR","QbxXcxReec","VNCPdNcICA","7Ow5CZhwG1","ciuWzwDajX","2DREseuZA5","jzUqRIKxdL","StlDJOxWIH","S77LHzHF1q",
-"UlU3MPb1pa","DQimpQClRL","h1zcHtlILt","ciuWzCNHmv","yToGWoQ87r","Y1mC0x3LDe","suY4x7lUXZ","7hyVvVBjhz","QYxC0NOHsz","tjQxsni2v1",
-"ZJTXHpmeCd","HlUbFuoStw","QClRLKASQ8","3weIFWreyP","nFqikyofH3","NOHszVIlwP","NAFuwxReec","ksJby2Yz7E","ix74rv1Hln","HzZT8s7Mxk",
-"v1HlnCxVEf","No0Qbpv0i7","pWiOs8xEKz","5nmWvWMiS3","m4bxUWmadA","uoStwaL6AJ","C2Irc07n1c","mz8gxiKqhr","FVMxohe9IA","8cVD3JXljW",
-"s93MlfaHir","CxVEfs93Ml","GWqqXlweGy","RzaZAJkzUn","sx5GljSjS3","W7cTsQ6hMC","gtCA5s93Ml","8U2nUAIYUu","nlaBy0ao3l","Mkgy8okgRi",
-"C2IrcZzJHW","WMiS3WmadA","cmXIXfcwDa","fLNg8Twano","NhXdufLNg8","StlDJjS1aj","IKxdL7fsYM","J2mQiFPfSE","blLA9IjTwP","kZANmX6Pin",
-"guMb8sx5Gl","Yh1hFpT8wu","WmadAjSjS3","xReecyvOMI","cShY2KsjRK","VjCZq5Drn0","Pb1paECMvU","cShY248cHL","jfREuEoToP","lkMUA16lHc",
-"Ss0Zu0PktI","LDk6fLDk6f","cShY22ZHdk","48cHLlCMxy","JXljWYf2Ec","16lHcqUJMd","VNCPdS2Dfu","i3pydWreyP","VLTy6W7cTs","MK07YYh1hF",
-"9GXkX3weIF","tvdkD2DREs","mX2GEBbwgA","zmLYDIKxdL","zqH0WWMiS3","Cfgr39eoRc","pT8wuW7cTs","7fKYUQbxXc","tuDySd85a9","OxWIHAmdQd",
-"vOqCEuupzk","EOE1ouLtKs","W7cTsWaWsv","Pb1patjQxs","dhSuHCfgr3","5Drn0M6qcG","bZLvSQbxXc","X6PinBpYhV","rz7UtCxVEf","euZA58RCUA",
-"qaofNBFkb8","In3NSOxWIH","QbxXc14FLR","FxX9qaez9y","8xEKznlaBy","ciuWz45cIH","lCMxynlaBy","MmsIofcwDa","0Wr5yBpYhV","pWiOsOUqFM",
-"VLTy6MGlTF","AmdQdPYBf4","gIYvE8U2nU","dpe1vmz8gx","0BmCypFrrl","BbwgARBhp0","9GXkXJIqXi","fmIK1zmLYD","gIYvE5VZjS","n8pJ9b29RJ",
-"Cp3mZRBhp0","VjCZq1LB1L","CK5W7tvdkD","FLsphciuWz","qUJMdlsQGo","D6rByJIqXi","lsQGoKASQ8","iwzGkfaHir","6q6L9W3VFH","aez9y7lUXZ",
-"okgRiZJTXH","0h1b10MR5X","lweGyuN6r3","VjCZqBpYhV","7Ow5ChE1Ql","DQimpv8yFN","FjHXRuAWyp","K20wKuN6r3","4QMc9X6Pin","Mkgy807n1c",
-"fFDrJChuy3","ydG8UhYBCK","BGaQYGXdoH","ThjNn580YD","Zv7z0zHF1q","FxX9qD6rBy","HzZT8K20wK","ydG8URxrsm","iKqhrs4786","IKxdLEdBKc",
-"AIYUu0Wr5y","nFqik0BmCy","ThjNnWaim6","KsjRKMmKGJ","No0QbQ6Lix","t59lRAXpwE","d85a9AgJHQ","pmeCdwiHrZ","3weIFCqqaD","G1RhSTwano",
-"C2IrcK4GS8","Cp3mZHlUbF","pv0i7Ul4a1","In3NSJKWYR","HfyNQe6e4z","azIWpPYBf4","i7WMQhUTw7","UmaEvCfgr3","MezSWFNYIM","zqH0W5Mg9r",
-"14FLRAIYUu","YOfrYqQxHP","lj07QHP433","gIYvEP6bcg","ZhwG1qQxHP","NAFuwlj07Q","fcwDa5Mg9r","gtCA5RkQke","ni2v16AFT0","W7cTsogLgc",
-"uupzkAOgEe","FwEJzaDGtS","CIShGhSSvQ","SmGzvK20wK","tl72Wy94nw","okgRiNhXdu","MmsIoX6Pin","1v5hHhUTw7","x3LDeFjHXR","iqv4kGrDg7",
-"v1HlnAgJHQ","5nmWvbZLvS","AgJHQFcWrW","zmLYDFhtgl","YOfrYd85a9","VIlwPQbxXc","QWxoTtuDyS","IKxdLtl72W","RpBQmgIYvE","lsQGod85a9",
-"guMb83otm6","QbxXcMGlTF","HRxd8WMiS3","hE1QlSmGzv","U3yw5guMb8","nFqik4W0Tl","sx5GlGSQwj","yEfy9BFkb8","jSjS3NAFuw","tAOsrFcWrW",
-"tAOsrZv7z0","7Ow5Ci7WMQ","XflUqni2v1","FPfSE6q6L9","LewvMRxrsm","ZhwG14W0Tl","07n1cEoToP","iKqhrhUTw7","Yh1hFNAFuw","AOgEet98iW",
-"aL6AJuTacx","guMb8s93Ml","WmadAuvf7A","4dEz6AmdQd","S77LHD6rBy","vkCHHsoy9t","RpBQm3otm6","hi5X7Fhtgl","rz7UtWmadA","jiVBPOHaBz",
-"faHirYh1hF","5VZjSgjUTu","FxX9qni2v1","n1pmO29QAz","nnP8oHzZT8","iB08lNcICA","ZzJHWSjskQ","nnP8os4786","1LB1LpT8wu","D6rBypFrrl",
-"7fsYMe6e4z","xReecuAWyp","yEfy9mX2GE","nnP8oP6bcg","Yh1hFk85Ae","lm0pDuvf7A","WaWsv6AFT0","FFDuiuoStw","t59lRF6PT2","ZuDtDFwEJz",
-"lCMxyh1zcH","fqypyJJs5m","vOqCEjiVBP","Fhtgltl72W","pWiOsWMiS3","IBe8kBpYhV","qaofNZ4I1v","KZamHOz8yZ","JRJQBJkzUn","Chuy3zFgtB",
-"UmaEvFxX9q","Pb1paBbwgA","djsrvFFDui","gdQsSyEfy9","5IhmGZzJHW","FFDuipmeCd","MK07Yd85a9","Chuy3ZhwG1","uN6r3MezSW","AmdQdni2v1",
-"kB5nPjS1aj","0MR5XFFDui","5NammMkgy8","wDajXDz1R3","9GXkXMmsIo","16lHcXyPZN","RACujFjHXR","uLtKsgIYvE","jzUqRAXpwE","FPfSEru4UG",
-"sqVrfzmLYD","qQxHPO3iyQ","gf8rI9XyT9","FNYIMFPfSE","Mm8siHP433","sx5GlfLNg8","fFDrJCK5W7","BpYhV2Yz7E","4QMc9G1RhS","qQxHPMezSW",
-"FGzgpokgRi","U3yw5AIYUu","BCxeCJkzUn","DG4sTcShY2","zFgtB0YAGH","AmdQdx3LDe","DQimpFPfSE","x3LDeMK07Y","CNHmvmX2GE","uTacxTXQ0Z",
-"azIWpRkQke","FPfSEqQxHP","KZamHW3VFH","cShY2ogLgc","MojnP9eoRc","zFgtBDG4sT","dQ5865VZjS","8hJdtbZLvS","zbIYYHP433","LDk6fzmLYD",
-"HRxd8zmLYD","VjCZqF6PT2","RzaZA2DREs","zz4ZUv2eC3","Q6hMC64s8N","CqqaDbrhlQ","DcpWBtAOsr","Ss0Zumz8gx","FPfSEjtn0X","L7cGc2TRI7",
-"Dz1R3atef2","RkQkeSbRYy","Dz1R3DcpWB","IKxdLeuZA5","CNHmve6e4z","MmKGJGXdoH","yEfy9hSSvQ","azIWpuN6r3","yEfy9VIlwP","3weIF16lHc",
-"GSQwj9y4lw","EOE1od85a9","BbwgAuJScX","Mm8siGWqqX","Q6hMCcmXIX","Zv7z0pFrrl","yToGW9y4lw","t98iWrz7Ut","uZPqgQ6Lix","16lHctlILt",
-"POUYSBFkb8","uoStwBCxeC","8TxD7MmsIo","EoToPBbwgA","5nmWvI7p2a","XflUqRmDcr","4QMc9WDVWJ","fcwDaQChxs","rKDLJtvdkD","LbRTHuvf7A",
-"lH1ktvkCHH","U3yw55VZjS","5VZjS9eoRc","he9IAtlILt","ZhwG10PktI","he9IA7fsYM","9y4lw8FmFH","uupzkhYBCK","okgRib29RJ","m4bxUydG8U",
-"n8pJ9piJSk","5drc6UmaEv","uN6r3Ss0Zu","rKDLJb29RJ","lXFOB1j5L8","UmaEv2Yz7E","bgJAz3otm6","iwzGkK4GS8","VBjhz618Di","e6e4zzmLYD",
-"8FmFHuPX7G","X6PinTCgPp","xReecTCgPp","OUqFMAIYUu","6q6L9v8yFN","vLsmSVjCZq","S2DfuJKWYR","fmIK1uoStw","b29RJlkMUA","rz7Utpv0i7",
-"8FmFH5nmWv","MezSW7hyVv","NOHszjS1aj","oVQp6lweGy","OHaBzHP433","5drc6SWfou","cQOnv7fsYM","7ku1ppvgjS","ru4UGPYBf4","0MR5XAIYUu",
-"bZLvSAXpwE","MmKGJ0Kyfs","pAhR1LDk6f","24ARFEOE1o","MaJQsuAWyp","k85AeuAWyp","QssNCvLsmS","tl72WYjB9t","OxWIHlm0pD","pv0i7zFgtB",
-"uN6r3Z4I1v","atef2WmadA","VNCPd5iGN5","xciqpni2v1","IKxdLtvdkD","Chuy3QWxoT","JKWYRK4GS8","uAWypyEfy9","XflUq4W0Tl","8RCUAt98iW",
-"SWfou8TxD7","ZUnqtKASQ8","WPmlxlsQGo","ZuDtDn1pmO","UlU3MP6bcg","4QMc9x3LDe","lCMxy0h1b1","JRJQBkZANm","I7p2aGSQwj","fFDrJ5Drn0",
-"VIlwPuAWyp","OxWIHOUqFM","AOgEed85a9","UmaEvI7p2a","K20wKL7cGc","uLtKs0MR5X","29QAziwzGk","07n1cVIlwP","7fsYMBCxeC","7hyVv2ZHdk",
-"I7p2aNAFuw","DG4sTYh1hF","Vprf2zY1GY","Y1mC0d85a9","ciuWzU3yw5","iB08lRsQUq","gtCA51j5L8","2TRI77hyVv","uoStwnnP8o","0PktIMmsIo",
-"vLsmSCfgr3","WMiS3NhXdu","SbRYyuAWyp","dmoS7qQxHP","Waim6zmLYD","pAhR1nFqik","No0Qb0MR5X","SWfouEdBKc","IjTwPCp3mZ","ksJby580YD",
-"OxWIHDG4sT","FxX9qjtn0X","GXdoH618Di","1LB1LSmGzv","Yw2oUfcwDa","9y4lwjfREu","8FmFHLbRTH","8hJdtJRJQB","J2mQiVprf2","JXljWQ6Lix",
-"AmdQdi7WMQ","JkzUnydG8U","uvf7AokgRi","S77LH29QAz","pvgjSGrDg7","rz7UtOHaBz","jS1aj4QMc9","uZPqgReKEW","MezSWaL6AJ","Dz1R3Ss0Zu",
-"Yw2oUfmIK1","HfyNQ618Di","HlUbFprNT6","Ss0ZuHzZT8","NAFuwHlUbF","FwEJzD6rBy","MmKGJy94nw","d85a9LDk6f","M3zXL2DREs","pFrrl1v5hH",
-"Cp3mZuN6r3","0MR5XSWfou","vkCHH4W0Tl","rKDLJVBjhz","HP433s7Mxk","BGaQYIRh48","L7cGcv2eC3","gf8rIgdQsS","CNHmvAgJHQ","QbxXcCdyBV",
-"bgJAzSmGzv","nlaByrhl0J","cL0aEfFDrJ","PYBf4TCgPp","rKDLJi3pyd","0KyfsNcICA","8xEKzPYBf4","soy9t2Yz7E","vLsmSn8pJ9","RACujm4bxU",
-"JJs5mguMb8","4W0TlQworu","HzZT82TRI7","n8pJ9Gv3Fq","U3yw5gIYvE","lpF6WlweGy","o8Uyd8U2nU","lpF6Wn1pmO","oQ87rJXljW","PYBf45Mg9r",
-"zQt6Q5nmWv","pT8wuaFFss","ni2v1mX2GE","9rlg9BFkb8","v8yFNuPX7G","QnJ1SVerEA","K20wKzqH0W","QWxoTqUJMd","618Di8U2nU","ThjNnGv3Fq",
-"MGlTFUl4a1","PYBf4oQ87r","l83UdPb1pa","iB08lIjTwP","K4GS8DQimp","taOXKsuY4x","MK07YZhwG1","xReecSbRYy","GXdoHs4786","tuDySlm0pD",
-"48cHLY1mC0","7hyVvNcICA","5iGN5JJs5m","uN6r3FLsph","5Drn06q6L9","fqypypmeCd","BFkb8lH1kt","8RCUAgf8rI","4W0TlDz1R3","9iGoTni2v1",
-"D6rByfLNg8","W7cTsYjB9t","RACujokgRi","tvdkDXflUq","Mkgy8Uvlv4","MK07Ya00b5","zY1GYzqH0W","jSjS3bgJAz","29QAzVprf2","jtn0XYjB9t",
-"gtCA5WPmlx","5IhmG5VZjS","lpF6WUl4a1","tl72WzqH0W","FnPFBDG4sT","RkQkejfREu","FLsphCfgr3","tvdkDlCMxy","bgJAz8RCUA","Yf2EciwzGk",
-"GrDg7ReKEW","cShY2POUYS","ReKEWGWqqX","8FmFH7fKYU","fLNg8HlUbF","Y1mC0Waim6","DLhzMFjHXR","aFFss07n1c","dhSuHFVMxo","S2DfuCp3mZ",
-"oVQp6O3iyQ","wiHrZJKWYR","iqv4kFnPFB","VLTy6zbIYY","FLsphqQxHP","HRxd824ARF","In3NSlpF6W","uZPqg07n1c","uAWypWMiS3","C2IrcdQ586",
-"sx5GlXflUq","55rfBAmdQd","d7vjMcShY2","lXFOB8TxD7","0KyfsfcJOy","CK5W7HzZT8","D6rByVIlwP","9GXkX8xEKz","brhlQFLsph","5nmWv8TxD7",
-"618DiuPX7G","prNT60BmCy","tuDySe6e4z","gtCA55Namm","S77LHDG4sT","5drc6RkQke","djsrv7Ow5C","QWxoTuTacx","0YAGHciuWz","GWqqXM6qcG",
-"FNYIMHfyNQ","lkMUAAIYUu","4QMc9StlDJ","AgJHQzQt6Q","nFqik7fKYU","WreyPwiHrZ","8U2nUzqH0W","FjHXRs93Ml","ru4UGFhtgl","2TRI7hi5X7",
-"QnJ1S07n1c","bgJAzDQimp","JIqXiogLgc","Cp3mZXflUq","RpBQm5iGN5","gjUTu9eoRc","W3VFHzHF1q","8U2nU7Ow5C","0PktIn1pmO","RpBQmNo0Qb",
-"BGaQYo8Uyd","0Wr5yOHaBz","uoStw5iGN5","5Namm7fKYU","gjUTumX2GE","L7cGcBGaQY","ciuWzzY1GY","J2mQiFnPFB","Fhtgl5ZaEz","KZamHSjskQ",
-"uAWyp5Drn0","fcwDaPOUYS","mX2GELbRTH","tvdkDUmaEv","RxrsmDQimp","7X3uyuupzk","5IhmGMmKGJ","XflUqlViBv","7fKYUjeskS","ciuWzJJs5m",
-"kZANmF6PT2","4QMc90ao3l","ru4UGVerEA","Gv3FqCdyBV","4dEz6hSSvQ","v8yFNZ4I1v","pvgjSMaJQs","2NslmS77LH","8xEKziKqhr","ZuDtDFPfSE",
-"okgRiCp3mZ","C2IrcCNHmv","gjUTuBGaQY","d7vjMFGzgp","n8pJ9JIqXi","9iGoTBGaQY","CqqaDv2eC3","Kr8ys48cHL","HP4336q6L9","RBhp00YAGH",
-"uoStwS77LH","1v5hHdpe1v","oVQp60Kyfs","3otm6rz7Ut","QClRL7ku1p","HzZT8tjQxs","tjQxs7lUXZ","fqypy5VZjS","BCxeCcmXIX","AXpwEjiVBP",
-"D6rBybgJAz","NOHsz8TxD7","Dz1R3UmaEv","OUqFMFnPFB","C2IrcYf2Ec","MGlTFVjCZq","lsQGorKDLJ","RpBQmS2Dfu","LbRTHGSQwj","ThjNnTXQ0Z",
-"I7p2aciuWz","TXQ0ZFNYIM","4QMc9faHir","NcICAgf8rI","F6PT2jeskS","he9IAbZLvS","POUYSU3yw5","YjB9teuZA5","F6PT2lXFOB","48cHLzz4ZU",
-"hSSvQCp3mZ","fcJOyNxx9V","AIYUuWreyP","mX2GEWaim6","AXpwEo8Uyd","HP433P6bcg","24ARFs4786","hYBCKGrDg7","Uvlv48xEKz","48cHLzqH0W",
-"EOE1odmoS7","RsQUq7lUXZ","jzUqR0PktI","RBhp0sqVrf","14FLREdBKc","t59lRpWiOs","48cHLWreyP","zqH0Wlj07Q","6AFT0vOqCE","wDajXpT8wu",
-"lkMUAFcWrW","guMb8ZzJHW","uN6r3ZUnqt","blLA9euZA5","zFgtBOUYuF","K4GS89eoRc","UmaEvPYBf4","FhtglfaHir","n1pmOCqqaD","2TRI7iwzGk",
-"Q6LixLbRTH","suY4x0Kyfs","zqH0Wi7WMQ","45cIH7lUXZ","zQt6QRxrsm","P6bcgk85Ae","MmKGJrhl0J","zFgtBECMvU","yvOMIuTacx","Vprf2OUYuF",
-"LDk6fThjNn","Cp3mZM6qcG","7hyVvOHaBz","uupzkpmeCd","55rfBBGaQY","mX2GEogLgc","WMiS3zbIYY","BCxeCVNCPd","OHaBzJRJQB","gdQsStvdkD",
-"MmKGJgjUTu","Oz8yZtaOXK","Zv7z0piJSk","2NslmThjNn","YOfrYl83Ud","NOHszM3zXL","gtCA5uupzk","rz7Ut0MR5X","Nxx9VUvlv4","ZzJHWfmIK1",
-"prNT6sx5Gl","o8UydprNT6","VIlwPUvlv4","580YDZv7z0","fqypyFNYIM","RpBQmTwano","uoStwCK5W7","vkCHHMkgy8","ni2v145cIH","WreyPoGu6x",
-"PYBf4P6bcg","m4bxUPb1pa","7Ow5CjzUqR","8cVD3GXdoH","xReecDz1R3","5NammnnP8o","TXQ0ZReKEW","5Mg9rCIShG","MGlTFru4UG","AIYUujfREu",
-"5ZaEzS77LH","MojnPlj07Q","KZamHLewvM","HlUbFFNYIM","RsQUqbZLvS","hi5X7NcICA","OxWIHtuDyS","aFFssogLgc","cL0aEOz8yZ","RsQUqb29RJ",
-"Pb1pai3pyd","jfREuXyPZN","s7Mxkn8pJ9","lweGy14FLR","taOXKKZamH","6AFT0atef2","CxVEfLDk6f","CdyBVD6rBy","POUYS8hJdt","azIWpUlU3M",
-"zz4ZUWDVWJ","EoToPVNCPd","S77LHGXdoH","1LB1LRzaZA","djsrv8xEKz","WreyPcmXIX","8cVD3oVQp6","h1zcHSmGzv","9GXkXlkMUA","UmaEvuN6r3",
-"uoStwP6bcg","jtn0XlsQGo","In3NS4QMc9","EOE1oY1mC0","FjHXRdpe1v","zQt6Qn1pmO","EoToPRACuj","t98iWe6e4z","fcJOyzqH0W","NhXdut59lR",
-"tuDySjeskS","pT8wuFNYIM","IKxdLni2v1","RxrsmYOfrY","MaJQsD6rBy","dpe1v6AFT0","EOE1o1j5L8","GWqqXECMvU","RBhp0P6bcg","VIlwP07n1c",
-"zHF1qCqqaD","y94nwYf2Ec","lm0pDLewvM","16lHcpT8wu","0h1b1TXQ0Z","pT8wusqVrf","VBjhzRkQke","aez9y2Nslm","b29RJOxWIH","zQt6Qx3LDe",
-"fcwDaBpYhV","LDk6fJkzUn","fcwDaY1mC0","Mm8siD6rBy","zqH0WxReec","qaofNMK07Y","Vprf2Chuy3","618DiRpBQm","ThjNnKASQ8","VIlwPhE1Ql",
-"GrDg7euZA5","ZUnqtQWxoT","S77LHS2Dfu","CIShGn1pmO","GSQwjlkMUA","Q6hMC5iGN5","Kr8ysoQ87r","7lUXZCIShG","oGu6xv2eC3","Uvlv48cVD3",
-"nnP8ofcJOy","JRJQB0PktI","FVMxociuWz","FhtglKASQ8","dmoS7lCMxy","FnPFBuJScX","6q6L9a00b5","5iGN5MezSW","TXQ0ZoVQp6","a00b5zz4ZU",
-"J2mQifaHir","yofH38xEKz","wDajXOUYuF","AkKTkulk41","dpe1vXflUq","D6rBy9XyT9","ZJTXHOxWIH","tjQxsWreyP","VBjhzjtn0X","zbIYYAgJHQ",
-"tl72WIRh48","BbwgAMaJQs","VjCZqoVQp6","s4786QClRL","K20wKmX2GE","gf8rIY1mC0","FPfSEZ4I1v","WmadA29QAz","Dz1R3kB5nP","atef2gjUTu",
-"DG4sT7X3uy","3weIFuTacx","5drc6U3yw5","2Yz7EBbwgA","nlaByVNCPd","uJScXW7cTs","uJScXUlU3M","UlU3M8xEKz","zmLYDksJby","5Drn0FcWrW",
-"lH1ktpmeCd","wiHrZlj07Q","Yw2oUFhtgl","WPmlxd7vjM","nnP8o5IhmG","nnP8oFwEJz","o8UydDcpWB","uTacxm4bxU","S2Dfu0Wr5y","JJs5mlpF6W",
-"d85a9ogLgc","CqqaDtl72W","ZzJHWEOE1o","WreyPXyPZN","ix74rru4UG","lpF6WqQxHP","Cfgr3AOgEe","7lUXZQworu","0ao3lXyPZN","dhSuHaL6AJ",
-"VjCZqguMb8","kZANmiB08l","tlILtDG4sT","IRh48fqypy","uQIczW7cTs","zY1GYe6e4z","s7MxkL7cGc","atef22Nslm","EOE1o8RCUA","Vprf2PYBf4",
-"lm0pDQ6hMC","yEfy9MK07Y","BbwgAuvf7A","BpYhVl83Ud","FPfSEKASQ8","bgJAzFLsph","tAOsrqaofN","24ARFX6Pin","zQt6QfaHir","rz7UtprNT6",
-"FwEJzgdQsS","i7WMQhSSvQ","CK5W7Nxx9V","L7cGcNOHsz","lj07Q0BmCy","jtn0XeuZA5","zqH0WSbRYy","7fKYUWaim6","7lUXZ7fsYM","yofH3s93Ml",
-"MezSWThjNn","Q6LixPOUYS","s4786lj07Q","OUqFMqaofN","lCMxydQ586","gdQsSDcpWB","QnJ1SFNYIM","tlILtOxWIH","aFFssDQimp","pAhR1faHir",
-"Nxx9Vtl72W","K4GS8No0Qb","fcwDaAIYUu","n1pmOFPfSE","bZLvSsx5Gl","dQ58645cIH","lj07Qrz7Ut","dhSuH7ku1p","0MR5Xni2v1","TXQ0ZWMiS3",
-"7fsYM1j5L8","jSjS3Zv7z0","lj07QIBe8k","J2mQipmeCd","kB5nPs93Ml","YOfrYtvdkD","oVQp6QWxoT","xReec618Di","EOE1oKr8ys","WPmlxUmaEv",
-"hi5X7KsjRK","h1zcHvLsmS","CdyBVFPfSE","KZamHuQIcz","l83UdQnJ1S","n1pmOVerEA","S2DfuTa8f6","FFDuiuPX7G","29QAzm4bxU","jiVBPtaOXK",
-"7ku1pjzUqR","Kr8yse6e4z","Yh1hFaL6AJ","OHaBzdhSuH","gjUTuMmKGJ","580YDLbRTH","MGlTFWPmlx","OHaBzVIlwP","aFFssk85Ae","3otm6aez9y",
-"QWxoT5drc6","Nxx9VOHaBz","h1zcHTa8f6","8U2nUGWqqX","lXFOBs93Ml","ni2v1mz8gx","rKDLJ5VZjS","LewvMBFkb8","vkCHHReKEW","sx5GlVIlwP",
-"Uvlv4L7cGc","yvOMI14FLR","WreyPNxx9V","sx5GlpFrrl","0PktITXQ0Z","AXpwEuN6r3","VLTy61LB1L","guMb85Mg9r","yEfy9t59lR","IBe8kCfgr3",
-"piJSk48cHL","gjUTuVjCZq","580YDsuY4x","oQ87rCqqaD","ru4UG45cIH","pmeCdpv0i7","xciqpgIYvE","rhl0JokgRi","14FLRFNYIM","Chuy3ru4UG",
-"aFFssFVMxo","Q6hMCWreyP","29QAzzY1GY","HP433gtCA5","7lUXZgtCA5","fLNg8FxX9q","OHaBzM6qcG","RsQUqKZamH","SjskQQWxoT","ru4UG0Kyfs",
-"RBhp05VZjS","dmoS7fcwDa","SjskQlCMxy","yToGWGWqqX","YjB9tk85Ae","EoToPtl72W","QbxXcuTacx","sqVrf5Mg9r","faHirGrDg7","uN6r3RkQke",
-"jS1ajksJby","WMiS3NOHsz","hE1QlRkQke","lpF6WNhXdu","48cHL0PktI","kB5nPFhtgl","AIYUuBGaQY","W7cTslH1kt","zmLYDQnJ1S","7X3uyRxrsm",
-"1j5L8NOHsz","8cVD3IjTwP","0YAGHECMvU","Oz8yZYw2oU","B3qemd85a9","16lHcAOgEe","1LB1LlkMUA","pvgjSpiJSk","pAhR17fsYM","GWqqXFnPFB",
-"9y4lwi3pyd","9iGoTG1RhS","FnPFB29QAz","Gv3FqqaofN","X6PinSjskQ","v2eC3lweGy","F6PT2MezSW","FwEJz48cHL","gIYvERxrsm","SjskQjfREu",
-"SbRYyU3yw5","UmaEvXyPZN","VNCPdRsQUq","VerEASWfou","hi5X7PYBf4","mX2GErKDLJ","qQxHPYw2oU","s93MlQ6Lix","X6PinKsjRK","3otm6hUTw7",
-"LDk6f0YAGH","RmDcr4dEz6","m4bxU1LB1L","UlU3MuTacx","b29RJpT8wu","uoStwdhSuH","AgJHQLbRTH","7ku1paez9y","uvf7ARACuj","64s8NLewvM",
-"jzUqReuZA5","NcICANOHsz","kB5nPDQimp","x3LDeChuy3","ZhwG1uupzk","BFkb8o8Uyd","h1zcH4dEz6","aL6AJhi5X7","4QMc9CIShG","Cp3mZwDajX",
-"MK07YyofH3","fqypy4QMc9","fcwDalpF6W","W7cTsWPmlx","uAWyp0PktI","v2eC3Y1mC0","5ZaEz07n1c","taOXKlj07Q","CK5W7hSSvQ","uN6r3uAWyp",
-"jiVBPL7cGc","ZJTXHRACuj","pAhR1Ta8f6","GrDg7XyPZN","OHaBzFhtgl","DcpWB6AFT0","iwzGk07n1c","MK07YlXFOB","F6PT2In3NS","RACujDQimp",
-"X6PinEoToP","AXpwEdhSuH","24ARFFhtgl","VIlwP2hEEU","bgJAzTCgPp","zqH0Wtl72W","K20wKQnJ1S","MK07YlViBv","Pb1pazHF1q","0BmCy29QAz",
-"tvdkDuJScX","ix74rRkQke","SjskQcL0aE","CNHmvsuY4x","CqqaDVBjhz","ZuDtDFVMxo","JJs5m0YAGH","In3NS9iGoT","BpYhVWmadA","m4bxUS77LH",
-"i3pydiqv4k","CqqaDW7cTs","l83Udfqypy","0ao3ljeskS","uvf7Av8yFN","iwzGkJKWYR","mX2GENOHsz","Mkgy8hYBCK","ThjNnsx5Gl","NhXdudmoS7",
-"uvf7Ak85Ae","KsjRK29QAz","5Namm7fsYM","SWfouhE1Ql","QYxC0hUTw7","GXdoHpAhR1","uJScXFnPFB","brhlQ55rfB","h1zcHm4bxU","dhSuHCdyBV",
-"FcWrW3weIF","QssNCyofH3","GSQwjVprf2","Y1mC05Mg9r","n1pmO618Di","v2eC3uPX7G","WaWsvSmGzv","4W0Tl24ARF","lH1ktbrhlQ","h1zcHOz8yZ",
-"NhXdui3pyd","SjskQ5VZjS","zmLYDdjsrv","soy9tyvOMI","rKDLJ7fKYU","Chuy3oVQp6","ni2v1aFFss","Pb1pa2Nslm","618DivLsmS","taOXK8FmFH",
-"brhlQhUTw7","8U2nUNAFuw","Ss0ZuDcpWB","QbxXcB3qem","QnJ1S3weIF","qaofNjzUqR","BbwgACqqaD","BbwgAfmIK1","BbwgAQClRL","W7cTsgtCA5",
-"iqv4kuupzk","uPX7G8U2nU","VerEAFwEJz","QClRLMm8si","v1HlnlCMxy","taOXKFnPFB","CNHmv0ao3l","VNCPdsoy9t","5Mg9ruvf7A","lkMUAokgRi",
-"S2DfuFnPFB","hSSvQAgJHQ","5drc6bgJAz","he9IA1v5hH","ydG8U24ARF","lH1ktgIYvE","QChxsgdQsS","Nxx9VD6rBy","F6PT2Yh1hF","W7cTsF6PT2",
-"64s8NQssNC","BGaQYtlILt","pv0i7BCxeC","QworuCqqaD","BpYhVzqH0W","5Mg9rVBjhz","zqH0WfLNg8","JJs5mzqH0W","wDajXX6Pin","FGzgpoQ87r",
-"CK5W7StlDJ","WDVWJD6rBy","CK5W7hUTw7","55rfB7X3uy","jiVBP8FmFH","7lUXZLbRTH","dpe1vkB5nP","EdBKcLewvM","lm0pDHzZT8","lH1ktm4bxU",
-"iwzGkHfyNQ","uQIczfLNg8","2DREsECMvU","uAWypaez9y","HP433W3VFH","O3iyQFhtgl","lCMxypiJSk","FVMxoFcWrW","hSSvQguMb8","2ZHdkUlU3M",
-"8TxD75ZaEz","zmLYDHlUbF","VjCZqhE1Ql","MmKGJmX2GE","i3pyd0Wr5y","NhXduDz1R3","uPX7GoGu6x","0Wr5y24ARF","W3VFHv1Hln","VLTy6qaofN",
-"U3yw5NAFuw","M6qcGX6Pin","JIqXiRzaZA","HfyNQatef2","zHF1q9rlg9","8U2nUIKxdL","qaofN7X3uy","5Mg9rRzaZA","9eoRc7Ow5C","Chuy3W7cTs",
-"b29RJlsQGo","uLtKsQ6hMC","48cHLD6rBy","Chuy3W3VFH","lm0pDgtCA5","ciuWzmX2GE","9rlg9EoToP","v2eC314FLR","jS1ajQnJ1S","JJs5mCNHmv",
-"2DREsCqqaD","uN6r3VNCPd","l83Udd85a9","zHF1qzz4ZU","FFDuiuLtKs","2DREs48cHL","5NammAkKTk","tl72WXflUq","RkQkeMm8si","IRh488RCUA",
-"WPmlxokgRi","L7cGc0BmCy","yluBx9iGoT","Twano07n1c","KASQ8RBhp0","SWfouQYxC0","6AFT0UmaEv","lj07Q64s8N","CqqaDjiVBP","Q6Lix4W0Tl",
-"JXljWdpe1v","h1zcHFPfSE","xXTI4ulk41","gtCA5cL0aE","P6bcgG1RhS","d85a9jzUqR","48cHLM6qcG","PYBf4v8yFN","55rfBaFFss","S77LH5Drn0",
-"gtCA5RsQUq","IKxdLyvOMI","KASQ81j5L8","HlUbFgdQsS","QClRLQWxoT","NcICAuAWyp","QbxXc0Kyfs","ECMvUDz1R3","1v5hHlXFOB","HfyNQ2Nslm",
-"vOqCEuQIcz","MK07YyvOMI","45cIHpFrrl","Qworu5IhmG","tl72WdQ586","BFkb8ZzJHW","zFgtB0PktI","RzaZAkB5nP","NOHszKZamH","v1HlnRmDcr",
-"mX2GE7X3uy","nlaByKsjRK","ksJbyhSSvQ","0MR5Xb29RJ","Q6LixPYBf4","tvdkDlm0pD","9iGoTFNYIM","EOE1oRxrsm","hi5X7nFqik","POUYS9rlg9",
-"Zv7z0euZA5","UmaEvAOgEe","lViBvoVQp6","jfREuaFFss","5iGN5zbIYY","kZANmNxx9V","Vprf27fKYU","fFDrJvkCHH","iqv4k8RCUA","JXljWEdBKc",
-"fcJOypAhR1","QWxoT4W0Tl","tuDySRkQke","k85AeRzaZA","fLNg8tjQxs","HRxd81LB1L","tl72WAmdQd","AgJHQ0YAGH","pvgjSIn3NS","zz4ZUPb1pa",
-"WreyPWreyP","wiHrZlCMxy","zbIYY7fsYM","tAOsry94nw","16lHcAkKTk","n1pmOCfgr3","0MR5X5ZaEz","pAhR1b29RJ","VBjhzjS1aj","U3yw5GWqqX",
-"14FLRFFDui","ni2v1NhXdu","IjTwP0MR5X","yEfy907n1c","bgJAzWaWsv","d85a92hEEU","0KyfsyToGW","8cVD30ao3l","9GXkX7fKYU","MGlTFsqVrf",
-"Kr8ys5Namm","k85Aee6e4z","rKDLJLDk6f","CIShGVerEA","F6PT2AOgEe","2DREsyToGW","dpe1ve6e4z","kZANmWMiS3","xXTI48cVD3","bgJAzFhtgl",
-"Yf2EclpF6W","C2Irc0h1b1","ReKEWFFDui","64s8NGv3Fq","bZLvS0BmCy","iB08lTXQ0Z","G1RhSFwEJz","Uvlv4FVMxo","WmadAe6e4z","Yh1hFTCgPp",
-"lH1ktokgRi","uJScXPYBf4","s93MlWreyP","RpBQmRzaZA","ydG8Un1pmO","55rfBWPmlx","ulk41L7cGc","uPX7G0YAGH","jtn0X7fsYM","EdBKcWPmlx",
-"GrDg7AOgEe","Ta8f6ZzJHW","piJSki7WMQ","rhl0JxReec","CqqaDPb1pa","S2DfuHfyNQ","s93MlJkzUn","pvgjS5IhmG","5VZjSuLtKs","ydG8Ut59lR",
-"xXTI4GrDg7","XyPZN9eoRc","24ARFy94nw","qUJMdprNT6","GXdoH8hJdt","GrDg75Drn0","IRh48UlU3M","0BmCyYf2Ec","0KyfsY1mC0","JKWYRs7Mxk",
-"RpBQmMK07Y","o8UydCqqaD","s7MxkfcJOy","ciuWzgjUTu","pT8wuvkCHH","07n1c5ZaEz","48cHL5Mg9r","lH1ktJJs5m","okgRiRpBQm","aFFssBpYhV",
-"jS1ajyofH3","uAWyp6AFT0","KsjRKmz8gx","qQxHPFwEJz","prNT6ZuDtD","iKqhrK4GS8","KsjRKECMvU","5Drn0rz7Ut","nnP8oK20wK","lViBv7fKYU",
-"pv0i7K20wK","0BmCyQ6hMC","SbRYyuTacx","Yf2EcHRxd8","t59lRs4786","AXpwES77LH","e6e4zRzaZA","8cVD3iB08l","U3yw516lHc","ru4UGCqqaD",
-"prNT6VIlwP","Mm8sid85a9","i7WMQxciqp","k85AeC2Irc","ReKEWzFgtB","dpe1vJkzUn","ulk41NOHsz","B3qemdjsrv","AOgEe5Mg9r","ZzJHWPOUYS",
-"FwEJziwzGk","RzaZAStlDJ","29QAzaDGtS","uZPqgzmLYD","5Drn0580YD","t59lRlViBv","yToGWLbRTH","5drc6HlUbF","QbxXcjtn0X","uPX7GHlUbF",
-"Mkgy80h1b1","FLsphzY1GY","8hJdtt59lR","lj07QvOqCE","cL0aEzHF1q","ulk41IKxdL","7ku1pWMiS3","CdyBVAIYUu","QChxsFwEJz","YjB9tydG8U",
-"tAOsrIn3NS","2Nslm3weIF","8FmFHzbIYY","t59lR8RCUA","RzaZAHP433","X6PinuPX7G","DG4sTPb1pa","uN6r37hyVv","s93Ml8FmFH","zmLYDMmKGJ",
-"djsrvOz8yZ","In3NSsoy9t","9iGoTB3qem","55rfBjSjS3","CNHmvmz8gx","NAFuwCNHmv","QssNCpT8wu","RBhp0O3iyQ","IRh489eoRc","gjUTufmIK1",
-"8U2nUTwano","5nmWv8hJdt","FnPFBfcwDa","lweGyOHaBz","s93MlcQOnv","i7WMQsuY4x","HzZT8e6e4z","m4bxUCqqaD","8RCUAzqH0W","RpBQm7X3uy",
-"MK07YpAhR1","uvf7AoVQp6","NAFuwWMiS3","oGu6x16lHc","oQ87r2ZHdk","lsQGonlaBy","cQOnvdmoS7","o8UydAkKTk","fmIK18hJdt","brhlQQworu",
-"WreyPt59lR","7hyVvHRxd8","P6bcgsoy9t","M6qcGPb1pa","3weIFQbxXc","8FmFHnFqik","aDGtSCqqaD","16lHc9iGoT","FnPFB7X3uy","CIShGRBhp0",
-"9GXkXo8Uyd","pmeCd9rlg9","RmDcrru4UG","RsQUq8U2nU","okgRiiqv4k","QnJ1SUvlv4","lViBvfmIK1","lpF6W55rfB","OHaBzsx5Gl","QWxoTS2Dfu",
-"qaofNs93Ml","mz8gx2Yz7E","IRh485nmWv","POUYSvLsmS","xXTI4HP433","OUqFMcL0aE","lXFOBfFDrJ","fqypyulk41","h1zcHyToGW","580YDtaOXK",
-"ZzJHWJIqXi","BpYhVK4GS8","ECMvUjeskS","pAhR1MaJQs","iwzGkLewvM","FxX9q16lHc","ZuDtDLewvM","5IhmGVLTy6","dhSuHFLsph","s7MxkuN6r3",
-"guMb8Q6hMC","7fKYU5Drn0","IjTwPtvdkD","4dEz6In3NS","i7WMQFhtgl","fcwDaogLgc","GrDg7tAOsr","BCxeCLbRTH","1LB1LkZANm","618DiRBhp0",
-"Cp3mZlCMxy","GWqqX3weIF","yvOMIHzZT8","FcWrWAkKTk","pWiOslViBv","8cVD3brhlQ","yluBxoGu6x","2ZHdkqUJMd","h1zcHZJTXH","5Mg9rdpe1v",
-"JJs5mLbRTH","9XyT9ciuWz","HzZT8MezSW","6AFT0RACuj","0MR5XCp3mZ","VLTy6FFDui","WPmlxDcpWB","soy9ttjQxs","jS1ajlkMUA","HRxd81v5hH",
-"K20wKMmsIo","9iGoTNxx9V","0MR5XFVMxo","HP433Q6hMC","atef2blLA9","DcpWBCNHmv","9rlg9DQimp","lpF6WhYBCK","Waim6B3qem","l83Ud7X3uy",
-"MmsIohYBCK","8FmFHL7cGc","MK07YGrDg7","kZANmVjCZq","0PktIZUnqt","6AFT0jfREu","FVMxookgRi","aL6AJWreyP","zz4ZUv1Hln","In3NSFnPFB",
-"MezSWRzaZA","pvgjSlj07Q","lXFOBiKqhr","0MR5XqQxHP","BFkb8M3zXL","he9IAn1pmO","v2eC3atef2","1LB1LXyPZN","Zv7z0rz7Ut","CqqaDBpYhV",
-"O3iyQDz1R3","nnP8oCp3mZ","ECMvUn1pmO","Yh1hFnnP8o","uvf7AlkMUA","Cfgr3ZzJHW","ksJbyYOfrY","YjB9tAkKTk","Q6hMCjS1aj","pv0i7JKWYR",
-"nlaByhE1Ql","FGzgpCK5W7","HfyNQFPfSE","QssNC0ao3l","fcJOygIYvE","tuDySsx5Gl","NcICAQssNC","mX2GE9GXkX","5drc6i3pyd","S2DfuFVMxo",
-"Ta8f6faHir","rz7Uthi5X7","ciuWzVerEA","6q6L9uupzk","uupzki3pyd","HzZT8sqVrf","55rfB8TxD7","o8UyduTacx","n1pmOa00b5","MojnPlm0pD",
-"QChxsFcWrW","I7p2a5IhmG","LDk6fIn3NS","lH1ktMm8si","Cfgr3aFFss","9XyT9NcICA","BFkb8WaWsv","CIShG0h1b1","wDajXnnP8o","0h1b1uoStw",
-"W7cTsU3yw5","gdQsS4QMc9","JIqXilsQGo","wiHrZyEfy9","HfyNQ2ZHdk","NcICAs93Ml","K20wKs93Ml","m4bxUuoStw","uQIcz6q6L9","HfyNQ3weIF",
-"gIYvEJKWYR","zbIYYuJScX","VerEAfFDrJ","azIWpYf2Ec","POUYSEdBKc","WmadA16lHc","rKDLJKASQ8","0ao3ltvdkD","MezSWSWfou","jiVBPqUJMd",
-"ksJbyiqv4k","AXpwEpWiOs","iB08ll83Ud","fmIK1dmoS7","BGaQYDQimp","Ss0ZuL7cGc","Ul4a1LewvM","Yw2oU7Ow5C","gdQsSQChxs","RkQkeQ6hMC",
-"SbRYyIKxdL","Nxx9V9y4lw","U3yw5P6bcg","tAOsrVprf2","WaWsvqaofN","6q6L9lj07Q","Uvlv4lXFOB","rhl0JdQ586","Oz8yZUl4a1","HlUbFFhtgl",
-"5Mg9rFjHXR","YjB9tZhwG1","4QMc9uJScX","jfREuvkCHH","RmDcrO3iyQ","In3NSrhl0J","cQOnvb29RJ","D6rBy14FLR","ogLgc6AFT0","MaJQsEOE1o",
-"OUYuFcL0aE","faHir7lUXZ","IRh48K20wK","7X3uyKZamH","0PktI2hEEU","GXdoHYf2Ec","lCMxysqVrf","jfREuSmGzv","uTacxCqqaD","NAFuwQChxs",
-"lkMUAMK07Y","O3iyQJkzUn","WreyPdjsrv","9XyT9VjCZq","0KyfsWMiS3","t59lRgtCA5","C2IrcpFrrl","FLsphpmeCd","IBe8kd7vjM","MaJQspAhR1",
-"zqH0WThjNn","HRxd8CxVEf","K20wK7fKYU","fqypyOUqFM","RBhp0FGzgp","guMb8azIWp","v8yFNn8pJ9","pvgjSKASQ8","Uvlv4JRJQB","QClRLCqqaD",
-"gf8rItaOXK","MezSW1v5hH","n8pJ98RCUA","8hJdtReKEW","Mkgy8618Di","d7vjMqaofN","rKDLJ1v5hH","7Ow5CoGu6x","9rlg9AkKTk","YjB9tuLtKs",
-"zY1GY29QAz","iwzGk5Namm","48cHLwiHrZ","VBjhzt59lR","XyPZNPOUYS","MmsIo29QAz","s4786yvOMI","F6PT2Q6hMC","2DREsxReec","m4bxUuLtKs",
-"bZLvSW3VFH","nnP8orz7Ut","QYxC0NcICA","ECMvUKr8ys","AkKTkuPX7G","LbRTHs93Ml","soy9tPYBf4","GWqqXzHF1q","3weIFjS1aj","t98iWvOqCE",
-"KASQ8uN6r3","KsjRKcL0aE","dpe1vI7p2a","i7WMQaL6AJ","X6Pin9iGoT","lkMUApvgjS","4W0Tln1pmO","HfyNQjSjS3","pAhR1C2Irc","8hJdtAXpwE",
-"AXpwEY1mC0","uPX7GlH1kt","WmadAdQ586","J2mQiIBe8k","KsjRKpvgjS","gtCA5yEfy9","jeskSxReec","7fKYUMkgy8","Pb1papAhR1","xciqpZuDtD",
-"yEfy9CdyBV","WMiS3uQIcz","ThjNnOz8yZ","MmsIoeuZA5","No0QbuZPqg","yvOMI8RCUA","O3iyQRxrsm","HP433rhl0J","sx5GlHlUbF","7X3uysqVrf",
-"iqv4k8hJdt","yEfy9EoToP","MojnPKr8ys","i7WMQ7fKYU","uZPqgzHF1q","UlU3MDz1R3","Yw2oUpvgjS","lXFOBwDajX","v1Hlnni2v1","2DREsWMiS3",
-"FwEJzRxrsm","Z4I1vThjNn","7X3uyksJby","fLNg8XyPZN","tvdkDJKWYR","he9IA48cHL","ksJbyOz8yZ","16lHc7X3uy","lweGy1v5hH","5VZjSblLA9",
-"ZhwG15Drn0","FxX9qEOE1o","0h1b1KZamH","48cHLpvgjS","CxVEf07n1c","bgJAzQ6hMC","vOqCEtlILt","FjHXRru4UG","ThjNnokgRi","2ZHdkS77LH",
-"SjskQhYBCK","DQimp5Drn0","No0QbdQ586","FjHXRfmIK1","C2IrcfFDrJ","WreyPlweGy","zY1GYiKqhr","FNYIMOHaBz","1j5L8uLtKs","uN6r31LB1L",
-"G1RhSQYxC0","pv0i7Z4I1v","1j5L8uZPqg","3otm6Q6hMC","t98iWWaim6","3otm6fmIK1","v8yFNk85Ae","uZPqgMK07Y","lkMUAyEfy9","2ZHdkgdQsS",
-"DcpWBmX2GE","mz8gxgdQsS","BbwgAe6e4z","lm0pDM6qcG","d85a9FwEJz","bZLvSZhwG1","pAhR14W0Tl","4dEz6uPX7G","dQ586IRh48","QClRLBFkb8",
-"lj07QhYBCK","zFgtB1v5hH","x3LDeStlDJ","tl72WAOgEe","ZuDtDciuWz","iKqhrjtn0X","XflUqqaofN","8cVD3UlU3M","SjskQRBhp0","VNCPduQIcz",
-"ydG8U7X3uy","Yw2oUHRxd8","MK07YzqH0W","kB5nP8xEKz","W3VFHYh1hF","CxVEfqaofN","xReeck85Ae","uJScXTCgPp","uAWypJkzUn","zqH0WXyPZN",
-"v2eC3pWiOs","D6rByuPX7G","n8pJ9TCgPp","uZPqgFFDui","dmoS7580YD","55rfBP6bcg","lpF6W2Yz7E","FhtglZJTXH","5VZjSBFkb8","Q6hMCpvgjS",
-"RBhp0TXQ0Z","suY4x6q6L9","yluBxv2eC3","euZA5BCxeC","mz8gxX6Pin","uoStwWaWsv","5drc6rz7Ut","9iGoT07n1c","NAFuwBCxeC","DcpWBHlUbF",
-"AkKTkx3LDe","SjskQYw2oU","uQIcz7lUXZ","i7WMQHP433","8RCUAGrDg7","dhSuHt59lR","HRxd85nmWv","cmXIX8xEKz","gIYvE9GXkX","HP4338cVD3",
-"pAhR1azIWp","EoToP3weIF","HlUbFh1zcH","lCMxy2ZHdk","7ku1pfcJOy","M6qcGuJScX","zY1GY2DREs","fFDrJDz1R3","prNT6oGu6x","hYBCKDLhzM",
-"l83UdZUnqt","No0QbFjHXR","s93MlM6qcG","rhl0JlViBv","W7cTs7ku1p","SmGzvv1Hln","Chuy3bZLvS","o8Uyd4QMc9","aFFssX6Pin","O3iyQs93Ml",
-"KASQ8piJSk","9GXkXzqH0W","JIqXi2DREs","BpYhV8RCUA","y94nwblLA9","JXljW7ku1p","7fsYM5iGN5","pFrrlfLNg8","AmdQdJRJQB","CIShGMmsIo",
-"e6e4zOUYuF","iKqhroGu6x","tlILtjiVBP","ksJby64s8N","1v5hHAXpwE","Uvlv4mz8gx","WreyP0Wr5y","RBhp0tvdkD","vOqCEM3zXL","KASQ87ku1p",
-"hE1Ql8TxD7","zY1GYSs0Zu","CxVEfGv3Fq","580YD07n1c","K20wK8U2nU","Cfgr3gdQsS","pWiOsYjB9t","EdBKcJXljW","CNHmv0h1b1","8FmFHjS1aj",
-"2Yz7ES77LH","mz8gxVNCPd","OUqFM9XyT9","RmDcrFjHXR","nFqikazIWp","pAhR1hE1Ql","t98iWuAWyp","pv0i7OUYuF","pWiOszqH0W","45cIHAkKTk",
-"Zv7z0MmKGJ","euZA5Dz1R3","EoToPeuZA5","YjB9t0YAGH","OxWIHXyPZN","Kr8ysF6PT2","hYBCKaez9y","9GXkXzFgtB","tjQxsjfREu","pmeCdNAFuw",
-"nnP8otuDyS","uTacx4dEz6","KASQ8dmoS7","7fsYMFVMxo","FwEJzsqVrf","aFFssiqv4k","MaJQso8Uyd","IBe8katef2","CxVEfciuWz","Yh1hF14FLR",
-"I7p2apvgjS","rKDLJvLsmS","FFDui6AFT0","sqVrfulk41","POUYSJ2mQi","No0QbNcICA","ThjNndQ586","d7vjMuQIcz","W3VFHKZamH","5Drn0LewvM",
-"IKxdLoVQp6","KsjRKAXpwE","9GXkXuLtKs","VjCZqfqypy","VjCZqK4GS8","B3qem3otm6","7fsYMpiJSk","zmLYDZuDtD","x3LDeCNHmv","CNHmv8TxD7",
-"YOfrYaDGtS","OHaBzNAFuw","fqypytuDyS","5IhmGpFrrl","gjUTu2Yz7E","gjUTu0h1b1","dpe1vFLsph","Ul4a1FPfSE","AXpwERBhp0","OUYuFuTacx",
-"v1HlnXyPZN","8hJdtzY1GY","VerEApAhR1","piJSk580YD","s4786B3qem","MojnPSmGzv","QWxoTy94nw","iB08logLgc","5ZaEzbrhlQ","brhlQHRxd8",
-"48cHLZhwG1","Mkgy8NAFuw","FFDuiJXljW","jiVBPjiVBP","Y1mC0fmIK1","piJSkQChxs","29QAz9y4lw","fcwDaqQxHP","h1zcHgf8rI","hE1Qlv8yFN",
-"Ul4a14QMc9","SmGzvy94nw","uN6r35nmWv","CIShGbZLvS","WreyPPYBf4","iB08lFnPFB","QYxC0cmXIX","x3LDeZJTXH","SWfouzHF1q","Gv3FqKASQ8",
-"StlDJZ4I1v","Waim6atef2","rz7Ut2hEEU","IBe8kJ2mQi","x3LDesx5Gl","qQxHPM3zXL","lH1ktO3iyQ","Zv7z0NOHsz","8FmFHiB08l","CxVEfpmeCd",
-"IjTwPPb1pa","ZhwG1No0Qb","KsjRK7lUXZ","AIYUumz8gx","lj07Q2DREs","RpBQmUvlv4","IKxdLkB5nP","AmdQdfFDrJ","VjCZqRkQke","QChxsYOfrY",
-"soy9tECMvU","4QMc9IRh48","fcJOyRmDcr","DLhzMiwzGk","s7MxkMaJQs","0YAGHBCxeC","gIYvEjiVBP","Q6hMCfmIK1","JXljWTXQ0Z","Q6LixOz8yZ",
-"5nmWv2Yz7E","e6e4zDLhzM","nlaByAkKTk","hSSvQuvf7A","hSSvQ8xEKz","Yh1hFiqv4k","VLTy6k85Ae","SmGzvv8yFN","8U2nUmX2GE","FFDuizQt6Q",
-"VNCPdZ4I1v","pT8wuulk41","FNYIM6q6L9","M3zXLNcICA","9eoRcRpBQm","UlU3Mk85Ae","VjCZqyofH3","jzUqR0ao3l","e6e4zGrDg7","KASQ8QnJ1S",
-"KASQ8VBjhz","rKDLJZv7z0","M3zXLMmsIo","VLTy6SbRYy","2Yz7E64s8N","pWiOsQ6hMC","oVQp6gdQsS","UlU3MHP433","bZLvSwiHrZ","JkzUnSjskQ",
-"Uvlv4fLNg8","oGu6xtlILt","uZPqgRxrsm","iKqhrvOqCE","wDajXzHF1q","oQ87r2Nslm","XyPZNXflUq","2DREspv0i7","oQ87r0YAGH","qaofNfcJOy",
-"AkKTksx5Gl","CxVEf3weIF","uoStwTCgPp","aL6AJzQt6Q","aDGtSlsQGo","OUYuFPb1pa","brhlQ4QMc9","lpF6Wb29RJ","DQimpRkQke","uN6r3EoToP",
-"wDajXCNHmv","qQxHPXyPZN","jzUqRzHF1q","zY1GYgf8rI","QChxstaOXK","Z4I1vSWfou","QbxXc1v5hH","YjB9tUvlv4","FLsphBFkb8","NhXduP6bcg",
-"TwanoRsQUq","9XyT9JIqXi","45cIHJKWYR","0Kyfs0YAGH","GXdoH07n1c","Cfgr3jeskS","8U2nUd85a9","8cVD3S77LH","In3NSJJs5m","K20wKJkzUn",
-"gtCA5NAFuw","Yw2oUMezSW","zmLYDuPX7G","0PktIZzJHW","7lUXZWPmlx","kB5nP0Wr5y","1LB1LAmdQd","5IhmGlViBv","uLtKsv1Hln","qUJMd2TRI7",
-"I7p2a6q6L9","QClRLjzUqR","AkKTkzHF1q","CxVEf6AFT0","CNHmvcQOnv","x3LDeJIqXi","yofH3MGlTF","Yw2oUQYxC0","S2DfuZ4I1v","cmXIXHzZT8",
-"zqH0WlpF6W","55rfB6q6L9","8RCUAAOgEe","AIYUuY1mC0","x3LDei3pyd","uJScXFLsph","NcICABCxeC","ZJTXHQworu","FwEJzaL6AJ","0BmCyS77LH",
-"Q6hMC580YD","1v5hHv8yFN","tlILtxXTI4","8FmFHEoToP","Ta8f62Nslm","vOqCEt98iW","prNT6BCxeC","0Kyfs5IhmG","0ao3lOUqFM","VNCPd5VZjS",
-"SWfouMojnP","ZzJHWjiVBP","gIYvEn8pJ9","gIYvEDLhzM","D6rByaFFss","HRxd8fcJOy","0MR5XzQt6Q","5ZaEzdmoS7","Oz8yZWreyP","FnPFBD6rBy",
-"qQxHPm4bxU","yEfy9FPfSE","nFqikprNT6","x3LDeUvlv4","MGlTFyvOMI","dhSuHe6e4z","W7cTsTCgPp","4dEz6t59lR","IjTwPblLA9","XflUqbZLvS",
-"uQIczKr8ys","a00b5ZhwG1","4W0Tle6e4z","JJs5mgIYvE","gIYvEiKqhr","8cVD3uPX7G","WaWsv1j5L8","GWqqXuupzk","MezSWv2eC3","JkzUne6e4z",
-"zHF1qMmKGJ","QbxXcmz8gx","zQt6QjS1aj","bZLvSGSQwj","BCxeCnnP8o","gtCA5HzZT8","fFDrJ07n1c","hSSvQ7lUXZ","29QAz3otm6","Y1mC0uupzk",
-"QChxshE1Ql","zQt6QNAFuw","B3qemCdyBV","24ARFB3qem","atef2iqv4k","v8yFNDz1R3","Cfgr3In3NS","Vprf2pT8wu","i3pydRACuj","fLNg8uZPqg",
-"Twano8FmFH","ru4UGuvf7A","gf8rIHRxd8","yToGWKsjRK","BFkb8uLtKs","Ta8f6LDk6f","No0QbksJby","k85Ae0ao3l","t59lRIKxdL","14FLRFhtgl",
-"FjHXRFNYIM","G1RhShE1Ql","WaWsvl83Ud","BCxeCk85Ae","M6qcGdjsrv","ogLgcCdyBV","oGu6x7X3uy","X6PinRxrsm","FVMxojiVBP","JKWYRFnPFB",
-"fmIK19GXkX","lm0pDhe9IA","uN6r3ydG8U","Cfgr3oGu6x","AXpwEWreyP","CIShGSmGzv","aL6AJuupzk","iB08lo8Uyd","9y4lw5VZjS","NcICARzaZA",
-"Vprf2M6qcG","MmsIoaez9y","GSQwjogLgc","uoStwulk41","kZANmAIYUu","0PktICdyBV","xReec8U2nU","IRh48lm0pD","VNCPdBFkb8","IjTwPlkMUA",
-"yToGW55rfB","i7WMQh1zcH","mX2GEjtn0X","OUYuF0Wr5y","fqypyTa8f6","WMiS3OHaBz","o8Uydl83Ud","prNT6hUTw7","FPfSE8FmFH","dmoS7FNYIM",
-"WDVWJhe9IA","Vprf2jS1aj","SWfouFGzgp","atef2ydG8U","GXdoHfmIK1","lweGypT8wu","guMb82Nslm","y94nw2DREs","4dEz67ku1p","FNYIMzmLYD",
-"s4786Cfgr3","uN6r3MK07Y","BCxeCO3iyQ","MK07Yv1Hln","9eoRcHfyNQ","m4bxUEdBKc","vOqCEzHF1q","jSjS33weIF","RkQkeUlU3M","GWqqXCK5W7",
-"Q6hMCrhl0J","faHirLDk6f","2DREsgf8rI","zmLYDpWiOs","NOHszGv3Fq","Q6hMCrz7Ut","FcWrWVjCZq","BGaQYSWfou","yofH3NOHsz","QnJ1SokgRi",
-"hi5X7pT8wu","QYxC07fsYM","mz8gxhi5X7","M3zXLMm8si","SmGzvfqypy","Q6LixbrhlQ","kB5nPciuWz","5drc6JkzUn","5IhmGHP433","RBhp03otm6",
-"cShY20ao3l","J2mQiReKEW","UlU3Mo8Uyd","ZhwG11LB1L","tvdkDFVMxo","i7WMQ0ao3l","Cp3mZoQ87r","soy9tlH1kt","e6e4zAmdQd","IRh4855rfB",
-"yofH39GXkX","Pb1paB3qem","1j5L8hSSvQ","7ku1pS77LH","FGzgpJkzUn","RzaZAYw2oU","K4GS8Ta8f6","ix74rQClRL","XflUqs4786","M3zXLfmIK1",
-"29QAz0Kyfs","XflUq0PktI","AgJHQRzaZA","ogLgczz4ZU","EdBKcPOUYS","StlDJlViBv","S2DfuOUYuF","Ul4a1JIqXi","VIlwPNxx9V","XflUqcmXIX",
-"45cIHChuy3","VNCPdyToGW","fmIK1OxWIH","KsjRKzHF1q","BpYhVpiJSk","qQxHPKZamH","No0QbQssNC","dQ586IBe8k","5nmWv9XyT9","CdyBVfcwDa",
-"XflUqb29RJ","yofH37Ow5C","8cVD3Yw2oU","GSQwjazIWp","jzUqRGrDg7","24ARFReKEW","uoStwStlDJ","OHaBzB3qem","lViBvMezSW","y94nwcL0aE",
-"zY1GYTwano","dQ586aL6AJ","m4bxU2TRI7","X6Pin5VZjS","5nmWvAgJHQ","L7cGcVjCZq","QbxXciKqhr","fcJOye6e4z","b29RJd85a9","IKxdLwiHrZ",
-"QbxXcYh1hF","RzaZAaFFss","ThjNn3weIF","jSjS3ni2v1","UmaEv2TRI7","faHirCK5W7","rz7Ut0PktI","Yf2EcVBjhz","soy9tTa8f6","tjQxssuY4x",
-"No0QbAmdQd","bZLvSni2v1","CK5W7dQ586","MaJQs16lHc","jfREuk85Ae","nFqikRmDcr","6q6L98U2nU","RACujyvOMI","4dEz6W3VFH","Gv3FqCK5W7",
-"LewvMv2eC3","TXQ0ZEOE1o","MojnPaFFss","55rfB8cVD3","VBjhztjQxs","W3VFHnFqik","YjB9t5iGN5","1j5L816lHc","OxWIHs93Ml","jS1ajSWfou",
-"rz7UtGv3Fq","VNCPdtAOsr","jS1ajRxrsm","Oz8yZW3VFH","v2eC3WreyP","FhtgluPX7G","n1pmOvLsmS","8xEKzyofH3","QClRLFNYIM","lkMUAvOqCE",
-"gf8rIn8pJ9","BpYhVWDVWJ","RACujhYBCK","IjTwPFPfSE","VIlwPIBe8k","jS1aj1v5hH","zHF1qsqVrf","AmdQd2DREs","ECMvUCxVEf","LewvMFGzgp",
-"AIYUuFLsph","CdyBVbgJAz","taOXKBpYhV","MaJQsCp3mZ","9y4lwG1RhS","ni2v1sqVrf","5iGN5jSjS3","X6Pinjtn0X","7fsYMX6Pin","hUTw7qQxHP",
-"VLTy6TXQ0Z","jeskSsoy9t","pWiOsCfgr3","9GXkX8RCUA","zbIYY5Mg9r","TCgPptvdkD","48cHLkB5nP","guMb8AOgEe","QWxoT1v5hH","nnP8osoy9t",
-"lm0pD8xEKz","MGlTF9rlg9","VNCPdyofH3","v2eC3wiHrZ","0BmCym4bxU","M3zXL4dEz6","7ku1pFwEJz","G1RhSS2Dfu","jfREuW3VFH","vOqCEYw2oU",
-"FcWrW5IhmG","IKxdLBpYhV","soy9t618Di","FGzgpru4UG","k85AeGXdoH","bZLvSzY1GY","cShY2xXTI4","AXpwEB3qem","BpYhVk85Ae","tAOsrEoToP",
-"t98iWkZANm","XflUqgtCA5","FjHXRnFqik","iKqhruLtKs","RzaZAhSSvQ","okgRii3pyd","wiHrZWDVWJ","RmDcrlCMxy","faHir8TxD7","Kr8ystuDyS",
-"CdyBVogLgc","MmsIoUvlv4","MK07Y8RCUA","ReKEWazIWp","5drc655rfB","J2mQirhl0J","1LB1LRpBQm","6AFT0ThjNn","POUYSzY1GY","atef2OHaBz",
-"cShY2P6bcg","zHF1q0Kyfs","Mkgy8lweGy","ZhwG17Ow5C","J2mQi7X3uy","FxX9qCxVEf","QWxoTDcpWB","hE1QlC2Irc","he9IAzqH0W","v8yFNlCMxy",
-"IRh48rz7Ut","iB08lwiHrZ","Z4I1vfcwDa","Q6hMCCqqaD","FxX9qhYBCK","WaWsvgjUTu","QssNCulk41","rhl0J6q6L9","FVMxouupzk","jeskSzmLYD",
-"FPfSEgdQsS","cShY2GrDg7","W7cTsVIlwP","JkzUndjsrv","DQimpaL6AJ","FwEJzYOfrY","iB08lQClRL","5Drn0v2eC3","HRxd8BCxeC","SbRYywDajX",
-"b29RJXyPZN","cmXIXrhl0J","nnP8oogLgc","580YDQnJ1S","FLsphlweGy","F6PT2b29RJ","nlaByFFDui","hE1Ql4QMc9","dmoS7J2mQi","Dz1R3uQIcz",
-"d85a9ksJby","0MR5X1j5L8","pvgjSWDVWJ","MK07YiKqhr","NcICAuLtKs","XflUqlj07Q","fcwDaQYxC0","FVMxocQOnv","FVMxoYjB9t","lCMxyyluBx",
-"ZJTXHMmKGJ","ksJbyCqqaD","5drc6D6rBy","ciuWzfcJOy","zFgtBvOqCE","fcJOylpF6W","fmIK1WaWsv","FxX9quLtKs","618DicQOnv","9y4lwRmDcr",
-"9y4lwgjUTu","LewvMzbIYY","Yf2Ec3otm6","MGlTFv1Hln","RpBQmWreyP","nlaBylCMxy","FNYIMUlU3M","nlaByiwzGk","dQ586fcwDa","s4786Yh1hF",
-"MezSWrz7Ut","TwanoWmadA","5Mg9rs7Mxk","zQt6Q9iGoT","QssNCsqVrf","nFqikfcJOy","PYBf4JkzUn","atef2FjHXR","LDk6fgIYvE","OUYuFKsjRK",
-"OUYuFEOE1o","d85a9s93Ml","QYxC0fmIK1","vLsmSOxWIH","7lUXZQ6Lix","jfREu0ao3l","RpBQmZhwG1","ThjNnazIWp","dQ586LbRTH","4QMc97lUXZ",
-"Dz1R3pmeCd","i3pydVprf2","2DREsrz7Ut","uoStws7Mxk","Twanot59lR","rKDLJRkQke","jS1ajFFDui","gf8rI7lUXZ","wDajX1j5L8","l83UdyEfy9",
-"2ZHdkrz7Ut","14FLRXyPZN","gjUTu0MR5X","55rfBDz1R3","FNYIMHlUbF","Kr8ysGWqqX","9XyT9PYBf4","zbIYYk85Ae","D6rByeuZA5","9iGoTWreyP",
-"0YAGHAgJHQ","s47867X3uy","7hyVvRxrsm","JkzUnX6Pin","ZuDtDVNCPd","WDVWJCK5W7","0YAGHBGaQY","TCgPpDG4sT","CIShGpv0i7","jzUqR8U2nU",
-"CNHmvNAFuw","Pb1pa7ku1p","zFgtBzQt6Q","faHirsuY4x","zQt6QUmaEv","nFqikMK07Y","zmLYDUl4a1","lViBvrz7Ut","5Mg9r5Namm","HRxd8G1RhS",
-"QYxC02DREs","pFrrl1j5L8","7fsYMuPX7G","uLtKsWaim6","Mkgy8RkQke","QssNCbZLvS","FNYIMRxrsm","FjHXRWmadA","hSSvQlXFOB","HlUbFlXFOB",
-"5VZjSStlDJ","uvf7AYOfrY","55rfBJ2mQi","jzUqRRACuj","S2DfuDG4sT","7Ow5CSbRYy","5ZaEzmX2GE","dmoS714FLR","7fsYMtl72W","aFFssReKEW",
-"uAWypyluBx","piJSklsQGo","zbIYY5Drn0","uPX7Gb29RJ","FNYIMWreyP","UlU3M9rlg9","jfREupWiOs","dmoS7FjHXR","fmIK10BmCy","CxVEf0Kyfs",
-"2DREsM3zXL","uvf7AiKqhr","uvf7A7fKYU","ZUnqtnnP8o","Cp3mZ7lUXZ","4dEz6RpBQm","nlaByXyPZN","O3iyQU3yw5","soy9tZzJHW","t98iW5Mg9r",
-"l83Ud5Namm","Cp3mZuJScX","tvdkDJRJQB","atef2hUTw7","FGzgp29QAz","iqv4kdhSuH","EOE1o0MR5X","SbRYyprNT6","5VZjSSbRYy","I7p2aiwzGk",
-"hUTw7aFFss","jzUqRIn3NS","1j5L8uupzk","vOqCEqQxHP","uLtKsd7vjM","zqH0WJKWYR","cQOnv0PktI","ZJTXHlpF6W","IjTwPO3iyQ","ECMvUjtn0X",
-"7lUXZK4GS8","Mm8si5VZjS","7fKYUzqH0W","SbRYyS77LH","QbxXcuN6r3","5IhmGtAOsr","14FLRix74r","yofH3AgJHQ","O3iyQMmsIo","tvdkDQChxs",
-"RmDcrCqqaD","FhtglZUnqt","HRxd8YjB9t","7X3uyciuWz","aez9yBGaQY","Ul4a1guMb8","fcwDaS77LH","2Yz7EvLsmS","azIWpzmLYD","dpe1v7ku1p",
-"jtn0XoGu6x","h1zcHhYBCK","uoStwqaofN","In3NS0BmCy","dmoS7JIqXi","TXQ0Zrz7Ut","hUTw7MaJQs","KsjRKHRxd8","8RCUAzz4ZU","tlILtsoy9t",
-"64s8NWPmlx","618DifcJOy","HfyNQCNHmv","XflUqGXdoH","iKqhrhE1Ql","Nxx9VBbwgA","HRxd8guMb8","Yw2oUt98iW","a00b5S77LH","yluBxHfyNQ",
-"C2IrcgtCA5","IBe8kLewvM","NOHszTa8f6","P6bcgHlUbF","JKWYRW3VFH","VNCPdvLsmS","QworuNxx9V","NhXduQ6Lix","dhSuHJXljW","SmGzv0MR5X",
-"7fsYMTa8f6","WDVWJNxx9V","HfyNQS77LH","gjUTuStlDJ","TCgPpTCgPp","580YDuTacx","8RCUA5Mg9r","7Ow5CBFkb8","Gv3FqzY1GY","P6bcgatef2",
-"fcJOyfmIK1","1LB1LOUqFM","DLhzMFVMxo","DG4sTAmdQd","e6e4zJJs5m","wiHrZJJs5m","d7vjMZ4I1v","NcICA7ku1p","Q6hMCoQ87r","Cp3mZzz4ZU",
-"0ao3ljS1aj","AgJHQlm0pD","iKqhrtuDyS","JkzUnReKEW","8FmFHS77LH","hE1QlVerEA","LewvMFLsph","NcICAQ6hMC","cL0aEnnP8o","8FmFHoQ87r",
-"zQt6QuPX7G","TwanodmoS7","Cfgr3I7p2a","FwEJzReKEW","HzZT8kB5nP","5iGN5JKWYR","qaofNpv0i7","OUqFMfLNg8","MezSWYOfrY","OxWIHQnJ1S",
-"9GXkXFPfSE","zqH0WZJTXH","Q6LixlsQGo","AIYUupvgjS","Zv7z0LbRTH","lH1kt0YAGH","a00b5i7WMQ","BFkb8ThjNn","Yh1hFqaofN","NcICARkQke",
-"45cIHeuZA5","VNCPdxReec","Cp3mZWMiS3","tvdkDqQxHP","gIYvEM3zXL","HfyNQCxVEf","QworuhUTw7","LDk6fkZANm","BbwgAZ4I1v","GSQwjnnP8o",
-"VNCPdVNCPd","oGu6xKr8ys","QClRLF6PT2","5ZaEzjiVBP","lm0pDy94nw","0h1b18hJdt","StlDJn8pJ9","JKWYR5iGN5","YOfrY16lHc","IjTwPfLNg8",
-"ni2v1Fhtgl","NOHszYw2oU","vOqCEt59lR","RACujI7p2a","ulk415nmWv","MmKGJhSSvQ","GWqqXRkQke","yofH3lsQGo","2Yz7E0MR5X","s7MxkAXpwE",
-"F6PT2WreyP","0MR5XQnJ1S","v8yFNn1pmO","IRh489GXkX","J2mQizHF1q","AXpwEGrDg7","G1RhSpWiOs","rKDLJDLhzM","v1HlnMojnP","0PktIpWiOs",
-"YjB9tX6Pin","djsrvYh1hF","RBhp0POUYS","JKWYRtjQxs","MojnPs4786","Cfgr3StlDJ","gIYvElCMxy","OxWIHWMiS3","FFDuiwDajX","WMiS3mz8gx",
-"Uvlv4Ss0Zu","xReec7hyVv","QnJ1Slm0pD","nnP8o2DREs","CxVEfPOUYS","n8pJ9UmaEv","oGu6xoGu6x","6q6L9IBe8k","FnPFBlViBv","ksJbylm0pD",
-"WMiS39GXkX","24ARFSjskQ","zmLYDQYxC0","5IhmGGSQwj","hUTw77fKYU","1LB1LW3VFH","CdyBVi3pyd","pmeCdSs0Zu","B3qempv0i7","vOqCEAgJHQ",
-"WaWsvRkQke","POUYSJkzUn","zz4ZUVNCPd","PYBf4CdyBV","9eoRcs93Ml","k85AefcJOy","M3zXL5Namm","QWxoTQ6Lix","hYBCKDG4sT","uQIczv2eC3",
-"s4786I7p2a","8hJdtUlU3M","7lUXZdmoS7","JJs5m7hyVv","ZzJHWZhwG1","UlU3MVBjhz","8FmFHv1Hln","i3pydK20wK","Ta8f6Uvlv4","xXTI4vLsmS",
-"WmadADG4sT","5nmWvTXQ0Z","FcWrW45cIH","aDGtSIKxdL","Twanon1pmO","0Wr5ynlaBy","aFFssyofH3","OxWIHatef2","azIWpbrhlQ","XyPZNCqqaD",
-"48cHLWMiS3","Waim6PYBf4","GrDg7GXdoH","pWiOsQ6Lix","RACujdQ586","xciqpb29RJ","Z4I1vyofH3","k85AeQChxs","VjCZqvOqCE","FVMxoY1mC0",
-"rhl0JPOUYS","BCxeCVIlwP","qUJMd7Ow5C","QClRL5ZaEz","6q6L9FwEJz","ciuWza00b5","Mm8siFwEJz","QssNCSs0Zu","NAFuwSjskQ","0MR5XSmGzv",
-"RzaZAciuWz","QnJ1S2Nslm","FnPFBOz8yZ","soy9t5nmWv","prNT6atef2","SmGzv5VZjS","7X3uycShY2","QworujeskS","B3qemlH1kt","tjQxslXFOB",
-"qaofNTXQ0Z","t98iWYw2oU","zz4ZUIjTwP","uJScXHzZT8","Fhtgl8FmFH","SjskQn8pJ9","0YAGHhi5X7","FjHXRfLNg8","WPmlxjiVBP","ZuDtD7hyVv",
-"uN6r3jS1aj","uvf7ACNHmv","DG4sTlpF6W","JXljW2Yz7E","RkQkebgJAz","pAhR1oQ87r","Ta8f6oGu6x","o8UydiwzGk","qQxHPtvdkD","a00b5CdyBV",
-"fcwDagIYvE","ix74r7fsYM","aFFss2Yz7E","zqH0WaL6AJ","Zv7z0FVMxo","QChxs0YAGH","hE1QlZhwG1","pFrrltuDyS","ciuWzFLsph","hSSvQK4GS8",
-"9XyT9MojnP","QbxXcmX2GE","d85a9he9IA","wDajXlXFOB","uAWypfcJOy","IBe8kMaJQs","LewvMW7cTs","RkQke580YD","iKqhrRACuj","Ul4a1OHaBz",
-"uTacx24ARF","5Nammi3pyd","GrDg7RmDcr","CxVEfSbRYy","IjTwPQ6Lix","5drc6d85a9","qaofNOxWIH","OxWIHJKWYR","7ku1p1j5L8","zHF1qoVQp6",
-"nnP8oB3qem","b29RJQbxXc","HP4338U2nU","pWiOsogLgc","uJScXcQOnv","Ul4a1S77LH","uvf7Am4bxU","QworuoVQp6","AXpwEHfyNQ","suY4xGWqqX",
-"8xEKzlj07Q","sx5GlpAhR1","hUTw7uTacx","n1pmOkB5nP","9rlg9ZUnqt","9iGoTdjsrv","AkKTktAOsr","ZUnqtzHF1q","Mkgy81j5L8","brhlQKsjRK",
-"FhtglMaJQs","FLsphi3pyd","QChxsni2v1","7hyVvIjTwP","RkQkeIBe8k","Ul4a1RBhp0","lweGygtCA5","SmGzvLewvM","LewvMAmdQd","9y4lwyvOMI",
-"okgRipAhR1","zQt6Q6AFT0","CNHmv8RCUA","tjQxsdQ586","l83UdTXQ0Z","W3VFHSs0Zu","64s8NFLsph","CNHmvJJs5m","QChxsCxVEf","pAhR1CIShG",
-"Pb1paQChxs","v2eC3Mm8si","HRxd8VLTy6","J2mQiGrDg7","O3iyQZuDtD","n1pmOokgRi","RmDcr7ku1p","yofH3aFFss","e6e4zHfyNQ","jSjS3fFDrJ",
-"KASQ8SbRYy","9GXkXWDVWJ","faHird85a9","RxrsmSWfou","djsrve6e4z","mz8gxFGzgp","OHaBzPYBf4","iKqhrKsjRK","YOfrYuAWyp","jzUqRCfgr3",
-"AmdQdv2eC3","24ARFBGaQY","uPX7GYOfrY","2DREslCMxy","C2IrcY1mC0","L7cGcS77LH","WreyPSbRYy","JRJQBs7Mxk","XflUqdmoS7","Ul4a1X6Pin",
-"HzZT8v1Hln","MmsIolViBv","guMb8pWiOs","AgJHQPb1pa","lm0pDlj07Q","9rlg9hYBCK","QWxoTGv3Fq","Yw2oUJkzUn","HRxd8kZANm","azIWpHlUbF",
-"64s8NzqH0W","RzaZAJKWYR","Ta8f6i3pyd","vkCHHOz8yZ","2NslmUl4a1","M6qcGDz1R3","soy9tTCgPp","fLNg8fLNg8","QClRLPYBf4","XflUqsuY4x",
-"QssNCsx5Gl","i7WMQd85a9","StlDJFGzgp","FVMxoSbRYy","9rlg9jSjS3","Mm8sii3pyd","7ku1p0Kyfs","ciuWzJkzUn","s93MlMmKGJ","atef2Vprf2",
-"uvf7AZJTXH","0Wr5y6q6L9","FNYIMIRh48","I7p2aaL6AJ","HRxd8taOXK","lViBvv8yFN","Cfgr35ZaEz","faHir5Mg9r","No0QbfcwDa","WDVWJ4W0Tl",
-"yToGW29QAz","RBhp00Kyfs","uoStws93Ml","mz8gxZzJHW","GXdoHulk41","QChxsuN6r3","jS1ajAkKTk","CdyBVThjNn","55rfBHfyNQ","9rlg9lweGy",
-"jeskSAgJHQ","1v5hHOz8yZ","0Wr5yJXljW","TwanoaDGtS","DcpWB7ku1p","pmeCdnFqik","580YD5ZaEz","3weIFFjHXR","M3zXLyofH3","2TRI7QChxs",
-"MojnPSWfou","48cHLEOE1o","cL0aERxrsm","nlaByFnPFB","dQ586UlU3M","ciuWz9rlg9","v8yFNv2eC3","d7vjMfFDrJ","NcICAVjCZq","aDGtSaDGtS",
-"K20wK5drc6","cL0aEHP433","HP433hYBCK","yEfy9K4GS8","29QAzni2v1","aez9yAmdQd","618Di0PktI","StlDJd7vjM","yEfy9guMb8","48cHLmX2GE",
-"8FmFH8U2nU","S2DfudhSuH","618DixReec","KZamHFFDui","W7cTsqaofN","vOqCETa8f6","2DREsWDVWJ","VIlwPCfgr3","RmDcrAXpwE","gf8rIAIYUu",
-"IBe8kjiVBP","ThjNnoVQp6","kZANmC2Irc","VjCZqGrDg7","djsrvCIShG","CdyBVdjsrv","GWqqXThjNn","JJs5m24ARF","5Mg9rbrhlQ","TwanopvgjS",
-"Mkgy8jeskS","xXTI4ni2v1","Vprf2Yf2Ec","BbwgAPOUYS","hSSvQhSSvQ","ZhwG1djsrv","UlU3Mt98iW","BpYhVyvOMI","dpe1vvkCHH","K20wKAgJHQ",
-"GrDg78FmFH","pAhR1VLTy6","lweGy0Kyfs","SWfouFwEJz","azIWpQbxXc","QWxoTxReec","jeskSY1mC0","fqypy1v5hH","cShY2d85a9","U3yw564s8N",
-"bZLvS7Ow5C","uQIczSjskQ","i7WMQRkQke","VLTy6K20wK","wiHrZG1RhS","h1zcH0Kyfs","AgJHQsqVrf","x3LDejiVBP","zFgtBMGlTF","Gv3Fqru4UG",
-"D6rByaez9y","zFgtBRBhp0","QClRLmz8gx","In3NSYf2Ec","lCMxyMGlTF","Pb1paGWqqX","hi5X7cmXIX","Zv7z0BGaQY","xciqpTXQ0Z","7ku1pZuDtD",
-"qaofNatef2","HRxd8Kr8ys","iB08lix74r","cQOnvRmDcr","tjQxsJXljW","tl72WCNHmv","IBe8kd85a9","taOXKsoy9t","pWiOsIRh48","4dEz6faHir",
-"kZANmSjskQ","cL0aEHfyNQ","uoStwYw2oU","AIYUulXFOB","W7cTsFhtgl","lViBvO3iyQ","ReKEW9eoRc","jfREuzqH0W","8hJdtJKWYR","5Drn0IRh48",
-"tlILtUmaEv","2ZHdkSjskQ","hUTw7OUqFM","Z4I1vhi5X7","9XyT9ZzJHW","5iGN51LB1L","Ul4a1lm0pD","nFqikMm8si","Mm8siZJTXH","pmeCdlweGy",
-"zmLYDOUqFM","7fsYMgtCA5","LDk6fx3LDe","LewvMhYBCK","ZUnqtwiHrZ","zz4ZUOUYuF","FhtglB3qem","oQ87r3weIF","ciuWzMojnP","3weIFs7Mxk",
-"RBhp0RzaZA","dQ586W3VFH","GrDg7KsjRK","5Mg9rn1pmO","uAWyp45cIH","IBe8kNOHsz","QworuTa8f6","hE1QlNo0Qb","7fKYU4dEz6","C2IrcHlUbF",
-"pT8wuVNCPd","vLsmStaOXK","0Wr5yNOHsz","pvgjStvdkD","qQxHPs93Ml","In3NSiB08l","Kr8ysAXpwE","v8yFNhe9IA","ECMvUS77LH","uZPqgGrDg7",
-"qQxHPNAFuw","14FLRaL6AJ","WDVWJHlUbF","ni2v1uN6r3","m4bxUAmdQd","zqH0WG1RhS","EdBKcn8pJ9","618Di14FLR","9y4lwydG8U","Cp3mZ7ku1p",
-"MmKGJP6bcg","W7cTs8cVD3","GXdoHdQ586","AkKTksoy9t","iqv4ki3pyd","P6bcgDcpWB","Yf2EcCfgr3","hE1QlFwEJz","Mm8siZ4I1v","AIYUuThjNn",
-"vOqCEW7cTs","zmLYDM3zXL","gdQsS4W0Tl","taOXKlpF6W","VBjhzOUqFM","b29RJZ4I1v","CqqaDI7p2a","1LB1Ld85a9","0KyfsoQ87r","9iGoTrhl0J",
-"WmadAzY1GY","s93MljiVBP","dQ586CxVEf","CxVEfcQOnv","9GXkXwiHrZ","1LB1L9XyT9","OHaBzRACuj","gdQsSJKWYR","RxrsmVprf2","7ku1pgdQsS",
-"ZuDtDHRxd8","aDGtSKr8ys","4W0TlK4GS8","4dEz6dhSuH","MGlTFGv3Fq","RsQUqtl72W","ru4UGy94nw","jS1aj64s8N","vLsmS618Di","W3VFHh1zcH",
-"NOHszl83Ud","cL0aES2Dfu","5nmWvyEfy9","RACujDz1R3","YjB9tnnP8o","5Mg9rokgRi","blLA9djsrv","tvdkDDcpWB","fqypyFVMxo","JKWYRMkgy8",
-"cL0aENo0Qb","uLtKsoQ87r","mX2GEZuDtD","fmIK1YjB9t","618DiDz1R3","t98iWjzUqR","sx5GlBbwgA","JkzUni7WMQ","RBhp0CK5W7","7hyVv8xEKz",
-"HRxd8B3qem","45cIHFcWrW","WmadARmDcr","rKDLJOUYuF","dpe1vKsjRK","YjB9tQ6Lix","ydG8UWPmlx","48cHLuQIcz","SbRYyOHaBz","vOqCEMGlTF",
-"9rlg95Namm","v8yFNQ6hMC","FjHXR7lUXZ","okgRihUTw7","ru4UGZuDtD","pFrrlQ6Lix","CNHmvSmGzv","UlU3MM3zXL","ni2v1gdQsS","Yw2oUfcJOy",
-"NOHszdmoS7","Ul4a1ReKEW","iwzGk9XyT9","gtCA5vLsmS","8hJdtrz7Ut","XflUqvOqCE","W3VFHZhwG1","hUTw7i7WMQ","Fhtgl7ku1p","qaofNOHaBz",
-"0PktI9iGoT","MezSWdQ586","0YAGHWMiS3","b29RJCK5W7","F6PT2ReKEW","fcJOyyluBx","aFFssFNYIM","ni2v1Vprf2","s4786RsQUq","o8UydP6bcg",
-"zQt6QuN6r3","580YD7hyVv","k85AeStlDJ","YOfrYMkgy8","P6bcgM6qcG","DG4sT5iGN5","QYxC0uTacx","zz4ZUQworu","uPX7Gd85a9","ReKEWhUTw7",
-"hSSvQ16lHc","soy9t2TRI7","9rlg9lm0pD","lH1ktsx5Gl","AkKTkcShY2","d85a9ECMvU","blLA9GXdoH","iB08lRACuj","qQxHPBpYhV","blLA97ku1p",
-"Mkgy8pFrrl","0Wr5y0ao3l","Zv7z0SWfou","EdBKcHP433","lkMUAStlDJ","9y4lwd85a9","sx5Gl5Namm","QChxswDajX","5VZjSZhwG1","vOqCEhE1Ql",
-"JKWYR4QMc9","s4786Waim6","n8pJ9aL6AJ","Y1mC0ReKEW","1LB1LgIYvE","BbwgA7Ow5C","iB08laDGtS","oGu6x4dEz6","uoStwuLtKs","jSjS3o8Uyd",
-"tjQxskB5nP","k85AeAkKTk","d7vjMECMvU","ZzJHWSbRYy","FcWrWQ6Lix","kB5nPtlILt","sx5GlAXpwE","HzZT8nlaBy","MK07YKsjRK","fmIK1lH1kt",
-"0ao3lJJs5m","jeskS7hyVv","lViBvFnPFB","t98iWdQ586","tvdkDZJTXH","HfyNQ8cVD3","yEfy9AXpwE","i7WMQQWxoT","kB5nPjeskS","tuDySciuWz",
-"fcwDaYjB9t","Vprf2KsjRK","FGzgpx3LDe","IBe8kNhXdu","WPmlxCxVEf","5Namm0BmCy","pv0i7CIShG","07n1cpiJSk","DLhzMlweGy","pFrrlX6Pin",
-"IBe8kOUYuF","Uvlv4fFDrJ","xXTI4S77LH","atef2jfREu","d85a9MezSW","VBjhzEOE1o","k85Ae64s8N","Chuy3tlILt","d85a95ZaEz","DG4sT8xEKz",
-"uAWypDcpWB","dpe1vMezSW","s93Mltl72W","2NslmStlDJ","JRJQB2hEEU","QworuzY1GY","FLsphK20wK","7fsYMHRxd8","AkKTksqVrf","OUYuFYjB9t",
-"7lUXZFwEJz","prNT6kB5nP","jfREu7hyVv","QChxsydG8U","Dz1R3JIqXi","F6PT2XflUq","4QMc9n1pmO","Vprf2QChxs","UmaEvi7WMQ","zHF1qGXdoH",
-"WaWsvK20wK","Nxx9VJXljW","x3LDeuupzk","ix74rmX2GE","lsQGo07n1c","3otm6WPmlx","jeskSAXpwE","FLsphEdBKc","9rlg9HfyNQ","MK07YK4GS8",
-"BGaQYTwano","ciuWzAkKTk","HRxd8lViBv","mz8gxRkQke","ix74rThjNn","HlUbFThjNn","vOqCE1v5hH","gjUTuazIWp","In3NSd85a9","fcwDaBCxeC",
-"QssNCCNHmv","Oz8yZGv3Fq","AIYUuuvf7A","FFDuiQChxs","QWxoTKASQ8","ThjNnuvf7A","QChxsaL6AJ","RACujHRxd8","l83UdQWxoT","9XyT9LewvM",
-"0ao3l5Mg9r","EOE1ojiVBP","8TxD7v2eC3","zQt6QjSjS3","S2Dfui7WMQ","iqv4kgf8rI","VBjhzgjUTu","3weIFJ2mQi","In3NStuDyS","KsjRK5nmWv",
-"8RCUAQworu","8cVD3jSjS3","vOqCEyEfy9","zbIYYbZLvS","2NslmJkzUn","vOqCEDcpWB","9eoRcyluBx","hUTw7VLTy6","0PktIKr8ys","zHF1q0ao3l",
-"GrDg7zbIYY","2NslmAXpwE","Dz1R3v8yFN","NOHszk85Ae","MmKGJFjHXR","WmadAPb1pa","cShY2iKqhr","HRxd829QAz","kZANmRkQke","8cVD3PYBf4",
-"Nxx9VlkMUA","yEfy92DREs","Mkgy85IhmG","O3iyQoQ87r","iB08l55rfB","P6bcg5VZjS","5Drn0FVMxo","i7WMQni2v1","t59lRcQOnv","h1zcHiqv4k",
-"DLhzM5ZaEz","QworuIBe8k","IRh48o8Uyd","Mm8si7fKYU","8U2nUjiVBP","uoStwoVQp6","d85a9BbwgA","SbRYyHP433","9iGoTfaHir","L7cGcpWiOs",
-"Mm8siCdyBV","Q6hMCQWxoT","No0QbS77LH","JkzUnK4GS8","BFkb8P6bcg","yluBx0MR5X","2ZHdkL7cGc","MmsIoFnPFB","uoStwhUTw7","AkKTkzFgtB",
-"yluBxlj07Q","55rfBVLTy6","14FLRzbIYY","9GXkXfLNg8","Yw2oUUl4a1","ZzJHWQClRL","tlILt14FLR","uupzknnP8o","VerEADG4sT","t98iW8FmFH",
-"AmdQdFxX9q","P6bcgfaHir","CNHmvfcJOy","Mkgy88hJdt","xciqp8cVD3","d7vjMiB08l","ksJby0Kyfs","qaofNWaim6","oGu6xLbRTH","PYBf4OHaBz",
-"cL0aEDLhzM","QssNCrKDLJ","lsQGoksJby","HfyNQDQimp","AOgEeEdBKc","6q6L9jS1aj","No0QbzqH0W","pmeCdAkKTk","hYBCKWPmlx","0PktIru4UG",
-"RzaZANOHsz","6AFT0BFkb8","euZA5xciqp","P6bcgfcJOy","9eoRcs4786","16lHccQOnv","zbIYYv1Hln","8hJdtCNHmv","sx5GlYw2oU","cQOnvxReec",
-"ECMvUtjQxs","cShY2Dz1R3","cShY2hE1Ql","O3iyQzFgtB","Yw2oUW7cTs","b29RJL7cGc","Waim6Q6Lix","9y4lwciuWz","mX2GE8cVD3","blLA9CxVEf",
-"VBjhzFVMxo","zqH0Wix74r","aDGtS9eoRc","IjTwPDz1R3","ogLgciKqhr","n8pJ92Nslm","29QAzuupzk","rKDLJmz8gx","uoStw5Namm","tl72WyofH3",
-"tl72WciuWz","lpF6WWDVWJ","v8yFNGSQwj","jtn0XfmIK1","0BmCyDLhzM","ix74rYh1hF","7hyVvbgJAz","RpBQmYw2oU","vOqCEjzUqR","OHaBzpFrrl",
-"v8yFN5VZjS","e6e4zhE1Ql","WreyPiB08l","OxWIH1v5hH","AXpwERxrsm","rKDLJfcwDa","b29RJWMiS3","Z4I1vVjCZq","s93MluJScX","IBe8kAkKTk",
-"4dEz6iKqhr","fFDrJKASQ8","uQIczfcwDa","i7WMQMkgy8","zQt6QzFgtB","2DREsCdyBV","GSQwjoVQp6","KASQ8JkzUn","n1pmOSjskQ","dpe1vo8Uyd",
-"SbRYyfqypy","NhXdu7X3uy","dQ586XyPZN","8hJdtzz4ZU","1LB1LJIqXi","FwEJzk85Ae","BCxeCiB08l","EOE1oPb1pa","8TxD7Uvlv4","WmadAXflUq",
-"pFrrllViBv","WMiS3l83Ud","QbxXc8TxD7","uPX7GUl4a1","CdyBVKsjRK","s4786J2mQi","pT8wupT8wu","5Mg9rAOgEe","Yw2oUCp3mZ","VjCZqVIlwP",
-"QssNCIRh48","lweGyHRxd8","kZANmuoStw","6q6L9GWqqX","ix74rD6rBy","SbRYytaOXK","zqH0W9rlg9","5Mg9rOUqFM","VNCPdjeskS","fcJOyaDGtS",
-"W3VFHokgRi","fqypyDcpWB","uJScX5Drn0","IBe8kb29RJ","pvgjS1j5L8","L7cGcuTacx","ZUnqtxciqp","U3yw55iGN5","0ao3lcmXIX","tuDyS1j5L8",
-"ix74rzHF1q","RBhp0y94nw","JKWYRRkQke","Ta8f6CIShG","CIShGd7vjM","P6bcgBpYhV","DcpWBjS1aj","AkKTkCNHmv","zY1GYyofH3","2Yz7ELbRTH",
-"UmaEv5nmWv","AkKTkQworu","pAhR1QChxs","EdBKcguMb8","3weIF2ZHdk","ksJbyMm8si","FjHXRQnJ1S","jeskSulk41","jiVBPfaHir","aFFssIBe8k",
-"CK5W7IKxdL","fcwDalkMUA","h1zcHyEfy9","uvf7Aiqv4k","7Ow5CGXdoH","JKWYRYOfrY","lpF6WKZamH","FPfSEiqv4k","GXdoH0Kyfs","s4786Nxx9V",
-"uPX7GfaHir","BpYhVdQ586","JIqXiv1Hln","WreyPLewvM","3otm6Rxrsm","7fsYMDz1R3","Gv3FqpT8wu","h1zcH1LB1L","IBe8kv8yFN","uZPqgQClRL",
-"9GXkXb29RJ","0MR5X8TxD7","vOqCE4W0Tl","faHir64s8N","AIYUudjsrv","FFDuiCNHmv","t98iWQYxC0","1j5L8580YD","AIYUuPOUYS","oGu6xnFqik",
-"euZA5P6bcg","SjskQ5nmWv","ZhwG1LbRTH","DG4sTNOHsz","Gv3Fqhi5X7","faHirF6PT2","djsrv2hEEU","FPfSE5ZaEz","zQt6QZ4I1v","zbIYYMmKGJ",
-"x3LDeMaJQs","RkQke8U2nU","Oz8yZRBhp0","EOE1oyEfy9","nFqikSmGzv","OUqFM0MR5X","i3pydAgJHQ","azIWpiwzGk","YOfrYFjHXR","Yf2EcfLNg8",
-"oVQp6Pb1pa","580YDmz8gx","HP433CK5W7","MmKGJgtCA5","X6PinS77LH","fmIK1AgJHQ","IjTwPqUJMd","i7WMQMmsIo","zQt6Q0Kyfs","zFgtBF6PT2",
-"VNCPdzFgtB","iKqhrNhXdu","Mm8simX2GE","yEfy9t98iW","RACujdjsrv","ru4UGOz8yZ","P6bcgSjskQ","HRxd8aL6AJ","vOqCEChuy3","VjCZqIKxdL",
-"NcICA5Mg9r","VjCZqprNT6","14FLRgtCA5","O3iyQCK5W7","yofH3JkzUn","uPX7GJXljW","B3qemIjTwP","0ao3lJKWYR","hi5X79eoRc","BGaQYG1RhS",
-"RzaZAUvlv4","9y4lwW7cTs","jtn0XHRxd8","JRJQBChuy3","2ZHdkfcwDa","hE1QlBbwgA","Ss0Zus93Ml","QYxC00ao3l","RxrsmwiHrZ","Q6hMCEoToP",
-"ru4UG0PktI","6q6L9prNT6","Q6Lix6q6L9","9GXkXUl4a1","Chuy3Cp3mZ","gtCA5nnP8o","AmdQdeuZA5","FGzgpblLA9","2hEEU5drc6","WreyPIBe8k",
-"SjskQxXTI4","4QMc9K20wK","prNT6vOqCE","brhlQ9rlg9","UmaEvd85a9","JkzUnVNCPd","4QMc9AOgEe","blLA9cQOnv","dhSuHydG8U","jiVBPYOfrY",
-"bgJAzhe9IA","e6e4zSbRYy","580YDzY1GY","gdQsSjfREu","zz4ZUuN6r3","Ss0ZuMkgy8","IBe8kuPX7G","U3yw5suY4x","8hJdtRACuj","FNYIM48cHL",
-"WreyPZuDtD","D6rByCxVEf","tvdkDSbRYy","n8pJ9s7Mxk","iwzGkSWfou","UmaEv580YD","NOHszNo0Qb","VBjhzWaim6","ix74rsqVrf","WDVWJx3LDe",
-"4dEz69y4lw","ZzJHWCK5W7","prNT6jeskS","Vprf2s4786","B3qemI7p2a","3otm6jeskS","ksJbylsQGo","AIYUuhSSvQ","No0QbMojnP","lXFOBHfyNQ",
-"QssNCVjCZq","BCxeCx3LDe","FjHXRGrDg7","EdBKc7hyVv","K4GS8ZUnqt","taOXKYOfrY","ZJTXH0Wr5y","FFDuik85Ae","3otm62Nslm","wDajXt59lR",
-"iqv4kjfREu","zHF1qmz8gx","7Ow5ClXFOB","PYBf4b29RJ","MK07Yhi5X7","jSjS35nmWv","JXljWpAhR1","OxWIHvOqCE","soy9trz7Ut","K4GS8XyPZN",
-"Cfgr3hSSvQ","5VZjSvLsmS","LbRTHF6PT2","4QMc9Q6Lix","GrDg7uJScX","NhXduKsjRK","FhtglCdyBV","GrDg7oVQp6","QnJ1Sx3LDe","hE1QljiVBP",
-"uQIczIjTwP","Dz1R3BFkb8","FxX9qMojnP","a00b5hE1Ql","RxrsmBbwgA","NAFuwGv3Fq","ciuWzStlDJ","5NammRpBQm","lsQGoru4UG","dpe1v0PktI",
-"0MR5XdmoS7","4W0Tlv8yFN","iwzGkdhSuH","5NammBpYhV","UlU3M7fsYM","uAWypKr8ys","WmadAGSQwj","fcJOyBbwgA","vOqCEVNCPd","JIqXii3pyd",
-"CIShGO3iyQ","Q6LixHlUbF","zQt6QbZLvS","JKWYR7Ow5C","fmIK1Ul4a1","QworuIKxdL","QYxC0dQ586","n1pmOWDVWJ","vOqCENhXdu","lweGyLDk6f",
-"o8UydfLNg8","zQt6QNcICA","bgJAz0h1b1","qQxHPcQOnv","KsjRKd85a9","vkCHHYjB9t","07n1cpv0i7","PYBf4gjUTu","FwEJznFqik","SbRYyRsQUq",
-"uJScXd7vjM","UmaEvFjHXR","0PktIBGaQY","Vprf2HfyNQ","lsQGoBpYhV","FPfSE5drc6","Cp3mZCNHmv","xciqplViBv","07n1cmX2GE","D6rByKsjRK",
-"ru4UGi7WMQ","CxVEfXyPZN","KASQ8GSQwj","Q6Lixi3pyd","5iGN5U3yw5","StlDJtuDyS","9GXkXpiJSk","QWxoT8FmFH","s4786EoToP","lViBvuoStw",
-"h1zcHhe9IA","OHaBzzY1GY","vkCHHSmGzv","mz8gxEdBKc","FNYIMxReec","n1pmOjfREu","Cfgr3fmIK1","RkQke7fsYM","Ss0ZuWmadA","AXpwEi3pyd",
-"2TRI7bgJAz","bgJAzDG4sT","JIqXi9GXkX","GrDg7kZANm","0YAGHv8yFN","ix74rReKEW","QClRLUlU3M","MaJQsMK07Y","VerEABCxeC","h1zcH8xEKz",
-"oGu6xIn3NS","YjB9tO3iyQ","9XyT9W7cTs","7Ow5CJXljW","6AFT0pWiOs","QssNCsuY4x","zQt6QYf2Ec","1LB1LStlDJ","pFrrlulk41","xXTI4Ta8f6",
-"hUTw7aez9y","2TRI78xEKz","L7cGcPOUYS","Dz1R3oGu6x","24ARFKsjRK","uTacxF6PT2","WmadAbrhlQ","x3LDeblLA9","FnPFBFNYIM","sx5GlJ2mQi",
-"CNHmvn8pJ9","MmKGJ1LB1L","ZJTXHNxx9V","Vprf2pWiOs","AOgEe5drc6","ZuDtDHfyNQ","K4GS8StlDJ","FxX9q0BmCy","In3NSReKEW","dQ586Cfgr3",
-"ksJbyb29RJ","YOfrYtAOsr","JJs5mfcwDa","i7WMQ9iGoT","lH1kt14FLR","ZzJHW0YAGH","rhl0JYjB9t","dhSuH2Yz7E","tvdkDzmLYD","1v5hHChuy3",
-"Chuy3RsQUq","9eoRcuPX7G","prNT614FLR","NAFuwpiJSk","dmoS7P6bcg","aDGtSydG8U","9XyT91j5L8","x3LDe0h1b1","55rfB7fKYU","FwEJz0YAGH",
-"VNCPdCfgr3","OHaBz7X3uy","KASQ8jSjS3","HRxd8uPX7G","HzZT88xEKz","S77LHYh1hF","zHF1qNAFuw","taOXKTwano","tvdkDwiHrZ","KASQ8WaWsv",
-"hE1QlwDajX","uJScXQ6hMC","S2DfuMm8si","GSQwjKsjRK","VNCPdl83Ud","lXFOBC2Irc","4QMc9QnJ1S","Ss0ZujeskS","dmoS7okgRi","hi5X71LB1L",
-"gIYvErhl0J","64s8NMmKGJ","RxrsmDLhzM","ZJTXHlViBv","8U2nU2Yz7E","Dz1R3FxX9q","Yf2EcfmIK1","BGaQYv1Hln","5VZjSFGzgp","x3LDen1pmO",
-"Z4I1vdQ586","CqqaDCqqaD","wiHrZlsQGo","l83Ud0ao3l","7ku1pmz8gx","AIYUu0PktI","jSjS3TXQ0Z","FGzgpGSQwj","iB08l2TRI7","gIYvERzaZA",
-"KZamHOxWIH","rz7Ut0ao3l","580YDUlU3M","lweGyk85Ae","0PktIBbwgA","kZANm55rfB","uN6r3djsrv","Zv7z0taOXK","oVQp6BGaQY","lH1ktFjHXR",
-"NOHszEOE1o","Uvlv4OUYuF","UmaEvgdQsS","hUTw7s7Mxk","soy9tlkMUA","lCMxyzQt6Q","qQxHPjiVBP","tjQxsWPmlx","fLNg8YjB9t","7Ow5CaL6AJ",
-"Ss0ZunlaBy","aFFssZzJHW","fmIK1WPmlx","uTacxlsQGo","FxX9qHlUbF","3otm6ogLgc","Ss0ZuFhtgl","BpYhVaez9y","IjTwPzFgtB","VjCZqPb1pa",
-"ReKEWulk41","uPX7GStlDJ","dmoS7Kr8ys","64s8Ni7WMQ","aez9yHlUbF","cmXIXoVQp6","uZPqgGXdoH","fcJOypv0i7","9y4lwlViBv","tAOsr14FLR",
-"AIYUu14FLR","aez9yIjTwP","OHaBzciuWz","x3LDezQt6Q","uvf7AfaHir","Uvlv4WmadA","BFkb8rz7Ut","SmGzvtjQxs","QworuUlU3M","PYBf40ao3l",
-"o8Uyd45cIH","fcwDaQWxoT","CIShGJJs5m","QnJ1SStlDJ","OHaBzulk41","BCxeClm0pD","NAFuwQWxoT","HRxd8ulk41","6q6L9t59lR","hSSvQqaofN",
-"lm0pDbZLvS","Waim62ZHdk","Oz8yZlsQGo","atef2b29RJ","5Mg9rYh1hF","QnJ1SzmLYD","BGaQYpAhR1","prNT6IKxdL","lkMUA0YAGH","JIqXiZUnqt",
-"AmdQdMojnP","aFFssKr8ys","uAWypjSjS3","RBhp0lpF6W","d85a9uupzk","RpBQmMezSW","lweGyjfREu","5VZjShE1Ql","uAWypMK07Y","IKxdLW3VFH",
-"n1pmOlm0pD","XflUqfcwDa","7lUXZLDk6f","rhl0Jk85Ae","fqypyMaJQs","QYxC0X6Pin","VLTy6kZANm","bgJAz7X3uy","0h1b1SjskQ","RzaZAoVQp6",
-"hYBCK48cHL","IjTwPYjB9t","FVMxoUlU3M","t98iWC2Irc","zFgtB8RCUA","HP433EdBKc","64s8NZUnqt","8TxD7tuDyS","MezSWYjB9t","VjCZqyToGW",
-"MojnP8FmFH","Ta8f6FjHXR","7lUXZeuZA5","F6PT2oVQp6","ksJbypmeCd","7fKYUlpF6W","8xEKzguMb8","0Wr5yhE1Ql","P6bcggIYvE","s93Mlulk41",
-"o8UydCdyBV","zFgtB5VZjS","7fKYUn1pmO","hUTw7iqv4k","16lHcgf8rI","Mkgy8MmsIo","uQIcz2DREs","OHaBzfFDrJ","Fhtgl5VZjS","i7WMQzFgtB",
-"k85AeM6qcG","AOgEetuDyS","AXpwEpT8wu","nnP8o7fKYU","he9IArKDLJ","WDVWJgf8rI","0h1b1x3LDe","Y1mC0jeskS","a00b5KsjRK","TwanoSjskQ",
-"WaWsvpFrrl","wDajXyToGW","ogLgcSs0Zu","8xEKzbrhlQ","qQxHPt59lR","5nmWvjiVBP","jtn0XLbRTH","55rfBVIlwP","BCxeCFNYIM","618DihSSvQ",
-"RzaZA45cIH","0KyfsdmoS7","jiVBPgIYvE","TwanoCqqaD","VBjhz8RCUA","MezSW9eoRc","xXTI4Yf2Ec","29QAz8FmFH","h1zcHt98iW","ru4UGpFrrl",
-"AgJHQfcJOy","pT8wutvdkD","ksJby29QAz","D6rByksJby","wDajXhUTw7","GrDg70BmCy","KASQ85Namm","taOXKK20wK","cShY2RACuj","vkCHHx3LDe",
-"D6rBysoy9t","zmLYDJkzUn","uQIczvOqCE","FFDuiQbxXc","GSQwjbgJAz","mz8gx24ARF","aFFssCfgr3","yToGWjtn0X","i7WMQNAFuw","wiHrZ45cIH",
-"0PktIEdBKc","3weIF7Ow5C","qaofNQssNC","ZJTXHTCgPp","iKqhr5Mg9r","O3iyQdpe1v","YjB9tGXdoH","9rlg9KsjRK","pAhR1lpF6W","ECMvUyToGW",
-"BbwgARkQke","NhXduX6Pin","FLsphfcwDa","CxVEfjfREu","UlU3Mmz8gx","yEfy9uQIcz","ZzJHWECMvU","VNCPdRkQke","Q6hMCaL6AJ","t98iWReKEW",
-"iwzGk7hyVv","XflUqL7cGc","WDVWJJIqXi","jiVBPIBe8k","y94nwOxWIH","m4bxUKZamH","fqypywiHrZ","prNT65Drn0","b29RJP6bcg","1j5L8Chuy3",
-"AXpwEFjHXR","Gv3FqQWxoT","S2DfuK4GS8","pmeCdB3qem","BFkb8pmeCd","ZzJHWL7cGc","0ao3lk85Ae","64s8NDLhzM","tl72WFwEJz","ksJbycL0aE",
-"16lHcQChxs","pmeCdbgJAz","uZPqgPYBf4","Mkgy8QnJ1S","29QAztlILt","JkzUnJIqXi","WaWsv8FmFH","VIlwPaDGtS","HlUbF4W0Tl","VjCZqoGu6x",
-"tl72Wd85a9","QChxsnnP8o","oVQp6Dz1R3","Nxx9VqQxHP","7hyVvmz8gx","16lHc8TxD7","AIYUuuPX7G","lkMUAWmadA","HRxd8KsjRK","8RCUAix74r",
-"nFqikv2eC3","yEfy9B3qem","yvOMIhi5X7","v1HlnsqVrf","0Wr5yix74r","MaJQsAIYUu","fmIK10ao3l","ZzJHWgdQsS","9rlg9QClRL","0PktI4QMc9",
-"HfyNQd7vjM","lXFOBh1zcH","djsrvdjsrv","29QAzEdBKc","lkMUARBhp0","VNCPdPOUYS","zQt6QCdyBV","7fsYMvLsmS","Cfgr3CIShG","Ta8f6GSQwj",
-"W7cTsdhSuH","uvf7A0PktI","JIqXiyToGW","gdQsStAOsr","ru4UG0Wr5y","KsjRKHlUbF","pv0i77hyVv","iqv4kiqv4k","OHaBzaDGtS","WMiS3mX2GE",
-"M6qcGfmIK1","nnP8oi7WMQ","8RCUArz7Ut","t98iWlkMUA","pFrrlyEfy9","i7WMQMm8si","hE1QlpFrrl","6AFT0aez9y","suY4x1v5hH","DG4sTAkKTk",
-"xciqp5Drn0","7lUXZ8FmFH","MojnPjfREu","BbwgApAhR1","FnPFBGSQwj","djsrv3weIF","zFgtBWmadA","bgJAz7fKYU","d7vjM0YAGH","MojnPKZamH",
-"BGaQY1j5L8","JJs5mcShY2","Z4I1vDG4sT","Vprf2CdyBV","0BmCyU3yw5","HlUbFFVMxo","IKxdLbgJAz","lXFOBrhl0J","i7WMQjzUqR","MK07YGSQwj",
-"5Nammsx5Gl","7lUXZThjNn","HfyNQFGzgp","mz8gxKr8ys","BpYhVjzUqR","tl72WMezSW","GWqqXzz4ZU","YjB9tpFrrl","dQ586MmsIo","aFFssfmIK1",
-"zmLYD7X3uy","D6rByD6rBy","6AFT0hi5X7","Q6hMCU3yw5","uZPqg5Drn0","cQOnvMaJQs","uN6r3IjTwP","POUYSAgJHQ","dhSuHpWiOs","MezSW24ARF",
-"PYBf4VjCZq","RxrsmPYBf4","8U2nUFnPFB","4dEz6OxWIH","uZPqgQChxs","0PktICqqaD","3otm614FLR","gjUTuvkCHH","uLtKs4QMc9","cL0aEjtn0X",
-"8FmFHs93Ml","S2DfuSs0Zu","bZLvS8TxD7","iB08l29QAz","jiVBPAXpwE","ydG8U9GXkX","e6e4zblLA9","NhXduh1zcH","G1RhS6AFT0","yvOMIpT8wu",
-"5nmWv1j5L8","Ta8f6lkMUA","taOXKKsjRK","atef2uQIcz","VBjhzd85a9","n8pJ9FNYIM","VBjhzNo0Qb","MojnPtlILt","RmDcrRBhp0","xXTI4e6e4z",
-"GSQwjVLTy6","ReKEWxXTI4","zbIYYSs0Zu","Gv3FqFNYIM","oGu6xK4GS8","cShY2JIqXi","mz8gxhE1Ql","aDGtSSjskQ","POUYS7fsYM","CK5W7S77LH",
-"dQ586NhXdu","oGu6xB3qem","D6rByVprf2","Vprf2nFqik","gf8rIdQ586","uvf7A580YD","taOXKOHaBz","bgJAzMm8si","CNHmvtlILt","8U2nU0YAGH",
-"djsrvOHaBz","Zv7z0Waim6","0PktItl72W","BFkb8bgJAz","OUYuFQ6hMC","gIYvEYh1hF","dQ586lViBv","7X3uy7Ow5C","t98iW5VZjS","azIWpgf8rI",
-"618DiBCxeC","iB08lY1mC0","QChxsMm8si","GWqqXnnP8o","uoStwOz8yZ","EdBKcVerEA","y94nwMezSW","mX2GEpWiOs","ReKEWRkQke","ix74rn1pmO",
-"MGlTFQ6hMC","CK5W7Yh1hF","euZA5s4786","K4GS8b29RJ","TCgPpYjB9t","bgJAzVLTy6","QClRL8cVD3","gdQsSsqVrf","dpe1vjSjS3","vOqCEL7cGc",
-"6AFT0i7WMQ","yluBxQ6hMC","StlDJuN6r3","6AFT08FmFH","24ARFuAWyp","HzZT8KASQ8","Ss0ZuFPfSE","9y4lw1j5L8","ksJbyYf2Ec","M6qcGTXQ0Z",
-"faHirKZamH","X6PinzqH0W","KsjRKQ6Lix","FGzgp7Ow5C","oGu6xkB5nP","0YAGHd85a9","VNCPdhE1Ql","b29RJOUqFM","okgRii7WMQ","ThjNnYjB9t",
-"lweGyBCxeC","o8Uyd07n1c","29QAzWreyP","Y1mC0VBjhz","RmDcrQWxoT","HfyNQksJby","QbxXcQworu","VNCPdO3iyQ","faHirJ2mQi","XyPZNuvf7A",
-"RpBQmFnPFB","Y1mC0v1Hln","AgJHQdpe1v","DcpWBQnJ1S","2NslmfcJOy","k85AehSSvQ","jiVBPFPfSE","yvOMIbZLvS","QYxC0Vprf2","d7vjM2Nslm",
-"14FLRh1zcH","No0QbzbIYY","SbRYyhYBCK","WMiS3RzaZA","PYBf40MR5X","BFkb8pT8wu","dhSuHyvOMI","jS1ajJRJQB","8hJdtOUqFM","MmsIoiKqhr",
-"jzUqRPYBf4","VerEAfLNg8","EoToPYjB9t","DcpWBEdBKc","zHF1qjzUqR","cQOnvFFDui","Y1mC0tlILt","LewvMzQt6Q","8TxD70h1b1","4W0TlzY1GY",
-"d85a9pT8wu","XyPZNHzZT8","ThjNnJXljW","FxX9qsx5Gl","guMb8KZamH","uupzkPOUYS","0KyfsZ4I1v","nFqiktuDyS","AOgEe1v5hH","ydG8U8FmFH",
-"ZuDtDJ2mQi","HzZT89iGoT","ZzJHWVIlwP","piJSkUl4a1","CqqaDGWqqX","ulk41qUJMd","tuDySAmdQd","AmdQdksJby","JkzUnWmadA","guMb8CdyBV",
-"e6e4z2TRI7","dmoS7Ul4a1","14FLRQClRL","RxrsmZ4I1v","CxVEfS77LH","VerEA7X3uy","mz8gxPYBf4","ulk41Ta8f6","8hJdtdQ586","KsjRKFjHXR",
-"lsQGoUl4a1","2Yz7EDQimp","DLhzMblLA9","NOHszOxWIH","h1zcHprNT6","fLNg8cShY2","hUTw75nmWv","VerEAuTacx","VLTy6IjTwP","pFrrluLtKs",
-"5nmWvUl4a1","MGlTFhE1Ql","Zv7z0pvgjS","xciqpzFgtB","he9IAQWxoT","W3VFHoVQp6","uJScXReKEW","Oz8yZ2DREs","Q6LixCdyBV","8hJdtZv7z0",
-"Zv7z0OHaBz","NAFuwMmKGJ","pvgjSAXpwE","faHirAgJHQ","Waim6iKqhr","jS1ajnnP8o","0MR5Xatef2","dpe1vnFqik","MmsIoFNYIM","NhXduNAFuw",
-"qUJMdRxrsm","v2eC32hEEU","taOXKbZLvS","vLsmSMaJQs","Uvlv4WreyP","XyPZNjSjS3","JRJQBW3VFH","x3LDeaL6AJ","yvOMIksJby","2DREsReKEW",
-"B3qemrhl0J","KZamH0ao3l","1v5hHYOfrY","piJSkzz4ZU","0h1b1P6bcg","Pb1paPOUYS","FjHXRNxx9V","oVQp6BFkb8","jfREu580YD","StlDJOHaBz",
-"3otm6FFDui","IjTwPi7WMQ","d85a9JJs5m","8RCUAlj07Q","VBjhzFFDui","0PktI8cVD3","o8UydnnP8o","SjskQtuDyS","zz4ZURkQke","K4GS8MK07Y",
-"G1RhSlH1kt","O3iyQtAOsr","16lHcS77LH","BFkb80BmCy","tvdkDhYBCK","CdyBVMmKGJ","ru4UG7lUXZ","wDajXCqqaD","tlILtiwzGk","lH1ktoQ87r",
-"IjTwPbgJAz","2TRI7XflUq","Waim6lH1kt","RACuj9GXkX","jiVBPHP433","suY4xm4bxU","24ARF0Kyfs","Pb1palXFOB","5nmWvJkzUn","rKDLJpv0i7",
-"2NslmSmGzv","B3qempAhR1","mX2GEsuY4x","Z4I1vwDajX","v1Hln1v5hH","mz8gxUlU3M","zqH0Wuupzk","RzaZARzaZA","Dz1R3rz7Ut","JXljWuoStw",
-"qUJMdDz1R3","HfyNQVLTy6","Zv7z0RBhp0","B3qem24ARF","DLhzM1j5L8","QClRLU3yw5","Ul4a1jiVBP","tjQxsHlUbF","FhtglOxWIH","Mm8si7X3uy",
-"IKxdLB3qem","StlDJpFrrl","jeskSWMiS3","JKWYRGSQwj","RpBQm5Drn0","gIYvE9iGoT","n1pmOGrDg7","P6bcg580YD","VjCZqVNCPd","IjTwPUl4a1",
-"jS1ajFGzgp","uN6r3KASQ8","CK5W7uvf7A","FjHXRMm8si","1j5L82DREs","cmXIXKASQ8","6AFT0xReec","NOHsziKqhr","bgJAzMkgy8","CdyBVRACuj",
-"Nxx9VlH1kt","qaofNJKWYR","CdyBV2ZHdk","NcICAKsjRK","QnJ1S7X3uy","Ss0ZuuQIcz","14FLRgIYvE","uQIczNOHsz","Ta8f6v2eC3","8hJdtlm0pD",
-"3otm6ydG8U","euZA5ZJTXH","24ARFuvf7A","oVQp6Y1mC0","Gv3FqRACuj","Yf2EcpmeCd","P6bcgiqv4k","M3zXLJKWYR","NcICAMK07Y","B3qemWaWsv",
-"Kr8ysOHaBz","24ARFNOHsz","GWqqXbgJAz","JIqXiGXdoH","e6e4zK4GS8","1j5L88hJdt","VjCZqn8pJ9","k85AeeuZA5","5nmWvcL0aE","JkzUnaDGtS",
-"JRJQBtjQxs","4dEz6OUYuF","yvOMIVjCZq","0PktIK20wK","kB5nPfLNg8","s93Ml4dEz6","J2mQiydG8U","fcJOynFqik","4dEz6RmDcr","e6e4zCxVEf",
-"EOE1oUlU3M","y94nwi3pyd","5IhmGEoToP","Dz1R37lUXZ","7X3uykB5nP","OxWIHIKxdL","suY4xDQimp","K4GS8hSSvQ","8cVD3lXFOB","zmLYDB3qem",
-"yluBxGSQwj","jtn0XI7p2a","yluBxsx5Gl","K20wKnnP8o","xXTI4oQ87r","RzaZAVprf2","QWxoTlCMxy","YOfrYBpYhV","5IhmGoQ87r","pmeCdO3iyQ",
-"VNCPdZzJHW","n1pmOtlILt","Qworu9eoRc","faHirIKxdL","FVMxoHP433","16lHcFLsph","d85a9cQOnv","zmLYDhSSvQ","jfREuK4GS8","gIYvE45cIH",
-"POUYShe9IA","s7MxklXFOB","Cfgr3zQt6Q","QbxXcrKDLJ","Waim6XyPZN","7fsYM2hEEU","Vprf29eoRc","7lUXZJJs5m","fqypylH1kt","QbxXcn8pJ9",
-"5Drn0K20wK","sqVrfv2eC3","atef2cShY2","AIYUuAgJHQ","48cHL2TRI7","jzUqRzmLYD","QssNCzqH0W","Cfgr3RkQke","MaJQsRsQUq","K4GS8vLsmS",
-"cShY2618Di","FhtglThjNn","I7p2ayToGW","RzaZASs0Zu","CxVEf0h1b1","HfyNQC2Irc","uLtKsyluBx","iwzGkNOHsz","rz7UtxXTI4","4dEz6Ta8f6",
-"NcICAUl4a1","lXFOB7Ow5C","euZA5jiVBP","kZANmwDajX","ZhwG1vkCHH","GrDg7DcpWB","45cIHHlUbF","NAFuw9eoRc","VjCZqx3LDe","dhSuHFGzgp",
-"1LB1LwDajX","PYBf4MK07Y","Yh1hFK20wK","ZzJHWs93Ml","KZamH3otm6","cmXIX0MR5X","S2DfuS77LH","jtn0XgdQsS","atef2K4GS8","HRxd8i3pyd",
-"4dEz6ZzJHW","RzaZApT8wu","9XyT95iGN5","8TxD7zQt6Q","2hEEUEOE1o","9XyT9jeskS","zFgtB618Di","GWqqX9rlg9","ZzJHWlpF6W","Zv7z0SmGzv",
-"MmKGJCfgr3","MmsIoStlDJ","QChxsuupzk","fcJOydpe1v","guMb8Zv7z0","hi5X7lkMUA","0h1b1dmoS7","dpe1vi7WMQ","oQ87rDz1R3","ogLgcFjHXR",
-"0BmCyNo0Qb","yluBxGv3Fq","cmXIXYh1hF","CdyBVWDVWJ","AIYUuk85Ae","VjCZqM6qcG","uAWyp07n1c","XyPZNyToGW","In3NSJIqXi","yvOMInnP8o",
-"ZuDtDlH1kt","OxWIHUmaEv","5IhmG2hEEU","WaWsv5drc6","uTacxIjTwP","YOfrYQworu","prNT66q6L9","FcWrWnnP8o","G1RhSZuDtD","t59lRn1pmO",
-"v8yFNDQimp","Fhtglsoy9t","DG4sTyvOMI","6AFT0UlU3M","48cHLThjNn","J2mQiOz8yZ","QClRL7hyVv","8TxD7ThjNn","VjCZq64s8N","vLsmS29QAz",
-"tlILtWaWsv","580YDAXpwE","hUTw7PYBf4","K4GS8VBjhz","jzUqRfFDrJ","mz8gxulk41","4dEz65Namm","lsQGon1pmO","yluBx2Yz7E","GXdoHv8yFN",
-"he9IA7lUXZ","lj07Q2TRI7","gIYvEcL0aE","Z4I1vKr8ys","fFDrJk85Ae","MGlTFGWqqX","LDk6fTXQ0Z","9rlg93otm6","qQxHPgtCA5","B3qemtlILt",
-"NcICAVprf2","vkCHHC2Irc","yofH3he9IA","FxX9qxXTI4","8U2nUhUTw7","9rlg9RkQke","soy9th1zcH","FxX9qYw2oU","FNYIM5iGN5","QbxXckB5nP",
-"CdyBVnlaBy","IBe8kAmdQd","brhlQ1j5L8","prNT6NAFuw","8RCUAwiHrZ","aez9yYh1hF","8TxD7xXTI4","X6PinFNYIM","iwzGkfcwDa","C2IrcXflUq",
-"uTacxzz4ZU","FjHXRCdyBV","BbwgAs93Ml","9y4lwuN6r3","9y4lwzz4ZU","CIShG1LB1L","AkKTkFGzgp","Yw2oU7fKYU","kZANmQ6Lix","v8yFN8FmFH",
-"MmsIoUl4a1","uQIczReKEW","4QMc9kB5nP","JIqXiX6Pin","ni2v1fcJOy","yvOMIGrDg7","EdBKcNxx9V","lj07QjiVBP","HzZT8qaofN","FcWrWI7p2a",
-"K20wKprNT6","lj07Q2hEEU","dpe1vYw2oU","ZzJHWSs0Zu","UlU3MLewvM","AOgEeprNT6","MmsIoTXQ0Z","v2eC3he9IA","s47862hEEU","fmIK1MmsIo",
-"JIqXiydG8U","e6e4zVprf2","5Mg9rzbIYY","618DiUmaEv","gdQsSzHF1q","9iGoTzbIYY","atef2yToGW","ydG8U8xEKz","KASQ8FnPFB","618DiYf2Ec",
-"djsrvDz1R3","yluBxpFrrl","mz8gx5iGN5","NhXdun8pJ9","uZPqg9GXkX","AOgEeIKxdL","Nxx9VhE1Ql","0BmCyrKDLJ","Waim6Nxx9V","VNCPdQbxXc",
-"tuDySTCgPp","5ZaEzKASQ8","n1pmOFVMxo","TCgPpNcICA","24ARFJJs5m","tAOsrFNYIM","uLtKsRkQke","Ss0ZufcJOy","QWxoThE1Ql","gf8rIKr8ys",
-"cShY2iB08l","Yh1hFt98iW","v2eC3W3VFH","Yf2EcBGaQY","MK07YHzZT8","Waim6fcJOy","uJScXWPmlx","iqv4kzbIYY","uPX7Gn1pmO","Chuy3Zv7z0",
-"jfREuKZamH","m4bxUTCgPp","lj07QQssNC","gdQsSQ6hMC","7Ow5CvOqCE","RxrsmFGzgp","SbRYyjfREu","vkCHHQworu","jSjS3IKxdL","FjHXR0MR5X",
-"AXpwEeuZA5","atef2zqH0W","RpBQm8TxD7","BCxeCnFqik","oVQp6cmXIX","KASQ8lkMUA","UlU3MlsQGo","2Yz7ExReec","jeskSiKqhr","FjHXRtl72W",
-"Vprf2vLsmS","vOqCExReec","UmaEvHlUbF","618DiMGlTF","v8yFNsoy9t","bZLvSgdQsS","Ss0ZuIjTwP","FjHXRqaofN","Mm8sini2v1","uLtKs7fsYM",
-"29QAzWmadA","RACujd85a9","WaWsv4dEz6","uPX7GUmaEv","OHaBztAOsr","FcWrWjeskS","lViBvRACuj","WreyPZUnqt","Twanoulk41","tuDyShe9IA",
-"5iGN5M6qcG","3weIFvOqCE","t59lRY1mC0","v1Hlnt59lR","618Did7vjM","lm0pDBFkb8","s47860Wr5y","s93MlMojnP","9iGoTDcpWB","zHF1qDLhzM",
-"No0Qbdpe1v","8FmFHOUYuF","J2mQidQ586","ix74r7Ow5C","prNT6rKDLJ","jSjS3uLtKs","s4786GWqqX","aFFsspWiOs","GWqqXNxx9V","D6rByFVMxo",
-"Ss0ZuoGu6x","uPX7Gtl72W","HlUbFyofH3","y94nwuPX7G","ksJby1j5L8","HP433UlU3M","t59lRrhl0J","580YDqaofN","ogLgcnlaBy","CdyBV2TRI7",
-"ydG8Ulj07Q","ZJTXHAIYUu","v1HlnKASQ8","SbRYypFrrl","OHaBzNo0Qb","djsrvlpF6W","lm0pDogLgc","lsQGoCxVEf","he9IAlH1kt","RxrsmMm8si",
-"TCgPpMm8si","AOgEedpe1v","i3pyd8xEKz","TXQ0Zv2eC3","MmsIodmoS7","wDajXuJScX","Zv7z0No0Qb","NOHsz9XyT9","AkKTklpF6W","iB08lhYBCK",
-"7hyVvlj07Q","gIYvEhE1Ql","K4GS8pFrrl","zQt6QQWxoT","soy9tgdQsS","CqqaDmX2GE","0Wr5ypFrrl","zmLYD07n1c","s4786ydG8U","jSjS3jSjS3",
-"Z4I1vLewvM","8TxD7TXQ0Z","0ao3lFGzgp","AXpwEdjsrv","WMiS3O3iyQ","B3qemh1zcH","tvdkDsuY4x","qUJMdTa8f6","1j5L8QWxoT","taOXKv1Hln",
-"uupzk6q6L9","0BmCyuQIcz","ksJby5IhmG","gtCA5GSQwj","8cVD3oQ87r","a00b5Oz8yZ","9XyT9FwEJz","DG4sT618Di","hE1Qlxciqp","m4bxUJKWYR",
-"LbRTHlXFOB","K4GS8HRxd8","azIWpJRJQB","fmIK1djsrv","brhlQgtCA5","Z4I1vDz1R3","OxWIHAkKTk","0h1b1B3qem","KZamHJRJQB","FcWrWjtn0X",
-"Ss0ZuzmLYD","jS1ajO3iyQ","jfREuaL6AJ","Zv7z0pv0i7","9XyT9K20wK","YOfrYksJby","zz4ZUuLtKs","M3zXL48cHL","k85AeLDk6f","C2IrcWaim6",
-"WDVWJHfyNQ","ECMvUuLtKs","x3LDeyEfy9","Q6hMCKsjRK","zFgtBK4GS8","Vprf2uJScX","2ZHdkGSQwj","OUqFMgf8rI","Oz8yZdpe1v","WmadA5Mg9r",
-"yEfy9oGu6x","FwEJzBbwgA","s4786pT8wu","e6e4zMkgy8","s7MxkJJs5m","OUYuF5IhmG","SjskQlj07Q","In3NSx3LDe","ciuWzWaWsv","tjQxsMaJQs",
-"XflUqxReec","ThjNn2Nslm","guMb845cIH","ZUnqtMK07Y","UmaEvnnP8o","hSSvQciuWz","LbRTHfcwDa","hUTw7hE1Ql","9eoRcQClRL","7lUXZ7X3uy",
-"t59lRGv3Fq","5NammjzUqR","qQxHP0BmCy","pAhR1oVQp6","JXljWh1zcH","DcpWBbgJAz","Q6hMCpmeCd","16lHc8U2nU","8FmFH5ZaEz","CK5W7aL6AJ",
-"0ao3lSjskQ","Cp3mZBGaQY","0MR5X4W0Tl","M3zXLQ6hMC","atef2gdQsS","fFDrJdpe1v","jfREugIYvE","n8pJ9pT8wu","4W0TlogLgc","0MR5XuAWyp",
-"fcJOypmeCd","ix74rzY1GY","tuDySJkzUn","Chuy3gf8rI","lm0pDJJs5m","pmeCdIn3NS","5iGN5kZANm","e6e4zgIYvE","VIlwP55rfB","EoToPatef2",
-"qUJMd3otm6","aez9yt59lR","9XyT9GXdoH","iwzGkNAFuw","d7vjMWaim6","e6e4z8FmFH","ru4UG48cHL","ReKEW5VZjS","I7p2auvf7A","FjHXRVLTy6",
-"uAWyp0Wr5y","mz8gxDG4sT","AOgEetAOsr","KsjRKgIYvE","PYBf4LDk6f","o8UydRpBQm","pmeCdDcpWB","2Yz7E7Ow5C","zY1GYTCgPp","RkQke7ku1p",
-"zY1GYkB5nP","iKqhrUvlv4","RmDcr29QAz","BGaQYRzaZA","64s8NlkMUA","QnJ1ScQOnv","zqH0W8cVD3","9y4lwm4bxU","pFrrlQClRL","xciqpdmoS7",
-"W7cTsSjskQ","5IhmG0YAGH","0h1b1jSjS3","JXljWHzZT8","nlaByn8pJ9","ru4UG4W0Tl","L7cGcpFrrl","K4GS80BmCy","jS1ajBbwgA","QssNC7lUXZ",
-"ksJbyjeskS","qaofNVBjhz","XflUqFLsph","Gv3FqoVQp6","NAFuwpWiOs","UmaEvQworu","lpF6WpmeCd","AIYUuDQimp","C2Ircni2v1","CIShGF6PT2",
-"RBhp0Gv3Fq","RBhp0QnJ1S","5ZaEz5iGN5","QChxsoVQp6","x3LDeNo0Qb","ru4UGblLA9","D6rByHP433","FPfSEk85Ae","dhSuHKASQ8","n1pmO2Nslm",
-"4QMc9Cp3mZ","kZANmi7WMQ","e6e4zKr8ys","i3pyduupzk","FLsphmX2GE","CK5W7WreyP","FLsphy94nw","5iGN5dmoS7","Yf2EcuJScX","IRh48gIYvE",
-"ZuDtD0ao3l","Oz8yZFhtgl","FGzgplkMUA","0Wr5yhi5X7","7ku1p618Di","rz7Utsx5Gl","lCMxy7lUXZ","MmKGJFLsph","UmaEvnFqik","RxrsmJkzUn",
-"rz7UtQChxs","ulk41M3zXL","tlILtpv0i7","tvdkDv1Hln","3weIFciuWz","ix74rlCMxy","uoStwhYBCK","RkQke7Ow5C","4QMc9GrDg7","WreyP5Drn0",
-"P6bcggdQsS","EdBKcUvlv4","Q6hMC5drc6","1j5L8WaWsv","iKqhruPX7G","Zv7z0lCMxy","rKDLJM6qcG","ZUnqtuQIcz","iB08llCMxy","U3yw58RCUA",
-"JJs5mlsQGo","iKqhrMm8si","jS1ajMaJQs","x3LDeyvOMI","5Namm618Di","5VZjS4QMc9","XyPZNU3yw5","uN6r3y94nw","ZhwG1MaJQs","NAFuwZv7z0",
-"BpYhVcmXIX","ogLgcOxWIH","RxrsmyEfy9","IjTwPFxX9q","qQxHPCqqaD","vLsmSFjHXR","CNHmvrhl0J","7fsYMS77LH","h1zcHv1Hln","iwzGkFFDui",
-"Nxx9V9eoRc","yEfy9jSjS3","dQ586Q6Lix","yEfy98xEKz","Waim6kB5nP","Kr8yszmLYD","hE1QlThjNn","9iGoTDQimp","5Drn0iB08l","Ul4a1yToGW",
-"UmaEvNOHsz","fmIK1cShY2","Cfgr3fFDrJ","cmXIXyvOMI","U3yw5lH1kt","Mm8siWaim6","48cHLcmXIX","QssNCCfgr3","jS1ajyvOMI","qQxHPDG4sT",
-"azIWp9eoRc","ni2v1lCMxy","CNHmv2TRI7","x3LDe7lUXZ","0h1b1KsjRK","4W0TlWaWsv","StlDJ2ZHdk","prNT6BGaQY","dpe1vzz4ZU","U3yw5ulk41",
-"ECMvU8hJdt","8hJdt0PktI","KsjRK2DREs","aDGtSzmLYD","SjskQ4W0Tl","VjCZqRsQUq","4dEz6lViBv","Qworu14FLR","618DigdQsS","RBhp0M6qcG",
-"cL0aECp3mZ","Yf2EcgIYvE","pT8wuPb1pa","Z4I1vC2Irc","U3yw5fcJOy","blLA9tvdkD","oVQp6MK07Y","dQ586d85a9","yEfy90MR5X","BGaQYpv0i7",
-"aFFssVerEA","YjB9ttjQxs","7lUXZgf8rI","fLNg8SbRYy","tlILtvkCHH","nFqikFFDui","JXljWTwano","9XyT9v8yFN","QClRLuN6r3","MK07YBGaQY",
-"RxrsmpAhR1","QWxoTzY1GY","pFrrlxReec","NhXdu1LB1L","9rlg9CIShG","2ZHdkVNCPd","Uvlv4IKxdL","v2eC3Gv3Fq","v8yFNfcwDa","jfREu48cHL",
-"pvgjSjSjS3","pWiOslsQGo","i7WMQkB5nP","uupzkYOfrY","fcJOydjsrv","Cp3mZ4dEz6","U3yw55IhmG","FnPFBLewvM","5nmWvhe9IA","yluBxlsQGo",
-"h1zcH8FmFH","RmDcrtl72W","kB5nPlkMUA","RkQked85a9","RkQkeZhwG1","MGlTF29QAz","uAWypTa8f6","XyPZN8cVD3","XyPZNRACuj","FFDuiDQimp",
-"DG4sTVerEA","QworuYf2Ec","HzZT8kZANm","9GXkXuTacx","xXTI4J2mQi","DG4sTtaOXK","gIYvES77LH","lH1ktKr8ys","SjskQ2hEEU","16lHc5IhmG",
-"Gv3FqEoToP","oVQp65Mg9r","5VZjSjfREu","9XyT9QChxs","XyPZNkZANm","aFFsssqVrf","618DirKDLJ","hUTw7WmadA","ThjNnO3iyQ","wDajX0MR5X",
-"MmsIoJKWYR","ECMvUaL6AJ","SjskQ9y4lw","3otm6t59lR","VNCPdUmaEv","SjskQM6qcG","DQimpD6rBy","vLsmSEdBKc","5VZjSd85a9","lkMUA9XyT9",
-"yEfy9LewvM","9rlg97fKYU","Vprf2brhlQ","n1pmOWPmlx","Yw2oUMmKGJ","2hEEURmDcr","AkKTkW7cTs","hE1QlNOHsz","0h1b1fcJOy","aL6AJDG4sT",
-"nFqiktaOXK","WDVWJlweGy","FFDuiRBhp0","iB08lQYxC0","v8yFN7fKYU","x3LDeOUqFM","l83UdDG4sT","DcpWBb29RJ","2Yz7EgtCA5","suY4xdQ586",
-"7hyVvFFDui","iKqhrksJby","Waim6ZJTXH","5ZaEz1LB1L","Zv7z0fLNg8","D6rByhUTw7","FLsph5drc6","GrDg7S77LH","8hJdtv8yFN","M3zXLNo0Qb",
-"dQ586StlDJ","pmeCdNo0Qb","0h1b1ru4UG","k85AelweGy","zqH0WQClRL","zqH0WRkQke","K20wKFVMxo","uvf7AlweGy","oGu6xUvlv4","6AFT0lpF6W",
-"aL6AJ0BmCy","uJScXlpF6W","0Wr5ylkMUA","uJScXtAOsr","WMiS3Rxrsm","Mm8siCxVEf","M6qcGzFgtB","s93MlFnPFB","nnP8oRBhp0","ZhwG1J2mQi",
-"fmIK1AkKTk","0h1b1VBjhz","fqypy2Nslm","24ARFdQ586","RpBQmMmsIo","lsQGovkCHH","OUYuFJKWYR","uAWypUl4a1","9XyT9I7p2a","xReec8RCUA",
-"1LB1LUvlv4","e6e4zMmsIo","kB5nP2hEEU","fcwDaVjCZq","VerEAHfyNQ","piJSkbrhlQ","VNCPdY1mC0","sqVrfKr8ys","cQOnv5Namm","CdyBVWaWsv",
-"W7cTsxciqp","2ZHdkGWqqX","VerEAGrDg7","oGu6xW7cTs","64s8NuJScX","iwzGkYw2oU","O3iyQaL6AJ","1LB1LBpYhV","4dEz6UmaEv","Q6LixO3iyQ",
-"SWfoumz8gx","piJSkru4UG","StlDJbrhlQ","pv0i7zQt6Q","GXdoHtvdkD","M3zXLbZLvS","djsrvQChxs","GWqqXpiJSk","RxrsmHP433","TXQ0ZJ2mQi",
-"Ss0ZuSWfou","9iGoT9eoRc","POUYSAXpwE","618DiZUnqt","xReec0Wr5y","yEfy92ZHdk","suY4xQnJ1S","xReecUmaEv","tl72Wdpe1v","LbRTH0ao3l",
-"SWfoufcJOy","Y1mC05drc6","ciuWzqQxHP","1j5L8gIYvE","IBe8kPYBf4","VjCZqQbxXc","FjHXR64s8N","IRh48mz8gx","vkCHHaDGtS","n1pmOFxX9q",
-"uN6r3hi5X7","jS1aj580YD","oGu6xm4bxU","jeskSX6Pin","kZANmhUTw7","gf8rIfqypy","mX2GEJXljW","29QAzTwano","djsrvLDk6f","jSjS3IBe8k",
-"uQIczSs0Zu","lCMxy9eoRc","8xEKzd7vjM","djsrvSbRYy","tjQxsI7p2a","gdQsS0YAGH","uoStwEdBKc","BGaQY0PktI","Z4I1vlkMUA","MojnPNAFuw",
-"5iGN59iGoT","fFDrJtlILt","0h1b1lViBv","IKxdLVBjhz","yofH3SbRYy","TXQ0ZECMvU","Ss0Zua00b5","lm0pDguMb8","Y1mC0lj07Q","Uvlv4azIWp",
-"NOHsz9eoRc","gdQsS2Yz7E","zY1GY64s8N","uvf7AyToGW","M3zXLuTacx","ni2v17ku1p","kB5nPcL0aE","Nxx9VuN6r3","zY1GYjtn0X","vkCHHsqVrf",
-"ulk41RzaZA","Ta8f65Namm","Yf2Ecni2v1","8TxD7iqv4k","0YAGH2DREs","n1pmOStlDJ","nnP8oprNT6","v2eC3Zv7z0","gf8rIokgRi","8U2nUOUqFM",
-"FVMxo8cVD3","ulk41tjQxs","lH1kt7lUXZ","D6rByC2Irc","CdyBVHlUbF","tuDySpmeCd","O3iyQcShY2","KASQ8Yw2oU","k85Ae5Namm","sqVrfGrDg7",
-"F6PT2jiVBP","wDajXo8Uyd","4QMc9ix74r","8hJdtSjskQ","OxWIHpWiOs","9eoRcCdyBV","v8yFNhUTw7","SWfouRACuj","tlILtFNYIM","OxWIH2Yz7E",
-"7ku1plweGy","0PktIoGu6x","LDk6fFFDui","xXTI4n1pmO","b29RJ4dEz6","d85a9QnJ1S","XflUqNo0Qb","0Wr5y5ZaEz","y94nwa00b5","9iGoT8U2nU",
-"16lHcHP433","5NammtaOXK","GSQwje6e4z","ZJTXHQ6Lix","t98iWprNT6","nFqikQssNC","7fKYUYw2oU","MezSWFFDui","KsjRKFNYIM","wiHrZoQ87r",
-"ogLgcLewvM","zHF1qni2v1","rz7Ut8FmFH","uPX7Gm4bxU","QWxoTQbxXc","BbwgApmeCd","QClRLVprf2","FwEJzMkgy8","Ss0ZugtCA5","LbRTH0Wr5y",
-"O3iyQEOE1o","Yf2EcSmGzv","4QMc9lH1kt","VjCZqk85Ae","1j5L8sqVrf","MK07YCNHmv","tuDySSs0Zu","iKqhrIjTwP","NcICAiwzGk","X6Pind85a9",
-"v8yFNpv0i7","QnJ1SSs0Zu","FjHXRuoStw","nlaByQ6Lix","uN6r3gdQsS","ksJbyyluBx","7ku1pFLsph","L7cGcoQ87r","fqypydQ586","Dz1R3EdBKc",
-"5ZaEz4W0Tl","lViBv0ao3l","ZhwG1ReKEW","lpF6WbgJAz","hi5X7dpe1v","lj07QnFqik","lj07Q9rlg9","uvf7AYw2oU","BCxeCv8yFN","xReecy94nw",
-"uLtKsdpe1v","WPmlxCqqaD","RzaZA4W0Tl","CxVEfdhSuH","48cHLKASQ8","KsjRK8FmFH","X6PinhUTw7","azIWpAIYUu","pFrrlXyPZN","e6e4z3otm6",
-"DG4sTa00b5","QssNCfLNg8","F6PT22TRI7","Oz8yZVIlwP","IBe8kHfyNQ","hE1QlFNYIM","MK07YMm8si","8TxD7Rxrsm","brhlQ7lUXZ","KsjRKQClRL",
-"tvdkDn1pmO","OUYuFuPX7G","9GXkXIjTwP","KsjRKiB08l","l83UdBpYhV","zHF1q0BmCy","FjHXRnlaBy","KZamHe6e4z","EdBKcMK07Y","MojnPFjHXR",
-"HP433RACuj","8FmFHgtCA5","lH1ktQ6Lix","DcpWBU3yw5","v1HlnzY1GY","M6qcGFVMxo","cmXIXprNT6","aez9yDLhzM","sqVrflweGy","29QAzJ2mQi",
-"nlaByAOgEe","taOXKWDVWJ","XflUqciuWz","TwanocQOnv","fcwDahi5X7","QClRLVerEA","CNHmv55rfB","XflUqogLgc","0Wr5y0Wr5y","uPX7GOz8yZ",
-"v2eC3RpBQm","CIShGb29RJ","jS1aj5Mg9r","hi5X70YAGH","tjQxsIRh48","uN6r3W3VFH","618DifmIK1","NcICAFFDui","4dEz6Yw2oU","FxX9q5VZjS",
-"fqypy8TxD7","48cHLCNHmv","POUYSogLgc","Yf2EczbIYY","hSSvQpv0i7","MojnPWMiS3","he9IARzaZA","LDk6fuoStw","uvf7AogLgc","qaofN580YD",
-"9GXkXnFqik","jtn0XfcwDa","m4bxUl83Ud","HfyNQW3VFH","okgRi0h1b1","AgJHQJ2mQi","jiVBPVNCPd","iwzGklH1kt","B3qemwiHrZ","QnJ1Sy94nw",
-"s4786Rxrsm","MojnPe6e4z","lsQGoDQimp","hi5X7Uvlv4","piJSkS77LH","8U2nUDG4sT","RACujSWfou","mz8gxYOfrY","wDajX2TRI7","5ZaEzatef2",
-"CxVEf8U2nU","pvgjSRsQUq","fcwDabgJAz","uPX7G8xEKz","DQimpRsQUq","JJs5mmz8gx","s93Mle6e4z","JJs5mo8Uyd","Oz8yZJXljW","M6qcGv8yFN",
-"RsQUquJScX","uTacxMm8si","SWfoulkMUA","FGzgp8xEKz","dpe1v24ARF","n1pmOW3VFH","dpe1vCfgr3","i3pyduPX7G","G1RhSDLhzM","DcpWBGrDg7",
-"oVQp616lHc","iKqhrd7vjM","SjskQWPmlx","7fsYMpAhR1","iKqhrtAOsr","uLtKsVprf2","h1zcHh1zcH","AkKTk8U2nU","lsQGoHlUbF","QbxXcuoStw",
-"AIYUu1v5hH","JRJQBGWqqX","CqqaDLbRTH","BCxeCd85a9","m4bxUrz7Ut","dQ586yToGW","3weIFhYBCK","xReeczHF1q","lXFOBWMiS3","zFgtBZzJHW",
-"dmoS7v1Hln","JkzUnguMb8","CdyBVZzJHW","FPfSEL7cGc","4QMc9ECMvU","Pb1pauJScX","L7cGclCMxy","okgRil83Ud","ksJbyC2Irc","a00b5rz7Ut",
-"kB5nPlCMxy","zQt6Q5Namm","SbRYyZUnqt","W3VFHK4GS8","AkKTkt98iW","iB08lmz8gx","ZuDtD8hJdt","9iGoTEOE1o","ogLgcRkQke","NhXduTCgPp",
-"vLsmSlViBv","VjCZqi3pyd","LDk6faFFss","ECMvUaFFss","580YDVIlwP","gjUTuDz1R3","OxWIHVprf2","cmXIXMezSW","5IhmGa00b5","0h1b1t98iW",
-"ECMvUoGu6x","QWxoTRACuj","FnPFBBpYhV","qUJMduLtKs","iwzGkprNT6","FPfSEThjNn","HRxd8pvgjS","lpF6W5iGN5","lm0pDHfyNQ","jzUqRSs0Zu",
-"qQxHPgIYvE","ZzJHWM6qcG","RzaZAYjB9t","I7p2aL7cGc","kZANmY1mC0","HfyNQMGlTF","LbRTHW3VFH","zbIYYQWxoT","Yw2oUb29RJ","CIShGLDk6f",
-"7Ow5CMK07Y","HzZT8rhl0J","OUqFM7ku1p","L7cGcfcJOy","jiVBP0Kyfs","7lUXZlj07Q","CqqaDsx5Gl","CK5W7Ta8f6","5Drn0AIYUu","618Di29QAz",
-"taOXKt59lR","AOgEe8xEKz","NhXduNhXdu","x3LDesoy9t","pv0i7jS1aj","XyPZNciuWz","blLA9SmGzv","W7cTsVNCPd","2TRI7hYBCK","5NammkZANm",
-"uvf7AB3qem","uN6r3K20wK","YOfrYU3yw5","faHirpiJSk","QnJ1SAXpwE","RxrsmQworu","Cfgr3IRh48","xXTI4NhXdu","0YAGHOHaBz","WMiS3brhlQ",
-"S2DfuP6bcg","8RCUAQChxs","gdQsSdmoS7","TwanoNcICA","FjHXRi3pyd","XyPZNGSQwj","8hJdtTCgPp","mX2GEUmaEv","Kr8yslweGy","I7p2alpF6W",
-"K20wKb29RJ","M6qcGiqv4k","14FLRBpYhV","yEfy9O3iyQ","IKxdLhE1Ql","Uvlv4FnPFB","fmIK1S2Dfu","16lHcHfyNQ","YOfrYWmadA","QWxoTuZPqg",
-"5Namm5ZaEz","CIShG7Ow5C","5Drn0zQt6Q","xXTI4aFFss","8xEKzn1pmO","hYBCKJKWYR","pT8wuni2v1","SbRYy5Mg9r","ogLgcZv7z0","jfREuVIlwP",
-"BGaQYd7vjM","S2DfuuTacx","iwzGkBGaQY","TXQ0ZhYBCK","7fsYMoQ87r","64s8Nv2eC3","Mkgy83weIF","rKDLJi7WMQ","dmoS7PYBf4","IBe8kOHaBz",
-"FPfSEMaJQs","qaofNkZANm","AgJHQzz4ZU","vOqCEd85a9","YOfrY8TxD7","WmadAksJby","8RCUAEOE1o","HP43314FLR","G1RhSblLA9","qaofN2hEEU",
-"5nmWvFGzgp","FNYIM8hJdt","9GXkXMm8si","s7MxkM6qcG","24ARFnlaBy","oVQp6taOXK","48cHL3weIF","W3VFHBpYhV","uupzkW7cTs","Pb1palH1kt",
-"okgRiQClRL","nFqikdpe1v","vOqCE8RCUA","0YAGHThjNn","fcwDa0ao3l","LbRTHi3pyd","jiVBPFFDui","lsQGoh1zcH","ThjNnQworu","QbxXcpAhR1",
-"zFgtBO3iyQ","BbwgAAmdQd","azIWpZUnqt","0h1b1dQ586","Chuy37hyVv","FwEJzix74r","P6bcg7ku1p","WMiS30ao3l","LDk6fMK07Y","CK5W7M6qcG",
-"Pb1pab29RJ","0PktI8U2nU","NOHszQssNC","nnP8oBCxeC","jzUqRIjTwP","POUYSDcpWB","J2mQiuN6r3","JJs5mtAOsr","BGaQY9eoRc","AOgEehUTw7",
-"tlILt6AFT0","Cfgr3Nxx9V","tvdkDU3yw5","EdBKcBFkb8","M6qcGLbRTH","l83UdVBjhz","v1HlnU3yw5","QChxszbIYY","S2DfufLNg8","8U2nUiKqhr",
-"F6PT2BCxeC","3weIFVBjhz","GSQwjksJby","6q6L9FGzgp","fcwDakZANm","GrDg7YOfrY","lsQGoguMb8","55rfBsuY4x","FcWrWLewvM","ulk41VLTy6",
-"VNCPdOHaBz","aDGtSatef2","5IhmGWPmlx","MGlTFAXpwE","S77LHCxVEf","pv0i7KZamH","o8Uyds7Mxk","aFFssNOHsz","7lUXZ24ARF","taOXK2DREs",
-"X6PinFxX9q","GrDg7tjQxs","NOHszpT8wu","v1HlnOz8yZ","ciuWzqaofN","UlU3M8U2nU","SjskQaL6AJ","KZamHdpe1v","HRxd8WreyP","4W0TlyofH3",
-"2Yz7EgIYvE","FjHXR14FLR","9iGoTCIShG","S77LH5nmWv","uTacxtjQxs","48cHL1LB1L","lViBvqUJMd","fqypylsQGo","tjQxsVBjhz","Waim6ciuWz",
-"xReecn1pmO","v8yFNYf2Ec","07n1ccShY2","dhSuHguMb8","AXpwEzFgtB","lj07Q1j5L8","Ta8f6aFFss","hYBCKl83Ud","6AFT0gIYvE","b29RJBpYhV",
-"VLTy6VIlwP","KsjRKd7vjM","dpe1vMm8si","h1zcHUlU3M","07n1cWPmlx","fqypyuN6r3","1LB1Lni2v1","xXTI4v2eC3","64s8N618Di","iqv4kgIYvE",
-"VNCPdwDajX","uZPqglViBv","NhXduZUnqt","No0Qb1j5L8","Z4I1vaDGtS","24ARFqaofN","7ku1pcL0aE","yvOMIAIYUu","7ku1pCK5W7","WaWsvQ6hMC",
-"RACujpv0i7","Yw2oUAIYUu","0Wr5yYOfrY","F6PT2HzZT8","G1RhS8hJdt","9GXkXCIShG","M3zXLpAhR1","XyPZNKsjRK","9eoRcFNYIM","o8Uydd85a9",
-"CK5W7K4GS8","yEfy95drc6","bgJAzOHaBz","4dEz6Fhtgl","CxVEfKr8ys","Fhtgl4QMc9","QWxoTIRh48","yToGW24ARF","uN6r3d7vjM","o8Uyd5iGN5",
-"lweGyIRh48","M6qcG14FLR","rhl0JlH1kt","oQ87rRsQUq","VLTy6jiVBP","JRJQBcL0aE","618DiO3iyQ","Pb1paIn3NS","55rfBVjCZq","blLA9guMb8",
-"1LB1LlH1kt","BpYhVQYxC0","U3yw5FxX9q","aFFssBFkb8","fmIK1IjTwP","2DREsCIShG","pAhR1Q6hMC","VNCPdIjTwP","nlaByW7cTs","1j5L85Mg9r",
-"0MR5Xtl72W","VNCPdZhwG1","KZamHazIWp","DcpWBZv7z0","pmeCduupzk","MezSWXflUq","brhlQNhXdu","h1zcH5nmWv","BFkb814FLR","b29RJXflUq",
-"8U2nUxReec","4W0Tl0Wr5y","5drc6t59lR","m4bxUv2eC3","CK5W7jtn0X","zqH0WFnPFB","Yw2oUDLhzM","fqypyHzZT8","qUJMdFhtgl","lpF6WF6PT2",
-"BFkb8D6rBy","QChxs8RCUA","FLsph5nmWv","RpBQmydG8U","JIqXiJKWYR","lsQGojiVBP","8cVD3WDVWJ","ZJTXH9iGoT","5iGN5HzZT8","Zv7z0dpe1v",
-"iB08l5IhmG","29QAzfmIK1","5Drn0MojnP","AkKTk55rfB","d85a9oVQp6","BpYhV7ku1p","AIYUufcwDa","qaofNW3VFH","pmeCdZv7z0","zbIYYhYBCK",
-"XflUqdjsrv","5VZjS8FmFH","Yh1hFFhtgl","EoToPDz1R3","vLsmSKASQ8","Cp3mZ8FmFH","NAFuwatef2","yvOMIm4bxU","lm0pDZuDtD","YjB9tVjCZq",
-"FcWrWRBhp0","lm0pDMmKGJ","mX2GEFwEJz","uLtKszqH0W","Vprf2CNHmv","wiHrZY1mC0","Yf2EcqaofN","hE1QlaFFss","zHF1qt59lR","zFgtBEoToP",
-"lm0pDd7vjM","K4GS8JJs5m","JJs5mNAFuw","EoToPChuy3","580YDatef2","o8UydQssNC","JKWYRsuY4x","zFgtBLDk6f","CNHmvQ6Lix","m4bxU2hEEU",
-"rKDLJgtCA5","he9IAFcWrW","2hEEU2Nslm","Zv7z0t98iW","ksJbyWaim6","t98iWMaJQs","jiVBPlH1kt","2TRI7lm0pD","mX2GEyofH3","OUqFMRpBQm",
-"5VZjSI7p2a","uJScXIRh48","vLsmSfqypy","O3iyQqaofN","7X3uyhe9IA","FLsphUl4a1","SmGzvNo0Qb","lViBvh1zcH","iwzGkfmIK1","piJSkXflUq",
-"GrDg7lpF6W","FVMxo1v5hH","55rfB5ZaEz","RBhp0xciqp","NOHszt59lR","QssNCNAFuw","JIqXiAmdQd","8TxD7zz4ZU","GWqqXJJs5m","XyPZNzz4ZU",
-"24ARF7lUXZ","8U2nU6q6L9","FcWrWfcwDa","16lHchYBCK","FNYIMF6PT2","GrDg7RpBQm","fcwDaciuWz","8FmFHZ4I1v","MK07Y6AFT0","2TRI7tlILt",
-"7ku1puoStw","RzaZAWaim6","d85a9euZA5","CNHmv2Yz7E","14FLROUYuF","LewvMiqv4k","WPmlxFFDui","hSSvQVLTy6","tvdkD9y4lw","Dz1R3FGzgp",
-"YOfrY5drc6","tvdkDmz8gx","tlILtM6qcG","ogLgcDz1R3","4QMc9Uvlv4","Cfgr3O3iyQ","BFkb8VIlwP","ZhwG1IBe8k","M6qcGe6e4z","5Drn0WmadA",
-"IBe8k4QMc9","cL0aEHzZT8","t59lRIn3NS","k85AemX2GE","5nmWvDcpWB","lm0pDs4786","ogLgcguMb8","he9IA9y4lw","uPX7GlsQGo","sx5GlW7cTs",
-"8cVD3s7Mxk","guMb8K4GS8","64s8Nuupzk","W7cTszQt6Q","Chuy3hi5X7","580YD5VZjS","WmadACIShG","5drc6lsQGo","ogLgcyluBx","d7vjMtAOsr",
-"vkCHHfLNg8","DLhzMdhSuH","tjQxst98iW","wDajXfLNg8","uJScXWreyP","EOE1opAhR1","5Mg9r8FmFH","BCxeC2TRI7","uoStwGXdoH","x3LDeVNCPd",
-"YOfrY6q6L9","1j5L87X3uy","Uvlv4AOgEe","hE1QlTXQ0Z","O3iyQPYBf4","Zv7z0Vprf2","jSjS3xReec","yEfy97Ow5C","ydG8Umz8gx","QWxoTtaOXK",
-"faHirWaim6","VNCPdZuDtD","Ta8f6bgJAz","yEfy9tAOsr","lweGySmGzv","gjUTuMojnP","OxWIHRxrsm","C2IrcWaWsv","kZANmStlDJ","FwEJzpFrrl",
-"OxWIHyofH3","VBjhzgf8rI","Chuy3iwzGk","64s8NksJby","2ZHdkkB5nP","SWfou14FLR","EdBKcAXpwE","pT8wuuLtKs","07n1cFNYIM","yToGWxXTI4",
-"n8pJ9uJScX","aFFsszqH0W","oGu6xAXpwE","5IhmGuAWyp","BbwgAv2eC3","PYBf4fcwDa","WPmlxl83Ud","RpBQmHlUbF","9y4lwjzUqR","Cfgr3t59lR",
-"djsrvtAOsr","e6e4zulk41","uN6r3B3qem","GrDg7b29RJ","580YDM3zXL","n8pJ9xciqp","8RCUAfqypy","OUYuFCK5W7","x3LDeMm8si","8xEKzzbIYY",
-"e6e4zcShY2","lXFOB9GXkX","L7cGchYBCK","hUTw7QWxoT","RxrsmfFDrJ","9eoRcSjskQ","9eoRc2Nslm","CqqaDtjQxs","24ARFDQimp","zqH0WDG4sT",
-"O3iyQsx5Gl","kB5nPbgJAz","jzUqRrz7Ut","s7MxksuY4x","gdQsS24ARF","XyPZN4W0Tl","oQ87r2DREs","cQOnvtuDyS","guMb8lweGy","n1pmOHlUbF",
-"WaWsvd85a9","RkQkexXTI4","QworucShY2","KZamHRkQke","tl72WnlaBy","MaJQstvdkD","EOE1oGXdoH","bZLvSzFgtB","ix74r8hJdt","No0QbQ6hMC",
-"CK5W7YjB9t","YjB9tv1Hln","S77LHI7p2a","bgJAzAkKTk","QChxsZUnqt","CdyBVL7cGc","lXFOBuZPqg","oQ87ruLtKs","JXljW48cHL","fcJOyx3LDe",
-"8U2nUgjUTu","lViBvix74r","atef2MaJQs","FjHXR9y4lw","uQIczU3yw5","M3zXLSmGzv","uupzkuoStw","AXpwE29QAz","tuDySn1pmO","hYBCKwiHrZ",
-"8hJdtWaWsv","brhlQ3weIF","RsQUqiqv4k","uTacxuPX7G","aDGtS5ZaEz","piJSkFjHXR","CxVEfpFrrl","B3qem4QMc9","8hJdtCqqaD","GSQwjiqv4k",
-"lViBvUl4a1","hSSvQgtCA5","WPmlx29QAz","M3zXLt59lR","9rlg9t59lR","lCMxylpF6W","nFqik8hJdt","yToGWJRJQB","ZUnqttaOXK","lCMxy0MR5X",
-"F6PT2Mkgy8","nnP8oReKEW","BbwgA0MR5X","Ss0ZuQworu","5ZaEza00b5","U3yw56AFT0","gjUTu5iGN5","X6PinsqVrf","64s8NtaOXK","2Yz7EJKWYR",
-"ciuWzwiHrZ","cL0aEUlU3M","9y4lw8cVD3","VNCPdgf8rI","SjskQblLA9","okgRiuJScX","zY1GYMezSW","pvgjSix74r","BbwgAPYBf4","GSQwjIn3NS",
-"2hEEUzY1GY","4QMc9lXFOB","aL6AJoQ87r","VjCZq2TRI7","ZhwG1X6Pin","b29RJ2Nslm","pT8wuyvOMI","VIlwPlXFOB","fFDrJWPmlx","RkQkeiqv4k",
-"pT8wuFcWrW","nnP8oRzaZA","blLA9oQ87r","KsjRKRzaZA","8U2nUAgJHQ","ZzJHW24ARF","9iGoTRpBQm","NOHsztaOXK","KASQ8yEfy9","Vprf2AgJHQ",
-"wiHrZCdyBV","W7cTsuQIcz","BCxeCZhwG1","9rlg945cIH","ru4UGQ6Lix","9XyT9Z4I1v","JkzUnMkgy8","euZA59GXkX","NhXdumX2GE","jzUqRciuWz",
-"RzaZAY1mC0","pmeCdLewvM","qUJMdW3VFH","tAOsraL6AJ","0KyfspWiOs","FnPFBRBhp0","piJSkzFgtB","JIqXiDcpWB","P6bcgCK5W7","uLtKslsQGo",
-"tlILtMmKGJ","iwzGk2Nslm","Fhtgl0PktI","VNCPdMK07Y","uAWypciuWz","hYBCKFPfSE","FwEJzVBjhz","s4786okgRi","xXTI4i7WMQ","Oz8yZ7Ow5C",
-"4QMc9nnP8o","fLNg8QClRL","CIShGX6Pin","tvdkDAOgEe","UlU3MFGzgp","MmsIoG1RhS","YjB9tix74r","QnJ1S1v5hH","HP433rz7Ut","Y1mC0RACuj",
-"2ZHdklkMUA","jS1aj5ZaEz","ulk41YOfrY","7X3uyTwano","BpYhVZhwG1","d7vjMEoToP","oVQp6NhXdu","zY1GYoVQp6","QnJ1ShE1Ql","jzUqRZhwG1",
-"7ku1pGWqqX","suY4xBbwgA","StlDJReKEW","QYxC0Pb1pa","zz4ZUMkgy8","QbxXcMkgy8","TwanozQt6Q","hi5X7B3qem","xciqpIBe8k","9rlg9FwEJz",
-"oVQp6No0Qb","tvdkDuvf7A","pmeCdKASQ8","0h1b1dhSuH","atef2FwEJz","ni2v1piJSk","prNT6ogLgc","lweGyuZPqg","No0QbVIlwP","h1zcHcmXIX",
-"JIqXis4786","euZA5gf8rI","zQt6QFxX9q","Mkgy8SbRYy","5ZaEztlILt","SWfouMezSW","Cp3mZL7cGc","y94nwtl72W","mz8gxx3LDe","OUqFM5Namm",
-"LewvMDG4sT","pFrrlPb1pa","S2Dfus4786","vLsmSCK5W7","uZPqgDcpWB","zY1GYzz4ZU","s4786AOgEe","zqH0WMK07Y","IKxdLRzaZA","ZhwG1guMb8",
-"MojnPgf8rI","blLA94dEz6","Mkgy8OHaBz","J2mQi29QAz","uTacxVNCPd","iB08l07n1c","n1pmOyluBx","LbRTH48cHL","X6PinaFFss","OxWIHFLsph",
-"aez9yxXTI4","3weIFdjsrv","7X3uyOUYuF","EOE1oDcpWB","BCxeCMm8si","suY4xSjskQ","RsQUqgf8rI","2DREsSjskQ","CK5W7XyPZN","Q6hMCm4bxU",
-"uTacxzQt6Q","9eoRcokgRi","ciuWzhi5X7","piJSkFGzgp","okgRijtn0X","mX2GEOxWIH","suY4xHzZT8","Mkgy8k85Ae","HP433G1RhS","JkzUnVLTy6",
-"3otm6ECMvU","55rfBIjTwP","jiVBPxReec","FGzgpt59lR","uJScXcL0aE","HlUbFjSjS3","LDk6fVLTy6","YjB9tbgJAz","S2DfuBFkb8","yluBxFxX9q",
-"Uvlv4s4786","FLsphAkKTk","24ARF8hJdt","FxX9qvkCHH","GWqqXG1RhS","lweGyuvf7A","XyPZNfcJOy","dmoS7Uvlv4","JkzUniwzGk","vLsmSt59lR",
-"wDajXGSQwj","hE1QlCp3mZ","suY4xJkzUn","bZLvSuTacx","L7cGci3pyd","tlILtgf8rI","CIShGP6bcg","RxrsmIKxdL","v8yFNfcJOy","hE1QlsqVrf",
-"ThjNnbgJAz","ksJbyY1mC0","zQt6Q64s8N","lH1ktulk41","soy9ts7Mxk","WaWsv5Drn0","7X3uyvOqCE","6AFT0GXdoH","yofH37fsYM","aL6AJJKWYR",
-"0Wr5yNxx9V","QYxC0v2eC3","sqVrfzY1GY","ix74rJRJQB","DLhzMuvf7A","pWiOsgtCA5","qaofNgf8rI","guMb8ZhwG1","8TxD7vkCHH","16lHcjzUqR",
-"uupzka00b5","WMiS3pv0i7","8RCUAfcJOy","RkQkeulk41","zQt6Q7ku1p","G1RhSyEfy9","BGaQY5IhmG","qaofN1v5hH","Waim6QClRL","pFrrlBGaQY",
-"MmsIoFjHXR","i3pydVBjhz","S77LHZhwG1","No0QbFVMxo","rKDLJ9GXkX","tvdkD7X3uy","F6PT2m4bxU","ZUnqtn1pmO","tAOsrQYxC0","vkCHHnFqik",
-"FNYIMnnP8o","8U2nUfcJOy","LewvM2Nslm","K20wKQChxs","0Wr5ylCMxy","0BmCyix74r","t59lRNhXdu","C2Ircfqypy","mX2GEMGlTF","d85a9wiHrZ",
-"pAhR19eoRc","uZPqgnnP8o","QnJ1SCdyBV","KZamH5drc6","9y4lwZuDtD","2TRI79rlg9","2DREsFwEJz","sx5GlbZLvS","bgJAz4W0Tl","JkzUnNcICA",
-"DG4sTrhl0J","QssNCX6Pin","2TRI77fKYU","JXljWpFrrl","XflUqYOfrY","aFFssXyPZN","atef28hJdt","In3NSh1zcH","k85AeAOgEe","zz4ZUiKqhr",
-"0ao3la00b5","8U2nUcL0aE","nFqikFhtgl","xXTI4FFDui","4W0TlQssNC","Mkgy83otm6","FGzgpStlDJ","TwanoIRh48","ix74ruAWyp","OUqFM9eoRc",
-"gtCA5AgJHQ","B3qemrKDLJ","45cIH1LB1L","ydG8UtAOsr","t98iWWDVWJ","0YAGHpAhR1","Yw2oUTXQ0Z","bgJAzHfyNQ","NcICAUmaEv","RxrsmSmGzv",
-"9iGoTQssNC","uvf7APb1pa","9eoRcYOfrY","LbRTHhi5X7","he9IAsoy9t","lViBvb29RJ","VNCPdx3LDe","d7vjMDQimp","Fhtglru4UG","bgJAzwiHrZ",
-"RsQUqxReec","POUYSC2Irc","nFqikRACuj","rKDLJS2Dfu","CNHmvzqH0W","L7cGcFGzgp","2NslmSjskQ","hYBCKgjUTu","qUJMdbZLvS","tl72WpT8wu",
-"8TxD7fFDrJ","pFrrlWreyP","brhlQVIlwP","WaWsvfaHir","aez9y6AFT0","5ZaEzFLsph","cL0aEgtCA5","D6rByZhwG1","GWqqXguMb8","lsQGoU3yw5",
-"Oz8yZ3weIF","In3NSBbwgA","7lUXZIn3NS","jtn0XIn3NS","MmsIookgRi","JJs5mCdyBV","dhSuHcL0aE","pmeCdcQOnv","WaWsvFFDui","bZLvSv1Hln",
-"45cIHx3LDe","UlU3MSmGzv","dQ586CqqaD","0Wr5yAXpwE","ThjNndhSuH","ix74rVIlwP","uvf7ARmDcr","pvgjSsoy9t","J2mQidhSuH","fLNg8vOqCE",
-"xReecAgJHQ","IKxdLDQimp","WDVWJbrhlQ","M6qcGSjskQ","yofH3o8Uyd","ZuDtDRkQke","ZhwG16AFT0","Nxx9VW7cTs","sx5GlQworu","NOHszAmdQd",
-"Oz8yZaFFss","FGzgpnFqik","AmdQdhSSvQ","suY4xBpYhV","SmGzv07n1c","TCgPpDcpWB","lViBvQYxC0","uJScXIKxdL","vLsmSvkCHH","djsrvC2Irc",
-"ZzJHWOxWIH","BFkb845cIH","9eoRcdhSuH","ZuDtDAXpwE","7ku1pa00b5","ECMvUbgJAz","lweGyQYxC0","RxrsmReKEW","HP433JXljW","Ss0ZuNhXdu",
-"vkCHHMmsIo","jS1ajQbxXc","h1zcHFcWrW","lpF6WwiHrZ","LewvMFhtgl","rKDLJfqypy","fLNg8oQ87r","ulk41yluBx","QbxXci7WMQ","48cHLQworu",
-"fcJOy3otm6","GWqqXprNT6","hi5X7zqH0W","AOgEel83Ud","BGaQYpmeCd","FGzgpcL0aE","Uvlv47X3uy","IRh48jS1aj","5drc6VjCZq","JKWYR5IhmG",
-"BGaQYtAOsr","IKxdLVerEA","tl72WksJby","Vprf2IBe8k","QssNCZ4I1v","gdQsSZhwG1","bgJAzuTacx","lsQGoThjNn","4QMc9tvdkD","S77LHPb1pa",
-"POUYSvkCHH","UlU3M4dEz6","djsrvBbwgA","Uvlv4GXdoH","Uvlv4uvf7A","pv0i764s8N","vkCHHlkMUA","rhl0JFhtgl","OHaBzzqH0W","vkCHHQssNC",
-"lj07QYjB9t","wiHrZZuDtD","FxX9qFFDui","y94nwYh1hF","qaofNeuZA5","tAOsrfaHir","ix74rChuy3","1LB1L7X3uy","CxVEft59lR","CNHmvEOE1o",
-"FcWrWMmKGJ","KsjRKtaOXK","ksJbyVerEA","I7p2ai3pyd","NcICA0MR5X","Oz8yZQbxXc","pv0i7MezSW","zbIYYzY1GY","zFgtBBGaQY","CxVEf1LB1L",
-"RkQkeOUYuF","5Mg9r0YAGH","QworufcJOy","Uvlv4pmeCd","ZJTXHP6bcg","h1zcHRkQke","9rlg9Mm8si","a00b5AOgEe","7hyVvsx5Gl","hi5X7vkCHH",
-"M3zXLYw2oU","29QAz8xEKz","FPfSEFNYIM","xReecx3LDe","uupzkfLNg8","blLA9pWiOs","brhlQfLNg8","vLsmSNAFuw","Oz8yZjiVBP","D6rBy7fsYM",
-"yvOMIe6e4z","dQ586zqH0W","Mkgy8fqypy","GrDg7cL0aE","7hyVvlsQGo","uN6r3GWqqX","aez9ypAhR1","WDVWJix74r","aez9yblLA9","tlILtZuDtD",
-"YjB9tPOUYS","KsjRKVBjhz","pT8wul83Ud","I7p2aThjNn","Kr8yslViBv","AmdQdcmXIX","sqVrfd7vjM","t59lR4dEz6","HfyNQBGaQY","SWfouIBe8k",
-"ciuWzjzUqR","5VZjSbrhlQ","RkQkesuY4x","Cp3mZFFDui","AmdQd9y4lw","Yh1hFJKWYR","TXQ0ZJRJQB","lCMxyJIqXi","ogLgccShY2","yofH3IBe8k",
-"8xEKzIRh48","1j5L8WMiS3","HRxd8Gv3Fq","RpBQmBCxeC","HP433AOgEe","tAOsrFLsph","nnP8osuY4x","ydG8U5iGN5","J2mQii3pyd","t98iWLbRTH",
-"LewvMpiJSk","fqypyCNHmv","AkKTkciuWz","v1HlnP6bcg","pmeCdbZLvS","0MR5XpWiOs","7fKYUrhl0J","29QAz9eoRc","NcICAzqH0W","AXpwEkZANm",
-"MK07YRzaZA","xReec5VZjS","lsQGoNo0Qb","FcWrWP6bcg","MmsIouTacx","d85a9y94nw","29QAzmX2GE","7X3uyAXpwE","yvOMItvdkD","fcwDas93Ml",
-"jiVBPbZLvS","7ku1pciuWz","7hyVvD6rBy","WaWsvJIqXi","OxWIHzbIYY","DcpWBYh1hF","pvgjSCp3mZ","JkzUnM3zXL","yofH32TRI7","M6qcGM3zXL",
-"nlaByGrDg7","Z4I1vFcWrW","HP433jeskS","7lUXZjSjS3","FGzgpUvlv4","n8pJ9wDajX","AIYUuQChxs","pT8wuSWfou","OHaBzni2v1","EOE1ozQt6Q",
-"kB5nPOxWIH","2Yz7Et59lR","tAOsrBpYhV","ru4UG14FLR","AkKTkQChxs","gjUTuzz4ZU","RpBQmpiJSk","lsQGo29QAz","oVQp6atef2","yofH3BbwgA",
-"5Mg9ro8Uyd","BCxeCQssNC","uQIczMmKGJ","gdQsSFjHXR","ciuWzRkQke","he9IAJJs5m","FVMxozbIYY","0YAGHCfgr3","LDk6f9y4lw","AOgEe2Nslm",
-"NhXdu0ao3l","wiHrZaez9y","QbxXcYjB9t","s7MxkWaim6","X6PinRmDcr","bgJAztuDyS","atef24W0Tl","LewvMGv3Fq","CxVEf7hyVv","yofH3fcwDa",
-"I7p2a5Drn0","LewvMcShY2","s93MlNxx9V","uN6r3IKxdL","LDk6fuTacx","pmeCd2TRI7","BpYhVMm8si","fcJOy5iGN5","zbIYYdpe1v","uLtKsBpYhV",
-"dhSuHWmadA","S2DfuD6rBy","VLTy6FVMxo","atef248cHL","EdBKctAOsr","l83Udatef2","ciuWzni2v1","0BmCyYOfrY","l83UdSs0Zu","7hyVvqQxHP",
-"8hJdtYjB9t","uupzk24ARF","oQ87r7hyVv","mz8gx14FLR","2NslmzFgtB","tjQxsQ6hMC","v8yFN5ZaEz","EOE1olj07Q","5ZaEzfmIK1","14FLR4dEz6",
-"K4GS8VNCPd","Kr8ysM6qcG","RBhp0HlUbF","hUTw716lHc","oGu6xOUqFM","aez9yvOqCE","C2IrcVNCPd","No0Qb0h1b1","uJScXJKWYR","MGlTFEdBKc",
-"64s8NFVMxo","uTacxxciqp","5IhmGFFDui","VNCPd4QMc9","lm0pDlweGy","wDajXQbxXc","v2eC3yToGW","W7cTsfqypy","Cfgr3xReec","QnJ1S2Yz7E",
-"zz4ZUogLgc","wiHrZiqv4k","fmIK1DQimp","CqqaDFnPFB","Yf2EcU3yw5","gtCA5VerEA","14FLRhYBCK","QYxC0lj07Q","tvdkDGSQwj","VerEAeuZA5",
-"XyPZN0Kyfs","5Drn0Ta8f6","OHaBzRmDcr","xciqpJXljW","nnP8od7vjM","pAhR1VerEA","AOgEe7X3uy","5NammfLNg8","BGaQYhi5X7","FwEJzYf2Ec",
-"J2mQiCNHmv","ReKEWjeskS","s7MxkksJby","VjCZqUvlv4","mX2GEJkzUn","bZLvS9rlg9","uAWypSmGzv","brhlQ5Namm","NOHsz3weIF","CqqaDDLhzM",
-"wDajXYOfrY","azIWpP6bcg","FcWrWt98iW","prNT69y4lw","azIWpRxrsm","zmLYDPb1pa","tAOsrTa8f6","9XyT9h1zcH","0ao3lFxX9q","55rfBh1zcH",
-"guMb88FmFH","XflUqCNHmv","hUTw7Mm8si","8RCUATXQ0Z","v8yFNy94nw","CqqaD1LB1L","xXTI4MezSW","SbRYypT8wu","QWxoTOHaBz","n8pJ95ZaEz",
-"faHirhE1Ql","B3qem0PktI","CdyBVCIShG","S77LHuQIcz","S77LH5drc6","n1pmOTCgPp","64s8NVBjhz","JJs5m4dEz6","dpe1v1j5L8","XflUqMm8si",
-"h1zcHSjskQ","gf8rItuDyS","9GXkXuZPqg","OUqFMdpe1v","7fKYUtvdkD","pAhR1lkMUA","i7WMQZzJHW","CqqaD0ao3l","lXFOBpmeCd","EoToPPYBf4",
-"ThjNnt98iW","VBjhzoVQp6","FLsphjS1aj","IKxdL2Nslm","d7vjMCNHmv","WmadACdyBV","yToGWY1mC0","5Drn09y4lw","gtCA5t98iW","ru4UGhE1Ql",
-"jzUqRY1mC0","64s8NC2Irc","C2IrcyToGW","cL0aEBGaQY","S77LHWreyP","8U2nUjtn0X","k85AeWPmlx","HRxd85VZjS","FLsphZUnqt","Zv7z0VjCZq",
-"9rlg9xReec","iKqhrqQxHP","o8UydYjB9t","okgRijiVBP","rz7UtNAFuw","1LB1LSWfou","XflUq9y4lw","pvgjSStlDJ","D6rBy0Wr5y","mX2GEtjQxs",
-"QChxsh1zcH","YjB9tFjHXR","7ku1pokgRi","wiHrZ0ao3l","NcICAS2Dfu","7Ow5CsuY4x","TXQ0Z4dEz6","L7cGcdhSuH","XflUqmz8gx","0Wr5yprNT6",
-"07n1cChuy3","WMiS38U2nU","JIqXiyluBx","RpBQmhUTw7","he9IAmX2GE","FPfSEvOqCE","DG4sTOHaBz","3weIFqUJMd","55rfBuPX7G","2Yz7EoVQp6",
-"aDGtScmXIX","bgJAzhi5X7","Ul4a1FxX9q","uQIczBbwgA","xReecDG4sT","dQ586pmeCd","zQt6QokgRi","HfyNQuoStw","rKDLJaez9y","YjB9tprNT6",
-"ciuWzxReec","0PktI2TRI7","zHF1qnnP8o","fqypyvLsmS","FFDui4W0Tl","UmaEv618Di","EdBKc5VZjS","qUJMdyToGW","IKxdLJJs5m","e6e4zTwano",
-"hUTw78TxD7","ix74rBFkb8","bZLvSk85Ae","dpe1vwDajX","2ZHdkO3iyQ","IKxdLXyPZN","618Difqypy","29QAz2Yz7E","55rfBlH1kt","48cHLru4UG",
-"FxX9qZuDtD","ZzJHWiwzGk","P6bcgI7p2a","pWiOs48cHL","n1pmO07n1c","VjCZqvLsmS","8U2nUeuZA5","JJs5ms93Ml","2Nslm5ZaEz","tlILtblLA9",
-"8U2nU07n1c","GWqqXyToGW","cmXIXwiHrZ","fLNg85VZjS","AkKTkPb1pa","ZhwG1ydG8U","Ss0ZuNOHsz","0ao3luJScX","dmoS7blLA9","Yh1hFTwano",
-"zQt6QFhtgl","atef2F6PT2","AIYUuvLsmS","sqVrf8U2nU","07n1clkMUA","jS1ajSs0Zu","3otm6s4786","lkMUA4QMc9","S77LHvOqCE","NhXdu8U2nU",
-"atef2NAFuw","jfREuZ4I1v","zqH0WtjQxs","TXQ0ZVIlwP","6AFT0Vprf2","XflUqChuy3","LewvMoVQp6","Ul4a1W3VFH","UlU3MQYxC0","9eoRcciuWz",
-"hSSvQU3yw5","uQIczOHaBz","fcwDa24ARF","WreyPtvdkD","6AFT0Chuy3","55rfBpFrrl","ZhwG1StlDJ","S77LHhUTw7","8U2nUdmoS7","d7vjMRpBQm",
-"hUTw7WDVWJ","9rlg9QnJ1S","zz4ZUxReec","RzaZAyEfy9","l83UdYw2oU","Rxrsm0YAGH","fcwDabrhlQ","K4GS82hEEU","0PktIDcpWB","2Nslm0YAGH",
-"vLsmSJRJQB","jtn0XgIYvE","nnP8o5Namm","0h1b15drc6","5nmWvFxX9q","CxVEfZv7z0","hSSvQYh1hF","okgRiZ4I1v","gjUTuVprf2","d85a9vkCHH",
-"lH1ktni2v1","7X3uyvLsmS","BCxeCqQxHP","aDGtSfFDrJ","cL0aEMmsIo","lweGyfaHir","xciqppiJSk","hYBCKatef2","pFrrlvkCHH","BFkb86q6L9",
-"xciqpUlU3M","45cIH5VZjS","MojnPoGu6x","ZUnqts7Mxk","JRJQBBbwgA","dhSuHlH1kt","nnP8o0MR5X","tl72WvLsmS","QChxsdjsrv","NAFuwAgJHQ",
-"9XyT9EoToP","WaWsvXyPZN","2DREstlILt","55rfBCNHmv","gdQsSSmGzv","QWxoTwiHrZ","WaWsvpmeCd","jzUqR2Yz7E","14FLRKZamH","v2eC39XyT9",
-"VjCZqlm0pD","fFDrJLDk6f","StlDJnFqik","wiHrZ9XyT9","0MR5XwiHrZ","TCgPpAmdQd","YjB9tTXQ0Z","In3NSJ2mQi","mz8gxQworu","Kr8ysbrhlQ",
-"GXdoHx3LDe","Pb1pad7vjM","prNT6CxVEf","FxX9qm4bxU","RxrsmOUYuF","VLTy60ao3l","bgJAz2Nslm","wiHrZ0BmCy","lm0pDFjHXR","W3VFH2TRI7",
-"d85a9U3yw5","a00b5aez9y","S77LHOxWIH","RxrsmaFFss","hSSvQFcWrW","i7WMQuupzk","uTacx7ku1p","BpYhVjSjS3","m4bxU6q6L9","lH1ktQbxXc",
-"3weIFMezSW","4QMc9Ul4a1","uPX7GsuY4x","lm0pD9iGoT","nlaBy5nmWv","CdyBVMm8si","lCMxyDG4sT","cL0aE48cHL","1j5L8Vprf2","2ZHdk16lHc",
-"5Drn0aL6AJ","qQxHPSs0Zu","tl72WfcJOy","C2IrcgIYvE","nnP8o4W0Tl","XyPZNQssNC","xReecU3yw5","Kr8ysn1pmO","lsQGoSs0Zu","Yf2EcyluBx",
-"PYBf4s4786","uvf7AJkzUn","atef2tlILt","MGlTFFPfSE","rz7Utx3LDe","IRh48l83Ud","WaWsvWPmlx","CxVEfrKDLJ","s7MxkFLsph","FhtglQ6Lix",
-"hSSvQQnJ1S","gtCA5bgJAz","AOgEeStlDJ","Waim6brhlQ","MK07YBFkb8","FPfSEtaOXK","cShY2ru4UG","wDajXhe9IA","Dz1R3LDk6f","Pb1paiB08l",
-"YOfrYRBhp0","EoToP7fKYU","cShY2bgJAz","ydG8UMm8si","OUYuFd7vjM","LbRTHZJTXH","5drc6pT8wu","POUYSMezSW","pFrrlHfyNQ","SbRYyEdBKc",
-"lViBvmX2GE","4QMc9tlILt","jtn0XjfREu","xciqpZhwG1","P6bcgv1Hln","7Ow5Ct98iW","OUqFMNAFuw","atef264s8N","qaofNuQIcz","hSSvQECMvU",
-"VjCZqCxVEf","hYBCKCdyBV","XyPZNIjTwP","vLsmSX6Pin","K4GS82ZHdk","0PktIWmadA","lm0pDazIWp","yToGWQworu","JXljWzmLYD","nFqikQ6Lix",
-"2ZHdkFNYIM","jfREuG1RhS","e6e4zd85a9","uoStwWreyP","ZuDtDlCMxy","iKqhrzqH0W","FGzgpd7vjM","Ta8f6azIWp","ni2v1BFkb8","ZhwG1jSjS3",
-"TwanoiB08l","DQimpru4UG","oGu6xNAFuw","DG4sTe6e4z","t59lRqaofN","SWfouFcWrW","nlaByIn3NS","aL6AJtAOsr","uN6r3zbIYY","nnP8olCMxy",
-"zY1GY2hEEU","QworuWaim6","AgJHQuN6r3","GSQwjrz7Ut","pT8wuiqv4k","t98iWCdyBV","EoToPJXljW","sx5Gl64s8N","45cIHhi5X7","zz4ZUuZPqg",
-"sqVrfQbxXc","jzUqRRBhp0","KASQ8gIYvE","v2eC3JIqXi","vLsmSiKqhr","Cp3mZThjNn","K4GS8BFkb8","5VZjSChuy3","OUqFMhe9IA","uoStwcmXIX",
-"WmadAuTacx","9rlg9ydG8U","HRxd8OUYuF","mX2GEfcwDa","O3iyQAgJHQ","64s8Nv8yFN","XflUqBFkb8","zqH0WMaJQs","F6PT2M3zXL","W7cTs8FmFH",
-"KZamHzmLYD","oGu6xlj07Q","MaJQsvOqCE","618Di7ku1p","GWqqX07n1c","DLhzMU3yw5","gtCA5euZA5","jiVBPZv7z0","07n1ckZANm","StlDJxXTI4",
-"2Yz7EW7cTs","jiVBPuupzk","7fsYMU3yw5","atef2ReKEW","SWfoutuDyS","WmadARACuj","Kr8ysYw2oU","DLhzMuPX7G","l83UdECMvU","zY1GYni2v1",
-"ogLgcwDajX","pT8wuyEfy9","F6PT2fLNg8","XflUqFVMxo","Waim6Cp3mZ","0MR5XReKEW","uJScXkZANm","Waim6pvgjS","guMb8ZUnqt","zmLYDGv3Fq",
-"Z4I1v8xEKz","IBe8k0Wr5y","brhlQy94nw","5NammwiHrZ","vOqCELbRTH","4dEz6mX2GE","tAOsrFnPFB","lm0pD1j5L8","QChxsJ2mQi","K4GS8zY1GY",
-"JIqXixReec","PYBf4okgRi","U3yw5zz4ZU","NcICAIBe8k","HP433TXQ0Z","gtCA555rfB","RkQkenFqik","In3NSFwEJz","lXFOB0MR5X","MK07Y0BmCy",
-"qUJMdiB08l","AOgEefcJOy","oVQp69GXkX","VNCPdrz7Ut","n1pmO6AFT0","jzUqR45cIH","HzZT86q6L9","MGlTFWreyP","qQxHPJkzUn","1v5hHCdyBV",
-"FGzgpYOfrY","QworuuAWyp","Chuy3wiHrZ","W3VFH0PktI","K20wKUvlv4","pv0i7OUqFM","NAFuwGWqqX","1j5L8M3zXL","K4GS8W7cTs","0YAGHQWxoT",
-"nlaByMojnP","h1zcHlXFOB","WmadA4dEz6","zqH0WYw2oU","618DiMmsIo","ThjNnVjCZq","7fsYMBbwgA","gIYvE4W0Tl","AIYUufcJOy","ciuWznlaBy",
-"GXdoH4QMc9","QssNCMK07Y","POUYS16lHc","ru4UG2TRI7","PYBf4zY1GY","WPmlxVerEA","iKqhrHP433","No0Qb9rlg9","kZANmThjNn","lXFOB24ARF",
-"uLtKsHlUbF","XyPZN2ZHdk","iwzGkfcJOy","RmDcrKZamH","fLNg8dQ586","MGlTFAgJHQ","RACujOUqFM","I7p2aZhwG1","StlDJAgJHQ","sx5GlS77LH",
-"k85Aen1pmO","O3iyQFwEJz","MGlTF7Ow5C","HlUbFaDGtS","7hyVvkZANm","okgRiiwzGk","Z4I1vkZANm","YjB9tn8pJ9","DcpWBDLhzM","nFqikfaHir",
-"Dz1R3hE1Ql","b29RJyEfy9","VjCZqWreyP","i7WMQuPX7G","2hEEUVBjhz","Ta8f6EdBKc","SjskQn1pmO","K4GS816lHc","djsrvZUnqt","5Mg9rD6rBy",
-"MmKGJt59lR","fFDrJMaJQs","DLhzMzQt6Q","MezSWnnP8o","sx5Glaez9y","UmaEvo8Uyd","YjB9tGv3Fq","HfyNQ24ARF","nnP8ojtn0X","yEfy9pAhR1",
-"zHF1qUlU3M","zHF1qs4786","K20wKfcwDa","07n1cgIYvE","S2Dfu618Di","RzaZAGSQwj","QbxXclweGy","580YDMezSW","P6bcg7fKYU","JXljWpT8wu",
-"6q6L9Chuy3","2ZHdkGv3Fq","RmDcrHzZT8","QssNCD6rBy","t59lR29QAz","M6qcGlm0pD","fFDrJhE1Ql","gtCA5DQimp","MojnPbgJAz","DQimpFNYIM",
-"L7cGcMezSW","gdQsSFFDui","9XyT9C2Irc","07n1cyToGW","SbRYyv2eC3","WaWsvCK5W7","48cHLJ2mQi","TCgPpSmGzv","l83UdfcwDa","oQ87r7fKYU",
-"CdyBVMezSW","jeskSU3yw5","s7MxkDcpWB","fcJOy0Wr5y","x3LDe8TxD7","O3iyQTXQ0Z","xReecJRJQB","pWiOs8FmFH","MezSWMkgy8","gtCA5RmDcr",
-"JkzUncmXIX","lCMxyqUJMd","IKxdL6AFT0","QClRLPOUYS","24ARFqUJMd","rKDLJfmIK1","v2eC3IKxdL","jfREu7fsYM","B3qemlViBv","prNT6G1RhS",
-"Gv3FqDQimp","uPX7GpiJSk","d7vjMFNYIM","VNCPd9eoRc","QnJ1Sgf8rI","zz4ZUs93Ml","Yh1hFbgJAz","uJScX0PktI","RBhp0sx5Gl","uN6r3TXQ0Z",
-"dQ586Q6hMC","Yf2Echi5X7","cQOnvoVQp6","POUYSFGzgp","kB5nPNAFuw","pv0i714FLR","RACujK4GS8","djsrvulk41","zmLYDCqqaD","IKxdLZv7z0",
-"RpBQmGv3Fq","LDk6fmz8gx","bZLvSqQxHP","xReecJkzUn","W7cTshe9IA","UmaEvFPfSE","WMiS3Mkgy8","SjskQCfgr3","AgJHQ5VZjS","0Wr5ybgJAz",
-"0Kyfsxciqp","RpBQmuZPqg","24ARFlViBv","5iGN5bgJAz","wDajXFnPFB","uZPqg5nmWv","iKqhrMojnP","FGzgpQworu","J2mQi5ZaEz","J2mQi6AFT0",
-"zQt6QwiHrZ","LewvMqaofN","AIYUuP6bcg","BpYhVVBjhz","d85a9EOE1o","8cVD3faHir","NAFuwFPfSE","vOqCEOUqFM","JXljWcmXIX","JXljWjeskS",
-"9XyT9W3VFH","hE1Qllm0pD","0MR5XuN6r3","TCgPpEOE1o","QssNCblLA9","zY1GYhYBCK","ZuDtDTwano","cmXIXB3qem","m4bxUt59lR","DLhzMIKxdL",
-"14FLR8cVD3","x3LDeQYxC0","WPmlxLbRTH","64s8Ny94nw","QYxC08hJdt","OUYuFS2Dfu","FcWrWS2Dfu","IBe8kix74r","soy9ttAOsr","IjTwPZhwG1",
-"djsrvzqH0W","jfREu5drc6","mz8gxThjNn","zmLYDVjCZq","TXQ0Z8TxD7","yEfy9pWiOs","IRh48MmKGJ","580YDYOfrY","QWxoTThjNn","S2Dfu5IhmG",
-"sqVrfdQ586","JRJQBDz1R3","8cVD3wDajX","5nmWvhi5X7","UmaEvazIWp","Yh1hFnFqik","ZJTXHHfyNQ","RBhp0prNT6","prNT6m4bxU","jS1ajvLsmS",
-"8hJdtHfyNQ","NhXduNcICA","yEfy98FmFH","v1Hln5VZjS","hUTw7tl72W","16lHcOHaBz","mX2GEEOE1o","tjQxsTCgPp","5VZjSdQ586","jiVBP8cVD3",
-"dpe1v2ZHdk","AXpwEqaofN","RsQUqUlU3M","uAWypix74r","zQt6QlsQGo","8TxD7WDVWJ","CxVEfYw2oU","QClRLzqH0W","07n1cBpYhV","VerEAVLTy6",
-"kZANm2TRI7","IjTwPFhtgl","WreyP7hyVv","VjCZqY1mC0","o8UydHP433","7X3uyReKEW","k85AeokgRi","QssNChUTw7","CqqaDCp3mZ","9rlg98cVD3",
-"vOqCEUmaEv","0Wr5yKr8ys","0PktI3weIF","bgJAzGWqqX","AmdQduoStw","lXFOBFFDui","Z4I1vlsQGo","zQt6Q3weIF","DcpWB0PktI","BGaQYyToGW",
-"pFrrlZuDtD","lm0pD3otm6","M6qcG8hJdt","MK07YmX2GE","dpe1vIjTwP","blLA9tAOsr","5Mg9rUl4a1","uZPqgC2Irc","VNCPdhUTw7","TCgPp5Drn0",
-"tAOsrMkgy8","iqv4kiwzGk","9GXkXdpe1v","HfyNQCp3mZ","3weIFpFrrl","OxWIHzz4ZU","G1RhSSWfou","zbIYYoQ87r","ZhwG1HRxd8","uupzkFhtgl",
-"DcpWBLDk6f","rz7UtwiHrZ","BFkb8yvOMI","Ul4a1U3yw5","U3yw5sx5Gl","GrDg74QMc9","jeskSJKWYR","KsjRK14FLR","AXpwEXflUq","580YDi7WMQ",
-"C2Ircsx5Gl","jiVBPG1RhS","LewvMIRh48","CdyBVFxX9q","OUYuFjzUqR","Ta8f6QYxC0","MezSWyvOMI","tuDySNxx9V","6AFT04W0Tl","45cIHJ2mQi",
-"2TRI7yToGW","tuDySprNT6","WPmlxVjCZq","1j5L8pWiOs","W7cTs2Nslm","5NammIjTwP","o8UydpWiOs","Z4I1v45cIH","StlDJhYBCK","9iGoTMK07Y",
-"djsrvzbIYY","5NammlH1kt","a00b59iGoT","cL0aEzFgtB","VjCZqmz8gx","ni2v17fsYM","HRxd85Drn0","FxX9qNhXdu","tl72WJIqXi","zFgtBQChxs",
-"Mkgy8pWiOs","dmoS7ksJby","7X3uyBbwgA","fcwDaWPmlx","M6qcGCdyBV","CdyBVAOgEe","oQ87rzQt6Q","Y1mC0Rxrsm","i3pydQClRL","OUYuFs4786",
-"I7p2adpe1v","5NammK4GS8","Z4I1vQWxoT","kB5nPWaim6","07n1cWMiS3","JIqXiZzJHW","DcpWBXyPZN","fcwDaFhtgl","nFqikn1pmO","29QAzcShY2",
-"Oz8yZb29RJ","bgJAz5VZjS","atef29GXkX","pmeCdRkQke","xXTI4nFqik","5IhmGI7p2a","oVQp6FxX9q","RxrsmuZPqg","YOfrYPOUYS","s93MlS2Dfu",
-"wiHrZuQIcz","0YAGHru4UG","55rfBqQxHP","djsrvh1zcH","1v5hHWPmlx","ix74r7lUXZ","7ku1pBCxeC","azIWpWDVWJ","HP433qaofN","l83Ud7fsYM",
-"hE1QlZzJHW","ThjNnZv7z0","nFqik0YAGH","fmIK1b29RJ","qaofNMaJQs","GXdoHyToGW","ZUnqtIBe8k","ReKEWjtn0X","VLTy6sqVrf","2Yz7EjSjS3",
-"9iGoTDLhzM","zHF1qK4GS8","soy9tv8yFN","uLtKs2hEEU","D6rBy2hEEU","LbRTHHRxd8","o8UydThjNn","cQOnvWDVWJ","xXTI4mX2GE","lCMxyFNYIM",
-"i3pydOz8yZ","W3VFH07n1c","rz7UtydG8U","8U2nUQssNC","DLhzM29QAz","Yf2EcsuY4x","EOE1o0h1b1","tvdkDNo0Qb","QnJ1SQChxs","yofH3hE1Ql",
-"Vprf28hJdt","BpYhV55rfB","ZuDtDfqypy","s93MlSWfou","IKxdLZ4I1v","RkQkeGSQwj","0ao3lfLNg8","cQOnvd85a9","soy9tyEfy9","tjQxsZUnqt",
-"WPmlx16lHc","gjUTuM3zXL","K4GS85Drn0","tlILtiqv4k","jS1ajOz8yZ","KsjRKCK5W7","M3zXLdjsrv","rKDLJWreyP","BGaQYmX2GE","CdyBVHRxd8",
-"9eoRcYf2Ec","s93MlSbRYy","W3VFHjzUqR","uTacxlj07Q","KASQ8ThjNn","yofH3pv0i7","45cIHIRh48","In3NSSs0Zu","RxrsmuoStw","gdQsSwiHrZ",
-"euZA5s93Ml","fcwDaZJTXH","fLNg8Yw2oU","IRh48uvf7A","d85a9LbRTH","Cfgr3Mm8si","d7vjMDG4sT","RmDcratef2","Vprf2NcICA","QbxXcsoy9t",
-"8TxD7Pb1pa","ECMvUIjTwP","lpF6WpWiOs","xciqpFVMxo","uvf7A16lHc","WreyPAkKTk","yToGWmX2GE","0Wr5yjiVBP","VjCZqkZANm","pFrrluAWyp",
-"uQIcz4dEz6","4W0Tl4dEz6","5nmWvIRh48","xciqp3otm6","3otm6XyPZN","BpYhVXyPZN","4W0TlYjB9t","bgJAz9y4lw","JRJQBThjNn","NhXduFLsph",
-"soy9tvkCHH","lj07QCIShG","F6PT2P6bcg","ZUnqt0BmCy","29QAz7X3uy","lH1ktQClRL","LbRTH29QAz","Q6LixYw2oU","pWiOs5Drn0","2DREsCfgr3",
-"07n1c9XyT9","QnJ1S8cVD3","3weIFECMvU","QssNCbgJAz","ZzJHWe6e4z","v2eC3brhlQ","KZamH580YD","SjskQ1v5hH","S77LHn1pmO","JJs5mix74r",
-"4QMc9n8pJ9","v8yFNhE1Ql","MaJQsU3yw5","CNHmvSbRYy","GXdoHuJScX","ru4UGiwzGk","k85AeaFFss","ydG8UciuWz","qQxHPxciqp","Chuy3dpe1v",
-"IBe8kn8pJ9","tvdkDdpe1v","gjUTudjsrv","0BmCyFNYIM","gIYvEStlDJ","BCxeCb29RJ","B3qemnnP8o","No0Qba00b5","vOqCEpAhR1","atef29rlg9",
-"oGu6xydG8U","OUYuFVNCPd","29QAzJXljW","TXQ0Z7X3uy","8FmFHECMvU","ZuDtDQssNC","RkQkeoVQp6","zFgtBHzZT8","MmsIoVNCPd","jiVBP6AFT0",
-"9rlg9MmsIo","wiHrZIn3NS","Yf2Ecuvf7A","a00b5tuDyS","zmLYD64s8N","Pb1papv0i7","2ZHdkMm8si","zQt6QNhXdu","9eoRcRkQke","taOXK7Ow5C",
-"SWfouOz8yZ","cL0aEPb1pa","t59lRpiJSk","C2IrcGWqqX","lweGyEOE1o","Cp3mZtjQxs","Twanodjsrv","8U2nUGrDg7","IBe8kL7cGc","6AFT0In3NS",
-"RBhp0dhSuH","hYBCKt59lR","QworuRmDcr","IjTwPuvf7A","VNCPdsuY4x","3otm6pmeCd","RzaZA5VZjS","lj07QSjskQ","W7cTsZUnqt","v8yFNS2Dfu",
-"Yw2oUCIShG","GXdoH8xEKz","QbxXcOUYuF","JRJQBuLtKs","0ao3lYjB9t","jSjS3s7Mxk","x3LDeRBhp0","Zv7z0LDk6f","W7cTsAgJHQ","iwzGkZhwG1",
-"Pb1panFqik","uvf7AVLTy6","pmeCdm4bxU","brhlQTCgPp","sx5GlJkzUn","SWfouqQxHP","WPmlxuN6r3","14FLRqUJMd","EdBKcnFqik","gf8rIFLsph",
-"LewvMhUTw7","YOfrYEdBKc","nFqikStlDJ","ThjNngtCA5","lCMxyvLsmS","U3yw5618Di","64s8N0Kyfs","cQOnvHlUbF","CK5W7zbIYY","In3NSRkQke",
-"blLA9LewvM","Mm8siuupzk","hSSvQpWiOs","MojnPJXljW","X6PinDz1R3","IRh48zz4ZU","CqqaDB3qem","tuDySNo0Qb","2hEEUZhwG1","7X3uyQClRL",
-"ciuWz7fsYM","s93MlChuy3","Cp3mZDcpWB","FLsphF6PT2","SjskQdQ586","yofH3dhSuH","AmdQdcQOnv","zbIYY0h1b1","BFkb8G1RhS","VLTy6OUYuF",
-"jeskSFGzgp","ksJbyMojnP","RmDcrBFkb8","taOXKMm8si","S2DfuKASQ8","Chuy3hSSvQ","soy9tCqqaD","2NslmIKxdL","7hyVvP6bcg","BCxeCSbRYy",
-"7X3uyfaHir","EoToP2ZHdk","lCMxyIn3NS","C2Ircn8pJ9","0ao3lRzaZA","rhl0JoQ87r","J2mQi14FLR","IRh48FNYIM","jSjS35Namm","YOfrYKr8ys",
-"pmeCdzz4ZU","D6rByZUnqt","Cp3mZ16lHc","e6e4zokgRi","JIqXi9y4lw","S77LHn8pJ9","uZPqge6e4z","D6rByCdyBV","SmGzvMkgy8","fLNg8S77LH",
-"8cVD3BbwgA","uAWypMezSW","cmXIXYf2Ec","cQOnvI7p2a","0PktI0PktI","AXpwE8xEKz","5drc6tAOsr","lweGy6AFT0","QbxXcTa8f6","AgJHQ8xEKz",
-"9XyT9Qworu","Dz1R3lsQGo","DQimpSmGzv","8xEKzi3pyd","HlUbFzz4ZU","h1zcHDG4sT","x3LDei7WMQ","MaJQsSjskQ","djsrvXflUq","soy9thSSvQ",
-"Q6LixjiVBP","VIlwPfcJOy","vkCHHWreyP","Twano0MR5X","ZJTXHhSSvQ","DG4sTmz8gx","2Yz7ENhXdu","QYxC0FjHXR","BFkb8pvgjS","6AFT0gjUTu",
-"0BmCyfFDrJ","atef20MR5X","VBjhzOHaBz","zHF1qcQOnv","M3zXLaL6AJ","vkCHHhe9IA","Y1mC0aL6AJ","0YAGHaDGtS","aFFss7hyVv","jfREuZv7z0",
-"0ao3lFcWrW","RxrsmtvdkD","nlaBy618Di","0Wr5yCxVEf","MmsIo7X3uy","uvf7ASWfou","Y1mC0L7cGc","ulk41taOXK","sqVrfXflUq","cQOnvqQxHP",
-"pT8wu48cHL","Kr8ysQ6Lix","ECMvUlweGy","VNCPdCqqaD","1LB1LCIShG","FVMxoNo0Qb","StlDJRpBQm","pAhR1QClRL","2NslmlXFOB","QworuQClRL",
-"jS1ajDcpWB","SbRYygtCA5","07n1ctaOXK","faHirulk41","W7cTsFGzgp","NAFuwuvf7A","mz8gxrKDLJ","16lHcYf2Ec","HfyNQydG8U","x3LDeCIShG",
-"14FLRUmaEv","zFgtBFnPFB","y94nw9y4lw","FLsphD6rBy","0BmCyGSQwj","KsjRKt59lR","OHaBzJKWYR","8xEKzmX2GE","IRh48M6qcG","Oz8yZprNT6",
-"580YDxXTI4","MK07YfcJOy","IKxdLNAFuw","uN6r345cIH","DLhzMWPmlx","FFDui5IhmG","ZUnqtOHaBz","3weIFlm0pD","Twano0h1b1","yToGWpmeCd",
-"OUqFMAXpwE","RACujhE1Ql","14FLRS2Dfu","LewvMVNCPd","BGaQYtuDyS","0YAGHdjsrv","d85a9gdQsS","ogLgcfLNg8","5Mg9r4QMc9","pWiOs2hEEU",
-"ZJTXHB3qem","WPmlxk85Ae","l83UdS77LH","5Mg9rv1Hln","F6PT2mX2GE","Pb1pa6q6L9","zbIYYAOgEe","G1RhSaFFss","F6PT2MGlTF","TXQ0ZSjskQ",
-"qUJMdjfREu","AgJHQnlaBy","brhlQM3zXL","F6PT2lm0pD","8U2nUL7cGc","EoToPyToGW","JIqXiZJTXH","EdBKcyvOMI","t59lRCK5W7","lXFOBBCxeC",
-"lViBvzHF1q","48cHLCqqaD","Cp3mZFVMxo","1j5L8ReKEW","VBjhzBpYhV","NOHszZv7z0","IRh487lUXZ","fcJOysqVrf","qQxHPRpBQm","ZzJHWpmeCd",
-"guMb8WmadA","OHaBzNcICA","I7p2azQt6Q","CdyBVVLTy6","Q6LixAOgEe","EOE1oTCgPp","Oz8yZxReec","mX2GEJKWYR","QbxXcZv7z0","XyPZNoQ87r",
-"zY1GYMkgy8","jzUqR8cVD3","suY4xni2v1","JIqXilViBv","yToGWiqv4k","zY1GYTXQ0Z","wiHrZP6bcg","t98iWvLsmS","oQ87rhi5X7","9rlg9iwzGk",
-"fmIK1ix74r","zQt6QhUTw7","gf8rIGrDg7","8TxD7ksJby","LDk6f8RCUA","VerEAs4786","MaJQsVLTy6","7X3uypmeCd","ReKEW8cVD3","jtn0XCfgr3",
-"FNYIM9iGoT","lXFOBlXFOB","5VZjSFjHXR","JKWYRyofH3","cmXIXHP433","SmGzvFxX9q","64s8N8U2nU","SWfouzbIYY","rKDLJOxWIH","4W0Tljtn0X",
-"FcWrWn1pmO","uTacxAOgEe","WaWsvlm0pD","5iGN5xciqp","KZamHS2Dfu","7fKYUuvf7A","07n1cAIYUu","v2eC316lHc","TCgPpVjCZq","Kr8ysl83Ud",
-"zqH0WoQ87r","okgRiAgJHQ","pmeCdkB5nP","d7vjMDLhzM","d7vjMPOUYS","XflUqW7cTs","nlaBylsQGo","a00b5k85Ae","WDVWJZzJHW","Y1mC0gdQsS",
-"XyPZN3weIF","uQIczFcWrW","wiHrZStlDJ","DG4sTjtn0X","4dEz6MaJQs","sx5GlGWqqX","VjCZqThjNn","vLsmS3weIF","bgJAzzQt6Q","S2DfuYOfrY",
-"M3zXLS2Dfu","Gv3FqzQt6Q","HRxd8AOgEe","NhXduUmaEv","h1zcH5IhmG","8U2nU4W0Tl","48cHL2DREs","lj07QfFDrJ","qQxHPdpe1v","RACuj24ARF",
-"RmDcrlpF6W","8cVD3yluBx","pFrrlMm8si","16lHcbrhlQ","FNYIMuupzk","sqVrfDcpWB","MaJQsjtn0X","zz4ZUru4UG","nnP8ocL0aE","5drc68xEKz",
-"EdBKcuupzk","CqqaDHzZT8","MojnPNhXdu","sqVrftuDyS","ECMvUFxX9q","JRJQB1LB1L","hi5X7jSjS3","14FLRMmKGJ","Kr8yssqVrf","ru4UGYf2Ec",
-"16lHclsQGo","QWxoT0h1b1","EdBKcvkCHH","mX2GE0ao3l","lViBvx3LDe","lj07QUl4a1","uLtKsW3VFH","GrDg71LB1L","dQ5867X3uy","CxVEfM3zXL",
-"fcwDaChuy3","IjTwPgtCA5","Kr8ysQbxXc","Cp3mZnFqik","dpe1v5drc6","DLhzM4QMc9","fcwDarz7Ut","pv0i7ru4UG","uvf7AmX2GE","8TxD75Namm",
-"W3VFHd7vjM","BpYhVQ6Lix","lsQGo580YD","Twanoatef2","Mkgy8s93Ml","KASQ8MK07Y","taOXKv8yFN","FcWrWG1RhS","K4GS87fsYM","7Ow5CB3qem",
-"FhtglcmXIX","CK5W79iGoT","AIYUuFxX9q","0KyfsUvlv4","s4786yToGW","d85a9IjTwP","iB08ln8pJ9","XflUqFxX9q","tl72WZJTXH","WDVWJo8Uyd",
-"FPfSEDLhzM","prNT6580YD","Z4I1vqUJMd","FFDuisoy9t","JKWYRQ6hMC","fcJOyksJby","hi5X78xEKz","P6bcgs93Ml","K20wKlm0pD","5nmWvNOHsz",
-"5VZjSDcpWB","dmoS7rKDLJ","GXdoH2Nslm","MaJQss93Ml","Mkgy8IKxdL","VBjhzX6Pin","45cIHvkCHH","0h1b15iGN5","ECMvUMkgy8","pAhR1FnPFB",
-"M3zXLnlaBy","ogLgcRzaZA","HlUbFRBhp0","9rlg9PYBf4","Q6hMC6q6L9","0h1b1hSSvQ","QnJ1Siqv4k","8TxD7VIlwP","rhl0J0YAGH","lpF6WFVMxo",
-"bgJAzSs0Zu","zz4ZUZJTXH","55rfB8U2nU","okgRiCdyBV","jSjS3qaofN","ThjNnzY1GY","tvdkD0h1b1","gdQsS0h1b1","uQIczpFrrl","zQt6QyEfy9",
-"qQxHPSmGzv","VIlwPP6bcg","WPmlxn8pJ9","7ku1pIRh48","FGzgpaDGtS","RmDcrlkMUA","IjTwP8hJdt","nFqikGrDg7","580YDYw2oU","MmsIobgJAz",
-"uZPqgcL0aE","Kr8ysFnPFB","FcWrWL7cGc","aL6AJnnP8o","sqVrfOUqFM","s4786FLsph","QWxoThi5X7","NAFuwogLgc","MojnPMmKGJ","cShY2cL0aE",
-"FcWrWbZLvS","aez9yi7WMQ","M6qcGAXpwE","n1pmOFFDui","3weIFNo0Qb","M3zXLYjB9t","QbxXcGWqqX","MojnPokgRi","dpe1v9GXkX","SWfoutlILt",
-"5Drn0YOfrY","CxVEf5Namm","9y4lwDLhzM","POUYS5iGN5","tlILtRpBQm","QbxXchUTw7","WmadAOUYuF","7hyVvtuDyS","MaJQsHRxd8","fFDrJNAFuw",
-"ZuDtDEoToP","gtCA5JIqXi","8hJdtL7cGc","ogLgcIRh48","gtCA5Ul4a1","t59lR7lUXZ","5IhmGjzUqR","MezSWi3pyd","e6e4zvOqCE","K4GS8l83Ud",
-"JkzUnuTacx","iqv4kRmDcr","0ao3lbrhlQ","J2mQiFGzgp","ZhwG1tl72W","ni2v1yToGW","b29RJ8hJdt","G1RhSGrDg7","yEfy9zbIYY","W7cTsMK07Y",
-"m4bxUZzJHW","9XyT94dEz6","6AFT0hSSvQ","DQimp55rfB","e6e4zPYBf4","pWiOsD6rBy","9GXkXsqVrf","GWqqX29QAz","rz7UtRzaZA","soy9tIRh48",
-"Dz1R3F6PT2","lsQGozz4ZU","FNYIMiqv4k","uQIczlm0pD","6AFT0AOgEe","618Dio8Uyd","zmLYD45cIH","CK5W7BCxeC","SmGzv8cVD3","5iGN5ni2v1",
-"0ao3l1j5L8","Q6hMCyvOMI","POUYSBGaQY","YOfrYCfgr3","LewvMvLsmS","CIShG5Drn0","S77LH2TRI7","JIqXi618Di","16lHcYjB9t","G1RhSuZPqg",
-"RsQUqfFDrJ","EOE1o24ARF","ECMvU1j5L8","vkCHHGWqqX","9eoRclweGy","fLNg8tvdkD","XflUqMmsIo","dQ586azIWp","JIqXiyofH3","oQ87rd7vjM",
-"OxWIHlXFOB","FjHXRRsQUq","UmaEvfmIK1","Zv7z0WMiS3","VBjhz07n1c","EOE1ot98iW","FwEJzJ2mQi","GSQwjl83Ud","CK5W70h1b1","e6e4zpmeCd",
-"LbRTH4W0Tl","vkCHHCxVEf","Oz8yZtvdkD","Uvlv4RBhp0","Mkgy8FFDui","uAWypfcwDa","Yf2EcGrDg7","uAWypqUJMd","WPmlx0YAGH","azIWplpF6W",
-"KsjRK1j5L8","FFDuiRsQUq","BbwgAUlU3M","gdQsSAkKTk","FjHXR48cHL","OUqFMcQOnv","OxWIHzY1GY","s4786RACuj","7lUXZ2Nslm","RzaZAhYBCK",
-"ZhwG1UmaEv","9XyT9NAFuw","FjHXRDcpWB","L7cGcru4UG","Dz1R3VBjhz","nlaByv2eC3","tl72Whe9IA","zHF1qfcJOy","s93MlnFqik","8FmFH4dEz6",
-"iqv4kbrhlQ","RzaZARsQUq","n8pJ9VLTy6","gIYvEa00b5","6q6L9iqv4k","OxWIH3weIF","hYBCKHlUbF","gIYvENhXdu","OxWIHvLsmS","pmeCdMojnP",
-"RmDcrAIYUu","qaofN4QMc9","s7MxkHRxd8","a00b5MK07Y","PYBf4ogLgc","rhl0JSbRYy","5IhmG5Mg9r","Waim6OxWIH","fcJOyv1Hln","QWxoTtAOsr",
-"SjskQvLsmS","rKDLJKZamH","AXpwEFPfSE","8cVD3618Di","5iGN5fmIK1","t59lRFLsph","m4bxUpAhR1","Vprf2I7p2a","BCxeC0Kyfs","AgJHQfqypy",
-"d85a9FnPFB","QYxC08FmFH","yofH3UmaEv","x3LDe16lHc","s93Ml7fsYM","0BmCy9iGoT","9iGoTMGlTF","Twano1v5hH","fcJOytuDyS","XyPZNxReec",
-"uQIczzQt6Q","1j5L8iKqhr","BpYhVrKDLJ","x3LDeoGu6x","Q6hMCnFqik","OxWIHfmIK1","qaofN7fsYM","wDajXPb1pa","CqqaD0BmCy","Kr8ysBCxeC",
-"Y1mC0Y1mC0","uupzkxReec","b29RJatef2","RkQkeiKqhr","hYBCKCp3mZ","brhlQdmoS7","48cHL16lHc","aFFsspvgjS","soy9t5drc6","6AFT00Kyfs",
-"Mkgy8ru4UG","618DiXyPZN","MGlTFzqH0W","TXQ0ZwDajX","5drc6XyPZN","cShY2hSSvQ","B3qemoQ87r","uoStwru4UG","xciqpMojnP","EOE1oHfyNQ",
-"cmXIXlj07Q","piJSkmz8gx","ciuWzNOHsz","HzZT8zbIYY","fqypyB3qem","24ARFuoStw","iKqhrU3yw5","uAWypCdyBV","SbRYykB5nP","FPfSEMezSW",
-"NcICAZJTXH","sqVrfiwzGk","blLA9S2Dfu","5drc6CIShG","jfREuOHaBz","yvOMIcQOnv","0ao3lxciqp","blLA9JKWYR","Dz1R348cHL","ZzJHWRpBQm",
-"WPmlxaDGtS","24ARFIBe8k","W7cTsFPfSE","OHaBzZUnqt","HfyNQKr8ys","Yw2oUuoStw","m4bxU2DREs","aDGtSCK5W7","8U2nUDcpWB","8FmFH1v5hH",
-"Ta8f6jtn0X","Chuy3ciuWz","fcwDaBFkb8","Uvlv4b29RJ","YOfrYDz1R3","ZhwG1CNHmv","FhtglOHaBz","1v5hHZUnqt","FLsphVNCPd","FGzgpkZANm",
-"WMiS3dQ586","Waim6jSjS3","Vprf2pAhR1","WDVWJSs0Zu","9GXkXGv3Fq","FxX9quupzk","ciuWzQ6hMC","UlU3Mm4bxU","W7cTsKASQ8","lXFOBAXpwE",
-"KZamHoQ87r","U3yw5RACuj","euZA55IhmG","JKWYRbZLvS","CNHmv2Nslm","xciqpzY1GY","6q6L9oVQp6","5VZjSlViBv","P6bcgVBjhz","jSjS3k85Ae",
-"WreyPzbIYY","4dEz65Mg9r","5ZaEz9y4lw","tlILtrz7Ut","jfREuMaJQs","qaofNmz8gx","Ss0ZuLbRTH","NAFuwzHF1q","0YAGHl83Ud","SjskQYh1hF",
-"MmKGJIKxdL","WMiS3OUYuF","Oz8yZCxVEf","S77LHi7WMQ","zQt6QCxVEf","jfREuJXljW","16lHcG1RhS","bZLvSJIqXi","M6qcG7lUXZ","l83UdzqH0W",
-"4dEz6S77LH","8RCUA5nmWv","hE1Qlsoy9t","RxrsmOHaBz","FPfSEn1pmO","0YAGHlkMUA","ogLgcIBe8k","XyPZNvOqCE","LbRTH8TxD7","mz8gx2Nslm",
-"TXQ0ZkZANm","yofH3BCxeC","BGaQYdpe1v","AkKTkeuZA5","EOE1o8TxD7","BbwgAMGlTF","guMb8AXpwE","UlU3MXflUq","2TRI7FnPFB","jtn0XVLTy6",
-"U3yw529QAz","e6e4ziwzGk","ZzJHWgjUTu","45cIHRpBQm","No0Qb5Drn0","JIqXiCdyBV","QChxs29QAz","mz8gxBFkb8","AkKTkAkKTk","fcJOyVjCZq",
-"K4GS8zHF1q","VerEAECMvU","HfyNQ5IhmG","1j5L82hEEU","AmdQdv8yFN","aez9yyEfy9","bgJAzYw2oU","GrDg75VZjS","azIWpQnJ1S","QChxslm0pD",
-"POUYSyvOMI","QnJ1SkZANm","WreyPQssNC","M3zXLokgRi","5IhmGfmIK1","rKDLJulk41","lXFOBuAWyp","0BmCy2ZHdk","tAOsrgtCA5","Cfgr3jS1aj",
-"lj07QSbRYy","FnPFB5IhmG","VNCPduupzk","8TxD7hi5X7","uAWypKASQ8","lkMUAd85a9","dQ5867fKYU","HzZT8FGzgp","RBhp01LB1L","S2DfuVprf2",
-"4dEz6SbRYy","LbRTH8hJdt","uoStwPb1pa","cmXIXvkCHH","HRxd8CIShG","EdBKcyofH3","J2mQiPb1pa","yluBxsuY4x","24ARFMGlTF","ThjNnpT8wu",
-"DcpWBVBjhz","580YDs7Mxk","29QAzRkQke","RpBQmdQ586","MmKGJi7WMQ","JXljWZJTXH","tvdkDxXTI4","uPX7GQWxoT","SmGzv1LB1L","lCMxyAIYUu",
-"ogLgcbgJAz","29QAzZ4I1v","0ao3lv2eC3","xXTI42hEEU","9rlg9dQ586","RkQkeFwEJz","14FLRsoy9t","1v5hHhi5X7","JJs5mECMvU","55rfBAgJHQ",
-"wiHrZOHaBz","WMiS3618Di","aL6AJAIYUu","s7Mxk7X3uy","m4bxUgf8rI","bZLvSFPfSE","8xEKzDQimp","U3yw5hSSvQ","sqVrfwiHrZ","mz8gxW7cTs",
-"i7WMQyToGW","S77LH5VZjS","rKDLJSbRYy","zqH0WOUYuF","TXQ0ZQYxC0","fcwDalCMxy","zbIYYnlaBy","RpBQmfqypy","M3zXL0YAGH","OUYuFDG4sT",
-"ZzJHWpT8wu","ThjNnF6PT2","XflUqyToGW","DcpWBdmoS7","FPfSEJ2mQi","5ZaEzDG4sT","5ZaEzSs0Zu","s7MxkFnPFB","WreyPVBjhz","S2Dfu9rlg9",
-"EoToPBCxeC","hUTw7RkQke","jiVBPs93Ml","JJs5mdjsrv","ZJTXHTXQ0Z","StlDJPb1pa","qUJMdUlU3M","mX2GE0YAGH","Yw2oUdhSuH","lm0pDKr8ys",
-"4W0TlHzZT8","0ao3lSbRYy","ru4UGrKDLJ","1LB1LU3yw5","EOE1oqQxHP","mX2GElj07Q","JXljWrz7Ut","zQt6QD6rBy","No0QbydG8U","s7MxkzbIYY",
-"QssNCDLhzM","gdQsSksJby","618DiCqqaD","5drc6I7p2a","2DREsMkgy8","JXljWZUnqt","NAFuwRxrsm","GSQwjiB08l","rz7UtZhwG1","d7vjMgdQsS",
-"Z4I1vzY1GY","GrDg7lj07Q","nnP8oNcICA","CNHmvS2Dfu","fmIK1WreyP","07n1cv8yFN","MmsIol83Ud","jSjS3QYxC0","qaofN0Kyfs","s7MxktjQxs",
-"4dEz6JKWYR","n1pmOAgJHQ","zY1GYjS1aj","s7Mxka00b5","Cp3mZG1RhS","7ku1pJJs5m","nnP8oZzJHW","DLhzMprNT6","oQ87rh1zcH","RACujFhtgl",
-"iqv4kv1Hln","Q6Lixt98iW","618DiCdyBV","CNHmvOUYuF","YjB9tMK07Y","yEfy9MmKGJ","1v5hHFNYIM","OUYuFZJTXH","uLtKs1j5L8","Q6LixZUnqt",
-"lpF6WMmsIo","fcJOy2DREs","nlaBySjskQ","0KyfspAhR1","dhSuHo8Uyd","zHF1qgdQsS","uAWypOUYuF","P6bcgmz8gx","jzUqRJRJQB","Yw2oUulk41",
-"sx5GltvdkD","5Drn0WMiS3","AXpwEblLA9","zFgtBZUnqt","ru4UGyToGW","pT8wuM3zXL","n1pmOAmdQd","MmsIos7Mxk","yofH3WmadA","Yh1hFzY1GY",
-"OxWIHBpYhV","OUYuFIjTwP","POUYSGWqqX","gtCA5HfyNQ","dmoS7uvf7A","h1zcHlm0pD","24ARFbZLvS","a00b5Kr8ys","BbwgAOHaBz","lj07QKZamH",
-"5IhmGDQimp","lViBv5ZaEz","Uvlv4yvOMI","HzZT85ZaEz","zbIYYqQxHP","7Ow5CM6qcG","lH1kt0h1b1","faHirU3yw5","QYxC04W0Tl","y94nw6AFT0",
-"IBe8kFLsph","zz4ZUsx5Gl","oGu6xgdQsS","zFgtBVBjhz","lkMUAFVMxo","ReKEWBGaQY","3weIFEOE1o","4dEz6jiVBP","ZzJHWEoToP","Twanob29RJ",
-"yluBxCIShG","IRh48b29RJ","GWqqXdpe1v","Z4I1vuTacx","Pb1paWMiS3","ZJTXH45cIH","1LB1LfFDrJ","piJSkYOfrY","jeskSwiHrZ","pFrrlCK5W7",
-"yluBxhi5X7","jfREuJJs5m","29QAzx3LDe","2hEEUcmXIX","brhlQ8RCUA","pAhR1h1zcH","RkQkeVerEA","aDGtSNOHsz","0YAGHFjHXR","wDajXyEfy9",
-"yEfy97fKYU","n8pJ9lm0pD","aFFss618Di","GSQwjQClRL","aDGtSjS1aj","5iGN5nlaBy","ECMvUeuZA5","oVQp6HzZT8","Pb1paKASQ8","NhXduv8yFN",
-"ZUnqta00b5","zY1GYBpYhV","uAWypZ4I1v","MezSWy94nw","wiHrZdpe1v","e6e4zNhXdu","VjCZqlkMUA","GrDg7RzaZA","F6PT2fmIK1","LDk6fk85Ae",
-"wiHrZFPfSE","kB5nP5ZaEz","faHirgjUTu","iB08lksJby","vkCHHd85a9","Kr8ysiqv4k","B3qemuAWyp","2Yz7EWmadA","W7cTsqUJMd","AIYUuG1RhS",
-"L7cGcTXQ0Z","RBhp0BbwgA","KsjRKgdQsS","8cVD3MojnP","HzZT80ao3l","MmKGJxciqp","ZzJHW2Yz7E","OUqFMQ6Lix","i7WMQQChxs","FjHXRCIShG",
-"BGaQYFFDui","zHF1qprNT6","uJScXGXdoH","VjCZqjS1aj","djsrvQClRL","aDGtSxciqp","Q6hMCuPX7G","KZamHTwano","VLTy6JkzUn","Waim6lj07Q",
-"hE1Qlix74r","ZJTXHrz7Ut","ZzJHWU3yw5","ulk41D6rBy","FxX9qJ2mQi","zmLYDSs0Zu","ZuDtDv8yFN","OxWIHLbRTH","OxWIHL7cGc","nFqik618Di",
-"DQimpKr8ys","jSjS3FjHXR","ZJTXHVjCZq","dQ5860MR5X","B3qemXflUq","guMb8EdBKc","GSQwjWaim6","RmDcrJIqXi","oGu6xCK5W7","uoStwpmeCd",
-"StlDJydG8U","dQ586OUYuF","QClRLHzZT8","2hEEUyToGW","8hJdt5VZjS","Yh1hFECMvU","ix74rWDVWJ","cL0aEnFqik","CxVEfuJScX","MojnPGSQwj",
-"RACujwDajX","9rlg9wDajX","h1zcH0BmCy","SjskQwiHrZ","vLsmSkZANm","O3iyQQnJ1S","fLNg8JIqXi","2Yz7EprNT6","yofH3EOE1o","pWiOsB3qem",
-"lCMxy7Ow5C","zY1GYIn3NS","pvgjSuAWyp","azIWpZuDtD","tjQxstjQxs","8FmFHOxWIH","0MR5X8hJdt","24ARFThjNn","tlILtOUqFM","taOXKZJTXH",
-"hi5X7HfyNQ","jiVBPjfREu","uoStwokgRi","QYxC0a00b5","ZzJHWguMb8","8U2nUjfREu","QnJ1S9rlg9","uupzkuTacx","UmaEvaez9y","ogLgcAkKTk",
-"BpYhVSmGzv","9eoRc7hyVv","Mkgy8AgJHQ","djsrvIjTwP","MmKGJprNT6","Z4I1voGu6x","2ZHdkQYxC0","uvf7AZ4I1v","ksJby0PktI","No0QbRACuj",
-"iB08lFxX9q","QWxoT16lHc","JKWYR2DREs","FGzgpjS1aj","cmXIXIRh48","JKWYRgIYvE","5ZaEzoGu6x","7fKYU0BmCy","UlU3MiB08l","QWxoTLbRTH",
-"TCgPpWmadA","AkKTkazIWp","faHirtl72W","uLtKsjSjS3","W3VFHjfREu","yluBxoQ87r","CdyBVrhl0J","ECMvUfFDrJ","lpF6WoQ87r","LewvMRpBQm",
-"2DREsqQxHP","JXljWv2eC3","ZzJHW9y4lw","Cp3mZJJs5m","l83UdaDGtS","0Wr5y5Drn0","xXTI4CK5W7","2Nslmxciqp","S77LH45cIH","4QMc9EOE1o",
-"a00b5RBhp0","F6PT2fcwDa","djsrv5ZaEz","M3zXLHzZT8","QClRLMmsIo","cL0aEVNCPd","ciuWzo8Uyd","uAWyp1j5L8","6AFT0m4bxU","zz4ZUBpYhV",
-"WaWsv4QMc9","tjQxsFhtgl","azIWp7fKYU","Q6LixiB08l","ThjNnSWfou","Z4I1vRACuj","EOE1oa00b5","7Ow5Cs93Ml","v2eC3rhl0J","VBjhzPYBf4",
-"2Nslm6q6L9","nlaByX6Pin","WMiS34W0Tl","Kr8ysCfgr3","StlDJVjCZq","5ZaEz0BmCy","qUJMdKZamH","MojnPKsjRK","Chuy38xEKz","t98iWv2eC3",
-"lm0pDsoy9t","2Nslml83Ud","Cfgr3jSjS3","i7WMQO3iyQ","3weIFJkzUn","F6PT24dEz6","2TRI79iGoT","7fsYMnFqik","24ARF2Yz7E","gf8rIsqVrf",
-"55rfBOz8yZ","Ul4a1BFkb8","POUYS0YAGH","QClRLn1pmO","Cfgr3tAOsr","2hEEU580YD","dmoS7EoToP","SbRYyciuWz","ni2v1JkzUn","FhtgljS1aj",
-"fqypynnP8o","AgJHQb29RJ","a00b5GXdoH","UlU3MfmIK1","TXQ0ZI7p2a","6q6L9uTacx","IBe8kPb1pa","rKDLJBCxeC","2Yz7En1pmO","d7vjMP6bcg",
-"NAFuwFnPFB","FwEJzpmeCd","U3yw5IRh48","OUqFMfaHir","8TxD78TxD7","NAFuwIKxdL","rhl0JG1RhS","4dEz6x3LDe","pmeCdiwzGk","JJs5mgdQsS",
-"pvgjSlH1kt","SWfouDLhzM","MezSWiqv4k","piJSkgjUTu","s93MlYjB9t","taOXKFVMxo","0BmCy7hyVv","NOHszY1mC0","ogLgcGWqqX","v8yFNRkQke",
-"tjQxsFwEJz","xXTI43otm6","0h1b1LDk6f","ZUnqtBbwgA","vkCHHBbwgA","lViBvlH1kt","hSSvQDcpWB","e6e4zzQt6Q","Kr8ysZUnqt","tl72WFjHXR",
-"55rfBS2Dfu","JXljWzFgtB","Ss0ZuYjB9t","uvf7AReKEW","zqH0WjSjS3","jiVBP9GXkX","1LB1Lhe9IA","K4GS8SWfou","lsQGo2Nslm","2ZHdkXyPZN",
-"zQt6QcmXIX","vLsmSYh1hF","yvOMIqUJMd","8TxD7Yw2oU","EoToPtaOXK","rhl0JBFkb8","8TxD7pv0i7","pmeCdRpBQm","azIWpBGaQY","Pb1payluBx",
-"wDajXiqv4k","NhXdu16lHc","L7cGci7WMQ","cQOnvgIYvE","UlU3M4W0Tl","NcICABbwgA","zqH0WZ4I1v","v8yFNTwano","fmIK1Uvlv4","s4786jiVBP",
-"SmGzvguMb8","FNYIMgtCA5","FGzgpHzZT8","8RCUARACuj","Z4I1vhe9IA","pvgjSIBe8k","5ZaEzlViBv","DG4sTnlaBy","okgRiUlU3M","iB08lnFqik",
-"POUYSuZPqg","uN6r30ao3l","k85AeUlU3M","nnP8oVNCPd","hE1Ql5Drn0","uupzkhe9IA","jS1aj5IhmG","lkMUAd7vjM","zY1GYWaim6","X6Pins4786",
-"a00b5CqqaD","gdQsSPb1pa","lkMUAtlILt","NhXduiKqhr","AmdQd45cIH","D6rByrKDLJ","piJSkuoStw","djsrv5IhmG","SmGzvpv0i7","In3NSFNYIM",
-"dmoS7MojnP","F6PT2Gv3Fq","9y4lwLDk6f","n1pmOQChxs","zz4ZUfqypy","JJs5mxXTI4","5iGN5WaWsv","DcpWBmz8gx","GWqqXdhSuH","VBjhzXyPZN",
-"gtCA5XyPZN","MezSWd7vjM","AIYUub29RJ","K20wKokgRi","nFqikReKEW","48cHLLbRTH","EoToPKsjRK","jtn0XhE1Ql","ZzJHWt98iW","DQimp2TRI7",
-"tlILtHlUbF","iwzGksuY4x","RBhp0tlILt","FLsphsx5Gl","64s8N5ZaEz","JRJQB45cIH","rKDLJiwzGk","M3zXLsuY4x","64s8Nt98iW","0KyfsO3iyQ",
-"O3iyQIKxdL","5nmWvqQxHP","l83UdNOHsz","0BmCyX6Pin","faHirHlUbF","ThjNnXflUq","HzZT8FNYIM","0KyfsSWfou","AOgEeix74r","JRJQBfFDrJ",
-"1j5L8faHir","x3LDeHlUbF","i7WMQzHF1q","QYxC0Mkgy8","OUqFMJKWYR","hUTw7faHir","RxrsmVjCZq","uTacx7fsYM","IBe8kQYxC0","hYBCKgdQsS",
-"cQOnvjtn0X","16lHcUl4a1","QbxXcEdBKc","StlDJRxrsm","pv0i7dhSuH","F6PT2XyPZN","KASQ83otm6","kZANmjeskS","SmGzvtlILt","xXTI4uN6r3",
-"pmeCd0h1b1","xXTI4SbRYy","S77LH8hJdt","Kr8ys4W0Tl","YjB9tZv7z0","oGu6x580YD","d85a9iwzGk","OUqFM2DREs","No0QbYw2oU","DG4sTnFqik",
-"YOfrYjiVBP","VNCPdlweGy","1j5L8VBjhz","RpBQmYOfrY","Z4I1vD6rBy","ECMvUzbIYY","CNHmvOxWIH","Yf2EcPOUYS","kB5nPFjHXR","aDGtS24ARF",
-"8cVD3yvOMI","qaofN618Di","ZzJHW48cHL","pFrrla00b5","QYxC0jiVBP","aL6AJjS1aj","fLNg8Gv3Fq","WreyPuJScX","fmIK1O3iyQ","BCxeChUTw7",
-"JJs5mhe9IA","ydG8UJKWYR","Uvlv47fKYU","dQ5860BmCy","xciqp48cHL","XyPZNdpe1v","BGaQYQWxoT","pWiOsyluBx","tlILtW7cTs","mz8gxfFDrJ",
-"CxVEfjtn0X","TXQ0ZBCxeC","No0QbAIYUu","hSSvQRmDcr","AgJHQo8Uyd","aez9yCqqaD","W7cTsCp3mZ","ZuDtDjiVBP","ru4UGaL6AJ","tl72WBpYhV",
-"gtCA5RBhp0","1LB1L7ku1p","faHirS77LH","RpBQmVIlwP","VBjhzCdyBV","0PktIOz8yZ","jfREuRxrsm","uLtKsn8pJ9","45cIHYw2oU","hUTw75ZaEz",
-"aDGtSFjHXR","3weIF7lUXZ","oVQp6lm0pD","5Drn02DREs","BGaQYTCgPp","y94nwRkQke","hYBCKY1mC0","Yh1hF4dEz6","B3qemGXdoH","uAWypcQOnv",
-"gf8rICxVEf","S77LHSs0Zu","CIShGKASQ8","GXdoHuPX7G","jSjS3m4bxU","OUYuF6q6L9","9GXkXYf2Ec","oGu6xCdyBV","yEfy9MaJQs","RzaZAK20wK",
-"24ARFgIYvE","0h1b1Cp3mZ","OHaBzKsjRK","wDajXEOE1o","o8Uyd3weIF","Nxx9VIKxdL","ZUnqttlILt","lkMUAWaim6","GWqqXYOfrY","s7MxkRmDcr",
-"D6rBycQOnv","WPmlxlj07Q","zY1GYsoy9t","uQIcz0MR5X","cShY28FmFH","M6qcGtjQxs","uvf7AQworu","zbIYYjfREu","5ZaEz1j5L8","euZA5hSSvQ",
-"zqH0Wxciqp","uupzkVLTy6","MGlTFt98iW","djsrv6AFT0","8xEKzAXpwE","lpF6WiB08l","7X3uypvgjS","hE1QlEOE1o","3weIFCfgr3","taOXKXflUq",
-"WaWsvP6bcg","M6qcGVprf2","CK5W7Yf2Ec","n8pJ9uPX7G","6AFT0DLhzM","GWqqXtuDyS","lm0pD29QAz","d7vjML7cGc","dhSuHI7p2a","QChxsyvOMI",
-"No0Qb45cIH","W3VFHyluBx","pAhR1jfREu","EoToPCp3mZ","1v5hHJKWYR","FFDuivLsmS","IRh48JIqXi","QClRLNOHsz","zFgtBuTacx","pvgjSXyPZN",
-"pWiOsh1zcH","K4GS8faHir","1v5hHpmeCd","DQimp6q6L9","FVMxoLDk6f","piJSk0Kyfs","i7WMQCxVEf","azIWpaez9y","JIqXiVjCZq","cL0aEjeskS",
-"yToGWqaofN","I7p2aW7cTs","7ku1pPOUYS","uupzkfcwDa","UmaEvzz4ZU","jSjS3fmIK1","lsQGonFqik","hSSvQfLNg8","uupzkDLhzM","AXpwElpF6W",
-"soy9tQChxs","zHF1qv2eC3","ZhwG1D6rBy","oGu6xFnPFB","iB08llm0pD","v8yFN5Mg9r","oVQp629QAz","FNYIMFxX9q","s7MxkAkKTk","tjQxshE1Ql",
-"HzZT8b29RJ","zz4ZUMezSW","hUTw7gIYvE","L7cGcMmKGJ","uvf7A0h1b1","Yf2EcRmDcr","s93Mla00b5","tuDySuAWyp","cmXIXKr8ys","ksJbyuAWyp",
-"CxVEfatef2","QChxsgtCA5","lH1ktdhSuH","cShY2Pb1pa","nFqikFPfSE","8RCUAhe9IA","s93MlCp3mZ","1LB1L0YAGH","FGzgpAOgEe","64s8NsuY4x",
-"zFgtBU3yw5","Q6hMCb29RJ","6AFT0b29RJ","IKxdLTwano","uAWypokgRi","yvOMI7X3uy","HP433jS1aj","4QMc9nlaBy","hi5X7L7cGc","yvOMIAkKTk",
-"uLtKssqVrf","sx5GlkB5nP","9y4lwXflUq","RACujSmGzv","4W0TlBpYhV","o8UydzHF1q","RsQUqa00b5","580YDhSSvQ","FcWrWbgJAz","5VZjSprNT6",
-"qUJMdvkCHH","Dz1R3brhlQ","fFDrJlXFOB","CIShGQClRL","fFDrJokgRi","NcICAgIYvE","5nmWvkB5nP","5ZaEzSWfou","LewvMlj07Q","gIYvEXyPZN",
-"VBjhzJ2mQi","F6PT2cShY2","fcJOySs0Zu","qQxHPSbRYy","QbxXchi5X7","64s8N1j5L8","ECMvUuN6r3","J2mQi0h1b1","8RCUA4QMc9","SWfouJ2mQi",
-"Yh1hFFLsph","gjUTutuDyS","AmdQdvkCHH","55rfB5drc6","MojnPWaWsv","pAhR1fcwDa","55rfB1j5L8","BCxeCjSjS3","MezSWdmoS7","WaWsv0MR5X",
-"8RCUA7fKYU","OxWIHCxVEf","tlILtYjB9t","MGlTFbZLvS","2DREsv2eC3","WDVWJy94nw","ksJby9rlg9","07n1c64s8N","WmadAhYBCK","Nxx9VCNHmv",
-"QYxC0FGzgp","tlILt7X3uy","prNT6AIYUu","3weIFOUqFM","0KyfsBCxeC","pT8wulCMxy","0MR5Xa00b5","3weIF07n1c","580YDAmdQd","yvOMIazIWp",
-"16lHcAgJHQ","M6qcGZ4I1v","GWqqXFNYIM","xReec48cHL","xReec64s8N","14FLRjiVBP","FPfSEB3qem","FcWrW16lHc","OxWIHxXTI4","YjB9tRBhp0",
-"lH1ktaL6AJ","v2eC3POUYS","vkCHHjfREu","2Nslmrz7Ut","LbRTHIRh48","ZUnqto8Uyd","WaWsvguMb8","tjQxsfFDrJ","1v5hHuoStw","Qworuk85Ae",
-"WPmlxY1mC0","lViBvQssNC","1j5L8oGu6x","uPX7GvkCHH","45cIHGSQwj","d85a97X3uy","m4bxU07n1c","fFDrJX6Pin","CNHmvprNT6","AOgEeSWfou",
-"M3zXLjSjS3","k85AeU3yw5","AIYUuFnPFB","atef2t98iW","IBe8k64s8N","iwzGkFGzgp","9GXkXcmXIX","Gv3Fqix74r","1LB1LzqH0W","iwzGkxReec",
-"uTacxmX2GE","ogLgcTXQ0Z","MGlTFpiJSk","MmsIoMK07Y","lj07QXflUq","0h1b1Twano","EdBKczbIYY","7fsYMvOqCE","QClRLuZPqg","oVQp6Cfgr3",
-"hi5X7Z4I1v","QssNCYOfrY","L7cGcni2v1","EOE1olkMUA","JKWYRydG8U","lsQGolpF6W","qUJMdS2Dfu","QYxC0Uvlv4","xXTI42Yz7E","aL6AJuoStw",
-"QYxC01v5hH","IRh48VLTy6","i3pyd7lUXZ","a00b5Gv3Fq","zY1GYIKxdL","580YDCNHmv","iB08ls93Ml","nnP8ooVQp6","ThjNnkZANm","SWfouazIWp",
-"ogLgc5nmWv","rKDLJBbwgA","Ta8f6YjB9t","pvgjSbgJAz","prNT6FPfSE","fcJOyv8yFN","0BmCyd85a9","WPmlxS77LH","8cVD3VjCZq","NAFuwZhwG1",
-"IBe8kfcJOy","DcpWB9XyT9","QYxC0t98iW","X6PinAIYUu","KZamHcmXIX","In3NSuLtKs","aDGtSpmeCd","EoToPzY1GY","h1zcHuLtKs","Twano7fKYU",
-"JkzUnjSjS3","okgRiqQxHP","GrDg7Zv7z0","Oz8yZBbwgA","okgRiyofH3","QworuyToGW","nFqikMGlTF","uAWyp7fsYM","1v5hH8U2nU","SbRYyQYxC0",
-"yvOMIUmaEv","yEfy9NcICA","SbRYyOUqFM","uPX7GoQ87r","ZJTXHtAOsr","vLsmSCdyBV","No0QbMaJQs","QYxC0RsQUq","lViBvjtn0X","FwEJzsx5Gl",
-"EdBKc2Nslm","cShY2VNCPd","0Kyfs2DREs","D6rBy7hyVv","faHirJIqXi","9y4lwSWfou","zqH0WWaim6","9GXkX2Nslm","lH1ktlH1kt","guMb8Ta8f6",
-"GSQwjBCxeC","580YD9y4lw","kZANmFFDui","FhtglMezSW","QssNCVLTy6","KASQ8HfyNQ","ECMvUt98iW","ru4UGUvlv4","t98iWdpe1v","9iGoTMojnP",
-"fLNg8QWxoT","dpe1vUl4a1","MmKGJoVQp6","580YDY1mC0","RmDcrI7p2a","fcJOyhE1Ql","fqypyrKDLJ","Z4I1vOUYuF","RmDcr7X3uy","pv0i7GSQwj",
-"ksJbyuZPqg","1j5L8JRJQB","DLhzM5Namm","e6e4zECMvU","BGaQYXflUq","2Yz7EiKqhr","EOE1orhl0J","fcwDaVNCPd","zbIYYguMb8","8cVD3h1zcH",
-"BpYhVb29RJ","tAOsriqv4k","k85AeJ2mQi","ZzJHW8U2nU","JkzUngdQsS","K4GS8aL6AJ","OxWIHF6PT2","07n1cd7vjM","pAhR129QAz","EdBKc8xEKz",
-"CNHmvQworu","VjCZq2ZHdk","hSSvQ1j5L8","FGzgpFcWrW","M3zXLMmKGJ","Ss0ZuKZamH","CK5W7hYBCK","gf8rI0Wr5y","d7vjMQClRL","Oz8yZ7ku1p",
-"0MR5XgIYvE","b29RJFVMxo","rhl0JSWfou","7lUXZQClRL","VIlwPpv0i7","dpe1vcQOnv","hE1QlfmIK1","GXdoHt59lR","HlUbFcmXIX","BbwgAJXljW",
-"jfREupAhR1","pmeCdpWiOs","kB5nPVerEA","Dz1R3uvf7A","8cVD3fmIK1","iB08lQ6hMC","lH1ktqUJMd","o8UydhUTw7","i7WMQi3pyd","suY4xnnP8o",
-"RBhp0jeskS","pWiOseuZA5","qUJMdCdyBV","o8Uyduvf7A","aez9yOz8yZ","MojnP7hyVv","fLNg8xXTI4","FcWrWRxrsm","iwzGk2DREs","fcwDakB5nP",
-"cmXIXkB5nP","zz4ZUCqqaD","XyPZN0PktI","cShY2faHir","tlILtBpYhV","pmeCdW3VFH","n1pmOnFqik","AXpwEhYBCK","y94nwHfyNQ","gIYvEksJby",
-"HlUbFS2Dfu","yluBxOHaBz","2DREs9GXkX","IKxdLh1zcH","bgJAzlViBv","FVMxoLbRTH","nnP8oFhtgl","7fKYUlj07Q","fqypyjS1aj","CxVEfjSjS3",
-"uLtKsUlU3M","8FmFHpWiOs","ZJTXHjS1aj","Yh1hFqQxHP","AgJHQokgRi","lXFOBuupzk","jS1aj0ao3l","0Wr5ypAhR1","RBhp0ru4UG","XflUqokgRi",
-"n1pmOD6rBy","HzZT8y94nw","fLNg8EoToP","CqqaDAkKTk","Uvlv4OxWIH","zHF1q4W0Tl","lsQGo8RCUA","iB08l9eoRc","G1RhSS77LH","lsQGoOUYuF",
-"BbwgAcShY2","3weIFi7WMQ","yofH3vOqCE","n8pJ9AXpwE","KASQ8EdBKc","MmsIoMm8si","uJScXqUJMd","48cHL55rfB","HRxd8FGzgp","uZPqgI7p2a",
-"mz8gxatef2","2DREsbgJAz","guMb848cHL","IBe8kJIqXi","i3pyd9iGoT","FPfSECxVEf","kZANmMezSW","Mkgy8Y1mC0","sx5GlF6PT2","jfREuo8Uyd",
-"s4786ZzJHW","cShY2k85Ae","fLNg85Drn0","BpYhV618Di","n8pJ9AkKTk","zHF1qJkzUn","pmeCdRmDcr","mz8gxlsQGo","jiVBPKASQ8","VNCPdulk41",
-"lXFOBFcWrW","XyPZNo8Uyd","gtCA5K4GS8","L7cGc8FmFH","y94nwEoToP","GrDg79GXkX","Mm8siy94nw","KASQ8NOHsz","AOgEeVprf2","MmsIoLewvM",
-"ECMvUFGzgp","1v5hHGv3Fq","k85AeIBe8k","K20wKpAhR1","jSjS3guMb8","L7cGchi5X7","KZamHfqypy","LewvMStlDJ","G1RhS9iGoT","azIWp9y4lw",
-"d7vjMaez9y","gjUTut59lR","0MR5XyEfy9","ZuDtDC2Irc","5Drn05IhmG","tl72W7Ow5C","O3iyQwDajX","WPmlx2hEEU","djsrvQnJ1S","dhSuHqUJMd",
-"iKqhrQssNC","rhl0JXflUq","fqypyprNT6","azIWp24ARF","lXFOB7lUXZ","iqv4kAgJHQ","7ku1pk85Ae","AXpwEqUJMd","gjUTu14FLR","zHF1qlsQGo",
-"fLNg8yEfy9","i3pydt98iW","zz4ZUEOE1o","zbIYYNhXdu","OHaBzgf8rI","vLsmSXyPZN","7X3uypAhR1","n1pmOChuy3","atef2D6rBy","jeskSdjsrv",
-"zY1GYQworu","QssNCuQIcz","RzaZAIBe8k","azIWpiB08l","MGlTF9eoRc","taOXKQYxC0","5drc624ARF","YjB9tv2eC3","blLA9W3VFH","MmsIotAOsr",
-"pmeCdaFFss","8xEKzjiVBP","EoToPZJTXH","AmdQdB3qem","gdQsSAIYUu","Chuy37ku1p","euZA5F6PT2","m4bxUsoy9t","618DiaDGtS","FnPFBGv3Fq",
-"KASQ8soy9t","ECMvUXyPZN","Ss0ZuTXQ0Z","hE1QlRmDcr","1v5hHtl72W","Y1mC0CIShG","MmsIovLsmS","ReKEWdQ586","No0Qb1v5hH","jiVBPVBjhz",
-"DLhzMQ6Lix","WaWsvhi5X7","OUYuFGv3Fq","MmsIopiJSk","ru4UGbgJAz","zFgtBG1RhS","D6rBy5IhmG","WaWsvtvdkD","7fsYMaDGtS","PYBf4FVMxo",
-"i7WMQLbRTH","uupzkRmDcr","3otm68TxD7","NcICAkB5nP","FVMxoSjskQ","IKxdLFnPFB","07n1cBGaQY","pvgjSgIYvE","JXljWKASQ8","IjTwPKr8ys",
-"16lHcxciqp","zFgtB4QMc9","gjUTuVLTy6","sx5Gl07n1c","EOE1oOz8yZ","rhl0JNcICA","ydG8UZuDtD","JkzUnQWxoT","7Ow5ClCMxy","fqypyokgRi",
-"Mkgy8GWqqX","uZPqgSjskQ","J2mQicmXIX","ZUnqtOz8yZ","5IhmGFGzgp","yToGW5drc6","uvf7A3weIF","Oz8yZiqv4k","C2IrcpWiOs","GrDg7iwzGk",
-"ZJTXH4QMc9","Gv3FqOUYuF","ydG8UMojnP","9rlg9a00b5","Vprf2xciqp","8TxD7FGzgp","zHF1qAOgEe","euZA5cmXIX","Ul4a1MojnP","oGu6xxXTI4",
-"zHF1q8hJdt","pT8wuEdBKc","cQOnv48cHL","uAWypjtn0X","h1zcHWaim6","0Wr5yUvlv4","0MR5XQClRL","hE1Qlv2eC3","suY4xcQOnv","F6PT2pvgjS",
-"t98iWIjTwP","IjTwPGv3Fq","FNYIMWMiS3","JkzUnoGu6x","i3pydNcICA","WMiS3uN6r3","s7MxktvdkD","EOE1opmeCd","BbwgAFxX9q","s4786BpYhV",
-"2DREsPOUYS","QbxXcK20wK","EOE1oPYBf4","ogLgcKsjRK","MK07YTwano","FxX9qjzUqR","580YDzz4ZU","e6e4zs4786","DQimpQWxoT","580YD5Namm",
-"CqqaDQChxs","0ao3lQYxC0","k85Aelm0pD","tAOsrDz1R3","Ss0ZuGrDg7","jiVBP580YD","K20wKdQ586","lsQGotlILt","lCMxyHzZT8","aFFssd7vjM",
-"xReec2Nslm","sqVrfUvlv4","JXljWStlDJ","580YDVerEA","l83UdMK07Y","gf8rIaFFss","euZA52ZHdk","v2eC3WMiS3","RsQUqYf2Ec","LDk6ffcwDa",
-"ZhwG1MezSW","W3VFHs93Ml","4QMc9d85a9","WreyPmz8gx","ThjNn9eoRc","FFDuiydG8U","QWxoTmX2GE","1v5hHECMvU","QYxC0jtn0X","5ZaEz3otm6",
-"IRh48RkQke","FnPFB0PktI","QnJ1SG1RhS","mz8gxcL0aE","4QMc9FVMxo","BbwgALDk6f","Yh1hFjfREu","euZA5XflUq","JkzUngf8rI","pFrrluJScX",
-"48cHLprNT6","5Drn01v5hH","bgJAzZUnqt","MaJQsCxVEf","CdyBVlViBv","e6e4zNAFuw","tAOsrCNHmv","QssNCMaJQs","VerEANAFuw","5Drn0hi5X7",
-"lweGy0ao3l","uLtKs64s8N","MezSWzz4ZU","WaWsvFwEJz","1LB1LTXQ0Z","Y1mC08RCUA","TXQ0ZtlILt","cmXIXuLtKs","yluBxVIlwP","9iGoTLewvM",
-"Dz1R345cIH","AXpwEQ6hMC","ECMvUtAOsr","jSjS3AIYUu","gjUTuAmdQd","WreyPMojnP","CdyBVGWqqX","Nxx9VWDVWJ","S2Dfu8RCUA","2DREsU3yw5",
-"WreyPDQimp","dpe1v7hyVv","he9IAoVQp6","55rfBbgJAz","Uvlv4ZzJHW","iB08lnnP8o","DG4sTs7Mxk","gdQsSUvlv4","MmKGJRmDcr","uLtKsYOfrY",
-"tjQxs48cHL","fqypyyluBx","GWqqXKr8ys","9XyT9suY4x","9rlg9VNCPd","aDGtS9GXkX","7Ow5Cs4786","RkQkeECMvU","v1HlnjiVBP","HP433b29RJ",
-"BGaQYlj07Q","pv0i77X3uy","gtCA5MGlTF","AgJHQJRJQB","HfyNQQbxXc","P6bcgVjCZq","FwEJzfFDrJ","euZA5hUTw7","MmsIo7Ow5C","rKDLJOz8yZ",
-"9rlg9uTacx","soy9tzHF1q","uTacxfFDrJ","NcICAfcwDa","jzUqRiwzGk","ZUnqtYh1hF","QWxoTnFqik","IRh48lsQGo","kB5nPvLsmS","qQxHP6AFT0",
-"RACujXflUq","6q6L9PYBf4","jfREuU3yw5","AmdQdtAOsr","suY4xfFDrJ","WreyPpFrrl","Cfgr30YAGH","2Nslm8U2nU","WreyP8xEKz","UmaEvD6rBy",
-"gf8rIMaJQs","MK07YAkKTk","okgRifcJOy","9rlg9piJSk","qaofNiKqhr","9iGoTPb1pa","t98iWXflUq","nlaByFwEJz","sqVrf4W0Tl","lsQGoblLA9",
-"MmKGJjeskS","14FLRY1mC0","HlUbFMmsIo","e6e4zJXljW","FPfSEtAOsr","fqypyMmsIo","kB5nPUvlv4","pvgjSNxx9V","BGaQYReKEW","SWfoutl72W",
-"RpBQmoVQp6","zqH0WogLgc","lpF6W7lUXZ","45cIH2TRI7","ulk41fcJOy","djsrvM6qcG","FNYIMhe9IA","sx5GlQChxs","IBe8kBCxeC","n8pJ9ksJby",
-"HfyNQMmKGJ","t59lR7X3uy","6q6L9KZamH","wDajXydG8U","lViBviB08l","EOE1oZuDtD","dhSuHJIqXi","m4bxUYjB9t","uZPqgQssNC","Ta8f6jeskS",
-"oGu6xlsQGo","618Did85a9","Vprf2P6bcg","TwanoyofH3","piJSkGSQwj","1LB1LuJScX","ogLgcJJs5m","48cHLBGaQY","EdBKcdjsrv","a00b5tvdkD",
-"pWiOsHRxd8","zY1GYX6Pin","Ss0ZuwiHrZ","m4bxUhe9IA","VBjhz5iGN5","lkMUADz1R3","zQt6QksJby","KASQ8CIShG","GWqqXQworu","Z4I1vRsQUq",
-"MmKGJ0ao3l","IKxdLHlUbF","dpe1v580YD","9XyT9ZJTXH","pWiOsMmKGJ","zQt6QtuDyS","cQOnvFhtgl","BpYhVIKxdL","Ta8f6MmsIo","jSjS3POUYS",
-"BCxeCFLsph","K20wKuupzk","vOqCEdpe1v","yofH3U3yw5","Vprf2fLNg8","h1zcHRsQUq","0BmCyDcpWB","NcICAHfyNQ","I7p2a0h1b1","F6PT2SmGzv",
-"5NammokgRi","fLNg8RBhp0","5drc6WDVWJ","618Di8xEKz","YjB9tyEfy9","GWqqXhi5X7","24ARFKr8ys","euZA5ThjNn","lH1ktJXljW","x3LDe7fsYM",
-"JIqXiCK5W7","SbRYyX6Pin","pAhR16AFT0","hSSvQYOfrY","jtn0XNcICA","HzZT8faHir","qQxHPtAOsr","5iGN5tuDyS","ix74rzz4ZU","AkKTkhi5X7",
-"sx5GlUmaEv","8xEKzFGzgp","OHaBzcShY2","QnJ1SIBe8k","zHF1quN6r3","8xEKzlsQGo","pWiOsmX2GE","RkQkeoQ87r","W7cTsAIYUu","Yw2oUh1zcH",
-"FnPFB0Wr5y","Ta8f6oQ87r","BCxeCtl72W","0Wr5y2ZHdk","fFDrJMezSW","lsQGoEOE1o","BbwgAZv7z0","0Kyfslj07Q","EoToPgf8rI","YOfrYlj07Q",
-"DQimpJKWYR","tAOsrfcJOy","v2eC30YAGH","RxrsmBFkb8","AgJHQ5IhmG","KsjRKUlU3M","7hyVvuTacx","B3qemoGu6x","FNYIM7lUXZ","h1zcHguMb8",
-"pFrrluZPqg","v8yFNzbIYY","YOfrYkZANm","gIYvEZJTXH","HlUbFatef2","2Yz7EsuY4x","jfREusx5Gl","ciuWzKsjRK","i7WMQciuWz","K4GS8uLtKs",
-"mX2GEwDajX","0YAGHSjskQ","pv0i75Namm","5drc6Ss0Zu","IjTwPNOHsz","lweGyIn3NS","7hyVv5iGN5","OHaBzGWqqX","ECMvUdhSuH","HfyNQ55rfB",
-"aFFssprNT6","VjCZqGWqqX","hUTw7Y1mC0","NcICAPYBf4","UlU3MhYBCK","5Namm14FLR","x3LDefLNg8","zqH0W1LB1L","mz8gxprNT6","CqqaDReKEW",
-"KZamHcQOnv","zmLYDtjQxs","SmGzvgjUTu","K4GS8VIlwP","D6rByfaHir","OUYuFZ4I1v","9y4lw8hJdt","8FmFHHRxd8","WreyPatef2","fFDrJECMvU",
-"ydG8UokgRi","t98iWQbxXc","WPmlxU3yw5","e6e4zVIlwP","CxVEfogLgc","Dz1R3t98iW","0BmCyvkCHH","4W0TlMmsIo","HzZT8n8pJ9","vkCHHtAOsr",
-"FwEJz5ZaEz","XflUqfmIK1","gtCA50YAGH","0h1b12Nslm","lCMxyfmIK1","64s8N64s8N","d7vjMt98iW","ThjNnn1pmO","4dEz6lH1kt","FPfSECNHmv",
-"S2Dfu1j5L8","FhtglHlUbF","t98iW5Drn0","bZLvS5IhmG","b29RJMmKGJ","EdBKcfqypy","MK07YWreyP","bZLvSlCMxy","07n1cBCxeC","14FLRcQOnv",
-"NOHszReKEW","NhXduru4UG","h1zcHEOE1o","iKqhr4W0Tl","7hyVvW3VFH","RzaZARACuj","0h1b1zz4ZU","azIWplkMUA","iB08lNhXdu","Uvlv4XflUq",
-"OUqFMIjTwP","atef2uTacx","dpe1vfLNg8","zY1GYpv0i7","LbRTH0Kyfs","FhtglguMb8","TXQ0Z3otm6","7hyVvNAFuw","t98iW48cHL","blLA9ru4UG",
-"ThjNnQ6hMC","tuDySFVMxo","Z4I1vvOqCE","piJSk3otm6","QnJ1SM3zXL","sqVrfFnPFB","PYBf4sqVrf","8xEKzHfyNQ","d7vjMni2v1","wiHrZWreyP",
-"YOfrYpFrrl","Mkgy8FVMxo","JRJQBMezSW","BGaQYi3pyd","xXTI48RCUA","IKxdLCp3mZ","zY1GYW7cTs","uLtKsuQIcz","brhlQuZPqg","7fKYUGWqqX",
-"t59lRjiVBP","618DiRkQke","TCgPpKr8ys","tlILt0PktI","Kr8ysru4UG","pvgjSRBhp0","WDVWJ5VZjS","Yh1hFBCxeC","9GXkXmX2GE","qUJMdkZANm",
-"B3qemECMvU","wiHrZsoy9t","GrDg7lXFOB","v1HlntAOsr","C2Irc64s8N","5Namm8hJdt","WDVWJkB5nP","uoStwazIWp","IBe8kdhSuH","EOE1oQWxoT",
-"xReecyofH3","AOgEecL0aE","tAOsrsuY4x","wiHrZfcwDa","zFgtB9rlg9","OHaBz3otm6","s93Ml5iGN5","FhtglTXQ0Z","v2eC3JXljW","iwzGkThjNn",
-"W3VFHCIShG","No0Qb0BmCy","5Drn00Kyfs","NAFuwmX2GE","vkCHHBFkb8","yofH30h1b1","xXTI445cIH","Pb1paLewvM","OUqFMs7Mxk","SbRYynFqik",
-"Yf2EcJRJQB","9XyT9uTacx","9y4lwdQ586","Ss0ZuBGaQY","sqVrf4QMc9","zmLYDCp3mZ","WmadAs4786","Ta8f6DQimp","8hJdt5iGN5","dmoS74dEz6",
-"aL6AJ9GXkX","1j5L8ThjNn","Zv7z0CqqaD","pv0i7uQIcz","pvgjSd85a9","Zv7z0ZhwG1","sx5GlNo0Qb","gIYvEWmadA","S2DfuoGu6x","AkKTkOUYuF",
-"iwzGkPOUYS","4W0TlhYBCK","TwanoMezSW","v8yFNuLtKs","yToGWfaHir","5iGN55Drn0","uupzkMaJQs","lViBvAOgEe","i3pyd2hEEU","AOgEeDQimp",
-"yEfy9gdQsS","GrDg7Fhtgl","Y1mC0OxWIH","7X3uyzmLYD","1LB1LdQ586","8TxD7lCMxy","Q6LixEdBKc","55rfBjS1aj","Y1mC0DLhzM","5NammFGzgp",
-"Uvlv4ogLgc","BpYhVtuDyS","OUYuFtAOsr","OUYuFkZANm","ulk41FNYIM","B3qemS2Dfu","iKqhrsx5Gl","lkMUAKsjRK","4W0TlJRJQB","hSSvQ48cHL",
-"KsjRK8cVD3","QnJ1SOHaBz","GXdoH5IhmG","b29RJuN6r3","oVQp6qUJMd","SbRYyYw2oU","JJs5m8U2nU","n8pJ9YOfrY","RzaZAfmIK1","16lHcksJby",
-"pT8wus7Mxk","suY4xRACuj","OUqFMVjCZq","Z4I1vFGzgp","RBhp0lweGy","NAFuwsuY4x","zz4ZUQssNC","tl72Wv8yFN","wiHrZMaJQs","tuDySCp3mZ",
-"XyPZNd7vjM","cL0aEIRh48","IjTwPni2v1","AgJHQNAFuw","1v5hH9XyT9","lCMxyJKWYR","b29RJIKxdL","Cp3mZCp3mZ","Mm8siuvf7A","gjUTunnP8o",
-"Waim60h1b1","EdBKcJIqXi","oGu6xkZANm","9GXkX1v5hH","D6rBytjQxs","JJs5muZPqg","zqH0WFLsph","45cIHM3zXL","Vprf2zFgtB","5ZaEzK4GS8",
-"zz4ZUiwzGk","24ARF45cIH","s93MlzbIYY","StlDJsuY4x","brhlQ0YAGH","FwEJz0h1b1","uLtKsZJTXH","S2DfuLDk6f","djsrv14FLR","okgRi9eoRc",
-"1j5L8fcwDa","zmLYDGrDg7","KZamH5Drn0","W7cTsFNYIM","zFgtB7X3uy","rKDLJRmDcr","VIlwPl83Ud","hSSvQsuY4x","rhl0JMm8si","VIlwPGSQwj",
-"he9IAuTacx","h1zcHZ4I1v","fcwDalsQGo","M3zXL6AFT0","kB5nPCK5W7","nFqik1v5hH","5iGN5MmsIo","2hEEURpBQm","WPmlxyvOMI","fqypyogLgc",
-"8hJdthYBCK","JRJQB4QMc9","In3NSOHaBz","zmLYD29QAz","Ss0ZuzY1GY","GrDg7IKxdL","LbRTHsoy9t","sqVrfRmDcr","azIWpAXpwE","QChxslsQGo",
-"zHF1qOUqFM","JKWYRQChxs","WaWsvOUqFM","jiVBPx3LDe","jtn0XiwzGk","fcJOy1LB1L","uvf7AtuDyS","uLtKsd85a9","ydG8UReKEW","vLsmS4W0Tl",
-"Q6hMCKZamH","vkCHHjeskS","DLhzMBGaQY","ReKEWjiVBP","NhXduyluBx","oVQp6CqqaD","RBhp06q6L9","AgJHQ4dEz6","piJSkQnJ1S","RkQkefmIK1",
-"Q6hMCQbxXc","FNYIM5Namm","FnPFBqQxHP","lH1ktG1RhS","ThjNn8FmFH","s4786RzaZA","NhXduuZPqg","Q6hMCk85Ae","CdyBVLDk6f","5Drn0QssNC",
-"vOqCEHRxd8","MezSW9rlg9","Kr8ysFxX9q","bgJAzprNT6","hYBCKzz4ZU","1LB1LpvgjS","uJScXe6e4z","QworuEoToP","gIYvES2Dfu","7fsYMM6qcG",
-"wDajXd7vjM","8xEKzsqVrf","ni2v1uJScX","v1HlnO3iyQ","48cHLS77LH","Mkgy8BCxeC","0YAGHXyPZN","5NammVIlwP","Nxx9V9XyT9","pWiOs7fsYM",
-"iwzGkgtCA5","8RCUAFnPFB","LewvMMK07Y","8TxD76q6L9","fqypyyofH3","oGu6xpmeCd","In3NS24ARF","LDk6fWPmlx","aez9yKr8ys","MmKGJM6qcG",
-"zbIYYksJby","fcwDaPYBf4","U3yw5tlILt","Ss0Zu6AFT0","FwEJzJkzUn","7X3uyuLtKs","lpF6W24ARF","JJs5myEfy9","pFrrl0h1b1","ZzJHWD6rBy",
-"d85a9lkMUA","QworuPb1pa","TCgPpTXQ0Z","9XyT91LB1L","uQIczPOUYS","Yw2oUAOgEe","zFgtBHlUbF","FjHXRVIlwP","pWiOsBCxeC","Zv7z048cHL",
-"WreyPpAhR1","dmoS7xReec","8cVD3d85a9","GSQwjwiHrZ","atef2pWiOs","WMiS3CK5W7","Q6hMCSWfou","v8yFNbgJAz","Mkgy8tAOsr","AOgEe8RCUA",
-"gf8rIXflUq","aDGtSDG4sT","suY4xM3zXL","HzZT8ZUnqt","Ta8f6MGlTF","fFDrJIKxdL","Oz8yZBCxeC","pAhR1L7cGc","CNHmviB08l","4W0TltvdkD",
-"oVQp6CxVEf","WPmlxuQIcz","NcICA2DREs","G1RhSZzJHW","aez9yZ4I1v","lkMUA45cIH","CK5W7uLtKs","8cVD3tuDyS","x3LDe0Kyfs","NOHsz2ZHdk",
-"2DREsQnJ1S","zHF1qYjB9t","WMiS3POUYS","pAhR1OHaBz","xciqpguMb8","ReKEW2ZHdk","7hyVvhi5X7","uvf7AcShY2","atef2Cfgr3","2ZHdkUmaEv",
-"Yh1hF45cIH","LewvMiB08l","14FLRni2v1","Nxx9VG1RhS","o8Uyd618Di","Q6hMCMmsIo","VNCPdZUnqt","AXpwEFLsph","0BmCypAhR1","wiHrZlweGy",
-"D6rByYjB9t","YOfrYprNT6","tl72WTXQ0Z","lViBvG1RhS","yEfy9XyPZN","RmDcruLtKs","lCMxyZzJHW","sx5GlFhtgl","Vprf2Mkgy8","5NammVprf2",
-"WMiS3vOqCE","blLA9lm0pD","Zv7z0WDVWJ","NcICAaez9y","gdQsSi3pyd","y94nwDQimp","ZJTXHfLNg8","29QAz6AFT0","djsrv4dEz6","GrDg7QWxoT",
-"blLA9yvOMI","J2mQiVBjhz","iKqhrix74r","Chuy3ix74r","RBhp0hSSvQ","618DiUlU3M","C2IrcNOHsz","vOqCE24ARF","1j5L81v5hH","pv0i7s93Ml",
-"5nmWvB3qem","HRxd8Mm8si","qQxHPksJby","7ku1pdpe1v","DcpWBFLsph","oGu6xpWiOs","JkzUnxciqp","taOXKyToGW","0YAGH0MR5X","yToGWNxx9V",
-"M3zXLnFqik","bZLvSuPX7G","zz4ZU7lUXZ","WPmlxOUqFM","7Ow5CDQimp","64s8N5iGN5","ix74rRACuj","WaWsvv8yFN","OUYuFmz8gx","gtCA5PYBf4",
-"rz7UtlkMUA","JRJQBIKxdL","0Wr5y8TxD7","Kr8ystAOsr","LDk6f0BmCy","VBjhzVLTy6","mz8gxjtn0X","bgJAzfaHir","48cHLuAWyp","fcJOyMezSW",
-"lpF6WtlILt","8xEKzatef2","W7cTsDQimp","QnJ1SWmadA","FVMxonnP8o","uLtKsKZamH","ciuWzksJby","SbRYyyToGW","sqVrfzHF1q","zmLYDt98iW",
-"45cIHzbIYY","uvf7AWmadA","jfREuM6qcG","5IhmGfcwDa","JIqXihE1Ql","QworucQOnv","KASQ8OUYuF","okgRiBbwgA","Ul4a1fmIK1","jzUqRAOgEe",
-"v2eC3J2mQi","IKxdLSbRYy","618DipFrrl","AIYUuWaim6","dhSuHvkCHH","lXFOBdjsrv","CIShGvLsmS","TXQ0ZyluBx","DQimpiB08l","Gv3FqaFFss",
-"wiHrZv2eC3","8FmFHJJs5m","JIqXiQworu","oVQp6mz8gx","gf8rIo8Uyd","uN6r32Yz7E","t98iWFjHXR","Uvlv4dhSuH","pvgjSlm0pD","1j5L8djsrv",
-"rKDLJxciqp","KASQ85drc6","ogLgcM6qcG","iwzGk0h1b1","4dEz6okgRi","zQt6QEdBKc","sx5Gl8FmFH","QWxoTOz8yZ","tlILt8cVD3","LbRTHfLNg8",
-"XflUqP6bcg","x3LDeAgJHQ","O3iyQXflUq","iKqhrpmeCd","rKDLJWMiS3","CK5W7rz7Ut","uJScXZzJHW","pWiOsGSQwj","x3LDezFgtB","QYxC0zbIYY",
-"8xEKzfLNg8","F6PT2MojnP","GWqqXAkKTk","7Ow5CmX2GE","dpe1vdjsrv","0PktIEOE1o","FNYIMNhXdu","s4786XyPZN","8hJdt7fKYU","DQimp24ARF",
-"POUYSGrDg7","POUYSzHF1q","prNT6k85Ae","lViBvWmadA","9iGoTFLsph","RACujpiJSk","v2eC31LB1L","yluBxQ6Lix","zFgtBS77LH","16lHcK20wK",
-"CIShGFLsph","oGu6xU3yw5","lCMxyfFDrJ","fmIK1PYBf4","Fhtgl7fsYM","TXQ0Zlm0pD","Rxrsm5nmWv","faHir4dEz6","P6bcgMaJQs","azIWp7hyVv",
-"kZANmjS1aj","BFkb8KZamH","lj07QAgJHQ","hE1QlYOfrY","RmDcr5Mg9r","7ku1phE1Ql","Y1mC0s4786","yofH3hUTw7","0BmCyhYBCK","kZANmFjHXR",
-"hi5X7Ta8f6","Dz1R3WmadA","s93MlThjNn","DcpWBSbRYy","cQOnv9iGoT","8RCUAZuDtD","JIqXiGSQwj","9eoRcgjUTu","qUJMdSbRYy","07n1c0ao3l",
-"fLNg88hJdt","dhSuH1LB1L","3weIF7fsYM","Nxx9VCqqaD","DG4sTVNCPd","tl72WoGu6x","YOfrYQssNC","OHaBz9y4lw","5Mg9rBGaQY","blLA9jiVBP",
-"5IhmGbrhlQ","Ul4a1atef2","cL0aEKZamH","5VZjSOUqFM","uupzkOUqFM","yEfy90ao3l","IjTwPStlDJ","MezSWZhwG1","BFkb8ogLgc","FGzgpfcJOy",
-"No0Qbs7Mxk","L7cGcS2Dfu","mz8gxOUqFM","KZamHIjTwP","uN6r3cmXIX","NAFuwcL0aE","t59lRprNT6","Nxx9VgIYvE","h1zcH14FLR","5IhmGpv0i7",
-"9eoRch1zcH","euZA529QAz","EoToP5ZaEz","AkKTkzQt6Q","QYxC00Wr5y","oVQp6BCxeC","POUYSlweGy","BbwgARmDcr","O3iyQQbxXc","0YAGHUl4a1",
-"fcJOyTXQ0Z","zqH0WF6PT2","FPfSEb29RJ","K4GS8Yw2oU","yofH324ARF","dmoS7uupzk","zY1GYB3qem","t98iWPYBf4","uN6r355rfB","SjskQciuWz",
-"Waim6FVMxo","SjskQtAOsr","64s8NCNHmv","pWiOsFwEJz","RsQUqMmKGJ","ix74rvLsmS","Nxx9VpiJSk","CxVEfI7p2a","IBe8kk85Ae","RsQUqW7cTs",
-"rKDLJWaim6","J2mQiuPX7G","HfyNQ3otm6","djsrvJIqXi","cShY2jS1aj","FPfSE8U2nU","Uvlv4oVQp6","W7cTsZ4I1v","45cIH8RCUA","KASQ8pv0i7",
-"48cHL0h1b1","yofH3DQimp","24ARFMezSW","Nxx9VVerEA","euZA5uPX7G","fFDrJrz7Ut","QYxC09iGoT","XyPZNlXFOB","LDk6f5drc6","ru4UGzHF1q",
-"k85AefFDrJ","yToGWhE1Ql","l83Ud7hyVv","lH1ktL7cGc","Kr8ysMezSW","DLhzMnFqik","yluBxSs0Zu","KASQ8DG4sT","0Wr5yUl4a1","Mm8si0Wr5y",
-"FjHXRChuy3","ECMvUxReec","ThjNnY1mC0","Ss0ZuyofH3","Cp3mZ8RCUA","hE1QlHzZT8","BbwgABGaQY","zqH0WJJs5m","AkKTkgdQsS","xReecvkCHH",
-"5Mg9rBFkb8","MaJQs9XyT9","JXljWXyPZN","OUYuFNcICA","SmGzvlm0pD","POUYSUl4a1","lm0pDRBhp0","QssNCx3LDe","AgJHQHzZT8","FxX9qLbRTH",
-"uZPqgYf2Ec","Kr8ysXflUq","P6bcgAXpwE","VerEAZv7z0","aFFssm4bxU","8U2nUZv7z0","gjUTudhSuH","fFDrJ2Yz7E","pvgjSVIlwP","JXljWBGaQY",
-"VIlwPuZPqg","gjUTuG1RhS","FGzgpZv7z0","VjCZq0Wr5y","FcWrWvOqCE","Kr8ysZ4I1v","lpF6WlCMxy","aL6AJiKqhr","bZLvSWDVWJ","faHir5Namm",
-"ni2v18cVD3","6AFT0CIShG","FnPFBVIlwP","lCMxyjS1aj","vkCHHhE1Ql","SbRYygjUTu","5ZaEzcQOnv","yofH3Gv3Fq","CxVEf7fsYM","pAhR1NcICA",
-"U3yw5jiVBP","48cHLpFrrl","suY4x9iGoT","uupzkk85Ae","7lUXZb29RJ","7X3uy580YD","MmKGJIn3NS","dpe1vYjB9t","FcWrWDQimp","FcWrWNcICA",
-"FNYIMvLsmS","5Mg9rh1zcH","xReecaL6AJ","SmGzvAIYUu","zmLYDmX2GE","djsrvx3LDe","lH1ktVIlwP","lsQGoMezSW","2TRI729QAz","SWfougtCA5",
-"CIShGGrDg7","v1HlnFVMxo","pFrrlhSSvQ","mz8gx618Di","MGlTFs7Mxk","6q6L9CNHmv","G1RhSJRJQB","WDVWJs4786","55rfBMojnP","NAFuwWaWsv",
-"uoStw8cVD3","prNT6wiHrZ","lsQGotl72W","Cp3mZqQxHP","0h1b16q6L9","i7WMQKASQ8","EdBKc0ao3l","5Namm580YD","RsQUquLtKs","ogLgcmz8gx",
-"VNCPdQClRL","d7vjMmX2GE","MezSWZ4I1v","kB5nPPb1pa","pv0i7i3pyd","7fKYUtlILt","WreyPU3yw5","fLNg8Dz1R3","5drc6JXljW","8hJdtMGlTF",
-"lXFOBIRh48","QYxC0M3zXL","yToGWrKDLJ","9y4lw5iGN5","Q6LixpT8wu","SjskQjzUqR","HlUbF7fKYU","5NammJkzUn","55rfBOUYuF","YOfrYWPmlx",
-"SWfouk85Ae","Dz1R316lHc","UlU3MlViBv","2NslmQworu","lweGy9rlg9","0ao3lfmIK1","Cp3mZbZLvS","x3LDefFDrJ","AmdQdlj07Q","uZPqgfqypy",
-"8hJdtCxVEf","uZPqgSmGzv","MmsIoVBjhz","45cIH2DREs","MK07Y7fsYM","s7Mxkd7vjM","uPX7GCxVEf","SWfou2TRI7","PYBf4he9IA","DLhzMNo0Qb",
-"WmadAix74r","s7Mxk0Wr5y","CK5W7prNT6","lweGytAOsr","lCMxypmeCd","lCMxyTCgPp","aFFssIn3NS","WreyPiqv4k","wDajXGWqqX","aL6AJ7fsYM",
-"ydG8Uxciqp","RmDcrYjB9t","7fKYU2DREs","EOE1ookgRi","55rfBO3iyQ","DLhzMX6Pin","cmXIXDG4sT","2NslmXflUq","kZANmYw2oU","0h1b1yvOMI",
-"5Namm5VZjS","h1zcHW3VFH","lXFOB4W0Tl","CIShGyEfy9","Z4I1v7lUXZ","Z4I1vJXljW","DG4sTyofH3","hSSvQo8Uyd","QWxoTkB5nP","o8Uydo8Uyd",
-"Nxx9Vs7Mxk","hi5X7FLsph","y94nwyvOMI","GSQwjJIqXi","guMb8lj07Q","7ku1pLbRTH","oQ87rTXQ0Z","FVMxo2ZHdk","gIYvEThjNn","xReecO3iyQ",
-"BbwgATa8f6","2ZHdkWmadA","5ZaEzaFFss","0KyfsyvOMI","S2DfuIjTwP","LewvM0YAGH","ThjNnuJScX","IKxdLyEfy9","EdBKcWaim6","8TxD7nFqik",
-"cmXIXAkKTk","xXTI48FmFH","FcWrW580YD","QbxXcsuY4x","yEfy9ksJby","NhXdu4W0Tl","lpF6WUvlv4","s4786zFgtB","5VZjSlCMxy","8hJdt7Ow5C",
-"FwEJzYjB9t","Rxrsmv8yFN","IKxdLReKEW","dhSuHOUqFM","ulk41BbwgA","jfREua00b5","XyPZNAOgEe","ZzJHWHzZT8","s4786OUqFM","P6bcgdhSuH",
-"4QMc9qaofN","KsjRKBGaQY","MGlTFtuDyS","CK5W7MojnP","uN6r35iGN5","I7p2aUl4a1","gdQsSG1RhS","QWxoTOUYuF","VBjhz6AFT0","Dz1R3ReKEW",
-"7fKYU2Nslm","zmLYDKZamH","VjCZqUmaEv","2NslmbrhlQ","azIWpZzJHW","S2DfuCfgr3","0h1b1CK5W7","5IhmG1LB1L","pWiOsazIWp","2DREsZuDtD",
-"GWqqXm4bxU","Waim6QssNC","jiVBP0h1b1","LbRTHPOUYS","hi5X7pmeCd","P6bcgUlU3M","fqypyzbIYY","lH1kt7hyVv","l83UdjSjS3","qUJMdM6qcG",
-"ReKEWt98iW","OUYuFi7WMQ","ZzJHWOUYuF","CdyBV24ARF","JJs5miKqhr","aL6AJpvgjS","64s8NEdBKc","OHaBz7fKYU","brhlQMGlTF","gIYvElweGy",
-"QWxoTpT8wu","Yf2Ecpv0i7","8RCUAJ2mQi","GrDg7hi5X7","BpYhVOUqFM","CNHmv8FmFH","RpBQmD6rBy","AOgEe55rfB","WreyPfqypy","BGaQYB3qem",
-"lkMUASWfou","HzZT8JIqXi","S77LHpv0i7","WreyPlm0pD","OUqFMuQIcz","bZLvS9XyT9","d7vjMOUqFM","gjUTugf8rI","lH1ktMezSW","FnPFB8TxD7",
-"C2IrcQYxC0","ReKEWUvlv4","VLTy6RpBQm","XyPZNzmLYD","GXdoHGXdoH","RsQUqzbIYY","EOE1o16lHc","7lUXZzz4ZU","d7vjMlH1kt","Waim62Nslm",
-"o8Uydrhl0J","8xEKzHP433","jS1ajIjTwP","8xEKzFVMxo","hi5X7O3iyQ","MmsIoIjTwP","uQIczokgRi","FLsphni2v1","XyPZNCxVEf","djsrvBpYhV",
-"WmadAhE1Ql","xciqpQ6Lix","1LB1Lzz4ZU","HP4337lUXZ","FVMxovOqCE","pAhR1G1RhS","gtCA5FxX9q","pWiOs29QAz","lXFOBgdQsS","k85AepWiOs",
-"zz4ZUsoy9t","Yh1hF1j5L8","lsQGouvf7A","uZPqgrhl0J","Yf2EcpvgjS","GSQwjwDajX","C2IrctAOsr","VBjhzmX2GE","IKxdLKASQ8","dmoS7MGlTF",
-"5IhmGFwEJz","AmdQdlm0pD","qaofNGSQwj","HP433he9IA","NAFuwQbxXc","DQimpkB5nP","lsQGoGrDg7","azIWpokgRi","5VZjS6q6L9","ZJTXHSbRYy",
-"okgRiUl4a1","piJSkzY1GY","In3NSW7cTs","i7WMQs93Ml","djsrvwDajX","LDk6fCfgr3","EOE1oFjHXR","5IhmGS2Dfu","KZamHn1pmO","b29RJW3VFH",
-"Ul4a1VBjhz","K20wKSjskQ","m4bxUHlUbF","TCgPpJRJQB","ru4UG5iGN5","uPX7GlweGy","prNT6MK07Y","vLsmSuJScX","OHaBzCqqaD","2Yz7EJJs5m",
-"9XyT9gdQsS","24ARFo8Uyd","ECMvU6q6L9","i7WMQ618Di","cQOnvU3yw5","lweGy07n1c","24ARFYOfrY","OxWIHYOfrY","KsjRKAgJHQ","7lUXZTwano",
-"KZamHiqv4k","CIShGFjHXR","kB5nPrz7Ut","HP433Ul4a1","lkMUAhUTw7","sx5Glv2eC3","tuDySC2Irc","FVMxoAXpwE","okgRiydG8U","Oz8yZvkCHH",
-"Dz1R3aFFss","RxrsmkB5nP","OHaBzCp3mZ","a00b5AmdQd","gtCA5uAWyp","Gv3Fq7lUXZ","8FmFHLewvM","n1pmOMK07Y","1v5hHBCxeC","d7vjMW3VFH",
-"9eoRcfLNg8","lXFOBRpBQm","0YAGHzQt6Q","tl72Wv2eC3","Dz1R3HfyNQ","lViBvk85Ae","IBe8kB3qem","ciuWz3weIF","FxX9qThjNn","x3LDeC2Irc",
-"fFDrJVNCPd","guMb84dEz6","m4bxUlViBv","qUJMdd7vjM","uLtKsAXpwE","X6PinlCMxy","ru4UGnnP8o","9rlg9Twano","Yf2EcSbRYy","vLsmSdjsrv",
-"IBe8k8xEKz","FnPFBo8Uyd","uTacxfaHir","m4bxUi3pyd","Gv3FqIjTwP","e6e4zuPX7G","kZANmyEfy9","L7cGcpmeCd","BFkb8lkMUA","atef2RBhp0",
-"jzUqRjeskS","lCMxyyvOMI","nnP8oS77LH","X6PinWPmlx","uTacxhSSvQ","lH1ktwDajX","FLsphDz1R3","No0Qb0ao3l","JKWYRBGaQY","14FLRcL0aE",
-"Dz1R3Q6Lix","bgJAzAIYUu","jfREuYh1hF","LewvMQ6Lix","mX2GEZ4I1v","1j5L8Twano","5Mg9rQChxs","L7cGcW3VFH","CqqaDaez9y","v2eC3SbRYy",
-"MK07YokgRi","VIlwPFFDui","BCxeCP6bcg","Gv3FqksJby","29QAzNOHsz","QClRLOz8yZ","uJScXgdQsS","tlILtiB08l","RACujlCMxy","IRh4848cHL",
-"EoToPQbxXc","StlDJtaOXK","lkMUA8FmFH","IBe8k0YAGH","atef2AOgEe","piJSkgIYvE","pmeCd5drc6","PYBf4y94nw","piJSknFqik","NhXdugIYvE",
-"8U2nUqUJMd","jeskSzz4ZU","GWqqX5iGN5","Mm8siMezSW","EOE1oOHaBz","pAhR1EoToP","RkQkeVNCPd","aDGtSazIWp","RmDcrzQt6Q","WmadA3otm6",
-"lViBv5nmWv","Oz8yZAkKTk","Y1mC0DcpWB","ulk41hSSvQ","ni2v15Namm","1LB1LP6bcg","0MR5X5Namm","ZzJHWzHF1q","xXTI4gtCA5","zY1GYjiVBP",
-"fqypyNo0Qb","uJScXn8pJ9","LDk6f7fKYU","5Mg9rK4GS8","yluBxWaWsv","C2IrcDG4sT","M3zXLNAFuw","LbRTHuZPqg","uupzkokgRi","NAFuwWmadA",
-"uPX7GQbxXc","S77LH4W0Tl","7Ow5CcmXIX","KASQ8uJScX","uupzk45cIH","aL6AJfLNg8","0Wr5yMm8si","OUYuFRsQUq","ZuDtDFFDui","ydG8UJIqXi",
-"QworuCfgr3","hUTw7vLsmS","5Mg9rFhtgl","UmaEvQClRL","2Yz7EbrhlQ","pv0i7RBhp0","yEfy9ogLgc","IjTwPhE1Ql","pmeCdlXFOB","lj07QVjCZq",
-"CK5W7oGu6x","K4GS8Cp3mZ","24ARFix74r","K4GS8Zv7z0","JKWYR5Mg9r","fLNg8Q6Lix","WreyP45cIH","1v5hHzbIYY","QworuuQIcz","zbIYYpv0i7",
-"RzaZAbgJAz","TCgPpzFgtB","zz4ZUSmGzv","nnP8ookgRi","SjskQD6rBy","0Kyfsv8yFN","iwzGkgdQsS","aDGtShYBCK","CqqaDuLtKs","GSQwjbZLvS",
-"uAWyp0Kyfs","djsrv7lUXZ","K20wKmz8gx","v8yFNgtCA5","vOqCEJJs5m","o8UydzY1GY","5iGN5tvdkD","9iGoTv8yFN","ogLgcHlUbF","9eoRcEOE1o",
-"8hJdtIBe8k","lsQGo7ku1p","7hyVv7fsYM","K20wKsx5Gl","ru4UGBFkb8","qUJMdNxx9V","ru4UGDz1R3","K4GS8CNHmv","LewvMGrDg7","5Drn08cVD3",
-"gdQsSMm8si","tuDySDcpWB","i3pyduJScX","piJSkUlU3M","t59lRDLhzM","jS1ajix74r","kB5nPiqv4k","bZLvSru4UG","n8pJ9s4786","9XyT9OUqFM",
-"iwzGkStlDJ","pFrrlNo0Qb","CdyBVyluBx","hE1Ql5nmWv","JXljW3otm6","lViBvYh1hF","VBjhzeuZA5","a00b5HzZT8","AkKTkDG4sT","soy9tjeskS",
-"zFgtBNcICA","Mm8sieuZA5","JRJQB5nmWv","lXFOB6AFT0","JXljWydG8U","fcJOy6AFT0","sqVrfNxx9V","55rfBYjB9t","BbwgAa00b5","HfyNQ9iGoT",
-"tvdkDFFDui","qUJMdni2v1","HzZT85iGN5","RxrsmciuWz","L7cGcMojnP","xReec7X3uy","RzaZAHfyNQ","HP433zz4ZU","3otm6QClRL","n8pJ97fKYU",
-"5nmWv8RCUA","45cIHuZPqg","ogLgcblLA9","uupzkbZLvS","7fKYUvLsmS","ZhwG1fLNg8","zqH0WyvOMI","Dz1R3uN6r3","No0QbTa8f6","Twanouvf7A",
-"he9IAQbxXc","Kr8ysTa8f6","Waim6TCgPp","CIShG7fsYM","mz8gxNhXdu","cQOnvFcWrW","GSQwjJJs5m","Rxrsmt59lR","8FmFHoGu6x","DG4sTK4GS8",
-"9eoRcYh1hF","iqv4kBGaQY","MojnP5IhmG","wDajXpmeCd","Yf2EcyEfy9","Kr8ysmz8gx","vkCHHogLgc","djsrvb29RJ","GWqqXMkgy8","5nmWvpiJSk",
-"RzaZAXflUq","K4GS8EdBKc","xciqp1j5L8","ThjNnQssNC","zmLYDoVQp6","fLNg8pmeCd","yvOMI0Wr5y","OUqFMF6PT2","P6bcg0BmCy","x3LDeuvf7A",
-"lj07Qi3pyd","faHirEdBKc","W7cTsokgRi","Ta8f6brhlQ","5ZaEzuTacx","L7cGc64s8N","24ARFQ6hMC","BGaQYDG4sT","BpYhV0MR5X","CIShGUmaEv",
-"1j5L8FLsph","pT8wuPOUYS","wiHrZ7Ow5C","oGu6x07n1c","MK07Y7hyVv","JKWYRW7cTs","CNHmv7lUXZ","CK5W78U2nU","brhlQJRJQB","WMiS3jSjS3",
-"XyPZNQWxoT","guMb81j5L8","zQt6QOz8yZ","WMiS3Z4I1v","bZLvSZv7z0","b29RJokgRi","Ss0Zuatef2","nnP8oKASQ8","HlUbFChuy3","Yh1hFFwEJz",
-"2hEEU7hyVv","9rlg9cL0aE","M3zXLZuDtD","bgJAz07n1c","uoStwGSQwj","uoStwUlU3M","NcICApmeCd","ix74rhe9IA","Nxx9VoQ87r","FjHXRLewvM",
-"W7cTsMmKGJ","ogLgcpFrrl","zHF1qHRxd8","618DivkCHH","7fKYU7ku1p","VjCZqK20wK","DG4sTChuy3","jeskSM3zXL","StlDJAOgEe","MojnPCK5W7",
-"GWqqX5ZaEz","DQimpo8Uyd","FnPFBv1Hln","rz7UtP6bcg","pFrrleuZA5","s4786kZANm","L7cGche9IA","yEfy9618Di","uLtKsyToGW","BbwgA580YD",
-"iB08lbrhlQ","sx5Glv8yFN","PYBf4GrDg7","hi5X7JKWYR","cQOnvzQt6Q","7Ow5CpvgjS","KsjRKhYBCK","BpYhVHlUbF","Chuy3FLsph","07n1ctl72W",
-"jSjS3lsQGo","JJs5mFhtgl","MmsIoGWqqX","2DREsJKWYR","AmdQdaFFss","Mkgy8kZANm","he9IAsqVrf","8U2nUGSQwj","QworulweGy","IBe8kuTacx",
-"JRJQBB3qem","BGaQYhSSvQ","azIWpyEfy9","uvf7AzHF1q","2NslmyToGW","yToGWblLA9","n1pmOJRJQB","lsQGo2Yz7E","Pb1paRxrsm","jtn0XMaJQs",
-"TXQ0ZYf2Ec","dpe1vRkQke","ulk41QYxC0","WaWsvYw2oU","S2DfuguMb8","NOHszoVQp6","K4GS8lj07Q","jeskSrhl0J","9rlg9W3VFH","ogLgche9IA",
-"i7WMQpiJSk","NcICAzmLYD","Nxx9VnlaBy","SbRYy618Di","fcJOyix74r","OHaBzatef2","o8Uyd580YD","Pb1pavLsmS","Mkgy8hi5X7","7ku1pjeskS",
-"2Nslm1v5hH","QnJ1StuDyS","WreyPDz1R3","5ZaEzAgJHQ","sqVrfW3VFH","WmadAcShY2","gf8rIzz4ZU","mX2GEksJby","jS1ajRACuj","J2mQigjUTu",
-"fFDrJaez9y","mX2GEjzUqR","dQ586OUqFM","J2mQijtn0X","2TRI70h1b1","Vprf2bgJAz","SmGzvlCMxy","dmoS7wDajX","2Yz7EcL0aE","okgRiEoToP",
-"iKqhrRzaZA","LbRTHVNCPd","uZPqgSbRYy","IBe8kOUqFM","ciuWzQClRL","NcICAYh1hF","FVMxo5Drn0","VLTy6uAWyp","y94nwZ4I1v","4W0TlmX2GE",
-"FFDuiRzaZA","zmLYDRzaZA","VBjhzdhSuH","2hEEU2ZHdk","UmaEvVLTy6","Yh1hFQworu","ZzJHWQWxoT","2DREs0h1b1","uZPqgNhXdu","uLtKssoy9t",
-"qaofNdhSuH","gIYvE2Yz7E","VLTy6t59lR","ydG8UJJs5m","2Yz7E9iGoT","LbRTHW7cTs","G1RhS07n1c","No0QbWmadA","9rlg9aez9y","ZUnqtWMiS3",
-"vkCHHFxX9q","FNYIMrKDLJ","Yw2oUhe9IA","HRxd8OHaBz","iKqhrgtCA5","Cfgr3JKWYR","0h1b1K20wK","1v5hHZ4I1v","hSSvQkB5nP","IBe8k7ku1p",
-"5ZaEzJKWYR","jSjS3fcwDa","rKDLJGXdoH","cQOnvOUqFM","oVQp6EdBKc","soy9tx3LDe","lweGy7X3uy","DQimpx3LDe","ogLgctl72W","nFqikpmeCd",
-"Uvlv43otm6","xciqp2hEEU","VNCPdn1pmO","fqypyNOHsz","5Mg9rtaOXK","48cHLaDGtS","rKDLJ3otm6","8FmFHSWfou","tl72WlH1kt","BFkb8FwEJz",
-"POUYSCNHmv","lViBvni2v1","k85AeGv3Fq","EdBKcThjNn","gjUTuHlUbF","qQxHPAIYUu","k85AeCp3mZ","lpF6WtuDyS","tvdkDWaim6","24ARFZUnqt",
-"SbRYyQChxs","tuDySbgJAz","K4GS8BCxeC","ThjNnsqVrf","8U2nUrKDLJ","Q6LixS2Dfu","aL6AJzHF1q","uPX7GcShY2","hYBCKRxrsm","mz8gxSs0Zu",
-"tvdkDIn3NS","RACujuZPqg","HfyNQRmDcr","azIWp4W0Tl","0BmCyyofH3","YOfrY5Mg9r","CxVEfwDajX","IKxdLwDajX","fqypyix74r","WmadAGWqqX",
-"he9IAjeskS","DcpWBTa8f6","WreyPxciqp","0BmCyIBe8k","5Drn05Mg9r","JIqXiAXpwE","F6PT2ogLgc","v2eC3ZuDtD","aez9y3weIF","oVQp6brhlQ",
-"ZzJHWtvdkD","16lHc1v5hH","HfyNQ5VZjS","Y1mC0J2mQi","zqH0WuPX7G","OUYuFn8pJ9","FFDui9XyT9","X6Pin64s8N","uZPqgCfgr3","CNHmvUlU3M",
-"uvf7APYBf4","fmIK1tuDyS","jeskSfLNg8","VBjhzStlDJ","8xEKzNAFuw","uN6r32hEEU","J2mQixReec","sx5Gltl72W","JXljWhUTw7","4dEz65iGN5",
-"Twanos4786","TXQ0ZSs0Zu","jS1ajni2v1","LbRTHblLA9","IBe8knFqik","QClRLcQOnv","s7Mxk0Kyfs","x3LDeGv3Fq","aFFssDG4sT","AOgEe580YD",
-"v8yFNGrDg7","he9IAt98iW","L7cGco8Uyd","Dz1R3euZA5","v8yFN7Ow5C","0PktI618Di","4W0TlhSSvQ","vkCHHAmdQd","fcwDaF6PT2","580YD8xEKz",
-"1v5hHNAFuw","VLTy6JIqXi","aL6AJn8pJ9","4W0TlCqqaD","he9IApvgjS","iqv4kqaofN","580YDNAFuw","gjUTu2TRI7","uJScXoVQp6","oQ87rvkCHH",
-"8xEKzaFFss","hE1QlVLTy6","StlDJOUqFM","ksJby24ARF","VjCZqMmsIo","7X3uylj07Q","ulk4116lHc","zz4ZUaDGtS","lpF6WIBe8k","pvgjSZhwG1",
-"mz8gxcShY2","XyPZNqUJMd","2hEEUuoStw","RxrsmCK5W7","AkKTk0ao3l","CNHmv2ZHdk","TXQ0ZKASQ8","dpe1vIKxdL","CxVEfkZANm","UmaEvM6qcG",
-"fLNg8pvgjS","jSjS3cShY2","d85a9MaJQs","ogLgcuvf7A","hi5X74QMc9","v1HlntjQxs","jfREujiVBP","W3VFHa00b5","BpYhVCdyBV","lH1ktZJTXH",
-"9XyT9Mkgy8","zY1GYpFrrl","cShY2mz8gx","yEfy9CxVEf","U3yw5FjHXR","xReecbrhlQ","QWxoTO3iyQ","RsQUqvLsmS","iB08lzmLYD","K4GS8NOHsz",
-"3otm6MojnP","ksJbyQssNC","bZLvSLbRTH","Cfgr3euZA5","0ao3lMK07Y","VLTy65nmWv","9eoRcl83Ud","MezSW64s8N","VBjhzwDajX","FcWrWlH1kt",
-"2ZHdkmX2GE","CqqaDLDk6f","CxVEfFLsph","Fhtgl0MR5X","HP433Chuy3","azIWpI7p2a","1j5L88TxD7","Oz8yZfaHir","AkKTkOz8yZ","Q6LixprNT6",
-"BGaQYyluBx","uTacx7fKYU","y94nwIjTwP","07n1cdpe1v","DLhzMxReec","jtn0XsuY4x","AOgEe8FmFH","lj07Ql83Ud","IjTwPQnJ1S","pT8wuJIqXi",
-"Waim6VerEA","9iGoTk85Ae","hUTw7uoStw","zz4ZUrz7Ut","KsjRKF6PT2","jeskSSbRYy","QYxC04QMc9","t59lRIBe8k","gdQsSjtn0X","X6PinD6rBy",
-"v2eC3cQOnv","Pb1papFrrl","bgJAz9GXkX","M6qcGdQ586","vLsmSBFkb8","fcJOy0MR5X","aez9yxciqp","LDk6fFNYIM","BpYhVlkMUA","45cIHZzJHW",
-"5Mg9rulk41","OxWIHC2Irc","sx5GlU3yw5","7Ow5CfcJOy","GSQwjFPfSE","EdBKc2DREs","lXFOBUl4a1","8cVD3zz4ZU","YOfrYDG4sT","MmsIozQt6Q",
-"uZPqg29QAz","jS1ajY1mC0","RpBQm24ARF","7Ow5ChYBCK","pv0i7tvdkD","5iGN5sqVrf","VerEA1LB1L","pFrrl9y4lw","JKWYRCdyBV","n8pJ9gtCA5",
-"uTacxlXFOB","D6rBys4786","piJSkRkQke","TwanoYf2Ec","B3qemKsjRK","YOfrYLDk6f","U3yw5qaofN","CNHmvgdQsS","7lUXZNo0Qb","9iGoTyEfy9",
-"Kr8ysgjUTu","aL6AJMaJQs","9XyT9hUTw7","5NammZUnqt","8TxD78FmFH","jfREu7ku1p","aL6AJZhwG1","MmKGJ0h1b1","jS1ajUmaEv","ciuWzRxrsm",
-"fFDrJoQ87r","FwEJzv1Hln","MezSWFLsph","ix74r0BmCy","BCxeCYf2Ec","WMiS32hEEU","gdQsSfcJOy","i7WMQPYBf4","S2DfuG1RhS","K20wK0Kyfs",
-"cQOnv0h1b1","L7cGczz4ZU","o8UydOxWIH","GWqqXTwano","aDGtSlj07Q","uLtKsJRJQB","lsQGodQ586","1j5L8FjHXR","hE1QlVjCZq","AmdQdAIYUu",
-"GXdoHFhtgl","d7vjMSs0Zu","2hEEUjiVBP","9XyT9d7vjM","0YAGH0ao3l","PYBf4ciuWz","gjUTudmoS7","Ul4a1Oz8yZ","OUqFMYh1hF","v2eC3jiVBP",
-"HRxd8uJScX","qQxHPpv0i7","VjCZqNOHsz","NcICAhUTw7","29QAztaOXK","zQt6QCK5W7","GXdoHsqVrf","jSjS3VBjhz","t98iWyluBx","0h1b1HzZT8",
-"a00b58cVD3","mX2GEblLA9","5NammWMiS3","4QMc9lsQGo","BGaQYLewvM","mz8gxvLsmS","jiVBPru4UG","VLTy69eoRc","hYBCKEOE1o","580YDECMvU",
-"4QMc9aDGtS","jiVBPSmGzv","7fKYUDLhzM","uvf7AMmsIo","AXpwEYf2Ec","s7MxkECMvU","guMb8UmaEv","5NammDQimp","ZJTXHJXljW","aFFss2DREs",
-"djsrvCK5W7","Yw2oUNcICA","24ARFpFrrl","U3yw5MK07Y","blLA9SjskQ","Fhtgldjsrv","cQOnvAOgEe","AXpwElXFOB","lH1ktWDVWJ","OxWIHFwEJz",
-"14FLRG1RhS","hYBCKLewvM","qQxHPrz7Ut","fLNg8Zv7z0","7X3uyYh1hF","gjUTuRsQUq","gtCA516lHc","DcpWBJJs5m","VNCPdQChxs","a00b5U3yw5",
-"euZA5lpF6W","No0QbI7p2a","3otm6FwEJz","Nxx9VxXTI4","VLTy67Ow5C","uJScXQClRL","3weIF8U2nU","rKDLJHlUbF","lweGycmXIX","blLA9XyPZN",
-"tuDyS3weIF","5VZjS24ARF","uupzk1LB1L","lm0pDVBjhz","d85a9Ss0Zu","U3yw548cHL","i3pyd5drc6","ZuDtDs7Mxk","W7cTsKsjRK","kZANmguMb8",
-"FNYIMs7Mxk","AOgEeThjNn","azIWpiqv4k","ECMvUwiHrZ","fFDrJFLsph","WmadAFVMxo","GWqqXS2Dfu","HlUbFb29RJ","ThjNnjfREu","iwzGkRsQUq",
-"dpe1vs4786","24ARF9y4lw","Nxx9VuZPqg","HfyNQulk41","HlUbFaez9y","lweGyprNT6","SjskQyofH3","8TxD7lkMUA","zqH0WzQt6Q","B3qemlpF6W",
-"S77LHwDajX","GXdoH7Ow5C","yofH35Namm","qaofNWPmlx","IjTwPx3LDe","5NammcQOnv","VIlwPni2v1","HzZT8cShY2","8cVD3RBhp0","5Drn0fLNg8",
-"Q6LixCIShG","v2eC30BmCy","9XyT929QAz","OUqFMcShY2","2DREsni2v1","k85AeRsQUq","qaofNAgJHQ","1LB1LJ2mQi","yToGWatef2","AOgEeeuZA5",
-"faHirPb1pa","2ZHdkXflUq","JIqXiuQIcz","lCMxyqaofN","NcICANo0Qb","0KyfsJIqXi","O3iyQEdBKc","Yw2oUHfyNQ","AgJHQuJScX","gtCA5suY4x",
-"yToGWsqVrf","qUJMd14FLR","4QMc9wiHrZ","C2IrcFxX9q","lm0pD9y4lw","hUTw7d85a9","tvdkDK20wK","pv0i7DcpWB","kZANmMkgy8","WmadAFjHXR",
-"lkMUAksJby","fcJOyChuy3","dmoS70PktI","Q6LixVprf2","tlILtaL6AJ","iqv4klj07Q","oQ87rhe9IA","M6qcG5Drn0","mX2GEGSQwj","NAFuwNo0Qb",
-"CdyBVn1pmO","e6e4zKZamH","AOgEeJJs5m","MK07YY1mC0","nnP8oGXdoH","NcICAlweGy","JXljWfaHir","aez9yQ6Lix","hi5X78RCUA","dQ586aez9y",
-"e6e4zFxX9q","NhXduAIYUu","WreyPYh1hF","gtCA5uJScX","rz7UtQssNC","Cp3mZLbRTH","rKDLJs7Mxk","7fsYMFcWrW","L7cGcUmaEv","5IhmGs7Mxk",
-"suY4xGv3Fq","uJScXXyPZN","n8pJ90ao3l","JJs5mFNYIM","JJs5mb29RJ","XyPZN2Nslm","0KyfsZzJHW","i7WMQblLA9","FLsph4W0Tl","CdyBVHfyNQ",
-"0h1b17fKYU","aDGtSSbRYy","wDajXRmDcr","AgJHQyToGW","Yw2oUWaWsv","AIYUuwDajX","s4786a00b5","POUYSNxx9V","Uvlv4lH1kt","soy9t5VZjS",
-"SjskQkZANm","Q6LixnFqik","CIShGMmKGJ","IBe8ki7WMQ","BGaQYZv7z0","2NslmpT8wu","TwanoFNYIM","NhXdusuY4x","uJScXdpe1v","Chuy3gjUTu",
-"2DREsyluBx","GWqqXGrDg7","24ARFHRxd8","tlILtlViBv","IKxdLWaim6","dpe1vNOHsz","L7cGcMaJQs","lViBv64s8N","SWfouMGlTF","uN6r34dEz6",
-"W7cTsSmGzv","Kr8yshUTw7","Vprf2ni2v1","ogLgce6e4z","gf8rIEoToP","lXFOBBbwgA","nlaBylXFOB","AmdQdblLA9","CNHmvzbIYY","8FmFHQbxXc",
-"NOHszhUTw7","cL0aEuoStw","lsQGom4bxU","nlaByFPfSE","uN6r3fqypy","I7p2an8pJ9","pmeCdv1Hln","zmLYDni2v1","LDk6foQ87r","FjHXRMkgy8",
-"In3NS1LB1L","BCxeCIKxdL","Ta8f6tl72W","yToGWTXQ0Z","IRh48RzaZA","gIYvEQ6hMC","tl72WLbRTH","SbRYyiKqhr","S77LHi3pyd","uupzkCdyBV",
-"jS1ajThjNn","s4786AIYUu","FLsphMkgy8","0PktIQnJ1S","L7cGcOz8yZ","MezSWW3VFH","jeskSlXFOB","2DREsGv3Fq","uLtKsi7WMQ","MezSWpvgjS",
-"XflUqQ6hMC","G1RhS7fKYU","VBjhz7lUXZ","BCxeCNcICA","vLsmSSs0Zu","vkCHHpAhR1","rz7UtzmLYD","jeskS0ao3l","CdyBVsqVrf","taOXKJXljW",
-"2DREsKZamH","RsQUqZv7z0","Yf2EcvkCHH","4QMc9HlUbF","qUJMdk85Ae","7Ow5CIKxdL","fFDrJOz8yZ","faHirGSQwj","Y1mC0ZJTXH","WDVWJtAOsr",
-"DLhzMNOHsz","zmLYDYjB9t","IKxdLbrhlQ","uoStwlCMxy","RBhp0ZJTXH","In3NS2ZHdk","tAOsr1j5L8","lViBvciuWz","WMiS3Vprf2","CqqaD1v5hH",
-"t98iWGXdoH","W7cTsMaJQs","2ZHdkatef2","D6rByRsQUq","CxVEfiwzGk","8xEKz45cIH","HRxd8aFFss","MmsIon1pmO","RxrsmEOE1o","ZJTXHAXpwE",
-"ydG8U0BmCy","GWqqXuZPqg","zFgtBlj07Q","faHirtlILt","m4bxUtuDyS","618Diy94nw","IBe8klXFOB","vkCHHO3iyQ","Chuy3azIWp","AIYUu2DREs",
-"07n1c7hyVv","nFqikfLNg8","FwEJzAOgEe","wiHrZBbwgA","8cVD3bZLvS","CqqaDCxVEf","uupzkuvf7A","hUTw7FPfSE","Y1mC0WPmlx","lj07Qb29RJ",
-"aez9yU3yw5","hYBCKUl4a1","FjHXRn1pmO","pT8wuNAFuw","JKWYRYf2Ec","uTacxuN6r3","o8UydY1mC0","9rlg9lH1kt","9rlg90Wr5y","xReecBpYhV",
-"55rfBuAWyp","mX2GERBhp0","Zv7z09iGoT","StlDJ0Kyfs","tlILtx3LDe","Yh1hFaDGtS","WmadAo8Uyd","tlILtVNCPd","lweGyO3iyQ","Cfgr3EOE1o",
-"0YAGHoVQp6","2DREsn1pmO","qUJMdsuY4x","Ss0Zusx5Gl","8U2nUzmLYD","ZzJHWdjsrv","xReecjtn0X","AXpwEIKxdL","o8UydStlDJ","pT8wuaDGtS",
-"7X3uyaDGtS","WmadAdhSuH","pFrrl4dEz6","uTacxMmsIo","WmadA8RCUA","okgRi07n1c","HlUbFDz1R3","i3pyduZPqg","hYBCK2TRI7","Vprf2XyPZN",
-"zqH0WAgJHQ","YjB9tqQxHP","9GXkXpFrrl","POUYSuLtKs","L7cGcGWqqX","7lUXZhE1Ql","zmLYDzqH0W","jzUqRMkgy8","S2DfuOUqFM","WMiS3d7vjM",
-"SmGzveuZA5","nFqikEoToP","hSSvQW7cTs","ix74rSbRYy","lViBvfaHir","QChxsa00b5","8FmFH2ZHdk","BbwgAaDGtS","HfyNQ0Wr5y","YOfrY0ao3l",
-"M3zXL0PktI","IKxdLIKxdL","7ku1puZPqg","9eoRcC2Irc","K20wKVIlwP","RpBQmQ6Lix","LDk6fo8Uyd","AIYUuydG8U","lweGyhYBCK","B3qemn1pmO",
-"dQ586UmaEv","Ta8f6ksJby","MK07YRxrsm","FNYIMZv7z0","d85a9TCgPp","ZUnqt5Namm","yvOMIGWqqX","QworuW3VFH","Chuy31LB1L","WaWsvFjHXR",
-"2hEEU16lHc","kB5nPBbwgA","xXTI4iB08l","mX2GErz7Ut","yvOMI5Drn0","B3qemQ6hMC","9eoRctuDyS","BbwgAMezSW","Mm8siFPfSE","FNYIM9y4lw",
-"FhtglgdQsS","jeskSQworu","VjCZqG1RhS","Gv3FqVjCZq","guMb8BGaQY","YjB9t4W0Tl","vOqCE64s8N","5NammECMvU","Mm8sizz4ZU","1v5hHiB08l",
-"M6qcGbZLvS","ZhwG1O3iyQ","uvf7AcmXIX","ECMvUuZPqg","gtCA5FcWrW","k85AezbIYY","uPX7Gs7Mxk","hE1QlQYxC0","BGaQYh1zcH","CIShGnnP8o",
-"In3NS9eoRc","YjB9tG1RhS","MaJQsFcWrW","RACujHzZT8","IRh48OUqFM","KASQ8NcICA","9GXkXcL0aE","i3pydVerEA","9iGoTQ6hMC","nlaByYjB9t",
-"RkQke0MR5X","lCMxyK4GS8","07n1cnlaBy","iwzGkW3VFH","WaWsvUl4a1","cQOnvrKDLJ","lViBvK20wK","okgRi5VZjS","okgRiKASQ8","FwEJzlViBv",
-"Cp3mZoVQp6","FwEJzrhl0J","Dz1R3djsrv","DcpWBQworu","jS1ajXflUq","lm0pDQ6Lix","5nmWvUvlv4","FhtglSWfou","zz4ZUokgRi","lViBv2DREs",
-"5iGN5D6rBy","Vprf2FLsph","0Wr5ylpF6W","5VZjSlpF6W","5iGN5QWxoT","rhl0JQ6hMC","8TxD7n8pJ9","B3qemydG8U","PYBf4VLTy6","ru4UG5IhmG",
-"YOfrY0MR5X","rz7UtY1mC0","FxX9qOz8yZ","FNYIMoGu6x","tlILtzFgtB","0MR5XguMb8","mz8gxpAhR1","7Ow5CRsQUq","QbxXciqv4k","WMiS32TRI7",
-"DLhzMlCMxy","a00b5xXTI4","y94nwXyPZN","brhlQW3VFH","8cVD3CNHmv","7Ow5CAgJHQ","QssNCmz8gx","bZLvSguMb8","zQt6QFNYIM","cShY2Nxx9V",
-"qaofN48cHL","aFFsstlILt","MmKGJQYxC0","FGzgpl83Ud","BCxeCSs0Zu","XflUqlXFOB","BbwgAuTacx","D6rBy1v5hH","Fhtgl24ARF","tuDySi3pyd",
-"pFrrlrKDLJ","F6PT22Nslm","SmGzv0ao3l","MezSW6AFT0","qUJMdWaWsv","oGu6x0Wr5y","h1zcHFnPFB","s93MlGv3Fq","s7MxkuLtKs","5VZjSxXTI4",
-"2hEEUjSjS3","t59lRrKDLJ","LewvMjeskS","BpYhVzz4ZU","1v5hHfFDrJ","OxWIHzFgtB","16lHcVBjhz","FxX9qBCxeC","55rfBlsQGo","24ARFMmKGJ",
-"48cHLF6PT2","W3VFHEoToP","atef2JJs5m","7fsYMW3VFH","QWxoTk85Ae","yofH3Q6hMC","6AFT0Uvlv4","ZhwG1pFrrl","s7Mxk9iGoT","okgRiOz8yZ",
-"BCxeCzbIYY","O3iyQ9y4lw","qQxHPpAhR1","0YAGHprNT6","W3VFHBbwgA","Q6LixaDGtS","OUYuFydG8U","aL6AJ8RCUA","J2mQijeskS","G1RhSpiJSk",
-"580YDUmaEv","2TRI75Namm","ru4UG4QMc9","lm0pDpAhR1","BpYhVPOUYS","QssNCcShY2","xReeczFgtB","yToGWcmXIX","2TRI7NAFuw","RzaZARmDcr",
-"J2mQiFNYIM","8hJdtNxx9V","aL6AJgf8rI","HfyNQI7p2a","NcICAblLA9","l83UdtlILt","pFrrllm0pD","Y1mC0hYBCK","lkMUANxx9V","VBjhz7X3uy",
-"zmLYDHRxd8","xciqpru4UG","IRh48Mkgy8","7X3uynnP8o","CqqaDs7Mxk","Yw2oUSmGzv","rz7UtpmeCd","lkMUAIjTwP","tl72W5nmWv","lCMxyIjTwP",
-"zQt6QYw2oU","jSjS3QClRL","IRh482Nslm","IKxdLogLgc","MK07YQbxXc","7fsYMkZANm","0MR5XFnPFB","zY1GYZ4I1v","5ZaEzRxrsm","prNT6iqv4k",
-"o8UydVjCZq","POUYSgjUTu","DLhzMTXQ0Z","ksJbyZuDtD","uvf7Afqypy","1j5L8qaofN","VLTy6VjCZq","POUYSIKxdL","Z4I1vX6Pin","zQt6QuZPqg",
-"IBe8kWaim6","TCgPp29QAz","guMb8CxVEf","8hJdtNAFuw","uupzkuJScX","JJs5mydG8U","Mkgy8lH1kt","CqqaDGv3Fq","uAWyp55rfB","oQ87rfcwDa",
-"FxX9qaFFss","WreyPYOfrY","d85a9fcwDa","i7WMQ3otm6","FVMxo8xEKz","rz7Ut5drc6","HRxd8okgRi","zmLYDx3LDe","lweGywiHrZ","ix74rfmIK1",
-"hE1QlHfyNQ","24ARFNAFuw","hYBCKHfyNQ","brhlQ7Ow5C","gdQsS7fsYM","ogLgcKr8ys","nnP8ovOqCE","xReecBbwgA","WmadAl83Ud","Twano6AFT0",
-"wDajXB3qem","uoStwGrDg7","14FLRSWfou","hSSvQJKWYR","hUTw7mX2GE","CxVEffcwDa","VLTy6K4GS8","S2Dfuk85Ae","Mkgy8CqqaD","lCMxyZhwG1",
-"StlDJEdBKc","2Nslm9GXkX","Kr8ys3weIF","hUTw77Ow5C","2NslmLDk6f","ZUnqttjQxs","45cIHBbwgA","aDGtSPb1pa","HlUbFYh1hF","M3zXL9rlg9",
-"yEfy9POUYS","4QMc9LDk6f","Cp3mZulk41","8hJdtMmKGJ","aDGtSksJby","JRJQBiwzGk","zFgtBLewvM","StlDJaez9y","ECMvUNhXdu","nFqikpT8wu",
-"5NammfmIK1","gf8rI8U2nU","Ta8f6uTacx","sx5GlyvOMI","FVMxoKZamH","oVQp6I7p2a","DLhzMLDk6f","SWfouUvlv4","l83UdLewvM","CIShGM3zXL",
-"ZhwG1RACuj","9iGoTOz8yZ","55rfBX6Pin","8xEKzAOgEe","Twano9GXkX","atef2BCxeC","Rxrsm5VZjS","5IhmGMojnP","VLTy6sx5Gl","L7cGcK4GS8",
-"EOE1on1pmO","4dEz6djsrv","iKqhrUmaEv","dpe1vogLgc","AkKTkfaHir","45cIHSWfou","5ZaEzW3VFH","ZhwG1vOqCE","RsQUqh1zcH","lpF6WZ4I1v",
-"yEfy9NhXdu","ksJby7fKYU","Y1mC0jSjS3","pFrrlfmIK1","DG4sT64s8N","QWxoTGWqqX","0MR5XjiVBP","2Yz7EFjHXR","9rlg9L7cGc","gdQsSVIlwP",
-"sx5Gl5drc6","CxVEfIRh48","lj07Qrhl0J","rKDLJmX2GE","IjTwPRpBQm","UmaEvK4GS8","iKqhr0Wr5y","FLsphX6Pin","uZPqgLewvM","zQt6QUvlv4",
-"kZANms4786","XyPZNQworu","9rlg9WDVWJ","Gv3Fq2hEEU","d85a9WDVWJ","Yw2oUMGlTF","azIWpFxX9q","VIlwP6AFT0","mz8gxMK07Y","i7WMQVNCPd",
-"ZJTXHeuZA5","GWqqXUvlv4","tlILtwDajX","uoStw5Mg9r","lpF6WDLhzM","ix74rZhwG1","29QAzaL6AJ","BpYhVv2eC3","aDGtSRsQUq","RACujkZANm",
-"hUTw7ZJTXH","xXTI4NAFuw","Cp3mZKASQ8","JXljW1v5hH","8TxD7jSjS3","VBjhzQ6hMC","wiHrZyvOMI","L7cGcm4bxU","1LB1LXflUq","Dz1R39GXkX",
-"5Mg9rWaim6","Mm8siQ6Lix","5Mg9rQClRL","Oz8yZgtCA5","JKWYRa00b5","2ZHdkVprf2","1j5L8Waim6","2Yz7EI7p2a","t98iWpv0i7","DcpWBThjNn",
-"2TRI7DG4sT","lpF6WpAhR1","2Yz7E8U2nU","euZA5POUYS","s7Mxk8RCUA","7fKYUjiVBP","zFgtBjfREu","WreyPWmadA","taOXKNcICA","9rlg9aFFss",
-"jtn0XJkzUn","9y4lwn1pmO","kZANmtl72W","dQ586okgRi","Chuy3pv0i7","LDk6f9GXkX","8FmFHFLsph","WaWsvnnP8o","ydG8U0Wr5y","jeskSAkKTk",
-"VerEAWreyP","CxVEfMK07Y","n8pJ9t98iW","jzUqRNcICA","Chuy3soy9t","n8pJ9QnJ1S","AgJHQRkQke","16lHcwiHrZ","QYxC0o8Uyd","cQOnvbZLvS",
-"MK07YOUqFM","aez9ylweGy","x3LDe5Namm","lweGyzHF1q","pT8wuOz8yZ","ulk415ZaEz","Dz1R3tuDyS","lj07QFnPFB","tl72Wfqypy","fmIK1cL0aE",
-"FGzgp5Drn0","9eoRcGXdoH","SbRYy5IhmG","zHF1qhi5X7","G1RhSJkzUn","HzZT8iB08l","8RCUAlweGy","I7p2aVerEA","W3VFH2hEEU","YjB9tOUYuF",
-"W7cTsqQxHP","1j5L8SmGzv","lj07QWDVWJ","Z4I1vMezSW","BFkb89GXkX","v1HlnhE1Ql","DLhzMLewvM","FwEJzfmIK1","1LB1LqaofN","0h1b1lj07Q",
-"dmoS7UmaEv","7fsYMpWiOs","CK5W7uTacx","RkQkezmLYD","cmXIXZUnqt","jzUqRwDajX","s4786uLtKs","k85AetuDyS","VNCPdJ2mQi","VjCZqJKWYR",
-"YOfrYX6Pin","618DikB5nP","cShY2WmadA","9y4lwpv0i7","brhlQazIWp","KASQ8J2mQi","VjCZq3otm6","QYxC0WreyP","jiVBPdQ586","ydG8UzmLYD",
-"WaWsvQnJ1S","RBhp0cL0aE","NOHsz7fKYU","gdQsS0MR5X","NAFuws7Mxk","d85a929QAz","hE1QlAXpwE","7fKYUwDajX","y94nwazIWp","zbIYYCqqaD",
-"YjB9t8hJdt","suY4xDz1R3","FwEJz7fKYU","5drc6VBjhz","Yh1hF2Yz7E","9rlg929QAz","kB5nPTwano","lpF6Wni2v1","iqv4kZzJHW","pFrrl8TxD7",
-"lj07QiKqhr","ZzJHWMaJQs","Oz8yZlweGy","2ZHdkxXTI4","uTacxogLgc","Cfgr3uAWyp","i7WMQ0h1b1","cL0aE2Nslm","6AFT0prNT6","xXTI4a00b5",
-"Kr8ysFVMxo","In3NSNxx9V","o8Uyd9GXkX","qUJMdZJTXH","cL0aE7Ow5C","b29RJOUYuF","PYBf4v2eC3","jfREuAkKTk","5IhmGlpF6W","07n1c8TxD7",
-"BCxeCtjQxs","NcICA0BmCy","gtCA57fKYU","8TxD7okgRi","zY1GYYOfrY","FNYIMNAFuw","faHirSbRYy","MmsIowDajX","2DREsn8pJ9","LDk6f8U2nU",
-"Mkgy8zqH0W","ECMvUuPX7G","OxWIHtjQxs","WDVWJ4QMc9","FVMxo7fKYU","lXFOBVBjhz","WaWsvHRxd8","gjUTuBpYhV","9GXkX0BmCy","Ul4a1iKqhr",
-"NhXdublLA9","Pb1pabgJAz","LbRTHFLsph","lm0pDFVMxo","t59lRtl72W","Dz1R3vOqCE","ksJbyix74r","s93Ml7X3uy","uN6r3QYxC0","64s8NCIShG",
-"WreyPB3qem","JkzUnnlaBy","Mm8si8hJdt","BGaQYAgJHQ","WreyPX6Pin","SjskQhUTw7","Oz8yZAgJHQ","LbRTHfmIK1","2Yz7EUlU3M","cmXIXvLsmS",
-"LDk6fCdyBV","uN6r3VBjhz","WreyP7lUXZ","xciqpVprf2","x3LDeD6rBy","i7WMQhE1Ql","Cfgr3VLTy6","tvdkDiKqhr","jzUqRRzaZA","C2IrcaFFss",
-"lCMxyjSjS3","oGu6xWDVWJ","K20wK9eoRc","zbIYYuPX7G","t59lRix74r","nnP8oDcpWB","FxX9qbgJAz","1j5L8OUqFM","OHaBzbrhlQ","FFDuijiVBP",
-"cmXIXFwEJz","wiHrZru4UG","soy9tGv3Fq","taOXKs4786","CxVEfeuZA5","zz4ZUQChxs","yEfy9x3LDe","PYBf40h1b1","tjQxsUvlv4","pT8wuChuy3",
-"0PktI0h1b1","B3qemfcwDa","2Nslm5drc6","9eoRcXyPZN","dhSuHQworu","b29RJtAOsr","QClRLblLA9","vkCHHCIShG","VerEAnlaBy","zFgtB7Ow5C",
-"K20wK1LB1L","SbRYyiqv4k","wDajXPYBf4","mX2GETwano","bgJAzk85Ae","jiVBPtjQxs","FVMxoC2Irc","Ss0ZuCp3mZ","sx5GlVLTy6","Qworutl72W",
-"k85AeQ6Lix","5Drn0Cp3mZ","0h1b1DQimp","uTacxpWiOs","X6PinguMb8","qQxHPuLtKs","FjHXRNcICA","0h1b1v8yFN","7lUXZcmXIX","O3iyQ9rlg9",
-"6q6L9UlU3M","OUqFMbrhlQ","k85AeXyPZN","cShY2uJScX","DcpWBokgRi","SmGzvYOfrY","sx5GlyofH3","aDGtSsx5Gl","guMb864s8N","DcpWBvOqCE",
-"uN6r3QbxXc","4dEz6euZA5","KZamHFhtgl","n1pmOpv0i7","Nxx9V8xEKz","lCMxyBFkb8","KZamHYOfrY","P6bcgMkgy8","AgJHQZuDtD","dpe1v8RCUA",
-"GXdoHFcWrW","nFqikUlU3M","8U2nUiB08l","prNT6i7WMQ","MmKGJSbRYy","HlUbF6q6L9","S77LHJIqXi","618Dini2v1","2ZHdkQ6hMC","zHF1qCxVEf",
-"uAWypChuy3","tAOsrdmoS7","o8UydmX2GE","iqv4k5VZjS","QYxC0vkCHH","MojnPt59lR","64s8N0h1b1","ZzJHWtaOXK","MojnPHzZT8","oVQp6FLsph",
-"GWqqXZv7z0","jiVBPCNHmv","WreyPQ6hMC","ZzJHW4dEz6","prNT68TxD7","SmGzvBCxeC","8hJdtv1Hln","BCxeCMaJQs","jeskSlpF6W","2TRI7sx5Gl",
-"Fhtgl0BmCy","fmIK1BCxeC","fcwDaJRJQB","suY4xnFqik","vkCHHFGzgp","Gv3Fqs93Ml","BFkb87fKYU","ciuWz8hJdt","3otm6EdBKc","b29RJvkCHH",
-"piJSklCMxy","hSSvQlweGy","hE1QlAgJHQ","Mkgy8cL0aE","MmKGJGrDg7","t98iWdmoS7","NcICAkZANm","RpBQml83Ud","hUTw7FjHXR","VLTy6CxVEf",
-"FhtgltAOsr","nlaBy7lUXZ","RpBQmWMiS3","FPfSElsQGo","qaofNU3yw5","PYBf4CxVEf","JkzUn5drc6","DG4sTZ4I1v","8xEKzeuZA5","Z4I1v4QMc9",
-"S77LH2DREs","jSjS3C2Irc","KASQ8Uvlv4","iwzGkW7cTs","07n1cgtCA5","ThjNnVNCPd","Mkgy8RzaZA","FwEJzWMiS3","2Nslm4dEz6","GWqqXksJby",
-"ZUnqtTXQ0Z","FGzgp1LB1L","iB08l64s8N","Yf2EcJIqXi","jS1ajguMb8","tlILtO3iyQ","zz4ZUsuY4x","2TRI7KZamH","dhSuH0Kyfs","4QMc9Yw2oU",
-"S77LHMm8si","EoToPCIShG","FLsphuTacx","pT8wuQ6hMC","t98iWni2v1","kB5nPt98iW","oVQp6Qworu","MmsIoiwzGk","GrDg7HfyNQ","he9IArhl0J",
-"EdBKcAmdQd","tuDySxXTI4","n1pmOaez9y","i3pydGWqqX","prNT6FwEJz","lXFOBoQ87r","JKWYR55rfB","pT8wuCNHmv","xciqp0MR5X","9GXkX4dEz6",
-"zQt6QBGaQY","WPmlxrhl0J","zz4ZUMaJQs","ThjNnydG8U","bgJAzUlU3M","yluBxSWfou","TwanoD6rBy","POUYSqQxHP","jSjS3gIYvE","7ku1pCp3mZ",
-"9GXkXFVMxo","lCMxyFwEJz","fFDrJDLhzM","k85Ae5IhmG","euZA50h1b1","fqypyazIWp","vkCHHVjCZq","07n1c4W0Tl","cmXIXl83Ud","gtCA5POUYS",
-"uoStw0BmCy","P6bcgFcWrW","0BmCyIKxdL","t98iWv1Hln","JkzUnGXdoH","jS1aj2Nslm","2hEEUW3VFH","hYBCKiwzGk","HfyNQZhwG1","UmaEv5Namm",
-"soy9tjiVBP","uAWypjzUqR","Yf2EcDQimp","M3zXLIRh48","MK07Y9iGoT","AIYUuAIYUu","rhl0J6AFT0","lH1ktFwEJz","i3pydP6bcg","iB08l8U2nU",
-"ZuDtD6AFT0","Cp3mZVprf2","QClRLJJs5m","MmsIonnP8o","MmKGJiqv4k","Yw2oUJJs5m","24ARF2hEEU","F6PT2IRh48","cmXIX5VZjS","LDk6fJJs5m",
-"LewvM7X3uy","cL0aElH1kt","55rfBRxrsm","Zv7z08FmFH","IRh48v8yFN","ksJby7fsYM","9y4lwfcJOy","pFrrlatef2","0Wr5ysuY4x","FFDuinnP8o",
-"JJs5mAkKTk","OUqFM5ZaEz","ogLgcs7Mxk","qQxHPydG8U","BFkb8s4786","rz7UtHP433","n1pmOFNYIM","7Ow5CJIqXi","gf8rIjS1aj","9GXkXru4UG",
-"VNCPddhSuH","yluBxBGaQY","GXdoH0BmCy","9rlg9CNHmv","pFrrls4786","ix74rFLsph","lweGyo8Uyd","MmKGJKr8ys","zHF1qZzJHW","0h1b1BbwgA",
-"pWiOsRkQke","J2mQiciuWz","5VZjSfFDrJ","JIqXiQssNC","a00b5fcJOy","Mkgy8Kr8ys","QClRLWDVWJ","W7cTsS77LH","Pb1pat59lR","MGlTFQYxC0",
-"soy9tMK07Y","suY4xOxWIH","nFqikiwzGk","CdyBVzQt6Q","PYBf4IBe8k","7X3uyt98iW","7X3uyKr8ys","i3pydfFDrJ","NhXduYw2oU","MezSWWDVWJ",
-"YjB9tNcICA","5Drn0e6e4z","0Wr5yxciqp","cmXIX9rlg9","uAWypk85Ae","QssNCFhtgl","pvgjS48cHL","1v5hHI7p2a","StlDJLewvM","zHF1qrz7Ut",
-"ciuWzkB5nP","5IhmGgdQsS","8hJdtni2v1","KZamHDz1R3","azIWppFrrl","YOfrYNhXdu","3otm6d85a9","GXdoHZUnqt","M3zXLZJTXH","ReKEWbgJAz",
-"EoToPqUJMd","MGlTFzbIYY","QWxoTIBe8k","FjHXR2hEEU","VNCPd4W0Tl","WreyPGrDg7","MmKGJMmKGJ","K4GS8yofH3","ksJby3weIF","y94nwogLgc",
-"IBe8kZuDtD","soy9tFNYIM","ZzJHWBbwgA","ThjNn8RCUA","vkCHH7Ow5C","uoStwZJTXH","QssNCRzaZA","fmIK15drc6","QnJ1Si3pyd","tjQxsqQxHP",
-"W3VFHGSQwj","vLsmSyvOMI","VIlwP2ZHdk","FcWrWIn3NS","Cfgr3Uvlv4","Yf2EcYf2Ec","gIYvEs4786","brhlQlj07Q","MaJQsAgJHQ","a00b5HRxd8",
-"4QMc9MaJQs","v1HlnFwEJz","64s8NVjCZq","ThjNnlj07Q","taOXKjS1aj","suY4xjtn0X","D6rByQnJ1S","CK5W77X3uy","QbxXcFVMxo","jzUqR5Namm",
-"VIlwPFcWrW","5Mg9rs93Ml","uvf7A2Nslm","QYxC0uQIcz","ZhwG1Ul4a1","k85AeWMiS3","n8pJ90h1b1","AIYUuo8Uyd","8xEKzuAWyp","zbIYYQbxXc",
-"aDGtSCIShG","GXdoHxciqp","dQ586vOqCE","hSSvQ580YD","RACuj5ZaEz","4QMc9ZhwG1","55rfBogLgc","Zv7z0uAWyp","U3yw5Yw2oU","uPX7GJIqXi",
-"zHF1qd7vjM","FxX9qjS1aj","M6qcGTa8f6","mX2GEiwzGk","ZUnqtRpBQm","he9IA580YD","s4786VLTy6","uoStwRBhp0","okgRiJIqXi","1v5hHgtCA5",
-"VLTy6uvf7A","Y1mC0UmaEv","prNT6Y1mC0","ru4UGB3qem","AXpwE7X3uy","8U2nUD6rBy","WMiS3JkzUn","b29RJl83Ud","KZamHpT8wu","AIYUuokgRi",
-"48cHLXflUq","BGaQYBCxeC","QYxC0Q6hMC","nFqikG1RhS","tjQxsn1pmO","8U2nUKr8ys","cQOnv7lUXZ","d85a9VNCPd","okgRilkMUA","b29RJd7vjM",
-"M6qcGOHaBz","uoStwtaOXK","NcICAMaJQs","hi5X7lm0pD","NAFuwDG4sT","pFrrlK20wK","K20wK5nmWv","Ul4a1UlU3M","7X3uy9rlg9","M6qcG4dEz6",
-"NhXduFjHXR","AIYUuJJs5m","uoStwJ2mQi","zHF1qHzZT8","MaJQsuupzk","blLA9NcICA","pAhR1M3zXL","DG4sT0BmCy","S77LHGv3Fq","WDVWJ5iGN5",
-"QnJ1SgIYvE","hi5X7CNHmv","Kr8ysiwzGk","55rfBpv0i7","rhl0JpFrrl","zqH0Wl83Ud","Dz1R3VIlwP","MezSWWMiS3","uoStwv1Hln","I7p2a8U2nU",
-"F6PT2pWiOs","fqypyL7cGc","580YDuAWyp","Yw2oUl83Ud","k85Ae2hEEU","iB08ltaOXK","fFDrJiqv4k","n8pJ9KASQ8","lm0pDs7Mxk","pFrrlzFgtB",
-"IjTwPVprf2","16lHcgjUTu","In3NSfqypy","bgJAzfqypy","ZuDtDpFrrl","DLhzMs93Ml","580YD3weIF","WMiS3oGu6x","EdBKclXFOB","FNYIM2hEEU",
-"GWqqX9iGoT","NcICAdQ586","jfREupvgjS","WDVWJQ6Lix","ZzJHWNcICA","oGu6xZ4I1v","WPmlxbrhlQ","C2IrcjiVBP","s4786lm0pD","PYBf4RpBQm",
-"KZamHdhSuH","In3NS8hJdt","sqVrfMezSW","Rxrsm0BmCy","uTacxVLTy6","nlaByaDGtS","9iGoTtjQxs","P6bcgyluBx","gf8rI7fKYU","0YAGH8RCUA",
-"ECMvUs7Mxk","EdBKcLDk6f","Waim6l83Ud","SmGzvQworu","CIShGiKqhr","0Wr5ysx5Gl","UlU3MCqqaD","x3LDeFcWrW","jiVBP5Drn0","SbRYyxciqp",
-"QbxXcpv0i7","lweGyaez9y","VIlwPjS1aj","WaWsvSbRYy","yofH3FVMxo","JJs5mjtn0X","RxrsmZJTXH","UmaEvS2Dfu","mz8gxYf2Ec","9GXkXpvgjS",
-"blLA9qUJMd","Fhtgl3weIF","0Kyfs7ku1p","cShY27fsYM","RBhp0BpYhV","1j5L8m4bxU","HfyNQ7fKYU","B3qemzqH0W","fFDrJGrDg7","zQt6QUlU3M",
-"45cIHQChxs","hE1QlpWiOs","cmXIX7hyVv","Cfgr3SmGzv","2Yz7EP6bcg","wDajXn8pJ9","bgJAz14FLR","v1Hlnm4bxU","M6qcG0h1b1","Mkgy8lpF6W",
-"AIYUutl72W","5iGN5W7cTs","fLNg8Pb1pa","pvgjSbZLvS","LbRTHTXQ0Z","dpe1vMGlTF","rKDLJVIlwP","s7MxkfcwDa","gf8rIdmoS7","bZLvSOz8yZ",
-"U3yw5VNCPd","lXFOBJRJQB","HfyNQjS1aj","DG4sTB3qem","y94nwx3LDe","uJScXHlUbF","uAWypsuY4x","QYxC0ZUnqt","QworuZ4I1v","2ZHdkLewvM",
-"Cfgr3J2mQi","GXdoHpT8wu","hYBCK9XyT9","JRJQB9iGoT","hE1QlK4GS8","NOHsze6e4z","48cHLDLhzM","Mkgy8uJScX","l83Ud5Mg9r","7ku1pFNYIM",
-"hUTw7xciqp","WmadArhl0J","QssNCAmdQd","D6rBypvgjS","ksJby4QMc9","zbIYYLDk6f","aDGtSMK07Y","wDajXaFFss","he9IANxx9V","0PktItuDyS",
-"Ss0ZuReKEW","gjUTuyvOMI","StlDJIn3NS","K4GS829QAz","ciuWzrKDLJ","uQIczQworu","DG4sTd85a9","pT8wuGWqqX","5NammC2Irc","Waim6I7p2a",
-"s7Mxk5Drn0","zFgtBuvf7A","Yf2Eczz4ZU","StlDJsx5Gl","0YAGH07n1c","fqypycL0aE","RmDcr16lHc","9eoRcvLsmS","mz8gxiqv4k","JJs5m5ZaEz",
-"I7p2aMezSW","zHF1qlXFOB","DG4sTCqqaD","t98iWZUnqt","9eoRcRACuj","vLsmSAgJHQ","BGaQYFhtgl","he9IAAIYUu","gIYvENxx9V","lXFOBdmoS7",
-"SjskQTXQ0Z","TwanoChuy3","BCxeCHzZT8","pmeCdulk41","yvOMITCgPp","FVMxoYf2Ec","VjCZqblLA9","dQ586pvgjS","Yf2EcIBe8k","gf8rIVIlwP",
-"No0Qb4QMc9","tuDySuvf7A","s93MltvdkD","v2eC3aez9y","CdyBVpvgjS","8FmFHwiHrZ","CIShG8hJdt","8FmFHM6qcG","FFDuiYOfrY","O3iyQgIYvE",
-"ZhwG1uN6r3","MmKGJZ4I1v","dmoS7W7cTs","Y1mC0Uvlv4","hi5X7No0Qb","taOXKuJScX","JXljWlj07Q","7lUXZvkCHH","aFFssWaim6","HlUbFUvlv4",
-"lCMxyuoStw","bZLvSD6rBy","pv0i7cmXIX","GXdoHMaJQs","mX2GEwiHrZ","BbwgA0BmCy","J2mQi07n1c","07n1cFwEJz","nlaByBCxeC","5Drn0AmdQd",
-"WreyPUlU3M","I7p2a8TxD7","QClRLRxrsm","pFrrl5iGN5","J2mQiiwzGk","iB08lVerEA","MmKGJEdBKc","JKWYRDQimp","CxVEfbZLvS","mz8gxzHF1q",
-"FNYIMyluBx","AmdQdxciqp","oQ87rYOfrY","7fKYUQnJ1S","HRxd8HlUbF","uZPqgoVQp6","gf8rIZUnqt","Ul4a1he9IA","5Namm4QMc9","pAhR1RzaZA",
-"M6qcGGv3Fq","Gv3FqMojnP","tAOsrNAFuw","CIShGWaim6","07n1cZ4I1v","Z4I1vZUnqt","0MR5XlkMUA","hE1QluJScX","AmdQdAXpwE","HzZT855rfB",
-"K20wK7lUXZ","QWxoTjfREu","8FmFHRkQke","aFFsskB5nP","In3NStjQxs","IBe8kaez9y","jzUqRGWqqX","HfyNQk85Ae","M6qcGLDk6f","FxX9qRmDcr",
-"VerEAcL0aE","ydG8UOxWIH","4W0TllpF6W","CqqaDfLNg8","dhSuHcmXIX","7hyVvRkQke","kB5nPAXpwE","qUJMdCqqaD","v8yFNvOqCE","azIWpCfgr3",
-"sx5GloQ87r","QnJ1S14FLR","jzUqRogLgc","aL6AJGSQwj","vLsmSReKEW","pmeCdgf8rI","wiHrZOUYuF","euZA5GSQwj","OUYuFUl4a1","XyPZNK4GS8",
-"uTacxHP433","gf8rIfcwDa","FNYIM0PktI","AXpwEM6qcG","pv0i7fLNg8","fLNg8kZANm","ZJTXH7fKYU","uJScXRzaZA","RmDcri3pyd","guMb81v5hH",
-"Zv7z0iqv4k","lXFOByluBx","lkMUAZhwG1","uPX7GAmdQd","IRh48K4GS8","he9IAgf8rI","v8yFNWPmlx","jeskSs93Ml","n8pJ9brhlQ","2hEEUFGzgp",
-"L7cGcCfgr3","9y4lwhi5X7","GrDg7zQt6Q","HfyNQPYBf4","4QMc9TXQ0Z","t59lRbgJAz","I7p2aSmGzv","3weIFFGzgp","618DiM3zXL","lpF6WLbRTH",
-"jtn0Xtl72W","0ao3lStlDJ","6q6L9xReec","7X3uypT8wu","pvgjS8RCUA","SmGzvJJs5m","8U2nUciuWz","uupzkhE1Ql","5iGN5o8Uyd","JKWYRQbxXc",
-"0ao3lRsQUq","SWfouNAFuw","fcwDa6q6L9","Y1mC0n1pmO","TCgPpi7WMQ","FjHXR2DREs","jtn0XdhSuH","07n1cpvgjS","guMb8TXQ0Z","fcwDaMkgy8",
-"FwEJz8xEKz","POUYSi3pyd","s93MlhSSvQ","GXdoHblLA9","xciqp5VZjS","s7MxkydG8U","yvOMI7ku1p","gf8rIQnJ1S","45cIHQnJ1S","n8pJ9No0Qb",
-"P6bcg1j5L8","BFkb8Mkgy8","CNHmvHfyNQ","EdBKcSWfou","lCMxyhe9IA","5nmWvyluBx","Q6LixiKqhr","FhtglAgJHQ","qUJMdYw2oU","KASQ8FLsph",
-"HRxd8xciqp","SWfouWaWsv","lCMxylweGy","zY1GYhUTw7","580YD0ao3l","tAOsrv2eC3","he9IA2Yz7E","WPmlxCIShG","NcICAd85a9","OUqFM9iGoT",
-"7Ow5CuJScX","0PktIRxrsm","pWiOsIKxdL","BCxeCwiHrZ","F6PT2soy9t","Uvlv4Chuy3","29QAze6e4z","GSQwj64s8N","2Yz7EMojnP","0Wr5yru4UG",
-"FVMxoFjHXR","blLA9wiHrZ","GrDg7Dz1R3","jzUqRdhSuH","K20wKjfREu","tuDyS2TRI7","L7cGclXFOB","vOqCEAOgEe","tl72Wt59lR","kB5nPQChxs",
-"YOfrYaFFss","5Namm2Yz7E","SmGzvFGzgp","ECMvUYOfrY","uQIczkB5nP","dpe1vDcpWB","lCMxyb29RJ","AIYUu9rlg9","tvdkDeuZA5","8U2nUsuY4x",
-"MojnP16lHc","JRJQBzY1GY","kB5nPxReec","b29RJ0MR5X","GWqqX8cVD3","QnJ1SWPmlx","tvdkDzQt6Q","zbIYYsqVrf","faHiraFFss","8FmFHokgRi",
-"6q6L9sx5Gl","QssNCChuy3","s7Mxkv8yFN","iqv4kI7p2a","Cfgr3FGzgp","yToGW45cIH","1LB1LciuWz","gtCA59y4lw","C2IrcBFkb8","IBe8kF6PT2",
-"BbwgAv1Hln","CNHmvLbRTH","EdBKc580YD","zQt6Q0h1b1","pv0i72Yz7E","sx5GlydG8U","vLsmS4QMc9","Chuy34W0Tl","kZANmCfgr3","ogLgcpiJSk",
-"5IhmGlweGy","hE1QljS1aj","yluBxRsQUq","DcpWBhe9IA","5NammpT8wu","s93MlCxVEf","DG4sTF6PT2","XflUqXyPZN","azIWpCNHmv","7X3uyVjCZq",
-"atef2YOfrY","FjHXRbZLvS","JXljWNxx9V","5Drn0HP433","Oz8yZ2ZHdk","BCxeCFGzgp","8TxD7fLNg8","pAhR1y94nw","jeskSi7WMQ","FxX9qfaHir",
-"Chuy3m4bxU","cL0aEJ2mQi","s7MxkuTacx","sx5GlDQimp","fcJOy7lUXZ","O3iyQru4UG","8xEKzSs0Zu","Gv3FqnnP8o","Vprf27hyVv","hSSvQa00b5",
-"ThjNnxXTI4","M6qcGXflUq","gdQsSuJScX","v1HlnS77LH","Yh1hFDz1R3","8U2nUoVQp6","hi5X7K4GS8","WMiS3GXdoH","TXQ0Z0Kyfs","9y4lwgtCA5",
-"9y4lwtvdkD","7lUXZX6Pin","NOHszsx5Gl","soy9tJIqXi","7ku1pyEfy9","TXQ0Z9GXkX","S77LHQworu","v2eC37hyVv","XflUqt59lR","GrDg7QYxC0",
-"4W0Tli7WMQ","P6bcgni2v1","dQ58655rfB","16lHcUmaEv","v2eC3RBhp0","NcICArz7Ut","b29RJVNCPd","5Nammrz7Ut","vLsmSlCMxy","uLtKshi5X7",
-"FxX9qTwano","sx5Glni2v1","580YD1LB1L","StlDJVerEA","0PktI1LB1L","5nmWvF6PT2","gIYvERkQke","VNCPdCxVEf","AIYUuMmKGJ","0YAGHnnP8o",
-"ydG8UsqVrf","QssNC8RCUA","WmadABCxeC","SbRYyuLtKs","uTacxuLtKs","ZuDtDyEfy9","taOXKVBjhz","hi5X7dQ586","uZPqgKASQ8","RzaZArhl0J",
-"yvOMII7p2a","sqVrfaez9y","ogLgcEOE1o","Chuy3YOfrY","B3qemsuY4x","Twano0Wr5y","MojnPzY1GY","ix74rfqypy","a00b5kB5nP","OHaBzs93Ml",
-"IRh48IBe8k","s93MlB3qem","uoStwciuWz","0KyfstaOXK","s93MlIRh48","jtn0XpT8wu","5ZaEzIBe8k","5VZjSlsQGo","Mkgy8iB08l","d7vjM3weIF",
-"CNHmvoQ87r","tjQxsoGu6x","fcJOy6q6L9","d85a9iB08l","MezSWGSQwj","OHaBzGv3Fq","qUJMdjS1aj","dpe1vnlaBy","lpF6WFwEJz","In3NSNo0Qb",
-"ydG8UOUYuF","uN6r3NOHsz","n8pJ9RzaZA","SbRYyo8Uyd","DQimps93Ml","KsjRKIn3NS","hUTw77X3uy","brhlQqaofN","ThjNntvdkD","vOqCEJIqXi",
-"MK07Yn8pJ9","QbxXcQChxs","ZhwG1WreyP","Cfgr3hUTw7","2hEEUzmLYD","9y4lwjeskS","ZzJHWTCgPp","POUYSXyPZN","5iGN5FGzgp","DcpWBB3qem",
-"JRJQByEfy9","lViBvRBhp0","atef2QClRL","Kr8ysuvf7A","jeskSJXljW","Z4I1vhE1Ql","RkQkeDG4sT","Chuy3ThjNn","FGzgp9rlg9","he9IAMm8si",
-"618DiuAWyp","yofH3FwEJz","24ARFxReec","sqVrfRxrsm","Waim6ZuDtD","5VZjSFFDui","nlaBytl72W","LDk6fguMb8","LDk6f4QMc9","jfREuDG4sT",
-"JkzUnhe9IA","5nmWvv8yFN","soy9tfLNg8","MmsIoFcWrW","Gv3FqKZamH","5nmWvSjskQ","zY1GYMojnP","iwzGkMezSW","2Nslm5Drn0","UmaEvdQ586",
-"14FLRTa8f6","ru4UGTa8f6","FcWrWEdBKc","gjUTuAkKTk","cL0aEW3VFH","8hJdtlkMUA","J2mQiJkzUn","KZamH4QMc9","Mkgy8ix74r","2Yz7En8pJ9",
-"aez9yQbxXc","VIlwPDQimp","iwzGkMGlTF","YjB9t5Drn0","580YDHRxd8","GWqqXfcJOy","55rfBlm0pD","6q6L9In3NS","S2Dfuatef2","y94nwWPmlx",
-"8xEKzOUqFM","OHaBzt98iW","WMiS39eoRc","IRh48WaWsv","ydG8UZ4I1v","3otm6TCgPp","RBhp0e6e4z","KASQ87hyVv","RxrsmECMvU","Oz8yZn1pmO",
-"XyPZNJRJQB","5IhmGmX2GE","2NslmgtCA5","2ZHdkokgRi","Chuy3NhXdu","0Wr5yAOgEe","ru4UGguMb8","CqqaDdhSuH","RzaZAFGzgp","dhSuHhi5X7",
-"W3VFHLbRTH","ogLgcsoy9t","pWiOs9rlg9","IRh4824ARF","a00b5fqypy","b29RJzbIYY","lsQGocQOnv","zbIYYwDajX","JRJQBMGlTF","IjTwP5ZaEz",
-"soy9tRpBQm","FxX9qZv7z0","W7cTsQYxC0","pFrrlpT8wu","RpBQm2hEEU","2TRI7ReKEW","i7WMQtjQxs","Gv3Fqlj07Q","Ss0ZuciuWz","5iGN5uoStw",
-"7fsYMMezSW","euZA5ni2v1","2NslmtjQxs","0MR5XS2Dfu","AmdQduLtKs","FVMxoAIYUu","EoToPuQIcz","x3LDezz4ZU","jfREuMGlTF","fmIK10Wr5y",
-"dhSuHtjQxs","HfyNQFFDui","64s8NWmadA","ni2v1nnP8o","cShY2Uvlv4","Oz8yZQChxs","B3qemxciqp","7X3uy0h1b1","07n1crz7Ut","a00b5JKWYR",
-"zFgtBFFDui","9XyT9WaWsv","RBhp0FVMxo","atef2B3qem","RzaZAjS1aj","RpBQmiqv4k","S2DfuqaofN","tl72Wk85Ae","euZA5VIlwP","LewvMjtn0X",
-"RxrsmdQ586","0KyfsgjUTu","ogLgcQ6Lix","M3zXLECMvU","5Drn0MK07Y","x3LDe3otm6","C2IrcCdyBV","wDajXIBe8k","d7vjMFLsph","hE1Qlni2v1",
-"rz7UtuAWyp","OUYuFgdQsS","IBe8kl83Ud","580YDQ6hMC","Zv7z0ogLgc","uvf7A8U2nU","QClRL55rfB","cShY2rhl0J","Vprf2iKqhr","HfyNQ9GXkX",
-"5nmWvrKDLJ","suY4xGrDg7","VNCPdv2eC3","5drc6b29RJ","UlU3M14FLR","7fsYMG1RhS","8FmFHni2v1","Kr8ysgIYvE","vOqCESWfou","EoToPRBhp0",
-"gIYvEi7WMQ","9GXkXXyPZN","lweGyRzaZA","Q6Lix7lUXZ","C2IrcGSQwj","Twano5ZaEz","1LB1LSbRYy","VNCPdQ6Lix","dpe1vjzUqR","wDajXlkMUA",
-"FFDui1j5L8","6AFT0a00b5","DcpWB9rlg9","CK5W7NcICA","gjUTuIRh48","Z4I1vjS1aj","gIYvEVBjhz","djsrv9GXkX","zHF1qaL6AJ","5Mg9r5VZjS",
-"lm0pDYf2Ec","RACujlj07Q","CqqaDogLgc","e6e4zbgJAz","WMiS3Ta8f6","HRxd8Cfgr3","W7cTsHlUbF","RzaZAvLsmS","fmIK10h1b1","7hyVvcShY2",
-"bZLvSIjTwP","jiVBPblLA9","EoToPzmLYD","5drc6M6qcG","jzUqRfcJOy","ru4UG6AFT0","AOgEeOHaBz","Oz8yZ2TRI7","8FmFH6q6L9","Waim616lHc",
-"JIqXiTCgPp","e6e4zFFDui","QWxoTOxWIH","m4bxUlsQGo","UmaEvNhXdu","24ARFGXdoH","bZLvSMmKGJ","ThjNns93Ml","AmdQduupzk","64s8NMmsIo",
-"9y4lwWMiS3","ksJby0ao3l","Y1mC016lHc","Yh1hFTXQ0Z","8RCUAaFFss","07n1cCNHmv","fLNg8WmadA","CK5W7qQxHP","yvOMI1j5L8","yofH3XyPZN",
-"XflUqxciqp","NAFuwJJs5m","t98iWgdQsS","W3VFH8U2nU","4W0TlB3qem","TXQ0ZUl4a1","Yw2oUix74r","pFrrlWaWsv","yluBxzY1GY","VNCPdxXTI4",
-"ix74rIKxdL","FLsphfqypy","2hEEU0Kyfs","blLA9OUYuF","s7MxkB3qem","QbxXcZuDtD","2hEEUtvdkD","hSSvQOHaBz","zbIYYatef2","7hyVvzHF1q",
-"RzaZAjiVBP","29QAzCqqaD","RBhp0FcWrW","9eoRcI7p2a","lXFOBciuWz","lsQGolViBv","tvdkD24ARF","Q6LixaFFss","atef2aez9y","7ku1phYBCK",
-"vOqCEnlaBy","cL0aEECMvU","BGaQYtl72W","zHF1qVprf2","5Mg9rMkgy8","jSjS3KASQ8","uupzkSmGzv","FGzgp55rfB","In3NSfLNg8","QClRLVIlwP",
-"tl72WJ2mQi","aDGtS0BmCy","WaWsvUvlv4","faHir5VZjS","Cfgr3MGlTF","JIqXihi5X7","Ta8f6iKqhr","AOgEe8hJdt","Zv7z0hSSvQ","tlILtF6PT2",
-"HlUbFVNCPd","lpF6WL7cGc","8FmFHsuY4x","pT8wub29RJ","sx5GlcmXIX","i7WMQhe9IA","FVMxoWmadA","fmIK1s4786","QYxC0euZA5","QChxsk85Ae",
-"CK5W7k85Ae","hE1Ql9iGoT","hSSvQEoToP","oVQp6NOHsz","zFgtBlXFOB","pAhR1RACuj","RsQUqJ2mQi","aDGtS64s8N","7hyVvvkCHH","ThjNnlCMxy",
-"ECMvUGXdoH","QnJ1SlH1kt","lH1ktrz7Ut","CIShGfqypy","tvdkDHP433","Yh1hFLewvM","uupzkFLsph","5Mg9rNo0Qb","sx5GllkMUA","Cfgr3CxVEf",
-"Z4I1ve6e4z","MojnPzmLYD","DG4sTuAWyp","7hyVvYh1hF","Yh1hFPOUYS","jzUqRChuy3","MmsIoQClRL","lm0pDdQ586","cmXIXNo0Qb","Q6hMCMmKGJ",
-"NhXdujSjS3","vLsmSogLgc","iwzGkZzJHW","pWiOsIBe8k","zQt6QhE1Ql","hi5X7uoStw","MezSWMojnP","qQxHPzQt6Q","uoStwydG8U","HP433pAhR1",
-"CK5W7ydG8U","9XyT9Kr8ys","fFDrJ8cVD3","VBjhzNAFuw","SmGzv2hEEU","zFgtBCIShG","BpYhVcL0aE","lpF6WQYxC0","8xEKz7hyVv","Z4I1vpmeCd",
-"pWiOsyvOMI","QYxC0Yf2Ec","pWiOst98iW","48cHLaL6AJ","lH1ktfqypy","0h1b1jiVBP","atef2jeskS","OxWIHuPX7G","tvdkDThjNn","gf8rI5Drn0",
-"YOfrYK20wK","EdBKcSs0Zu","M6qcGW3VFH","Nxx9Vy94nw","YOfrYTwano","nFqikcmXIX","rhl0J7lUXZ","cShY2F6PT2","9GXkXZhwG1","ydG8U48cHL",
-"MGlTFcQOnv","P6bcgQChxs","JRJQBd7vjM","29QAzRACuj","xciqpRxrsm","oGu6x0PktI","CIShGv2eC3","faHirJXljW","07n1cJJs5m","BFkb8AkKTk",
-"ciuWzVIlwP","AkKTkZv7z0","6AFT05drc6","14FLRokgRi","jSjS3KsjRK","okgRi7fsYM","FNYIMpAhR1","QnJ1SUmaEv","n8pJ9S2Dfu","dQ5864W0Tl",
-"nlaByvkCHH","Kr8ysDG4sT","Pb1pa8TxD7","ECMvUK20wK","QnJ1SGXdoH","BFkb8l83Ud","CqqaDDG4sT","48cHLulk41","hi5X78U2nU","DQimp5VZjS",
-"cmXIXBbwgA","a00b5FxX9q","m4bxUDz1R3","Uvlv4LbRTH","aez9yFLsph","8TxD7hSSvQ","GXdoHfcwDa","jtn0XVprf2","RxrsmFjHXR","lkMUAtl72W",
-"uTacxMezSW","vOqCENcICA","FjHXRgf8rI","P6bcgTa8f6","1j5L8C2Irc","Q6LixK20wK","14FLRdpe1v","ulk41CNHmv","SmGzvn1pmO","IKxdLCqqaD",
-"BGaQYPb1pa","W7cTsyofH3","aez9yogLgc","G1RhSfcwDa","zFgtBn8pJ9","ECMvU9iGoT","TXQ0ZMezSW","8xEKzIBe8k","4dEz6NhXdu","uQIczsx5Gl",
-"PYBf4ydG8U","Cfgr3bZLvS","he9IAECMvU","tl72WuoStw","AgJHQYOfrY","vOqCEJXljW","IjTwPzHF1q","pAhR1jiVBP","vOqCErKDLJ","No0QbeuZA5",
-"I7p2aQbxXc","AmdQd24ARF","qQxHPxXTI4","aDGtSKASQ8","okgRi7Ow5C","atef2WreyP","45cIHGWqqX","LDk6flpF6W","CqqaDFGzgp","FjHXRcmXIX",
-"hSSvQ1LB1L","RsQUqzFgtB","zY1GYK20wK","MmsIoMojnP","rhl0J3weIF","zbIYYMK07Y","uLtKsciuWz","uupzkrKDLJ","BGaQYokgRi","RBhp05nmWv",
-"5iGN5zmLYD","0Wr5yZv7z0","xciqpprNT6","Yh1hF07n1c","d85a9hYBCK","GrDg75ZaEz","MmKGJvkCHH","YOfrY9XyT9","HP433618Di","7fsYMwDajX",
-"sqVrf1j5L8","o8Uydi3pyd","blLA9U3yw5","8U2nUzQt6Q","55rfB4W0Tl","m4bxUfqypy","jS1ajuZPqg","rhl0JoVQp6","WmadAaFFss","EoToPYw2oU",
-"AOgEeDLhzM","6AFT0iwzGk","FcWrWv8yFN","faHirKASQ8","4dEz6FGzgp","RsQUqIKxdL","pmeCdTwano","RzaZAi3pyd","3otm6Kr8ys","v8yFNokgRi",
-"POUYSZUnqt","FVMxoZuDtD","48cHLRmDcr","uTacxs4786","AOgEe7Ow5C","n1pmO14FLR","24ARFn8pJ9","hE1Ql5Namm","3otm6Fhtgl","gjUTusoy9t",
-"HP433YOfrY","uvf7A8hJdt","cmXIXxReec","4QMc9Pb1pa","pFrrlWPmlx","5Namms93Ml","cShY2piJSk","MojnPK4GS8","SmGzvuAWyp","Yf2EcnnP8o",
-"tlILtaDGtS","fFDrJ7hyVv","JkzUnZUnqt","sx5Gl2hEEU","VerEAIKxdL","EOE1oXflUq","48cHLlm0pD","tAOsrx3LDe","5drc6HRxd8","jS1aj8hJdt",
-"9y4lwRACuj","Ta8f6OUqFM","O3iyQMm8si","RkQkeBpYhV","IKxdLuJScX","7hyVvOz8yZ","gjUTuzbIYY","8U2nUoQ87r","Yw2oUuAWyp","U3yw5pT8wu",
-"i3pydjeskS","No0Qb4dEz6","ix74rDcpWB","KASQ8ZzJHW","8U2nUo8Uyd","ix74raL6AJ","WDVWJFGzgp","lViBvmz8gx","0h1b1zY1GY","jSjS3vLsmS",
-"uJScXCNHmv","2DREsUlU3M","2TRI7zHF1q","ydG8Un8pJ9","Ss0Zu7Ow5C","5ZaEzJIqXi","580YD8FmFH","n1pmOo8Uyd","DcpWBdhSuH","HfyNQjzUqR",
-"0BmCyuvf7A","QWxoT580YD","lXFOB6q6L9","9XyT9Gv3Fq","5VZjScmXIX","lsQGoTa8f6","pmeCd9GXkX","XyPZN8hJdt","wiHrZpAhR1","7fsYMWreyP",
-"OxWIHkZANm","lj07QHlUbF","jSjS3hUTw7","aez9yK20wK","9eoRcdQ586","KASQ8fmIK1","8xEKzVLTy6","2TRI7RkQke","yToGWfcwDa","jfREuQnJ1S",
-"Zv7z0RzaZA","7X3uyIKxdL","3otm6dpe1v","HlUbFVBjhz","FPfSEzmLYD","DG4sTQWxoT","djsrvkZANm","CxVEffaHir","In3NSix74r","uJScXLewvM",
-"SmGzv29QAz","IjTwP0YAGH","TCgPpm4bxU","RpBQmuupzk","Zv7z00Kyfs","5Drn0FPfSE","m4bxUoQ87r","lpF6Wlj07Q","7Ow5CzQt6Q","FVMxoK4GS8",
-"uvf7Axciqp","mz8gxEOE1o","vkCHH9eoRc","9GXkXHzZT8","8FmFHxciqp","jiVBPjtn0X","WPmlxjtn0X","dQ586y94nw","djsrvW7cTs","YOfrYpiJSk",
-"zHF1q9y4lw","BCxeCWMiS3","0h1b1BCxeC","Ss0Zurhl0J","aL6AJDz1R3","8FmFHSs0Zu","No0QbqQxHP","Yh1hFv8yFN","HRxd8x3LDe","OUqFMBFkb8",
-"xciqpaL6AJ","NhXdulCMxy","ZUnqtwDajX","m4bxUQ6Lix","7hyVv0PktI","ZhwG1RkQke","lkMUAuPX7G","4W0Tl7lUXZ","lweGyBGaQY","0KyfsnFqik",
-"6q6L9yofH3","HlUbF55rfB","brhlQ48cHL","8hJdtdhSuH","bgJAz6q6L9","sqVrfzbIYY","Ta8f6YOfrY","oQ87riKqhr","9rlg9pmeCd","8RCUA5VZjS",
-"6AFT0lweGy","fqypyI7p2a","tvdkDHzZT8","l83UdzFgtB","48cHLpiJSk","RzaZApAhR1","jeskSYf2Ec","lweGy5nmWv","a00b5WMiS3","uAWypLbRTH",
-"hSSvQlm0pD","Vprf2QYxC0","ZhwG1uvf7A","zbIYY1LB1L","djsrvrKDLJ","fmIK1ru4UG","wDajX2Nslm","RzaZAQ6Lix","4QMc9pAhR1","t59lR9XyT9",
-"zqH0Wdjsrv","O3iyQv2eC3","d7vjMzQt6Q","he9IAvLsmS","nFqikSjskQ","iwzGkWreyP","VBjhzrKDLJ","cmXIXgdQsS","gdQsSyvOMI","7lUXZatef2",
-"0ao3l0Kyfs","l83Udjtn0X","Kr8yslm0pD","5ZaEzyToGW","TCgPpFLsph","2Nslms4786","v8yFNJIqXi","BGaQYxReec","uPX7G0PktI","P6bcg14FLR",
-"WreyPydG8U","BFkb84QMc9","m4bxUSWfou","OxWIHcL0aE","WaWsv0BmCy","FjHXR580YD","M6qcG2DREs","rKDLJtl72W","jzUqRP6bcg","xReecIRh48",
-"dmoS7UlU3M","wiHrZ55rfB","cL0aEvkCHH","guMb8Yw2oU","guMb8ZJTXH","3otm6Twano","SmGzvlViBv","blLA9fLNg8","he9IAJRJQB","JJs5m29QAz",
-"K4GS8RACuj","NhXdu7hyVv","fLNg8aDGtS","Twanov1Hln","5Drn0NAFuw","9y4lwFLsph","MaJQsJKWYR","nlaByMmsIo","DcpWBI7p2a","0Kyfs8FmFH",
-"1j5L8ZUnqt","24ARFni2v1","Y1mC0ni2v1","aFFssDcpWB","0ao3lBCxeC","QbxXcWMiS3","8U2nUhi5X7","2hEEU5VZjS","bgJAz7Ow5C","IjTwPiB08l",
-"1j5L8gf8rI","qUJMdv1Hln","WreyPYw2oU","xXTI4jfREu","48cHLdmoS7","55rfBn1pmO","LDk6fWreyP","TCgPpprNT6","uAWypU3yw5","MGlTFBbwgA",
-"7ku1p8cVD3","JKWYRM6qcG","ThjNn8TxD7","0YAGHzz4ZU","nlaBy5drc6","VLTy6nnP8o","zQt6Qy94nw","POUYSQ6hMC","HRxd8oVQp6","lsQGoFxX9q",
-"Q6LixOxWIH","W7cTslpF6W","LewvMsqVrf","0BmCyUvlv4","fmIK1h1zcH","CNHmvThjNn","Z4I1vtAOsr","NOHszs7Mxk","5drc6Mkgy8","oGu6xRsQUq",
-"M3zXL55rfB","v1Hln2DREs","lViBv7X3uy","ogLgc7Ow5C","xReecYjB9t","v2eC3pT8wu","G1RhSsqVrf","MaJQs8xEKz","bZLvSpFrrl","VerEA5Mg9r",
-"AkKTkYh1hF","0h1b1CqqaD","W3VFHyofH3","yofH38TxD7","EdBKcIRh48","jSjS3oVQp6","rKDLJlkMUA","0PktIMojnP","gtCA5qUJMd","OUqFMCxVEf",
-"rhl0JtAOsr","FPfSEpT8wu","s4786FxX9q","AkKTkXflUq","SmGzvBpYhV","29QAzKZamH","a00b5fmIK1","mz8gxv8yFN","atef27Ow5C","AkKTkgIYvE",
-"tjQxsYOfrY","XyPZNPb1pa","b29RJiqv4k","JJs5mI7p2a","IjTwPgjUTu","GWqqXXyPZN","FNYIMUvlv4","WreyPaFFss","VjCZqa00b5","RxrsmSjskQ",
-"16lHclCMxy","nFqikW3VFH","uTacx45cIH","2hEEUyvOMI","OHaBzNhXdu","Fhtgl5Mg9r","pWiOsyToGW","fcJOyY1mC0","DQimpqaofN","QYxC0rz7Ut",
-"C2IrcBpYhV","2DREsvkCHH","dmoS7EOE1o","FhtglSs0Zu","ThjNnqaofN","OHaBzfaHir","No0QbGv3Fq","zFgtBgf8rI","n8pJ9zz4ZU","TwanolH1kt",
-"lkMUAbZLvS","OUYuF14FLR","oGu6x4QMc9","xXTI4BGaQY","8hJdtvkCHH","DcpWBK4GS8","618Di8FmFH","IKxdLpv0i7","6AFT0djsrv","jfREugjUTu",
-"prNT6WreyP","s7MxkLDk6f","FwEJzmz8gx","EOE1oi7WMQ","5iGN5OHaBz","2ZHdk5iGN5","7fsYMReKEW","29QAzFwEJz","1j5L8DG4sT","KsjRKXyPZN",
-"VNCPdUlU3M","QworuXflUq","8hJdtpT8wu","ciuWzTCgPp","D6rByDcpWB","0PktI0BmCy","e6e4zyofH3","cL0aEaFFss","uAWypCqqaD","tAOsrjfREu",
-"lViBvPYBf4","gf8rI2ZHdk","v1HlneuZA5","M6qcGrKDLJ","ReKEWlCMxy","TCgPpgIYvE","lCMxyS2Dfu","l83UdjeskS","kB5nPaFFss","Yw2oUzbIYY",
-"8FmFHTwano","3otm6pvgjS","8FmFHIn3NS","ZhwG1SmGzv","JXljW7Ow5C","uQIczVerEA","FFDuiWmadA","IRh48HRxd8","GWqqXjtn0X","O3iyQNOHsz",
-"7fsYM0MR5X","5ZaEzYOfrY","hSSvQjtn0X","v8yFNgjUTu","MK07Y6q6L9","hE1QlTa8f6","JKWYR2hEEU","07n1cU3yw5","suY4xQClRL","StlDJHlUbF",
-"jS1ajTCgPp","uZPqgRsQUq","Y1mC0Chuy3","y94nwdhSuH","jS1ajOHaBz","s93MlAOgEe","VBjhzNOHsz","VNCPdTa8f6","W7cTs9GXkX","07n1cRxrsm",
-"RsQUqLDk6f","zFgtBOxWIH","d7vjM8RCUA","0ao3lFNYIM","JRJQBlj07Q","8RCUACp3mZ","oGu6x0MR5X","taOXK0Wr5y","5drc6NhXdu","l83Udru4UG",
-"SmGzv5Namm","qaofNZzJHW","iB08lzbIYY","lpF6Wl83Ud","lsQGoix74r","tvdkDWaWsv","zHF1qOz8yZ","dpe1vHlUbF","16lHc2Nslm","xciqpF6PT2",
-"v1HlncL0aE","lXFOBguMb8","7fsYMB3qem","qUJMdzY1GY","uvf7AkZANm","lkMUAzFgtB","JRJQBy94nw","BpYhVRpBQm","FhtglM6qcG","okgRizz4ZU",
-"cL0aE9iGoT","ix74rGWqqX","FwEJzCqqaD","uupzklpF6W","yEfy9pv0i7","07n1cuQIcz","zQt6QMK07Y","fFDrJxXTI4","uJScX7X3uy","2NslmhSSvQ",
-"h1zcHX6Pin","fmIK1MaJQs","xReecWaim6","qUJMdBpYhV","m4bxUHRxd8","fFDrJlViBv","djsrvvOqCE","J2mQiRxrsm","2hEEUZuDtD","G1RhSZUnqt",
-"1LB1LdhSuH","Ss0ZuZuDtD","ZUnqtulk41","CdyBVXyPZN","S2Dfu580YD","uN6r3I7p2a","U3yw5WaWsv","2ZHdkRkQke","LewvMnlaBy","FVMxoJkzUn",
-"AmdQduvf7A","okgRiRzaZA","6q6L9YOfrY","bgJAzogLgc","VerEA9y4lw","fcJOy8FmFH","n1pmOs93Ml","aL6AJvLsmS","QbxXcn1pmO","cShY2aL6AJ",
-"ZzJHW64s8N","iqv4kFLsph","zbIYYt59lR","aez9yAkKTk","1LB1Llm0pD","Chuy3pvgjS","iwzGklm0pD","hSSvQcShY2","Vprf2ZzJHW","VNCPdJkzUn",
-"Mkgy87fsYM","FjHXR55rfB","RpBQmaez9y","prNT6ulk41","lkMUAQClRL","9rlg9SjskQ","RkQkesqVrf","EoToPJkzUn","Q6hMCZUnqt","taOXK4W0Tl",
-"I7p2aD6rBy","5ZaEzokgRi","wiHrZAXpwE","OUYuF5Mg9r","Dz1R3Qworu","4dEz6FVMxo","xciqphSSvQ","lj07QVNCPd","2TRI7No0Qb","K4GS8yEfy9",
-"h1zcHQnJ1S","qUJMdwiHrZ","i3pydZuDtD","wDajXBCxeC","i7WMQBbwgA","SbRYy4W0Tl","JKWYR8RCUA","HlUbFtaOXK","sqVrflm0pD","iB08lsqVrf",
-"tlILt16lHc","cmXIXVLTy6","YOfrYLewvM","cmXIXbrhlQ","a00b5l83Ud","FFDuiyEfy9","Q6hMCB3qem","tl72WjSjS3","0KyfsECMvU","0h1b1oQ87r",
-"zQt6Q7lUXZ","Fhtglv8yFN","jtn0XdQ586","1LB1LQChxs","Uvlv4Qworu","LDk6fCp3mZ","AgJHQFNYIM","0BmCyDz1R3","pFrrllpF6W","ZhwG1JkzUn",
-"QbxXcrz7Ut","JkzUnk85Ae","4QMc95ZaEz","b29RJ14FLR","6AFT0bgJAz","vLsmSJ2mQi","iqv4kRzaZA","9eoRcnnP8o","uupzkqQxHP","vkCHHfcJOy",
-"Chuy3y94nw","7lUXZ3otm6","yToGWm4bxU","VBjhzZzJHW","dhSuHuoStw","L7cGcBpYhV","aFFssFPfSE","FxX9q55rfB","LDk6fi7WMQ","9eoRc580YD",
-"v2eC35Drn0","FVMxozmLYD","jiVBPvLsmS","y94nwjfREu","zQt6QQworu","YOfrYW3VFH","gf8rI6AFT0","WaWsvtAOsr","cShY2lH1kt","s93MlciuWz",
-"S77LHBGaQY","cmXIXhYBCK","5iGN5bZLvS","S77LHiwzGk","1v5hH7hyVv","cmXIX2Nslm","pFrrlI7p2a","uupzkMK07Y","TXQ0ZKr8ys","Dz1R3soy9t",
-"fmIK1uPX7G","uN6r3lm0pD","VLTy6gjUTu","WmadAQworu","1LB1LxXTI4","yluBxJKWYR","AIYUuJkzUn","gdQsSEoToP","WMiS3K4GS8","4W0TlIBe8k",
-"9rlg9brhlQ","Ss0Zuzz4ZU","48cHL2Nslm","iqv4kYOfrY","Vprf2Oz8yZ","0PktIQYxC0","45cIHjiVBP","pFrrl8U2nU","uTacx5Drn0","Waim6JRJQB",
-"piJSkYjB9t","FNYIMzFgtB","s93MlG1RhS","IKxdL5Drn0","HlUbFlViBv","14FLRRmDcr","POUYSfFDrJ","hi5X70MR5X","JXljWCdyBV","W3VFHuZPqg",
-"L7cGcJKWYR","I7p2apFrrl","k85AeMmsIo","VBjhzlViBv","ZUnqtatef2","SbRYylj07Q","KASQ8QWxoT","mX2GEQbxXc","e6e4zhYBCK","4W0TlGSQwj",
-"G1RhSulk41","C2IrcGrDg7","faHirZv7z0","fcJOylXFOB","faHir29QAz","IjTwPOxWIH","jfREuuvf7A","iwzGk55rfB","jSjS3MezSW","KsjRKaez9y",
-"yToGWVprf2","cQOnvvLsmS","0h1b1LbRTH","5Drn0QChxs","xReecfcJOy","WaWsvksJby","h1zcHK20wK","hE1Ql9rlg9","bgJAzHzZT8","1v5hH0h1b1",
-"vLsmSQssNC","Waim6ix74r","n1pmOIKxdL","v1HlnMezSW","1v5hHjSjS3","jeskSZv7z0","9iGoTYh1hF","5Mg9ruPX7G","fcwDaCIShG","QnJ1SzY1GY",
-"PYBf4uoStw","ZUnqtsoy9t","8TxD7W7cTs","wiHrZGv3Fq","jzUqRguMb8","O3iyQatef2","M3zXLt98iW","blLA9No0Qb","JJs5mUlU3M","GSQwjgf8rI",
-"8hJdtWPmlx","OUYuFFnPFB","Waim6AkKTk","vkCHHeuZA5","2TRI7DQimp","AkKTkOxWIH","K4GS82Nslm","rhl0Ji3pyd","48cHLQnJ1S","s7MxkciuWz",
-"ZhwG1ZhwG1","CqqaDbgJAz","Cfgr3WPmlx","jeskSix74r","7lUXZbrhlQ","C2Irc3otm6","HfyNQUlU3M","pvgjSlsQGo","DG4sTZuDtD","8hJdtQ6Lix",
-"IKxdLOUYuF","rKDLJGSQwj","dhSuH64s8N","5VZjSDLhzM","4dEz6fFDrJ","MojnPHfyNQ","JkzUnfcwDa","EdBKc0h1b1","yToGW0h1b1","xciqptlILt",
-"P6bcg5Mg9r","GSQwjReKEW","Qworu0YAGH","oVQp6IBe8k","2NslmDG4sT","uupzkFVMxo","2Yz7EPOUYS","NOHszB3qem","v2eC3Q6Lix","lsQGouN6r3",
-"jS1ajSmGzv","djsrvFcWrW","7lUXZs93Ml","K4GS8djsrv","55rfBMK07Y","sx5GlEOE1o","lViBvSWfou","ZhwG1HfyNQ","I7p2a618Di","hSSvQJXljW",
-"7fKYUNOHsz","FFDuiIjTwP","lXFOBVerEA","ZzJHWtlILt","5drc6zmLYD","L7cGcgjUTu","PYBf4HlUbF","580YDjtn0X","MK07YjfREu","ogLgcS2Dfu",
-"FxX9qVIlwP","CdyBVVprf2","FNYIMSWfou","pAhR1tuDyS","W7cTsRmDcr","SjskQqUJMd","brhlQ9XyT9","soy9tBbwgA","lViBvJkzUn","Z4I1vWPmlx",
-"zY1GYRBhp0","cmXIXsqVrf","45cIHBFkb8","9y4lw7lUXZ","iqv4kTCgPp","7fKYUksJby","0h1b1D6rBy","nnP8oyToGW","Chuy3QYxC0","v1HlnBGaQY",
-"3weIFUvlv4","55rfB9iGoT","1j5L8jtn0X","RkQkeXyPZN","7hyVvFjHXR","45cIH64s8N","IKxdLDz1R3","PYBf4EdBKc","pT8wuFjHXR","jfREuBCxeC",
-"VerEAsx5Gl","gjUTubrhlQ","0PktIuAWyp","29QAzjzUqR","fFDrJbrhlQ","okgRi9XyT9","ulk412hEEU","yofH3gf8rI","JKWYRAkKTk","9y4lwZUnqt",
-"uoStw0PktI","xciqpWMiS3","x3LDexReec","wDajXHRxd8","nnP8oJJs5m","JJs5mEOE1o","X6PingtCA5","Waim60YAGH","uN6r3OxWIH","VBjhz5nmWv",
-"cL0aEFVMxo","pWiOsPb1pa","GWqqXuAWyp","LewvMiKqhr","Mm8siCp3mZ","Cp3mZOUqFM","mz8gxD6rBy","ogLgc0BmCy","No0Qbru4UG","Ss0ZuMm8si",
-"7lUXZgdQsS","AkKTkIRh48","BbwgAOUYuF","BbwgAyluBx","dpe1vNo0Qb","xReecZhwG1","BCxeCNAFuw","AIYUu8hJdt","C2IrcNAFuw","gf8rICNHmv",
-"RxrsmSbRYy","RzaZAcShY2","X6Pinrhl0J","64s8NJXljW","DLhzMLbRTH","2DREsjeskS","tuDyS9XyT9","MaJQsGWqqX","v2eC3FnPFB","mz8gx9y4lw",
-"pmeCdtl72W","rz7UtLbRTH","jiVBPS2Dfu","9y4lwYOfrY","0ao3lYf2Ec","9rlg9Cp3mZ","o8UydNcICA","BCxeCru4UG","ydG8UiKqhr","MGlTFKASQ8",
-"blLA9POUYS","HlUbFD6rBy","580YDQssNC","t59lRVerEA","7fKYUzY1GY","faHirEoToP","0BmCylsQGo","5Mg9rFnPFB","KZamHC2Irc","Ul4a1xciqp",
-"rKDLJQnJ1S","ZzJHWDcpWB","zmLYDl83Ud","zbIYYhSSvQ","tAOsrJXljW","yEfy9i3pyd","NhXduNOHsz","o8Uyd4W0Tl","taOXKTXQ0Z","HlUbFKr8ys",
-"Mkgy8ReKEW","MK07YXflUq","t98iWQ6hMC","LewvM8FmFH","djsrvM3zXL","uvf7A29QAz","Dz1R3zbIYY","zz4ZUFFDui","FnPFBMojnP","uvf7AIn3NS",
-"ogLgcJKWYR","pT8wun8pJ9","6AFT05iGN5","2hEEUh1zcH","guMb8Pb1pa","jeskSKsjRK","sqVrf1LB1L","pv0i7Mm8si","5Drn0OUqFM","U3yw5OxWIH",
-"DcpWBfcwDa","FGzgpWPmlx","0BmCypiJSk","fcwDa8TxD7","0BmCyJkzUn","oVQp6AIYUu","Y1mC0StlDJ","nnP8o4dEz6","hUTw7soy9t","7ku1p7fsYM",
-"VIlwP2TRI7","8hJdtFNYIM","vOqCEcmXIX","nnP8oMm8si","BpYhVbZLvS","RmDcruQIcz","ZhwG1lweGy","24ARF2Nslm","JKWYROz8yZ","vOqCEFnPFB",
-"oVQp6qaofN","F6PT2qaofN","K20wKhSSvQ","v1HlnFLsph","vLsmSjSjS3","rhl0Jn1pmO","D6rByCqqaD","faHirGv3Fq","55rfBkB5nP","S77LHNo0Qb",
-"5ZaEzwDajX","7fKYUOUYuF","RkQkekZANm","Zv7z0JJs5m","B3qemzz4ZU","Gv3Fqgf8rI","yofH3WPmlx","0ao3lMojnP","pWiOsQnJ1S","vLsmSi3pyd",
-"KsjRKs93Ml","7hyVv2hEEU","ZuDtDaL6AJ","dhSuHgdQsS","m4bxUW7cTs","hYBCKxXTI4","YOfrY0h1b1","atef2Qworu","tlILtjtn0X","Nxx9VQworu",
-"QWxoT1j5L8","lkMUA5VZjS","QWxoTjzUqR","taOXKJKWYR","TwanoZuDtD","5NammRkQke","dpe1vjtn0X","0BmCyPYBf4","jfREuQChxs","6AFT0mX2GE",
-"RkQkeFNYIM","sx5Gl5Drn0","NOHsz14FLR","h1zcHdQ586","ZzJHWvkCHH","XyPZNCNHmv","QChxslj07Q","soy9tXyPZN","FxX9qCNHmv","BbwgAUl4a1",
-"AmdQdZ4I1v","ciuWzs7Mxk","Pb1paFPfSE","S2DfuCdyBV","RBhp08TxD7","9eoRchE1Ql","WmadAIBe8k","NcICAQnJ1S","EdBKcVBjhz","TCgPpQChxs",
-"StlDJ07n1c","7Ow5CNAFuw","GrDg79iGoT","s93MlcL0aE","5IhmGRACuj","BGaQY5ZaEz","xciqp5Mg9r","he9IAix74r","okgRiYw2oU","uAWypQClRL",
-"3otm6dmoS7","1j5L8ru4UG","0BmCyt98iW","FnPFBVBjhz","Z4I1vrhl0J","uvf7AMaJQs","Kr8ysGv3Fq","GSQwjFjHXR","t98iWW7cTs","RzaZAxXTI4",
-"KASQ89XyT9","aL6AJBbwgA","he9IAUvlv4","lm0pDokgRi","Dz1R34QMc9","OHaBzEdBKc","618DiBbwgA","oGu6xP6bcg","WmadAFhtgl","O3iyQG1RhS",
-"tAOsrRmDcr","OUYuFeuZA5","v8yFNIn3NS","vkCHH8xEKz","gf8rIXyPZN","6q6L9pv0i7","pAhR1RpBQm","RmDcrpiJSk","1LB1LVBjhz","48cHLOxWIH",
-"Vprf2DcpWB","FNYIMWPmlx","uTacxQClRL","9y4lwgdQsS","Q6Lix48cHL","oVQp6s4786","ciuWzdjsrv","fcwDasqVrf","zmLYDs7Mxk","lH1ktl83Ud",
-"QClRLKsjRK","4QMc9BbwgA","lpF6WVNCPd","AgJHQblLA9","sqVrf24ARF","tlILtpmeCd","AgJHQ16lHc","SbRYy5Drn0","y94nw45cIH","16lHc7ku1p",
-"Qworu5ZaEz","v8yFN1v5hH","azIWp5iGN5","0h1b1fFDrJ","No0QbyluBx","QbxXcHlUbF","5drc6IBe8k","07n1cpmeCd","JXljWs7Mxk","7lUXZNOHsz",
-"MGlTFD6rBy","IjTwPCfgr3","VerEAzQt6Q","BCxeCgIYvE","JKWYRBCxeC","dmoS7mz8gx","IRh48Ss0Zu","jSjS3oQ87r","QbxXcsx5Gl","Pb1paMmsIo",
-"FjHXRtAOsr","aDGtS0ao3l","SjskQX6Pin","tl72WQbxXc","AmdQdHfyNQ","cQOnv5nmWv","atef2uAWyp","rhl0J8cVD3","4dEz69eoRc","i3pydIBe8k",
-"uPX7GfcwDa","3otm6hYBCK","cL0aE8FmFH","CxVEfQworu","nnP8ofmIK1","yEfy9gIYvE","fcJOytvdkD","UmaEv2Nslm","5IhmGfcJOy","lpF6WiwzGk",
-"zmLYDJXljW","FFDui618Di","M3zXLm4bxU","gIYvEokgRi","NOHszkZANm","5drc6kZANm","SWfouTwano","8cVD3zFgtB","tuDySAOgEe","2NslmNcICA",
-"QYxC0Nxx9V","14FLRm4bxU","P6bcgv8yFN","XyPZNs93Ml","oQ87rQChxs","gdQsS8cVD3","vkCHHKsjRK","tl72WzQt6Q","QssNC7fsYM","5ZaEz0ao3l",
-"dpe1vUlU3M","QChxsOUYuF","ZzJHWn8pJ9","cL0aEwDajX","bgJAzpvgjS","QssNCxXTI4","QnJ1SfLNg8","tjQxst59lR","AXpwExXTI4","taOXKHP433",
-"ydG8U9iGoT","dmoS7Qworu","pT8wugdQsS","ECMvUbZLvS","brhlQnlaBy","Gv3FqLewvM","i7WMQ2hEEU","X6PinblLA9","aL6AJYf2Ec","aez9yW7cTs",
-"kB5nP8cVD3","9rlg9Pb1pa","dhSuHgf8rI","QClRLuoStw","D6rByGWqqX","jtn0XPb1pa","lweGyRkQke","pFrrlNhXdu","faHireuZA5","D6rBy4QMc9",
-"RzaZADQimp","gf8rIOxWIH","fFDrJPOUYS","Gv3Fqi7WMQ","TCgPpRmDcr","0YAGHgdQsS","rKDLJa00b5","4dEz60PktI","d85a9tuDyS","gtCA5zQt6Q",
-"P6bcg3weIF","IKxdLZUnqt","pFrrlQworu","8U2nUJJs5m","W3VFHZv7z0","0BmCy24ARF","JJs5mSWfou","soy9tO3iyQ","RkQkeQssNC","uvf7AvkCHH",
-"580YDyofH3","No0QbFhtgl","G1RhSa00b5","VLTy6FGzgp","U3yw5kB5nP","d7vjMtaOXK","XflUqSs0Zu","Ul4a1djsrv","prNT6BFkb8","FLsphFxX9q",
-"jtn0X2ZHdk","OHaBzi7WMQ","JJs5m0PktI","ZJTXHMGlTF","5iGN50YAGH","yluBxBCxeC","pFrrl3weIF","CqqaDHRxd8","580YDLDk6f","yvOMI07n1c",
-"bgJAzXflUq","Kr8ys45cIH","IRh48I7p2a","5Mg9rPYBf4","lkMUAtuDyS","AIYUul83Ud","IBe8knlaBy","pvgjSfqypy","DLhzM2Nslm","n1pmOFhtgl",
-"TwanoNxx9V","9GXkXl83Ud","Kr8ys0MR5X","W7cTsn1pmO","pv0i7blLA9","suY4xMm8si","FFDuiIKxdL","nlaByVerEA","qUJMds93Ml","2Yz7EzHF1q",
-"VBjhzGrDg7","I7p2aksJby","n1pmOsqVrf","8hJdtRsQUq","FwEJzJJs5m","s7Mxkzz4ZU","VNCPdkB5nP","14FLRdQ586","k85AevkCHH","ydG8UlViBv",
-"J2mQis4786","d7vjMF6PT2","NcICAAkKTk","SWfoufcwDa","Cfgr3uPX7G","ni2v1ZzJHW","EoToPNxx9V","StlDJh1zcH","UmaEvlkMUA","tvdkDni2v1",
-"cL0aESjskQ","cL0aECIShG","uoStwdjsrv","Vprf20h1b1","vLsmSFFDui","2Yz7EEdBKc","pvgjSgf8rI","K4GS8iwzGk","suY4xuN6r3","14FLRQbxXc",
-"yofH3fmIK1","hUTw7QYxC0","Chuy3MojnP","ru4UGMojnP","oVQp6iqv4k","DcpWBkZANm","t59lRe6e4z","MK07YMezSW","aDGtSdjsrv","y94nwuAWyp",
-"J2mQiMmKGJ","JkzUn55rfB","JRJQBrz7Ut","6AFT0TCgPp","OUqFMjtn0X","ni2v1Ul4a1","LewvMLbRTH","QClRLdpe1v","VLTy6Uvlv4","6AFT0sx5Gl",
-"UlU3MsuY4x","0KyfsEoToP","MezSW8RCUA","GXdoHkZANm","580YDyToGW","lsQGoTwano","atef2n8pJ9","aez9yJkzUn","Z4I1v8FmFH","K4GS8ZzJHW",
-"euZA5yToGW","Yh1hF1v5hH","OxWIHNOHsz","jtn0XYw2oU","I7p2aTa8f6","rKDLJ8RCUA","ECMvUD6rBy","64s8NX6Pin","Z4I1vBbwgA","BbwgA5ZaEz",
-"jSjS3wDajX","lweGyNhXdu","ReKEW5Drn0","NcICAKr8ys","4QMc9zqH0W","pv0i7SWfou","s4786xReec","D6rByRkQke","mX2GEdhSuH","W3VFHmz8gx",
-"FxX9qYOfrY","8hJdttjQxs","9GXkXEdBKc","3weIFgtCA5","Vprf2jtn0X","8TxD7FxX9q","7Ow5C9iGoT","ZzJHWZJTXH","WPmlx5VZjS","yEfy9zY1GY",
-"U3yw5ZJTXH","UlU3M5IhmG","wiHrZjfREu","DLhzMyEfy9","uoStwWmadA","gdQsSlj07Q","pAhR114FLR","HP433ksJby","iB08l7fsYM","U3yw5CqqaD",
-"EdBKc8U2nU","tlILtydG8U","pmeCdjiVBP","HzZT8xciqp","Nxx9V5Mg9r","5drc60Kyfs","M3zXL0h1b1","tlILtOHaBz","zQt6QQ6Lix","EdBKc7X3uy",
-"QClRL0BmCy","QWxoTt98iW","8RCUA07n1c","YOfrYQYxC0","RsQUqWmadA","ksJbyQbxXc","GrDg7jSjS3","ydG8UQ6hMC","iqv4kn8pJ9","DcpWBBCxeC",
-"tAOsrrhl0J","J2mQid7vjM","CIShGzbIYY","M6qcGVNCPd","qaofNVerEA","MGlTF5iGN5","UmaEvuvf7A","zqH0WCp3mZ","Q6Lix8hJdt","MmKGJFhtgl",
-"soy9tIBe8k","X6PintaOXK","DQimpoVQp6","Y1mC0fFDrJ","3otm6MaJQs","CNHmvd85a9","aez9yJIqXi","StlDJvLsmS","PYBf4ni2v1","GSQwjaFFss",
-"DG4sT0YAGH","FcWrWUlU3M","0BmCyJ2mQi","RpBQmPOUYS","sqVrf0PktI","1LB1L0BmCy","i3pydlj07Q","FNYIM55rfB","0ao3li3pyd","ZuDtDStlDJ",
-"GSQwjQWxoT","8xEKzuupzk","618DiQnJ1S","iwzGkS2Dfu","fcJOyOUqFM","2DREsFjHXR","ZuDtDPYBf4","CqqaDlm0pD","JJs5ms4786","PYBf4yToGW",
-"fmIK1VBjhz","Qworuuvf7A","SmGzvrhl0J","WDVWJwDajX","s93MlFNYIM","djsrvjiVBP","i7WMQRmDcr","24ARFLewvM","5iGN5lj07Q","mX2GELewvM",
-"I7p2a64s8N","nFqik5ZaEz","8xEKzECMvU","2TRI7okgRi","pT8wu7ku1p","hE1QluoStw","Twanoe6e4z","48cHLQ6Lix","sx5GlMojnP","Q6hMCRzaZA",
-"ZzJHWBpYhV","HfyNQnFqik","b29RJx3LDe","kB5nPhE1Ql","5iGN5fqypy","O3iyQs4786","IBe8kbrhlQ","nFqikWPmlx","UmaEvl83Ud","dpe1vtaOXK",
-"I7p2aCp3mZ","MmKGJGSQwj","NAFuwWPmlx","Gv3FqNAFuw","azIWpydG8U","VjCZqpv0i7","FxX9qoVQp6","DQimpTCgPp","rhl0JnnP8o","Dz1R34dEz6",
-"NcICA618Di","brhlQNAFuw","IBe8kUmaEv","nFqikCfgr3","4dEz6zY1GY","FxX9qRsQUq","EOE1ouTacx","fFDrJRACuj","In3NSlm0pD","OHaBzlkMUA",
-"rKDLJoGu6x","ZuDtDS2Dfu","fmIK1uvf7A","QChxsgjUTu","WPmlxL7cGc","OUqFMk85Ae","4W0TlStlDJ","fmIK1Z4I1v","jeskSaL6AJ","s93MlsqVrf",
-"rz7UtMGlTF","AmdQdpmeCd","wiHrZI7p2a","uLtKsdhSuH","Mkgy87ku1p","QClRLQ6hMC","K20wK7hyVv","5iGN5jS1aj","uZPqgJKWYR","YjB9tsqVrf",
-"24ARFd85a9","CNHmvbgJAz","gdQsSn1pmO","WmadAXyPZN","ni2v1LewvM","48cHLRBhp0","6AFT0Q6hMC","0ao3l9GXkX","IKxdL29QAz","vLsmScL0aE",
-"vkCHHTa8f6","NcICAIjTwP","MmKGJfLNg8","cShY2okgRi","Dz1R3No0Qb","W3VFHQ6hMC","LbRTHo8Uyd","OHaBzAOgEe","x3LDe9y4lw","BGaQYKsjRK",
-"zmLYD5ZaEz","nnP8ogdQsS","PYBf4ix74r","7ku1pt98iW","XflUqKASQ8","pmeCd9y4lw","VBjhzMGlTF","wiHrZzmLYD","i7WMQIBe8k","hSSvQIKxdL",
-"JKWYRC2Irc","KsjRKCfgr3","pmeCdGrDg7","24ARFCNHmv","0MR5XlViBv","8U2nUZ4I1v","Y1mC06AFT0","0MR5XHRxd8","iwzGkoVQp6","16lHckZANm",
-"yToGWnlaBy","BFkb81j5L8","KASQ8GrDg7","rhl0JkZANm","WaWsv9y4lw","yEfy98U2nU","W3VFHMK07Y","AXpwEru4UG","XyPZNh1zcH","pvgjSMm8si",
-"pvgjSLbRTH","QChxs8U2nU","1v5hHCIShG","FcWrWRzaZA","FxX9qwDajX","OUqFM0h1b1","WaWsvoVQp6","YjB9tgIYvE","6AFT0618Di","QbxXcl83Ud",
-"IjTwPNhXdu","B3qemWMiS3","dQ5868cVD3","prNT6yluBx","v8yFNTXQ0Z","t98iWt59lR","1j5L87Ow5C","fqypyIjTwP","3weIFaez9y","BbwgAYjB9t",
-"EoToPjiVBP","BCxeCTwano","0YAGHjtn0X","xXTI4o8Uyd","RxrsmaL6AJ","KASQ8QYxC0","uupzkIjTwP","5NammNAFuw","Cfgr3Waim6","QssNCQworu",
-"Twano9eoRc","tl72WblLA9","KASQ8ydG8U","Ta8f6tlILt","azIWpFwEJz","tjQxscL0aE","UlU3MNOHsz","5Nammy94nw","a00b5Zv7z0","RkQkeGXdoH",
-"kZANmGv3Fq","LbRTHuPX7G","Uvlv4n1pmO","YjB9tuN6r3","tlILtuQIcz","tAOsrsoy9t","S77LHtvdkD","8FmFHZv7z0","mz8gx1j5L8","JIqXi64s8N",
-"8xEKz55rfB","aFFssVprf2","nnP8ogIYvE","0BmCyMaJQs","ZuDtDazIWp","Yh1hFtjQxs","7fsYMa00b5","o8Uyd0Kyfs","29QAzZv7z0","fqypydmoS7",
-"CK5W7fLNg8","5iGN5aFFss","ReKEWTa8f6","SmGzvCxVEf","n8pJ9pmeCd","TwanoHRxd8","jiVBPn8pJ9","OUYuFP6bcg","guMb8jzUqR","pv0i79GXkX",
-"oQ87rW7cTs","y94nwdQ586","XyPZNRBhp0","ZJTXH3otm6","d7vjMdpe1v","he9IAqQxHP","rKDLJaDGtS","lH1ktvOqCE","k85AeMezSW","Vprf20ao3l",
-"CK5W7atef2","QChxsMojnP","S2Dfuy94nw","QChxsDG4sT","Cfgr3XyPZN","ni2v1MGlTF","qUJMduupzk","mX2GEVprf2","OUYuFtl72W","FLsphd7vjM",
-"FwEJzAXpwE","8hJdtlCMxy","FNYIM2DREs","9GXkX45cIH","VNCPdIBe8k","ThjNny94nw","FhtglZzJHW","F6PT2taOXK","zHF1qpv0i7","14FLRJKWYR",
-"FnPFBsx5Gl","5ZaEzVjCZq","wDajXQClRL","oQ87r4W0Tl","2NslmoVQp6","SWfouRkQke","aL6AJiB08l","xXTI4nlaBy","h1zcHW7cTs","Chuy3JXljW",
-"RBhp0UmaEv","cL0aEgdQsS","zY1GY7fsYM","fFDrJDcpWB","QWxoTuvf7A","8hJdt4dEz6","QssNCy94nw","qUJMdPb1pa","Yf2EcNo0Qb","HlUbFEOE1o",
-"RxrsmFwEJz","mz8gxQssNC","HlUbFP6bcg","PYBf4nFqik","SjskQKr8ys","cQOnvS77LH","3otm6Yf2Ec","ZhwG1zY1GY","Q6LixciuWz","WMiS3MGlTF",
-"RkQkev1Hln","ni2v1KZamH","atef2HRxd8","taOXKUl4a1","mX2GEm4bxU","ZUnqtzY1GY","dQ586Uvlv4","lXFOB9XyT9","atef2uupzk","0KyfsK20wK",
-"CIShGuQIcz","iwzGkJkzUn","Yh1hFix74r","CK5W7Uvlv4","FLsphyvOMI","jfREu9eoRc","jSjS3zmLYD","nnP8omz8gx","0h1b1tjQxs","i7WMQwiHrZ",
-"7fKYU2TRI7","0MR5Xh1zcH","8cVD35drc6","jfREuRACuj","n1pmOYh1hF","M3zXLFhtgl","7ku1pVBjhz","7ku1pMGlTF","AIYUu2Yz7E","K20wKzQt6Q",
-"Ul4a1taOXK","nnP8oBpYhV","zHF1qECMvU","HRxd8Ta8f6","F6PT2J2mQi","YOfrYOUqFM","2NslmRACuj","FcWrWyofH3","IjTwPUmaEv","FGzgpUlU3M",
-"SjskQs7Mxk","HfyNQ8U2nU","0PktIyofH3","8U2nUmz8gx","i7WMQ5Mg9r","yluBxW3VFH","14FLR9eoRc","5iGN5uZPqg","Ul4a1rKDLJ","v1HlnnFqik",
-"5drc6zz4ZU","DG4sTRmDcr","n8pJ9MaJQs","yofH3nFqik","nlaBySbRYy","tAOsrSWfou","0PktIjzUqR","QbxXc0MR5X","VBjhzWPmlx","IBe8khE1Ql",
-"MojnPFGzgp","TXQ0Z16lHc","WDVWJLDk6f","aDGtStjQxs","FnPFBEdBKc","BFkb8X6Pin","a00b57Ow5C","5Drn0pv0i7","WPmlxQssNC","FhtglU3yw5",
-"VIlwPWPmlx","5VZjStuDyS","NcICAHP433","lweGytlILt","FVMxoyEfy9","RzaZAJRJQB","YjB9tChuy3","djsrvAOgEe","WMiS3JIqXi","Nxx9VQYxC0",
-"Yh1hFUlU3M","gIYvEtaOXK","tl72W7X3uy","OUYuFY1mC0","TCgPpoVQp6","ZzJHWhi5X7","SbRYy9y4lw","3weIFDQimp","JIqXiM3zXL","n1pmOOxWIH",
-"BpYhVCxVEf","VjCZqyEfy9","WmadAFxX9q","FjHXRoVQp6","HP433fFDrJ","s4786v8yFN","Ul4a11LB1L","W7cTsJKWYR","FjHXRgjUTu","2TRI7uvf7A",
-"UlU3MKASQ8","W3VFHThjNn","VjCZqOz8yZ","zFgtB8xEKz","GrDg7ciuWz","dhSuHpFrrl","TwanoLbRTH","e6e4zlweGy","RmDcrQClRL","i7WMQJXljW",
-"uZPqgF6PT2","8FmFHMojnP","NAFuwvLsmS","ogLgc0Kyfs","Nxx9VDLhzM","y94nwQWxoT","k85Ae2TRI7","LDk6fMkgy8","BCxeCZJTXH","CxVEfCK5W7",
-"e6e4ztjQxs","Oz8yZjSjS3","FcWrWZhwG1","7Ow5CMGlTF","580YDoVQp6","HzZT8CdyBV","iB08lpAhR1","qUJMdWmadA","J2mQi6q6L9","MmsIoCxVEf",
-"aL6AJgjUTu","lViBv5drc6","cShY2v1Hln","Kr8ysguMb8","zqH0WECMvU","Q6hMChSSvQ","EdBKcs4786","dhSuHpmeCd","5ZaEzNcICA","B3qemM3zXL",
-"ulk41oQ87r","uoStwsoy9t","7fKYU1LB1L","HlUbFdpe1v","b29RJ4QMc9","DLhzMDG4sT","C2IrcSs0Zu","WaWsv7hyVv","wDajXlj07Q","M6qcGHRxd8",
-"gf8rIFFDui","uupzkxXTI4","1j5L8xciqp","qUJMdMkgy8","4QMc9HzZT8","lm0pD2hEEU","WMiS3QbxXc","VerEAMGlTF","jiVBPzFgtB","piJSkt59lR",
-"prNT6ECMvU","jeskSFwEJz","v1Hlniqv4k","Nxx9V0MR5X","l83UdtaOXK","QworuKsjRK","64s8Ns4786","FVMxo8TxD7","2Nslm618Di","yluBxlCMxy",
-"cL0aE24ARF","KsjRKDcpWB","RxrsmQYxC0","2TRI7ydG8U","oQ87rZUnqt","2Yz7E4W0Tl","Yh1hFoQ87r","SmGzvuQIcz","5ZaEzuAWyp","ZJTXHcL0aE",
-"0h1b1HlUbF","4QMc9JIqXi","D6rByyofH3","AXpwE3otm6","48cHLMm8si","5Drn0CqqaD","t59lRLDk6f","DQimpdjsrv","ThjNnDz1R3","fmIK1LbRTH",
-"faHirn1pmO","ydG8Upv0i7","CqqaDDcpWB","QChxs618Di","9eoRcLewvM","xXTI4uTacx","ZJTXHpAhR1","Zv7z0IjTwP","RpBQmyvOMI","VLTy6iB08l",
-"pT8wuEoToP","Rxrsm29QAz","aFFssUmaEv","sx5GllViBv","MGlTFhUTw7","k85Ae2Nslm","VBjhz9y4lw","SmGzvlweGy","RpBQmAIYUu","jzUqRD6rBy",
-"pvgjShe9IA","tl72WRxrsm","pWiOsYw2oU","zmLYDMGlTF","xXTI4lm0pD","0ao3lOz8yZ","EOE1oNcICA","b29RJtaOXK","16lHci3pyd","VLTy6oQ87r",
-"1j5L8Q6hMC","kB5nPlweGy","AIYUuRzaZA","D6rByazIWp","EOE1oFcWrW","uLtKsmz8gx","StlDJlweGy","JkzUnb29RJ","uPX7Gv2eC3","rhl0JNAFuw",
-"vLsmSlweGy","No0QbMmKGJ","ReKEWQ6hMC","aFFss8hJdt","cQOnvVBjhz","2TRI7ECMvU","LDk6f2Yz7E","vLsmSfFDrJ","StlDJSmGzv","yluBxU3yw5",
-"ThjNnCp3mZ","UlU3MSbRYy","HzZT8yvOMI","1LB1LGSQwj","yToGWlweGy","4W0TlQ6hMC","EOE1oEOE1o","W3VFH7fsYM","QYxC0xXTI4","RpBQmzY1GY",
-"0BmCyRzaZA","xXTI4I7p2a","IBe8kMmKGJ","EoToPv8yFN","Yf2EccL0aE","yluBxFFDui","v2eC3gIYvE","RACujNxx9V","WDVWJhUTw7","0MR5XPYBf4",
-"tlILtgtCA5","ZhwG1uJScX","QClRLiwzGk","CIShG9GXkX","580YDpT8wu","rhl0Js4786","FwEJzNo0Qb","DLhzM8FmFH","2NslmqaofN","EOE1o48cHL",
-"7X3uyCIShG","IKxdLMmsIo","fqypyO3iyQ","EoToPOz8yZ","yofH3azIWp","EoToPPOUYS","DQimpMm8si","GXdoH5iGN5","uupzkXyPZN","djsrvECMvU",
-"jzUqRpFrrl","rhl0JIBe8k","dmoS77lUXZ","0Wr5ys93Ml","DcpWBMkgy8","9iGoTAmdQd","8xEKz0PktI","djsrvhe9IA","uTacxKZamH","HRxd8uN6r3",
-"0MR5XM6qcG","gf8rIyEfy9","piJSkEdBKc","IBe8kZv7z0","BCxeCTa8f6","QYxC0iwzGk","k85AeCfgr3","blLA9WDVWJ","Uvlv4nnP8o","1j5L8Uvlv4",
-"Uvlv448cHL","JIqXidQ586","1v5hHHzZT8","X6PinIKxdL","aFFss5IhmG","UlU3MFPfSE","atef2RzaZA","Zv7z0zbIYY","jS1ajTwano","LDk6fhYBCK",
-"zQt6Q5ZaEz","o8UydzmLYD","29QAzl83Ud","BpYhVpAhR1","W3VFHHRxd8","jtn0X8cVD3","GWqqXP6bcg","48cHL3otm6","J2mQiBbwgA","L7cGcQClRL",
-"GrDg7zz4ZU","9y4lwJ2mQi","cQOnvWMiS3","tuDySdQ586","0MR5Xs4786","1j5L8a00b5","ogLgcCqqaD","lH1kt16lHc","IKxdL618Di","QYxC0s7Mxk",
-"HfyNQQnJ1S","RmDcr8RCUA","KZamHrz7Ut","tvdkDMK07Y","prNT6rhl0J","5IhmG4QMc9","O3iyQ8U2nU","yEfy9C2Irc","8RCUA9XyT9","9GXkXI7p2a",
-"wDajXAgJHQ","No0QboQ87r","sqVrfIn3NS","e6e4zqQxHP","8RCUAzQt6Q","v1HlnDLhzM","lkMUAru4UG","VIlwPYh1hF","OUYuFIKxdL","cmXIX8RCUA",
-"StlDJBFkb8","RpBQmpFrrl","mz8gxsoy9t","a00b5m4bxU","ZzJHWFhtgl","OUqFM5iGN5","FVMxoGv3Fq","o8Uydt59lR","sqVrfQworu","pFrrlUlU3M",
-"cL0aEAOgEe","pv0i7dpe1v","7X3uyBpYhV","WPmlx0ao3l","uTacxFjHXR","uN6r3KZamH","gtCA5CK5W7","HfyNQNhXdu","t98iWFGzgp","Cfgr3yluBx",
-"wiHrZuoStw","ciuWzVNCPd","ThjNnmX2GE","h1zcHhi5X7","GSQwjSbRYy","14FLRpWiOs","uvf7AjeskS","aFFssuoStw","ciuWzQChxs","BGaQYWreyP",
-"t59lR4QMc9","lweGyjzUqR","HlUbFVprf2","ulk41aDGtS","2TRI7rz7Ut","7lUXZOHaBz","8RCUAsuY4x","HfyNQDz1R3","xciqpaFFss","ZhwG145cIH",
-"2NslmZJTXH","s4786MmsIo","ZhwG1cL0aE","L7cGcpv0i7","qaofNzY1GY","7lUXZhYBCK","No0QbnnP8o","prNT6hSSvQ","FPfSErz7Ut","RBhp0wiHrZ",
-"BbwgAs7Mxk","HlUbFuupzk","1v5hHdmoS7","jtn0Xatef2","Yf2EcRzaZA","I7p2a9y4lw","sqVrfFhtgl","lCMxyYOfrY","Pb1pamz8gx","5nmWv5Drn0",
-"6q6L9xciqp","ZuDtDZv7z0","zmLYDP6bcg","lkMUA9GXkX","wiHrZyofH3","CqqaDQworu","YOfrYxciqp","7fsYMZ4I1v","pT8wu6q6L9","P6bcglH1kt",
-"KsjRKfqypy","yluBxWaim6","MGlTF2DREs","0YAGH0Kyfs","fFDrJgIYvE","gjUTuM6qcG","HzZT8hSSvQ","uTacxn1pmO","KZamHbZLvS","guMb8xXTI4",
-"WMiS3guMb8","oGu6xEdBKc","lkMUANcICA","Mkgy8bZLvS","6AFT00PktI","S2DfuKsjRK","24ARFjzUqR","FjHXRl83Ud","faHirFVMxo","KsjRKOHaBz",
-"ogLgcprNT6","XyPZN4dEz6","fqypysqVrf","0ao3logLgc","3weIFYw2oU","ydG8UW3VFH","ix74rdmoS7","8xEKzMkgy8","i3pyd7hyVv","ReKEWlViBv",
-"J2mQiYf2Ec","euZA5Y1mC0","ix74rpiJSk","2Yz7EfcwDa","No0QboVQp6","s93MlAgJHQ","ru4UG9XyT9","UlU3M7lUXZ","Rxrsm48cHL","RsQUqFwEJz",
-"VLTy66q6L9","aez9yFxX9q","55rfBuJScX","PYBf4zbIYY","fcJOyAmdQd","Waim624ARF","tuDySvOqCE","48cHLtvdkD","l83Uda00b5","W7cTsDG4sT",
-"4W0TlfFDrJ","xXTI4QnJ1S","Q6hMCTwano","LewvMkB5nP","TwanoAIYUu","vOqCEdhSuH","jiVBP8TxD7","rKDLJFhtgl","In3NStlILt","QbxXcIRh48",
-"618Di9rlg9","TXQ0ZyofH3","TXQ0Z8U2nU","RzaZAOz8yZ","No0QbuPX7G","0BmCyCp3mZ","pv0i7TXQ0Z","bZLvSMojnP","MojnPsx5Gl","Nxx9Vv8yFN",
-"1j5L8CqqaD","WMiS364s8N","VBjhzC2Irc","VerEAD6rBy","s7Mxkx3LDe","brhlQFcWrW","aez9yLbRTH","W7cTsrKDLJ","mX2GESbRYy","WDVWJVjCZq",
-"B3qemLbRTH","iKqhrru4UG","QYxC0lsQGo","8TxD7IRh48","ReKEWtuDyS","0BmCy0h1b1","tl72W48cHL","GWqqXhYBCK","MmsIo7fsYM","vkCHHFLsph",
-"64s8NtAOsr","djsrvFVMxo","y94nwK20wK","ReKEWyvOMI","FwEJzCfgr3","UmaEvsx5Gl","d7vjMzz4ZU","GSQwjL7cGc","jtn0X9rlg9","Cfgr3fcJOy",
-"x3LDeFNYIM","uoStwzFgtB","DcpWBtaOXK","suY4xYw2oU","Ta8f6d7vjM","1v5hHZJTXH","d85a9OUYuF","VjCZqMaJQs","X6PinBGaQY","UlU3MbrhlQ",
-"5IhmGEOE1o","tuDyS0ao3l","hUTw7Oz8yZ","POUYSpiJSk","ZJTXHoQ87r","vOqCEQbxXc","S77LHtjQxs","OUqFMjzUqR","fqypy2DREs","6q6L9Ul4a1",
-"sx5GlQYxC0","ydG8U5Namm","8RCUAYw2oU","8RCUAPb1pa","55rfBKr8ys","7X3uyo8Uyd","W3VFHKr8ys","Mm8sigIYvE","Cfgr3rKDLJ","y94nw5ZaEz",
-"pT8wuru4UG","TCgPpO3iyQ","0h1b1VLTy6","kZANmOz8yZ","TCgPpU3yw5","8U2nUsqVrf","SbRYy0MR5X","Rxrsm8xEKz","nFqikRpBQm","8U2nUVjCZq",
-"8FmFHQYxC0","s93MluoStw","9GXkXVLTy6","BCxeCtAOsr","jtn0XCNHmv","J2mQijfREu","4W0TlMaJQs","BCxeC8cVD3","mX2GEiqv4k","aFFssfqypy",
-"brhlQuoStw","lpF6WtAOsr","ECMvU5Drn0","tjQxsokgRi","K4GS8JRJQB","uN6r3lpF6W","fFDrJCdyBV","OHaBzzz4ZU","t98iWCfgr3","0BmCyLbRTH",
-"lH1ktzQt6Q","AgJHQFFDui","pmeCd7fsYM","4dEz6ydG8U","pAhR1atef2","TXQ0ZhUTw7","zqH0Wv8yFN","MGlTFlCMxy","VNCPdprNT6","cQOnvgdQsS",
-"m4bxU7X3uy","jS1ajqUJMd","rz7UtEdBKc","RzaZAgf8rI","BCxeCjeskS","FxX9qpT8wu","s7Mxk4QMc9","16lHchi5X7","okgRiAIYUu","o8Uydn8pJ9",
-"guMb8faHir","QClRLzz4ZU","0PktIzmLYD","JkzUnwiHrZ","AmdQdF6PT2","nlaByuJScX","uTacxiKqhr","s7MxkEdBKc","sx5GlDcpWB","WreyPCdyBV",
-"AOgEerKDLJ","ix74rlH1kt","IKxdLEOE1o","ThjNn0YAGH","tAOsrQssNC","RsQUq1LB1L","lkMUAPYBf4","YOfrYzmLYD","uLtKsQ6Lix","Chuy3lpF6W",
-"RACujh1zcH","W3VFHlj07Q","Pb1paSbRYy","oGu6xjiVBP","QssNCQWxoT","ogLgcwiHrZ","aDGtSUl4a1","AkKTkix74r","7lUXZrKDLJ","WPmlxVBjhz",
-"Y1mC06q6L9","S77LHlViBv","lCMxytvdkD","2hEEU3weIF","iKqhrNAFuw","ZUnqt5Drn0","jiVBPXflUq","ciuWzbZLvS","GrDg7hE1Ql","StlDJpiJSk",
-"4QMc9CdyBV","piJSkHP433","MaJQsFhtgl","zFgtBix74r","Ta8f60Wr5y","WmadA7fsYM","UlU3M0ao3l","GXdoHzqH0W","ZuDtDQbxXc","FVMxoWaWsv",
-"aL6AJTXQ0Z","OxWIH9iGoT","8RCUAoQ87r","tlILtnnP8o","nFqikHP433","cShY2XyPZN","J2mQiMkgy8","6AFT0soy9t","he9IAK4GS8","JIqXi24ARF",
-"VIlwPkZANm","SjskQkB5nP","NOHszMm8si","UmaEvaL6AJ","9eoRcJXljW","hSSvQ618Di","FGzgpG1RhS","d85a9soy9t","S2DfuMaJQs","okgRiZhwG1",
-"Vprf2StlDJ","ciuWzdpe1v","FPfSEtlILt","P6bcgoVQp6","fmIK1Y1mC0","lH1ktv8yFN","lkMUAhYBCK","v2eC3NhXdu","GSQwjcL0aE","OUqFMStlDJ",
-"fFDrJe6e4z","yofH3x3LDe","yToGWlH1kt","CK5W7brhlQ","2hEEUFFDui","QChxsBCxeC","Ss0Zu07n1c","uupzk7X3uy","uTacxThjNn","W3VFHMezSW",
-"hE1QloGu6x","blLA9DcpWB","hSSvQ5ZaEz","okgRiyEfy9","CxVEfQYxC0","SjskQgIYvE","pv0i7jtn0X","jiVBPF6PT2","Q6hMCK20wK","yToGWnnP8o",
-"8hJdtguMb8","zQt6Q24ARF","Yf2EcCNHmv","aDGtSMojnP","07n1cMkgy8","2ZHdkECMvU","nFqikWaim6","soy9taFFss","JKWYRi3pyd","wiHrZfcJOy",
-"kB5nPGSQwj","fcJOyxXTI4","5drc6AmdQd","ZuDtDKZamH","QbxXcAmdQd","lkMUALbRTH","Q6Lix24ARF","Chuy3uvf7A","uTacx0h1b1","Ul4a1SjskQ",
-"4QMc9FNYIM","JJs5mBbwgA","RACuj8U2nU","cQOnvyToGW","t59lRThjNn","iqv4kKsjRK","KASQ8lsQGo","CIShGDQimp","tl72WGWqqX","No0Qbo8Uyd",
-"618DijzUqR","4dEz607n1c","2hEEUDG4sT","Oz8yZguMb8","7lUXZZJTXH","BGaQYtaOXK","euZA5SjskQ","Pb1pa5nmWv","POUYSlH1kt","5nmWviwzGk",
-"HRxd8NAFuw","1LB1Lb29RJ","kZANm0PktI","NOHsztvdkD","ZJTXHyToGW","Yf2Ec8TxD7","5NammJIqXi","b29RJCp3mZ","IjTwPzz4ZU","UlU3MyToGW",
-"ReKEWzbIYY","kB5nP5VZjS","ZhwG1jS1aj","t98iWpWiOs","UlU3M8cVD3","a00b5Dz1R3","QWxoTFFDui","8U2nUHRxd8","NAFuweuZA5","Waim67X3uy",
-"6q6L9Mkgy8","JKWYRSmGzv","uvf7Ai3pyd","CIShGxXTI4","8U2nUP6bcg","5Drn0lm0pD","b29RJydG8U","ZUnqtTCgPp","Mm8sivOqCE","Yw2oUVprf2",
-"FxX9qd85a9","RzaZAydG8U","8xEKzQ6hMC","FnPFBWaim6","JRJQB0Wr5y","JKWYR2Nslm","1j5L8CNHmv","azIWpNo0Qb","Q6hMC5VZjS","IBe8kOz8yZ",
-"FPfSEn8pJ9","29QAz5Drn0","VBjhzaDGtS","4W0TliB08l","jfREuB3qem","VNCPdYh1hF","0PktIlweGy","XflUqMGlTF","kB5nPGv3Fq","l83UdoGu6x",
-"AgJHQoVQp6","rz7UtjfREu","l83UdFjHXR","5VZjS4W0Tl","XflUquvf7A","QChxs1j5L8","oGu6xjSjS3","qQxHPRzaZA","zQt6QuoStw","Oz8yZRkQke",
-"vLsmSxciqp","HRxd80Kyfs","MK07Y2ZHdk","HfyNQVprf2","Waim69y4lw","piJSkCNHmv","ECMvUaDGtS","cQOnvnnP8o","JIqXiS2Dfu","JkzUnv2eC3",
-"8TxD7StlDJ","guMb8SjskQ","dQ5861j5L8","5IhmGDz1R3","POUYSCfgr3","dmoS7ix74r","zHF1qpvgjS","9iGoTX6Pin","hSSvQbrhlQ","Yw2oUW3VFH",
-"EdBKcECMvU","lkMUAx3LDe","Fhtgll83Ud","14FLR64s8N","qQxHP9y4lw","uQIczhYBCK","fmIK1DG4sT","HRxd8MojnP","CqqaDokgRi","WPmlx5Mg9r",
-"s93MlwiHrZ","LDk6fyvOMI","QClRL8hJdt","Yf2Ec5VZjS","piJSkNo0Qb","YOfrYo8Uyd","bZLvSZuDtD","Ta8f6VLTy6","0ao3lbgJAz","45cIHVjCZq",
-"fqypyRkQke","0h1b16AFT0","soy9toGu6x","hSSvQnFqik","hE1QlQ6hMC","AOgEeuZPqg","sqVrfZUnqt","gdQsSuTacx","7ku1pAXpwE","n8pJ9y94nw",
-"5ZaEzyofH3","SjskQNo0Qb","StlDJ64s8N","0ao3lFFDui","JRJQBd85a9","HzZT8ni2v1","Ss0ZuwDajX","guMb8a00b5","GXdoHEOE1o","4dEz6tjQxs",
-"BCxeCFwEJz","Pb1pao8Uyd","e6e4zd7vjM","GSQwj2Yz7E","QbxXcPb1pa","DLhzM8TxD7","prNT6EoToP","DQimpAXpwE","VIlwPoGu6x","WaWsv9iGoT",
-"BbwgADG4sT","TCgPps93Ml","uoStwXyPZN","MGlTF0PktI","zqH0WS2Dfu","BCxeClCMxy","ni2v1qQxHP","K4GS8vkCHH","Gv3Fqhe9IA","dhSuHfmIK1",
-"pvgjSjeskS","7lUXZFVMxo","Pb1pa7fKYU","tuDySdjsrv","zbIYY64s8N","ru4UG7hyVv","OUYuF5Namm","P6bcgGWqqX","Mkgy8QChxs","wDajXtlILt",
-"uAWypQworu","mX2GEM3zXL","C2IrcogLgc","K20wKAIYUu","rz7UtKr8ys","qUJMdpvgjS","yofH3k85Ae","zmLYDn8pJ9","JXljWM3zXL","AgJHQpT8wu",
-"6AFT0D6rBy","SbRYyBGaQY","0MR5XfaHir","pFrrlIRh48","s4786StlDJ","WmadA7lUXZ","uQIczQYxC0","WreyPRsQUq","e6e4zGv3Fq","pvgjSulk41",
-"vLsmSYf2Ec","faHiruJScX","X6PingIYvE","gtCA5FPfSE","soy9tuZPqg","lCMxypAhR1","pmeCd7X3uy","5IhmGy94nw","fLNg8MaJQs","fLNg8rhl0J",
-"QssNCn1pmO","zmLYD9XyT9","ReKEWJkzUn","L7cGcThjNn","Q6LixydG8U","e6e4zhUTw7","lj07QRkQke","euZA5tlILt","2Yz7E0YAGH","9GXkXn8pJ9",
-"ix74rP6bcg","iB08lDQimp","rz7UtnlaBy","Qworut59lR","yvOMIJRJQB","jiVBPatef2","aL6AJksJby","yluBx2hEEU","Kr8ysJ2mQi","UlU3MMmKGJ",
-"KASQ8y94nw","d85a91j5L8","WDVWJpmeCd","0Wr5yF6PT2","S77LHFnPFB","BbwgA2hEEU","uoStwtuDyS","BbwgAdmoS7","Ta8f6BpYhV","ni2v1No0Qb",
-"hi5X7Yf2Ec","fmIK1FGzgp","LewvM580YD","lkMUA580YD","jS1ajZ4I1v","vkCHHuZPqg","VLTy6zY1GY","GrDg7L7cGc","yvOMIhSSvQ","FxX9qKsjRK",
-"Waim65nmWv","IKxdLdmoS7","Q6Lix14FLR","Ul4a1Twano","cL0aEFhtgl","FGzgpOHaBz","S2DfupFrrl","oQ87rFVMxo","16lHcsuY4x","mz8gxGSQwj",
-"FwEJzkB5nP","EOE1orKDLJ","jSjS3nFqik","sqVrfMojnP","0ao3lDG4sT","fcwDaW3VFH","KASQ8FjHXR","zHF1qnFqik","ciuWzGWqqX","8TxD7C2Irc",
-"i3pydfLNg8","FhtglKZamH","8cVD30Wr5y","djsrviqv4k","vLsmS8hJdt","8cVD3tjQxs","GSQwjjiVBP","B3qemZuDtD","soy9tJXljW","pT8wuCIShG",
-"hE1QlU3yw5","pvgjSI7p2a","AmdQdZUnqt","jSjS3nnP8o","9eoRcprNT6","m4bxU5IhmG","ZhwG1S77LH","EoToPFGzgp","FPfSEOxWIH","zY1GYvLsmS",
-"x3LDeNhXdu","xReecMm8si","qQxHPuPX7G","GrDg7ZuDtD","AOgEeBbwgA","Rxrsm16lHc","y94nwGSQwj","LDk6frz7Ut","brhlQKASQ8","gf8rIAOgEe",
-"lkMUAsx5Gl","F6PT2TXQ0Z","iwzGk0PktI","8RCUAFVMxo","MaJQsMkgy8","2DREsuTacx","JJs5mjzUqR","9XyT9KsjRK","QworuqaofN","vOqCES77LH",
-"KsjRK9GXkX","AkKTkMmsIo","4W0TlQWxoT","48cHLtAOsr","1j5L8Kr8ys","prNT6IjTwP","TCgPplsQGo","7X3uyEOE1o","ECMvUSmGzv","07n1c1j5L8",
-"4dEz6TCgPp","Yw2oU8hJdt","TCgPplm0pD","kZANmsqVrf","lj07Q9GXkX","NOHszh1zcH","F6PT2BbwgA","Cp3mZ14FLR","1v5hHM3zXL","v2eC3nlaBy",
-"4QMc9AIYUu","dmoS7gf8rI","Pb1pa2Yz7E","8U2nUqQxHP","uupzktjQxs","HlUbF0YAGH","Q6Lix2Nslm","C2IrcEoToP","CIShG24ARF","oGu6xRACuj",
-"nlaByfaHir","aL6AJPOUYS","jS1ajtaOXK","oGu6xyvOMI","FxX9qCIShG","tlILt618Di","5nmWvpT8wu","dQ586M3zXL","IjTwP4QMc9","zbIYYuoStw",
-"Cfgr3UmaEv","HlUbF2Nslm","Q6Lixhe9IA","bZLvSoGu6x","SbRYydpe1v","StlDJMojnP","OUYuFuAWyp","QnJ1S16lHc","Dz1R3MmKGJ","8xEKzZhwG1",
-"VerEAo8Uyd","9GXkXBbwgA","QssNCLDk6f","FGzgphUTw7","fcJOy64s8N","Oz8yZWaWsv","pT8wuRxrsm","lsQGozmLYD","mz8gxKASQ8","fqypy580YD",
-"8FmFHJRJQB","AXpwEEoToP","dQ586FLsph","8U2nUAXpwE","MGlTFFhtgl","iB08lprNT6","YOfrYI7p2a","MK07YwDajX","dpe1vAmdQd","sqVrf7ku1p",
-"a00b55nmWv","Chuy3JRJQB","lkMUAIKxdL","Kr8ysSmGzv","pv0i7lj07Q","zY1GYnnP8o","3weIFDG4sT","vLsmSk85Ae","uoStwFjHXR","24ARFgf8rI",
-"3otm6Yw2oU","prNT6WPmlx","aFFssPYBf4","jtn0XMmsIo","ECMvUtuDyS","Chuy3VLTy6","G1RhS0PktI","ru4UGzbIYY","oVQp6CdyBV","JIqXipFrrl",
-"uAWypRzaZA","ru4UGQWxoT","s7MxkYf2Ec","Oz8yZQssNC","faHirIBe8k","DLhzM0PktI","hE1Ql4dEz6","TwanoPOUYS","9rlg9DG4sT","uvf7AuJScX",
-"FcWrWhYBCK","MaJQsbgJAz","8FmFHJkzUn","tvdkDiwzGk","0BmCyh1zcH","iqv4kNhXdu","lXFOBWaWsv","zFgtBzFgtB","Q6LixgtCA5","Nxx9VjSjS3",
-"ZuDtD14FLR","ZUnqtjS1aj","KZamH5Mg9r","djsrv0YAGH","0PktIpmeCd","0Wr5yuupzk","lkMUATXQ0Z","tl72Wru4UG","piJSkqUJMd","lj07Qzz4ZU",
-"Cp3mZhi5X7","3weIFRkQke","RsQUq5Namm","brhlQMezSW","uupzkd85a9","AOgEe5ZaEz","VjCZqCIShG","tuDySNOHsz","uQIczZuDtD","n1pmOS77LH",
-"uvf7A0Wr5y","6AFT07hyVv","Zv7z0o8Uyd","2DREsoVQp6","uQIczMK07Y","NcICAn1pmO","GrDg7i3pyd","ni2v1jS1aj","8U2nUZzJHW","Chuy30BmCy",
-"cL0aEuAWyp","5Drn0TCgPp","ydG8U8hJdt","WreyPTwano","he9IADQimp","gjUTuMezSW","LewvM0MR5X","7hyVvydG8U","t59lRulk41","No0QbQbxXc",
-"CK5W7l83Ud","QChxs7X3uy","gf8rIUvlv4","QnJ1SWreyP","SjskQyToGW","pmeCdn8pJ9","ZzJHWFPfSE","14FLRsqVrf","0PktI64s8N","HP433BFkb8",
-"RBhp0aL6AJ","AmdQdv1Hln","55rfBxReec","gtCA5v1Hln","0ao3lI7p2a","pAhR1x3LDe","6AFT0lCMxy","RzaZASjskQ","oGu6xprNT6","WDVWJAIYUu",
-"OUqFMS2Dfu","gIYvEzz4ZU","a00b5EoToP","uLtKsmX2GE","gf8rI9GXkX","BCxeC2hEEU","ZUnqt0ao3l","yluBxs93Ml","KsjRK7fsYM","MK07Y7X3uy",
-"RBhp007n1c","JXljWWmadA","oVQp6D6rBy","LDk6fP6bcg","kB5nPGXdoH","O3iyQsoy9t","FjHXRksJby","s93MlVjCZq","L7cGcprNT6","4QMc9zHF1q",
-"hYBCKaL6AJ","faHirIRh48","U3yw5jfREu","UlU3MK4GS8","LewvMt98iW","W7cTsYh1hF","4QMc95VZjS","RpBQmm4bxU","hSSvQpT8wu","n8pJ9wiHrZ",
-"nFqikiKqhr","Cfgr3v8yFN","FxX9ql83Ud","W7cTsCfgr3","MGlTFcShY2","55rfBfcJOy","QChxsblLA9","MezSWcQOnv","GrDg7FwEJz","mz8gxZuDtD",
-"5drc6xReec","kZANmtuDyS","MojnPAkKTk","kB5nPv8yFN","HzZT848cHL","fqypyFPfSE","ZhwG1tlILt","Pb1paZv7z0","ZJTXHtuDyS","gtCA5Ta8f6",
-"In3NSfmIK1","h1zcHVIlwP","JRJQBm4bxU","h1zcH8RCUA","GSQwjUvlv4","uPX7GCNHmv","45cIHulk41","bgJAzv2eC3","zHF1qS2Dfu","QworuMaJQs",
-"S77LH07n1c","dQ586uLtKs","NhXduWDVWJ","9iGoTo8Uyd","Oz8yZWaim6","uAWypaL6AJ","Vprf2piJSk","pWiOs5VZjS","dQ586JRJQB","FFDuiaez9y",
-"AIYUu580YD","Vprf2fqypy","ru4UGVIlwP","BCxeCn1pmO","b29RJ0ao3l","hE1Ql29QAz","S2DfuNo0Qb","uZPqgru4UG","StlDJzbIYY","P6bcgJIqXi",
-"rhl0J618Di","WPmlxe6e4z","lm0pDjS1aj","hUTw7hSSvQ","QworugIYvE","v2eC3tuDyS","8hJdtQworu","EoToPFxX9q","7X3uyCxVEf","n8pJ9Y1mC0",
-"NhXdudpe1v","zbIYYZv7z0","uvf7A5IhmG","8hJdtaL6AJ","n8pJ9prNT6","K4GS8ix74r","hSSvQ55rfB","OUqFMRACuj","TXQ0ZfmIK1","YOfrYYh1hF",
-"hE1QluPX7G","CdyBVuAWyp","pv0i7pv0i7","29QAzd85a9","VNCPdDQimp","l83Ud0MR5X","9GXkXKr8ys","o8UydzQt6Q","MmKGJHfyNQ","oQ87rAXpwE",
-"0PktIzz4ZU","AkKTkgf8rI","5iGN5vkCHH","0Wr5yWreyP","nFqikUvlv4","ulk41lweGy","In3NSBCxeC","YjB9tOHaBz","pT8wupAhR1","fcwDajzUqR",
-"FhtglMGlTF","B3qemjS1aj","zmLYD5iGN5","GXdoHpvgjS","LewvM5Namm","iwzGkQWxoT","VerEAs93Ml","hSSvQaL6AJ","vOqCEpvgjS","7X3uyYOfrY",
-"nnP8ofaHir","Yh1hFhe9IA","fcJOyjtn0X","iB08l2Yz7E","cShY2Chuy3","5VZjStAOsr","lViBvulk41","xReecRBhp0","wDajXJ2mQi","sx5Glix74r",
-"OHaBz8xEKz","IRh48Twano","nnP8o8xEKz","OUYuFoVQp6","4QMc9fcwDa","i7WMQZhwG1","Y1mC0NAFuw","SWfouFFDui","pv0i7uN6r3","b29RJBFkb8",
-"lsQGobgJAz","5drc6ZUnqt","KASQ8FGzgp","FjHXRlH1kt","hSSvQQbxXc","uQIczlXFOB","MmsIoOUqFM","tlILtgIYvE","b29RJpv0i7","dQ5863weIF",
-"5iGN53otm6","EdBKcNcICA","iB08luJScX","9GXkX1LB1L","7fsYMrz7Ut","pvgjSrz7Ut","0h1b1RmDcr","Ss0ZufLNg8","W7cTslj07Q","sx5GlM6qcG",
-"CxVEfTwano","Q6LixvkCHH","BCxeCs7Mxk","WDVWJiwzGk","h1zcHNhXdu","nFqikblLA9","s93MlhYBCK","n8pJ9dQ586","XyPZNJIqXi","07n1c0Kyfs",
-"aez9yJRJQB","v8yFN48cHL","i3pydyofH3","TXQ0ZyToGW","vOqCEVLTy6","FVMxopFrrl","guMb8lm0pD","MojnP8cVD3","WDVWJaFFss","ksJbyuTacx",
-"aez9yaez9y","VLTy6C2Irc","FnPFBMkgy8","9rlg9SbRYy","5Mg9rnnP8o","U3yw5VjCZq","euZA5yofH3","pvgjSs4786","7fKYUxReec","618DiQClRL",
-"9eoRc64s8N","qUJMdpWiOs","Dz1R3cmXIX","StlDJWMiS3","JIqXi5Drn0","0MR5XogLgc","lCMxyAXpwE","zmLYDuZPqg","uZPqgCdyBV","okgRiGrDg7",
-"iB08lZv7z0","cShY2i7WMQ","29QAz1v5hH","ogLgcuLtKs","M3zXLlkMUA","AgJHQqUJMd","SbRYy8cVD3","FLsphAmdQd","lsQGoxXTI4","VNCPdVerEA",
-"zQt6Qdpe1v","4W0TljzUqR","DQimpzqH0W","HP433qUJMd","lweGyQWxoT","LDk6f0Kyfs","07n1cTCgPp","5NammpWiOs","9GXkXCxVEf","s7MxklkMUA",
-"9iGoT5drc6","atef2guMb8","faHir4W0Tl","Cfgr3i3pyd","xciqpiqv4k","e6e4zI7p2a","ECMvUDQimp","580YDWmadA","jS1aj2TRI7","J2mQiatef2",
-"he9IAMmKGJ","CxVEfVprf2","POUYSokgRi","d7vjMlj07Q","xciqpgdQsS","s4786cQOnv","U3yw5bgJAz","pv0i7vOqCE","B3qembrhlQ","JXljWix74r",
-"ni2v1zmLYD","ZhwG1ZzJHW","MGlTFxciqp","8U2nUZUnqt","QWxoTzz4ZU","dQ586nlaBy","B3qemEOE1o","LewvMAkKTk","Uvlv4SjskQ","WaWsvx3LDe",
-"9GXkXZuDtD","6AFT00MR5X","jS1ajK20wK","7fKYUcmXIX","lj07QWreyP","PYBf4yEfy9","SmGzvFPfSE","oVQp6PYBf4","ReKEWK4GS8","8xEKzyvOMI",
-"ZzJHWDQimp","OHaBz2ZHdk","C2IrcNhXdu","YOfrYt59lR","MaJQsrKDLJ","QnJ1SWDVWJ","KASQ8ECMvU","6q6L9lXFOB","jiVBPyofH3","B3qemC2Irc",
-"StlDJIBe8k","qaofNNo0Qb","h1zcHQChxs","gdQsSKASQ8","QworuZhwG1","FjHXRB3qem","AgJHQhSSvQ","QChxspmeCd","M6qcGAkKTk","fLNg8AkKTk",
-"okgRiMaJQs","ZJTXHuQIcz","DQimpUmaEv","8FmFHaDGtS","QnJ1SRsQUq","1j5L8zbIYY","QChxsSjskQ","QClRL0MR5X","Mkgy8tuDyS","UmaEvgf8rI",
-"ogLgcv2eC3","0ao3li7WMQ","0BmCyfcwDa","hYBCKt98iW","rz7UtJXljW","O3iyQIBe8k","1v5hHlweGy","XyPZNaez9y","ReKEWm4bxU","Fhtgls7Mxk",
-"6AFT0nnP8o","In3NSatef2","v8yFNWmadA","DLhzMZv7z0","RACujRmDcr","faHirfqypy","k85AejSjS3","Mm8si2Nslm","7hyVvZ4I1v","gtCA5ksJby",
-"P6bcgnnP8o","8U2nU8xEKz","2TRI7UlU3M","F6PT29y4lw","mX2GEv8yFN","ulk41pT8wu","bZLvSsoy9t","ZUnqtYf2Ec","zbIYY8xEKz","tAOsrZhwG1",
-"gtCA5taOXK","piJSkulk41","Waim6zz4ZU","OUYuF8hJdt","dhSuHXflUq","lCMxyfaHir","WreyPd7vjM","6AFT0GSQwj","3weIFulk41","fcwDaJ2mQi",
-"2ZHdkt98iW","1LB1L7hyVv","3weIFt98iW","brhlQdjsrv","MezSWGXdoH","lpF6WuQIcz","pvgjS5nmWv","DG4sTZUnqt","ksJbyIRh48","UmaEvjSjS3",
-"BCxeCrz7Ut","GWqqX55rfB","HP433W7cTs","MaJQsxXTI4","Cp3mZ9iGoT","CIShG64s8N","d7vjMRxrsm","KsjRKWPmlx","W7cTsYw2oU","ydG8UdmoS7",
-"L7cGcDLhzM","8U2nUThjNn","wDajXzz4ZU","ulk415iGN5","5iGN5UmaEv","8TxD7JkzUn","7X3uybZLvS","Mm8sit59lR","FcWrWOHaBz","ZUnqth1zcH",
-"WMiS3GWqqX","jSjS3hi5X7","MojnPjiVBP","8xEKzuN6r3","K4GS8tlILt","pAhR1uN6r3","RxrsmGrDg7","WmadAyofH3","ZzJHW5iGN5","v1HlnzQt6Q",
-"9XyT9dQ586","k85Ae07n1c","RkQkezFgtB","jfREu0BmCy","v1HlntlILt","7X3uyMaJQs","QworuRzaZA","MK07YaDGtS","9eoRcWDVWJ","gIYvEMK07Y",
-"5IhmGNhXdu","ZzJHWBGaQY","ReKEWAOgEe","55rfBQ6Lix","M6qcGix74r","aez9y5ZaEz","07n1csuY4x","5ZaEzaDGtS","2ZHdkjzUqR","0PktIIKxdL",
-"d7vjMWmadA","fcwDa5Drn0","k85AeXflUq","GSQwjFVMxo","Yw2oUNOHsz","IjTwPRxrsm","tjQxs7hyVv","GrDg7lkMUA","FPfSE2Nslm","uQIczGSQwj",
-"x3LDerhl0J","O3iyQ0Wr5y","QssNCyluBx","rhl0JyToGW","7fsYMW7cTs","CK5W7blLA9","StlDJiB08l","azIWp14FLR","jSjS35ZaEz","brhlQt59lR",
-"RmDcrMaJQs","QYxC0oVQp6","6q6L9StlDJ","2hEEUXyPZN","HfyNQlpF6W","WmadAfqypy","5nmWv8U2nU","OHaBzksJby","VIlwPK20wK","uLtKsaDGtS",
-"blLA9b29RJ","Cfgr3Yh1hF","FLsph2TRI7","tl72Wsx5Gl","jS1ajbZLvS","RpBQmzbIYY","oVQp6cQOnv","G1RhSfcJOy","P6bcgWaWsv","DLhzMZzJHW",
-"zFgtBlpF6W","xReecazIWp","1v5hHCK5W7","mz8gxFnPFB","Oz8yZfFDrJ","9XyT9Cfgr3","FxX9qUmaEv","IjTwPL7cGc","Zv7z00MR5X","JJs5mzFgtB",
-"580YDFxX9q","azIWpaFFss","Nxx9VQ6hMC","FcWrWo8Uyd","FwEJzuTacx","v2eC3d7vjM","PYBf4WmadA","k85AetlILt","RsQUq2DREs","aDGtSTCgPp",
-"jiVBPpv0i7","8U2nUwiHrZ","qaofNDLhzM","mz8gxtlILt","he9IAcShY2","MmsIoEdBKc","gdQsSRmDcr","mX2GE9y4lw","MK07YFVMxo","zqH0WRzaZA",
-"lj07QP6bcg","uZPqgQ6hMC","WreyPokgRi","S2DfutAOsr","7X3uyNhXdu","GrDg7KZamH","W3VFHcmXIX","QClRLnlaBy","HlUbFS77LH","lViBvIBe8k",
-"S77LHBCxeC","RmDcrChuy3","hi5X7XyPZN","RpBQm0PktI","Yh1hFRkQke","D6rBygf8rI","lCMxy7fKYU","uJScXi7WMQ","k85AebgJAz","sqVrfuLtKs",
-"qQxHPHP433","KASQ8pvgjS","ni2v1pmeCd","Q6hMCEOE1o","gjUTuP6bcg","Yw2oUS77LH","ZzJHWhUTw7","O3iyQOHaBz","AgJHQKASQ8","lViBvWaWsv",
-"StlDJlj07Q","8TxD70Kyfs","DG4sTuLtKs","L7cGcAkKTk","C2Irce6e4z","BGaQYM3zXL","MmKGJtAOsr","lj07QBGaQY","hYBCKuAWyp","GXdoHK20wK",
-"QssNClViBv","YOfrY0BmCy","qaofNECMvU","5IhmGdpe1v","LewvMQbxXc","Ss0ZuXyPZN","HzZT8BbwgA","Mkgy8StlDJ","jzUqRHlUbF","ReKEWCdyBV",
-"9iGoTlViBv","2hEEUCK5W7","Mm8siCNHmv","JkzUntuDyS","fcJOyRBhp0","Vprf2kB5nP","euZA5QWxoT","ydG8UYf2Ec","0h1b1RACuj","uZPqgjiVBP",
-"uTacxlkMUA","KZamHPYBf4","FLsphVBjhz","Mkgy8azIWp","LewvM6AFT0","SmGzvcShY2","5Drn0suY4x","JRJQBpiJSk","oQ87r2hEEU","QbxXcL7cGc",
-"CNHmvTa8f6","OHaBzuJScX","SjskQpAhR1","IKxdLS2Dfu","M6qcGGrDg7","14FLR7lUXZ","d85a9yToGW","CK5W7Kr8ys","i3pydtvdkD","iKqhrQClRL",
-"8RCUAF6PT2","tjQxsS2Dfu","cmXIXZJTXH","No0QbGrDg7","mz8gxJ2mQi","Ss0Zudjsrv","zFgtBSmGzv","JIqXiOxWIH","TCgPpCxVEf","Mkgy8JIqXi",
-"aFFss6q6L9","cShY2zqH0W","jzUqRB3qem","qUJMdiwzGk","sx5GlgIYvE","Cfgr3pT8wu","7ku1pfmIK1","pAhR1ZUnqt","lkMUAogLgc","HP433RzaZA",
-"kB5nPTCgPp","djsrvNxx9V","8hJdtBFkb8","pT8wuRsQUq","QworuHzZT8","MK07Yt59lR","x3LDeUl4a1","1LB1L2TRI7","CdyBVt59lR","CNHmv4W0Tl",
-"G1RhShYBCK","5ZaEzWreyP","Gv3Fqt98iW","WreyPjiVBP","prNT6Zv7z0","euZA5CxVEf","Kr8ysQ6hMC","LewvMzz4ZU","W3VFHzz4ZU","Vprf2uupzk",
-"RACuj5Mg9r","okgRi0ao3l","rhl0Jmz8gx","prNT6HP433","FcWrWuvf7A","CqqaDlXFOB","v1HlnbrhlQ","NOHszfqypy","oVQp6SjskQ","W7cTskB5nP",
-"lweGys93Ml","Ta8f6IBe8k","bgJAzaez9y","OUqFMK20wK","FNYIMChuy3","MmsIoMezSW","atef2P6bcg","yToGWECMvU","0Wr5y0MR5X","Z4I1vzqH0W",
-"JKWYRF6PT2","cQOnvfmIK1","LDk6fzY1GY","FcWrWDG4sT","h1zcHfaHir","yluBxfcwDa","EoToPMmsIo","9iGoTUlU3M","kB5nPgjUTu","48cHLiwzGk",
-"UlU3MBpYhV","CK5W7JKWYR","4dEz60YAGH","9eoRc0PktI","KASQ8qaofN","faHirFcWrW","618DihYBCK","7fsYMQ6hMC","ZuDtDY1mC0","sqVrfpiJSk",
-"MojnPFnPFB","S2DfuvOqCE","ru4UGt98iW","guMb8fFDrJ","AkKTkUlU3M","P6bcgChuy3","0BmCyFPfSE","lweGyMGlTF","618DiYh1hF","VLTy6gIYvE",
-"Yh1hFZ4I1v","NhXdulweGy","rz7UtCdyBV","lm0pDqaofN","pT8wuhi5X7","RACujUmaEv","dhSuHB3qem","TwanoUmaEv","zz4ZUM3zXL","WmadAHfyNQ",
-"Cp3mZbrhlQ","Chuy3RBhp0","tjQxs29QAz","No0QbNOHsz","7fKYUqaofN","RpBQmBbwgA","sqVrfaFFss","LDk6fWaim6","Pb1pa7fsYM","lsQGooQ87r",
-"nFqikZ4I1v","B3qemEdBKc","NOHsz3otm6","a00b58FmFH","rhl0JlCMxy","GrDg7P6bcg","29QAzzQt6Q","QssNCwDajX","jS1ajlH1kt","v8yFNvkCHH",
-"v2eC3W7cTs","D6rByO3iyQ","G1RhSCqqaD","euZA59eoRc","pFrrlPYBf4","IRh48jfREu","uQIczVjCZq","aDGtSnFqik","JXljWeuZA5","nlaBycL0aE",
-"xXTI4GWqqX","Q6LixWreyP","2Yz7El83Ud","okgRizbIYY","sqVrfvLsmS","MmsIolpF6W","QworueuZA5","3weIFcQOnv","d7vjMs93Ml","Twanol83Ud",
-"14FLRKASQ8","DQimpuoStw","0YAGHO3iyQ","QClRLO3iyQ","s7MxkoQ87r","HzZT8WPmlx","9eoRcCp3mZ","ciuWzKZamH","OxWIHGrDg7","Oz8yZ618Di",
-"IKxdLY1mC0","K4GS8MGlTF","fFDrJZ4I1v","l83UdOUqFM","HP433yEfy9","Qworu5iGN5","cQOnvnlaBy","Waim6uQIcz","29QAzDLhzM","FwEJzi7WMQ",
-"Nxx9VyofH3","cShY29iGoT","2NslmFNYIM","TCgPpnFqik","soy9t24ARF","07n1cG1RhS","U3yw5xciqp","yluBxlpF6W","Oz8yZJ2mQi","GrDg7W7cTs",
-"iqv4kVjCZq","7ku1pfLNg8","o8UydBpYhV","1j5L8atef2","TXQ0ZRzaZA","M6qcGdmoS7","8TxD7yofH3","pFrrlwiHrZ","CNHmvqUJMd","1LB1L2ZHdk",
-"RBhp0lsQGo","Mkgy8lj07Q","1v5hHoVQp6","FhtglUvlv4","SWfouqUJMd","07n1clsQGo","ogLgcuupzk","6q6L98FmFH","U3yw5RkQke","v8yFNFPfSE",
-"0h1b164s8N","6AFT0S2Dfu","UmaEv7lUXZ","x3LDeZzJHW","9XyT9QYxC0","VjCZqlsQGo","JIqXiOUqFM","lj07QHzZT8","AmdQdsx5Gl","J2mQilkMUA",
-"XflUqFPfSE","jtn0XxXTI4","VjCZqciuWz","dQ5865Mg9r","l83Udi7WMQ","wiHrZdmoS7","W3VFHb29RJ","tuDySFGzgp","07n1cyEfy9","D6rBy0h1b1",
-"prNT6bZLvS","9GXkXjSjS3","atef2Twano","7hyVvThjNn","JRJQBMaJQs","ru4UG8U2nU","vLsmSuQIcz","gdQsSAmdQd","MmKGJQbxXc","uoStwxReec",
-"MGlTFdmoS7","v8yFNuupzk","Vprf2Kr8ys","8TxD7jS1aj","gdQsSQworu","2TRI7Qworu","Mkgy8OxWIH","XyPZNHlUbF","0BmCyGv3Fq","QssNCBFkb8",
-"J2mQiNAFuw","AOgEeRkQke","JXljWsx5Gl","m4bxUIRh48","MmKGJdhSuH","x3LDeMmsIo","C2IrcFPfSE","NcICA2TRI7","lsQGo5nmWv","WPmlxzQt6Q",
-"jSjS3BFkb8","zqH0W2DREs","RkQkeYjB9t","M6qcG2Nslm","8RCUAaL6AJ","s4786K20wK","FjHXRdhSuH","24ARFgjUTu","Nxx9VNcICA","M6qcG07n1c",
-"MaJQsPYBf4","ZzJHWdhSuH","W3VFHDcpWB","taOXKtlILt","GWqqXF6PT2","TXQ0Zzz4ZU","Ta8f6LewvM","s7MxkLewvM","SWfous93Ml","dhSuHDcpWB",
-"rz7UtM6qcG","I7p2aqQxHP","uJScXoQ87r","e6e4zB3qem","taOXKuZPqg","ogLgcMaJQs","djsrvIRh48","Yw2oUn8pJ9","48cHL8RCUA","Vprf2tjQxs",
-"No0QbYjB9t","taOXKx3LDe","dpe1vsuY4x","soy9td85a9","ZuDtDMezSW","LbRTH2Nslm","IKxdLRsQUq","kB5nPOz8yZ","jeskSFPfSE","pAhR1vkCHH",
-"48cHL5nmWv","v1HlnxXTI4","RsQUqcmXIX","5ZaEzJJs5m","14FLRDQimp","0BmCyQnJ1S","ksJbyaez9y","RsQUqv2eC3","M3zXLpiJSk","16lHc0ao3l",
-"JIqXi5IhmG","Nxx9V0BmCy","CdyBVUl4a1","jS1ajJIqXi","LDk6fBFkb8","5IhmGnFqik","HfyNQlweGy","JJs5mt59lR","sqVrf5VZjS","XflUqM6qcG",
-"lH1ktt59lR","45cIHblLA9","jS1ajpWiOs","1j5L8ECMvU","uoStwiwzGk","GSQwjmz8gx","Uvlv4gtCA5","rKDLJCp3mZ","gtCA5jzUqR","G1RhSD6rBy",
-"fcJOySWfou","9eoRcMaJQs","Gv3FqxReec","7lUXZ4dEz6","iB08latef2","uTacxs93Ml","JRJQBpv0i7","rhl0JZ4I1v","2DREs5IhmG","07n1coGu6x",
-"Ss0ZuEdBKc","OxWIHpFrrl","MaJQspWiOs","RkQkeTXQ0Z","pvgjSFjHXR","hYBCKThjNn","uJScXPb1pa","ZJTXHSs0Zu","v2eC3DG4sT","FGzgpjtn0X",
-"MaJQsi7WMQ","0KyfsAmdQd","JkzUn9rlg9","dmoS7FwEJz","jfREucmXIX","h1zcHpFrrl","3otm6NcICA","ZuDtD5drc6","jzUqRatef2","QssNCtl72W",
-"RmDcrbZLvS","QYxC0XyPZN","tl72WHRxd8","AgJHQfaHir","zbIYYMaJQs","ZUnqtVprf2","RmDcrCp3mZ","SjskQv2eC3","RzaZACqqaD","jeskSQWxoT",
-"QworuJXljW","qQxHPSWfou","lm0pDJXljW","tl72W2hEEU","jzUqRhe9IA","taOXKuQIcz","sx5GlNcICA","FjHXRuN6r3","yToGW0MR5X","HzZT8Qworu",
-"uN6r3M6qcG","618DiLbRTH","CNHmvAmdQd","6q6L9VjCZq","7hyVvTwano","iB08llsQGo","8RCUABFkb8","DG4sTRACuj","gf8rIGWqqX","Zv7z06q6L9",
-"U3yw54dEz6","jeskSyofH3","IKxdLBCxeC","xXTI4CNHmv","CdyBVpAhR1","ReKEWOz8yZ","e6e4zuoStw","azIWpgtCA5","dmoS7aDGtS","GSQwjkB5nP",
-"EdBKcCNHmv","24ARFblLA9","45cIHciuWz","lj07Q0ao3l","pv0i7VjCZq","6AFT0cmXIX","oQ87r1LB1L","FwEJzZzJHW","55rfBa00b5","IjTwPP6bcg",
-"CK5W7CK5W7","ZhwG1dQ586","i3pyd16lHc","zY1GYMK07Y","QbxXcOHaBz","WDVWJZv7z0","uN6r3ZzJHW","m4bxUcQOnv","fcJOy9GXkX","VNCPdQ6hMC",
-"PYBf4zFgtB","i3pydb29RJ","FnPFBBCxeC","5IhmGdjsrv","GXdoHsx5Gl","blLA9IKxdL","mz8gxbZLvS","0KyfsQClRL","jS1aj7Ow5C","a00b5MGlTF",
-"Zv7z0lsQGo","9y4lwl83Ud","MezSWMezSW","ReKEWn1pmO","uTacx8U2nU","2Nslm1LB1L","uPX7GC2Irc","OxWIH8U2nU","VBjhztAOsr","fqypyMm8si",
-"aDGtSJKWYR","QworuNhXdu","k85AesuY4x","uQIczyluBx","MezSWgtCA5","bZLvSQworu","CxVEfO3iyQ","GSQwjzz4ZU","aFFssWaWsv","FPfSEF6PT2",
-"JkzUnjiVBP","WDVWJzmLYD","FhtglLbRTH","RmDcrjtn0X","1j5L8No0Qb","8xEKzGv3Fq","IBe8kFhtgl","6AFT0CK5W7","5nmWv0PktI","bZLvStjQxs",
-"48cHLMaJQs","VNCPdSjskQ","M6qcGa00b5","VLTy6OxWIH","guMb8ix74r","KsjRKX6Pin","4dEz6VIlwP","sqVrfxXTI4","S2DfuKZamH","jtn0X5Drn0",
-"48cHLhe9IA","wDajX8FmFH","RzaZAbZLvS","qUJMdh1zcH","QChxsY1mC0","yToGWgjUTu","LbRTHBbwgA","b29RJLewvM","dpe1vhUTw7","RBhp0FwEJz",
-"WPmlxdhSuH","ulk41KASQ8","UmaEvEOE1o","v1HlnqaofN","iKqhr9eoRc","2NslmzY1GY","QworuGv3Fq","Ul4a1v1Hln","EOE1oOxWIH","RmDcrIn3NS",
-"i7WMQ8cVD3","0Wr5yjSjS3","0Wr5y9rlg9","a00b5M3zXL","ru4UGM3zXL","POUYSCdyBV","5Drn0lj07Q","i3pydyvOMI","JKWYR16lHc","9XyT99y4lw",
-"VIlwPMm8si","lm0pDo8Uyd","Q6LixQ6Lix","a00b5iwzGk","Vprf2jzUqR","pWiOsfcwDa","t59lRMK07Y","tl72WuLtKs","9rlg9iB08l","HfyNQciuWz",
-"9XyT9qaofN","gtCA5JXljW","48cHLpWiOs","Q6LixqaofN","RxrsmnnP8o","yofH3Ta8f6","uPX7GSjskQ","ydG8Ui7WMQ","lViBvK4GS8","Waim6tl72W",
-"Twano8U2nU","zmLYDiB08l","0KyfsRzaZA","UlU3MU3yw5","3otm69rlg9","VjCZqzqH0W","IBe8kcmXIX","brhlQoQ87r","Mm8siAXpwE","MmsIo3weIF",
-"kZANmFwEJz","8TxD7QYxC0","PYBf4VerEA","zQt6QOUYuF","ulk41fmIK1","0Wr5yQnJ1S","jeskS580YD","lH1ktQWxoT","0ao3lyEfy9","14FLREoToP",
-"yofH3RACuj","fFDrJxReec","8U2nUZJTXH","i3pydoQ87r","RkQkegIYvE","LewvM7fKYU","IKxdL3otm6","s4786RmDcr","uN6r3Dz1R3","VBjhzdpe1v",
-"gjUTuS77LH","MK07Y48cHL","Waim6tjQxs","aez9yNxx9V","suY4xK20wK","FGzgpUl4a1","2DREss7Mxk","lXFOBKr8ys","0PktIAOgEe","NOHszRzaZA",
-"3weIFWaim6","pv0i7lkMUA","tuDySMm8si","M6qcGwDajX","Cp3mZzqH0W","45cIHQ6Lix","aez9yTa8f6","FFDuizmLYD","piJSkOz8yZ","AgJHQlViBv",
-"ogLgcU3yw5","RmDcrJkzUn","EdBKcQWxoT","oGu6xfcJOy","Z4I1vjiVBP","KZamHhUTw7","8TxD7HRxd8","4QMc9CxVEf","tlILt8hJdt","gf8rIC2Irc",
-"tjQxs6q6L9","gdQsSjS1aj","RBhp0Y1mC0","1LB1LnnP8o","ReKEWn8pJ9","xReecMojnP","MmsIoEoToP","bgJAz2Yz7E","POUYSCK5W7","EdBKcwDajX",
-"yluBxxciqp","HzZT88cVD3","lH1ktlj07Q","ZJTXHd85a9","RBhp00ao3l","d85a93otm6","prNT6zbIYY","6q6L9ni2v1","pFrrlDLhzM","3otm6soy9t",
-"tAOsrzFgtB","5VZjS5ZaEz","jSjS3MK07Y","14FLRTCgPp","1v5hHK20wK","0KyfsAgJHQ","9y4lwpFrrl","Ta8f645cIH","mz8gxhSSvQ","rz7UtSs0Zu",
-"FwEJzLbRTH","HfyNQU3yw5","prNT645cIH","fmIK164s8N","lj07Q3otm6","xciqpDG4sT","AmdQdK4GS8","ogLgcVerEA","ZJTXH2ZHdk","9iGoTHfyNQ",
-"QClRLcShY2","MK07Yzz4ZU","m4bxUC2Irc","CqqaDAXpwE","lm0pD8cVD3","wDajXoQ87r","BGaQYThjNn","JIqXiW7cTs","WMiS31LB1L","n1pmO5VZjS",
-"1LB1LL7cGc","okgRixciqp","FPfSE6AFT0","CK5W7EoToP","pmeCdpvgjS","ciuWzHfyNQ","PYBf4xXTI4","9iGoT7lUXZ","n1pmO8cVD3","2DREsThjNn",
-"RBhp0Uvlv4","MmsIoL7cGc","zFgtBkZANm","FnPFBCp3mZ","2TRI75ZaEz","xciqpgf8rI","HfyNQO3iyQ","xXTI4zmLYD","ZzJHWuPX7G","mz8gxYh1hF",
-"cL0aEjSjS3","QbxXc2TRI7","hi5X7ydG8U","gtCA5yofH3","WaWsvpv0i7","kB5nPMaJQs","zFgtBlkMUA","uJScXFGzgp","AOgEeZ4I1v","16lHcxXTI4",
-"zFgtBFGzgp","zQt6Q45cIH","EdBKcYh1hF","W3VFHQnJ1S","uQIcz9eoRc","fcwDaReKEW","S77LHHlUbF","W7cTsCIShG","7fsYMUmaEv","K4GS8nFqik",
-"B3qemcmXIX","sx5GlNxx9V","LbRTHIBe8k","sx5GlQbxXc","cmXIXGrDg7","jSjS3GXdoH","SmGzvBFkb8","gIYvE9y4lw","pAhR1uoStw","cShY2cShY2",
-"JkzUnHfyNQ","2Nslmjtn0X","Zv7z0ksJby","tjQxsLDk6f","piJSk7hyVv","16lHcFjHXR","Q6LixQChxs","VBjhzRACuj","5IhmGChuy3","5Mg9rNOHsz",
-"QChxsMezSW","nlaBypFrrl","jiVBPnnP8o","gdQsSs7Mxk","sqVrfD6rBy","Yf2Ecd7vjM","5Mg9ruAWyp","bgJAzs93Ml","rKDLJsqVrf","Mkgy8VerEA",
-"DQimpogLgc","lpF6WRxrsm","I7p2a24ARF","YOfrYHzZT8","16lHcaDGtS","i7WMQNo0Qb","F6PT2K4GS8","0BmCyQClRL","hSSvQb29RJ","yEfy92Nslm",
-"CdyBV5IhmG","ogLgcpAhR1","nFqikn8pJ9","m4bxUyofH3","4dEz67fsYM","qQxHPs4786","OxWIHM6qcG","OUYuFW3VFH","29QAzpvgjS","aDGtS2Nslm",
-"pFrrlcQOnv","QWxoTDLhzM","iB08lHlUbF","8FmFHuQIcz","lCMxyLDk6f","Rxrsmi3pyd","TXQ0ZVerEA","hSSvQhYBCK","WDVWJDG4sT","MmKGJQnJ1S",
-"guMb8h1zcH","azIWp9GXkX","cShY2x3LDe","jzUqRlj07Q","aL6AJUl4a1","0h1b1LewvM","M3zXLv1Hln","xXTI4Mkgy8","64s8NoVQp6","MezSWsoy9t",
-"45cIHsqVrf","1LB1LHfyNQ","pAhR1GSQwj","ZhwG1qaofN","uoStwZUnqt","RzaZA64s8N","G1RhSe6e4z","5Drn0gIYvE","0KyfsVjCZq","prNT6LewvM",
-"Yf2Ec0YAGH","0BmCy1j5L8","BbwgAO3iyQ","Yw2oU3weIF","WmadAsoy9t","RkQketl72W","EOE1o4QMc9","MmsIoIRh48","NcICAuPX7G","pvgjS0ao3l",
-"IRh48Kr8ys","JRJQBJIqXi","RxrsmMojnP","RzaZA9GXkX","45cIHjeskS","8FmFH64s8N","qUJMdblLA9","POUYSJXljW","PYBf4fLNg8","tvdkDtvdkD",
-"iqv4kXflUq","tjQxs5VZjS","9iGoT8RCUA","KsjRKpFrrl","lweGyfFDrJ","KASQ8XyPZN","bZLvS2TRI7","BpYhVCIShG","DG4sTLDk6f","C2Irc5Namm",
-"JIqXimX2GE","s93MllCMxy","lsQGojzUqR","xReecAXpwE","n8pJ9lj07Q","tAOsruZPqg","fLNg8ZhwG1","OxWIHxReec","Mm8sis93Ml","ZUnqtjiVBP",
-"iB08laFFss","dQ58614FLR","K20wK07n1c","VIlwPbgJAz","580YD8RCUA","I7p2anFqik","dQ5865iGN5","TXQ0ZzY1GY","taOXKYh1hF","JKWYRx3LDe",
-"QClRL9eoRc","ksJbyB3qem","0ao3ld7vjM","DcpWBjiVBP","jS1ajlj07Q","prNT6DLhzM","AgJHQguMb8","oVQp6fcJOy","D6rBydQ586","oGu6xVNCPd",
-"7fsYMZUnqt","4QMc9W3VFH","Kr8ys1LB1L","580YDuupzk","pT8wuNo0Qb","Y1mC0BbwgA","QWxoT7hyVv","djsrvv8yFN","RBhp045cIH","TwanolCMxy",
-"QYxC0MmsIo","I7p2avkCHH","Q6Lixl83Ud","4dEz655rfB","tlILtXyPZN","POUYSdQ586","IjTwPulk41","CNHmvCxVEf","1j5L8mX2GE","3otm6AIYUu",
-"lm0pDXyPZN","BGaQYyEfy9","0BmCySmGzv","nFqikfcwDa","he9IA2TRI7","jtn0X9GXkX","TwanoqUJMd","DG4sTtl72W","DcpWBS77LH","lViBvzqH0W",
-"vOqCEDLhzM","LDk6fXyPZN","MaJQsOUYuF","x3LDezmLYD","9rlg9uQIcz","YjB9tDLhzM","MojnP9iGoT","lweGyRsQUq","0PktIxReec","StlDJHRxd8",
-"FLsphBpYhV","e6e4z2hEEU","I7p2ayEfy9","lXFOBi7WMQ","UlU3MReKEW","HRxd8ThjNn","guMb8HzZT8","Oz8yZk85Ae","HRxd87ku1p","W7cTsWMiS3",
-"PYBf44dEz6","JKWYRBFkb8","FLsphix74r","ydG8UFhtgl","yofH3jiVBP","KsjRKReKEW","e6e4zogLgc","qUJMdsqVrf","48cHLFnPFB","RkQkefLNg8",
-"lsQGolj07Q","8U2nUiqv4k","OxWIHK4GS8","S2DfuCK5W7","VLTy6HlUbF","JkzUngjUTu","0KyfscShY2","HP433xReec","FNYIMa00b5","VLTy6lsQGo",
-"lj07QQChxs","yToGWCqqaD","iwzGk9eoRc","hYBCKcShY2","WaWsvvOqCE","RxrsmGv3Fq","HfyNQvkCHH","cL0aEB3qem","Dz1R3Q6hMC","gf8rII7p2a",
-"d85a9yluBx","Yf2Eciqv4k","8TxD7lH1kt","MK07YaL6AJ","3otm67hyVv","QnJ1SVprf2","dpe1vWmadA","dpe1vTa8f6","lm0pD5nmWv","LDk6ffcJOy",
-"ZuDtD1v5hH","uZPqguvf7A","ZuDtDzbIYY","JIqXijeskS","WreyPZv7z0","WaWsv16lHc","QssNCRBhp0","8cVD3yofH3","oQ87rnnP8o","VjCZqh1zcH",
-"uPX7GyofH3","CqqaDcmXIX","mX2GEpv0i7","yofH3lViBv","tlILtSjskQ","QbxXcs93Ml","X6Pin5Mg9r","K20wKCp3mZ","Waim6O3iyQ","RsQUqwiHrZ",
-"lViBvD6rBy","QChxshi5X7","MK07YzFgtB","gjUTuwDajX","NhXdu7fsYM","kZANmqaofN","uLtKsAgJHQ","FwEJzIKxdL","qaofN0h1b1","nFqikS2Dfu",
-"S77LHqaofN","sx5Gl8xEKz","fLNg87hyVv","x3LDeEdBKc","HzZT8Kr8ys","KsjRKLDk6f","FwEJzMK07Y","uZPqgjtn0X","9eoRct59lR","xReecK20wK",
-"VIlwPOxWIH","FNYIMuN6r3","NOHszwDajX","aFFssLewvM","7ku1pGv3Fq","M6qcGZuDtD","FLsphOUqFM","8FmFHi3pyd","soy9tWPmlx","fmIK1SmGzv",
-"Q6LixL7cGc","Zv7z0pWiOs","M6qcGGWqqX","hUTw79rlg9","t98iWgjUTu","JIqXi8TxD7","SWfou1LB1L","In3NSYw2oU","gdQsSVNCPd","QWxoTNo0Qb",
-"aFFsssx5Gl","uJScXYjB9t","hYBCKIKxdL","i3pyd4QMc9","ciuWzFjHXR","CNHmvfaHir","Yw2oUdpe1v","KASQ8nlaBy","guMb8dmoS7","AOgEebgJAz",
-"EOE1o1LB1L","07n1cTa8f6","DcpWBcmXIX","CdyBVMojnP","9GXkXXflUq","FnPFByvOMI","faHirQbxXc","07n1c8xEKz","5VZjSMojnP","ciuWz29QAz",
-"GSQwjMGlTF","tl72W7fKYU","1j5L8Ss0Zu","hUTw7K20wK","JRJQBbZLvS","aDGtSK20wK","8xEKzix74r","Fhtgli3pyd","6AFT0F6PT2","yToGWt59lR",
-"a00b5CK5W7","1j5L8AOgEe","VBjhzrhl0J","C2IrcoQ87r","blLA9t98iW","BGaQY6q6L9","2Yz7EaFFss","guMb8RkQke","4QMc98RCUA","StlDJRsQUq",
-"NOHsz07n1c","VerEAogLgc","7fKYUHRxd8","tuDySiwzGk","cQOnvsx5Gl","FGzgpFxX9q","nnP8oAmdQd","oQ87riwzGk","iwzGk9iGoT","hE1Ql618Di",
-"0KyfsfFDrJ","CqqaDpmeCd","lsQGoydG8U","uPX7GzFgtB","e6e4z1LB1L","gjUTud85a9","i3pydwDajX","TXQ0ZHlUbF","LbRTH5ZaEz","Kr8ysuPX7G",
-"5ZaEz48cHL","IjTwPtuDyS","VIlwPW3VFH","t98iWU3yw5","dQ5868U2nU","jtn0XUlU3M","JKWYRIn3NS","uN6r3LbRTH","DcpWBguMb8","k85AePOUYS",
-"5IhmG0Kyfs","3otm6W3VFH","aL6AJIn3NS","9rlg9MGlTF","bgJAzZzJHW","lkMUAGv3Fq","brhlQNOHsz","JkzUnBFkb8","RpBQmVjCZq","CxVEf9rlg9",
-"TXQ0ZJIqXi","oVQp6M6qcG","wDajX5ZaEz","CdyBVM6qcG","s93MlBGaQY","NAFuwn8pJ9","BGaQYEdBKc","Ss0Zu7hyVv","EoToP5iGN5","aez9ycShY2",
-"MojnPoQ87r","i7WMQNcICA","tuDySgf8rI","aez9yNOHsz","uvf7AzmLYD","PYBf4jtn0X","Mm8si8FmFH","cShY2lXFOB","uPX7Gi3pyd","tl72WZhwG1",
-"JJs5mWDVWJ","FxX9qDG4sT","bZLvSjzUqR","lkMUAtvdkD","sx5GlWaim6","AkKTktlILt","b29RJAmdQd","jzUqRtAOsr","RpBQmnlaBy","bgJAzx3LDe",
-"VerEAAXpwE","hYBCKuJScX","jiVBPFLsph","fFDrJHfyNQ","WreyP0YAGH","tl72WStlDJ","jtn0XjeskS","HP433taOXK","s93Mlv8yFN","ru4UGCfgr3",
-"3otm6faHir","WPmlxm4bxU","ZJTXHHRxd8","0Wr5yuLtKs","lCMxyBGaQY","Vprf2d7vjM","pWiOsChuy3","EdBKc2TRI7","9XyT9QnJ1S","i7WMQMojnP",
-"atef2t59lR","aDGtSZzJHW","cShY2iwzGk","m4bxUzbIYY","POUYSpT8wu","M3zXL29QAz","Pb1pa0h1b1","F6PT2nlaBy","jS1ajZzJHW","aL6AJkB5nP",
-"07n1cciuWz","tuDySrKDLJ","DQimpCqqaD","LbRTHdQ586","Cp3mZMm8si","0YAGHKr8ys","VjCZqn1pmO","CqqaDru4UG","Ul4a1AmdQd","7fsYMwiHrZ",
-"y94nwZJTXH","zFgtBMm8si","8U2nUUlU3M","QChxsQYxC0","9eoRcKZamH","ksJbyRkQke","Q6LixoVQp6","VLTy6StlDJ","07n1co8Uyd","oGu6xAIYUu",
-"5IhmG8FmFH","YjB9tcQOnv","580YDPb1pa","9GXkXtaOXK","MojnPzz4ZU","uJScXiB08l","WaWsvhYBCK","GSQwjDQimp","djsrv2DREs","Mkgy8jzUqR",
-"2Yz7EsqVrf","CqqaD9rlg9","OHaBzsqVrf","jfREuJIqXi","uoStwRmDcr","kB5nPTXQ0Z","Vprf20YAGH","7lUXZyluBx","LbRTH0BmCy","14FLRd85a9",
-"FjHXRhe9IA","4W0TlfmIK1","kB5nPG1RhS","X6PinXyPZN","4dEz6NcICA","W7cTsGWqqX","5Mg9r2DREs","MaJQsuLtKs","uQIczS77LH","CdyBVru4UG",
-"pmeCdv2eC3","WPmlxqUJMd","CdyBVhi5X7","AIYUuvOqCE","LDk6fC2Irc","4W0Tln8pJ9","AkKTka00b5","5Mg9rIn3NS","d85a9uLtKs","ZuDtDpmeCd",
-"Twano1j5L8","uAWyp8xEKz","8U2nUaL6AJ","WaWsvHfyNQ","MaJQsL7cGc","Waim6lm0pD","AXpwEwDajX","BGaQYUmaEv","yofH3RBhp0","FnPFBoQ87r",
-"ydG8UFxX9q","W7cTs4W0Tl","IKxdLaez9y","h1zcHqaofN","AIYUukB5nP","HfyNQvLsmS","5drc6MmKGJ","FNYIM0Wr5y","pvgjSXflUq","8TxD7Ul4a1",
-"WmadAjeskS","0KyfsbrhlQ","n1pmOiwzGk","3otm6KASQ8","v1Hln55rfB","sx5Gl55rfB","VNCPdtlILt","Pb1paNhXdu","MK07YfFDrJ","n1pmOBpYhV",
-"0h1b1I7p2a","FPfSEDG4sT","S77LHMGlTF","M3zXLDLhzM","hE1QltjQxs","ulk41zQt6Q","7lUXZNxx9V","Zv7z0TXQ0Z","QChxsAmdQd","pAhR1hYBCK",
-"fLNg8iwzGk","l83Ud9rlg9","jS1aj9y4lw","XflUql83Ud","WDVWJpvgjS","RsQUqrhl0J","2ZHdk9eoRc","G1RhS3otm6","azIWpQChxs","CNHmvhUTw7",
-"RxrsmDG4sT","8FmFHQChxs","i7WMQ24ARF","Uvlv40ao3l","K4GS8aFFss","guMb8qUJMd","uTacxOHaBz","QworuI7p2a","MmKGJyToGW","qQxHP9XyT9",
-"QnJ1SazIWp","LDk6f7X3uy","5VZjS2Nslm","GrDg7a00b5","d85a9J2mQi","ZhwG1L7cGc","uTacxWaim6","vLsmSGSQwj","Y1mC04QMc9","lCMxyQ6hMC",
-"pAhR1pWiOs","FxX9qru4UG","GWqqXVBjhz","MmsIoW7cTs","2NslmHfyNQ","Ta8f6e6e4z","Ul4a1gf8rI","XyPZNZ4I1v","blLA955rfB","NAFuw8FmFH",
-"D6rBypAhR1","vOqCEGWqqX","uoStwTa8f6","HfyNQi7WMQ","5nmWvBFkb8","JJs5msuY4x","QworunlaBy","Cfgr3TCgPp","aL6AJZuDtD","07n1crKDLJ",
-"FwEJzYw2oU","guMb8618Di","GrDg7hSSvQ","fcJOyQnJ1S","S77LHjfREu","FnPFBn1pmO","d7vjMRzaZA","Mkgy8x3LDe","BCxeCWreyP","fmIK1QnJ1S",
-"G1RhSFcWrW","tuDySVLTy6","cQOnvd7vjM","uPX7GuoStw","UmaEvHP433","Vprf2C2Irc","lH1ktCfgr3","lXFOBOUYuF","jeskSlViBv","gtCA5MK07Y",
-"pvgjSi3pyd","uZPqgWMiS3","OUYuF7fKYU","OUYuFEoToP","BpYhVWMiS3","14FLRfcwDa","pAhR1fcJOy","he9IACNHmv","ECMvUjS1aj","IRh48mX2GE",
-"HRxd8qaofN","dpe1vzmLYD","h1zcHTXQ0Z","yEfy9xXTI4","ZUnqtjfREu","7hyVvKASQ8","GSQwj7X3uy","0ao3l8hJdt","JXljWXflUq","U3yw5fqypy",
-"ciuWz8FmFH","lj07QStlDJ","5ZaEz5ZaEz","i7WMQIRh48","9eoRczqH0W","NcICAAIYUu","gIYvExReec","7lUXZ2TRI7","HzZT8RsQUq","HlUbF7X3uy",
-"nnP8oOxWIH","iwzGkhSSvQ","8FmFHjSjS3","o8UydBCxeC","LewvMXflUq","7Ow5CpiJSk","D6rByFNYIM","FwEJzo8Uyd","9rlg91j5L8","xReecoVQp6",
-"sqVrf9eoRc","9eoRc0BmCy","HlUbFJ2mQi","t59lRhUTw7","atef2qQxHP","ix74rECMvU","B3qemjtn0X","bZLvSB3qem","x3LDekZANm","iB08l7hyVv",
-"MmsIoFPfSE","BCxeCyofH3","HlUbFJkzUn","uZPqgo8Uyd","DG4sTxXTI4","NAFuw9GXkX","ogLgcX6Pin","ulk41VjCZq","lXFOBPOUYS","Yh1hFCK5W7",
-"jzUqRG1RhS","mz8gx580YD","FVMxoVIlwP","NOHszDz1R3","XyPZNGv3Fq","QYxC0P6bcg","uZPqg5VZjS","5iGN5pAhR1","QClRLJ2mQi","uQIczZJTXH",
-"BFkb8yluBx","Cp3mZHP433","zFgtBhE1Ql","AgJHQReKEW","Ul4a1Vprf2","16lHclH1kt","tuDySFhtgl","In3NSWaWsv","QworuU3yw5","lj07Qy94nw",
-"4W0TlGXdoH","v2eC30Kyfs","guMb8TCgPp","5drc64dEz6","KZamHpv0i7","WMiS3VjCZq","jfREulViBv","3otm6No0Qb","SWfouksJby","ReKEWBpYhV",
-"9rlg9OHaBz","WPmlxBGaQY","M6qcGlpF6W","29QAzh1zcH","iwzGkdmoS7","v2eC3UlU3M","jfREuZzJHW","NAFuwBbwgA","suY4x55rfB","bZLvSmX2GE",
-"SjskQru4UG","e6e4zRsQUq","GrDg7MaJQs","7fKYUChuy3","Ss0ZuprNT6","WPmlxcmXIX","ciuWzYw2oU","ReKEWfaHir","rz7Ut5ZaEz","a00b5gIYvE",
-"JIqXicmXIX","CNHmvGSQwj","0h1b1JkzUn","IKxdLru4UG","sqVrfbgJAz","RxrsmkZANm","Gv3Fq7ku1p","JXljWOUqFM","Yw2oU580YD","faHirJJs5m",
-"FFDuiLDk6f","7fKYUjtn0X","fcJOyMK07Y","0BmCyNOHsz","4QMc9YOfrY","oQ87rRkQke","Zv7z0lH1kt","tuDyS8FmFH","0Wr5ypWiOs","ReKEW7fsYM",
-"iKqhrWmadA","Ul4a1TCgPp","qQxHPnnP8o","t98iWMezSW","xReeclCMxy","uoStwOHaBz","X6PinGSQwj","uJScXBpYhV","rhl0JqQxHP","D6rByzqH0W",
-"xciqp7Ow5C","iKqhrlViBv","hE1QlFLsph","hi5X78hJdt","Mm8siuTacx","zz4ZUQnJ1S","IjTwPpFrrl","Ss0ZuokgRi","b29RJeuZA5","pWiOssuY4x",
-"X6PinVIlwP","QYxC05IhmG","fFDrJD6rBy","RmDcrt59lR","UmaEv64s8N","MmKGJ5nmWv","b29RJ0BmCy","d7vjM7hyVv","Pb1pawiHrZ","euZA5jtn0X",
-"rz7UtNo0Qb","fLNg8IKxdL","NAFuwReKEW","cShY2WMiS3","zFgtBfqypy","HRxd8rz7Ut","3weIFnnP8o","nFqik0PktI","64s8N2ZHdk","Zv7z0zz4ZU",
-"VLTy62ZHdk","lsQGoJKWYR","QWxoTQ6hMC","hSSvQNxx9V","7lUXZwDajX","FGzgpaL6AJ","IjTwPTXQ0Z","lsQGozHF1q","Oz8yZaL6AJ","VNCPdMkgy8",
-"CK5W7F6PT2","ydG8Uiqv4k","RxrsmSs0Zu","7fsYMPb1pa","WmadAgtCA5","2hEEUv8yFN","jeskSFhtgl","sx5GlSjskQ","KsjRKHzZT8","618DiL7cGc",
-"CIShGpT8wu","uAWypHlUbF","PYBf4tuDyS","14FLR5IhmG","GSQwjbrhlQ","ciuWzReKEW","14FLRwDajX","WPmlxgtCA5","O3iyQZhwG1","7Ow5CuoStw",
-"RkQke0BmCy","dQ586KASQ8","ZUnqtX6Pin","OxWIHMmKGJ","IjTwPQWxoT","sqVrfcQOnv","4dEz6zmLYD","fmIK1BGaQY","aFFssNhXdu","pmeCdFNYIM",
-"zz4ZUwDajX","zbIYY7Ow5C","WaWsvyluBx","lCMxyjtn0X","VerEACIShG","dpe1vn8pJ9","oVQp607n1c","pv0i7SbRYy","oGu6xWaWsv","Z4I1vjfREu",
-"RpBQm9y4lw","ZhwG1y94nw","sx5Glzz4ZU","VNCPdLbRTH","AmdQdwDajX","OHaBzIn3NS","l83UdcShY2","VBjhzlH1kt","WMiS3TCgPp","yvOMI6AFT0",
-"t59lRYw2oU","9GXkXReKEW","okgRihE1Ql","FNYIMcQOnv","MojnPBpYhV","ciuWzdQ586","zQt6QZJTXH","zqH0WqQxHP","AXpwE48cHL","he9IAYf2Ec",
-"9eoRcyvOMI","AIYUuaFFss","y94nwtvdkD","HP433BpYhV","pWiOsRxrsm","FVMxo5ZaEz","AmdQd5iGN5","S2DfutlILt","Ul4a1DcpWB","Q6LixSs0Zu",
-"9y4lwU3yw5","oVQp6nFqik","W3VFHMm8si","JIqXiHlUbF","zQt6QXflUq","QWxoTru4UG","In3NSfcwDa","nFqik9XyT9","QbxXcvLsmS","QssNCRsQUq",
-"ksJbyjSjS3","gtCA5yToGW","ciuWz7X3uy","Yh1hFM6qcG","lweGyMezSW","dQ586QYxC0","Gv3FqgIYvE","FnPFBYf2Ec","xXTI4pv0i7","MmKGJQClRL",
-"lCMxyCfgr3","NhXduatef2","AIYUuOxWIH","BGaQYm4bxU","mX2GES77LH","RsQUquoStw","JkzUnvLsmS","blLA9MGlTF","MmKGJOxWIH","zFgtBAOgEe",
-"euZA5yEfy9","cmXIXpWiOs","S77LHMaJQs","qUJMdJRJQB","oQ87rfaHir","0h1b1uvf7A","GSQwj5nmWv","0MR5XTCgPp","t98iWMGlTF","WPmlxsx5Gl",
-"kZANm1LB1L","IjTwP0Kyfs","rz7UtfcwDa","ulk41wiHrZ","Cfgr3ThjNn","qQxHPFLsph","B3qemhE1Ql","tlILtlj07Q","DQimp2hEEU","TCgPpRpBQm",
-"07n1czbIYY","QWxoTJKWYR","NcICAiKqhr","8TxD74dEz6","tuDySiB08l","VBjhz8TxD7","pT8wu2Nslm","SjskQuPX7G","TwanoUl4a1","5drc6fFDrJ",
-"lXFOBwiHrZ","qaofNIBe8k","uN6r3k85Ae","CqqaD9iGoT","8hJdtlH1kt","fmIK16q6L9","xciqpS77LH","WMiS3fcJOy","7ku1plXFOB","m4bxUZuDtD",
-"ZzJHW6AFT0","sqVrfRzaZA","aFFssjtn0X","Pb1paNOHsz","kB5nPFnPFB","DQimppAhR1","7ku1piwzGk","jSjS3AOgEe","b29RJRkQke","CxVEfzQt6Q",
-"aDGtSokgRi","I7p2aQworu","7X3uyfFDrJ","gjUTuqaofN","WMiS3W3VFH","bgJAzIn3NS","14FLRoQ87r","XyPZNNOHsz","CIShGhi5X7","IKxdLMezSW",
-"5VZjSOz8yZ","qQxHP0Kyfs","bZLvSXflUq","0h1b1CNHmv","AXpwEFhtgl","oQ87rDQimp","DcpWBOxWIH","pAhR1Fhtgl","QbxXcfcwDa","hYBCKbZLvS",
-"fLNg8AgJHQ","GWqqX0PktI","K20wKsoy9t","PYBf429QAz","FwEJzGSQwj","4W0TlWMiS3","Oz8yZe6e4z","iqv4kW7cTs","QChxspT8wu","64s8NAkKTk",
-"ZuDtDYOfrY","QworucL0aE","RBhp0nFqik","3weIFjtn0X","CIShGDLhzM","9iGoT29QAz","M6qcGQYxC0","MaJQsjS1aj","tuDySOz8yZ","t98iWuoStw",
-"cL0aEWPmlx","djsrvtvdkD","CdyBVaL6AJ","8RCUAG1RhS","JkzUn8hJdt","UlU3M6q6L9","jfREulH1kt","sx5Gl0MR5X","9eoRcoGu6x","JRJQBRxrsm",
-"FLsph5IhmG","fcwDaP6bcg","aFFsso8Uyd","blLA9Mkgy8","0MR5XuJScX","2hEEURsQUq","kZANm0YAGH","zFgtBoVQp6","AkKTkCfgr3","ix74r5Mg9r",
-"Yw2oUM6qcG","AXpwExciqp","Ul4a1FFDui","5Mg9rUmaEv","AkKTkWaWsv","LewvMSmGzv","faHirVLTy6","ZhwG1uLtKs","0PktIBCxeC","Oz8yZzHF1q",
-"oVQp6S77LH","NAFuwRsQUq","brhlQChuy3","W3VFHDG4sT","v2eC3JKWYR","uupzkkB5nP","VLTy6pWiOs","WMiS37fsYM","rhl0J0h1b1","FLsphiwzGk",
-"9rlg9B3qem","M3zXLlsQGo","djsrvYw2oU","vLsmSC2Irc","TCgPplCMxy","oGu6xDcpWB","Kr8ysuLtKs","zz4ZUL7cGc","CdyBV7fKYU","FGzgp0h1b1",
-"6AFT0kZANm","WPmlxeuZA5","9XyT9Ss0Zu","YOfrYokgRi","Y1mC0gf8rI","gtCA5gjUTu","pmeCdrhl0J","o8UydEOE1o","uZPqgOUqFM","7X3uygf8rI",
-"9iGoTjSjS3","sqVrfThjNn","ZJTXHqQxHP","zQt6QPb1pa","Yw2oUJ2mQi","WmadAQssNC","Uvlv4VjCZq","uAWypyvOMI","WmadAlweGy","RzaZAFnPFB",
-"hYBCKrhl0J","Qworuv8yFN","ciuWzIjTwP","Waim6rz7Ut","HzZT8I7p2a","uN6r3QnJ1S","SbRYycShY2","v2eC3uupzk","8TxD7BpYhV","jSjS3l83Ud",
-"QChxsDLhzM","djsrvuN6r3","kZANmBpYhV","MojnPrKDLJ","iqv4k14FLR","WaWsv1LB1L","uvf7AbZLvS","QChxsqQxHP","CqqaDqaofN","WmadA6AFT0",
-"NOHszoGu6x","n8pJ9RmDcr","9iGoT14FLR","S77LHHfyNQ","yvOMIKr8ys","kZANm1j5L8","FnPFBuupzk","FxX9qIRh48","24ARFXyPZN","rKDLJrKDLJ",
-"LbRTHmX2GE","ZzJHW8TxD7","tjQxsRzaZA","pFrrl9GXkX","YOfrYciuWz","dQ586QClRL","Mm8siBGaQY","OUqFMRBhp0","TCgPpOxWIH","5NammWmadA",
-"soy9tMmsIo","wDajX5IhmG","FhtglZuDtD","EdBKcix74r","iB08lYh1hF","EoToPyluBx","ksJby7Ow5C","tl72WNcICA","JRJQBtAOsr","AmdQd580YD",
-"ogLgc7fsYM","kB5nPPOUYS","HzZT8gIYvE","1LB1LQnJ1S","VNCPdoVQp6","5iGN5SmGzv","2Nslm0PktI","he9IAOxWIH","lm0pDtAOsr","lpF6WIRh48",
-"qaofNlm0pD","2ZHdka00b5","QClRLNcICA","ix74rqUJMd","LewvMhe9IA","b29RJiB08l","zHF1qjS1aj","oGu6xG1RhS","8cVD3vkCHH","Nxx9VJRJQB",
-"e6e4zVjCZq","cQOnv9GXkX","yEfy9Cfgr3","m4bxUhSSvQ","Cfgr3ydG8U","IKxdLhUTw7","Q6hMCVIlwP","OUqFM6q6L9","fqypye6e4z","t59lRB3qem",
-"M3zXLIjTwP","zY1GYG1RhS","Yw2oUzFgtB","9GXkXDz1R3","iwzGkwDajX","VLTy6cmXIX","Ta8f6B3qem","Waim6euZA5","gdQsSW3VFH","yluBx5Namm",
-"2Yz7EPYBf4","F6PT2azIWp","jeskSlm0pD","Mm8siTwano","DQimphi5X7","OxWIHZ4I1v","FwEJz9eoRc","FGzgpEoToP","KASQ8hSSvQ","piJSkkZANm",
-"UlU3MAkKTk","FxX9qNcICA","atef26AFT0","Cp3mZNhXdu","Yf2EcciuWz","X6PinlH1kt","W3VFH5Namm","Chuy3s4786","uoStw618Di","guMb8Waim6",
-"Z4I1vWDVWJ","uoStwUl4a1","Cfgr35IhmG","MaJQsJIqXi","jSjS37fKYU","Nxx9VReKEW","ix74rt98iW","6q6L9FNYIM","tAOsrECMvU","ZzJHWJkzUn",
-"0MR5X24ARF","WmadAWaWsv","FhtglK20wK","Yf2EcWaWsv","StlDJoGu6x","EOE1oWaim6","In3NSI7p2a","uQIcz0Wr5y","UmaEvcmXIX","oGu6xZuDtD",
-"l83UdKsjRK","55rfBCdyBV","hUTw7MezSW","P6bcgFFDui","8TxD7prNT6","5iGN58cVD3","uPX7GYh1hF","iB08lDcpWB","rz7UtQ6Lix","piJSk7ku1p",
-"o8UyddQ586","uoStwpWiOs","wDajXAOgEe","hE1QlciuWz","K4GS8uPX7G","BFkb8RzaZA","Uvlv464s8N","AmdQdZzJHW","StlDJzHF1q","DLhzMAgJHQ",
-"VIlwPFjHXR","qQxHPiKqhr","pv0i7ulk41","sx5GlPYBf4","P6bcgo8Uyd","ix74r2Yz7E","lj07QAmdQd","WPmlxAIYUu","ZhwG1hi5X7","ZuDtDDz1R3",
-"O3iyQuPX7G","ZuDtDMaJQs","4dEz65Drn0","jeskS48cHL","SbRYyn8pJ9","uupzkK4GS8","he9IA8RCUA","AOgEes7Mxk","DcpWBLewvM","lpF6WNAFuw",
-"XflUqtl72W","pFrrlRkQke","3otm6GrDg7","s7MxkRsQUq","1v5hH45cIH","Y1mC0fqypy","ix74rAkKTk","CK5W7HP433","lsQGoFcWrW","vLsmSjiVBP",
-"45cIHfqypy","euZA5uAWyp","9rlg99XyT9","Vprf28U2nU","qUJMdHP433","RmDcr8TxD7","0YAGHsx5Gl","IBe8kyluBx","JkzUnjzUqR","MmKGJksJby",
-"DcpWB9iGoT","ZhwG1VBjhz","jeskSG1RhS","qaofN0ao3l","aDGtSn8pJ9","cQOnvZv7z0","cQOnvhUTw7","0Kyfs5Namm","aez9yjSjS3","GXdoHYh1hF",
-"48cHLhSSvQ","Y1mC0FVMxo","Q6hMCtuDyS","8xEKzwDajX","fmIK1580YD","nlaBywDajX","yvOMINAFuw","oGu6xAgJHQ","i3pydCp3mZ","uvf7AZv7z0",
-"0MR5XZUnqt","n8pJ9lweGy","pWiOs0BmCy","48cHL7lUXZ","3otm6i7WMQ","8xEKzNo0Qb","TXQ0Z8cVD3","fcwDaQnJ1S","HP433ciuWz","jS1ajRmDcr",
-"euZA5taOXK","580YDNcICA","K20wKa00b5","IKxdLGXdoH","HlUbFjeskS","jeskSBbwgA","i7WMQyluBx","QClRLTCgPp","yvOMIFcWrW","uLtKs0PktI",
-"7ku1pb29RJ","K4GS8QChxs","SjskQcmXIX","P6bcgi3pyd","wiHrZtjQxs","t59lRsx5Gl","48cHL7ku1p","618DijeskS","14FLRgf8rI","CxVEfCqqaD",
-"BpYhVKsjRK","lj07Q2Nslm","ZzJHWwiHrZ","aL6AJjiVBP","Kr8ysDLhzM","Nxx9VQWxoT","hE1QlVNCPd","cShY2MaJQs","Q6LixChuy3","nlaByVLTy6",
-"l83UdnlaBy","FNYIMjS1aj","MK07YS77LH","6AFT0aDGtS","7X3uy6AFT0","WDVWJTCgPp","RpBQmBpYhV","yEfy9zz4ZU","3weIFOUYuF","2hEEUFhtgl",
-"uupzk3weIF","WMiS3Nxx9V","BpYhVprNT6","vLsmSzbIYY","gf8rIRpBQm","0h1b1i3pyd","1v5hHyvOMI","AmdQduPX7G","soy9the9IA","dQ586J2mQi",
-"24ARFJIqXi","azIWpThjNn","azIWpQYxC0","t59lRFcWrW","aDGtShe9IA","jtn0XgtCA5","lj07Qix74r","aDGtSciuWz","taOXKZuDtD","d85a9Nxx9V",
-"taOXKMK07Y","8cVD355rfB","wiHrZW7cTs","Kr8ysNhXdu","iqv4k8U2nU","7X3uyzbIYY","IjTwP7fsYM","OxWIHdjsrv","8hJdthUTw7","DG4sT1v5hH",
-"jSjS3QWxoT","In3NSaFFss","Ul4a1iqv4k","aL6AJ1LB1L","S77LHDLhzM","4dEz69rlg9","FGzgpQssNC","Q6hMCXyPZN","qUJMdlj07Q","Twano5drc6",
-"Q6LixNxx9V","XyPZNuupzk","t98iWzmLYD","AgJHQO3iyQ","hUTw7JXljW","vLsmS55rfB","vLsmSrKDLJ","pWiOsUmaEv","G1RhSs7Mxk","ZuDtDsoy9t",
-"rhl0JnlaBy","jS1ajzY1GY","8TxD7y94nw","Oz8yZ5Drn0","faHiroGu6x","Q6LixWDVWJ","cmXIX64s8N","uLtKsXyPZN","h1zcHtjQxs","2TRI7jtn0X",
-"Cfgr3WreyP","y94nwbZLvS","oGu6xSs0Zu","VerEAtl72W","ZhwG19iGoT","atef2fFDrJ","lkMUAvkCHH","brhlQW7cTs","IjTwPi3pyd","0YAGHpWiOs",
-"XyPZN0YAGH","uLtKsyEfy9","TCgPpAgJHQ","Qworuzz4ZU","bZLvSWmadA","yofH3mz8gx","1j5L8BbwgA","uZPqgBbwgA","mz8gxUvlv4","lXFOBzY1GY",
-"HlUbFQChxs","lm0pDUvlv4","RmDcrk85Ae","CqqaDiqv4k","GWqqXUlU3M","aez9yjtn0X","uoStw7lUXZ","FLsphZJTXH","gf8rIOUqFM","blLA9v1Hln",
-"azIWpCK5W7","QbxXcI7p2a","DQimp9eoRc","MezSW5VZjS","IRh48Ul4a1","0ao3liB08l","vkCHHVNCPd","n8pJ9ydG8U","GrDg79XyT9","DcpWBvkCHH",
-"JkzUnyluBx","Qworusx5Gl","WaWsvVLTy6","WaWsv2ZHdk","lsQGov2eC3","UmaEv24ARF","6AFT0uAWyp","tAOsrCIShG","rhl0JvOqCE","WDVWJDLhzM",
-"SbRYyNhXdu","gf8rIEOE1o","t59lRMm8si","dhSuHlm0pD","14FLRQ6Lix","iwzGkAXpwE","bZLvS1j5L8","cL0aEPOUYS","7ku1p9rlg9","BFkb8MGlTF",
-"gf8rI9eoRc","cShY2jeskS","mz8gxGWqqX","zqH0WlXFOB","ReKEWVjCZq","gdQsSUlU3M","2hEEUsqVrf","MmKGJRkQke","LbRTHMmKGJ","pAhR19GXkX",
-"AkKTkNo0Qb","FcWrW7fKYU","FcWrWfmIK1","fcJOyIKxdL","JKWYRokgRi","2NslmBpYhV","jzUqRJKWYR","8TxD7Q6hMC","yluBxMmsIo","zQt6QuLtKs",
-"zqH0WMmKGJ","NhXdugf8rI","x3LDeGSQwj","LDk6fB3qem","vkCHHS2Dfu","SbRYywiHrZ","8hJdt2hEEU","K20wK3weIF","rhl0JWmadA","580YDQChxs",
-"618DiJ2mQi","hUTw7fmIK1","yofH3zFgtB","AkKTktaOXK","suY4xaez9y","oVQp6MGlTF","JIqXiKsjRK","lH1kt8xEKz","a00b5CxVEf","KZamHvkCHH",
-"MmsIoKsjRK","qaofNpmeCd","KASQ8v2eC3","piJSkSmGzv","gf8rIe6e4z","7X3uyFxX9q","vOqCEuTacx","v1HlnKr8ys","VIlwPXyPZN","aFFssHlUbF",
-"Gv3FqZUnqt","BFkb8QChxs","7X3uyVBjhz","KZamHtaOXK","ReKEWWMiS3","X6PinazIWp","zbIYY580YD","Cfgr3o8Uyd","1v5hHYh1hF","PYBf4CK5W7",
-"9eoRcFPfSE","uN6r3lViBv","tjQxsyofH3","Yf2EcMkgy8","Dz1R3VerEA","EoToPZuDtD","CK5W78xEKz","piJSkNcICA","WDVWJ0PktI","FVMxoTCgPp",
-"djsrv0Kyfs","lH1kthE1Ql","rKDLJdhSuH","MmsIoS77LH","v2eC39rlg9","vOqCE5drc6","jzUqRd85a9","HlUbF8TxD7","LDk6fni2v1","jS1ajhYBCK",
-"SmGzvix74r","fcwDa2ZHdk","8FmFHGXdoH","DcpWBxReec","GrDg7Y1mC0","7fsYMqQxHP","jSjS3DcpWB","Uvlv4FwEJz","8cVD32Yz7E","zHF1q5iGN5",
-"ReKEWSs0Zu","7fKYUTXQ0Z","LewvMcL0aE","RpBQmx3LDe","uAWyphSSvQ","Gv3FqtvdkD","gjUTuaDGtS","2hEEURACuj","zY1GYuvf7A","JJs5mv2eC3",
-"Q6LixSbRYy","M3zXLWMiS3","lXFOBlCMxy","HP433dpe1v","jiVBPWMiS3","FwEJz2Nslm","0YAGHKASQ8","ZzJHW5drc6","yEfy95Drn0","uvf7AQ6Lix",
-"bgJAzGrDg7","sx5GlSbRYy","CqqaDhe9IA","FcWrWcShY2","lkMUAaFFss","Oz8yZEOE1o","Kr8ysAmdQd","RzaZAZUnqt","DcpWB14FLR","AkKTkZ4I1v",
-"24ARF9iGoT","5nmWvuTacx","wiHrZrhl0J","K20wKQYxC0","W3VFHMkgy8","1v5hHIKxdL","In3NSxReec","gf8rIpFrrl","fFDrJFNYIM","uPX7G9iGoT",
-"sqVrfxReec","suY4x7Ow5C","JJs5mL7cGc","jeskSD6rBy","nnP8od85a9","x3LDenFqik","M6qcGU3yw5","4dEz6vkCHH","soy9tni2v1","zz4ZUVIlwP",
-"hYBCKYh1hF","LbRTHlj07Q","HRxd8jeskS","fLNg8FjHXR","kB5nPfaHir","gtCA5BbwgA","n1pmOydG8U","s4786In3NS","t59lR3otm6","8hJdtuJScX",
-"a00b5dQ586","pAhR1SjskQ","iqv4klH1kt","QbxXcjzUqR","xciqpyluBx","fLNg8B3qem","ZhwG12DREs","EdBKclCMxy","dmoS7POUYS","lH1ktFPfSE",
-"3otm6yluBx","OUYuFF6PT2","WDVWJNhXdu","GSQwjLDk6f","FjHXRwiHrZ","7Ow5C618Di","3weIFFPfSE","DQimp29QAz","CK5W748cHL","suY4xzFgtB",
-"MaJQsbZLvS","1v5hHCxVEf","WDVWJDz1R3","he9IAcQOnv","SbRYyTa8f6","uJScX8TxD7","FcWrWFcWrW","BFkb8Q6hMC","djsrvksJby","LewvMO3iyQ",
-"lkMUAcmXIX","prNT6K20wK","LDk6fpAhR1","qQxHP8cVD3","9y4lwWPmlx","iwzGkL7cGc","tl72WOz8yZ","uPX7GMm8si","KsjRKFhtgl","2Yz7E8TxD7",
-"jS1ajXyPZN","zFgtBvLsmS","RpBQmNcICA","rz7UtO3iyQ","xXTI4XyPZN","lCMxyCK5W7","BpYhVIRh48","pWiOs8U2nU","QworuFPfSE","S2DfuB3qem",
-"fqypyv1Hln","FcWrW4QMc9","hYBCKSjskQ","fqypyX6Pin","tuDySGv3Fq","aFFss9XyT9","JXljWMaJQs","ulk41uvf7A","uZPqgTwano","BbwgAqQxHP",
-"okgRiVprf2","StlDJ8cVD3","fFDrJsoy9t","oVQp6pmeCd","Ta8f6EoToP","nFqikDcpWB","45cIHsx5Gl","AOgEeYh1hF","Ta8f6SbRYy","lweGydQ586",
-"zmLYDprNT6","QClRLni2v1","WPmlxRBhp0","JKWYRDcpWB","RpBQmKsjRK","lkMUAhe9IA","yEfy9y94nw","iKqhrQ6Lix","k85Ae5VZjS","B3qemCIShG",
-"uQIczjSjS3","djsrvJ2mQi","qUJMdaFFss","AkKTkpmeCd","FVMxo0YAGH","YOfrYsx5Gl","ydG8UazIWp","atef2mX2GE","mX2GEfcJOy","ulk41CqqaD",
-"5IhmG9eoRc","WMiS3XflUq","K20wKd85a9","jeskS8TxD7","UlU3MaL6AJ","0KyfshYBCK","CdyBVd85a9","guMb8QYxC0","ZzJHWBCxeC","zmLYDfaHir",
-"tuDySK4GS8","64s8Nb29RJ","48cHLi7WMQ","FNYIM5Mg9r","U3yw5tl72W","NAFuwIRh48","d7vjMhi5X7","5IhmGaFFss","i3pyd8TxD7","cQOnvO3iyQ",
-"EOE1o2Yz7E","pvgjSzHF1q","guMb8ECMvU","Q6LixTwano","4W0TlMm8si","s93Mldpe1v","blLA9blLA9","bZLvSAOgEe","gtCA5ogLgc","LDk6fatef2",
-"EOE1ouoStw","I7p2azbIYY","prNT6kZANm","K20wKfqypy","OUYuF1j5L8","HP433DG4sT","ulk41EoToP","UlU3MUl4a1","CqqaDvkCHH","tvdkDe6e4z",
-"8TxD7wiHrZ","lXFOBQChxs","Mm8siNo0Qb","cQOnvRACuj","nlaByJJs5m","djsrvKsjRK","dQ5867lUXZ","pAhR1fmIK1","Ul4a1pWiOs","5Mg9rSWfou",
-"yEfy9uLtKs","G1RhSciuWz","lViBvFVMxo","KZamHrhl0J","1j5L8EdBKc","uJScXLbRTH","618DinFqik","BGaQY8hJdt","GSQwjTCgPp","3otm6lkMUA",
-"2hEEUgdQsS","djsrvgdQsS","I7p2aQnJ1S","BCxeC9rlg9","X6Pint98iW","0Kyfs5VZjS","uPX7GSbRYy","t59lRfmIK1","RpBQme6e4z","vOqCEi7WMQ",
-"uAWypCK5W7","Zv7z0MaJQs","uvf7AK20wK","rKDLJ0MR5X","QnJ1St98iW","8cVD3HzZT8","64s8NQworu","LDk6fSmGzv","n8pJ9LewvM","pWiOs9XyT9",
-"0BmCy2hEEU","WMiS3lXFOB","WaWsvVBjhz","uLtKs8RCUA","L7cGcuAWyp","jiVBPECMvU","euZA5QbxXc","CNHmvKASQ8","HzZT8n1pmO","P6bcgazIWp",
-"DcpWBtjQxs","RBhp0gdQsS","pmeCdgjUTu","zFgtBjiVBP","7hyVv9eoRc","a00b5qUJMd","618DiS2Dfu","1v5hHBpYhV","580YDpv0i7","oVQp6Ul4a1",
-"8TxD764s8N","Nxx9VpT8wu","OUYuFdhSuH","0MR5XMmKGJ","d7vjMThjNn","14FLRD6rBy","yofH30ao3l","Pb1paoQ87r","AmdQdXyPZN","oVQp6aez9y",
-"14FLRyToGW","5Mg9rMmKGJ","OHaBz07n1c","k85Ae8U2nU","1j5L8aDGtS","ZuDtDCxVEf","No0QbDQimp","KASQ8Chuy3","NcICAoGu6x","pFrrlZUnqt",
-"FjHXRpT8wu","8cVD3ix74r","OUYuFcQOnv","FwEJz0ao3l","nlaByHfyNQ","EOE1ozz4ZU","XyPZNhe9IA","QbxXcm4bxU","lCMxyfqypy","gjUTufcJOy",
-"Waim6MaJQs","K4GS8yToGW","7ku1p48cHL","uAWypEoToP","8xEKzdQ586","xReecOxWIH","sqVrf0ao3l","ECMvUWaWsv","YOfrYvOqCE","WreyPlViBv",
-"sx5GlP6bcg","uAWyp5drc6","DG4sTgIYvE","5VZjSECMvU","brhlQlkMUA","OUYuFMkgy8","Ta8f6jzUqR","8U2nUZhwG1","qaofNaez9y","5iGN5aDGtS",
-"Chuy3OxWIH","BFkb8iqv4k","Gv3Fqd85a9","2hEEUyofH3","7lUXZ6q6L9","DcpWBJRJQB","v8yFN8U2nU","VLTy6i3pyd","GrDg7lViBv","3otm65drc6",
-"SWfou618Di","Vprf27fsYM","aDGtSHP433","vLsmSJKWYR","0h1b1Cfgr3","16lHcNcICA","B3qem64s8N","gdQsSlCMxy","CNHmvTCgPp","b29RJO3iyQ",
-"ZhwG1fqypy","Waim6Yh1hF","X6PinHRxd8","2DREsS2Dfu","xciqpO3iyQ","O3iyQfcJOy","iB08lCdyBV","o8Uyd0h1b1","yofH35iGN5","QssNCgf8rI",
-"BbwgAFVMxo","ZJTXHNOHsz","ydG8UbZLvS","WMiS345cIH","UmaEv5iGN5","aez9yMmKGJ","brhlQyToGW","pv0i7WaWsv","QworuqUJMd","vkCHHgtCA5",
-"lpF6W6AFT0","0BmCysx5Gl","CIShGyluBx","iB08llH1kt","J2mQiyToGW","IBe8k1v5hH","0KyfsQChxs","yvOMIKZamH","14FLRciuWz","uupzkWaim6",
-"NOHszQClRL","nnP8oNo0Qb","Q6LixRkQke","lViBvzz4ZU","Yf2EcSWfou","MGlTFdQ586","ZhwG11j5L8","ogLgcBCxeC","ZuDtDhe9IA","8RCUAM6qcG",
-"4W0Tlo8Uyd","yToGWIKxdL","FFDui45cIH","sx5GlfcJOy","yvOMIOz8yZ","JkzUnHP433","BbwgAogLgc","ZUnqt8xEKz","ulk41ix74r","pWiOsjtn0X",
-"d85a9VLTy6","zQt6QMm8si","8TxD7zFgtB","64s8NZ4I1v","okgRiMkgy8","ksJbyfmIK1","8hJdtk85Ae","aez9yNhXdu","SmGzvM3zXL","uN6r3SWfou",
-"ni2v1C2Irc","PYBf40Wr5y","0MR5XKASQ8","6q6L9ZuDtD","SmGzvCfgr3","CqqaDuTacx","ZuDtDUl4a1","zHF1q55rfB","yvOMIGv3Fq","ni2v1WmadA",
-"O3iyQQWxoT","In3NSYOfrY","v2eC3MezSW","0MR5X0Wr5y","6AFT05Mg9r","lj07QtaOXK","U3yw53weIF","s93MlDG4sT","s93MlyToGW","Ss0ZuWPmlx",
-"AmdQdHP433","NcICAmz8gx","DQimpWaWsv","GSQwjWaWsv","HRxd8uAWyp","GWqqX8FmFH","DcpWB2ZHdk","Qworu2hEEU","d7vjMguMb8","lH1ktlsQGo",
-"nFqikGSQwj","oQ87rfmIK1","taOXKlXFOB","jSjS3HP433","AXpwE0h1b1","ksJby2DREs","StlDJ0ao3l","he9IA2hEEU","24ARF3weIF","WDVWJuPX7G",
-"uZPqgdjsrv","YOfrYRACuj","0BmCy5drc6","P6bcgSmGzv","kZANmtvdkD","qaofNgtCA5","LewvMRmDcr","IRh48a00b5","OUYuFn1pmO","hE1Qlaez9y",
-"QworusuY4x","K4GS85IhmG","2TRI7OHaBz","Q6hMCIn3NS","2ZHdksuY4x","pAhR1pFrrl","9eoRc7fsYM","MezSWaFFss","Chuy30Wr5y","4QMc9OUqFM",
-"TCgPpuN6r3","C2Irc45cIH","fcJOyWDVWJ","ECMvUydG8U","7ku1p7X3uy","RkQke6AFT0","yToGWtlILt","lm0pDSjskQ","taOXKnlaBy","cQOnv7Ow5C",
-"yofH3oGu6x","pAhR1iwzGk","Vprf2lsQGo","QClRLlkMUA","1LB1LFcWrW","CxVEfWDVWJ","i3pydfaHir","M6qcGsqVrf","iqv4kRpBQm","yvOMILbRTH",
-"AXpwEHlUbF","G1RhSGWqqX","9eoRc1v5hH","ix74rCqqaD","Nxx9VSmGzv","EoToPW7cTs","gtCA52Yz7E","vOqCEPYBf4","5ZaEzuoStw","2TRI7618Di",
-"uZPqgjzUqR","yToGWazIWp","0BmCygf8rI","B3qemDG4sT","t98iW7fKYU","Pb1pa29QAz","ZzJHWxciqp","RsQUq3weIF","he9IAKZamH","cL0aENhXdu",
-"1j5L8CdyBV","8cVD39eoRc","7fsYMQworu","TCgPpyToGW","WmadAtl72W","JJs5mwDajX","RkQke3otm6","1v5hHSWfou","mz8gxh1zcH","FVMxo7ku1p",
-"8xEKzo8Uyd","uZPqghUTw7","BbwgAgf8rI","lViBvd7vjM","vkCHH8cVD3","Ss0ZuG1RhS","brhlQzFgtB","DcpWBjzUqR","8RCUAuQIcz","QChxskZANm",
-"45cIHQClRL","he9IAJIqXi","Ul4a1aL6AJ","piJSkMmsIo","B3qemUvlv4","kB5nPJIqXi","W3VFHP6bcg","uQIczTXQ0Z","P6bcgblLA9","CxVEfksJby",
-"1j5L8S77LH","fcwDav2eC3","dmoS7d85a9","pWiOsuJScX","lj07QLDk6f","uvf7AOUYuF","S2DfuhE1Ql","Cp3mZpvgjS","QbxXcbgJAz","8cVD3iwzGk",
-"No0QbX6Pin","UmaEvDz1R3","lsQGotAOsr","ru4UGKZamH","tuDySUvlv4","O3iyQ0BmCy","qQxHPhSSvQ","KASQ87X3uy","EOE1oFhtgl","wiHrZ618Di",
-"aDGtSWaWsv","v1HlngtCA5","blLA95VZjS","7fKYUaFFss","lsQGoRpBQm","VjCZqqQxHP","B3qem0h1b1","In3NSVBjhz","Ul4a1RACuj","IBe8kru4UG",
-"ksJby5drc6","F6PT2uupzk","wDajXcmXIX","W7cTs6q6L9","v2eC3xciqp","EoToPZ4I1v","LDk6fsuY4x","K20wKW7cTs","o8Uydsx5Gl","F6PT2uvf7A",
-"Gv3FqfcJOy","0Wr5yTa8f6","d7vjMWMiS3","DcpWBsuY4x","Nxx9VZUnqt","In3NSXflUq","K20wKiKqhr","4QMc9FxX9q","VBjhzCxVEf","v8yFNxReec",
-"ru4UGlpF6W","In3NSOz8yZ","pvgjSVBjhz","yofH3i3pyd","Vprf2uLtKs","BbwgA1v5hH","uLtKsYf2Ec","BCxeCksJby","S2Dfut98iW","faHirgtCA5",
-"n1pmO5ZaEz","DG4sTxciqp","lm0pD9XyT9","LewvMtjQxs","euZA5UlU3M","iKqhrK20wK","0PktIv2eC3","nnP8oqQxHP","Cfgr3x3LDe","8xEKzOz8yZ",
-"JkzUnHRxd8","lpF6Whe9IA","3otm6o8Uyd","29QAz14FLR","QYxC0D6rBy","lm0pDfqypy","DG4sTGXdoH","blLA95Drn0","2ZHdkeuZA5","ZzJHWfcwDa",
-"0h1b1suY4x","0MR5XFhtgl","wDajXMm8si","8hJdtK20wK","VerEAWaWsv","gtCA5EdBKc","VerEAFLsph","aL6AJ0YAGH","suY4xMaJQs","CdyBVFjHXR",
-"Z4I1vzHF1q","taOXKCdyBV","wDajXAkKTk","WMiS3KZamH","rhl0JxXTI4","QWxoT1LB1L","d7vjMYh1hF","xXTI4UmaEv","ni2v1t59lR","piJSkn8pJ9",
-"blLA9hUTw7","X6PinDQimp","FVMxoWaim6","nnP8oyluBx","IBe8k4W0Tl","hE1QlWaim6","oVQp6SmGzv","QnJ1SKASQ8","2NslmNOHsz","lsQGoGXdoH",
-"AIYUufFDrJ","618DikZANm","n8pJ9LDk6f","yvOMIfLNg8","NcICAv8yFN","Ss0ZuYw2oU","zmLYDokgRi","8xEKzyEfy9","jtn0X5drc6","b29RJuAWyp",
-"UmaEvWDVWJ","In3NSrz7Ut","SjskQuJScX","GWqqX7fKYU","qQxHPlweGy","m4bxUWaWsv","RmDcrni2v1","0KyfsNAFuw","JXljWAkKTk","Mm8sii7WMQ",
-"cmXIXZv7z0","No0QbEoToP","LewvM8TxD7","QWxoTgjUTu","Q6hMCQssNC","Ta8f6StlDJ","HRxd8CdyBV","W7cTsTwano","HRxd8tjQxs","uQIcz9GXkX",
-"blLA9HzZT8","MojnPYOfrY","StlDJ7fsYM","OUYuF0MR5X","lm0pDJ2mQi","8TxD7MGlTF","iqv4kDcpWB","lpF6WgtCA5","euZA5gtCA5","VjCZq8hJdt",
-"bgJAzMGlTF","5VZjSLewvM","dhSuHQbxXc","dmoS729QAz","iqv4kF6PT2","Yf2EcjS1aj","lXFOBRsQUq","Pb1paAXpwE","o8Uyd48cHL","IKxdLsx5Gl",
-"CK5W74W0Tl","GWqqXM3zXL","2DREsyofH3","FNYIMuJScX","aDGtSqQxHP","lkMUAv8yFN","HP433dhSuH","AXpwEix74r","zY1GY580YD","DG4sTIn3NS",
-"IBe8k9y4lw","he9IASbRYy","EOE1oulk41","fmIK14QMc9","rKDLJpmeCd","he9IANo0Qb","RBhp0wDajX","djsrvFPfSE","0BmCyJKWYR","b29RJQYxC0",
-"aez9ygf8rI","CK5W7JIqXi","VjCZqFGzgp","WDVWJtaOXK","2TRI7K4GS8","e6e4zOUqFM","Yw2oUrKDLJ","nFqikzbIYY","jSjS3ciuWz","2Nslm5Mg9r",
-"Cp3mZm4bxU","5iGN5Cp3mZ","M3zXLbgJAz","lj07Qatef2","4QMc9IKxdL","guMb8wDajX","lH1ktaFFss","YOfrY0Kyfs","xciqpuPX7G","Mkgy8brhlQ",
-"FcWrWm4bxU","gjUTuv1Hln","ZzJHWbZLvS","pFrrlZ4I1v","atef2lpF6W","KASQ8Waim6","v8yFNEOE1o","lXFOBWmadA","ZhwG1FNYIM","4W0TluTacx",
-"9XyT9WreyP","8RCUASbRYy","CxVEfHfyNQ","FGzgp2Yz7E","aL6AJulk41","fcJOylweGy","Ss0ZulH1kt","JIqXiFcWrW","i3pydS77LH","Mm8si5nmWv",
-"5VZjSpT8wu","OxWIHGv3Fq","FFDui5ZaEz","5IhmGjfREu","3weIF0ao3l","RpBQmtuDyS","OUYuFCfgr3","24ARFWmadA","EdBKcAkKTk","dmoS7ZuDtD",
-"0BmCypv0i7","ksJby6AFT0","soy9tt59lR","WreyPAgJHQ","FFDuiYh1hF","9XyT9djsrv","mX2GEUl4a1","2ZHdkiB08l","M6qcGFPfSE","RkQkeM3zXL",
-"wDajXKsjRK","AXpwEFcWrW","QbxXcqQxHP","No0QbAXpwE","9XyT9uJScX","QnJ1S6q6L9","ciuWz0YAGH","UlU3MBbwgA","2Yz7EU3yw5","5ZaEzMojnP",
-"ECMvU5ZaEz","TwanoEOE1o","2hEEUQworu","DQimphe9IA","JJs5m8TxD7","EoToP2Yz7E","s4786hE1Ql","JJs5mIKxdL","cL0aE4W0Tl","FGzgpm4bxU",
-"vOqCEMmKGJ","QbxXcFcWrW","BbwgACfgr3","vkCHHQClRL","taOXK2Yz7E","ZuDtD4QMc9","9y4lwrz7Ut","Waim65Mg9r","xciqpGSQwj","OxWIHx3LDe",
-"1j5L8FxX9q","okgRiv1Hln","FNYIMo8Uyd","QssNCVNCPd","5Mg9rqQxHP","m4bxUDG4sT","55rfBn8pJ9","XflUqM3zXL","O3iyQL7cGc","S2DfuprNT6",
-"cShY2uN6r3","uupzkZuDtD","MGlTF0h1b1","0PktITwano","8U2nUHlUbF","jtn0XsqVrf","G1RhSOxWIH","S2Dfuhi5X7","iB08lQWxoT","0BmCyjiVBP",
-"JJs5m5Namm","4W0Tlaez9y","yofH3HRxd8","hi5X7k85Ae","zmLYDWreyP","JXljWCxVEf","8xEKzF6PT2","2hEEUMaJQs","X6PinoQ87r","iwzGkNxx9V",
-"zQt6QJKWYR","wiHrZ0Wr5y","FNYIMGrDg7","QssNCWMiS3","C2IrcOHaBz","rKDLJ8cVD3","i3pydeuZA5","nnP8oaDGtS","AgJHQlkMUA","lXFOBhi5X7",
-"fmIK1ZhwG1","ZuDtDvOqCE","CqqaD5Mg9r","xXTI4t98iW","fFDrJYf2Ec","xciqpbrhlQ","iKqhrtvdkD","azIWp4dEz6","ZzJHW3otm6","24ARFVprf2",
-"0KyfsprNT6","pAhR1FxX9q","aez9yQYxC0","y94nw9eoRc","Cp3mZChuy3","jeskSMmsIo","LDk6fL7cGc","NcICAuZPqg","jiVBPKsjRK","QWxoTlsQGo",
-"zbIYYRACuj","L7cGcn1pmO","lXFOBGSQwj","UlU3MZhwG1","UmaEv3otm6","9XyT9fcwDa","L7cGcl83Ud","azIWpd7vjM","3weIFJKWYR","JIqXiv2eC3",
-"Q6hMCdhSuH","5Drn0FxX9q","cQOnvlViBv","pWiOs1j5L8","HzZT8jSjS3","AOgEeQYxC0","FPfSEPYBf4","iKqhryofH3","ydG8UWreyP","blLA9QWxoT",
-"FhtglVIlwP","bZLvS580YD","MmKGJcmXIX","uN6r3b29RJ","5iGN57lUXZ","8hJdt8xEKz","bgJAzzmLYD","K20wK2hEEU","MmKGJFnPFB","iqv4kulk41",
-"48cHL0MR5X","C2IrcUl4a1","pT8wuZ4I1v","1j5L8oVQp6","GXdoHVjCZq","FFDuiKsjRK","he9IAo8Uyd","HP433IKxdL","Dz1R3tlILt","IBe8kYh1hF",
-"TwanoNo0Qb","DQimpU3yw5","tAOsr0MR5X","d7vjM2ZHdk","GXdoHYOfrY","CIShGVBjhz","Uvlv4aez9y","NOHszaDGtS","s4786x3LDe","G1RhSZhwG1",
-"NcICAjiVBP","1v5hHQbxXc","EOE1o0BmCy","FnPFByluBx","TwanoeuZA5","FFDui9GXkX","2NslmxReec","QbxXc1j5L8","oVQp6OUqFM","t98iWlm0pD",
-"Yh1hFpiJSk","zY1GY9rlg9","8hJdtXyPZN","5Drn0s4786","kZANm3otm6","TCgPpv8yFN","5VZjSVLTy6","euZA5MmsIo","QworuvkCHH","BbwgA9y4lw",
-"EOE1oFnPFB","LewvMDz1R3","B3qemb29RJ","fFDrJWaWsv","7Ow5Cuupzk","AmdQddhSuH","pv0i7v1Hln","2TRI7MK07Y","J2mQiy94nw","Twanoiqv4k",
-"8U2nU1j5L8","ksJbyU3yw5","O3iyQ6AFT0","blLA93otm6","BbwgA0ao3l","y94nwVjCZq","tvdkDMm8si","FjHXRyEfy9","rz7UtHlUbF","hYBCKgf8rI",
-"tvdkDNxx9V","oVQp65Drn0","prNT62DREs","nnP8oU3yw5","IjTwP7Ow5C","C2Irct98iW","Vprf2D6rBy","FwEJz5IhmG","FGzgp5ZaEz","t98iWM6qcG",
-"h1zcHAXpwE","C2IrcVjCZq","zHF1q3weIF","SWfouOUqFM","QbxXcFNYIM","d85a99y4lw","vLsmSWmadA","uJScXlViBv","yofH3lXFOB","6q6L9M3zXL",
-"VjCZq9y4lw","UmaEvW3VFH","9iGoTulk41","piJSkECMvU","zbIYYkZANm","HlUbF9y4lw","K4GS82Yz7E","uZPqghi5X7","hUTw7guMb8","J2mQizbIYY",
-"U3yw5d7vjM","3weIFL7cGc","JIqXiwiHrZ","ulk41lCMxy","FPfSEaL6AJ","48cHLU3yw5","580YDd85a9","5Mg9rCp3mZ","ThjNnMaJQs","oQ87rDLhzM",
-"qQxHPWaWsv","29QAzwDajX","QYxC0KsjRK","S2Dfus93Ml","L7cGc618Di","NAFuwHRxd8","0KyfstvdkD","8U2nUlCMxy","yvOMI1v5hH","QClRLCdyBV",
-"I7p2acShY2","AXpwEaDGtS","8cVD3FcWrW","RzaZAVerEA","HRxd8FVMxo","Q6hMCpv0i7","XflUqix74r","pv0i7k85Ae","oQ87rL7cGc","Cfgr3mX2GE",
-"xciqpZJTXH","vLsmSzY1GY","Qworufqypy","MezSWQ6hMC","0h1b1CxVEf","TCgPpLewvM","P6bcgSbRYy","BbwgAzmLYD","zz4ZUgjUTu","ksJbylCMxy",
-"ZuDtDDcpWB","jS1aj3weIF","Q6LixFLsph","t98iWTa8f6","16lHcRmDcr","euZA5LbRTH","hE1QlkB5nP","TwanoVIlwP","HzZT8Ss0Zu","RACujZUnqt",
-"DLhzMqUJMd","gjUTuZ4I1v","jeskSpvgjS","K20wKqaofN","VLTy6cL0aE","sqVrf07n1c","k85AefLNg8","ZzJHWuAWyp","8hJdtZJTXH","ThjNnrz7Ut",
-"TXQ0Zv8yFN","Dz1R3XyPZN","8hJdtZzJHW","pv0i7lweGy","AgJHQTa8f6","uN6r30h1b1","QChxsBFkb8","xReecRACuj","VLTy6QYxC0","OUqFM07n1c",
-"JJs5mni2v1","iKqhrGSQwj","AXpwEv8yFN","B3qemguMb8","Dz1R3BbwgA","RkQke16lHc","IKxdLgdQsS","SWfou7X3uy","MezSWjS1aj","QClRLciuWz",
-"ZJTXHdhSuH","HzZT8qQxHP","8hJdtY1mC0","WmadAYf2Ec","hi5X7M6qcG","HlUbFkB5nP","suY4xoVQp6","JXljWRzaZA","5VZjSOxWIH","ZJTXHtl72W",
-"580YDFGzgp","he9IAKsjRK","vLsmSChuy3","ZJTXH4W0Tl","lCMxyMezSW","8U2nUTCgPp","iKqhrrhl0J","OxWIHNhXdu","K20wKB3qem","pmeCd7lUXZ",
-"hE1QlxXTI4","uQIczZhwG1","Mm8sitaOXK","iqv4kfFDrJ","0Wr5y1j5L8","QChxsjS1aj","AkKTkVBjhz","QbxXc64s8N","e6e4zF6PT2","8RCUAuZPqg",
-"yluBxEdBKc","soy9tHfyNQ","uvf7ApvgjS","iB08l9GXkX","djsrvdQ586","lj07QQworu","4dEz65VZjS","29QAz7fKYU","JKWYR8TxD7","IRh48uLtKs",
-"euZA5EdBKc","dhSuHEOE1o","ogLgc1v5hH","48cHLuN6r3","RBhp0o8Uyd","FVMxotuDyS","8cVD3W7cTs","cmXIXFVMxo","qQxHPCIShG","Q6hMClsQGo",
-"2hEEUiqv4k","zbIYY24ARF","uupzkDz1R3","jeskSMaJQs","hSSvQcQOnv","ogLgcb29RJ","azIWpjzUqR","JIqXiRpBQm","RmDcrfcJOy","lpF6WlkMUA",
-"n8pJ945cIH","vLsmSIBe8k","VBjhz0BmCy","rhl0JRsQUq","uupzkCxVEf","QworuCNHmv","k85AeMmKGJ","SWfouJKWYR","Y1mC0AIYUu","lViBvLDk6f",
-"7Ow5CjeskS","5iGN5xReec","7ku1pdjsrv","aL6AJCK5W7","AmdQd8xEKz","2ZHdkNo0Qb","fcwDataOXK","qUJMdOz8yZ","fmIK1zbIYY","zFgtB2Nslm",
-"5ZaEzB3qem","WMiS3QYxC0","RpBQm0ao3l","Yw2oUru4UG","uvf7AazIWp","FcWrWlsQGo","1v5hH2DREs","n1pmOpmeCd","vOqCEFjHXR","RmDcrQChxs",
-"RpBQmatef2","JXljWIRh48","x3LDe8RCUA","yluBxfcJOy","zbIYYcShY2","WmadAiKqhr","7hyVvRmDcr","Oz8yZt59lR","kB5nPQ6Lix","mz8gx55rfB",
-"ydG8UEdBKc","lViBvpWiOs","lj07Qaez9y","tuDySO3iyQ","16lHc3weIF","Q6Lixm4bxU","jzUqRokgRi","pvgjSPYBf4","oQ87rMK07Y","gf8rI4dEz6",
-"m4bxUYh1hF","RBhp0fcJOy","8TxD7h1zcH","RmDcruZPqg","1LB1L1j5L8","jzUqRHRxd8","d7vjMi3pyd","DG4sTAOgEe","LewvMC2Irc","uLtKspv0i7",
-"Zv7z0fmIK1","M3zXLh1zcH","6q6L9WmadA","uTacxFwEJz","jzUqR7hyVv","FhtgluLtKs","3weIF2Nslm","nFqikRsQUq","QssNCt98iW","nnP8ojzUqR",
-"QnJ1S7fsYM","CqqaDuQIcz","suY4xciuWz","nlaByCK5W7","29QAzxciqp","l83UdRmDcr","UmaEvBCxeC","mz8gxCNHmv","cmXIXpFrrl","HzZT8pvgjS",
-"jiVBP5iGN5","gjUTuogLgc","AgJHQAOgEe","SbRYyPYBf4","pWiOszz4ZU","8xEKzQClRL","RACujtjQxs","x3LDeatef2","wDajXCdyBV","HRxd87fsYM",
-"Ss0ZuGv3Fq","MGlTFQ6Lix","zQt6QAIYUu","xciqpuLtKs","In3NS8TxD7","e6e4zFwEJz","Z4I1vt98iW","EoToPsqVrf","n1pmOUmaEv","0KyfsPYBf4",
-"FPfSEni2v1","GXdoHv1Hln","ksJby3otm6","XyPZNQ6hMC","7fKYUv8yFN","dmoS7sx5Gl","X6PineuZA5","U3yw5Q6Lix","FGzgp1v5hH","0Kyfs8hJdt",
-"W7cTsNxx9V","he9IAuoStw","Gv3Fq2ZHdk","ReKEWcL0aE","gf8rIgIYvE","uoStwLDk6f","NOHsz0ao3l","ZJTXHogLgc","Nxx9VLDk6f","lCMxydjsrv",
-"BCxeCfLNg8","ogLgcvkCHH","4QMc9wDajX","fLNg8djsrv","dpe1vSjskQ","ECMvUIKxdL","tvdkDlweGy","GXdoH2ZHdk","WPmlxy94nw","9iGoTcShY2",
-"LewvM07n1c","LbRTHhe9IA","1v5hHD6rBy","zbIYYaL6AJ","Chuy3XyPZN","nFqikJJs5m","gf8rIlViBv","uZPqghSSvQ","d85a95nmWv","WMiS3blLA9",
-"ECMvUl83Ud","BGaQYK4GS8","0YAGHrKDLJ","FLsphRsQUq","7Ow5CnnP8o","nlaBygf8rI","Dz1R3pWiOs","VjCZqVLTy6","9GXkXG1RhS","RBhp0Oz8yZ",
-"uoStwKASQ8","IKxdLzFgtB","piJSkrKDLJ","ZJTXHjSjS3","v1HlnCp3mZ","KASQ8AIYUu","FLsphMmsIo","guMb8uTacx","bgJAzX6Pin","ZJTXHzQt6Q",
-"uLtKsCIShG","Yw2oUUlU3M","tlILtd85a9","zz4ZUlm0pD","aez9ykZANm","cmXIXRACuj","Kr8yspvgjS","hE1QlJKWYR","pT8wuBCxeC","F6PT2ulk41",
-"lj07Qjtn0X","WmadA2TRI7","he9IAXflUq","0Wr5y0Kyfs","5Namm6AFT0","jtn0XyToGW","m4bxUe6e4z","Rxrsm7hyVv","i7WMQUvlv4","EoToPUvlv4",
-"4dEz6GSQwj","CxVEf7Ow5C","dmoS7soy9t","DcpWBpiJSk","lH1ktt98iW","Q6hMCDQimp","55rfBQWxoT","brhlQcQOnv","s4786DQimp","o8UydIRh48",
-"MmsIoQnJ1S","W7cTsFcWrW","pWiOshi5X7","LbRTHEoToP","B3qemnlaBy","8xEKz5VZjS","KASQ8n8pJ9","OHaBzChuy3","DQimpdmoS7","CdyBVIKxdL",
-"TXQ0ZlViBv","iqv4kChuy3","FhtgluAWyp","Yf2EcuZPqg","t59lRHRxd8","cL0aEe6e4z","P6bcgFNYIM","tjQxsWMiS3","lkMUA0Kyfs","Mkgy8Z4I1v",
-"tjQxs2ZHdk","7hyVvfqypy","64s8NMojnP","55rfBzFgtB","k85Ae0Kyfs","l83UdLbRTH","Pb1paPYBf4","Chuy3UmaEv","2Yz7EgjUTu","2Nslmv2eC3",
-"i7WMQa00b5","aL6AJHlUbF","MojnPWaim6","Fhtgluupzk","S77LHni2v1","9rlg98U2nU","cL0aEsqVrf","ZhwG1zFgtB","lm0pDFLsph","uN6r3618Di",
-"CxVEfzFgtB","EOE1o8FmFH","aL6AJhE1Ql","ni2v1Twano","Y1mC0bgJAz","SWfou2DREs","Yw2oUtlILt","iqv4k2TRI7","pmeCdt59lR","WaWsvKASQ8",
-"pFrrln8pJ9","StlDJThjNn","JkzUnprNT6","3weIFaL6AJ","bZLvSMmsIo","hSSvQbZLvS","K4GS8fcwDa","RmDcrJ2mQi","7X3uy07n1c","WreyP5Namm",
-"cmXIXgf8rI","Yf2EcWPmlx","dhSuHvLsmS","2NslmkB5nP","FjHXR2Yz7E","FGzgphE1Ql","5VZjSkB5nP","mX2GEQYxC0","OxWIHJ2mQi","9iGoTO3iyQ",
-"Mm8sil83Ud","MaJQsCdyBV","ZzJHW0Wr5y","2Yz7EY1mC0","TwanoFGzgp","iB08l7ku1p","tAOsrCdyBV","FFDuiFjHXR","Q6LixUlU3M","bgJAz0Kyfs",
-"WreyPlkMUA","uvf7AL7cGc","2hEEUHzZT8","KZamHReKEW","1j5L8uQIcz","Uvlv4Yh1hF","AmdQdJIqXi","gdQsSUmaEv","Nxx9V8FmFH","7hyVv24ARF",
-"9XyT9Yw2oU","atef2sx5Gl","8cVD3BCxeC","RACujJKWYR","prNT6pvgjS","0MR5XDG4sT","k85AeQ6hMC","2TRI7G1RhS","m4bxUUl4a1","iwzGkcmXIX",
-"O3iyQfcwDa","pAhR1Cp3mZ","hUTw7dhSuH","zbIYYcmXIX","iwzGkUmaEv","piJSkuQIcz","uLtKsLDk6f","EOE1oYh1hF","fLNg8gjUTu","zbIYYKr8ys",
-"lm0pD2Nslm","RsQUqZUnqt","8TxD72Nslm","aFFsszbIYY","W3VFHpT8wu","faHirThjNn","wiHrZGSQwj","1j5L8aL6AJ","gdQsSWMiS3","cL0aEoQ87r",
-"qQxHPWMiS3","VLTy6n8pJ9","QClRL7fsYM","BGaQYJJs5m","tl72WVLTy6","lH1ktbgJAz","EdBKcRmDcr","YjB9the9IA","QWxoTh1zcH","SjskQ1LB1L",
-"prNT6h1zcH","4dEz6pT8wu","djsrvpWiOs","zqH0W14FLR","hi5X7i3pyd","mX2GE2ZHdk","CdyBViB08l","8TxD7Qworu","jSjS3faHir","QChxsG1RhS",
-"AmdQdAkKTk","8TxD7tjQxs","XyPZN45cIH","lj07Qa00b5","CIShG5iGN5","qQxHPyluBx","5VZjS7X3uy","v2eC3580YD","QYxC0uN6r3","bgJAz8FmFH",
-"QworuPYBf4","uZPqgCqqaD","Pb1pahi5X7","yluBx24ARF","iqv4kQYxC0","K20wKtjQxs","t59lRXflUq","Dz1R3zHF1q","0PktIPOUYS","FcWrWRmDcr",
-"0YAGHydG8U","zFgtBtAOsr","WMiS3RsQUq","AgJHQZUnqt","8FmFHCNHmv","JXljWUvlv4","hYBCKZzJHW","AOgEeazIWp","l83UdbgJAz","rKDLJ1LB1L",
-"aFFssG1RhS","0KyfsVerEA","45cIHMmKGJ","OxWIH4dEz6","suY4xVBjhz","IKxdLix74r","suY4xsuY4x","JJs5m9XyT9","oQ87rBbwgA","SWfounlaBy",
-"yvOMIBGaQY","qaofNFNYIM","nlaByD6rBy","5iGN5Qworu","zmLYDqaofN","OUYuFuJScX","i3pydPb1pa","7Ow5C3weIF","iB08ldjsrv","suY4xKZamH",
-"Oz8yZ7fKYU","gf8rI5drc6","d7vjMJJs5m","UmaEvzbIYY","NcICAWDVWJ","2Nslm8cVD3","QworuD6rBy","MaJQsK20wK","0YAGHzmLYD","6q6L9CdyBV",
-"lXFOBe6e4z","0h1b1580YD","9rlg9yvOMI","5Mg9rxReec","xXTI4hi5X7","YOfrYFNYIM","iwzGkn8pJ9","uN6r3K4GS8","uN6r3G1RhS","tAOsr3otm6",
-"8U2nUSs0Zu","zY1GY9XyT9","F6PT2Ta8f6","VerEAlViBv","aL6AJzz4ZU","IRh48Vprf2","uZPqgn8pJ9","9iGoTlH1kt","ZuDtDVprf2","K20wKP6bcg",
-"Ta8f6uQIcz","FLsphSWfou","iwzGkydG8U","HP4335ZaEz","1v5hHVBjhz","suY4x8hJdt","TCgPpjiVBP","6AFT0Yh1hF","kB5nPpvgjS","DQimpn1pmO",
-"SmGzvoGu6x","rhl0JMmKGJ","ZJTXHru4UG","ulk41zY1GY","dhSuHjtn0X","Ta8f6AmdQd","GWqqXEoToP","x3LDe0ao3l","FxX9q64s8N","5nmWv0Wr5y",
-"2DREsfcwDa","O3iyQHP433","VLTy6ZuDtD","Q6hMCgf8rI","Yf2Ecx3LDe","gtCA5KASQ8","14FLRlj07Q","Y1mC0MK07Y","jfREuWDVWJ","i7WMQAXpwE",
-"uAWypuJScX","kZANmh1zcH","NOHszS77LH","Ul4a1JRJQB","Vprf29GXkX","pFrrlRxrsm","FcWrWTa8f6","y94nwpiJSk","gdQsSKr8ys","M6qcGpv0i7",
-"cQOnvogLgc","RACujWaim6","t59lRNo0Qb","SmGzvyofH3","lpF6WtjQxs","zmLYDsqVrf","2TRI7uPX7G","YjB9tVprf2","9rlg9X6Pin","POUYSM3zXL",
-"sx5Glhi5X7","oQ87rTa8f6","gdQsSYh1hF","lXFOBlH1kt","W3VFHFVMxo","8TxD7Fhtgl","Mm8siJKWYR","uN6r3DG4sT","OUqFM5VZjS","pmeCd5Drn0",
-"Yh1hFlj07Q","bgJAz9iGoT","QworuJJs5m","brhlQhi5X7","FnPFBqaofN","1j5L8he9IA","okgRidhSuH","FLsph45cIH","JRJQBjS1aj","zY1GY0h1b1",
-"s7MxkaL6AJ","v1HlnpT8wu","fcJOyRxrsm","14FLRK4GS8","FPfSEdjsrv","jiVBP8xEKz","yluBxZuDtD","5drc629QAz","jfREuFjHXR","WreyP2Yz7E",
-"2Yz7EOUYuF","DcpWBhUTw7","FLsphblLA9","taOXKv2eC3","Cfgr3ciuWz","iB08lI7p2a","5nmWvCNHmv","Uvlv4tvdkD","iB08lyEfy9","7hyVvW7cTs",
-"4W0TltaOXK","pv0i7e6e4z","Yf2EcQYxC0","SmGzvk85Ae","uvf7ABpYhV","GXdoHBbwgA","5IhmGWreyP","uLtKs0Wr5y","jS1ajdpe1v","Q6hMCydG8U",
-"uZPqgUl4a1","iKqhrMGlTF","k85Ae6q6L9","prNT6Waim6","CxVEfFwEJz","DQimpPYBf4","WPmlxfmIK1","RzaZAFjHXR","jSjS3ThjNn","GSQwjCqqaD",
-"TwanoO3iyQ","hYBCK4dEz6","RACujtaOXK","rhl0JDz1R3","VBjhzvOqCE","NcICAjtn0X","soy9toVQp6","L7cGcIBe8k","atef2WaWsv","vkCHHpFrrl",
-"ZhwG1WMiS3","s7Mxk5iGN5","JIqXiVIlwP","ksJbyFnPFB","45cIHWMiS3","RBhp0jtn0X","okgRitjQxs","FcWrWuAWyp","AmdQdh1zcH","7X3uyS2Dfu",
-"fFDrJiKqhr","iqv4k5IhmG","iwzGk0BmCy","U3yw5hi5X7","JRJQB9eoRc","tlILtd7vjM","Cp3mZ2TRI7","jzUqR6q6L9","dQ586x3LDe","uupzkfcJOy",
-"pWiOs0ao3l","VLTy6LewvM","W3VFH0YAGH","BGaQYt59lR","TCgPplXFOB","kZANmtaOXK","tuDySD6rBy","y94nwThjNn","8hJdtQClRL","zHF1q9iGoT",
-"8xEKz6AFT0","fFDrJMm8si","QbxXcatef2","D6rByoQ87r","cmXIXi3pyd","cShY2dpe1v","uoStwvOqCE","iB08ljtn0X","PYBf4AIYUu","FPfSEdmoS7",
-"GXdoHfLNg8","ZuDtDFhtgl","JIqXiuTacx","MK07YvLsmS","atef2iKqhr","kZANmSWfou","1v5hHDz1R3","SmGzv48cHL","2TRI7x3LDe","oVQp6uZPqg",
-"aDGtSZ4I1v","uN6r3YjB9t","MaJQstjQxs","5Drn07fKYU","ciuWzRBhp0","ZhwG1YOfrY","4W0TlGWqqX","atef2QnJ1S","hSSvQ3otm6","l83UdsuY4x",
-"RzaZAS2Dfu","VLTy63weIF","b29RJX6Pin","gjUTu2DREs","FVMxomX2GE","oQ87rHlUbF","8hJdt6AFT0","NOHszy94nw","0h1b1lm0pD","y94nwTa8f6",
-"RsQUqNcICA","Vprf2W3VFH","YOfrYtjQxs","ZhwG1GXdoH","JJs5mVIlwP","5VZjSL7cGc","fFDrJTwano","SmGzv0BmCy","uupzkNhXdu","ZUnqtcL0aE",
-"xciqpKASQ8","QChxsv1Hln","lj07QeuZA5","lViBv2TRI7","JIqXiC2Irc","ix74rk85Ae","6q6L9HlUbF","2NslmaL6AJ","2hEEUzz4ZU","Waim6RzaZA",
-"WaWsvsoy9t","EdBKcfcJOy","W7cTsrz7Ut","JkzUnRmDcr","ReKEWqaofN","Zv7z0KASQ8","euZA5okgRi","9iGoTJIqXi","n8pJ9XyPZN","FGzgp5IhmG",
-"FPfSERzaZA","uupzkVprf2","zQt6QprNT6","JKWYRMm8si","nnP8oxReec","55rfB2Nslm","pv0i70Kyfs","RpBQmn8pJ9","lm0pDprNT6","48cHLfcwDa",
-"StlDJO3iyQ","FFDuiSs0Zu","KZamHRsQUq","NhXduNo0Qb","FPfSELDk6f","ThjNn618Di","tlILt7ku1p","FnPFBcmXIX","Zv7z0zmLYD","jiVBPlpF6W",
-"bZLvSFVMxo","I7p2ablLA9","lpF6WAgJHQ","2hEEU618Di","ZhwG18U2nU","jiVBPAIYUu","qaofN7Ow5C","nFqik0MR5X","lweGyoGu6x","lViBvgdQsS",
-"8xEKzWmadA","UmaEvmX2GE","MK07Y0PktI","i3pydL7cGc","b29RJWmadA","fcJOycShY2","5Mg9rjSjS3","KsjRKs4786","i3pydUvlv4","pvgjSQChxs",
-"64s8N4W0Tl","MK07YGXdoH","FxX9qFLsph","ReKEWiB08l","uZPqg580YD","fcJOyn1pmO","Zv7z0dhSuH","yEfy9e6e4z","zmLYDZJTXH","fcJOyk85Ae",
-"RxrsmfmIK1","cShY2HzZT8","QworuDcpWB","LewvMRBhp0","lCMxybZLvS","uvf7AiwzGk","lm0pDuoStw","blLA99y4lw","HfyNQv8yFN","v2eC3FNYIM",
-"WMiS3JJs5m","qaofN8RCUA","DLhzMAXpwE","e6e4zUlU3M","atef2aFFss","iqv4kZUnqt","jzUqRb29RJ","IBe8kzqH0W","ZuDtDTa8f6","RkQkeThjNn",
-"jSjS32hEEU","HlUbFFwEJz","i3pydTXQ0Z","IjTwPbrhlQ","uZPqgHzZT8","yToGWFFDui","lm0pDMm8si","2DREsiqv4k","F6PT27X3uy","i3pyd48cHL",
-"0MR5Xt98iW","IKxdL5IhmG","vkCHHvkCHH","AIYUuXyPZN","pAhR1YOfrY","0ao3lfFDrJ","Q6LixAkKTk","OHaBz6q6L9","lH1ktnnP8o","he9IA0PktI",
-"XyPZNOxWIH","aFFssO3iyQ","C2Irc0Kyfs","8hJdtazIWp","OxWIHMkgy8","14FLRtjQxs","Cp3mZfcJOy","iB08lFNYIM","BCxeCjzUqR","sx5GlBFkb8",
-"5IhmGt59lR","9XyT9Q6hMC","Uvlv4M6qcG","yvOMIJXljW","2NslmFhtgl","uZPqgiwzGk","AkKTkJIqXi","b29RJgjUTu","b29RJGSQwj","OxWIHZv7z0",
-"RsQUqciuWz","i7WMQYf2Ec","uPX7GyvOMI","QWxoTTXQ0Z","ThjNnKr8ys","MaJQsaL6AJ","jiVBPFxX9q","jzUqRqaofN","lweGywDajX","ogLgcatef2",
-"CK5W7cL0aE","4W0Tl07n1c","MojnPtvdkD","GrDg7nnP8o","b29RJ0PktI","WreyPhYBCK","9eoRcjzUqR","atef2U3yw5","J2mQiuZPqg","ThjNnUlU3M",
-"48cHLNo0Qb","DQimpJXljW","lsQGoXyPZN","ogLgcIKxdL","CxVEffLNg8","HzZT8AIYUu","uJScXMojnP","U3yw5F6PT2","PYBf4ru4UG","dQ586dhSuH",
-"ulk41i3pyd","VerEA3weIF","ZJTXHJJs5m","8RCUAStlDJ","Y1mC0FLsph","9eoRcFFDui","WaWsvFcWrW","VIlwPcL0aE","SmGzvWaWsv","UmaEvokgRi",
-"QbxXcy94nw","VjCZqtAOsr","wiHrZogLgc","CIShGQ6hMC","JXljWtuDyS","hi5X7xReec","580YDXyPZN","CxVEfdjsrv","DcpWBCK5W7","580YDSs0Zu",
-"LewvM9y4lw","jSjS3FFDui","FNYIM7Ow5C","i3pydoVQp6","Vprf2dpe1v","vLsmSRsQUq","uoStwoQ87r","9iGoT64s8N","K20wKuAWyp","tuDySpWiOs",
-"yofH37hyVv","HfyNQ4QMc9","WreyPMaJQs","NOHszrhl0J","Z4I1vl83Ud","CxVEf2DREs","Ss0ZuFFDui","nnP8oZJTXH","580YDtvdkD","16lHc7fsYM",
-"wiHrZGrDg7","wDajX3otm6","tl72WL7cGc","8RCUAVjCZq","jeskShi5X7","pmeCd2Yz7E","jeskS9GXkX","Dz1R3azIWp","Waim6YjB9t","a00b56AFT0",
-"DLhzMlsQGo","3weIFOxWIH","GSQwjMaJQs","QWxoTcmXIX","ZuDtDJRJQB","KASQ8nnP8o","MGlTF7ku1p","4W0TlAgJHQ","IjTwPuLtKs","cmXIXQ6Lix",
-"VjCZqCdyBV","suY4x5iGN5","WreyPyluBx","RBhp05Mg9r","lkMUAHP433","C2IrcW3VFH","AXpwElj07Q","FFDui0h1b1","vOqCEGv3Fq","e6e4zdmoS7",
-"BCxeCW3VFH","lweGyfcJOy","HlUbFNxx9V","FxX9qfqypy","zY1GYt59lR","HlUbFZJTXH","uvf7AOUqFM","djsrvcQOnv","rKDLJ0h1b1","hUTw7U3yw5",
-"0ao3lCdyBV","n1pmOCK5W7","ru4UGpvgjS","JXljWd85a9","7X3uy2hEEU","n8pJ9zY1GY","rz7UtazIWp","JRJQBWMiS3","DLhzMYh1hF","zQt6Qd85a9",
-"sx5GlsqVrf","CqqaDaDGtS","gIYvEIn3NS","lXFOBn1pmO","ulk41jSjS3","VerEAgjUTu","wDajXd85a9","RkQkeUvlv4","J2mQiYw2oU","euZA5iKqhr",
-"Kr8ysIRh48","zz4ZU0h1b1","7Ow5CDLhzM","pAhR1IKxdL","MojnP7lUXZ","Gv3FqUl4a1","IjTwPVBjhz","EOE1ogIYvE","ECMvUsqVrf","gtCA5wDajX",
-"oQ87rJJs5m","2ZHdk8TxD7","zz4ZUatef2","X6PinPOUYS","DLhzMa00b5","UmaEvn8pJ9","S2Dfuv1Hln","fmIK1faHir","C2IrcfmIK1","TCgPpfFDrJ",
-"fmIK1e6e4z","9XyT9zHF1q","9iGoTTXQ0Z","azIWphUTw7","djsrvaez9y","vkCHHGXdoH","v1HlnBCxeC","0ao3lHzZT8","NhXdu0MR5X","iqv4kMaJQs",
-"qQxHPLewvM","Q6LixWPmlx","FnPFBNAFuw","M6qcGd7vjM","cQOnv3weIF","IRh48uPX7G","nFqikZuDtD","VBjhzulk41","JkzUnzbIYY","jzUqRwiHrZ",
-"MojnPuoStw","8FmFHHlUbF","M3zXL9eoRc","No0QbaL6AJ","jS1ajFcWrW","RkQkeQClRL","ksJbywDajX","o8UydjfREu","FNYIMHRxd8","W3VFHru4UG",
-"aFFssMojnP","FGzgpMm8si","WDVWJRmDcr","9eoRcMojnP","KASQ8OUqFM","fFDrJydG8U","ix74riwzGk","No0QbSWfou","L7cGcI7p2a","0PktIGXdoH",
-"uAWypMojnP","oGu6xVerEA","X6PinZuDtD","aL6AJQssNC","tjQxsLewvM","FnPFBwiHrZ","9y4lwZJTXH","hSSvQF6PT2","64s8NgtCA5","Q6hMCnnP8o",
-"K4GS8kB5nP","0YAGH7fKYU","1v5hH14FLR","k85Aeru4UG","64s8N16lHc","4QMc9bgJAz","8FmFHZuDtD","618Dit98iW","3otm6JIqXi","QChxsL7cGc",
-"fmIK1zz4ZU","mX2GEAXpwE","M3zXLChuy3","J2mQi2Yz7E","VNCPdB3qem","Mm8siHlUbF","zmLYDCfgr3","7Ow5CuN6r3","2hEEUU3yw5","tlILtRsQUq",
-"uJScX14FLR","euZA5vOqCE","IKxdLZhwG1","uPX7GBbwgA","hSSvQZUnqt","Waim6NhXdu","5nmWvmX2GE","No0QbJIqXi","ECMvUgIYvE","CdyBVRmDcr",
-"FLsphRBhp0","NhXduMmKGJ","B3qemFwEJz","FjHXR0YAGH","RmDcrVNCPd","zmLYDazIWp","5drc6ThjNn","MaJQsGrDg7","0YAGHd7vjM","uPX7GKr8ys",
-"Ul4a15Namm","tl72W5iGN5","2DREsksJby","WMiS3FwEJz","jzUqRkB5nP","xReecB3qem","ZzJHWs7Mxk","CNHmv07n1c","29QAzhYBCK","iwzGkblLA9",
-"dQ586Y1mC0","5IhmGyEfy9","WaWsvChuy3","CqqaDTwano","Yh1hF7hyVv","s7MxkjfREu","RzaZAWDVWJ","NhXduO3iyQ","NcICA0ao3l","oGu6xuTacx",
-"0h1b10Wr5y","WDVWJyofH3","x3LDeQssNC","vOqCEv1Hln","yToGW0Wr5y","2NslmjfREu","9iGoTgIYvE","AIYUuuAWyp","ksJbyfqypy","iB08l3weIF",
-"RxrsmvOqCE","2NslmvOqCE","7fKYUokgRi","wDajXb29RJ","0Wr5yeuZA5","EOE1odjsrv","OHaBzru4UG","yEfy9qQxHP","ulk41fcwDa","pAhR1AgJHQ",
-"QworufLNg8","0h1b1EoToP","FFDuiatef2","m4bxUwDajX","fmIK1SbRYy","WmadATwano","yofH3JIqXi","SWfou45cIH","djsrvs4786","0KyfsW7cTs",
-"RmDcruupzk","7lUXZFFDui","OxWIHqUJMd","RkQket98iW","KZamHVprf2","SbRYyUl4a1","FwEJz0Kyfs","mz8gxCIShG","W3VFHVLTy6","6AFT0JIqXi",
-"DcpWBpFrrl","ECMvUXflUq","faHirZ4I1v","BCxeC618Di","RsQUq48cHL","RkQkesx5Gl","uoStw8TxD7","NOHsznFqik","U3yw5NhXdu","uQIczLDk6f",
-"WmadAtjQxs","lpF6WFcWrW","b29RJStlDJ","7X3uyqUJMd","HRxd8Oz8yZ","9iGoTdpe1v","UmaEvFhtgl","hE1Qlt98iW","brhlQOxWIH","uTacxk85Ae",
-"4dEz6uvf7A","EOE1otl72W","8FmFHI7p2a","QChxsNxx9V","MaJQs7Ow5C","AgJHQVNCPd","07n1cX6Pin","Zv7z0UmaEv","cQOnv7ku1p","2ZHdkuupzk",
-"HlUbFfFDrJ","VIlwPM3zXL","h1zcHHRxd8","Mkgy8t98iW","ZUnqtQnJ1S","Gv3FqU3yw5","QWxoTFxX9q","ThjNnsuY4x","mX2GE9rlg9","4QMc9DG4sT",
-"4W0TluN6r3","fmIK1iKqhr","ksJbypFrrl","Uvlv4blLA9","a00b5No0Qb","xReecpiJSk","IjTwPfaHir","s7MxkdQ586","J2mQipvgjS","W7cTsKr8ys",
-"tvdkDyofH3","QYxC0AkKTk","d85a9Cfgr3","yToGWFGzgp","B3qemAgJHQ","a00b5e6e4z","hYBCKGWqqX","0YAGHcQOnv","jS1ajatef2","2NslmCNHmv",
-"W3VFHFPfSE","DLhzMAmdQd","d7vjMMkgy8","7ku1pB3qem","ksJby7hyVv","Vprf2fFDrJ","he9IAW3VFH","OUYuFEdBKc","WPmlx0BmCy","QworuzmLYD",
-"tuDySHRxd8","2ZHdkogLgc","d7vjMVIlwP","blLA9uN6r3","S2Dfue6e4z","QYxC0pFrrl","aez9ylj07Q","uLtKs14FLR","t98iWgIYvE","Ul4a19XyT9",
-"jtn0Xrhl0J","CIShGJKWYR","jfREuQworu","pAhR1K4GS8","uJScXpAhR1","Gv3FqYh1hF","lsQGohe9IA","s7MxkM3zXL","0YAGHOxWIH","MmsIotvdkD",
-"aDGtSuvf7A","ECMvUpiJSk","FFDuiBFkb8","YjB9t24ARF","euZA50PktI","1LB1LX6Pin","0PktIvOqCE","QnJ1S0PktI","Chuy3cmXIX","5nmWvRkQke",
-"oQ87r8TxD7","QssNCuPX7G","1v5hH9iGoT","pFrrlyofH3","RmDcrDQimp","BGaQYMaJQs","euZA5wiHrZ","RxrsmYf2Ec","U3yw5s4786","X6PinoGu6x",
-"BbwgAFNYIM","1j5L8YOfrY","MGlTFTCgPp","VNCPdEOE1o","VBjhzAmdQd","S2DfujeskS","n8pJ9MGlTF","pWiOskZANm","BCxeCtvdkD","SjskQUl4a1",
-"Cp3mZrKDLJ","azIWpEoToP","fmIK1NcICA","0BmCylkMUA","jzUqRIBe8k","GSQwjFcWrW","7fsYMS2Dfu","RmDcrVjCZq","pvgjSjS1aj","Cfgr3NhXdu",
-"AkKTkiwzGk","GrDg7618Di","azIWpDG4sT","ydG8UydG8U","CK5W7U3yw5","I7p2afLNg8","sx5GlfaHir","Yw2oU45cIH","Z4I1vdmoS7","LbRTH2hEEU",
-"pT8wuwDajX","lCMxyuTacx","wDajXcQOnv","D6rByAXpwE","uLtKsatef2","RxrsmFFDui","uupzkHfyNQ","uJScX5nmWv","DLhzMuN6r3","EoToPhE1Ql",
-"n8pJ9uN6r3","In3NSdjsrv","n8pJ9djsrv","kB5nP2TRI7","yofH3uN6r3","YOfrYFnPFB","FNYIMWaim6","v2eC3suY4x","qUJMdWMiS3","MGlTFFNYIM",
-"GSQwjprNT6","OUqFMMm8si","zY1GYQnJ1S","gjUTuix74r","In3NSRzaZA","pmeCd2ZHdk","mz8gxaDGtS","OxWIHlViBv","l83Udo8Uyd","2TRI7guMb8",
-"XflUq2hEEU","2TRI72ZHdk","9rlg9okgRi","3weIFZhwG1","CdyBVcmXIX","euZA5No0Qb","RkQkeqUJMd","OHaBzvOqCE","qUJMdgf8rI","JRJQBHP433",
-"OxWIHtaOXK","FNYIM1j5L8","RzaZAIn3NS","tl72WhE1Ql","pmeCdpT8wu","YjB9tzmLYD","aDGtS29QAz","24ARF7X3uy","NhXduwiHrZ","hSSvQDG4sT",
-"uPX7GaDGtS","Oz8yZhE1Ql","CqqaDuJScX","zY1GY48cHL","580YDKASQ8","NOHszQ6Lix","d7vjMDz1R3","LewvMqQxHP","mz8gxM3zXL","5NammFNYIM",
-"Waim6Yf2Ec","HRxd8fcwDa","HzZT8o8Uyd","yEfy9UlU3M","uN6r3tAOsr","WPmlxuPX7G","ru4UGIBe8k","soy9tFPfSE","UmaEvKASQ8","GrDg7LewvM",
-"MK07Y4dEz6","S2DfuMmKGJ","AkKTk4W0Tl","oQ87rJkzUn","y94nwiwzGk","JJs5mP6bcg","vLsmSQnJ1S","9rlg9WPmlx","AkKTk9XyT9","pv0i7POUYS",
-"Vprf2hi5X7","3otm6gjUTu","VIlwPMmsIo","8FmFHMmsIo","d85a9Ta8f6","v1HlnaL6AJ","W3VFHjS1aj","WDVWJEdBKc","uAWypuLtKs","NhXdu2Yz7E",
-"YjB9tDz1R3","MmsIoY1mC0","ksJbyRACuj","taOXKblLA9","fmIK1dQ586","QWxoTWaWsv","n1pmOcmXIX","xReeciKqhr","Zv7z01LB1L","BFkb8Chuy3",
-"i7WMQFjHXR","5ZaEzvkCHH","oGu6xYjB9t","Waim6JJs5m","RBhp05Drn0","pFrrlBpYhV","faHirlpF6W","ru4UGh1zcH","6AFT07ku1p","VerEA45cIH",
-"Y1mC0Ss0Zu","FGzgpOz8yZ","POUYSRzaZA","ZUnqtuLtKs","SjskQd85a9","9rlg9jeskS","0ao3lLDk6f","ksJbyni2v1","Zv7z0MmsIo","ulk41POUYS",
-"Vprf2MezSW","Ul4a1v8yFN","rKDLJNOHsz","MK07YCxVEf","cQOnvReKEW","lkMUA5IhmG","YjB9tQYxC0","d85a9fmIK1","atef2XflUq","L7cGczbIYY",
-"gtCA5yvOMI","aFFsspv0i7","soy9t3weIF","JRJQB5IhmG","oQ87r5IhmG","uQIczaL6AJ","sqVrftaOXK","KsjRKGSQwj","NAFuwDLhzM","ReKEWWreyP",
-"FGzgplsQGo","Yh1hF0MR5X","yToGWOUqFM","EOE1o6AFT0","nnP8oksJby","CIShG2Yz7E","5nmWvgf8rI","ReKEWni2v1","azIWpjiVBP","jS1ajQChxs",
-"SbRYy0ao3l","NOHszqUJMd","fFDrJ0h1b1","5Drn0ThjNn","OUqFMIKxdL","pT8wu7hyVv","2DREsIjTwP","djsrvzY1GY","uZPqgFnPFB","1j5L8x3LDe",
-"Q6LixogLgc","GSQwjyEfy9","y94nwI7p2a","8cVD3QChxs","45cIHDG4sT","tjQxsvkCHH","Ta8f6FcWrW","6q6L9POUYS","I7p2aFGzgp","i7WMQHfyNQ",
-"MmKGJVerEA","b29RJOHaBz","fmIK1Twano","GrDg7vOqCE","qQxHPjzUqR","fcJOyulk41","PYBf4Yf2Ec","hUTw7S77LH","5ZaEzQClRL","0ao3l07n1c",
-"fcwDa2hEEU","d7vjMGv3Fq","MGlTFuLtKs","3otm6CNHmv","vkCHHmX2GE","VLTy6zFgtB","NOHszcQOnv","fmIK1iwzGk","jeskSQClRL","zQt6QgtCA5",
-"Ul4a1tlILt","xciqpX6Pin","9eoRcUvlv4","BGaQYiqv4k","X6PinlkMUA","azIWpvOqCE","t98iWOHaBz","v1HlnQWxoT","8xEKzK20wK","CIShGK20wK",
-"55rfBJXljW","Uvlv4ydG8U","BFkb8fFDrJ","kB5nPMezSW","uJScXzHF1q","5ZaEzSbRYy","FjHXRjiVBP","fcJOyLewvM","EoToPuZPqg","QYxC0ydG8U",
-"EOE1oKsjRK","TXQ0Zsoy9t","gdQsSkB5nP","gjUTugjUTu","9GXkXiKqhr","v8yFNb29RJ","16lHcZzJHW","BFkb85Namm","5ZaEzoQ87r","W7cTsMGlTF",
-"cL0aEhSSvQ","0YAGHQClRL","bgJAz5Mg9r","jSjS3S2Dfu","IRh48QChxs","lXFOBOHaBz","taOXKwiHrZ","iB08lHfyNQ","4QMc9aFFss","StlDJXyPZN",
-"oGu6xF6PT2","2hEEUdQ586","FFDuiciuWz","YOfrYbrhlQ","pvgjSOxWIH","OUYuFDz1R3","LewvMReKEW","J2mQiLewvM","lpF6Wv8yFN","prNT6jtn0X",
-"W3VFHVprf2","BCxeCOUYuF","QChxs9XyT9","FLsph14FLR","lj07QD6rBy","OHaBzPb1pa","Yf2Ec0PktI","CdyBV8xEKz","qUJMdlweGy","OUqFMrKDLJ",
-"9GXkX5Mg9r","2TRI7AOgEe","B3qemIKxdL","L7cGcazIWp","MezSW07n1c","azIWpHfyNQ","4dEz6jSjS3","9XyT9POUYS","tuDySaDGtS","qaofNazIWp",
-"C2Irc29QAz","zqH0WAXpwE","tAOsrS77LH","FGzgp2Nslm","VerEAbrhlQ","zbIYYtlILt","PYBf4G1RhS","uZPqgtl72W","o8Uydmz8gx","uN6r3xReec",
-"AgJHQazIWp","JRJQBVerEA","I7p2admoS7","RACujuupzk","iB08llXFOB","Ta8f6C2Irc","yEfy9gtCA5","Q6hMCaFFss","qUJMdpAhR1","ogLgcydG8U",
-"jSjS35Mg9r","SbRYyFVMxo","MK07YFwEJz","LewvMblLA9","iwzGkNhXdu","h1zcHFFDui","45cIH9rlg9","RkQkeWreyP","FjHXR5Mg9r","jfREuzQt6Q",
-"2hEEUQClRL","VLTy65ZaEz","QbxXcFnPFB","n8pJ99eoRc","MezSWDG4sT","AgJHQ07n1c","o8Uydzz4ZU","Mm8siOUqFM","RmDcrzmLYD","580YDUvlv4",
-"UlU3MQ6Lix","pWiOstvdkD","ogLgc6q6L9","P6bcgJRJQB","GXdoHDQimp","5Mg9rpAhR1","24ARFQYxC0","hSSvQhUTw7","rz7UtuLtKs","RpBQmW3VFH",
-"gdQsSMGlTF","ZhwG1ZUnqt","m4bxUkB5nP","XyPZNnnP8o","zFgtBsoy9t","C2IrcThjNn","Q6hMCfcwDa","0Wr5yJIqXi","VNCPdAkKTk","NAFuwlsQGo",
-"pWiOsBpYhV","16lHcECMvU","BCxeCoQ87r","zQt6QGrDg7","pvgjS8U2nU","prNT6CK5W7","M3zXLxXTI4","zqH0WuoStw","fcwDayluBx","ReKEWblLA9",
-"ZhwG1zqH0W","Yf2EcChuy3","X6PinFcWrW","4QMc9LewvM","qQxHPuupzk","hUTw7YOfrY","aFFssfFDrJ","Y1mC0FPfSE","X6Pin7X3uy","4W0TlSs0Zu",
-"bZLvSuQIcz","rKDLJZ4I1v","BpYhVW7cTs","HzZT8Yh1hF","DLhzM7fKYU","IRh48RpBQm","hSSvQBGaQY","Pb1paWmadA","IRh48blLA9","M6qcGJIqXi",
-"vOqCE5ZaEz","PYBf4Ss0Zu","BFkb8jzUqR","XyPZNwDajX","GXdoHRBhp0","bZLvSKZamH","aFFssaez9y","taOXKF6PT2","7ku1pnFqik","EOE1oVBjhz",
-"xXTI4dhSuH","3weIFBCxeC","2TRI7RsQUq","RxrsmOxWIH","K4GS8HlUbF","MojnPuN6r3","8FmFHpAhR1","HzZT8vLsmS","kZANmzFgtB","5drc6B3qem",
-"vkCHH24ARF","MmsIoyluBx","n8pJ9CIShG","tuDyS5Drn0","BCxeCo8Uyd","dQ586WDVWJ","QnJ1SM6qcG","dhSuHfaHir","14FLR29QAz","5drc6Gv3Fq",
-"0PktIdjsrv","TCgPplpF6W","Gv3FqM6qcG","3weIFHRxd8","1v5hHPYBf4","oQ87rCxVEf","uQIczk85Ae","RzaZAeuZA5","7hyVvHfyNQ","ThjNnQYxC0",
-"uTacxVerEA","gIYvE7hyVv","qaofNC2Irc","mX2GEMaJQs","iB08lNOHsz","OHaBzDcpWB","FcWrWWMiS3","DG4sTSWfou","yluBxjtn0X","QnJ1SpvgjS",
-"blLA92Yz7E","2ZHdklpF6W","k85AeSjskQ","Ta8f67ku1p","FhtglRmDcr","2ZHdkRzaZA","uJScXlsQGo","l83UdKZamH","SmGzv1j5L8","HzZT8gjUTu",
-"xReecgtCA5","d85a9piJSk","M6qcGFnPFB","X6Pin9eoRc","64s8NWaim6","dQ586uZPqg","L7cGcLDk6f","POUYSRBhp0","lpF6Watef2","6q6L9Rxrsm",
-"HlUbFjiVBP","2hEEU4dEz6","Qworu5nmWv","s4786fLNg8","YjB9tmX2GE","CxVEflpF6W","5drc6VIlwP","7hyVvMezSW","SjskQbrhlQ","5drc6kB5nP",
-"uupzkAkKTk","uTacx3weIF","b29RJDG4sT","Yh1hFulk41","QWxoTWaim6","YOfrYtlILt","5ZaEzZv7z0","VerEAyluBx","tAOsrMK07Y","ksJby0YAGH",
-"jiVBPvOqCE","uTacxECMvU","0Wr5yFGzgp","jfREu6q6L9","S2DfuX6Pin","FNYIMDG4sT","55rfBMGlTF","RpBQm4dEz6","QworuWMiS3","KsjRK07n1c",
-"zFgtBNxx9V","HfyNQK20wK","hSSvQqUJMd","yofH3pvgjS","lkMUABFkb8","ThjNnuQIcz","a00b5v2eC3","1j5L8Ul4a1","5VZjSWaWsv","JJs5m0MR5X",
-"atef2Nxx9V","5Mg9r3weIF","MGlTFuAWyp","5iGN5BFkb8","lCMxyEoToP","bZLvSWPmlx","07n1cDLhzM","CNHmv3weIF","Z4I1vksJby","HRxd8KZamH",
-"Ta8f6MK07Y","No0QbIjTwP","AgJHQIRh48","zFgtBP6bcg","Vprf2VjCZq","mX2GEv2eC3","AkKTk6q6L9","64s8NcQOnv","uJScXFVMxo","fqypy24ARF",
-"RkQkeMmKGJ","55rfB24ARF","hSSvQ8hJdt","uN6r3Pb1pa","wiHrZbZLvS","zHF1qy94nw","0PktIZhwG1","5VZjSWaim6","cShY2I7p2a","qUJMdFwEJz",
-"2ZHdkCp3mZ","QYxC0ThjNn","RzaZAwDajX","yToGWSWfou","o8UydcL0aE","pFrrld7vjM","POUYSsoy9t","lH1ktWaim6","QClRLyToGW","uQIczlkMUA",
-"FcWrWCIShG","iwzGkAIYUu","JKWYRhi5X7","W7cTsS2Dfu","BGaQYW3VFH","uZPqgGSQwj","tuDySW7cTs","JKWYRnnP8o","2NslmRBhp0","4dEz6HRxd8",
-"0BmCyBGaQY","jiVBPguMb8","GrDg7FcWrW","Zv7z0WreyP","618Di9iGoT","Nxx9VTwano","SbRYygIYvE","SWfouzFgtB","In3NSgIYvE","pFrrlxXTI4",
-"CNHmvuvf7A","YOfrYjS1aj","mX2GEReKEW","I7p2aKASQ8","TXQ0ZBbwgA","blLA9TXQ0Z","YjB9tzQt6Q","5drc6EoToP","QbxXcBbwgA","QYxC0IRh48",
-"h1zcHoGu6x","dhSuHv2eC3","vkCHH45cIH","nFqikdjsrv","9eoRcY1mC0","G1RhS4W0Tl","9rlg907n1c","MmsIoCp3mZ","2Yz7EeuZA5","MaJQsYf2Ec",
-"FLsphNOHsz","uupzkRkQke","yofH3gtCA5","KZamHQssNC","UlU3MHlUbF","MK07YFhtgl","ThjNnhYBCK","Zv7z0oGu6x","BpYhVtjQxs","9GXkXhe9IA",
-"K20wK0YAGH","lViBviwzGk","IBe8kKsjRK","QChxs0MR5X","ZuDtDpAhR1","blLA9PYBf4","ru4UG16lHc","aDGtS16lHc","ksJbyydG8U","RpBQmpAhR1",
-"prNT6ydG8U","29QAzJkzUn","aDGtShUTw7","7hyVvZuDtD","LDk6fFwEJz","IjTwPtjQxs","4W0TlNOHsz","Pb1pafqypy","n1pmOHP433","s4786DcpWB",
-"ni2v1ix74r","QClRLlCMxy","LbRTHZv7z0","nnP8oI7p2a","oGu6xpT8wu","tvdkDcmXIX","HRxd8sx5Gl","3weIF6AFT0","nFqikF6PT2","0PktIlH1kt",
-"yluBxaDGtS","NcICAFPfSE","xciqpOxWIH","0YAGHGv3Fq","P6bcgJ2mQi","MaJQs8U2nU","JIqXiFxX9q","8xEKzFwEJz","5nmWvciuWz","Ta8f6Y1mC0",
-"7Ow5CWPmlx","lkMUACdyBV","7ku1pWPmlx","1v5hHpWiOs","dmoS7MezSW","ksJbyRmDcr","vOqCEkZANm","QworuWaWsv","euZA5nFqik","tjQxsGrDg7",
-"U3yw5gdQsS","ZUnqt29QAz","nlaBy9iGoT","QnJ1SXyPZN","iKqhrt59lR","yToGWjeskS","v1Hlnv8yFN","lm0pDRpBQm","zQt6QCfgr3","t59lRfcJOy",
-"CIShG0MR5X","uTacxUlU3M","3weIFfaHir","MmsIoCNHmv","cShY2OUqFM","guMb8YOfrY","8cVD37lUXZ","Zv7z0yEfy9","1v5hHDQimp","iwzGklCMxy",
-"3otm6UmaEv","jiVBPIKxdL","QbxXc07n1c","Q6LixRzaZA","gf8rIM3zXL","rhl0JDLhzM","8FmFHGSQwj","EOE1oRACuj","Gv3Fqdpe1v","Ta8f65iGN5",
-"MojnPVLTy6","Cfgr33weIF","3otm6prNT6","29QAzOHaBz","sx5GlFcWrW","I7p2aTwano","fFDrJZv7z0","C2Irc6q6L9","brhlQ0MR5X","DQimpVIlwP",
-"djsrvpAhR1","5Drn0KsjRK","atef2Waim6","HRxd8Ul4a1","LDk6fOz8yZ","jS1ajIn3NS","Oz8yZxXTI4","L7cGcRmDcr","i7WMQfmIK1","sqVrfNhXdu",
-"JRJQBS77LH","9y4lwYf2Ec","8TxD7gtCA5","zbIYYlsQGo","TXQ0ZCdyBV","ydG8UguMb8","KZamHgdQsS","kZANmHlUbF","K4GS8Chuy3","ZJTXHuupzk",
-"MojnP5iGN5","tvdkDRkQke","piJSkPOUYS","n8pJ99y4lw","P6bcg8xEKz","uupzkgIYvE","wDajXVLTy6","YOfrYv8yFN","K4GS8soy9t","rKDLJzQt6Q",
-"14FLRuQIcz","nlaByRACuj","FLsphcmXIX","zFgtBuQIcz","JKWYR9y4lw","Mkgy8QClRL","Kr8ysNAFuw","VerEANhXdu","B3qemNcICA","5ZaEzCNHmv",
-"JKWYRhYBCK","POUYSNAFuw","Chuy3MezSW","Cfgr314FLR","FjHXRStlDJ","tuDySMezSW","nFqikM6qcG","he9IARkQke","7lUXZYOfrY","Vprf2jeskS",
-"JRJQBMkgy8","NOHszlsQGo","IRh482hEEU","QWxoTWreyP","ECMvUnFqik","mX2GEBGaQY","OUqFMkZANm","zY1GY7Ow5C","P6bcgO3iyQ","jzUqRQbxXc",
-"iKqhrAmdQd","cL0aE0Wr5y","In3NSQWxoT","oGu6xlpF6W","No0QbUlU3M","IRh487X3uy","sx5GlAgJHQ","QnJ1SuN6r3","AXpwE618Di","GWqqX0MR5X",
-"QnJ1SHfyNQ","mz8gxpFrrl","tjQxsX6Pin","NcICAjfREu","lViBvHfyNQ","EoToPMojnP","cL0aElkMUA","7X3uyX6Pin","yToGWjiVBP","i7WMQoVQp6",
-"ZhwG1WPmlx","qaofNxXTI4","dmoS7Nxx9V","vkCHHIjTwP","GrDg7M3zXL","cShY2fFDrJ","v2eC3jSjS3","KsjRKaL6AJ","rz7UtSjskQ","2ZHdkJ2mQi",
-"t98iWOxWIH","S77LHbZLvS","EoToPZzJHW","tuDySXflUq","ix74rlXFOB","tjQxsYh1hF","y94nwPb1pa","TXQ0ZG1RhS","he9IAfLNg8","48cHLi3pyd",
-"MaJQsiqv4k","580YD5Drn0","wDajXTXQ0Z","tlILtogLgc","9eoRcjfREu","rhl0Jlj07Q","7hyVvWaim6","CK5W7ksJby","Kr8ysFjHXR","hE1QlfcwDa",
-"W7cTsReKEW","VNCPdxciqp","Chuy3xciqp","ThjNnSjskQ","JRJQBJXljW","uN6r3guMb8","JXljWQssNC","LbRTH0PktI","o8Uydni2v1","fLNg8qQxHP",
-"xciqp5IhmG","tuDySbZLvS","s7Mxk5VZjS","ZzJHWlCMxy","MojnPDcpWB","VNCPd8hJdt","sx5GlSWfou","Dz1R3WreyP","faHir2TRI7","7Ow5C0BmCy",
-"wiHrZFwEJz","wiHrZIKxdL","No0Qby94nw","8U2nUHP433","gjUTuThjNn","qUJMdGSQwj","rKDLJVNCPd","0ao3lMmKGJ","0Wr5y5drc6","I7p2aBpYhV",
-"CqqaDEoToP","pAhR1yluBx","RpBQm0MR5X","GXdoHcmXIX","5IhmGSWfou","lCMxyv8yFN","CdyBV7ku1p","AkKTk1j5L8","jSjS36q6L9","6q6L97fsYM",
-"HlUbFYOfrY","RkQken1pmO","VIlwPcmXIX","uN6r3Mm8si","BpYhVHfyNQ","lXFOB1v5hH","BpYhVfcJOy","qaofNoQ87r","rz7Ut8xEKz","t98iWDLhzM",
-"UmaEvt98iW","JRJQBnnP8o","In3NSpT8wu","S77LHsoy9t","WPmlxM6qcG","xciqpmX2GE","suY4xMGlTF","2NslmjSjS3","Gv3Fq2Yz7E","aFFssokgRi",
-"yluBxW7cTs","8cVD3sx5Gl","pT8wuHzZT8","euZA5hi5X7","OUqFM2TRI7","WMiS3Oz8yZ","0ao3lQWxoT","b29RJSbRYy","1j5L8FGzgp","MGlTFgjUTu",
-"Yh1hF5drc6","bZLvSlViBv","618Di8hJdt","2Yz7EQ6hMC","v2eC3i7WMQ","prNT65VZjS","OHaBzDLhzM","Yh1hFlsQGo","4W0TlvOqCE","Chuy3prNT6",
-"RkQke4W0Tl","pv0i7O3iyQ","7hyVvcL0aE","7fKYUSWfou","uupzkRsQUq","FxX9q9y4lw","nlaByqQxHP","VBjhzRxrsm","FFDuizY1GY","LbRTHaDGtS",
-"vkCHH5iGN5","lweGysqVrf","QssNCjtn0X","VBjhzL7cGc","qQxHPOHaBz","IKxdLkZANm","5IhmGYOfrY","0Wr5yCNHmv","TXQ0ZxReec","G1RhS4QMc9",
-"b29RJMkgy8","VLTy6aez9y","lH1ktBFkb8","lweGySs0Zu","oGu6xYh1hF","uJScXtlILt","Zv7z04QMc9","yluBxtvdkD","618DiZ4I1v","NAFuw2ZHdk",
-"BGaQYAXpwE","oGu6xsuY4x","Z4I1v2hEEU","pFrrlVNCPd","TXQ0Zo8Uyd","HP433GXdoH","EdBKceuZA5","FNYIMv2eC3","ZhwG1LewvM","VerEAFNYIM",
-"kB5nPtaOXK","POUYSYw2oU","MezSWmz8gx","45cIHFhtgl","MezSWtl72W","QWxoTMm8si","jiVBPs4786","Yf2Ec2hEEU","YjB9tS77LH","i7WMQFLsph",
-"5nmWvxciqp","uupzkyluBx","hi5X7rhl0J","aFFssTXQ0Z","Y1mC0EoToP","zbIYY6q6L9","S2DfuIRh48","gf8rI14FLR","ydG8U2TRI7","JKWYRciuWz",
-"QssNCIjTwP","Chuy37lUXZ","ZhwG1AXpwE","uvf7AhE1Ql","07n1cwDajX","GrDg7hYBCK","v1HlnECMvU","Q6hMC5Namm","kB5nP5iGN5","16lHc580YD",
-"RmDcrMGlTF","YOfrYgIYvE","4dEz6fLNg8","dhSuHYw2oU","9iGoT45cIH","FcWrWSWfou","v1HlnVNCPd","SmGzvOHaBz","vOqCETXQ0Z","lpF6Wuupzk",
-"M3zXL7lUXZ","m4bxUYOfrY","CxVEfcmXIX","0PktIXyPZN","7lUXZbgJAz","blLA9pvgjS","W7cTs64s8N","hUTw78hJdt","Qworu2Yz7E","lm0pD1LB1L",
-"n1pmOSs0Zu","K4GS8qQxHP","In3NS618Di","he9IAQClRL","Vprf2K20wK","Yh1hFlXFOB","64s8Npv0i7","dpe1vqUJMd","JKWYRksJby","kB5nPXflUq",
-"Chuy3uPX7G","jS1ajjfREu","0Wr5yqUJMd","No0QbQWxoT","e6e4zQ6Lix","QYxC0W3VFH","nnP8oW3VFH","EOE1ovOqCE","5VZjSLbRTH","KASQ8VIlwP",
-"MK07Y8hJdt","F6PT2guMb8","piJSkFcWrW","16lHcCdyBV","hE1Qlzz4ZU","Chuy37fsYM","Gv3FqWPmlx","h1zcHStlDJ","QYxC0Y1mC0","Cp3mZgtCA5",
-"suY4xuvf7A","5Drn0n1pmO","uN6r37fKYU","uTacxI7p2a","3otm6CK5W7","Zv7z0h1zcH","xXTI4JRJQB","WPmlxMmsIo","cShY214FLR","hSSvQv1Hln",
-"qUJMdFcWrW","Yh1hFC2Irc","yofH3uZPqg","RACujOHaBz","kB5nPlXFOB","W7cTsW3VFH","L7cGcFxX9q","BGaQYAOgEe","KASQ84dEz6","Oz8yZ7X3uy",
-"brhlQl83Ud","QChxsFVMxo","1LB1L8RCUA","n1pmOcShY2","VjCZq55rfB","pWiOsJkzUn","Yw2oUtAOsr","QworudmoS7","7X3uywDajX","Twanolj07Q",
-"Cp3mZLewvM","PYBf4tjQxs","FnPFBAmdQd","24ARFIjTwP","iqv4kPYBf4","tlILtEoToP","D6rByJ2mQi","EdBKcydG8U","UlU3MGXdoH","JIqXiP6bcg",
-"lViBvtAOsr","FhtglQ6hMC","cmXIXdjsrv","Zv7z0kB5nP","FPfSEEoToP","CqqaDuAWyp","Zv7z0v8yFN","MmsIofaHir","DcpWB07n1c","ulk41CdyBV",
-"DQimp16lHc","JRJQBUl4a1","QnJ1SprNT6","NAFuwAXpwE","l83UdCdyBV","Dz1R3xReec","kZANmM6qcG","StlDJSjskQ","nnP8oYf2Ec","mX2GEI7p2a",
-"gtCA5Fhtgl","Cfgr3KsjRK","2DREsCK5W7","EoToPYh1hF","0MR5XfcwDa","pvgjS3weIF","2TRI75Drn0","YOfrYk85Ae","jeskS14FLR","oVQp63weIF",
-"8RCUAeuZA5","JRJQBVprf2","jzUqRGSQwj","s7MxkUvlv4","ReKEWBCxeC","B3qemGv3Fq","uupzkzY1GY","14FLRFwEJz","lweGyB3qem","pAhR1ZzJHW",
-"m4bxUNo0Qb","uupzkUlU3M","VjCZqsx5Gl","AmdQdW3VFH","qQxHPlCMxy","7Ow5Crz7Ut","hSSvQiB08l","cL0aEFjHXR","dQ586GWqqX","fmIK1No0Qb",
-"Q6LixrKDLJ","2hEEUDcpWB","EoToPCNHmv","2ZHdkuTacx","6q6L9iwzGk","NcICAVNCPd","Nxx9Vmz8gx","ix74rQYxC0","0ao3l5drc6","Nxx9VEdBKc",
-"Yh1hF8hJdt","1j5L8pv0i7","1j5L8taOXK","7fKYUSs0Zu","t98iWF6PT2","Y1mC0gIYvE","SjskQ0YAGH","ZuDtD0YAGH","45cIHqQxHP","yvOMIChuy3",
-"uvf7Ab29RJ","tlILtyToGW","dhSuHs7Mxk","d7vjM7fKYU","9rlg9SmGzv","uZPqgVerEA","tl72Wi3pyd","fmIK1pmeCd","v8yFN5iGN5","Kr8ysRzaZA",
-"FnPFB2Nslm","IBe8k0ao3l","16lHcUlU3M","9XyT9aFFss","zz4ZUzQt6Q","IjTwP8FmFH","uTacxRmDcr","BCxeCzY1GY","8xEKzs93Ml","GXdoHRACuj",
-"k85AeZv7z0","GWqqXuoStw","MGlTFMmsIo","7lUXZGrDg7","lViBvMK07Y","FwEJzqQxHP","K20wKoGu6x","14FLRS77LH","Q6Lix7ku1p","9y4lwP6bcg",
-"Uvlv4qQxHP","he9IAs93Ml","G1RhSbgJAz","yvOMIMojnP","AmdQd8hJdt","QYxC0AgJHQ","d7vjMCIShG","7fKYUJIqXi","K20wKKr8ys","jeskSbrhlQ",
-"SWfoudhSuH","W3VFHQssNC","9GXkXiB08l","Waim6sqVrf","FFDuiEOE1o","HlUbFSjskQ","J2mQiyvOMI","fqypyDG4sT","K4GS89XyT9","K20wK0Wr5y",
-"OxWIHru4UG","lXFOB16lHc","faHirCNHmv","WDVWJrhl0J","L7cGcWaim6","uQIczWreyP","5nmWvJRJQB","48cHLb29RJ","lViBvVBjhz","Zv7z0StlDJ",
-"C2IrcTwano","t98iWY1mC0","SWfoulm0pD","8TxD7CIShG","HRxd8lm0pD","FjHXR1j5L8","JIqXi9rlg9","BGaQYHzZT8","d85a9Mm8si","Uvlv4Kr8ys",
-"gf8rIlm0pD","YOfrYgtCA5","JJs5mHzZT8","tvdkDRzaZA","SbRYyvOqCE","tuDyS5drc6","2hEEUBbwgA","VLTy6rhl0J","xXTI4lsQGo","pvgjSb29RJ",
-"5nmWv7fsYM","v8yFNciuWz","8RCUAvOqCE","aFFssxciqp","fqypyF6PT2","7hyVvZJTXH","45cIHWDVWJ","FNYIMD6rBy","tuDySSjskQ","fcJOy7ku1p",
-"DG4sTsqVrf","piJSkVLTy6","dpe1vhYBCK","ZUnqtIn3NS","h1zcHyofH3","VLTy6Y1mC0","n1pmOogLgc","sx5GlCfgr3","QnJ1SGv3Fq","he9IAxReec",
-"sx5Gl9iGoT","FnPFBe6e4z","ZzJHW2Nslm","7X3uy0PktI","VNCPdjiVBP","tuDySuQIcz","5NammiB08l","GWqqXHP433","hYBCK4QMc9","fLNg8hSSvQ",
-"Pb1paaDGtS","ni2v12hEEU","X6PinjS1aj","24ARFxciqp","2Yz7Euupzk","P6bcgF6PT2","MmsIoYf2Ec","BpYhVYjB9t","9eoRcuQIcz","7ku1pK4GS8",
-"1v5hHuAWyp","k85AeOUYuF","iKqhrNOHsz","ydG8UOHaBz","ogLgcHzZT8","WreyPix74r","zbIYYfcJOy","MGlTFRpBQm","L7cGcyvOMI","GrDg70h1b1",
-"Dz1R3OxWIH","JRJQB3weIF","L7cGcRzaZA","iwzGkcQOnv","5VZjSsqVrf","n1pmORxrsm","Yw2oUSbRYy","FNYIMW3VFH","Uvlv4MojnP","3weIFs4786",
-"gtCA5pvgjS","8U2nUru4UG","jSjS3O3iyQ","iqv4k580YD","MK07YprNT6","45cIHuvf7A","lm0pDBGaQY","djsrvG1RhS","7fsYMYh1hF","FjHXRYw2oU",
-"9GXkXKsjRK","wDajXZUnqt","UlU3Ms4786","MezSWS77LH","yToGWgIYvE","BCxeClsQGo","azIWpKr8ys","lCMxyGSQwj","5iGN54dEz6","i7WMQuLtKs",
-"WMiS38TxD7","ZzJHWJ2mQi","No0Qb2Yz7E","bgJAzyEfy9","m4bxUmX2GE","kB5nP5nmWv","FnPFBrz7Ut","RzaZASbRYy","VjCZqHfyNQ","W7cTsuN6r3",
-"KsjRKjeskS","lsQGo8U2nU","OUYuFb29RJ","lCMxyqQxHP","JkzUnWPmlx","tvdkDjSjS3","U3yw5euZA5","VerEATa8f6","mz8gxuTacx","K4GS8FxX9q",
-"uvf7Ay94nw","6q6L9Y1mC0","5Drn0yEfy9","h1zcHjfREu","ydG8UMkgy8","atef2CxVEf","Zv7z0ydG8U","MaJQs55rfB","hi5X7RzaZA","djsrvSjskQ",
-"FLsphtjQxs","RACujrz7Ut","d85a9nFqik","Yh1hFoGu6x","jSjS3ZhwG1","YjB9t9iGoT","GrDg7lsQGo","JXljWAIYUu","dpe1v1v5hH","ZzJHWY1mC0",
-"IRh48s7Mxk","I7p2aZv7z0","i7WMQsqVrf","zqH0WKr8ys","8RCUAY1mC0","hUTw7RACuj","RkQketuDyS","G1RhSIKxdL","EdBKcBCxeC","ReKEWThjNn",
-"4W0TlEoToP","0BmCygtCA5","9rlg9uPX7G","RmDcrbgJAz","OHaBzCxVEf","TXQ0ZQworu","QbxXcgtCA5","vkCHHpmeCd","WreyPPb1pa","hi5X7hi5X7",
-"tlILtkB5nP","MezSWQYxC0","qUJMdK20wK","h1zcHatef2","CK5W7NOHsz","OUqFMciuWz","X6PinNOHsz","7Ow5ChUTw7","pAhR1ciuWz","K4GS8uoStw",
-"0BmCygdQsS","O3iyQ24ARF","RzaZARBhp0","zQt6QkB5nP","NcICAIRh48","CIShGW3VFH","JRJQBL7cGc","4dEz6oVQp6","XflUqNAFuw","W7cTsmX2GE",
-"7fKYU9y4lw","atef2o8Uyd","FxX9qWPmlx","5IhmGlkMUA","lweGyrz7Ut","7Ow5Cfqypy","RACujgtCA5","45cIHQssNC","zFgtBNo0Qb","jfREut59lR",
-"JRJQB4dEz6","xXTI4D6rBy","Z4I1vRpBQm","Mkgy8xXTI4","64s8N9GXkX","4QMc9jtn0X","0PktICp3mZ","9eoRcEdBKc","lViBvn1pmO","zmLYDNhXdu",
-"sx5GlD6rBy","4QMc9RpBQm","2ZHdkSbRYy","QChxspv0i7","TwanozFgtB","0PktIRmDcr","MaJQsaFFss","POUYSpvgjS","AIYUupFrrl","In3NSUmaEv",
-"jSjS3RBhp0","FcWrWs7Mxk","bZLvShSSvQ","7Ow5CcShY2","5IhmGFVMxo","s4786gdQsS","IjTwPFNYIM","pWiOsuLtKs","S77LHtlILt","2ZHdkWPmlx",
-"aez9y8xEKz","lH1ktzY1GY","OxWIHHRxd8","FLsphgf8rI","lweGy4dEz6","4dEz6pAhR1","uTacxQssNC","KsjRKRsQUq","GWqqXzbIYY","JKWYRuPX7G",
-"yofH3s4786","Q6LixG1RhS","GSQwjtlILt","ix74r2Nslm","tvdkDMojnP","tvdkDix74r","tvdkDKsjRK","FnPFBL7cGc","QnJ1SyluBx","AIYUugf8rI",
-"hSSvQOUqFM","Mkgy81v5hH","RsQUqix74r","FcWrW5Mg9r","5Nammfqypy","4QMc9BpYhV","dQ586F6PT2","nnP8odpe1v","zQt6QRkQke","tAOsrVerEA",
-"aDGtSFFDui","0BmCyatef2","oVQp6ZUnqt","WaWsvi3pyd","pT8wuqUJMd","piJSkJKWYR","SbRYyi3pyd","hSSvQPYBf4","yluBxCxVEf","ThjNnuN6r3",
-"0h1b1MmsIo","O3iyQlH1kt","FPfSEv1Hln","ReKEW8TxD7","wiHrZYh1hF","v2eC3Uvlv4","Uvlv4QssNC","tAOsrSs0Zu","FxX9qJIqXi","9eoRcNhXdu",
-"JRJQBsqVrf","5drc6uupzk","JkzUnsx5Gl","RmDcrnlaBy","FGzgptlILt","WDVWJL7cGc","i7WMQlViBv","O3iyQaDGtS","MGlTF4W0Tl","jS1ajWDVWJ",
-"piJSkAOgEe","5Mg9r580YD","5iGN5FnPFB","prNT6yEfy9","dmoS7aL6AJ","FLsphRkQke","cL0aEBbwgA","2TRI7zY1GY","ZJTXHQChxs","1v5hH1j5L8",
-"JRJQB8FmFH","bZLvSyvOMI","guMb8FLsph","POUYS07n1c","cL0aEhYBCK","7Ow5CMmKGJ","0ao3l4QMc9","i7WMQpv0i7","cShY2EoToP","45cIHwDajX",
-"FcWrWlCMxy","Waim6IKxdL","TXQ0ZuAWyp","RkQkeAIYUu","kB5nPiKqhr","FVMxohi5X7","fcJOyM6qcG","dmoS7ECMvU","n1pmOwiHrZ","ZUnqtkZANm",
-"CxVEfFGzgp","Chuy3okgRi","W3VFH1LB1L","VIlwPrz7Ut","0h1b1blLA9","Mkgy8MGlTF","1j5L8bZLvS","bZLvS45cIH","618DiIjTwP","ksJbyjzUqR",
-"FPfSElm0pD","IKxdL0Wr5y","pT8wu5Drn0","Dz1R3zQt6Q","NAFuwmz8gx","FFDuiMK07Y","WaWsvYjB9t","8hJdtGXdoH","cShY2mX2GE","he9IAuQIcz",
-"oVQp6tlILt","G1RhS1v5hH","kZANmni2v1","9GXkXuPX7G","suY4xx3LDe","x3LDe45cIH","tjQxs9iGoT","UlU3MChuy3","zz4ZU07n1c","S2DfuTXQ0Z",
-"4dEz6gIYvE","M6qcGnlaBy","2NslmIBe8k","nnP8oQ6hMC","ulk41cmXIX","RBhp0Yf2Ec","iKqhrDLhzM","sx5Gln8pJ9","zHF1quoStw","IBe8kCqqaD",
-"IjTwPGSQwj","OUqFMbZLvS","SmGzvsoy9t","qQxHPdmoS7","S2DfuFcWrW","QWxoTW3VFH","45cIHaez9y","0Wr5yNo0Qb","uZPqgbrhlQ","B3qemazIWp",
-"pAhR1HRxd8","I7p2a8xEKz","MGlTFGrDg7","ZUnqtJRJQB","hi5X75Namm","FjHXRQbxXc","dmoS7brhlQ","hE1QloVQp6","azIWpa00b5","WPmlxBbwgA",
-"zqH0WGv3Fq","Mkgy89XyT9","ru4UGJIqXi","yToGW1j5L8","ThjNn07n1c","x3LDeaDGtS","AIYUuyEfy9","G1RhStlILt","FLsph6AFT0","SmGzvyluBx",
-"s4786GXdoH","n1pmOtuDyS","pv0i7s4786","bgJAzCqqaD","Uvlv4KsjRK","ix74ryvOMI","MmsIo5IhmG","MmKGJsqVrf","i7WMQyvOMI","b29RJ1LB1L",
-"24ARFAgJHQ","YjB9tcShY2","OUqFMQYxC0","Ul4a1VNCPd","14FLRBGaQY","BbwgADz1R3","DcpWBlH1kt","suY4xe6e4z","gf8rIulk41","FPfSEuN6r3",
-"VBjhz16lHc","07n1cXyPZN","0ao3l0YAGH","s47867fsYM","7lUXZv1Hln","prNT67X3uy","uupzkMkgy8","JXljWUlU3M","Z4I1vyluBx","AIYUuWaWsv",
-"Yh1hF7lUXZ","nlaByyvOMI","Q6hMCvkCHH","KsjRKulk41","zbIYYCNHmv","LbRTH7X3uy","QChxsHlUbF","07n1chYBCK","qQxHPyofH3","lkMUAzbIYY",
-"JXljW0BmCy","5Mg9r7fsYM","xciqpVBjhz","DcpWBOHaBz","fmIK1CK5W7","7fKYUlkMUA","SmGzvciuWz","cQOnvAmdQd","Ul4a1rz7Ut","fcwDagdQsS",
-"cmXIXjfREu","HfyNQ9y4lw","QnJ1SC2Irc","hYBCKFLsph","BpYhVChuy3","UmaEvlViBv","5nmWvydG8U","hYBCKuQIcz","atef2RsQUq","MojnP55rfB",
-"yEfy9pFrrl","VjCZqcL0aE","LewvMVerEA","blLA9aez9y","lm0pDfmIK1","1v5hHVjCZq","AgJHQK20wK","lViBvF6PT2","P6bcggf8rI","Dz1R3KASQ8",
-"n1pmOzmLYD","hUTw7Rxrsm","Ta8f6v8yFN","dhSuHMezSW","vkCHHAkKTk","M6qcGFFDui","Oz8yZvLsmS","yofH3SmGzv","1LB1LlCMxy","7Ow5C8U2nU",
-"rz7UtjSjS3","TXQ0Z5ZaEz","IBe8k29QAz","AgJHQUvlv4","dQ586MK07Y","MmsIo7ku1p","W7cTsECMvU","O3iyQVBjhz","VjCZqfLNg8","FVMxodpe1v",
-"rhl0JFNYIM","FxX9qQWxoT","ydG8UCqqaD","HP433UmaEv","2ZHdk9XyT9","IjTwPAgJHQ","2DREs5ZaEz","zQt6QiwzGk","blLA9ZhwG1","IBe8kydG8U",
-"JRJQBuN6r3","RACujfmIK1","zqH0Wdpe1v","5Mg9rMaJQs","TwanoBGaQY","jzUqRtlILt","mz8gxF6PT2","k85AeEdBKc","Mkgy8o8Uyd","WmadAtvdkD",
-"a00b5uQIcz","IRh48faHir","m4bxUCp3mZ","djsrvNOHsz","faHirDcpWB","fmIK1zFgtB","GXdoHRxrsm","mz8gxv2eC3","v1HlnqQxHP","t98iW0h1b1",
-"brhlQh1zcH","8U2nURkQke","48cHLFNYIM","MojnPtaOXK","5NammWPmlx","7fKYU4QMc9","xXTI4Chuy3","jzUqRhUTw7","xXTI4RACuj","ogLgcm4bxU",
-"6q6L9aDGtS","Waim68hJdt","QWxoTBpYhV","cQOnvsuY4x","ThjNnDG4sT","ZzJHWcmXIX","lpF6WGXdoH","FwEJzKASQ8","he9IAVjCZq","zz4ZUd85a9",
-"dmoS7x3LDe","ReKEWHRxd8","CNHmvYjB9t","DLhzMKr8ys","S2Dfuix74r","ciuWz2ZHdk","ksJbyNOHsz","9rlg9Q6hMC","jfREuwDajX","9y4lwGrDg7",
-"RxrsmxReec","sx5GlWmadA","0ao3lx3LDe","lXFOBjfREu","KZamHD6rBy","RkQkeEdBKc","Chuy3JkzUn","ZUnqtCqqaD","SWfouaDGtS","SWfouMkgy8",
-"qaofNksJby","UlU3MFVMxo","h1zcHfmIK1","B3qemSWfou","0MR5Xulk41","lH1ktdQ586","B3qemuZPqg","8TxD7Vprf2","4QMc9UlU3M","faHirjzUqR",
-"i3pyd9eoRc","tlILtvLsmS","lsQGooGu6x","ECMvU5IhmG","BCxeCI7p2a","b29RJprNT6","1j5L8euZA5","M3zXLzbIYY","MmsIokB5nP","tuDySxReec",
-"CqqaD5nmWv","FLsphk85Ae","NAFuwni2v1","zY1GYv2eC3","DcpWB5drc6","VLTy6xXTI4","ECMvUY1mC0","fcwDa5VZjS","LbRTH4dEz6","FLsphUlU3M",
-"Gv3FqUlU3M","atef2AmdQd","piJSkChuy3","EOE1od7vjM","lm0pDuTacx","KsjRKjzUqR","Cp3mZYjB9t","PYBf45iGN5","yEfy9blLA9","zqH0W0MR5X",
-"2TRI7pWiOs","5iGN5zHF1q","QClRLaDGtS","MmsIozFgtB","CqqaD48cHL","RsQUqJJs5m","9XyT9Uvlv4","aDGtSZuDtD","DcpWBuLtKs","L7cGc9XyT9",
-"jtn0Xb29RJ","ni2v1qaofN","yluBxJRJQB","JRJQBRsQUq","StlDJl83Ud","Vprf2a00b5","atef2KASQ8","7Ow5CS2Dfu","AOgEeF6PT2","aez9y6q6L9",
-"ulk41uLtKs","5Drn0aDGtS","0MR5XnnP8o","Z4I1vFnPFB","ZhwG1QWxoT","1v5hHQ6Lix","64s8NuAWyp","JkzUnlViBv","JkzUnRkQke","cL0aEguMb8",
-"NAFuwqaofN","U3yw52Yz7E","RBhp0JkzUn","K4GS8d85a9","JIqXiWMiS3","0h1b19GXkX","MaJQs1LB1L","OUYuF7lUXZ","UlU3M16lHc","29QAz0h1b1",
-"ZuDtDhUTw7","P6bcgK20wK","S77LHlkMUA","1j5L8jS1aj","55rfBEOE1o","0Wr5yuAWyp","fqypyQssNC","In3NSZzJHW","DG4sTlViBv","NOHszAOgEe",
-"6AFT0K4GS8","Q6hMCdpe1v","tuDySfLNg8","9iGoTVNCPd","vkCHHxXTI4","h1zcHblLA9","s93Ml5Drn0","QWxoTlH1kt","QYxC0hi5X7","JkzUnECMvU",
-"hE1QlaL6AJ","mz8gxfcJOy","5drc69y4lw","D6rByOUqFM","1v5hHlsQGo","uvf7AYjB9t","Dz1R3AOgEe","P6bcglm0pD","lXFOBWDVWJ","7fsYMuupzk",
-"lpF6W580YD","pmeCd6q6L9","lkMUAM6qcG","uAWypGXdoH","lj07Q48cHL","bZLvS5Namm","uAWypzHF1q","e6e4z0ao3l","BFkb855rfB","4dEz6YOfrY",
-"NOHszuTacx","ReKEWZzJHW","mX2GEAIYUu","k85Aei3pyd","pv0i7ni2v1","VBjhzgIYvE","HRxd89y4lw","ulk410YAGH","jtn0X1LB1L","tvdkDKr8ys",
-"WaWsvhUTw7","rhl0J07n1c","dmoS7faHir","X6Pin5iGN5","ulk415IhmG","uoStwfqypy","h1zcHFwEJz","6q6L9Zv7z0","gdQsS07n1c","yToGWjSjS3",
-"Vprf248cHL","S77LHRsQUq","GrDg7QClRL","K20wKNAFuw","vkCHH8TxD7","StlDJDLhzM","07n1cpAhR1","FNYIMVjCZq","CxVEfS2Dfu","9iGoTyvOMI",
-"ciuWzhUTw7","9XyT9uvf7A","dmoS7suY4x","7hyVvaDGtS","RpBQmgtCA5","hYBCK5drc6","BbwgAuPX7G","OUYuFnnP8o","5Drn0kB5nP","5IhmGlCMxy",
-"vOqCEi3pyd","lCMxysuY4x","No0QbU3yw5","ogLgclXFOB","i3pydSmGzv","vOqCElpF6W","IKxdL5ZaEz","TXQ0ZvOqCE","iqv4kDz1R3","5iGN55iGN5",
-"ZuDtDOz8yZ","3weIFVjCZq","Yw2oUEOE1o","iwzGkJRJQB","fFDrJuJScX","oGu6xI7p2a","CNHmvQbxXc","ksJbyMmKGJ","VBjhzJJs5m","9iGoTOHaBz",
-"sx5GlFnPFB","fcJOyNo0Qb","hYBCKgtCA5","gdQsSTa8f6","FxX9qGSQwj","jfREuJRJQB","tl72Wuvf7A","pv0i7MaJQs","Q6hMC8hJdt","EdBKcxReec",
-"nlaBytuDyS","7hyVvIn3NS","MmKGJblLA9","wiHrZn1pmO","2hEEUlm0pD","jS1aj1LB1L","FVMxooGu6x","mz8gxdpe1v","JkzUnMm8si","W7cTsyToGW",
-"4QMc9jS1aj","d85a9tvdkD","s93MlJRJQB","9GXkXlCMxy","gjUTu8U2nU","ZUnqt4QMc9","fLNg8ZuDtD","zmLYDJ2mQi","7ku1ptuDyS","X6PinNhXdu",
-"jiVBP64s8N","fLNg8DQimp","L7cGcyluBx","jfREu4QMc9","fLNg8tuDyS","dmoS7FcWrW","Oz8yZdjsrv","FnPFBfLNg8","9iGoTMaJQs","iwzGk4QMc9",
-"mX2GEPOUYS","b29RJgdQsS","piJSkpiJSk","uAWypOz8yZ","WreyP7Ow5C","NhXduoVQp6","YOfrYStlDJ","wiHrZNo0Qb","2Yz7EtjQxs","9rlg9EOE1o",
-"AIYUuCIShG","YjB9tAOgEe","6q6L9BGaQY","EdBKcWaWsv","2ZHdkBCxeC","Z4I1vogLgc","SWfouM6qcG","Kr8ysHzZT8","uZPqgRBhp0","YjB9t2Yz7E",
-"MezSWbgJAz","uZPqguPX7G","hYBCKJJs5m","jSjS3pAhR1","0YAGHVerEA","zHF1qW3VFH","4QMc9jeskS","fcJOy14FLR","v2eC329QAz","7ku1paL6AJ",
-"jfREuuupzk","5nmWvlpF6W","YOfrYWaWsv","pAhR1DLhzM","mX2GEpmeCd","7hyVvqaofN","Q6Lixatef2","9rlg9I7p2a","Uvlv4WaWsv","MGlTFzFgtB",
-"qQxHPWreyP","AkKTkhE1Ql","16lHclj07Q","7X3uy9GXkX","EoToP7Ow5C","vLsmSGXdoH","MK07YYjB9t","B3qemvLsmS","DQimpgf8rI","ZuDtDQnJ1S",
-"ReKEWoQ87r","Twano45cIH","uQIczzmLYD","Z4I1v8hJdt","hi5X70Kyfs","Ss0ZulCMxy","ydG8USmGzv","tvdkDQYxC0","fFDrJFGzgp","FwEJzlsQGo",
-"Yw2oUWmadA","uN6r3dhSuH","Dz1R3suY4x","HP433KsjRK","BbwgAtvdkD","taOXKAgJHQ","Yw2oUSjskQ","taOXKy94nw","MmKGJhE1Ql","0BmCyRmDcr",
-"zHF1qSmGzv","ThjNnm4bxU","v8yFN580YD","FwEJzatef2","9XyT9iKqhr","jfREuX6Pin","HlUbFUmaEv","0PktIvkCHH","uvf7AEOE1o","HfyNQjtn0X",
-"EOE1o7hyVv","KZamHpvgjS","Pb1paJKWYR","yluBxzFgtB","MGlTFRxrsm","BGaQY5drc6","ZuDtDoGu6x","hYBCKQYxC0","d7vjMjfREu","S77LHpT8wu",
-"Yh1hFfmIK1","hE1Ql0MR5X","1v5hHfcwDa","ulk41Waim6","Z4I1vFVMxo","FGzgpFLsph","WmadA0YAGH","d85a9ni2v1","RzaZAaDGtS","QChxspiJSk",
-"FxX9qHP433","iKqhr7lUXZ","s93MlNo0Qb","GSQwjuQIcz","vLsmS14FLR","2TRI7qUJMd","VjCZqL7cGc","8xEKzBbwgA","Rxrsm2ZHdk","M3zXLHlUbF",
-"9XyT9e6e4z","FxX9qP6bcg","taOXKRzaZA","Zv7z00ao3l","Y1mC0ulk41","0Wr5yVprf2","Q6hMC0BmCy","vLsmShi5X7","5nmWvuLtKs","pFrrluN6r3",
-"kZANmEoToP","2ZHdkzY1GY","Zv7z0XyPZN","S2DfuwiHrZ","FxX9qaDGtS","QssNC0MR5X","7lUXZ8RCUA","618Diuvf7A","oVQp6uQIcz","lXFOBQYxC0",
-"kB5nPYf2Ec","SWfouZ4I1v","Vprf2lXFOB","lm0pDcQOnv","F6PT2RmDcr","O3iyQ2hEEU","ru4UGuupzk","WPmlxtuDyS","RpBQm2DREs","9XyT9tAOsr",
-"FFDuiv1Hln","5Mg9rDLhzM","Ta8f6DG4sT","NhXduKASQ8","VIlwPeuZA5","I7p2aM3zXL","QssNCXyPZN","pWiOs0h1b1","1LB1LEoToP","oVQp6POUYS",
-"5Namm5Drn0","okgRirz7Ut","F6PT2QnJ1S","dQ586Waim6","29QAzlH1kt","ogLgcsx5Gl","lweGyni2v1","pAhR18FmFH","B3qemd7vjM","DLhzM3weIF",
-"rKDLJcQOnv","QbxXcpFrrl","NhXdunFqik","KsjRKyvOMI","CdyBVF6PT2","ZUnqtrz7Ut","S2DfuWaim6","BpYhVRzaZA","1j5L8nFqik","KZamHDG4sT",
-"iwzGkGWqqX","NhXdugtCA5","ZUnqtYOfrY","hUTw7618Di","IBe8kaDGtS","Yf2EcVIlwP","lCMxyBCxeC","X6PinbgJAz","OxWIHQworu","WMiS3QChxs",
-"0BmCyMkgy8","ECMvUlH1kt","dhSuH14FLR","ogLgcWreyP","16lHc0PktI","NOHszWPmlx","UmaEv7fsYM","8TxD79GXkX","580YDSbRYy","CIShG7hyVv",
-"C2IrcaDGtS","fmIK1D6rBy","XyPZNyluBx","azIWplsQGo","pAhR1kB5nP","FPfSEHlUbF","hi5X7i7WMQ","VBjhzGXdoH","Dz1R3IjTwP","wDajX2ZHdk",
-"QYxC0zY1GY","WPmlx5nmWv","soy9tIjTwP","Waim6vLsmS","zQt6QOUqFM","hYBCKuLtKs","sx5Gld85a9","MaJQsBGaQY","fcJOyOxWIH","vLsmSIn3NS",
-"RBhp0zz4ZU","wiHrZVBjhz","KZamHK20wK","Yh1hFHfyNQ","pmeCdWaWsv","RmDcrdjsrv","6AFT0AXpwE","ix74rpWiOs","CIShGpWiOs","dmoS7HP433",
-"bgJAznlaBy","h1zcHzFgtB","EdBKcuoStw","zz4ZUuupzk","Yh1hFaez9y","W3VFH6AFT0","EdBKcFVMxo","8TxD70ao3l","Yf2Ecb29RJ","Gv3FqvkCHH",
-"TXQ0Z0YAGH","4dEz6Vprf2","rz7UtM3zXL","NhXdupT8wu","64s8NjzUqR","fcwDat98iW","0MR5XoGu6x","mz8gxZv7z0","iqv4kFVMxo","Q6Lixe6e4z",
-"48cHLuTacx","uupzkVIlwP","CK5W7rKDLJ","ru4UGGrDg7","zbIYYa00b5","VjCZq6q6L9","AmdQd9eoRc","29QAzQWxoT","In3NSqaofN","OUYuFdQ586",
-"WreyP0BmCy","OHaBzWmadA","FNYIMKASQ8","618DiC2Irc","Vprf25VZjS","d85a9taOXK","Fhtgl7lUXZ","nFqikpWiOs","lkMUAhE1Ql","FLsph9y4lw",
-"WPmlxZUnqt","zQt6QFjHXR","CIShGe6e4z","DG4sTrKDLJ","AmdQdbrhlQ","JKWYRpWiOs","xciqpB3qem","KsjRKJ2mQi","azIWpgjUTu","ZhwG1AmdQd",
-"l83Udpv0i7","NAFuw14FLR","uN6r3HP433","a00b5RkQke","EoToPhe9IA","45cIHVerEA","fFDrJjzUqR","7hyVvIKxdL","DQimpIn3NS","8FmFHReKEW",
-"VIlwPv2eC3","Yw2oUAkKTk","TXQ0ZNAFuw","6AFT0uoStw","AmdQdtlILt","HzZT87ku1p","b29RJWaim6","CNHmvsqVrf","uQIcz16lHc","0BmCyBpYhV",
-"MK07YlH1kt","LbRTHokgRi","IRh48jtn0X","GSQwjVBjhz","DQimpJRJQB","rz7UtZJTXH","hSSvQblLA9","L7cGcjfREu","8FmFHdQ586","GSQwjU3yw5",
-"Cp3mZv2eC3","5iGN5ZJTXH","Yw2oUv2eC3","atef2nnP8o","cmXIX5Mg9r","MojnPxReec","MaJQsQChxs","RBhp0VLTy6","soy9tNo0Qb","ReKEWpAhR1",
-"9y4lwfLNg8","0MR5X0h1b1","Cp3mZuZPqg","he9IA0YAGH","m4bxUGXdoH","i7WMQd7vjM","cShY2Mm8si","he9IAzbIYY","VNCPdNAFuw","oGu6xlm0pD",
-"WaWsvQChxs","FwEJzRBhp0","QClRLJRJQB","J2mQifqypy","s7MxkogLgc","No0QbZ4I1v","yluBxOUqFM","7fKYUAmdQd","FPfSE2Yz7E","t98iWKsjRK",
-"9XyT9tlILt","8hJdt9XyT9","aez9yd85a9","BGaQYX6Pin","nlaByB3qem","uQIczjfREu","zz4ZUpT8wu","v8yFN6q6L9","pv0i7KsjRK","guMb8t98iW",
-"CxVEf2ZHdk","EdBKcXflUq","qUJMdfcwDa","B3qemQssNC","iwzGktl72W","yvOMIBbwgA","SWfouCqqaD","y94nwdjsrv","2DREsaL6AJ","tvdkD2Yz7E",
-"HlUbFRxrsm","KZamHMaJQs","J2mQipv0i7","7hyVvtAOsr","YjB9t0BmCy","0BmCyWaim6","Nxx9V0ao3l","QbxXcnlaBy","zFgtBlCMxy","zQt6QKZamH",
-"0Wr5yi7WMQ","aez9yv8yFN","EdBKca00b5","VIlwP2Nslm","vkCHHIKxdL","mX2GEzFgtB","QssNCyEfy9","FLsphFPfSE","rKDLJYOfrY","5IhmGm4bxU",
-"9GXkXblLA9","fmIK1QssNC","Gv3Fq0Wr5y","CNHmvFNYIM","dQ586xReec","tAOsrHRxd8","dpe1vPb1pa","Chuy3QClRL","Ta8f6L7cGc","yvOMICqqaD",
-"14FLR2Nslm","xciqptaOXK","SbRYysx5Gl","TwanopiJSk","oVQp6k85Ae","5Drn0ru4UG","sqVrfSs0Zu","jS1ajHRxd8","vOqCEgf8rI","3otm6ZUnqt",
-"ZhwG15ZaEz","FLsphi7WMQ","fcJOyyEfy9","s7MxkQWxoT","prNT6mz8gx","7X3uydQ586","ru4UGLewvM","uJScXzqH0W","Pb1paU3yw5","W3VFHlweGy",
-"lweGyQClRL","NAFuwEdBKc","vOqCEsoy9t","ru4UGXflUq","Cp3mZOHaBz","iKqhr0PktI","KZamHCdyBV","SjskQ24ARF","pWiOsMmsIo","ReKEWQYxC0",
-"K4GS8rhl0J","tuDyS8cVD3","JkzUnUvlv4","l83UdIBe8k","D6rBybrhlQ","0MR5XF6PT2","6AFT0CqqaD","uupzkCqqaD","pWiOsZUnqt","2DREst59lR",
-"m4bxUsx5Gl","0Wr5y16lHc","i7WMQ5ZaEz","fLNg87lUXZ","gtCA54dEz6","RxrsmCxVEf","ThjNn5IhmG","lH1ktRpBQm","rhl0JRxrsm","uN6r3gf8rI",
-"0Wr5yuN6r3","EoToP9rlg9","WmadACp3mZ","EdBKccShY2","BGaQYQ6Lix","BGaQYprNT6","45cIHOUYuF","kZANme6e4z","FFDuiU3yw5","3weIFIBe8k",
-"lj07QPb1pa","B3qemuvf7A","uoStw0Kyfs","AOgEeG1RhS","0h1b1cmXIX","yvOMIcShY2","9y4lwix74r","jS1ajhe9IA","Yf2EcBpYhV","iKqhr2TRI7",
-"HfyNQXyPZN","lkMUAdhSuH","D6rByxciqp","gf8rIMkgy8","FLsphokgRi","VLTy6Gv3Fq","jSjS38cVD3","8RCUAUvlv4","7X3uyAIYUu","JkzUnCIShG",
-"AkKTk8RCUA","NhXduBFkb8","gIYvE2ZHdk","LewvMgjUTu","jzUqRv1Hln","YOfrYGWqqX","TCgPp5Mg9r","Yh1hFS77LH","FwEJz9GXkX","64s8NAOgEe",
-"brhlQguMb8","48cHLYjB9t","lkMUATa8f6","JKWYRix74r","ksJbyVIlwP","piJSkpT8wu","5VZjSIBe8k","9GXkXs4786","fLNg8s93Ml","Yw2oUkZANm",
-"VIlwP0MR5X","XflUqFwEJz","azIWpru4UG","M6qcG0PktI","2TRI7IBe8k","OUYuFJ2mQi","U3yw5yvOMI","wiHrZ24ARF","2hEEU5Namm","Mkgy8piJSk",
-"a00b5C2Irc","guMb82hEEU","CK5W7FNYIM","Mm8sisqVrf","9iGoTlj07Q","FwEJzF6PT2","Kr8ysNOHsz","qaofNuJScX","yvOMIMK07Y","t59lRL7cGc",
-"0PktIDLhzM","pT8wu4W0Tl","fcwDao8Uyd","Mkgy8U3yw5","8hJdtxciqp","n8pJ9hYBCK","DQimpK20wK","CNHmvGWqqX","16lHc5Drn0","LewvMHlUbF",
-"KASQ8MmsIo","Waim6fcwDa","07n1c16lHc","tuDySFFDui","nlaBy5ZaEz","i7WMQrz7Ut","jzUqRtvdkD","vLsmSU3yw5","v1HlnsuY4x","WaWsvhSSvQ",
-"580YDgf8rI","b29RJ9eoRc","OxWIHYh1hF","No0QbFLsph","gtCA5xReec","FLsphuAWyp","uoStwvLsmS","tvdkDfcwDa","a00b5HlUbF","iqv4kZ4I1v",
-"yvOMIWaim6","CdyBVuvf7A","taOXKFjHXR","HlUbFtjQxs","lkMUAvLsmS","JJs5m07n1c","suY4xprNT6","lm0pD64s8N","GWqqXZ4I1v","pAhR1lweGy",
-"FNYIMgdQsS","xReeciqv4k","ru4UGn1pmO","5ZaEzMK07Y","2TRI7HfyNQ","Nxx9VlViBv","uZPqglCMxy","7hyVvGrDg7","MojnPru4UG","GSQwj618Di",
-"ZuDtD8RCUA","48cHLfaHir","jfREuSWfou","rz7UtOz8yZ","2TRI7FLsph","pvgjSuZPqg","fFDrJMojnP","8hJdtM6qcG","iB08lG1RhS","t98iWOUqFM",
-"RBhp0ydG8U","IBe8ktl72W","OUYuFJIqXi","2Yz7E2ZHdk","2DREsRACuj","I7p2agtCA5","wiHrZ1j5L8","n1pmOMm8si","BbwgAuLtKs","2NslmhE1Ql",
-"Zv7z0Chuy3","QbxXcXyPZN","ciuWzd85a9","lH1ktxciqp","jS1ajNAFuw","OUqFMhYBCK","Ul4a1BpYhV","2ZHdkxReec","D6rByEOE1o","TXQ0ZWPmlx",
-"DQimpGXdoH","VjCZqtl72W","CNHmv5iGN5","blLA9Uvlv4","AXpwE5Namm","EOE1o580YD","k85AeLewvM","BFkb8wiHrZ","FhtglRACuj","0h1b1HfyNQ",
-"WPmlxxXTI4","rhl0JOxWIH","EdBKcW3VFH","FNYIMhSSvQ","24ARFtjQxs","HP433guMb8","Kr8ysQworu","7Ow5CMojnP","8cVD3XflUq","uoStwa00b5",
-"XflUqdpe1v","ZzJHWv2eC3","uupzkTXQ0Z","xReec29QAz","uAWypTXQ0Z","O3iyQ1LB1L","vOqCERkQke","y94nwl83Ud","t98iWzHF1q","JKWYRWaWsv",
-"qQxHP7Ow5C","AmdQdG1RhS","PYBf4IjTwP","5nmWvhE1Ql","pAhR1NOHsz","Zv7z0Mkgy8","NcICAn8pJ9","5iGN5In3NS","FLsphuLtKs","dpe1vsoy9t",
-"gtCA5lpF6W","MmsIo5Drn0","QClRL3weIF","jS1aj9rlg9","cL0aEyEfy9","AkKTkG1RhS","faHirS2Dfu","Pb1paVprf2","ThjNnNo0Qb","nnP8oFPfSE",
-"5iGN5uvf7A","djsrvnFqik","0PktICIShG","FNYIM8U2nU","CNHmvRACuj","yToGWSs0Zu","7hyVvgf8rI","xXTI4CqqaD","fFDrJ45cIH","W7cTs8TxD7",
-"K20wK8FmFH","RxrsmoVQp6","I7p2aLewvM","8TxD7uTacx","zmLYDBpYhV","iqv4kGWqqX","oQ87ri3pyd","OHaBz1v5hH","45cIHEOE1o","AOgEeIRh48",
-"ZhwG1nFqik","K20wKpiJSk","fqypyZJTXH","JIqXiJ2mQi","5drc6Z4I1v","CNHmvQYxC0","tuDySChuy3","ulk41xXTI4","m4bxUYf2Ec","uTacxL7cGc",
-"Nxx9VFwEJz","SjskQGSQwj","ni2v1yEfy9","F6PT2xReec","5Mg9rGWqqX","LDk6fNOHsz","fLNg8JRJQB","dpe1vVprf2","CNHmv9GXkX","kZANmU3yw5",
-"FPfSEYh1hF","iqv4k29QAz","aL6AJWaim6","0KyfspT8wu","NcICAo8Uyd","oQ87rhE1Ql","ZhwG1SbRYy","m4bxU5ZaEz","atef2YjB9t","VerEAIn3NS",
-"BCxeCd7vjM","i7WMQ3weIF","RkQkeYh1hF","fLNg807n1c","ThjNn5drc6","tuDyS5Namm","F6PT2RACuj","8hJdtlViBv","XflUqBbwgA","SmGzv24ARF",
-"uQIczgdQsS","YOfrYHfyNQ","5VZjSguMb8","e6e4zyluBx","yofH3Y1mC0","uTacxVIlwP","jSjS3LDk6f","0MR5XC2Irc","bZLvSJJs5m","EoToPjS1aj",
-"zY1GYSmGzv","RACujYf2Ec","jfREuMm8si","euZA5Kr8ys","S77LHKr8ys","7Ow5CyvOMI","8RCUAJRJQB","QssNC4W0Tl","dpe1vMK07Y","GWqqXhUTw7",
-"QChxsogLgc","M6qcGogLgc","tjQxs7X3uy","FNYIM8xEKz","Kr8ysoVQp6","QChxs2TRI7","zHF1qSjskQ","1v5hHdhSuH","FVMxo2Nslm","UmaEvuJScX",
-"aDGtSReKEW","FnPFBIn3NS","Dz1R3blLA9","oQ87rtuDyS","OUqFMGrDg7","4QMc9FwEJz","zQt6QQChxs","4dEz6iB08l","Mm8si2DREs","GWqqXix74r",
-"M6qcGcmXIX","uupzk1v5hH","Yh1hFn1pmO","mz8gxCdyBV","YOfrY7lUXZ","YjB9tYOfrY","yofH3Twano","JJs5mKASQ8","iwzGkru4UG","FFDuituDyS",
-"GrDg7gf8rI","qaofNjeskS","4dEz68cVD3","lCMxyy94nw","RpBQmogLgc","taOXKMGlTF","lweGy5Drn0","MaJQsVBjhz","cmXIXFnPFB","3otm6LbRTH",
-"FwEJzpT8wu","VLTy6t98iW","VBjhzs7Mxk","zHF1qv8yFN","1LB1LS2Dfu","0PktIokgRi","SbRYybgJAz","jfREugdQsS","zqH0WpvgjS","FGzgp4QMc9",
-"9iGoTeuZA5","WPmlxVNCPd","XflUqGrDg7","FFDuiFLsph","prNT6GWqqX","J2mQik85Ae","7hyVvtlILt","GSQwjh1zcH","S2DfuqQxHP","RBhp0ix74r",
-"2DREsIRh48","uZPqgG1RhS","5drc61j5L8","Yh1hFpFrrl","RACujuPX7G","W3VFHTXQ0Z","Oz8yZ07n1c","FNYIMkB5nP","16lHcC2Irc","VIlwPJJs5m",
-"dpe1vix74r","ZUnqtjeskS","jS1ajt98iW","jSjS3FNYIM","tvdkDsx5Gl","QWxoTogLgc","n1pmOlkMUA","Ss0ZuVBjhz","SWfouQ6Lix","iKqhr9iGoT",
-"LDk6fhe9IA","Ss0ZuuPX7G","POUYSTwano","yvOMIpvgjS","FjHXRzHF1q","pv0i7zHF1q","RkQkeFnPFB","FjHXR2Nslm","soy9tZ4I1v","B3qema00b5",
-"tlILtRkQke","AOgEeZv7z0","uN6r3IRh48","Uvlv4RkQke","FxX9qVNCPd","29QAzThjNn","s4786blLA9","5Nammv2eC3","XflUq8xEKz","D6rBygtCA5",
-"W3VFH4QMc9","yofH3Q6Lix","cL0aEfmIK1","uupzkX6Pin","oVQp6ni2v1","VNCPdJJs5m","FcWrWokgRi","Z4I1vhYBCK","Dz1R3StlDJ","AXpwEIn3NS",
-"Zv7z0cL0aE","0Wr5yS2Dfu","rhl0JcQOnv","FFDuiOUYuF","DQimp0h1b1","tuDyS5Mg9r","Vprf2Zv7z0","yToGW14FLR","tuDyS14FLR","QChxsvLsmS",
-"29QAzo8Uyd","uN6r3RBhp0","djsrvoGu6x","1LB1LyluBx","Q6LixQ6hMC","RACujCp3mZ","rz7Ut6q6L9","blLA9FPfSE","brhlQs7Mxk","VjCZqAIYUu",
-"QbxXcHfyNQ","M3zXLlCMxy","pT8wuhe9IA","7hyVvVerEA","7hyVvdmoS7","jfREuPOUYS","Cfgr36q6L9","DcpWBUlU3M","U3yw5zmLYD","7X3uylsQGo",
-"MojnPkZANm","m4bxU9rlg9","yToGWokgRi","CxVEfKsjRK","Ta8f67hyVv","3weIFMmKGJ","IjTwPEdBKc","ksJbypiJSk","FVMxozQt6Q","5drc6C2Irc",
-"618Di5drc6","s7Mxk7fsYM","fqypyuJScX","MojnPYw2oU","ogLgc8U2nU","QYxC0FwEJz","pmeCd6AFT0","ru4UGlj07Q","5drc68U2nU","cmXIXVIlwP",
-"e6e4zxXTI4","uAWypguMb8","SjskQNOHsz","pT8wum4bxU","J2mQiThjNn","RsQUqRBhp0","soy9t16lHc","iKqhrIn3NS","pWiOsJIqXi","9GXkXaez9y",
-"ix74r0Kyfs","SmGzvNAFuw","AmdQdUvlv4","prNT67fsYM","Ta8f6J2mQi","FFDuiguMb8","Yh1hF5nmWv","AXpwE7hyVv","8xEKzrhl0J","L7cGcQYxC0",
-"K4GS8FnPFB","cmXIXa00b5","fcJOy2Yz7E","6AFT0cQOnv","iB08lpiJSk","QChxsZuDtD","7fsYMRmDcr","IRh48618Di","uZPqgVNCPd","DG4sTFjHXR",
-"UlU3MguMb8","atef2Pb1pa","azIWpTXQ0Z","2TRI7vLsmS","RzaZAReKEW","Uvlv4euZA5","YjB9tNhXdu","AgJHQzqH0W","RzaZACdyBV","iB08lSjskQ",
-"7lUXZpv0i7","VIlwPS2Dfu","8xEKz07n1c","3otm6suY4x","vkCHHlH1kt","FjHXRTwano","HlUbFsoy9t","5nmWvix74r","uJScXOUYuF","45cIHOHaBz",
-"POUYSEOE1o","Pb1padhSuH","TCgPpOUYuF","Cfgr3wDajX","pv0i7JRJQB","WPmlxQbxXc","7Ow5CCIShG","5iGN58U2nU","pv0i7EoToP","vOqCEkB5nP",
-"fFDrJulk41","RmDcrCfgr3","Qworue6e4z","Twanoaez9y","zmLYDru4UG","aDGtS4QMc9","0YAGH6AFT0","tlILt0ao3l","pAhR1FFDui","0Wr5yuoStw",
-"NAFuw5IhmG","ThjNnlH1kt","s7MxkMGlTF","o8UydGXdoH","EOE1oFxX9q","DG4sTzFgtB","rKDLJd85a9","sqVrfhSSvQ","55rfBOxWIH","Dz1R3D6rBy",
-"zHF1ql83Ud","azIWpwDajX","No0QblsQGo","M3zXLi3pyd","fmIK1CdyBV","b29RJReKEW","1j5L8jzUqR","rKDLJJXljW","ogLgcMGlTF","BpYhVJ2mQi",
-"UlU3MTXQ0Z","IRh482Yz7E","VIlwPWMiS3","pT8wulweGy","8TxD7FwEJz","ReKEWaez9y","45cIHLDk6f","W7cTsfcwDa","4QMc9ThjNn","cL0aEo8Uyd",
-"Pb1paHlUbF","FGzgpSWfou","U3yw5ix74r","uoStwhE1Ql","UlU3MBGaQY","s4786SjskQ","aDGtSi7WMQ","VBjhzGWqqX","POUYSaL6AJ","dhSuHqaofN",
-"Gv3Fq0BmCy","nlaByG1RhS","nFqikSWfou","yofH3CNHmv","CIShGECMvU","FnPFBChuy3","3weIF1v5hH","FLsphMezSW","n8pJ9QssNC","n1pmOTXQ0Z",
-"14FLR14FLR","ZUnqtl83Ud","P6bcgFLsph","IKxdLjfREu","48cHLyluBx","i7WMQ2ZHdk","I7p2aoQ87r","v1HlnK4GS8","WmadAfLNg8","n8pJ94dEz6",
-"t59lR5drc6","OUqFMhE1Ql","Yw2oUG1RhS","0YAGHtvdkD","MmKGJEoToP","uLtKsvkCHH","8xEKzydG8U","ni2v10h1b1","BGaQYZhwG1","JJs5mZUnqt",
-"vLsmS1v5hH","PYBf4JJs5m","zqH0WYh1hF","S2DfupAhR1","CNHmvJXljW","FhtglC2Irc","gdQsSRBhp0","6q6L9dhSuH","fLNg8SmGzv","n8pJ9tjQxs",
-"Mm8sin8pJ9","0ao3lwDajX","CIShGaFFss","PYBf4tl72W","Yw2oUY1mC0","POUYS2Nslm","9rlg9FnPFB","xReecxXTI4","pWiOszFgtB","xciqpiB08l",
-"Oz8yZ4QMc9","RmDcra00b5","fLNg8AmdQd","X6PinEOE1o","D6rByrz7Ut","HlUbFtAOsr","pT8wu618Di","S2DfuZJTXH","gf8rI5VZjS","F6PT2EOE1o",
-"tlILtzQt6Q","Q6hMCOUYuF","Twano64s8N","K20wKPYBf4","2TRI7AIYUu","ix74rS2Dfu","dpe1vL7cGc","pv0i7GrDg7","Cp3mZzQt6Q","ydG8UQYxC0",
-"v1Hln3weIF","AXpwEciuWz","3weIFWDVWJ","t59lRAgJHQ","5iGN5Z4I1v","s4786Pb1pa","piJSkxXTI4","pT8wuciuWz","AgJHQVIlwP","IKxdLjS1aj",
-"vOqCEFhtgl","2NslmhUTw7","lCMxyhE1Ql","K4GS8Kr8ys","16lHcMm8si","uLtKskB5nP","yToGWdpe1v","taOXKiwzGk","VLTy6NAFuw","5IhmGAmdQd",
-"6q6L99eoRc","Pb1paatef2","WPmlxydG8U","StlDJ2Yz7E","iKqhrFhtgl","7X3uyJkzUn","n1pmO7Ow5C","HfyNQx3LDe","ZhwG13otm6","TwanoSmGzv",
-"F6PT2HfyNQ","UlU3MhE1Ql","UlU3MdQ586","FVMxoksJby","Gv3FqEOE1o","DcpWBYOfrY","rhl0J0Kyfs","o8UydIKxdL","ni2v1yvOMI","he9IAlViBv",
-"BFkb89y4lw","FLsphThjNn","7Ow5Cy94nw","bgJAz0Wr5y","CxVEflkMUA","0KyfsydG8U","FPfSEzHF1q","8U2nU8TxD7","tvdkDHlUbF","MmsIo5iGN5",
-"uvf7AC2Irc","XyPZNQ6Lix","rhl0JPYBf4","Chuy30Kyfs","KsjRKP6bcg","i3pyd9GXkX","aL6AJRzaZA","lpF6WyToGW","L7cGcEdBKc","RsQUqQChxs",
-"7Ow5CdQ586","uoStwdpe1v","3otm64dEz6","ciuWztvdkD","Cfgr3d85a9","M3zXLRxrsm","qQxHP8hJdt","IjTwP2Yz7E","MaJQsuZPqg","ECMvUdmoS7",
-"Kr8yszQt6Q","AIYUui3pyd","ZzJHWzmLYD","J2mQilsQGo","Yw2oUgtCA5","7fKYUI7p2a","7lUXZmX2GE","mz8gxRxrsm","vkCHHUl4a1","djsrvlweGy",
-"QWxoTNxx9V","DG4sT5Mg9r","ReKEW07n1c","MojnPAOgEe","jeskSRACuj","oVQp66AFT0","8xEKzzqH0W","FnPFBuPX7G","FxX9qBGaQY","DcpWB0Kyfs",
-"Mm8siyofH3","tAOsr0BmCy","TwanoYjB9t","oQ87rOxWIH","pv0i7xXTI4","jiVBPlsQGo","5nmWvZUnqt","7hyVvReKEW","YOfrYix74r","QChxsP6bcg",
-"v2eC3mz8gx","kZANmcmXIX","n1pmOqaofN","gtCA5VjCZq","aDGtSJ2mQi","n8pJ9uupzk","8TxD7WPmlx","SbRYyRpBQm","vOqCEYh1hF","hSSvQtjQxs",
-"bZLvSQWxoT","WMiS3ogLgc","5drc6RpBQm","8xEKzVerEA","v2eC324ARF","a00b5QClRL","8TxD7JKWYR","lH1ktlkMUA","Nxx9V4QMc9","LbRTHJXljW",
-"HfyNQpmeCd","W3VFHJJs5m","yofH3fLNg8","aez9y2ZHdk","ThjNn7fsYM","zqH0WzbIYY","0h1b1i7WMQ","l83UdFnPFB","DcpWBUmaEv","fcJOyMmKGJ",
-"0h1b1OHaBz","nnP8oyofH3","0PktI8RCUA","xReecjSjS3","ZJTXHHzZT8","Oz8yZyEfy9","suY4xZhwG1","iwzGklsQGo","FFDuiB3qem","RACujQssNC",
-"AIYUuSWfou","8xEKz8hJdt","Z4I1vaez9y","55rfBs4786","Ss0Zupv0i7","K4GS8618Di","C2Ircuupzk","jiVBPcQOnv","uJScX5VZjS","ix74r0h1b1",
-"JIqXigtCA5","d85a9G1RhS","Z4I1v2Yz7E","b29RJC2Irc","7fsYMh1zcH","CK5W7P6bcg","aDGtSdpe1v","QChxsmX2GE","W3VFHgIYvE","fLNg8yluBx",
-"pWiOsWDVWJ","VIlwPGWqqX","Nxx9Vdpe1v","CK5W7HRxd8","ksJbyQChxs","hUTw7blLA9","i3pydlXFOB","NOHszAXpwE","o8UydfcwDa","AkKTkRzaZA",
-"45cIHFVMxo","hSSvQDQimp","lm0pDrhl0J","rz7Utdjsrv","45cIHS77LH","K20wKJIqXi","v2eC3soy9t","0MR5XK20wK","pT8wudhSuH","2Yz7ELDk6f",
-"DQimpcShY2","xXTI4wDajX","D6rBy9iGoT","F6PT2KZamH","0Kyfs7X3uy","07n1cHP433","1j5L8aFFss","M6qcGuAWyp","NOHszOUYuF","AmdQdoVQp6",
-"S2DfumX2GE","KZamH8FmFH","TXQ0ZiwzGk","lj07QblLA9","lj07Q1LB1L","QClRLL7cGc","iB08lVNCPd","aFFssQ6hMC","BGaQYZUnqt","QClRLdmoS7",
-"ZhwG1brhlQ","BbwgAW7cTs","QnJ1StaOXK","uvf7AdhSuH","2hEEUwDajX","HP4333weIF","AXpwEcmXIX","Twanoh1zcH","NcICA9eoRc","VjCZqm4bxU",
-"s93MlJXljW","d85a9xXTI4","Yf2EcoQ87r","euZA5AIYUu","DG4sTs4786","yofH3HzZT8","vOqCEgdQsS","GXdoHgtCA5","8U2nUhSSvQ","VjCZqLewvM",
-"5ZaEzx3LDe","GXdoHMmKGJ","QClRLoVQp6","W7cTszbIYY","9y4lwIjTwP","S2DfuAIYUu","I7p2aatef2","ydG8UDLhzM","hSSvQBbwgA","0KyfsMm8si",
-"AOgEeNcICA","gjUTu4QMc9","Uvlv4S2Dfu","7X3uyMm8si","uPX7GTwano","euZA5MGlTF","ogLgcpvgjS","m4bxUQWxoT","piJSkaez9y","yofH3GXdoH",
-"6AFT07lUXZ","lweGyiB08l","kB5nPD6rBy","9eoRcyofH3","XflUqyEfy9","ZhwG1Yf2Ec","n1pmOnnP8o","FLsphOxWIH","qUJMdCK5W7","MojnPCfgr3",
-"i7WMQ0YAGH","h1zcH0Wr5y","jtn0X8U2nU","LewvMtAOsr","FLsphvOqCE","MmKGJzY1GY","7fsYMs93Ml","lweGytl72W","0PktIqUJMd","UmaEv1j5L8",
-"wiHrZCqqaD","DG4sTNxx9V","VLTy6HfyNQ","rhl0JOUYuF","h1zcHzmLYD","nnP8oRmDcr","DLhzMYf2Ec","ECMvUb29RJ","DQimpS2Dfu","azIWpkZANm",
-"wiHrZi3pyd","QChxshe9IA","v8yFNcShY2","piJSkjtn0X","45cIHWreyP","Uvlv4DLhzM","NhXduSmGzv","DQimpuN6r3","9eoRcPYBf4","tAOsrlH1kt",
-"gjUTuDcpWB","Mkgy8JkzUn","7X3uyuQIcz","2NslmF6PT2","gtCA5jtn0X","Nxx9VCK5W7","5NammHzZT8","ulk41CxVEf","RsQUqnnP8o","uN6r3pvgjS",
-"BpYhVCqqaD","Cfgr3yToGW","VNCPdKr8ys","ZUnqthSSvQ","8FmFHZzJHW","brhlQDQimp","HlUbF14FLR","8RCUAni2v1","hUTw7jtn0X","IjTwPuZPqg",
-"qQxHPzz4ZU","he9IAQssNC","t59lR2DREs","2TRI75IhmG","8hJdt2Nslm","YOfrYBFkb8","X6PinVjCZq","jeskSeuZA5","sqVrfVIlwP","0h1b1U3yw5",
-"VBjhz24ARF","Mkgy8WaWsv","HzZT84W0Tl","pv0i7euZA5","ix74rQworu","AOgEewiHrZ","XyPZNtAOsr","lCMxyn8pJ9","zY1GYCqqaD","FGzgpulk41",
-"WMiS3UmaEv","mX2GEWPmlx","ECMvU580YD","gIYvEcQOnv","pT8wuQnJ1S","yluBxsqVrf","I7p2auupzk","48cHL5Drn0","EoToPAmdQd","7X3uyChuy3",
-"vLsmSksJby","m4bxUjSjS3","Ul4a1iwzGk","guMb807n1c","pmeCdmX2GE","oQ87rEoToP","AgJHQd7vjM","MK07YRpBQm","uLtKsECMvU","VNCPdbgJAz",
-"VNCPdBGaQY","DLhzMCxVEf","B3qemfmIK1","CNHmvtvdkD","7Ow5CbgJAz","HzZT8v2eC3","45cIH0MR5X","GrDg7ru4UG","gdQsSaL6AJ","vOqCEKsjRK",
-"MaJQsuTacx","CNHmv2hEEU","IjTwPvLsmS","NAFuwsqVrf","yEfy9VNCPd","0YAGHQYxC0","nlaBy7hyVv","vkCHHDcpWB","WDVWJjfREu","BpYhVFLsph",
-"14FLR2ZHdk","ECMvUJJs5m","zmLYDO3iyQ","vOqCEydG8U","oVQp6lH1kt","D6rByZJTXH","VIlwPS77LH","9y4lwfFDrJ","XflUq48cHL","5Mg9rtjQxs",
-"CxVEfBGaQY","uN6r3hUTw7","Vprf2Cp3mZ","14FLRYh1hF","ZUnqt7hyVv","s4786n8pJ9","8xEKz7Ow5C","AmdQdzY1GY","6AFT0CdyBV","taOXKoGu6x",
-"HRxd8cmXIX","B3qemv8yFN","zY1GYDG4sT","jfREu4dEz6","hSSvQ8FmFH","VjCZqUl4a1","55rfBfFDrJ","suY4x580YD","pmeCdHfyNQ","jtn0XMK07Y",
-"pv0i7guMb8","pvgjSAkKTk","XyPZNnlaBy","zqH0WfcJOy","ix74r0Wr5y","In3NSM6qcG","b29RJY1mC0","oGu6xaFFss","ECMvUVjCZq","8cVD3cQOnv",
-"48cHLBpYhV","FNYIMuoStw","CK5W7ix74r","v1HlniKqhr","WreyPRzaZA","UmaEvMaJQs","pWiOs1LB1L","xciqpxReec","IRh48FxX9q","C2Irc5Mg9r",
-"fmIK1jzUqR","fFDrJTXQ0Z","yEfy9cQOnv","yEfy9k85Ae","X6PinW7cTs","GWqqXQWxoT","CxVEfDLhzM","FxX9qUlU3M","WreyPWMiS3","jSjS3jiVBP",
-"ZUnqtKr8ys","X6Pin55rfB","gf8rIpT8wu","Nxx9VXyPZN","tlILtdQ586","7fsYMjSjS3","x3LDeDcpWB","ru4UGokgRi","zFgtBkB5nP","1j5L8JXljW",
-"CK5W7hE1Ql","Nxx9Vdjsrv","BpYhVIBe8k","TCgPpjtn0X","xXTI4hSSvQ","hUTw7s93Ml","Ss0ZuMK07Y","Q6hMCgtCA5","AgJHQ5drc6","D6rByP6bcg",
-"jzUqRtl72W","blLA9UlU3M","FhtglCxVEf","jiVBPX6Pin","I7p2ahSSvQ","Waim6OUqFM","h1zcHuAWyp","48cHL8FmFH","Yw2oU7fsYM","ksJbyGWqqX",
-"n8pJ9FcWrW","hi5X7yofH3","aDGtSv2eC3","ThjNnfqypy","aFFssCqqaD","AmdQdYjB9t","LDk6ftvdkD","RpBQmPb1pa","v2eC3VerEA","dpe1v2DREs",
-"aez9yaDGtS","0ao3lmz8gx","VIlwPZuDtD","Y1mC0Cp3mZ","taOXKqUJMd","fmIK1cQOnv","aFFssblLA9","CNHmvxReec","0PktIPYBf4","BCxeCi3pyd",
-"Ul4a1RpBQm","fmIK1x3LDe","aez9y7fsYM","FGzgpK20wK","J2mQi7fKYU","K20wKwiHrZ","ru4UG55rfB","lsQGoQYxC0","aDGtSUlU3M","X6Pinuupzk",
-"Ul4a1l83Ud","zbIYYOUYuF","FnPFBMezSW","y94nwaez9y","L7cGcn8pJ9","n8pJ916lHc","WmadArz7Ut","UmaEvJkzUn","kZANmxReec","ZhwG1oVQp6",
-"Nxx9VfLNg8","ZUnqtFxX9q","i3pydXyPZN","ksJbyD6rBy","ZJTXHhe9IA","VBjhzB3qem","VerEA7lUXZ","3otm6O3iyQ","XflUqs93Ml","nnP8oJKWYR",
-"MK07YJKWYR","jSjS38RCUA","MaJQs7fKYU","C2IrcYw2oU","fLNg88cVD3","hYBCKpWiOs","BFkb8he9IA","tvdkDbrhlQ","lm0pDb29RJ","QChxsSWfou",
-"lm0pDfcwDa","d85a9lViBv","5Drn0okgRi","lH1ktRmDcr","3weIFThjNn","HP433JJs5m","x3LDe2hEEU","Chuy3Fhtgl","OUYuFtlILt","2DREsSmGzv",
-"5IhmGCdyBV","KASQ8mX2GE","5Drn07fsYM","y94nw5nmWv","uTacxprNT6","NcICA4W0Tl","2ZHdk1j5L8","tl72WhUTw7","lsQGowDajX","sx5GltaOXK",
-"rKDLJgIYvE","U3yw51j5L8","XyPZNIKxdL","vOqCEzmLYD","8hJdtn8pJ9","uTacxazIWp","VLTy6CIShG","C2IrclsQGo","xciqpFcWrW","dQ586oQ87r",
-"CIShGlweGy","RsQUqvOqCE","7ku1pMaJQs","VIlwP5iGN5","JJs5mB3qem","uZPqgW7cTs","hSSvQLewvM","EoToPksJby","5Drn016lHc","StlDJmX2GE",
-"tuDySkZANm","BGaQY5Drn0","pAhR1prNT6","9XyT9OxWIH","I7p2ahe9IA","k85AeqUJMd","vkCHH9GXkX","iB08lSWfou","pmeCd5Mg9r","mX2GErhl0J",
-"7fsYMQClRL","7ku1p64s8N","cmXIXW3VFH","YjB9tfcwDa","Gv3Fqe6e4z","hYBCKyToGW","Twano8cVD3","ZuDtDQChxs","lkMUA8cVD3","sqVrfguMb8",
-"Ta8f69y4lw","pvgjS2Yz7E","9rlg9blLA9","atef2LewvM","vkCHHJRJQB","yvOMIGSQwj","cL0aEhi5X7","v1Hln5IhmG","rKDLJ9XyT9","aDGtSzHF1q",
-"Mkgy8In3NS","Twanohi5X7","yEfy9ThjNn","3weIFn8pJ9","hi5X7FnPFB","ulk4114FLR","x3LDeWPmlx","GrDg7xXTI4","9y4lwaDGtS","blLA9Twano",
-"VBjhzv2eC3","lweGyxReec","jSjS3uupzk","8xEKzFnPFB","iqv4klkMUA","KsjRKBFkb8","OxWIHyToGW","bgJAzguMb8","Yf2EcK4GS8","Kr8yszz4ZU",
-"QssNC6q6L9","8hJdtC2Irc","O3iyQzbIYY","dpe1vzqH0W","ZJTXHUlU3M","L7cGclm0pD","l83UdFPfSE","FPfSEDQimp","pv0i73otm6","IKxdLgf8rI",
-"DG4sTIKxdL","MmsIoaFFss","piJSkJkzUn","Uvlv4VNCPd","LewvMCqqaD","nlaBygtCA5","yluBxdQ586","K4GS8Ss0Zu","9rlg9Cfgr3","cQOnv8cVD3",
-"POUYSQssNC","YjB9t2DREs","fcJOytlILt","SbRYyxXTI4","QWxoTKr8ys","16lHcFFDui","qaofNMm8si","EdBKcpv0i7","JJs5mlViBv","lpF6WQChxs",
-"5ZaEzU3yw5","ru4UGP6bcg","B3qemZJTXH","bgJAznnP8o","Fhtglb29RJ","aL6AJi3pyd","RpBQm55rfB","prNT6iB08l","MmsIoO3iyQ","bZLvSuZPqg",
-"y94nwEOE1o","lm0pDNcICA","45cIH7hyVv","yEfy91v5hH","xXTI4VBjhz","5Namm5iGN5","fmIK1ni2v1","lsQGolm0pD","QChxsFjHXR","i7WMQAIYUu",
-"45cIHtAOsr","XflUqIjTwP","Chuy3zqH0W","14FLRrKDLJ","Ul4a1xXTI4","uZPqgsuY4x","CK5W75iGN5","Gv3Fq0ao3l","7X3uy8hJdt","b29RJpvgjS",
-"RkQkefaHir","PYBf4fmIK1","BGaQYCqqaD","okgRiM3zXL","QChxsFnPFB","5NammqaofN","pFrrlCdyBV","5VZjSDz1R3","fqypyTwano","45cIHNxx9V",
-"VerEAoVQp6","aDGtSs4786","hUTw7WPmlx","5VZjSo8Uyd","brhlQVLTy6","JRJQB3otm6","4QMc9AgJHQ","v8yFNUl4a1","AIYUugjUTu","X6PinFhtgl",
-"8cVD3NAFuw","29QAzFPfSE","9XyT9DcpWB","B3qemvkCHH","16lHcsqVrf","s93MltlILt","ix74rSWfou","0BmCyRsQUq","a00b5SjskQ","GSQwjZhwG1",
-"nlaByAXpwE","ix74r29QAz","580YDVLTy6","rKDLJeuZA5","PYBf4M3zXL","yvOMIoVQp6","1LB1LZ4I1v","fcwDaOUqFM","7fKYU55rfB","oQ87r7X3uy",
-"bgJAzQ6Lix","wDajXM6qcG","UlU3MzbIYY","pWiOsuQIcz","vOqCE580YD","OHaBz6AFT0","piJSkW3VFH","Oz8yZDQimp","s4786sqVrf","KASQ8AgJHQ",
-"DcpWBQWxoT","v2eC3FPfSE","2Yz7EwDajX","MaJQsYw2oU","nFqikogLgc","MGlTFfcJOy","kB5nPZzJHW","MmsIofLNg8","vkCHHzbIYY","Pb1paRBhp0",
-"FhtglY1mC0","XflUqQssNC","uJScXvOqCE","pmeCdBCxeC","uQIcz9y4lw","GrDg70ao3l","n1pmOP6bcg","07n1cv1Hln","guMb87fsYM","FPfSE8hJdt",
-"6q6L9uvf7A","t59lRMaJQs","Z4I1vReKEW","OHaBz29QAz","l83UdvOqCE","QChxsgIYvE","X6Pine6e4z","VerEAiKqhr","WPmlxhSSvQ","hi5X7n1pmO",
-"7hyVvB3qem","Mm8si6q6L9","7fKYU8cVD3","d7vjMzHF1q","BpYhVi3pyd","iKqhrECMvU","M6qcGS77LH","8xEKzksJby","cQOnv5drc6","VBjhzblLA9",
-"YjB9t3otm6","Dz1R3MGlTF","POUYS8RCUA","GrDg7uPX7G","s7MxkiwzGk","ZzJHWb29RJ","2TRI7SbRYy","IjTwPt59lR","hSSvQVIlwP","fLNg845cIH",
-"9y4lwBFkb8","nnP8o5ZaEz","0BmCy7lUXZ","CNHmvqQxHP","xXTI42TRI7","FFDuiiB08l","HlUbFuN6r3","VLTy67lUXZ","okgRi2ZHdk","fmIK1jtn0X",
-"Nxx9Vi7WMQ","CNHmv5VZjS","tAOsrpv0i7","OUqFMQChxs","tl72WgjUTu","1v5hHOxWIH","kZANmVBjhz","vOqCE5Drn0","n8pJ9LbRTH","2hEEUpFrrl",
-"I7p2ad7vjM","FPfSEWDVWJ","FLsphkB5nP","Cp3mZo8Uyd","C2IrcYjB9t","9GXkXChuy3","v1HlnjS1aj","soy9ttl72W","djsrvGv3Fq","KASQ8zY1GY",
-"fFDrJ5nmWv","LDk6f64s8N","7hyVvY1mC0","QWxoTIjTwP","ECMvUL7cGc","s4786hi5X7","s7MxkCK5W7","WreyPHfyNQ","8cVD3U3yw5","Q6hMCRBhp0",
-"EOE1ok85Ae","bZLvSCxVEf","B3qemBGaQY","fcwDauLtKs","uTacxBbwgA","vOqCE5VZjS","StlDJrhl0J","FPfSE0h1b1","mX2GEGrDg7","FxX9qt59lR",
-"MezSW7X3uy","v2eC3MojnP","lsQGojS1aj","CdyBVix74r","iKqhrAXpwE","oGu6xOUYuF","L7cGcKr8ys","2ZHdkJXljW","QnJ1SuLtKs","mX2GE45cIH",
-"lweGyyEfy9","M3zXLOxWIH","LDk6fWaWsv","U3yw5Vprf2","5Mg9rAmdQd","WreyPprNT6","FcWrWlm0pD","W3VFHlViBv","prNT6QYxC0","uvf7A5iGN5",
-"9y4lwGSQwj","lpF6WZUnqt","yvOMI55rfB","hi5X7yToGW","VjCZqzz4ZU","LewvMEOE1o","jiVBPSWfou","iqv4kfaHir","UmaEvuPX7G","O3iyQuvf7A",
-"ThjNnl83Ud","B3qemokgRi","iKqhrmX2GE","K4GS8TXQ0Z","sqVrfOUYuF","BFkb8BCxeC","fmIK1KASQ8","8U2nUWMiS3","d7vjMvLsmS","VerEAxciqp",
-"s93Ml9XyT9","pv0i7taOXK","zmLYDcQOnv","KZamH29QAz","qaofNRBhp0","HzZT8fmIK1","AOgEe1j5L8","brhlQ7hyVv","P6bcgIRh48","24ARFe6e4z",
-"0KyfsS2Dfu","5nmWvx3LDe","ciuWzt98iW","aL6AJrz7Ut","xXTI4FwEJz","HRxd8Cp3mZ","29QAzd7vjM","sx5Gl0PktI","0h1b1S2Dfu","7fKYUK20wK",
-"2TRI7ZzJHW","OxWIHHlUbF","mz8gxSjskQ","Yw2oUCNHmv","nnP8o2hEEU","JJs5m5nmWv","9eoRc4QMc9","6q6L9G1RhS","7ku1pWreyP","pFrrlFFDui",
-"pT8wuMK07Y","zqH0WM6qcG","s7MxkiKqhr","EOE1oLDk6f","5Namm4W0Tl","7lUXZFGzgp","Z4I1vMkgy8","HlUbFblLA9","TXQ0ZHRxd8","JKWYRpFrrl",
-"Waim6uTacx","DLhzMCqqaD","nnP8oQYxC0","ECMvUzFgtB","yvOMI2TRI7","1v5hHjiVBP","QWxoT2ZHdk","iB08lqQxHP","J2mQiuvf7A","5drc6Qworu",
-"HRxd88xEKz","euZA5RkQke","WPmlxhi5X7","ru4UGS77LH","MmsIozbIYY","v1HlnB3qem","X6PincL0aE","9GXkXzmLYD","J2mQiPYBf4","cmXIX2DREs",
-"NAFuwpvgjS","jS1ajk85Ae","EdBKcdQ586","RsQUq0BmCy","gf8rI2TRI7","cL0aE64s8N","rKDLJlm0pD","WDVWJokgRi","LDk6fGrDg7","d7vjMtlILt",
-"sqVrfY1mC0","U3yw5gtCA5","7Ow5CWaim6","uJScXQbxXc","580YDL7cGc","iKqhrOxWIH","K20wKuQIcz","tuDySZhwG1","Oz8yZqaofN","zmLYDpT8wu",
-"ZhwG1Fhtgl","BpYhVgdQsS","uvf7AGrDg7","s7MxkEoToP","FxX9qSbRYy","aFFsscmXIX","K20wKIn3NS","Pb1pakB5nP","FPfSEWaWsv","zz4ZUdmoS7",
-"NAFuwy94nw","W7cTsJXljW","Waim6GSQwj","2hEEUVprf2","cQOnvfqypy","jfREuSbRYy","pWiOs9y4lw","NAFuwyluBx","hE1QlcL0aE","I7p2a2Yz7E",
-"0BmCylj07Q","pT8wuuupzk","VNCPdzz4ZU","RBhp0nnP8o","blLA9VIlwP","Cfgr3pv0i7","RxrsmWreyP","9GXkXbZLvS","h1zcHKZamH","jS1aj1j5L8",
-"Gv3FqciuWz","ksJbyokgRi","5Mg9r7hyVv","JkzUnThjNn","VIlwPVBjhz","8RCUAWreyP","lH1ktOUqFM","IRh48DLhzM","d85a9CdyBV","Cfgr3BFkb8",
-"dmoS7ZUnqt","NhXdu580YD","9eoRc8hJdt","CNHmvsx5Gl","WPmlx4W0Tl","Nxx9VBFkb8","K20wKVLTy6","O3iyQ0PktI","G1RhS0BmCy","vOqCEVprf2",
-"5IhmGksJby","GXdoHuQIcz","ZUnqtvkCHH","gtCA5l83Ud","vLsmSsuY4x","QWxoTi3pyd","MojnPMmsIo","AOgEeZhwG1","0Wr5y2Yz7E","suY4xvLsmS",
-"gtCA58xEKz","BpYhV0YAGH","n1pmOcQOnv","guMb8VIlwP","jS1ajI7p2a","fmIK1In3NS","0BmCyVNCPd","VLTy6CdyBV","CNHmvWaim6","8RCUAsqVrf",
-"IBe8kYOfrY","BCxeCbgJAz","t59lRy94nw","Dz1R38U2nU","OUYuFKASQ8","aez9yYOfrY","0YAGHGSQwj","dmoS7uoStw","v2eC35Mg9r","zQt6Qiqv4k",
-"M6qcGReKEW","48cHLC2Irc","n8pJ9sqVrf","e6e4zi3pyd","i3pydRBhp0","ZUnqtgtCA5","ZhwG1YjB9t","Pb1pav8yFN","ulk41djsrv","Nxx9VaFFss",
-"GSQwjJKWYR","OHaBzm4bxU","8hJdtksJby","Yw2oUlXFOB","fcJOyWaim6","JKWYRFVMxo","lpF6WbZLvS","9eoRcoVQp6","Gv3Fqy94nw","9GXkXsoy9t",
-"azIWpZhwG1","Cp3mZGv3Fq","zqH0WpWiOs","BCxeCsuY4x","he9IARACuj","sqVrfK20wK","TXQ0Zpv0i7","dmoS79iGoT","CNHmvJkzUn","uZPqgGWqqX",
-"iqv4kY1mC0","ReKEWNo0Qb","VBjhzKsjRK","JkzUnRxrsm","cmXIXWreyP","NhXdudQ586","djsrvSmGzv","HzZT8ciuWz","9y4lwECMvU","0Wr5yL7cGc",
-"gIYvEzFgtB","b29RJ7hyVv","zY1GYIBe8k","S2DfuLbRTH","s4786nFqik","gjUTuFjHXR","Ul4a1IKxdL","7lUXZo8Uyd","5Drn064s8N","s93MlVLTy6",
-"xXTI4uZPqg","7lUXZiKqhr","VLTy6GWqqX","rhl0JlpF6W","oQ87rFFDui","QWxoTAmdQd","RxrsmfaHir","FLsphksJby","lViBvNAFuw","wDajXFPfSE",
-"yvOMInlaBy","BGaQY2Yz7E","Ul4a1AOgEe","Chuy3lkMUA","5Drn0JRJQB","AXpwElViBv","ulk41gdQsS","Ta8f6BGaQY","W7cTsOxWIH","bgJAzJ2mQi",
-"pWiOsGXdoH","LbRTHkZANm","IjTwPaFFss","7ku1p7lUXZ","FNYIMUl4a1","GSQwjBFkb8","pT8wuoVQp6","Ul4a114FLR","hSSvQdhSuH","o8UydvOqCE",
-"wiHrZgjUTu","nnP8oAOgEe","VLTy6x3LDe","uTacxFcWrW","Q6LixMmsIo","DLhzMIBe8k","8U2nUYh1hF","YOfrYazIWp","uTacxcShY2","ksJbyprNT6",
-"No0Qbh1zcH","FGzgpgdQsS","ydG8UFNYIM","uAWypWaim6","F6PT21j5L8","Zv7z0tl72W","5NammyofH3","lpF6WwDajX","NcICAGXdoH","RpBQmqUJMd",
-"WMiS3SjskQ","FLsphHfyNQ","l83Ud2Yz7E","l83UdIKxdL","l83UdXflUq","CIShGFPfSE","5IhmGrz7Ut","tjQxsdmoS7","xReec8FmFH","CxVEfBbwgA",
-"gIYvElm0pD","suY4xaDGtS","iqv4kM3zXL","t98iWSmGzv","ZUnqtguMb8","CqqaD8FmFH","Ul4a1sqVrf","OUqFMMmKGJ","0PktIs4786","uPX7GDz1R3",
-"jiVBP2hEEU","Yh1hFSmGzv","lViBvCqqaD","fFDrJ2Nslm","OxWIHhE1Ql","he9IAM6qcG","Waim60Kyfs","2NslmGWqqX","v1Hln7fKYU","PYBf4euZA5",
-"RkQke9XyT9","8cVD3ZJTXH","IRh48wiHrZ","2Nslm8hJdt","FwEJzStlDJ","yToGWEoToP","iKqhrhi5X7","tAOsrLDk6f","oGu6xGrDg7","FVMxo7Ow5C",
-"yvOMIRxrsm","IKxdL1LB1L","580YDRpBQm","3weIFVIlwP","D6rBygjUTu","Gv3FqMmsIo","d7vjMW7cTs","C2IrcL7cGc","jSjS3jtn0X","b29RJNcICA",
-"PYBf4uAWyp","580YDv8yFN","fLNg8Ul4a1","48cHLRkQke","dQ586brhlQ","4QMc9Kr8ys","LewvMS77LH","Waim6JIqXi","Cp3mZHRxd8","VIlwPY1mC0",
-"CxVEftlILt","i3pydNhXdu","KZamHi7WMQ","JKWYRVjCZq","GXdoHpmeCd","aez9yQWxoT","U3yw5QWxoT","Uvlv45iGN5","OHaBzmX2GE","CqqaDIn3NS",
-"J2mQiFcWrW","4W0TlYw2oU","vOqCE29QAz","B3qemIRh48","iB08lNAFuw","soy9tQ6Lix","pmeCdhSSvQ","IRh48pv0i7","gjUTuW7cTs","2DREszz4ZU",
-"lm0pDzFgtB","VIlwPKZamH","Waim6jtn0X","nlaByK20wK","YOfrY7ku1p","QbxXcRACuj","HP433iKqhr","djsrvPYBf4","hE1QlblLA9","X6PinWMiS3",
-"taOXK7X3uy","jfREuHfyNQ","9GXkX7Ow5C","HfyNQPOUYS","brhlQm4bxU","SjskQ5ZaEz","azIWpoQ87r","LDk6fiB08l","s7MxkNxx9V","4W0TlReKEW",
-"4W0Tl9rlg9","GrDg77X3uy","Mkgy85Mg9r","CIShGIRh48","NhXdu2TRI7","4dEz6F6PT2","YOfrY3weIF","AIYUuYh1hF","uJScXX6Pin","ZJTXHhUTw7",
-"JKWYRX6Pin","GXdoH48cHL","JIqXiTXQ0Z","blLA9HlUbF","CxVEfChuy3","vOqCEprNT6","qUJMdNhXdu","VLTy6S77LH","l83UduZPqg","lkMUAyluBx",
-"e6e4zP6bcg","zFgtBY1mC0","Vprf2uvf7A","PYBf4MGlTF","K4GS8Twano","2hEEU2Yz7E","atef2JIqXi","MmsIoRzaZA","DQimp7Ow5C","KsjRK45cIH",
-"3weIFX6Pin","SjskQk85Ae","FxX9qVprf2","K20wK2DREs","FGzgpuLtKs","iwzGk6AFT0","POUYSd7vjM","5drc6ZuDtD","2TRI764s8N","NhXduzz4ZU",
-"xReecokgRi","YjB9tJkzUn","NOHsz5ZaEz","DLhzMaFFss","o8UydG1RhS","s93MliKqhr","lCMxyRxrsm","M6qcG24ARF","MmKGJpT8wu","OUYuF5drc6",
-"VLTy66AFT0","FVMxo2DREs","uZPqg2ZHdk","vLsmS64s8N","VIlwPHP433","wiHrZJRJQB","ZhwG1OHaBz","9y4lwWreyP","JJs5mDG4sT","IBe8kMkgy8",
-"HRxd8W7cTs","zz4ZUgIYvE","tjQxsM3zXL","XflUqOxWIH","Oz8yZPYBf4","pFrrlOz8yZ","jfREu9iGoT","lH1ktiKqhr","FhtgltaOXK","zqH0WIBe8k",
-"lweGyoVQp6","ulk41NAFuw","Ta8f6G1RhS","580YDpvgjS","7X3uy0YAGH","NOHszWMiS3","MK07YfaHir","FwEJzUvlv4","Oz8yZRmDcr","WPmlxqaofN",
-"fFDrJHRxd8","bZLvSv2eC3","Cp3mZmX2GE","YjB9tv8yFN","5ZaEz4QMc9","cmXIX0PktI","VIlwPVLTy6","FLsphMm8si","RpBQmdhSuH","CdyBVdpe1v",
-"oGu6x7fsYM","soy9tReKEW","KZamHFLsph","EdBKc7fsYM","xReecZzJHW","ZJTXHTwano","5iGN529QAz","qaofNd85a9","oQ87r3otm6","9XyT916lHc",
-"WaWsvJJs5m","gdQsSqQxHP","HP4339eoRc","45cIHRsQUq","wiHrZksJby","WaWsvfFDrJ","CNHmva00b5","t59lR16lHc","ZJTXHStlDJ","RmDcr7Ow5C",
-"LbRTHzz4ZU","5nmWvs93Ml","bgJAzNAFuw","In3NSMezSW","JXljWEOE1o","GrDg7i7WMQ","Gv3FqCp3mZ","LDk6fb29RJ","aL6AJzqH0W","FGzgpiwzGk",
-"VjCZq9eoRc","faHirKr8ys","i7WMQLDk6f","SbRYydhSuH","gtCA5uQIcz","2Nslmk85Ae","cL0aEulk41","vLsmSsx5Gl","hE1QlxReec","qUJMdpmeCd",
-"zHF1qDG4sT","RpBQmuN6r3","JKWYR24ARF","oQ87ruJScX","8FmFHyofH3","aez9ycmXIX","8cVD3tlILt","QYxC0DG4sT","NhXdua00b5","lsQGoaFFss",
-"5Mg9r0PktI","MmsIoaL6AJ","JXljWUl4a1","2DREsvLsmS","48cHLnFqik","jiVBPZuDtD","jtn0XYf2Ec","zbIYY0PktI","fFDrJRxrsm","vLsmSrz7Ut",
-"v2eC3kZANm","mz8gx7lUXZ","tjQxsNhXdu","JKWYRMmsIo","SWfouzY1GY","ECMvUMezSW","VerEA5Namm","In3NStaOXK","Mm8siMkgy8","Yw2oUuQIcz",
-"6q6L9Cp3mZ","RpBQm618Di","ZhwG1CqqaD","AXpwE2Yz7E","07n1cCK5W7","WaWsvn8pJ9","gtCA5YOfrY","LDk6fdpe1v","Chuy3tuDyS","1j5L88xEKz",
-"ulk41kB5nP","QClRL8RCUA","fFDrJBbwgA","gf8rIn1pmO","Ss0ZuoVQp6","GrDg7rKDLJ","nlaBy6AFT0","4W0TlKr8ys","ReKEWYOfrY","prNT6nlaBy",
-"CdyBVaDGtS","RmDcrVLTy6","soy9tVLTy6","0h1b19iGoT","ECMvUYw2oU","dQ586Pb1pa","i3pydB3qem","AXpwEzqH0W","Gv3Fq7Ow5C","16lHcP6bcg",
-"ReKEWjS1aj","CqqaDP6bcg","MojnPvLsmS","CxVEfjeskS","5Drn0fqypy","U3yw5UlU3M","CK5W7fqypy","P6bcgzz4ZU","Gv3FqAOgEe","QYxC0rKDLJ",
-"Qworu0ao3l","MGlTFjtn0X","euZA5HlUbF","zmLYD0MR5X","KsjRKFxX9q","UlU3MRpBQm","SWfouI7p2a","suY4xvkCHH","tAOsrzmLYD","soy9tsoy9t",
-"brhlQS77LH","VBjhzlpF6W","ECMvUM3zXL","zmLYDDG4sT","uLtKsVjCZq","gIYvEiqv4k","tAOsrSmGzv","BFkb8fcJOy","k85AeCxVEf","3weIFhUTw7",
-"5Mg9r6q6L9","3otm6W7cTs","ciuWz1j5L8","16lHcRBhp0","NcICAHRxd8","0YAGHi3pyd","sqVrfni2v1","n1pmOBCxeC","LewvMQnJ1S","cQOnvzbIYY",
-"iB08lChuy3","gIYvE2DREs","ulk41ZhwG1","RkQkee6e4z","okgRiG1RhS","tAOsrb29RJ","yofH38hJdt","ksJbyIjTwP","t59lR580YD","lsQGopv0i7",
-"Ta8f67lUXZ","sx5GlogLgc","Cp3mZcmXIX","BFkb8vOqCE","0KyfsVLTy6","9XyT9BpYhV","Mm8si7hyVv","Vprf2HP433","LewvM5Drn0","5NammMmsIo",
-"gf8rIYh1hF","EoToPdhSuH","HzZT8LbRTH","4W0TlOUqFM","CK5W7SjskQ","HP433nlaBy","29QAzjS1aj","LDk6fGXdoH","qUJMdfmIK1","oQ87ry94nw",
-"Vprf2Yh1hF","SmGzvDG4sT","pT8wufFDrJ","ZhwG1dhSuH","ogLgc5IhmG","l83UdVjCZq","IBe8kqaofN","pFrrl2TRI7","azIWp9XyT9","wiHrZcmXIX",
-"v8yFNNxx9V","RxrsmdhSuH","QssNCnnP8o","2NslmWaWsv","oVQp6ReKEW","U3yw5zY1GY","oQ87rcQOnv","Ul4a18cVD3","DLhzMlXFOB","StlDJguMb8",
-"5Mg9r2hEEU","9iGoTM3zXL","VjCZqJXljW","7lUXZRzaZA","HRxd8ZzJHW","QChxsRmDcr","faHirxciqp","uN6r3UmaEv","AXpwEGWqqX","soy9tI7p2a",
-"RACujuQIcz","SWfouhe9IA","xXTI4OxWIH","DG4sTWaim6","MaJQsZUnqt","9iGoTs7Mxk","07n1cd85a9","QnJ1S7ku1p","WPmlxJIqXi","B3qemFnPFB",
-"LDk6fs7Mxk","0BmCydpe1v","14FLRQChxs","m4bxUFFDui","zbIYYyofH3","tuDySru4UG","RpBQm0Kyfs","CK5W7jS1aj","0ao3lK20wK","4W0TlFjHXR",
-"DLhzMokgRi","7ku1pzbIYY","lweGy7ku1p","gdQsSNcICA","NOHszfcwDa","0Kyfs5drc6","OHaBzEoToP","uZPqgfFDrJ","OHaBzuAWyp","M3zXLLbRTH",
-"UlU3MNAFuw","pmeCd3otm6","wDajXK4GS8","prNT6zqH0W","gIYvEEdBKc","J2mQiECMvU","S77LHjS1aj","v8yFNPb1pa","rKDLJ3weIF","lj07QRsQUq",
-"SjskQW7cTs","x3LDeix74r","Waim6zqH0W","b29RJ5iGN5","VjCZqB3qem","jS1ajCfgr3","tAOsrZuDtD","0Wr5yOUqFM","zY1GYFjHXR","9eoRcBCxeC",
-"ksJbyMaJQs","ix74rnnP8o","pWiOsCNHmv","0Wr5y8hJdt","Oz8yZcL0aE","a00b5Cp3mZ","SmGzvxciqp","e6e4zzHF1q","e6e4z2ZHdk","sqVrf9y4lw",
-"ulk41v8yFN","RkQkeXflUq","lweGyQChxs","FnPFB0Kyfs","lXFOBOUqFM","S2DfuokgRi","XflUqFhtgl","cL0aEFLsph","xReecprNT6","d7vjMB3qem",
-"yvOMIM6qcG","8RCUAOxWIH","M3zXLQbxXc","2TRI75nmWv","ECMvUi7WMQ","14FLRZ4I1v","dmoS7LDk6f","ZJTXH7fsYM","0YAGHt98iW","UlU3McL0aE",
-"RmDcr6q6L9","prNT6jS1aj","D6rByKr8ys","cL0aEAmdQd","5iGN5xXTI4","pAhR10ao3l","uN6r364s8N","jfREuzY1GY","CqqaDsqVrf","pAhR1IBe8k",
-"JXljWuupzk","RmDcruvf7A","AkKTk24ARF","7Ow5Cjtn0X","Pb1paulk41","aDGtS8TxD7","0BmCyqaofN","faHirnnP8o","FLsphJRJQB","vOqCE1LB1L",
-"KsjRKSWfou","fcJOya00b5","7Ow5C8xEKz","jeskSUvlv4","sx5GlMezSW","YjB9tCNHmv","dpe1vReKEW","2NslmAOgEe","RBhp0xReec","hi5X7OHaBz",
-"kZANmAkKTk","FFDuio8Uyd","AIYUuoVQp6","xReeciwzGk","yofH3EdBKc","8RCUAuJScX","yofH3a00b5","8RCUADcpWB","Uvlv4bgJAz","VLTy6vOqCE",
-"jSjS3kB5nP","FcWrWQnJ1S","faHirBbwgA","1LB1LcL0aE","tAOsrRkQke","wiHrZhUTw7","Nxx9VCxVEf","zFgtBfaHir","hE1QlS77LH","0KyfsTCgPp",
-"GXdoH7fsYM","kZANmWDVWJ","9y4lwMK07Y","7Ow5CkB5nP","OHaBzzQt6Q","ZuDtDfLNg8","OxWIHNcICA","BFkb8Waim6","0YAGHiwzGk","580YDlH1kt",
-"ReKEW14FLR","9eoRc29QAz","WPmlxQ6Lix","atef2kB5nP","nlaByfLNg8","fcwDalj07Q","azIWpB3qem","TXQ0ZZUnqt","IjTwPrKDLJ","KsjRKlpF6W",
-"G1RhSFGzgp","lm0pDZhwG1","OUYuFyvOMI","RkQkel83Ud","Uvlv45Mg9r","JkzUntvdkD","kZANmBFkb8","8cVD3WaWsv","1v5hHsx5Gl","Cp3mZ6AFT0",
-"s47861LB1L","NhXduKr8ys","m4bxU14FLR","UmaEv2DREs","zFgtB0Wr5y","jtn0XM3zXL","i7WMQ7fsYM","dhSuHM3zXL","yluBxMezSW","tjQxsv8yFN",
-"b29RJ0Kyfs","dhSuH2TRI7","IBe8k6q6L9","Pb1paAIYUu","0PktIlCMxy","pWiOsZuDtD","e6e4zY1mC0","QWxoTFGzgp","5NammpiJSk","2Yz7EqUJMd",
-"7hyVvKsjRK","BbwgAjtn0X","OUqFMzFgtB","RxrsmpFrrl","Zv7z0Uvlv4","2NslmRpBQm","VerEAUvlv4","FxX9qokgRi","VjCZqQClRL","QYxC0EoToP",
-"NcICAECMvU","okgRiX6Pin","MojnPzFgtB","OUYuFU3yw5","HlUbFfcJOy","fmIK1fmIK1","yEfy9qaofN","Z4I1vlm0pD","Q6LixfcwDa","QssNCSmGzv",
-"VjCZqix74r","WMiS39rlg9","KASQ8EOE1o","RACujNcICA","XyPZNChuy3","zqH0WgdQsS","MmKGJyofH3","okgRieuZA5","uoStwOUqFM","FjHXRatef2",
-"cL0aEQnJ1S","oVQp6OUYuF","v1Hlnv1Hln","fcwDa29QAz","uQIczqaofN","v2eC3AkKTk","WMiS3EOE1o","JIqXi9iGoT","GWqqXDz1R3","s4786JKWYR",
-"cmXIXpAhR1","BpYhV07n1c","m4bxUBCxeC","45cIHyvOMI","piJSkuAWyp","HRxd8rhl0J","5VZjSKr8ys","zqH0WWreyP","yvOMIQClRL","DcpWBQClRL",
-"MK07YxReec","0BmCy9rlg9","wDajXxciqp","uN6r3nFqik","qaofNFnPFB","jiVBPHfyNQ","4W0Tl9iGoT","P6bcg8TxD7","ECMvUNOHsz","lXFOBsuY4x",
-"L7cGc9eoRc","07n1cKsjRK","2DREspFrrl","NAFuwwDajX","16lHc8cVD3","Pb1palCMxy","euZA5djsrv","F6PT2oQ87r","O3iyQOUqFM","IKxdLcQOnv",
-"HRxd8Ss0Zu","atef26q6L9","5iGN5taOXK","fFDrJOUqFM","QbxXcBCxeC","S77LHtAOsr","SWfouF6PT2","JKWYR5VZjS","Ta8f6tjQxs","oGu6x618Di",
-"iB08l6q6L9","ReKEWECMvU","0ao3lcQOnv","AIYUupv0i7","uAWyp9iGoT","b29RJB3qem","wiHrZokgRi","h1zcHIn3NS","bgJAzVNCPd","BbwgAXyPZN",
-"CNHmvMK07Y","uPX7G9y4lw","Gv3Fqn1pmO","lXFOBWPmlx","DLhzMhUTw7","zQt6QPOUYS","JKWYRJXljW","9eoRc07n1c","Pb1paGSQwj","X6PinUlU3M",
-"I7p2a2hEEU","XflUq5drc6","d85a9fqypy","fcwDalViBv","vLsmSStlDJ","lweGygjUTu","dhSuHBGaQY","FNYIMy94nw","6q6L97X3uy","l83UdCNHmv",
-"tuDySuupzk","yluBxFnPFB","gjUTuXyPZN","9eoRclm0pD","0PktIuPX7G","kZANmoGu6x","MmKGJW3VFH","ix74rtaOXK","oGu6xlXFOB","vLsmSVNCPd",
-"dhSuHRzaZA","WaWsvoGu6x","HfyNQjeskS","Yh1hFn8pJ9","PYBf4Zv7z0","2hEEUWaim6","ZhwG1AgJHQ","KsjRKTwano","MGlTFoQ87r","hE1QlJJs5m",
-"MaJQsBpYhV","14FLRprNT6","uvf7AG1RhS","M6qcGRACuj","dmoS7CNHmv","ECMvUoVQp6","L7cGc4W0Tl","DQimpdpe1v","RBhp01j5L8","Vprf2hUTw7",
-"VLTy6pvgjS","5Mg9rVprf2","OUYuF8TxD7","O3iyQuTacx","MojnPzqH0W","uQIczzz4ZU","d7vjM0MR5X","soy9t0YAGH","SjskQ29QAz","KsjRKtjQxs",
-"Nxx9Vrhl0J","okgRioGu6x","ZUnqtuPX7G","oVQp6FPfSE","oGu6xix74r","KsjRKni2v1","TXQ0ZZ4I1v","5drc6sqVrf","0MR5XVLTy6","FPfSElXFOB",
-"MezSWeuZA5","s7Mxk7hyVv","GrDg7SjskQ","CNHmv0BmCy","P6bcg2ZHdk","XflUqpT8wu","Ss0Zu5drc6","wDajXYw2oU","lXFOBDz1R3","ciuWzuZPqg",
-"tlILttjQxs","QworuNo0Qb","v8yFN9eoRc","s47860BmCy","v1Hln6q6L9","0BmCyP6bcg","TwanoMaJQs","RzaZAyToGW","tl72WUlU3M","24ARFbrhlQ",
-"hYBCKSbRYy","Ss0ZuVprf2","mz8gxECMvU","atef2Yh1hF","VLTy6MK07Y","Q6LixFxX9q","JKWYRWPmlx","h1zcHRmDcr","VjCZqsoy9t","FxX9qnlaBy",
-"8hJdtuLtKs","POUYSVBjhz","FcWrWlkMUA","IRh48pFrrl","BpYhVPb1pa","9rlg9GSQwj","TwanoOHaBz","o8UyduQIcz","ciuWzOHaBz","BCxeC4W0Tl",
-"rhl0JY1mC0","RACujlm0pD","o8UydydG8U","AgJHQX6Pin","HzZT80YAGH","CK5W7gf8rI","Yf2EcHzZT8","h1zcHRBhp0","pAhR1nlaBy","mX2GEeuZA5",
-"ksJbyWMiS3","SjskQDcpWB","Yw2oUdQ586","5NammogLgc","W3VFHFGzgp","ru4UGazIWp","KZamH64s8N","8U2nUpT8wu","U3yw5Qworu","0YAGH8cVD3",
-"TCgPpd7vjM","yToGWZJTXH","X6Pin48cHL","HzZT8brhlQ","KsjRKK4GS8","NAFuwxciqp","k85AeQnJ1S","zQt6QeuZA5","In3NS0h1b1","uN6r3JRJQB",
-"FFDuiFVMxo","9y4lwuQIcz","kZANmzHF1q","dpe1vJKWYR","64s8NVLTy6","1j5L8Cfgr3","gIYvEAgJHQ","M6qcG580YD","ix74rVerEA","64s8NUvlv4",
-"7hyVvgdQsS","WDVWJAkKTk","9y4lwhYBCK","VBjhz1LB1L","MezSWblLA9","StlDJZhwG1","x3LDeiKqhr","0MR5XGv3Fq","QClRLGXdoH","FLsph8cVD3",
-"C2IrcP6bcg","NAFuwPb1pa","mX2GEiKqhr","uvf7AGWqqX","SWfouy94nw","LbRTHEdBKc","pmeCdix74r","Waim6pWiOs","FNYIMMGlTF","C2IrcfaHir",
-"0ao3lEOE1o","aL6AJCdyBV","2ZHdkYh1hF","hUTw7CIShG","M3zXLSs0Zu","jS1ajYjB9t","GWqqXVNCPd","Yf2EcFcWrW","0BmCytaOXK","Q6hMCMm8si",
-"RsQUq8TxD7","FLsph9iGoT","BGaQYJRJQB","QssNC5Drn0","k85AeW3VFH","SWfoujS1aj","cQOnvDQimp","pAhR1rz7Ut","zmLYDjtn0X","iB08lazIWp",
-"d85a948cHL","xXTI4VjCZq","8hJdtP6bcg","pT8wuDG4sT","hSSvQ4QMc9","cmXIXQClRL","Vprf2ciuWz","16lHctAOsr","CxVEfTa8f6","yluBxVBjhz",
-"lj07QNOHsz","FcWrWGWqqX","Uvlv4uN6r3","soy9tB3qem","JkzUn5Mg9r","2hEEUcShY2","WPmlxogLgc","WMiS3lm0pD","t59lRhe9IA","ZuDtD4dEz6",
-"IRh48QbxXc","TCgPpCdyBV","Pb1paxXTI4","cShY2BCxeC","lweGyGWqqX","Q6hMC4W0Tl","0ao3ltjQxs","IRh48TXQ0Z","QssNCqQxHP","jtn0XIjTwP",
-"a00b5QssNC","8U2nU4QMc9","NOHszv8yFN","5NammzQt6Q","RmDcry94nw","StlDJCxVEf","uQIczFPfSE","mz8gxNcICA","dpe1vLewvM","FLsphNxx9V",
-"ogLgcZzJHW","dmoS7S77LH","7lUXZyEfy9","uoStwXflUq","J2mQi64s8N","ogLgclweGy","Nxx9VHfyNQ","FxX9qWmadA","okgRiU3yw5","wDajXXflUq",
-"RzaZAZv7z0","Cfgr3mz8gx","aez9yk85Ae","kB5nPAOgEe","hSSvQ9y4lw","iwzGkZ4I1v","4W0Tllm0pD","9rlg9Yh1hF","pT8wuIjTwP","Cfgr3TXQ0Z",
-"6q6L9hi5X7","CK5W7AXpwE","2ZHdk7Ow5C","soy9tYw2oU","D6rByzmLYD","GSQwjuvf7A","MezSWRxrsm","5nmWvd7vjM","IRh48YOfrY","5Mg9rDcpWB",
-"zFgtBdQ586","tuDySMojnP","5VZjSVIlwP","YjB9t1v5hH","GWqqXxciqp","JkzUnDz1R3","xReecVprf2","S77LHjeskS","UlU3MRBhp0","Kr8ysJIqXi",
-"fLNg8sqVrf","bZLvSjSjS3","MK07Yb29RJ","nlaByCp3mZ","FcWrWZuDtD","tl72WYw2oU","SWfoulpF6W","MGlTFC2Irc","0BmCyt59lR","pvgjS4W0Tl",
-"M6qcGy94nw","8hJdt1v5hH","BbwgAyEfy9","0MR5XdQ586","zQt6QtjQxs","IBe8kIBe8k","FFDuiSbRYy","QChxsNOHsz","vLsmSUmaEv","ulk41pmeCd",
-"7Ow5Catef2","tvdkDuTacx","gf8rIChuy3","ulk41ReKEW","tvdkDjzUqR","NOHszYjB9t","hi5X7atef2","nnP8oAIYUu","14FLRChuy3","3weIFNhXdu",
-"QYxC055rfB","FhtglyofH3","sx5GllpF6W","C2IrcIRh48","qaofNWmadA","UlU3MzY1GY","9eoRcIRh48","MmsIo8cVD3","hYBCK7hyVv","M3zXLhYBCK",
-"2DREskB5nP","nnP8oatef2","GSQwjZuDtD","soy9ts93Ml","U3yw5IKxdL","uLtKscmXIX","8xEKzVjCZq","5Drn0Q6hMC","GXdoHKZamH","lj07QChuy3",
-"jiVBPHlUbF","CqqaDMojnP","JkzUnuJScX","29QAzBbwgA","9iGoTb29RJ","ZzJHWK20wK","Z4I1v6q6L9","uAWypPYBf4","xReecBFkb8","iwzGkD6rBy",
-"DQimpmz8gx","ZuDtD8cVD3","iwzGkuZPqg","hYBCKhYBCK","xXTI4DcpWB","n8pJ9gdQsS","FnPFBguMb8","JJs5mhYBCK","fcwDaMm8si","JIqXi2Nslm",
-"Uvlv4IjTwP","QssNCEOE1o","t98iWiwzGk","JXljW29QAz","uN6r3s4786","YOfrYMGlTF","M3zXLksJby","AOgEeQWxoT","W7cTspvgjS","uAWypksJby",
-"HRxd8FLsph","BCxeC580YD","fqypyStlDJ","HlUbF1j5L8","M6qcGtl72W","2DREspT8wu","gIYvEAmdQd","k85Ael83Ud","8U2nUQYxC0","cmXIXTa8f6",
-"zQt6Qzz4ZU","RBhp0Zv7z0","14FLRfLNg8","7fKYUQ6hMC","kZANmCK5W7","DG4sTpT8wu","d85a9faHir","ni2v1pv0i7","he9IAJXljW","W7cTswDajX",
-"IRh4807n1c","aez9yRxrsm","9rlg95Mg9r","bZLvSlkMUA","FNYIMDz1R3","Vprf214FLR","lpF6WyluBx","Z4I1vlViBv","BFkb8U3yw5","jfREuQClRL",
-"jtn0XSjskQ","Uvlv4QbxXc","Uvlv4NOHsz","QbxXc7Ow5C","yvOMIsuY4x","AXpwEtuDyS","zmLYD8RCUA","BFkb8m4bxU","uPX7GuAWyp","FjHXRWPmlx",
-"Uvlv4D6rBy","No0QbCK5W7","NcICAazIWp","RBhp04QMc9","FVMxofcwDa","taOXK6q6L9","l83UdpiJSk","FLsph8xEKz","dQ5867fsYM","Cfgr3P6bcg",
-"KASQ8W3VFH","xXTI4t59lR","cmXIXU3yw5","yEfy9ECMvU","xReecsqVrf","BCxeC64s8N","MGlTF0BmCy","n1pmO1LB1L","HP4339y4lw","SWfouDQimp",
-"lkMUARACuj","RkQkewiHrZ","1v5hHfLNg8","14FLRwiHrZ","pWiOsAXpwE","Ta8f6JJs5m","zQt6Qsoy9t","Kr8ysPb1pa","pWiOsMK07Y","tjQxsQssNC",
-"LbRTHK4GS8","VerEAoGu6x","jfREu5VZjS","OUqFMe6e4z","FGzgpBbwgA","ksJbyksJby","RpBQmSmGzv","HP433ECMvU","i7WMQOUYuF","ZhwG1TXQ0Z",
-"2DREslViBv","JJs5mSjskQ","16lHc7Ow5C","cQOnvJKWYR","SmGzvTwano","EdBKcoVQp6","1LB1Luupzk","FVMxoo8Uyd","ZhwG1ru4UG","MmsIouLtKs",
-"SmGzvatef2","Cp3mZxciqp","DcpWBYjB9t","StlDJzY1GY","lm0pDEdBKc","2Yz7EFLsph","wiHrZPb1pa","0PktI5Mg9r","SbRYyFhtgl","FPfSE1v5hH",
-"ZhwG10h1b1","FGzgpHRxd8","pvgjSh1zcH","QChxsB3qem","rz7UtGXdoH","bZLvSi3pyd","aDGtSni2v1","WreyPFVMxo","iqv4kHRxd8","K4GS8RBhp0",
-"kZANmTwano","qQxHP1LB1L","K4GS8Oz8yZ","JKWYRkB5nP","IjTwPVerEA","lpF6WMK07Y","XflUqS2Dfu","QWxoTWmadA","Kr8ysL7cGc","lsQGoZUnqt",
-"gf8rIRmDcr","RsQUq5IhmG","k85AeWDVWJ","MmKGJcQOnv","DG4sTv1Hln","MGlTFHzZT8","blLA9ECMvU","580YD1j5L8","4W0TlVIlwP","Ss0ZuyEfy9",
-"AXpwEy94nw","tAOsr7fKYU","P6bcgMmsIo","J2mQiIRh48","8TxD7LbRTH","FcWrWzz4ZU","lkMUAsqVrf","RkQkeCK5W7","9iGoT6q6L9","tvdkDChuy3",
-"azIWpHzZT8","aDGtSZhwG1","jfREulXFOB","No0QbJJs5m","VIlwPAXpwE","yEfy9cShY2","Ul4a1TXQ0Z","KZamH7fKYU","8xEKz24ARF","dQ586BbwgA",
-"NOHszuvf7A","cQOnvni2v1","NAFuwDz1R3","5Mg9rksJby","s4786EOE1o","CxVEf0PktI","ZzJHWuTacx","OUYuFvOqCE","SmGzvQYxC0","tuDyS0MR5X",
-"lsQGoRmDcr","OHaBzpmeCd","55rfB2TRI7","yToGWM6qcG","xReecSs0Zu","9y4lw55rfB","DLhzMNxx9V","K4GS8FLsph","jiVBPTCgPp","uJScXtvdkD",
-"wDajXJXljW","nlaByjfREu","AmdQdWMiS3","P6bcgZ4I1v","OxWIHYjB9t","ydG8UMK07Y","BGaQYFxX9q","55rfB0BmCy","soy9tuAWyp","W7cTsxReec",
-"rhl0JzqH0W","48cHLTCgPp","EOE1oOUqFM","wiHrZZv7z0","QYxC0Mm8si","cQOnvQChxs","CIShG6AFT0","FVMxoNhXdu","K20wKx3LDe","uAWypFcWrW",
-"hUTw7NhXdu","zY1GYPOUYS","Y1mC0MaJQs","Kr8ysn8pJ9","IjTwPAmdQd","TXQ0ZuoStw","rz7UtEoToP","2DREsBFkb8","fmIK1zQt6Q","o8UydhE1Ql",
-"VNCPdnnP8o","i7WMQlm0pD","Z4I1vlpF6W","FVMxoMkgy8","pv0i7QbxXc","6q6L9BpYhV","jfREueuZA5","QnJ1S64s8N","16lHcnlaBy","0KyfsEdBKc",
-"8xEKzgf8rI","MmKGJBGaQY","Mm8sitAOsr","KASQ87fsYM","ZuDtD2DREs","Y1mC0PYBf4","4QMc9Oz8yZ","tAOsr8FmFH","Mm8si4QMc9","OxWIH24ARF",
-"PYBf4lH1kt","m4bxU7ku1p","Twano7X3uy","ZzJHWCqqaD","yvOMIhe9IA","gf8rIpAhR1","zY1GYSjskQ","JIqXi7ku1p","lkMUAChuy3","xReecpmeCd",
-"618DiOUYuF","tlILtMkgy8","NOHszW3VFH","ulk418cVD3","e6e4ztuDyS","lXFOBRACuj","FPfSEi3pyd","dhSuHfcwDa","QClRLBGaQY","djsrvjtn0X",
-"i7WMQ0PktI","8hJdtpv0i7","IBe8kqUJMd","lweGyVerEA","5iGN5piJSk","Cp3mZsoy9t","iKqhrVIlwP","07n1c5Mg9r","TXQ0ZK4GS8","Vprf2yToGW",
-"GrDg7CdyBV","Zv7z0FPfSE","IBe8kZhwG1","uvf7ADz1R3","Zv7z0Dz1R3","QnJ1SguMb8","JkzUnpAhR1","KZamHQClRL","Pb1paZJTXH","ru4UG3weIF",
-"Q6LixjSjS3","iKqhrZ4I1v","618Di24ARF","RsQUq0YAGH","SWfougdQsS","CNHmvtAOsr","VNCPdAIYUu","W3VFH5drc6","6q6L9FLsph","RBhp0jSjS3",
-"zmLYD7hyVv","CNHmvvkCHH","rz7UtPYBf4","iB08lSbRYy","Oz8yZuZPqg","lpF6W8FmFH","Q6hMCIBe8k","45cIHlsQGo","FLsph29QAz","2hEEUhYBCK",
-"iKqhr0BmCy","SjskQOUqFM","ix74rBpYhV","k85Aei7WMQ","XyPZNsqVrf","tl72WYOfrY","zY1GYUl4a1","DcpWBMK07Y","WmadAm4bxU","lCMxyv2eC3",
-"TCgPpSbRYy","jeskS8U2nU","k85Aexciqp","tAOsrYOfrY","5ZaEzYf2Ec","uJScXpFrrl","QbxXcK4GS8","Kr8ystjQxs","5iGN5KZamH","hE1QlReKEW",
-"WPmlxyofH3","24ARF8RCUA","tvdkDjS1aj","cQOnv45cIH","5drc6Ta8f6","2Yz7EC2Irc","Z4I1vMmsIo","Kr8ysnlaBy","ReKEWfLNg8","9iGoTJ2mQi",
-"IKxdLFGzgp","S77LHqUJMd","BFkb8KsjRK","WmadAjfREu","GWqqXDG4sT","soy9tCNHmv","DG4sTMkgy8","M3zXLtvdkD","lCMxyDz1R3","Kr8ysyvOMI",
-"cShY2fqypy","M6qcGKsjRK","cShY2Mkgy8","fFDrJKr8ys","8cVD3bgJAz","v1Hln5iGN5","yToGWJJs5m","O3iyQuLtKs","6q6L9d7vjM","oQ87rMezSW",
-"nlaBycmXIX","lweGy0PktI","0MR5XyofH3","JJs5mmX2GE","W7cTsQClRL","FFDuiOUqFM","d7vjMlViBv","W3VFHuvf7A","rKDLJvOqCE","VIlwPMaJQs",
-"aDGtSaL6AJ","blLA90YAGH","KZamHHlUbF","24ARFhYBCK","zz4ZUWaim6","CdyBVFwEJz","MaJQsv2eC3","ogLgcXyPZN","uAWypd85a9","taOXKDz1R3",
-"48cHL7fKYU","tAOsrEOE1o","UlU3Md85a9","oGu6x2ZHdk","Cfgr3ogLgc","VBjhzlkMUA","QYxC0CdyBV","FcWrWOUqFM","jtn0XThjNn","POUYSsuY4x",
-"PYBf4UmaEv","Y1mC0RsQUq","DG4sTiB08l","fcwDaKsjRK","ZzJHW9GXkX","M6qcGKr8ys","uN6r30Kyfs","mz8gx9rlg9","pWiOsTCgPp","5NammIKxdL",
-"zQt6QWPmlx","WaWsvECMvU","hSSvQxReec","Chuy3MGlTF","OxWIHCIShG","1v5hHMmsIo","jSjS3lkMUA","zqH0WuAWyp","jS1ajF6PT2","v1HlnlViBv",
-"5nmWvfaHir","IjTwPoQ87r","lViBvo8Uyd","MmKGJx3LDe","FNYIMZzJHW","rhl0Jrhl0J","x3LDey94nw","lViBvcQOnv","RzaZAFVMxo","Z4I1vt59lR",
-"QClRL1v5hH","BFkb80ao3l","NOHszVerEA","AOgEeBFkb8","W7cTsIn3NS","qQxHPd85a9","jfREuVLTy6","piJSkhE1Ql","vLsmSdhSuH","5nmWvzmLYD",
-"G1RhSyluBx","pFrrl8hJdt","yEfy9zHF1q","FcWrWpmeCd","pFrrl0YAGH","uLtKsbgJAz","PYBf4hE1Ql","7fsYMWMiS3","VIlwP6q6L9","L7cGctaOXK",
-"FjHXRy94nw","MmKGJAmdQd","ZUnqtyofH3","QnJ1S5Namm","QWxoTpWiOs","nlaByLbRTH","b29RJHRxd8","zmLYDi3pyd","m4bxUMm8si","cQOnvpT8wu",
-"dQ586X6Pin","t59lRQ6hMC","VBjhz5ZaEz","EOE1o9y4lw","hi5X7yvOMI","nnP8oGSQwj","8xEKz5drc6","RmDcrtjQxs","Yf2EcWaim6","lpF6WMkgy8",
-"KZamHuN6r3","QworuvOqCE","e6e4zfaHir","ciuWzTa8f6","7fsYMRpBQm","suY4xjfREu","CIShGYjB9t","MGlTFlkMUA","24ARFNo0Qb","y94nwIKxdL",
-"v2eC3ksJby","GSQwjzFgtB","5VZjSuZPqg","8cVD3kB5nP","YOfrYsoy9t","EOE1o4dEz6","VLTy6lViBv","55rfBBpYhV","FwEJzSmGzv","2TRI7y94nw",
-"t59lRM6qcG","hYBCKqaofN","oGu6xfcwDa","suY4xO3iyQ","8RCUALewvM","jS1aj8RCUA","K4GS8K20wK","GrDg7DLhzM","4QMc9GWqqX","AgJHQW3VFH",
-"Waim6BpYhV","hYBCK0MR5X","5VZjSYjB9t","Q6hMCs7Mxk","UmaEv5VZjS","wiHrZsqVrf","KASQ8e6e4z","faHirFnPFB","QChxsulk41","jSjS3CqqaD",
-"lXFOBM6qcG","sqVrf7lUXZ","tl72WcQOnv","1LB1LFGzgp","DQimpFLsph","580YDS77LH","ix74rHP433","WaWsvuLtKs","HzZT8rKDLJ","lXFOB2DREs",
-"cQOnvMojnP","3otm69GXkX","SmGzvhYBCK","SjskQvkCHH","2Yz7EGrDg7","8xEKzZuDtD","Pb1paDcpWB","blLA9k85Ae","FNYIMuvf7A","kB5nPCqqaD",
-"8TxD7iB08l","i7WMQiKqhr","kB5nPcQOnv","Q6hMCFPfSE","QnJ1S6AFT0","b29RJ24ARF","TXQ0ZlkMUA","wiHrZpT8wu","uJScXIBe8k","AkKTkqQxHP",
-"BFkb8fmIK1","EdBKcgtCA5","0ao3lBGaQY","ZJTXHsqVrf","8hJdt9eoRc","U3yw5FcWrW","fmIK1QYxC0","POUYSZJTXH","QClRLJXljW","jeskSoGu6x",
-"okgRiWDVWJ","GrDg7dQ586","IKxdLsuY4x","v1HlnD6rBy","vkCHHJkzUn","tvdkD8hJdt","tvdkDl83Ud","IjTwP3otm6","LDk6fblLA9","tjQxsMmKGJ",
-"vOqCEoVQp6","8RCUAnlaBy","AIYUuQnJ1S","7lUXZFxX9q","2NslmblLA9","s7MxkbrhlQ","uvf7AgtCA5","5NammGWqqX","AmdQdyofH3","uN6r3Twano",
-"tjQxsCK5W7","ni2v1faHir","zz4ZUpWiOs","4W0TlRkQke","9GXkXB3qem","oGu6xMmsIo","0Wr5yaDGtS","O3iyQMojnP","faHirJKWYR","cmXIXv2eC3",
-"tAOsrzHF1q","CK5W7tl72W","WaWsv9GXkX","azIWpQClRL","7fsYMFPfSE","pFrrlt98iW","pmeCdokgRi","uJScXazIWp","guMb89XyT9","pvgjSM6qcG",
-"x3LDeS77LH","uAWyph1zcH","In3NSWMiS3","Q6hMClkMUA","JKWYRn1pmO","5Mg9rYf2Ec","lpF6WD6rBy","07n1cNAFuw","JRJQBydG8U","tl72WWMiS3",
-"yToGWmz8gx","ZUnqtP6bcg","4dEz67X3uy","CNHmvD6rBy","WaWsvEdBKc","StlDJhUTw7","FFDuiFNYIM","MaJQsFVMxo","ZhwG1OxWIH","YjB9t9rlg9",
-"Uvlv42Nslm","O3iyQs7Mxk","Cfgr3dpe1v","LDk6fK4GS8","kB5nPCNHmv","zFgtBRkQke","lweGyuLtKs","yToGW3weIF","fmIK1XyPZN","UlU3MGrDg7",
-"hYBCKVNCPd","i3pydkZANm","9eoRcfaHir","LbRTHvkCHH","HzZT8aDGtS","suY4xMojnP","BCxeC2Nslm","tAOsrjtn0X","S77LHzz4ZU","faHir48cHL",
-"d7vjMIn3NS","0BmCyCIShG","dmoS7vLsmS","DLhzMuJScX","U3yw5blLA9","uupzkl83Ud","0MR5XFcWrW","Cfgr33otm6","lkMUAMezSW","1v5hHWaim6",
-"64s8NprNT6","lm0pD5IhmG","RkQkeAkKTk","0MR5XksJby","iqv4kmz8gx","oVQp63otm6","K20wKxReec","Mkgy8No0Qb","5VZjSWPmlx","48cHLgdQsS",
-"soy9tFLsph","MmKGJPOUYS","9rlg9zFgtB","6AFT0MezSW","9y4lw8RCUA","VerEADcpWB","DcpWBOUqFM","d7vjMzqH0W","YOfrYm4bxU","jzUqRM3zXL",
-"2TRI70Kyfs","gIYvEb29RJ","uJScX8RCUA","7Ow5COz8yZ","CdyBVB3qem","e6e4zKASQ8","ZJTXH8RCUA","RBhp0pv0i7","sx5GlhYBCK","24ARFCqqaD",
-"BpYhVqUJMd","0ao3lW3VFH","EdBKcJKWYR","7X3uyhE1Ql","rz7Ut8hJdt","16lHc9XyT9","64s8NW7cTs","2Yz7EpAhR1","yvOMIFNYIM","iwzGkFcWrW",
-"KsjRKS77LH","hE1Ql8U2nU","Vprf2uAWyp","FGzgpgf8rI","EOE1opvgjS","RmDcrVIlwP","TXQ0ZfaHir","fqypyaL6AJ","t59lRHP433","a00b5FcWrW",
-"SjskQo8Uyd","Zv7z0RkQke","64s8Nlm0pD","ZuDtDgdQsS","2Yz7E9GXkX","Yw2oUiKqhr","UlU3MAIYUu","cShY2tjQxs","0ao3lYw2oU","d85a9ZuDtD",
-"RxrsmAIYUu","MK07YBpYhV","OHaBz8TxD7","qUJMdMm8si","Gv3FqgdQsS","16lHcWaim6","Mkgy8b29RJ","djsrvlXFOB","qUJMddjsrv","yToGWZzJHW",
-"oQ87rksJby","TXQ0Z0BmCy","dQ5860h1b1","Yf2EcjfREu","Yh1hFDLhzM","lXFOBEdBKc","yEfy9Yw2oU","tAOsriwzGk","ZuDtD5VZjS","uJScXZhwG1",
-"Waim6bgJAz","RzaZAaL6AJ","guMb86AFT0","JkzUnyofH3","atef2piJSk","TXQ0ZIKxdL","5IhmGOz8yZ","zbIYYQworu","VjCZqDz1R3","uJScXMK07Y",
-"B3qem4dEz6","5nmWvdhSuH","mX2GEnnP8o","Nxx9VjzUqR","NOHszS2Dfu","hYBCKuN6r3","1v5hHRACuj","FjHXRDz1R3","lm0pD7lUXZ","QYxC0lm0pD",
-"yToGW7fsYM","Pb1paFjHXR","QClRLWaWsv","8RCUANxx9V","8RCUAXflUq","CqqaD7hyVv","s4786m4bxU","FGzgpzz4ZU","Chuy3GXdoH","m4bxUdQ586",
-"d85a9gIYvE","yToGW6q6L9","uJScX5drc6","PYBf4pWiOs","WmadAAmdQd","FhtglLewvM","djsrvlH1kt","QssNCn8pJ9","nFqikECMvU","L7cGcVNCPd",
-"xReec8TxD7","6AFT0euZA5","ECMvUzz4ZU","MojnP0MR5X","taOXK5IhmG","xXTI4pT8wu","AIYUuLbRTH","GXdoHFxX9q","2DREsfLNg8","tuDySyEfy9",
-"ogLgcQYxC0","AgJHQ64s8N","JKWYRoGu6x","soy9to8Uyd","Y1mC0zHF1q","J2mQidjsrv","M6qcGdpe1v","Waim6CxVEf","zz4ZUzY1GY","5IhmGcShY2",
-"G1RhSRkQke","blLA945cIH","jiVBPgf8rI","OUqFMM3zXL","9GXkXni2v1","azIWpOHaBz","FNYIMQnJ1S","Ul4a12DREs","VBjhzzmLYD","Ss0ZuQ6hMC",
-"FhtglSjskQ","OUYuF4QMc9","BbwgApT8wu","ZzJHWsx5Gl","Vprf2fcJOy","Mkgy8MojnP","zz4ZUpAhR1","d7vjMlkMUA","HfyNQiqv4k","StlDJprNT6",
-"iB08lGv3Fq","1j5L8vLsmS","RkQke5drc6","oVQp6MmKGJ","LbRTH1v5hH","yofH3WaWsv","PYBf4aez9y","2Yz7Esoy9t","s7MxkAmdQd","zQt6QtlILt",
-"P6bcguupzk","v2eC3LewvM","7fsYMokgRi","gdQsSzz4ZU","NhXduuAWyp","Ta8f6taOXK","uupzkYf2Ec","JXljWJkzUn","MGlTFprNT6","rz7UtS2Dfu",
-"kZANmRpBQm","EdBKcQChxs","K20wKuPX7G","lCMxyru4UG","MGlTFuvf7A","HP433M6qcG","euZA5SmGzv","No0Qbxciqp","2TRI70ao3l","Mm8siDQimp",
-"SbRYyNcICA","azIWpi3pyd","xXTI45IhmG","WreyPEdBKc","NhXdulj07Q","4dEz6VerEA","KZamHy94nw","WDVWJ5Mg9r","nnP8oeuZA5","8TxD7taOXK",
-"Uvlv4Ul4a1","y94nw8FmFH","I7p2apT8wu","RBhp0MmsIo","uN6r3Cfgr3","QYxC0TCgPp","pv0i79y4lw","Y1mC0uAWyp","jtn0X5iGN5","QYxC0Yh1hF",
-"cL0aEWreyP","3otm6jSjS3","4W0TlIRh48","7hyVv29QAz","zQt6QFFDui","5drc6lXFOB","Oz8yZi3pyd","gf8rIPb1pa","zY1GY5Drn0","8xEKzD6rBy",
-"tlILtLbRTH","5nmWvUlU3M","29QAztvdkD","Dz1R3YOfrY","Ta8f6l83Ud","RxrsmZzJHW","b29RJJIqXi","s93Mlni2v1","0h1b1pAhR1","gf8rIciuWz",
-"pT8wu8hJdt","WmadAa00b5","vLsmSJXljW","2ZHdk5VZjS","QWxoTrhl0J","Cfgr3uZPqg","ni2v12DREs","BGaQYOUqFM","e6e4zsx5Gl","F6PT2jzUqR",
-"MmsIoTwano","jS1ajkB5nP","UmaEvThjNn","iqv4kZhwG1","ni2v1uAWyp","16lHcHzZT8","Ta8f6jiVBP","m4bxUCIShG","2Yz7Ejtn0X","qUJMdStlDJ",
-"iB08l16lHc","KsjRKnFqik","l83UduAWyp","LewvMd85a9","vOqCECfgr3","WDVWJCIShG","Vprf2wDajX","4QMc9yluBx","MK07YzQt6Q","MGlTFqUJMd",
-"SjskQlweGy","DLhzMzz4ZU","FwEJzrz7Ut","iKqhrAIYUu","5Mg9rCdyBV","NhXdub29RJ","FLsph2Nslm","Q6LixFFDui","3weIFe6e4z","lkMUAVIlwP",
-"618DiQworu","OxWIHy94nw","he9IA9XyT9","tvdkDTCgPp","FxX9qa00b5","WreyPK20wK","QChxsxciqp","SjskQVjCZq","6q6L9jtn0X","RBhp0TCgPp",
-"K20wKBpYhV","WDVWJRBhp0","0ao3lcShY2","6q6L9VNCPd","fcwDa3otm6","RsQUqFFDui","soy9tqaofN","RBhp0yofH3","lweGyguMb8","1j5L87ku1p",
-"uoStwLewvM","7fsYMyofH3","wiHrZix74r","FwEJzwiHrZ","JIqXiB3qem","ZUnqtJKWYR","NAFuwa00b5","2ZHdkZzJHW","xReecPOUYS","K20wKyToGW",
-"uZPqgBGaQY","AgJHQ0MR5X","Uvlv47lUXZ","4QMc9i3pyd","MmKGJ618Di","soy9tbgJAz","nnP8oTwano","0YAGHNo0Qb","J2mQiNhXdu","brhlQsx5Gl",
-"ru4UGZ4I1v","9y4lwtaOXK","MK07YD6rBy","azIWpoVQp6","rKDLJWDVWJ","XyPZNGXdoH","5NammLewvM","FGzgpyvOMI","RmDcrrKDLJ","Waim6K20wK",
-"AgJHQJJs5m","4dEz6o8Uyd","iqv4kIKxdL","CqqaDIjTwP","aL6AJAkKTk","KASQ82ZHdk","JKWYRcL0aE","ciuWzb29RJ","AIYUulj07Q","DcpWBzFgtB",
-"MK07YW3VFH","KsjRKIKxdL","POUYSjtn0X","WmadALbRTH","C2IrczQt6Q","qaofNk85Ae","NAFuwoVQp6","mX2GEdmoS7","8hJdtwDajX","4QMc9Fhtgl",
-"ru4UG07n1c","d7vjMx3LDe","ECMvUyEfy9","MmKGJZJTXH","iwzGkDz1R3","580YDhE1Ql","M3zXLhe9IA","tuDySHlUbF","4QMc9v1Hln","atef2tvdkD",
-"fqypyFwEJz","GWqqX9GXkX","uZPqgJIqXi","yvOMId7vjM","xciqpYjB9t","lH1ktMkgy8","i3pydVLTy6","C2IrcUmaEv","tAOsrzQt6Q","FhtglGSQwj",
-"B3qemStlDJ","XyPZNnFqik","4W0TlMmKGJ","Oz8yZhe9IA","DcpWBWreyP","K20wK7ku1p","8RCUAAkKTk","prNT6uN6r3","s7Mxklj07Q","AXpwEDQimp",
-"fmIK1qUJMd","J2mQiFjHXR","B3qemulk41","uPX7GM6qcG","uPX7GprNT6","VIlwP0PktI","5ZaEzWmadA","7fKYUG1RhS","zmLYDlViBv","AkKTkuTacx",
-"tjQxs4QMc9","BGaQYgtCA5","dQ586wDajX","U3yw5FwEJz","StlDJv2eC3","PYBf40Kyfs","mX2GEkZANm","In3NSStlDJ","CIShGlsQGo","qUJMdpFrrl",
-"jSjS3X6Pin","IKxdLLDk6f","8FmFHfcwDa","xciqpkB5nP","qUJMd2hEEU","1j5L8fqypy","uPX7GtuDyS","WPmlxAgJHQ","MezSWn1pmO","5drc6y94nw",
-"t59lRiwzGk","7fsYMFwEJz","8FmFHUvlv4","VerEAazIWp","m4bxUWDVWJ","VerEAFnPFB","P6bcg16lHc","AXpwE3weIF","5Drn0yToGW","Waim6VIlwP",
-"K20wKVerEA","3weIFMGlTF","OHaBzFFDui","JKWYRfcwDa","dQ586yvOMI","MK07Yatef2","bZLvSaDGtS","taOXKYw2oU","WMiS3AIYUu","iwzGkzqH0W",
-"Waim6Q6hMC","AgJHQn1pmO","NhXduuoStw","zY1GYVNCPd","7fKYUC2Irc","C2Irc618Di","Nxx9VuoStw","W7cTsv8yFN","fcwDaZhwG1","ZUnqty94nw",
-"suY4xSmGzv","MaJQsJJs5m","i3pydRpBQm","0MR5XK4GS8","uoStwFnPFB","UlU3MNo0Qb","nlaBy8cVD3","8RCUAjtn0X","StlDJa00b5","Q6LixMmKGJ",
-"TXQ0ZRBhp0","pWiOstuDyS","M6qcGM6qcG","2DREshi5X7","8RCUAPYBf4","WMiS3iB08l","v1HlnMmsIo","uupzkYw2oU","AXpwEJJs5m","uupzklweGy",
-"tl72Wgf8rI","lkMUADcpWB","kZANmIjTwP","ZzJHWogLgc","lH1ktqaofN","2DREs2Nslm","pvgjSOUqFM","yvOMIlViBv","pAhR1BGaQY","aFFssvOqCE",
-"FNYIMqUJMd","0KyfsMaJQs","2ZHdklsQGo","Q6LixGXdoH","yvOMIgjUTu","7Ow5CyofH3","lm0pDgIYvE","HRxd8NcICA","L7cGccQOnv","uoStwcQOnv",
-"soy9tru4UG","i7WMQFcWrW","v2eC3K4GS8","ReKEW2hEEU","GSQwjzHF1q","MaJQs2Yz7E","4dEz6GrDg7","U3yw5Rxrsm","yluBxyToGW","Ul4a15nmWv",
-"uLtKsZUnqt","5nmWvprNT6","gdQsSNo0Qb","FPfSEUvlv4","FGzgpydG8U","ni2v1Q6Lix","9XyT9NhXdu","ZUnqtuAWyp","Yf2EcZUnqt","nFqikatef2",
-"FnPFBZzJHW","DcpWBatef2","Ta8f69XyT9","NAFuwpT8wu","jiVBPLDk6f","RpBQmtvdkD","6q6L99rlg9","8cVD3L7cGc","B3qem6q6L9","Nxx9VzqH0W",
-"uLtKsRxrsm","yluBxb29RJ","48cHLcL0aE","uAWyp5IhmG","jS1aj7hyVv","2ZHdkfFDrJ","XyPZNBFkb8","zz4ZUhE1Ql","BpYhVZJTXH","8RCUAZUnqt",
-"n1pmOru4UG","3weIFRsQUq","s4786QChxs","e6e4zpFrrl","BbwgAlH1kt","yofH3zbIYY","Ss0Zulm0pD","Ss0ZuSs0Zu","WMiS3bgJAz","TCgPpQnJ1S",
-"MGlTFG1RhS","UmaEvcShY2","Dz1R31v5hH","tl72WHlUbF","WreyPAXpwE","FjHXRRmDcr","Mm8silweGy","8hJdtRBhp0","OUYuFvkCHH","d7vjMt59lR",
-"lH1ktMmsIo","0Wr5yWMiS3","StlDJkB5nP","uQIczSmGzv","RkQkeBGaQY","FcWrWD6rBy","MGlTFLbRTH","JJs5mRmDcr","5ZaEzMaJQs","a00b55IhmG",
-"4dEz6JRJQB","DQimpDLhzM","Cfgr3iB08l","jtn0XzqH0W","t98iWHRxd8","Mkgy8qaofN","HzZT8uQIcz","DLhzMix74r","l83UdOz8yZ","IBe8kgjUTu",
-"hi5X7Nxx9V","XflUqCIShG","yvOMINOHsz","iB08lAXpwE","a00b50PktI","0h1b1BFkb8","yToGWF6PT2","5drc6LDk6f","XyPZNjfREu","NhXduUl4a1",
-"MGlTF7X3uy","ydG8UtlILt","7X3uy8TxD7","fLNg8gdQsS","2Nslm9eoRc","uLtKsVNCPd","HzZT8YjB9t","i7WMQ5Namm","x3LDelm0pD","RBhp0n8pJ9",
-"14FLRMK07Y","VjCZqpT8wu","Z4I1vVNCPd","FwEJzlweGy","pWiOsk85Ae","ni2v1blLA9","14FLRGXdoH","8RCUA0MR5X","U3yw5wiHrZ","gdQsSSjskQ",
-"7X3uyCqqaD","oGu6xOHaBz","SjskQaDGtS","fqypyBpYhV","atef2gIYvE","NcICA9rlg9","RpBQmNAFuw","rKDLJ4W0Tl","qQxHPOxWIH","jzUqRnFqik",
-"4dEz6MezSW","8hJdtjzUqR","hUTw7NcICA","UlU3M7Ow5C","B3qem5nmWv","ReKEWaDGtS","Dz1R3MezSW","jS1ajo8Uyd","VjCZqJkzUn","8TxD7i7WMQ",
-"2ZHdkdmoS7","mX2GE48cHL","1LB1LprNT6","iB08lPOUYS","lXFOBXyPZN","24ARFWaim6","0Kyfsi7WMQ","ZuDtDzz4ZU","QYxC0WPmlx","M3zXLyluBx",
-"FwEJz4QMc9","NcICAB3qem","S2DfuQ6hMC","2ZHdktjQxs","k85AeSmGzv","NAFuwtaOXK","16lHco8Uyd","n1pmOW7cTs","jiVBPzHF1q","uTacxtaOXK",
-"Oz8yZC2Irc","mX2GE8U2nU","cQOnvMGlTF","JJs5mMmsIo","VerEAWPmlx","pv0i7In3NS","QworufaHir","ThjNnNxx9V","dhSuHUmaEv","UmaEvJ2mQi",
-"fFDrJ1j5L8","FNYIM07n1c","pAhR1SbRYy","aL6AJFVMxo","Yf2Eca00b5","ZJTXHl83Ud","hSSvQlpF6W","K4GS8WmadA","PYBf4BbwgA","mX2GEfqypy",
-"RsQUqZhwG1","nlaByRmDcr","7fsYM5Drn0","QClRLAkKTk","QbxXc5ZaEz","vkCHHEdBKc","fqypy9eoRc","Q6LixFGzgp","jzUqROUqFM","1j5L8LbRTH",
-"ZuDtD6q6L9","LbRTHUlU3M","KASQ8M3zXL","CNHmvCK5W7","Kr8ysKZamH","ksJbyO3iyQ","WDVWJCNHmv","8hJdtTa8f6","HP433cShY2","aez9y9eoRc",
-"KASQ87fKYU","8hJdthSSvQ","MojnPuPX7G","Mm8siZhwG1","yEfy9VjCZq","8U2nUuTacx","k85AeuZPqg","CNHmvs4786","oGu6xXyPZN","In3NSQYxC0",
-"BbwgAuoStw","8U2nUWreyP","X6Pini7WMQ","wDajXjzUqR","VLTy6s7Mxk","iwzGkvOqCE","ogLgcuJScX","HlUbFKASQ8","LDk6ftl72W","Q6Lix7Ow5C",
-"suY4x4dEz6","uoStw16lHc","SbRYynnP8o","b29RJFhtgl","M6qcGY1mC0","LewvMRsQUq","OUYuFQChxs","HfyNQKASQ8","0h1b1ksJby","azIWpFLsph",
-"UmaEv7fKYU","07n1cSjskQ","NhXduOxWIH","U3yw5BpYhV","5Drn0qaofN","TwanoBFkb8","aL6AJjzUqR","okgRixXTI4","aez9yLDk6f","JJs5mAgJHQ",
-"C2IrcCK5W7","WDVWJKZamH","yofH3faHir","iqv4kMmKGJ","Yw2oUECMvU","ulk41fqypy","DLhzMZUnqt","S77LHFGzgp","QssNC48cHL","IRh48tl72W",
-"HfyNQgIYvE","vLsmSgtCA5","FPfSEvLsmS","pAhR12DREs","QworuReKEW","Q6LixqQxHP","yEfy9vOqCE","qUJMdrz7Ut","ydG8UZUnqt","5nmWvFFDui",
-"FNYIMcmXIX","v8yFNnlaBy","uupzk7fKYU","RACuj9iGoT","LbRTHAOgEe","Pb1paQYxC0","BbwgAatef2","POUYSgf8rI","8FmFHC2Irc","FjHXROUqFM",
-"CNHmvZhwG1","5Namm0Wr5y","55rfBL7cGc","HP4331j5L8","fcwDawiHrZ","BFkb8lXFOB","jzUqRCdyBV","qUJMduAWyp","QssNCpWiOs","n8pJ9xXTI4",
-"QYxC0aDGtS","zFgtBMaJQs","0MR5XRxrsm","DLhzMuLtKs","BbwgAmX2GE","s93MluLtKs","Y1mC0zbIYY","0KyfsJkzUn","euZA5e6e4z","piJSk9rlg9",
-"QChxsVNCPd","MaJQs8FmFH","KZamHNcICA","9rlg9Fhtgl","gjUTusqVrf","pWiOsv2eC3","lpF6W8RCUA","GXdoHuvf7A","k85AeQYxC0","K20wK55rfB",
-"zqH0WuZPqg","4W0TlvLsmS","NAFuwt98iW","U3yw5PYBf4","uJScXrKDLJ","W7cTs9y4lw","0ao3lVBjhz","hi5X7tuDyS","4dEz6TXQ0Z","OUqFMfqypy",
-"zmLYDWPmlx","suY4xlm0pD","wDajXdpe1v","o8UydkZANm","9eoRctaOXK","JJs5mC2Irc","he9IAhe9IA","5drc6blLA9","jSjS3WMiS3","pvgjSWMiS3",
-"blLA9EoToP","CIShGCp3mZ","RsQUqsqVrf","FxX9qYh1hF","8U2nUgtCA5","CK5W70YAGH","VjCZqRBhp0","zY1GY9GXkX","SjskQ7hyVv","hUTw7BFkb8",
-"2Yz7EKASQ8","oQ87rQ6Lix","VBjhzUl4a1","iKqhrY1mC0","cmXIXK20wK","D6rBy2Yz7E","Zv7z0BFkb8","WDVWJbgJAz","YjB9tEOE1o","4dEz6CxVEf",
-"VIlwPCxVEf","gtCA5piJSk","SjskQlViBv","atef2ix74r","Cfgr3aL6AJ","VjCZqX6Pin","580YDcQOnv","cQOnvyofH3","MGlTFlXFOB","s7MxkU3yw5",
-"fcwDaZzJHW","VNCPddmoS7","M3zXLjS1aj","oVQp6Zv7z0","9y4lwUl4a1","djsrvciuWz","CNHmvWreyP","FhtglWreyP","ni2v1cL0aE","EdBKcCfgr3",
-"W3VFHblLA9","guMb8RpBQm","5NammtlILt","AIYUuhYBCK","WreyPpmeCd","1v5hH0Wr5y","B3qemuupzk","oQ87rzY1GY","0ao3lMaJQs","580YDs93Ml",
-"G1RhS0Kyfs","0MR5XEoToP","EoToPStlDJ","wiHrZy94nw","fqypyMojnP","FjHXRuupzk","CdyBVCK5W7","55rfBNxx9V","faHir6AFT0","ydG8U8RCUA",
-"blLA9RpBQm","euZA5Qworu","5drc6yofH3","tuDySCqqaD","taOXKQ6hMC","07n1culk41","AXpwEOz8yZ","7ku1phi5X7","HRxd8RkQke","kZANm5VZjS",
-"P6bcgMmKGJ","kZANmRzaZA","cShY2SWfou","pFrrlECMvU","24ARFFVMxo","1v5hHRsQUq","O3iyQ7fsYM","MmKGJGv3Fq","fFDrJYOfrY","SmGzvuJScX",
-"nFqikFVMxo","TwanoCp3mZ","tAOsr7ku1p","NcICAmX2GE","BbwgAThjNn","Oz8yZjtn0X","Yh1hFvOqCE","taOXKIjTwP","m4bxUvOqCE","FGzgp9GXkX",
-"WDVWJZhwG1","2TRI7rKDLJ","RzaZAhi5X7","EOE1oBCxeC","uZPqgqUJMd","HlUbFCfgr3","GXdoHKASQ8","TCgPpfcwDa","qUJMdQ6hMC","Mm8si9XyT9",
-"lsQGoIKxdL","uQIczFwEJz","TwanopT8wu","9y4lwqQxHP","Gv3FqsqVrf","QbxXcRxrsm","ulk41SWfou","JKWYRFLsph","SmGzvThjNn","taOXKOz8yZ",
-"1j5L85Drn0","iwzGkEOE1o","FcWrWFxX9q","AIYUuQbxXc","dQ586NcICA","y94nwd85a9","n1pmOfmIK1","m4bxUogLgc","Y1mC0RkQke","LDk6fO3iyQ",
-"NcICAv1Hln","In3NSRsQUq","euZA5KASQ8","X6PinC2Irc","JRJQBtaOXK","FwEJzjS1aj","xciqpdhSuH","5Mg9rni2v1","45cIHuTacx","tAOsr9rlg9",
-"i7WMQBpYhV","tuDySzY1GY","F6PT2nnP8o","ogLgcpT8wu","RACujtl72W","SbRYyRkQke","vkCHHyToGW","ydG8UGv3Fq","lH1ktOxWIH","zbIYYv8yFN",
-"lCMxyQClRL","uPX7GgIYvE","lXFOBK20wK","h1zcHfFDrJ","LbRTHpAhR1","XflUq0Wr5y","0KyfsNo0Qb","LDk6fAIYUu","618DigjUTu","CK5W7zY1GY",
-"zz4ZUAgJHQ","qaofNuPX7G","29QAzNhXdu","7ku1puJScX","FFDui5Mg9r","oQ87rqaofN","M3zXLwDajX","uJScXdhSuH","VBjhzChuy3","OUYuFUvlv4",
-"iqv4kyEfy9","5NammlweGy","nFqikJXljW","OUqFM64s8N","MmsIoqaofN","64s8Ne6e4z","IjTwPFLsph","piJSkksJby","0Wr5yD6rBy","No0QbLewvM",
-"SWfouNhXdu","pAhR1wDajX","VerEA618Di","HfyNQQssNC","zY1GYJ2mQi","29QAzhUTw7","9iGoTh1zcH","qUJMddhSuH","Q6hMC07n1c","YOfrYECMvU",
-"K4GS8HzZT8","qQxHPoQ87r","VIlwPYOfrY","iB08lXflUq","jiVBP0BmCy","M3zXLgIYvE","U3yw5OUYuF","P6bcgGXdoH","Ul4a1pT8wu","nlaBys4786",
-"l83UdqQxHP","5VZjSyluBx","gtCA5xXTI4","7Ow5Cmz8gx","JKWYRYjB9t","CIShGix74r","piJSkPb1pa","Nxx9VPOUYS","CxVEfFxX9q","AXpwEbrhlQ",
-"JIqXiuvf7A","B3qem8hJdt","CqqaDeuZA5","iKqhrYf2Ec","ru4UGWDVWJ","8hJdtQnJ1S","AXpwEiqv4k","5ZaEzJXljW","0BmCyzFgtB","jzUqRfcwDa",
-"HfyNQxXTI4","zFgtB5nmWv","zqH0Wrhl0J","StlDJLbRTH","JRJQBHRxd8","TwanoqQxHP","SWfoukB5nP","dmoS7NAFuw","Fhtglix74r","AmdQdVBjhz",
-"iqv4ktl72W","tvdkDulk41","lpF6WfaHir","gf8rIAgJHQ","FnPFBjfREu","v1HlnHP433","U3yw5ksJby","ThjNnMm8si","vkCHHkB5nP","Ta8f6HlUbF",
-"5NammSs0Zu","hSSvQHP433","tlILtAmdQd","M6qcGnnP8o","b29RJuJScX","vkCHH48cHL","aez9yix74r","2ZHdkKr8ys","yofH3Zv7z0","uTacxSjskQ",
-"hYBCKVIlwP","BbwgApWiOs","LbRTHt98iW","07n1c5VZjS","TCgPpYw2oU","pT8wuaez9y","JJs5mIBe8k","Zv7z0soy9t","oGu6xFcWrW","nnP8oyvOMI",
-"29QAzVLTy6","faHircShY2","ZJTXH2Nslm","IRh48suY4x","S77LHjSjS3","Kr8ysZuDtD","gtCA5Yf2Ec","WPmlx4dEz6","ciuWz2hEEU","AmdQdQssNC",
-"4W0TlU3yw5","rKDLJ2DREs","tvdkDpT8wu","he9IAMojnP","lj07Q7X3uy","RsQUqOUYuF","cShY2K20wK","GWqqXtl72W","Zv7z0yToGW","RBhp0IjTwP",
-"djsrvokgRi","FPfSE16lHc","7fsYMF6PT2","gf8rIFNYIM","a00b5sqVrf","B3qemUl4a1","uoStwAgJHQ","jiVBP1LB1L","Z4I1vHfyNQ","tuDySFwEJz",
-"8U2nUFVMxo","ZJTXHfmIK1","oVQp6Twano","jS1aj8cVD3","hUTw7QbxXc","2hEEUsx5Gl","D6rByAOgEe","zQt6Quvf7A","NAFuws4786","lXFOB618Di",
-"5iGN5AOgEe","cQOnvFnPFB","FjHXRjSjS3","VNCPdv1Hln","ogLgc45cIH","8hJdtfcJOy","bgJAzs4786","IjTwPokgRi","qaofNRACuj","QssNCb29RJ",
-"WaWsvlweGy","4W0TlVjCZq","vkCHHoQ87r","JKWYRVerEA","7Ow5CuPX7G","Mm8sitlILt","9iGoTtAOsr","vkCHHFFDui","blLA9F6PT2","MaJQsnFqik",
-"Cp3mZ2Yz7E","Dz1R3FPfSE","WreyP2DREs","KsjRKK20wK","IRh48iKqhr","t98iWGSQwj","4QMc9ni2v1","GSQwjru4UG","qaofNru4UG","vOqCEFFDui",
-"kB5nPni2v1","v1HlnM6qcG","2hEEU1j5L8","SmGzvOUqFM","No0QbW7cTs","SWfouSbRYy","wiHrZnFqik","QWxoTOUqFM","gIYvEMGlTF","Oz8yZnnP8o",
-"FcWrW1LB1L","Kr8ystaOXK","24ARFRxrsm","fqypyhSSvQ","CdyBVSjskQ","0KyfsDLhzM","RzaZAfqypy","FGzgp8hJdt","atef2ZJTXH","lCMxyYw2oU",
-"hE1Ql9y4lw","jiVBPYw2oU","MaJQsCIShG","48cHLFVMxo","0h1b1uQIcz","zFgtBLbRTH","AgJHQMojnP","NhXdu0YAGH","IKxdL5drc6","ReKEWU3yw5",
-"ksJbyCK5W7","aFFssMK07Y","OHaBzpAhR1","lpF6Wm4bxU","uJScXQssNC","OUYuFpFrrl","5ZaEz6AFT0","he9IApmeCd","FhtglqQxHP","l83UdRpBQm",
-"ReKEWHlUbF","StlDJvkCHH","bgJAzy94nw","SWfouM3zXL","oQ87rIRh48","WaWsvIn3NS","lj07Q45cIH","580YD3otm6","8TxD77fKYU","RACujfFDrJ",
-"Y1mC0jiVBP","IBe8k2hEEU","W7cTsMkgy8","MK07Y9rlg9","FhtglIBe8k","cShY20BmCy","7ku1pnlaBy","5ZaEzPYBf4","i7WMQ0BmCy","Ul4a1b29RJ",
-"Uvlv4oGu6x","AXpwE5drc6","uoStwQClRL","y94nw29QAz","7X3uyBGaQY","Gv3FqfcwDa","gdQsSpmeCd","HfyNQ0ao3l","0KyfsDG4sT","uTacxSWfou",
-"aFFssi7WMQ","SWfouuAWyp","FNYIMi7WMQ","ZzJHWNAFuw","LDk6frhl0J","qUJMd7fsYM","FVMxoaL6AJ","wDajXReKEW","DQimpGSQwj","aDGtS45cIH",
-"pmeCdFPfSE","bZLvSuoStw","2DREsSs0Zu","2DREs5iGN5","JRJQBprNT6","9eoRc9y4lw","NcICAtl72W","QssNC1j5L8","lm0pDZJTXH","Yh1hFGXdoH",
-"tvdkDaL6AJ","Y1mC0LewvM","tlILtCqqaD","he9IAt59lR","sqVrfjtn0X","FNYIMfmIK1","Y1mC0d7vjM","M3zXLGWqqX","RsQUqoVQp6","v1HlngIYvE",
-"IjTwPxXTI4","pWiOsFnPFB","lsQGoIRh48","5drc6cmXIX","FwEJzFnPFB","RBhp0RsQUq","4QMc9sqVrf","HRxd8dhSuH","5drc6jtn0X","RkQkex3LDe",
-"pv0i71LB1L","9XyT9Yf2Ec","1v5hHMK07Y","i7WMQRACuj","gf8rIhUTw7","zQt6Q8U2nU","AXpwEYh1hF","GrDg7ZhwG1","5ZaEzi7WMQ","yToGW8xEKz",
-"Dz1R3rKDLJ","xXTI4In3NS","vLsmSNhXdu","HlUbFTXQ0Z","okgRiHP433","fqypylm0pD","5IhmGRkQke","KASQ8OHaBz","JkzUnQChxs","Waim6gIYvE",
-"fFDrJlm0pD","oVQp6wDajX","kB5nPK4GS8","M6qcGzY1GY","Cfgr3lH1kt","JIqXiIBe8k","7ku1pkZANm","ni2v1lH1kt","ZJTXHJ2mQi","Yf2EcGXdoH",
-"VerEAGv3Fq","Mkgy8i7WMQ","5VZjSaDGtS","lViBvJJs5m","NAFuwS2Dfu","m4bxUkZANm","9rlg9jiVBP","RmDcrC2Irc","tl72W0Kyfs","tlILt7fsYM",
-"zqH0WVNCPd","9rlg9VIlwP","zHF1q618Di","W3VFHksJby","Dz1R3FcWrW","lViBv5VZjS","vOqCEyvOMI","G1RhSLbRTH","HlUbFWDVWJ","s4786SbRYy",
-"jtn0XpFrrl","dhSuHv1Hln","0YAGHWreyP","16lHcPOUYS","7Ow5Ca00b5","RsQUqfaHir","Z4I1vZv7z0","kB5nPblLA9","FxX9qs4786","e6e4zcQOnv",
-"IKxdLWPmlx","K4GS8Yh1hF","8hJdtJXljW","W3VFHtvdkD","WMiS3gf8rI","WMiS35IhmG","euZA5CK5W7","OxWIHHfyNQ","8RCUAVprf2","Z4I1vFxX9q",
-"CK5W7fmIK1","YOfrYpT8wu","48cHLjeskS","QssNCoQ87r","B3qemBbwgA","1v5hHqQxHP","DcpWB64s8N","xReecix74r","WMiS3VBjhz","JJs5mzbIYY",
-"pvgjSJIqXi","tlILtlXFOB","zFgtByofH3","Gv3Fqlm0pD","fcJOyRzaZA","lViBvLewvM","guMb8HRxd8","JkzUnlweGy","7lUXZtaOXK","K20wKrhl0J",
-"fcwDaZUnqt","xReecLewvM","FnPFBvOqCE","WMiS37lUXZ","e6e4zm4bxU","y94nwRsQUq","yluBxUl4a1","m4bxUaDGtS","FVMxos4786","uLtKshe9IA",
-"2ZHdks7Mxk","48cHL45cIH","KsjRKU3yw5","GWqqXokgRi","QbxXctuDyS","lj07QU3yw5","9y4lwaL6AJ","MmsIoHP433","gtCA5CdyBV","Q6hMC0ao3l",
-"fcwDaG1RhS","hi5X7JXljW","IjTwPIn3NS","WaWsv2TRI7","JXljWfLNg8","Yw2oUtvdkD","gIYvEnlaBy","uAWyprKDLJ","Kr8ysNo0Qb","cL0aEcShY2",
-"HfyNQB3qem","xXTI4v8yFN","Yf2Ec4dEz6","9y4lwOxWIH","i3pydfcwDa","n1pmO0Wr5y","UmaEvvkCHH","9eoRcLDk6f","45cIHCqqaD","s93MlYf2Ec",
-"IBe8k7fKYU","Fhtgl0Kyfs","ksJbyiwzGk","RmDcrlViBv","M3zXL0Kyfs","5NammO3iyQ","FNYIM5drc6","5VZjSn8pJ9","y94nwDcpWB","PYBf4CqqaD",
-"fcJOyRkQke","bZLvSnnP8o","JKWYRU3yw5","ThjNnvLsmS","uJScXCIShG","1j5L8B3qem","Yf2EccmXIX","JkzUngtCA5","VLTy6FxX9q","HP433v2eC3",
-"2NslmyvOMI","fLNg8FnPFB","4W0TluQIcz","U3yw5uoStw","o8UydyluBx","zbIYYFwEJz","DG4sTHP433","zQt6Q7Ow5C","48cHLuvf7A","kZANm9iGoT",
-"RpBQmaFFss","B3qem9eoRc","uLtKslViBv","oVQp6BpYhV","SWfouCIShG","0Wr5ytl72W","0PktIx3LDe","yofH307n1c","euZA56AFT0","RsQUquupzk",
-"ZJTXHcmXIX","8cVD3pFrrl","LDk6ffmIK1","EdBKcChuy3","JkzUnNo0Qb","AXpwE5IhmG","hE1QlpmeCd","fcwDahE1Ql","tl72WprNT6","Uvlv45VZjS",
-"hUTw7prNT6","tvdkDoVQp6","OUqFMuvf7A","o8UydVprf2","SWfoupT8wu","RkQkeZ4I1v","s4786he9IA","pAhR18cVD3","Twanoix74r","P6bcgNo0Qb",
-"uvf7AFxX9q","uvf7AJIqXi","piJSklViBv","rz7Uts93Ml","TCgPp48cHL","NcICAFnPFB","iwzGkqUJMd","LbRTH9rlg9","7ku1patef2","I7p2azqH0W",
-"o8UydFnPFB","lj07QWaWsv","L7cGcYOfrY","EdBKchYBCK","4W0Tlsx5Gl","7X3uyhi5X7","kB5nPWPmlx","gf8rICqqaD","8hJdt48cHL","M3zXLWmadA",
-"CdyBVPOUYS","CK5W7okgRi","0YAGHbgJAz","sx5GlxXTI4","FcWrWlj07Q","CxVEfJIqXi","WreyPDLhzM","dmoS7dpe1v","taOXKNhXdu","NOHszguMb8",
-"yofH3Ul4a1","NcICAPb1pa","jSjS3uTacx","SmGzvNcICA","TXQ0Z7lUXZ","48cHLCfgr3","ThjNnJKWYR","euZA5rKDLJ","ThjNni7WMQ","dpe1vCqqaD",
-"iKqhrAgJHQ","NcICAlH1kt","14FLRRpBQm","soy9ta00b5","ThjNnzHF1q","oVQp61v5hH","OUqFMvLsmS","dhSuH8RCUA","JJs5mHP433","rz7UtL7cGc",
-"b29RJs7Mxk","uZPqgWaim6","uJScXbZLvS","8TxD7qUJMd","iwzGkuLtKs","7fKYUFhtgl","RsQUq5Drn0","W7cTslkMUA","jfREuyEfy9","CdyBVsoy9t",
-"pv0i7wDajX","Mm8siSbRYy","oVQp6B3qem","hE1QlTwano","t59lRdhSuH","s4786QbxXc","lpF6WGWqqX","v2eC3ni2v1","EoToPi7WMQ","dQ586MojnP",
-"CK5W77lUXZ","Yf2EclViBv","MGlTFUvlv4","7Ow5CP6bcg","fcwDazHF1q","D6rByZ4I1v","yvOMITXQ0Z","CNHmv6AFT0","9iGoTHlUbF","NOHszHfyNQ",
-"EoToPL7cGc","OxWIHQChxs","taOXKni2v1","mz8gxpWiOs","uAWypJKWYR","xReectAOsr","W7cTsZuDtD","48cHLJRJQB","FjHXR2ZHdk","1LB1LfmIK1",
-"2ZHdk0BmCy","QWxoT6AFT0","Yw2oUlkMUA","Uvlv4s7Mxk","nFqikoGu6x","FcWrWSbRYy","jSjS3Vprf2","atef2d85a9","ECMvUFPfSE","IKxdLlXFOB",
-"JKWYRjtn0X","8hJdt2TRI7","oQ87rgf8rI","JkzUnMK07Y","8FmFHQ6Lix","LewvM55rfB","guMb8Chuy3","5Drn0GrDg7","9rlg90YAGH","GrDg714FLR",
-"GSQwj3weIF","n8pJ9580YD","nlaByt98iW","2NslmXyPZN","yToGWlj07Q","NAFuw6AFT0","mX2GEQChxs","xReeclpF6W","suY4xFPfSE","AkKTk5iGN5",
-"Ta8f6AkKTk","jSjS3wiHrZ","8FmFHy94nw","5Drn00ao3l","XflUqMkgy8","TCgPp14FLR","9rlg97Ow5C","5iGN5euZA5","gjUTuFcWrW","S77LH8RCUA",
-"Ul4a1fcJOy","QworuS77LH","yvOMIuJScX","IKxdLNOHsz","Yw2oURpBQm","ZJTXH2hEEU","aL6AJ7ku1p","lH1ktoGu6x","QYxC0M6qcG","fcJOygf8rI",
-"DLhzMlpF6W","D6rBywiHrZ","VerEAReKEW","WreyPv8yFN","45cIHbZLvS","lXFOBjSjS3","PYBf4LbRTH","16lHcVjCZq","WDVWJdpe1v","nnP8oTa8f6",
-"Pb1pa4dEz6","K20wKZJTXH","yvOMIBFkb8","HP433HP433","FFDuigf8rI","FNYIMAIYUu","Zv7z0uvf7A","ECMvUCdyBV","WDVWJMmsIo","NOHszd7vjM",
-"hUTw7fLNg8","W3VFH2DREs","EdBKcbZLvS","5NammCNHmv","9y4lwaFFss","ix74rFNYIM","AgJHQuTacx","8hJdtjtn0X","QssNCMmsIo","HzZT8wiHrZ",
-"LewvMAgJHQ","FVMxo7lUXZ","x3LDepT8wu","AgJHQU3yw5","Yf2EcyvOMI","64s8NJkzUn","7fsYMuZPqg","rKDLJfcJOy","OUYuFDQimp","0ao3lKASQ8",
-"Gv3FqguMb8","2NslmS2Dfu","UlU3MYf2Ec","a00b5vOqCE","okgRiuQIcz","yofH3Fhtgl","M6qcGIn3NS","piJSkyEfy9","X6PinVBjhz","DQimpBFkb8",
-"FjHXRHP433","aL6AJdhSuH","uLtKsP6bcg","HzZT8Oz8yZ","RACujn8pJ9","cShY24W0Tl","0MR5Xd7vjM","KASQ8RACuj","MaJQs7lUXZ","Yf2Ech1zcH",
-"taOXKyofH3","nnP8oSmGzv","2DREs5Namm","UlU3MVprf2","KsjRK7X3uy","ZhwG1GrDg7","ogLgc4dEz6","8FmFHWPmlx","LewvMPYBf4","9GXkX6AFT0",
-"Zv7z0prNT6","tAOsrQClRL","oGu6xJRJQB","QYxC0AmdQd","DG4sTFVMxo","a00b5Rxrsm","8FmFHRmDcr","QbxXc9y4lw","7hyVv580YD","7lUXZQ6hMC",
-"he9IATwano","I7p2aECMvU","HRxd8ZUnqt","Q6hMCBGaQY","TXQ0Zv1Hln","qUJMdMaJQs","1v5hH5drc6","L7cGcuPX7G","pAhR1X6Pin","VIlwPFxX9q",
-"BCxeCt98iW","0PktIzqH0W","S2DfuDQimp","7Ow5C8TxD7","iB08l2hEEU","WDVWJLbRTH","O3iyQOxWIH","In3NSMkgy8","YjB9tAmdQd","IKxdLVNCPd",
-"h1zcH9y4lw","MGlTFaez9y","WaWsvydG8U","nFqikokgRi","zQt6QuQIcz","ulk41vLsmS","FLsphcShY2","OUYuFzqH0W","JRJQBYh1hF","CIShG4dEz6",
-"WmadATCgPp","fqypyNhXdu","SWfou07n1c","zz4ZUhYBCK","0PktIblLA9","CK5W7YOfrY","lXFOBHRxd8","JXljWjtn0X","BCxeCECMvU","oGu6x1j5L8",
-"FGzgpyofH3","bZLvS2ZHdk","i7WMQazIWp","m4bxUVNCPd","SmGzvgtCA5","prNT6y94nw","guMb8uupzk","2ZHdkzHF1q","CqqaD45cIH","Yh1hF0ao3l",
-"kB5nP16lHc","Dz1R3l83Ud","aFFssF6PT2","VjCZqoQ87r","mz8gx6q6L9","4W0Tl5Namm","24ARF7fKYU","e6e4zn1pmO","StlDJmz8gx","9rlg9djsrv",
-"SbRYyZJTXH","7X3uyfqypy","618DiP6bcg","zbIYYkB5nP","Ul4a1In3NS","m4bxUeuZA5","HfyNQNxx9V","uupzkWreyP","pvgjSxReec","oVQp6K20wK",
-"djsrvQWxoT","FjHXRZUnqt","2ZHdknlaBy","In3NSCdyBV","DcpWBe6e4z","hE1Ql8xEKz","ogLgc8TxD7","he9IAsuY4x","9XyT9pvgjS","zmLYD55rfB",
-"29QAzzHF1q","7lUXZuTacx","pv0i7J2mQi","uJScX7ku1p","9GXkXyToGW","t59lRTa8f6","HRxd8n1pmO","7Ow5CpWiOs","NhXduTwano","ZzJHWJJs5m",
-"RkQkeRkQke","rhl0JBCxeC","JXljW618Di","AmdQdJ2mQi","8TxD716lHc","EoToPKr8ys","Ul4a17X3uy","ni2v1ulk41","HlUbFIKxdL","QClRLatef2",
-"bZLvSb29RJ","sqVrfh1zcH","piJSkgdQsS","29QAzC2Irc","FNYIMFwEJz","GXdoHLewvM","KASQ8uTacx","D6rBykB5nP","lweGy64s8N","FwEJzZhwG1",
-"Cfgr3zbIYY","U3yw52hEEU","SjskQpvgjS","mX2GEHP433","2Yz7E5VZjS","ReKEWQChxs","QWxoTfLNg8","lm0pDAmdQd","v8yFNStlDJ","VIlwPgIYvE",
-"Mkgy8pAhR1","gdQsS5ZaEz","bZLvSKr8ys","jSjS3Cfgr3","atef28xEKz","yToGWQChxs","pAhR1NhXdu","bZLvSYh1hF","IRh48rhl0J","FjHXRKASQ8",
-"G1RhS2TRI7","MojnPzQt6Q","hUTw70h1b1","ECMvUECMvU","0MR5XcShY2","FjHXRPOUYS","GSQwjRzaZA","lsQGoNxx9V","GXdoHGWqqX","SWfouFPfSE",
-"QssNCpv0i7","7Ow5C5iGN5","aDGtS0YAGH","NOHszfLNg8","GXdoHP6bcg","RxrsmK4GS8","BGaQYuAWyp","CqqaDrz7Ut","29QAzuZPqg","ni2v1RmDcr",
-"ZzJHWhYBCK","K4GS8zQt6Q","gjUTuuQIcz","bZLvSh1zcH","FGzgpcShY2","I7p2aIRh48","pv0i7CdyBV","1LB1LMm8si","GSQwjnFqik","PYBf40YAGH",
-"lj07QtvdkD","ksJbyCfgr3","ulk417fsYM","uPX7GdQ586","DG4sTW7cTs","29QAzqQxHP","FwEJz55rfB","POUYS0ao3l","LewvMt59lR","WreyP4QMc9",
-"oGu6xzbIYY","45cIHtl72W","RsQUq7hyVv","MezSW8cVD3","qQxHPpmeCd","ru4UGtuDyS","14FLRyluBx","uQIczLbRTH","Nxx9V7ku1p","v8yFNjtn0X",
-"uvf7AUlU3M","MaJQsJ2mQi","jzUqRpmeCd","Ss0ZuFNYIM","FNYIML7cGc","yvOMIoGu6x","AIYUuTa8f6","64s8NjSjS3","uQIczVLTy6","LbRTHZhwG1",
-"t59lROUYuF","euZA5ReKEW","Yw2oUuTacx","Kr8ysWPmlx","SbRYyW3VFH","CxVEf7lUXZ","OUqFMMezSW","tjQxsXflUq","Nxx9VKsjRK","Q6LixCp3mZ",
-"Yh1hFZJTXH","cL0aERACuj","0MR5XVNCPd","zHF1qmX2GE","nnP8o9rlg9","hUTw7lXFOB","64s8Ns7Mxk","S2DfuQ6Lix","5drc6BbwgA","tuDySaL6AJ",
-"FGzgpD6rBy","HP4330BmCy","cQOnvYh1hF","uJScXMmsIo","k85AeJJs5m","oGu6xAkKTk","he9IAjSjS3","W3VFH5Mg9r","t59lRStlDJ","K20wKfmIK1",
-"5Drn0Rxrsm","RsQUqFxX9q","XyPZNW3VFH","lCMxyd85a9","RzaZAlpF6W","kZANmtAOsr","W3VFHOUqFM","16lHcrz7Ut","2Yz7EhUTw7","iwzGkt59lR",
-"9iGoThSSvQ","0ao3lFhtgl","d7vjMKASQ8","24ARFiwzGk","nlaBypiJSk","yvOMI8TxD7","ECMvUFLsph","a00b5IRh48","FVMxo6q6L9","fcJOyIn3NS",
-"WMiS3jtn0X","KASQ8o8Uyd","0Kyfst98iW","Nxx9VAkKTk","cQOnvm4bxU","wDajXOHaBz","fcwDaru4UG","b29RJogLgc","v8yFNogLgc","QnJ1S2TRI7",
-"MezSWtaOXK","nFqikRBhp0","P6bcglpF6W","4dEz6jtn0X","UmaEvqUJMd","djsrvWaim6","RsQUqUl4a1","t59lR9GXkX","uLtKsJ2mQi","Uvlv4lCMxy",
-"cmXIXfqypy","0YAGHlH1kt","iwzGkUlU3M","OHaBzbgJAz","dmoS7I7p2a","ZJTXH5Drn0","JKWYROxWIH","2ZHdkP6bcg","jfREus93Ml","he9IAwDajX",
-"v1HlnksJby","uQIczyToGW","wiHrZs7Mxk","YOfrYpAhR1","b29RJ9iGoT","OHaBz0BmCy","ciuWzfLNg8","dhSuHRmDcr","RxrsmChuy3","QChxsQ6hMC",
-"gtCA5FVMxo","uZPqgpFrrl","cQOnvpFrrl","Ta8f6NOHsz","iKqhrn1pmO","VerEAfmIK1","ZzJHWjeskS","9GXkX9rlg9","0h1b1yofH3","Zv7z014FLR",
-"G1RhSBpYhV","K20wKhYBCK","pT8wuFxX9q","KZamHQworu","KASQ864s8N","HlUbFHP433","rKDLJDG4sT","tlILt45cIH","JKWYRjS1aj","hYBCKYOfrY",
-"9eoRcfcJOy","FcWrWYh1hF","ZUnqtJXljW","qaofNBCxeC","nlaByHzZT8","ru4UGMkgy8","1j5L8MK07Y","In3NSn1pmO","HzZT8fqypy","oVQp6VerEA",
-"NOHszK20wK","nnP8oHlUbF","X6PintuDyS","W7cTsIKxdL","Q6LixxXTI4","nnP8oVjCZq","Pb1pai7WMQ","k85AeoVQp6","5IhmGMGlTF","4QMc9uZPqg",
-"W3VFH9rlg9","ksJbyt59lR","QChxsokgRi","ZJTXHv1Hln","GSQwjK4GS8","iqv4kC2Irc","DQimp64s8N","7X3uyOUqFM","7fsYMtaOXK","Cp3mZzbIYY",
-"JRJQBD6rBy","hE1QlokgRi","l83UdjzUqR","JJs5mZv7z0","dmoS7OUqFM","bZLvSGXdoH","5nmWv5iGN5","0BmCyVBjhz","xReeclH1kt","5Drn0TXQ0Z",
-"nFqikIBe8k","jtn0XSmGzv","uTacx16lHc","HP433kB5nP","FhtglyEfy9","e6e4zSWfou","WreyPnFqik","uupzkdjsrv","qQxHPVLTy6","W3VFH8hJdt",
-"kB5nPZ4I1v","I7p2aGrDg7","jSjS3Cp3mZ","VBjhzBFkb8","ogLgcW7cTs","tvdkDZv7z0","FwEJz580YD","jeskSciuWz","yluBxEoToP","FLsphpWiOs",
-"7Ow5CAmdQd","MmsIojSjS3","QbxXcs4786","uZPqguoStw","FNYIMStlDJ","2DREsyvOMI","prNT6jfREu","QYxC0No0Qb","Cfgr3ZJTXH","pWiOsVNCPd",
-"8hJdtChuy3","bZLvSlH1kt","Fhtglx3LDe","9eoRclsQGo","BFkb8pAhR1","Dz1R35VZjS","2TRI72Nslm","07n1cQChxs","Uvlv4P6bcg","AkKTkjSjS3",
-"ReKEWL7cGc","fmIK1bZLvS","AXpwEgdQsS","uTacxQworu","QChxszQt6Q","aL6AJKsjRK","K20wKWaWsv","rz7UtRxrsm","AgJHQFnPFB","guMb8KsjRK",
-"lkMUAyToGW","AIYUu8FmFH","jSjS3pWiOs","hi5X7SmGzv","GXdoHgjUTu","ogLgcS77LH","Uvlv4djsrv","nFqikXflUq","hi5X7oGu6x","Nxx9Vs4786",
-"aez9yn1pmO","GWqqXrz7Ut","ZhwG1aez9y","BGaQYkZANm","Q6hMCW3VFH","Yh1hFrKDLJ","M3zXLPOUYS","lCMxyOxWIH","0PktIMaJQs","a00b5vkCHH",
-"Oz8yZfqypy","hi5X7FwEJz","gtCA5ECMvU","5VZjS9XyT9","bgJAz5ZaEz","oQ87rMaJQs","yofH3SjskQ","KZamHEoToP","S2Dfufqypy","kZANm2Yz7E",
-"MGlTFgtCA5","0MR5Xdjsrv","4dEz6h1zcH","Kr8ysU3yw5","uZPqg0PktI","S2DfuzqH0W","OUYuFsx5Gl","QChxsRsQUq","7X3uyFNYIM","AXpwEhi5X7",
-"v2eC3b29RJ","DLhzM1v5hH","mX2GEWMiS3","iKqhr29QAz","Yw2oUP6bcg","iB08lMK07Y","hUTw75iGN5","d7vjM6q6L9","NAFuwStlDJ","AXpwE580YD",
-"RACujprNT6","Q6hMCSmGzv","dQ586MmKGJ","24ARFY1mC0","VIlwPLewvM","uN6r3Mkgy8","Cfgr3IBe8k","tjQxspWiOs","NOHszhe9IA","k85Aedjsrv",
-"nlaByxciqp","lj07QuLtKs","xReecatef2","VjCZqKsjRK","Yf2EclH1kt","hi5X7okgRi","AkKTkK20wK","7hyVvMmsIo","0YAGHatef2","POUYSfcwDa",
-"VBjhz64s8N","uPX7GFFDui","Yh1hFQbxXc","hE1QlyvOMI","uTacxBpYhV","CIShGyToGW","D6rByQClRL","2Yz7EcShY2","zHF1qgjUTu","W7cTsJkzUn",
-"16lHcIn3NS","JJs5mdQ586","gdQsSDQimp","BCxeCwDajX","t98iWvkCHH","gIYvEqQxHP","OUqFMguMb8","5iGN5lCMxy","GSQwjPYBf4","WreyPFcWrW",
-"GrDg7pT8wu","jfREuHRxd8","Qworu45cIH","YjB9tatef2","VNCPdBbwgA","s4786MmKGJ","lm0pDi3pyd","rKDLJjzUqR","YOfrYjSjS3","7X3uyTCgPp",
-"5ZaEzuvf7A","5ZaEzFhtgl","Mkgy8DLhzM","cQOnvTwano","POUYSAOgEe","okgRilweGy","LbRTHNxx9V","2TRI7lViBv","BCxeCuTacx","i3pydwiHrZ",
-"7lUXZHRxd8","Q6Lixv2eC3","hi5X72ZHdk","v1HlnC2Irc","prNT6WaWsv","BFkb8v1Hln","JIqXiF6PT2","lm0pDNhXdu","JXljWF6PT2","ThjNnIBe8k",
-"2TRI7Uvlv4","bgJAztjQxs","0Wr5yIn3NS","5ZaEzC2Irc","zbIYYPOUYS","jS1ajWaim6","atef22ZHdk","JJs5mtjQxs","s93Ml7fKYU","MK07Y0MR5X",
-"AOgEegIYvE","hE1QlRACuj","uTacxIKxdL","uJScXSWfou","ksJbyWDVWJ","jfREu9XyT9","FwEJzcmXIX","55rfBokgRi","uQIczNAFuw","TCgPpMaJQs",
-"ru4UGG1RhS","pT8wuzz4ZU","6AFT0pAhR1","8RCUAHlUbF","5VZjSJXljW","PYBf4Dz1R3","jfREuoVQp6","P6bcghSSvQ","QClRLI7p2a","5NammFVMxo",
-"In3NSGSQwj","0PktIt59lR","Yw2oU1v5hH","1v5hHVNCPd","JXljWK20wK","CK5W7Pb1pa","i7WMQgIYvE","EOE1oBGaQY","jeskSVjCZq","uAWypK4GS8",
-"yofH3QnJ1S","29QAz0PktI","rKDLJStlDJ","n1pmOM6qcG","lCMxyFcWrW","aFFss9eoRc","QnJ1SuAWyp","uLtKsdjsrv","7hyVvUmaEv","Y1mC0cQOnv",
-"3otm6xReec","3otm655rfB","HfyNQECMvU","Mm8siX6Pin","jiVBPi7WMQ","xReecfLNg8","IjTwPFFDui","Chuy3zz4ZU","pWiOskB5nP","PYBf45Namm",
-"d7vjMFhtgl","yEfy9QnJ1S","lsQGotjQxs","gtCA5dpe1v","VBjhzyEfy9","9y4lwkB5nP","1v5hHuupzk","7X3uyyToGW","5drc6RmDcr","DG4sTfFDrJ",
-"F6PT2iKqhr","QChxs5ZaEz","EOE1o618Di","AOgEedQ586","FNYIMdhSuH","bgJAz9XyT9","Cfgr3hi5X7","fqypy8RCUA","GrDg7AmdQd","L7cGcVLTy6",
-"BbwgAWaWsv","pmeCdLDk6f","hE1QlGrDg7","M6qcGEoToP","DQimpuupzk","POUYSRACuj","SbRYy55rfB","AXpwEogLgc","VerEAi3pyd","cShY2Ss0Zu",
-"a00b5RsQUq","a00b5piJSk","bgJAzcmXIX","5ZaEze6e4z","s4786L7cGc","5iGN5b29RJ","hi5X79rlg9","qaofNYOfrY","cL0aE07n1c","ix74rjiVBP",
-"NOHsz4QMc9","v1Hln0Wr5y","LbRTHGrDg7","l83UdRBhp0","WMiS32Nslm","AmdQdhYBCK","pWiOspT8wu","7X3uyUl4a1","FVMxov2eC3","2Yz7EEOE1o",
-"ydG8Uru4UG","QWxoTU3yw5","zHF1qix74r","jS1ajogLgc","vOqCESjskQ","pv0i7X6Pin","FPfSE5Namm","vLsmSL7cGc","soy9txciqp","pWiOs5iGN5",
-"FwEJzBpYhV","y94nwtaOXK","fcJOy8xEKz","EdBKc14FLR","5Mg9rRmDcr","FhtglzmLYD","v2eC3s4786","bZLvSmz8gx","wiHrZbrhlQ","JXljWIKxdL",
-"zHF1qzQt6Q","MGlTFW7cTs","EOE1ojzUqR","9iGoTx3LDe","tlILtCp3mZ","FcWrWpWiOs","CNHmvRBhp0","tjQxsFjHXR","Dz1R3IBe8k","VerEAQssNC",
-"nnP8oQ6Lix","CqqaDDQimp","U3yw5uQIcz","sx5Gl5VZjS","LbRTHcShY2","B3qemgjUTu","yluBxYf2Ec","Dz1R35Drn0","b29RJ7Ow5C","yvOMIM3zXL",
-"VBjhzCfgr3","mz8gxBpYhV","KASQ814FLR","FLsph5Namm","HfyNQRsQUq","n1pmONhXdu","QClRL580YD","QworupFrrl","Yf2Ec2DREs","5nmWvaez9y",
-"SbRYyAOgEe","FwEJzNhXdu","fcJOyrKDLJ","MezSWNAFuw","VNCPdWaWsv","iqv4kLDk6f","IRh48GrDg7","Rxrsm3otm6","k85AeRpBQm","K4GS8ZJTXH",
-"BCxeCBbwgA","m4bxUMmKGJ","zQt6QMojnP","8TxD7W3VFH","uoStwhSSvQ","K4GS855rfB","dQ586pT8wu","s93MlJJs5m","AOgEeJKWYR","5Mg9rsx5Gl",
-"s93MlSs0Zu","OxWIHVNCPd","ZuDtDokgRi","ZuDtDmz8gx","0Wr5yVerEA","t59lR0PktI","W7cTsNhXdu","55rfB3otm6","9y4lw7ku1p","FNYIMlm0pD",
-"MmsIoVLTy6","t98iWJKWYR","hi5X7v8yFN","FPfSEWPmlx","Mm8siS77LH","Vprf2MmKGJ","BGaQYK20wK","AmdQdhi5X7","QChxsYf2Ec","GXdoHKr8ys",
-"FjHXRJIqXi","ogLgc5VZjS","ReKEWyluBx","4dEz6ni2v1","bgJAzb29RJ","Yf2EcbZLvS","ogLgcQClRL","RzaZACNHmv","0YAGHZUnqt","WreyPb29RJ",
-"M3zXLd85a9","PYBf45Drn0","BpYhVAXpwE","jfREu1j5L8","pFrrls7Mxk","6AFT0IRh48","LewvM4QMc9","BpYhVEoToP","okgRiGSQwj","JRJQB48cHL",
-"lH1ktFnPFB","iqv4kNOHsz","YjB9tni2v1","NhXduCfgr3","B3qem7hyVv","FjHXRs4786","OxWIHrKDLJ","Cp3mZuQIcz","7lUXZAXpwE","kB5nPIn3NS",
-"s7Mxkxciqp","FNYIMUmaEv","GXdoHlpF6W","JIqXi2Yz7E","ogLgcWPmlx","v2eC3t59lR","RpBQmrz7Ut","ReKEWrz7Ut","BGaQYZzJHW","AkKTkzz4ZU",
-"OHaBzDQimp","1j5L8uPX7G","7X3uyqaofN","2NslmdQ586","xciqpjS1aj","pAhR18xEKz","jiVBPWaWsv","RsQUq2TRI7","cQOnvrhl0J","5VZjS8hJdt",
-"e6e4z8U2nU","FFDuia00b5","O3iyQciuWz","580YDMaJQs","CxVEfzz4ZU","5Drn0HlUbF","uupzkRzaZA","ogLgc9eoRc","ni2v1K4GS8","RzaZAFwEJz",
-"D6rByMmsIo","jiVBP7ku1p","MezSWuZPqg","i7WMQCdyBV","JIqXiCxVEf","v1HlnzbIYY","0ao3l7ku1p","580YDt98iW","DQimpy94nw","K4GS8ZuDtD",
-"XyPZNUmaEv","rhl0JSmGzv","VNCPd8cVD3","ECMvUIRh48","618DioVQp6","O3iyQvLsmS","2Yz7EiB08l","zbIYYsoy9t","pT8wu45cIH","v1HlntaOXK",
-"soy9t2DREs","RpBQmSWfou","soy9tMm8si","jzUqR580YD","lXFOBQnJ1S","zY1GYQWxoT","FLsphfFDrJ","DcpWBQYxC0","BCxeCCIShG","rz7UtFLsph",
-"FLsphAXpwE","RxrsmJXljW","J2mQiTCgPp","9iGoT7fsYM","VIlwPRACuj","8TxD7qQxHP","BpYhVrhl0J","SbRYyK4GS8","JKWYRhe9IA","guMb8atef2",
-"14FLRYw2oU","FLsphReKEW","soy9tlXFOB","LewvMGWqqX","zz4ZUlpF6W","SmGzvdjsrv","ZhwG1aDGtS","zbIYYDz1R3","9GXkXM6qcG","LDk6ft59lR",
-"5VZjSgtCA5","Yf2EcOUqFM","HRxd8fqypy","rhl0JDQimp","uJScX580YD","piJSkFFDui","d85a99eoRc","suY4xLbRTH","RsQUqG1RhS","jS1ajD6rBy",
-"yToGWv8yFN","yEfy9ZUnqt","EoToP4QMc9","lpF6WqUJMd","7fsYM8cVD3","MaJQsHfyNQ","b29RJ7fsYM","rz7UtjiVBP","8TxD77fsYM","VNCPdgtCA5",
-"fFDrJPYBf4","IjTwP2hEEU","16lHcTa8f6","CNHmvJRJQB","QChxsfcJOy","0YAGH5IhmG","KsjRK7hyVv","MGlTFydG8U","bgJAzcShY2","In3NS0PktI",
-"580YDyEfy9","brhlQlweGy","s93MlhE1Ql","ThjNncQOnv","PYBf4QssNC","x3LDeS2Dfu","16lHcoGu6x","No0QbFPfSE","oGu6xSbRYy","d7vjMiKqhr",
-"gtCA54W0Tl","Oz8yZs7Mxk","5drc6dpe1v","GWqqXEdBKc","sx5GlokgRi","64s8NqQxHP","iKqhrJXljW","6AFT0pFrrl","iwzGkqaofN","k85Aex3LDe",
-"ZUnqt7fsYM","MezSWP6bcg","aFFssbgJAz","blLA9ZzJHW","GWqqX7Ow5C","tvdkDBFkb8","wDajXS77LH","d7vjM4QMc9","yofH3B3qem","Vprf2gIYvE",
-"VerEAdQ586","Chuy3l83Ud","FGzgpTwano","F6PT2tl72W","lCMxyKZamH","C2Irc7fKYU","xciqp0h1b1","Uvlv4fqypy","2TRI7VLTy6","gtCA5ZJTXH",
-"xReecv8yFN","zQt6Qt98iW","brhlQVNCPd","MaJQsyluBx","0BmCyzmLYD","JXljWgIYvE","i3pydkB5nP","IjTwPzY1GY","MezSWFwEJz","Z4I1v24ARF",
-"RpBQmhe9IA","CqqaDKr8ys","GWqqX0YAGH","dpe1viB08l","POUYSK20wK","v8yFNVNCPd","S77LHAIYUu","OHaBzjzUqR","jSjS3vOqCE","jeskSgjUTu",
-"ThjNno8Uyd","jzUqR3otm6","07n1c9rlg9","3weIF2Yz7E","vOqCEyToGW","6AFT0NcICA","Nxx9Vt59lR","vOqCEl83Ud","C2Ircxciqp","RpBQmLDk6f",
-"ZhwG1mX2GE","OUqFMix74r","s93Ml8U2nU","QYxC0gIYvE","W7cTs7fsYM","s7Mxkni2v1","GWqqX0BmCy","rKDLJpiJSk","wiHrZkZANm","Uvlv4HlUbF",
-"iKqhrkZANm","Oz8yZHRxd8","CxVEfrz7Ut","MGlTFmz8gx","zHF1qa00b5","JJs5mcmXIX","oVQp6DQimp","EdBKc3weIF","QworuFnPFB","B3qemiKqhr",
-"0MR5XUvlv4","VBjhzxXTI4","8TxD748cHL","Cfgr3GSQwj","55rfBIn3NS","IjTwPhe9IA","ZJTXH5Mg9r","o8UydFVMxo","B3qem618Di","YOfrY2TRI7",
-"PYBf46q6L9","o8UydFxX9q","ReKEWwiHrZ","Nxx9V1j5L8","ZUnqthUTw7","i7WMQ1j5L8","1j5L8IBe8k","he9IAiwzGk","Ul4a1WDVWJ","aez9yaFFss",
-"Yw2oUdjsrv","x3LDe8hJdt","D6rByyToGW","4QMc9rhl0J","48cHLlkMUA","zqH0WyluBx","prNT6ni2v1","qaofNGWqqX","lViBvQworu","WMiS3cmXIX",
-"jzUqRy94nw","07n1cbrhlQ","dmoS7JXljW","J2mQiZuDtD","2Yz7E8RCUA","uLtKsM6qcG","1LB1LuPX7G","tlILtjeskS","AmdQdKZamH","9rlg97hyVv",
-"AkKTkGWqqX","WmadA8TxD7","zHF1quLtKs","aFFssECMvU","oVQp6GrDg7","mz8gx5Drn0","MaJQsdhSuH","soy9tfqypy","ZuDtDgf8rI","rz7Utt59lR",
-"2TRI7v8yFN","FhtgltuDyS","ThjNnZzJHW","3weIFIjTwP","FPfSEx3LDe","9GXkXlpF6W","hUTw7qUJMd","9y4lwZv7z0","ZJTXHReKEW","tuDySOUqFM",
-"4W0TlzHF1q","VerEAQYxC0","jtn0XfaHir","euZA5WPmlx","brhlQIRh48","S2DfuBCxeC","dhSuHFhtgl","ZzJHWuLtKs","JRJQBnFqik","WPmlxYh1hF",
-"fmIK1Yw2oU","NhXduReKEW","djsrvQ6hMC","lH1kt9iGoT","ix74rKASQ8","1j5L8L7cGc","BFkb8cShY2","iKqhriwzGk","v8yFNAmdQd","oVQp6lCMxy",
-"brhlQFnPFB","24ARFjSjS3","euZA57fsYM","TCgPp64s8N","CIShGVNCPd","lsQGosqVrf","EOE1ojeskS","zHF1qhYBCK","Cfgr3b29RJ","oVQp6Waim6",
-"xciqptvdkD","euZA5I7p2a","okgRitlILt","Zv7z0dmoS7","xXTI41j5L8","29QAz07n1c","LDk6ffFDrJ","okgRiMK07Y","Kr8ysRkQke","uLtKszY1GY",
-"5drc65nmWv","Ss0ZuAgJHQ","4dEz6J2mQi","45cIHEdBKc","bgJAzdmoS7","gjUTuOUqFM","D6rBytlILt","M3zXLuAWyp","WMiS3yEfy9","2Yz7EuQIcz",
-"L7cGcaL6AJ","FNYIMTwano","5Drn0xReec","FGzgp0MR5X","I7p2aQWxoT","AIYUuuupzk","fLNg8L7cGc","JkzUny94nw","M6qcGCNHmv","EOE1oEdBKc",
-"lj07QoVQp6","ZuDtDpiJSk","Ul4a10h1b1","MojnPL7cGc","Pb1paMaJQs","No0Qb5drc6","pvgjSHfyNQ","gdQsSyToGW","v2eC3vkCHH","9y4lwLewvM",
-"xciqpRkQke","JkzUnCdyBV","GSQwjEOE1o","zY1GYWPmlx","Q6LixTa8f6","jfREupiJSk","lViBvVprf2","OUqFMHzZT8","tjQxslj07Q","okgRiSmGzv",
-"qQxHPECMvU","QWxoTUvlv4","taOXKprNT6","iqv4k0h1b1","24ARFOxWIH","jeskSnFqik","5drc6TCgPp","taOXKFFDui","l83Udn1pmO","pvgjSoVQp6",
-"618Di7Ow5C","RpBQmDQimp","QbxXcNcICA","3otm6QbxXc","uN6r3rz7Ut","7fsYMtuDyS","MK07YhUTw7","4W0Tl7Ow5C","8U2nUazIWp","VLTy6lkMUA",
-"tjQxs5Namm","TXQ0Z8FmFH","yluBxfFDrJ","lm0pDCxVEf","0h1b1QssNC","Uvlv4RsQUq","xReec2Yz7E","tlILtECMvU","Z4I1vBFkb8","ZzJHWtl72W",
-"YjB9t5Namm","5IhmGbgJAz","iqv4kQClRL","HzZT8No0Qb","BpYhV7fKYU","DcpWBVjCZq","8hJdt9rlg9","MezSWt59lR","pWiOs0MR5X","OHaBzxXTI4",
-"P6bcg9GXkX","SWfouVIlwP","6AFT0L7cGc","XyPZNMGlTF","DQimpW3VFH","uTacxdmoS7","NcICAlj07Q","atef2Chuy3","1j5L8RsQUq","s93MlQssNC",
-"uZPqgk85Ae","xXTI4xciqp","SjskQNhXdu","No0QbfLNg8","uQIczlweGy","QYxC0Gv3Fq","fcJOytAOsr","gdQsSjzUqR","QssNCuAWyp","t98iWDz1R3",
-"B3qemyvOMI","blLA9RACuj","29QAzYOfrY","vOqCExXTI4","9XyT9F6PT2","Dz1R3C2Irc","nnP8oTXQ0Z","CK5W7Rxrsm","s7MxkStlDJ","Ss0ZuvLsmS",
-"QYxC0StlDJ","tAOsr29QAz","MmKGJVLTy6","VIlwP0Kyfs","qQxHPh1zcH","MezSW9GXkX","Zv7z0gtCA5","NhXduuvf7A","1v5hHUvlv4","Ta8f69eoRc",
-"lH1ktmX2GE","FxX9qv1Hln","pFrrlFwEJz","RACujOxWIH","IRh48jeskS","I7p2abZLvS","sx5GlnnP8o","l83UdlsQGo","Mkgy8soy9t","d85a90PktI",
-"AgJHQgf8rI","lCMxymz8gx","iwzGk2TRI7","6q6L9UmaEv","v1HlnJ2mQi","FLsphFcWrW","jzUqRSbRYy","3otm6iKqhr","Gv3FquPX7G","vLsmSFLsph",
-"QChxso8Uyd","dpe1vblLA9","24ARFlkMUA","5ZaEzhSSvQ","zz4ZULbRTH","zz4ZUfcJOy","cQOnvFxX9q","x3LDeprNT6","MaJQssx5Gl","sx5GlKZamH",
-"jzUqRuJScX","MezSWo8Uyd","6AFT0GrDg7","BpYhVYf2Ec","lCMxyAOgEe","wDajXFNYIM","W7cTsTXQ0Z","1v5hHkB5nP","KZamHW7cTs","QssNCm4bxU",
-"K20wKQWxoT","nFqikoQ87r","LDk6fOHaBz","JkzUnQ6Lix","uQIcz64s8N","fcJOyVerEA","JIqXi0Wr5y","0h1b1SWfou","No0QbtaOXK","pmeCd0PktI",
-"GrDg7kB5nP","cShY2MezSW","hi5X7DcpWB","3otm6FVMxo","SjskQJJs5m","U3yw58hJdt","lj07Q3weIF","RxrsmgdQsS","guMb8WaWsv","zmLYDKASQ8",
-"gjUTuGSQwj","n8pJ9B3qem","0ao3lnFqik","NcICA4QMc9","WmadA2DREs","s478648cHL","IRh483weIF","JRJQBksJby","v8yFNOUYuF","WreyPChuy3",
-"U3yw5TXQ0Z","bgJAziqv4k","qUJMd9rlg9","9eoRcD6rBy","FPfSEjzUqR","LbRTHBpYhV","nFqik5Drn0","VLTy6WreyP","8xEKzJRJQB","CIShGtuDyS",
-"rKDLJuN6r3","No0Qbs93Ml","QworuQssNC","0PktInlaBy","yluBxpiJSk","zHF1qMkgy8","Vprf2JkzUn","cQOnvKsjRK","7X3uy8RCUA","uJScXmX2GE",
-"taOXKmz8gx","yluBx9GXkX","HRxd8ix74r","FLsphhSSvQ","0h1b19y4lw","VjCZqMojnP","Fhtgl2hEEU","LewvMuQIcz","Dz1R3uLtKs","4W0TljSjS3",
-"tlILtWPmlx","rhl0JAmdQd","C2Irc5IhmG","ThjNnFxX9q","h1zcHBCxeC","jS1ajZhwG1","Zv7z0RsQUq","AOgEezbIYY","WaWsv0YAGH","tjQxs8FmFH",
-"xciqpFwEJz","AOgEejS1aj","618DiCIShG","1v5hHzQt6Q","4QMc9fcJOy","s4786X6Pin","Q6hMCM6qcG","FcWrWQssNC","ydG8UDQimp","HfyNQ14FLR",
-"5NammtvdkD","5iGN5s93Ml","iB08lEOE1o","ThjNn5Namm","MGlTFuZPqg","55rfByofH3","qUJMdtvdkD","8xEKzh1zcH","o8UydXyPZN","i7WMQFVMxo",
-"tAOsrl83Ud","xXTI4RsQUq","atef2EOE1o","JkzUn1v5hH","RBhp05IhmG","gf8rIFGzgp","OxWIH9GXkX","zFgtBS2Dfu","AgJHQ6q6L9","aFFss5iGN5",
-"QWxoTgf8rI","l83Ud9y4lw","vLsmSOHaBz","KsjRKpv0i7","BFkb8Oz8yZ","0MR5XW3VFH","5VZjS8xEKz","v2eC3ZJTXH","ydG8UeuZA5","BpYhVuAWyp",
-"POUYSCqqaD","7X3uy24ARF","JKWYR5drc6","AgJHQSs0Zu","1LB1LMmKGJ","ECMvU5iGN5","nFqikMojnP","Y1mC0NcICA","HlUbFzFgtB","5Mg9rOxWIH",
-"QworuZzJHW","AIYUudQ586","lsQGoJXljW","9GXkXaL6AJ","dQ586RmDcr","0PktIpFrrl","uvf7AIBe8k","0YAGHD6rBy","JXljWdmoS7","wDajXMmKGJ",
-"LDk6fxReec","B3qemqUJMd","oGu6xFLsph","FLsphh1zcH","zqH0WS77LH","BbwgARzaZA","iwzGkVLTy6","07n1caDGtS","8U2nU8FmFH","ru4UGrhl0J",
-"OUYuFBCxeC","Ss0Zu8TxD7","kZANmsuY4x","7fsYM24ARF","RpBQmwDajX","0BmCyLewvM","jfREuWMiS3","0MR5Xk85Ae","5iGN5Ul4a1","RsQUqjzUqR",
-"0h1b1he9IA","GWqqXOUqFM","WaWsvdhSuH","gIYvEtAOsr","ksJbyFGzgp","5nmWvlViBv","VjCZqgIYvE","zbIYYGXdoH","zQt6Qatef2","lm0pDfaHir",
-"Q6hMCLDk6f","s4786DLhzM","UlU3MprNT6","FFDuirKDLJ","aL6AJ618Di","fmIK1ulk41","JXljWqQxHP","Ul4a1EOE1o","dpe1vxReec","mX2GEgf8rI",
-"Pb1paGXdoH","CqqaDUl4a1","5Mg9rQnJ1S","xciqpuTacx","SbRYyQWxoT","lpF6WNo0Qb","7hyVvv8yFN","MaJQsTa8f6","i3pyd0MR5X","ReKEWpmeCd",
-"ReKEWWaim6","Yf2EcNxx9V","SmGzvUvlv4","S2Dfu2ZHdk","9GXkX0h1b1","l83UdVprf2","DcpWBiKqhr","tuDyS16lHc","uvf7ABFkb8","Kr8ysaFFss",
-"VjCZqJ2mQi","FhtglTCgPp","SWfouRxrsm","QClRLRkQke","RsQUqWDVWJ","s93MluZPqg","JIqXiFjHXR","fcwDaWDVWJ","okgRi24ARF","Gv3Fq7X3uy",
-"14FLRJRJQB","yofH3JJs5m","6q6L9LDk6f","t98iWRmDcr","StlDJG1RhS","gjUTudpe1v","uTacxlpF6W","JkzUnUl4a1","ThjNnWreyP","gIYvEKZamH",
-"NAFuw7fsYM","jeskSuZPqg","hUTw72TRI7","XflUqnlaBy","rhl0JNo0Qb","O3iyQSmGzv","I7p2aWaWsv","qaofNEOE1o","piJSkG1RhS","FxX9qiKqhr",
-"CIShGtl72W","AOgEeguMb8","Chuy3XflUq","X6PinQworu","M6qcGzbIYY","Nxx9VB3qem","zQt6Q0Wr5y","qUJMdiqv4k","hE1QlWPmlx","RzaZAe6e4z",
-"ksJbyThjNn","Z4I1v1j5L8","ru4UGDLhzM","W3VFHkZANm","Z4I1v2TRI7","5Drn0lsQGo","Ta8f6Vprf2","lpF6W8xEKz","dpe1vDLhzM","YOfrYRkQke",
-"Q6LixMezSW","v1Hlnatef2","ru4UGZhwG1","oVQp6M3zXL","pAhR1tlILt","hi5X7tlILt","0Wr5ybrhlQ","qQxHP9rlg9","x3LDeQnJ1S","qUJMdGXdoH",
-"Waim6DcpWB","RBhp0mX2GE","aL6AJWPmlx","uZPqg7fKYU","FxX9qQ6Lix","TXQ0Zb29RJ","soy9tTwano","aL6AJe6e4z","gIYvEjS1aj","aFFssiB08l",
-"Q6hMCCIShG","FhtgllViBv","OUqFM8hJdt","oGu6xBCxeC","8xEKz48cHL","6q6L95iGN5","S77LH1j5L8","vkCHHcmXIX","b29RJPOUYS","7lUXZVNCPd",
-"kZANmgf8rI","xciqpSs0Zu","NOHsz5VZjS","cL0aEv2eC3","7fsYMlCMxy","dQ586Vprf2","XyPZNuZPqg","QbxXcReKEW","vkCHHDG4sT","2Yz7EyToGW",
-"IBe8k8RCUA","16lHcBGaQY","ZuDtDqQxHP","M3zXL2ZHdk","jiVBPbgJAz","qQxHPk85Ae","2ZHdkKsjRK","Waim6VBjhz","7fKYULDk6f","CNHmvBCxeC",
-"8cVD3aDGtS","D6rByVjCZq","n1pmORpBQm","zmLYD618Di","bgJAzdQ586","HP433suY4x","ReKEWy94nw","2hEEUMezSW","GrDg7MezSW","iB08lTCgPp",
-"BbwgAqUJMd","64s8Nlj07Q","jfREuuPX7G","wiHrZuJScX","lkMUAlXFOB","QClRLy94nw","M3zXLNhXdu","8cVD3SbRYy","5nmWvlsQGo","zz4ZU618Di",
-"hE1QlvkCHH","7X3uyxReec","djsrvblLA9","yluBxHP433","cL0aE2Yz7E","mz8gxtAOsr","QWxoTQClRL","DcpWBC2Irc","4QMc9hYBCK","MaJQsAXpwE",
-"gjUTuVBjhz","QYxC0suY4x","IBe8kfFDrJ","ciuWzCxVEf","D6rByYf2Ec","m4bxUVLTy6","uupzk7lUXZ","Yh1hF8FmFH","4QMc924ARF","jSjS3PYBf4",
-"5Drn05iGN5","zmLYDSjskQ","K20wKciuWz","M6qcGs93Ml","y94nwfcJOy","HP433RsQUq","kZANm8U2nU","45cIHjS1aj","TCgPpzbIYY","xciqpIKxdL",
-"8cVD3yEfy9","C2Irc9eoRc","vkCHHFjHXR","kZANmxciqp","HfyNQeuZA5","FjHXRsqVrf","mz8gx07n1c","6AFT07X3uy","Waim6CIShG","qUJMdPOUYS",
-"MK07YeuZA5","oQ87r580YD","HP4336AFT0","v2eC3xReec","gIYvEzqH0W","ThjNn9XyT9","t59lRlCMxy","tuDySlsQGo","Ss0ZuaDGtS","uLtKsjS1aj",
-"BbwgAK20wK","VBjhzDcpWB","zHF1qfFDrJ","MmKGJBbwgA","VBjhzVIlwP","jzUqRzqH0W","lj07QlkMUA","gIYvECfgr3","Gv3FqoQ87r","aDGtSGXdoH",
-"x3LDezbIYY","pT8wuzbIYY","CdyBV0BmCy","MmsIoydG8U","Uvlv4aL6AJ","BpYhV2TRI7","aDGtStlILt","lViBvksJby","CNHmvi7WMQ","VNCPd7hyVv",
-"5drc63otm6","9eoRcNAFuw","HfyNQni2v1","ZhwG1DQimp","iwzGkgjUTu","FNYIM4dEz6","dQ586VNCPd","RkQkeK4GS8","uoStwW7cTs","8TxD7v1Hln",
-"5ZaEzfqypy","6AFT0fFDrJ","v1HlnpmeCd","5Mg9rWPmlx","6AFT0iKqhr","8RCUAWDVWJ","fqypyHP433","hE1QlDLhzM","FPfSETXQ0Z","6q6L93otm6",
-"07n1ccL0aE","Cfgr3y94nw","zbIYYEOE1o","Chuy3WaWsv","5NammMmKGJ","AOgEepWiOs","07n1cqQxHP","Nxx9VuJScX","RBhp0rhl0J","BGaQYEOE1o",
-"3otm6Dz1R3","WMiS31j5L8","C2IrcD6rBy","piJSkAmdQd","o8UydkB5nP","Ul4a1DG4sT","zmLYDNo0Qb","IBe8kogLgc","i3pydAOgEe","vOqCEOUYuF",
-"8RCUAS2Dfu","jiVBP07n1c","fcwDaokgRi","ru4UG64s8N","MezSWtvdkD","55rfBFcWrW","tvdkDWreyP","618DiazIWp","xXTI4DLhzM","5drc6tjQxs",
-"0Wr5y9y4lw","HzZT85Drn0","Gv3FqrKDLJ","pWiOscQOnv","No0Qb5nmWv","cQOnvgtCA5","RBhp0Ul4a1","jSjS3QssNC","HzZT8nFqik","FcWrWLDk6f",
-"HlUbFAXpwE","jfREu8U2nU","v1HlnXflUq","8xEKzMmKGJ","DcpWBsqVrf","v2eC3TCgPp","nnP8oix74r","UlU3MECMvU","S77LHy94nw","Ss0Zurz7Ut",
-"t59lRsqVrf","HfyNQZUnqt","soy9tn8pJ9","YjB9tRmDcr","uJScXHRxd8","JkzUnStlDJ","Vprf2uTacx","PYBf4lsQGo","okgRiuN6r3","s93MlZzJHW",
-"vLsmSRpBQm","FNYIMix74r","OHaBziqv4k","aL6AJRpBQm","J2mQiVIlwP","s4786euZA5","48cHLgIYvE","uupzkFcWrW","hi5X7piJSk","vLsmSW7cTs",
-"NcICAwDajX","tlILt8FmFH","YOfrYIKxdL","Mkgy86q6L9","faHirQ6hMC","ZJTXHVIlwP","oVQp6AkKTk","9y4lw45cIH","aL6AJ2TRI7","WPmlxsoy9t",
-"Mkgy8WMiS3","tuDyS7Ow5C","7fKYUyvOMI","U3yw5Cfgr3","JXljWFLsph","GXdoHY1mC0","aFFssFxX9q","OHaBzk85Ae","RmDcrX6Pin","2DREsogLgc",
-"7ku1plViBv","XflUqjiVBP","ZuDtDtvdkD","C2IrchE1Ql","azIWpTCgPp","rz7Ut9XyT9","IBe8ktuDyS","gf8rIsoy9t","ZhwG1GWqqX","gtCA5oVQp6",
-"IjTwPB3qem","StlDJF6PT2","bZLvS2Yz7E","VjCZqlpF6W","m4bxUgtCA5","nlaBy16lHc","rz7UtpT8wu","2hEEUDz1R3","jS1ajydG8U","YOfrYrz7Ut",
-"FVMxopT8wu","uZPqgoGu6x","cL0aE2ZHdk","WaWsvO3iyQ","lkMUAFxX9q","J2mQiS77LH","n8pJ9BbwgA","FNYIMoVQp6","Uvlv4BbwgA","oVQp645cIH",
-"soy9tBpYhV","L7cGcZzJHW","0BmCyXflUq","FwEJzMmKGJ","EoToP5Drn0","cmXIXfcJOy","ix74rdjsrv","7lUXZJKWYR","YOfrYF6PT2","pmeCdNhXdu",
-"rKDLJF6PT2","3weIFzmLYD","pT8wuuAWyp","tvdkDBpYhV","CxVEfwiHrZ","pFrrlzHF1q","n8pJ929QAz","ciuWzs4786","HfyNQmz8gx","K4GS8Waim6",
-"qQxHPBFkb8","FhtglksJby","uJScXD6rBy","CK5W7MK07Y","xXTI4QbxXc","LDk6fcmXIX","9y4lwRsQUq","pv0i70PktI","wDajXRxrsm","AkKTkZhwG1",
-"atef207n1c","suY4xhYBCK","djsrvyluBx","P6bcgOxWIH","DG4sTJ2mQi","9GXkXazIWp","CIShGqUJMd","fmIK12hEEU","AgJHQFhtgl","K20wKRzaZA",
-"EdBKcS77LH","Oz8yZQ6hMC","iwzGkazIWp","W7cTspAhR1","n1pmOrKDLJ","0BmCy9eoRc","2DREss93Ml","b29RJYjB9t","faHirvLsmS","Yw2oU4W0Tl",
-"ZJTXHUmaEv","zqH0Wy94nw","uoStwy94nw","GXdoHSWfou","2DREsX6Pin","PYBf4lpF6W","TCgPpfmIK1","uvf7Auvf7A","zY1GY8hJdt","FxX9qKr8ys",
-"WmadAxciqp","uPX7Gh1zcH","pAhR1DQimp","FcWrWguMb8","IjTwPMezSW","9eoRc5Drn0","ulk41VBjhz","X6PinVerEA","hi5X7WaWsv","OxWIHiKqhr",
-"UmaEvpWiOs","rhl0JgjUTu","QWxoTbgJAz","tAOsrWmadA","O3iyQMezSW","8FmFH2Yz7E","uQIczn1pmO","lkMUApv0i7","JIqXiBbwgA","ReKEWd85a9",
-"FhtglQbxXc","Zv7z0K4GS8","2ZHdk7ku1p","J2mQi0ao3l","NcICAFxX9q","uvf7AStlDJ","azIWpvkCHH","ksJbyFjHXR","guMb8FNYIM","BbwgAQ6hMC",
-"lpF6WksJby","AgJHQF6PT2","qaofNFhtgl","vLsmS5iGN5","RACuj6AFT0","RACujjSjS3","d85a9I7p2a","cQOnvzqH0W","9rlg9BCxeC","J2mQiWaim6",
-"hUTw7G1RhS","CNHmvpv0i7","BGaQYSmGzv","9iGoTL7cGc","zY1GYRzaZA","FnPFBnnP8o","7X3uyRsQUq","5drc6QnJ1S","tuDySSmGzv","MGlTF8hJdt",
-"nFqiklH1kt","aL6AJ8FmFH","uN6r3sx5Gl","0BmCy1v5hH","vOqCE7lUXZ","Cp3mZFjHXR","rz7UtvLsmS","e6e4zMGlTF","FVMxoblLA9","cQOnvmz8gx",
-"07n1cdQ586","HfyNQDcpWB","LbRTHaez9y","yofH32DREs","OHaBz5nmWv","prNT6aDGtS","F6PT2UmaEv","QYxC0AXpwE","YOfrYRzaZA","Zv7z055rfB",
-"m4bxUDQimp","WreyPNOHsz","Ss0ZuWMiS3","taOXKL7cGc","3otm6zY1GY","DQimpMkgy8","0h1b1brhlQ","rz7Ut6AFT0","a00b5Nxx9V","0YAGHtaOXK",
-"SmGzv9iGoT","QChxsF6PT2","aL6AJrhl0J","nlaBybZLvS","OxWIHMm8si","VjCZqpmeCd","TXQ0ZDcpWB","taOXKd85a9","FnPFBQ6hMC","Nxx9VtAOsr",
-"RBhp0BFkb8","JJs5mQChxs","Dz1R3P6bcg","C2Ircv8yFN","618DiblLA9","7hyVvQClRL","6AFT0ix74r","TXQ0ZlXFOB","7X3uynlaBy","No0QbcmXIX",
-"FNYIM5nmWv","ix74rblLA9","Mkgy82Yz7E","gIYvEtjQxs","aDGtSlkMUA","VjCZqqUJMd","FVMxoL7cGc","k85AeBCxeC","Yw2oUcQOnv","0h1b1Waim6",
-"iB08lPb1pa","iB08lZhwG1","ciuWzrz7Ut","9rlg9Nxx9V","Pb1paFGzgp","8xEKzNcICA","Pb1pahE1Ql","lH1ktiqv4k","LewvM7hyVv","K20wKni2v1",
-"Z4I1v8RCUA","i7WMQNOHsz","faHirNxx9V","KsjRK16lHc","b29RJTXQ0Z","5iGN5Pb1pa","Y1mC0HP433","KZamHuTacx","VIlwPsoy9t","dpe1v2Yz7E",
-"y94nwrKDLJ","m4bxUBGaQY","Oz8yZQYxC0","pmeCdbrhlQ","okgRibZLvS","EoToPv2eC3","FPfSEMK07Y","yofH3Z4I1v","QnJ1SChuy3","Cfgr3BCxeC",
-"lweGyPYBf4","IBe8knnP8o","sqVrfvOqCE","jfREuUmaEv","atef2l83Ud","he9IAYw2oU","KZamHuJScX","cShY2FLsph","i3pydNAFuw","lXFOBdhSuH",
-"55rfBatef2","ReKEWNAFuw","L7cGcciuWz","CNHmv5Namm","LewvMAOgEe","CK5W7CqqaD","dmoS7xXTI4","ksJbyn1pmO","n8pJ9F6PT2","2hEEUFwEJz",
-"xciqpBFkb8","MmKGJmz8gx","MaJQsIBe8k","aDGtSuN6r3","LDk6fYw2oU","tjQxsY1mC0","FPfSEJKWYR","BbwgAy94nw","580YDsqVrf","StlDJ5nmWv",
-"ogLgcRACuj","mz8gx2ZHdk","aFFssuJScX","DG4sTfcwDa","OUYuFVerEA","VIlwPrhl0J","QWxoTCNHmv","d7vjMdQ586","he9IACxVEf","OUqFMa00b5",
-"wDajXlweGy","nFqikb29RJ","blLA9fqypy","2DREsaFFss","dhSuHFFDui","nnP8olpF6W","ciuWzIKxdL","S77LHCfgr3","CIShGgIYvE","P6bcguPX7G",
-"brhlQCfgr3","5NammeuZA5","Dz1R3ZzJHW","RxrsmStlDJ","n8pJ9pvgjS","BGaQYrKDLJ","14FLR0Wr5y","x3LDe5Mg9r","NhXduOHaBz","JRJQBLewvM",
-"uJScXjS1aj","pvgjSSWfou","pv0i7FLsph","Mkgy8aFFss","Chuy39iGoT","kZANmzz4ZU","0MR5X7ku1p","QWxoT7X3uy","WmadAlpF6W","fcJOyGSQwj",
-"EdBKcDz1R3","CqqaDzbIYY","AIYUu6AFT0","fLNg8vkCHH","CdyBViwzGk","rKDLJCqqaD","gIYvEHzZT8","gtCA5tl72W","Cp3mZ6q6L9","faHir2Yz7E",
-"M6qcGwiHrZ","pWiOs5nmWv","fcwDaK20wK","fcJOymX2GE","S2DfuuoStw","tlILtI7p2a","14FLRd7vjM","StlDJWmadA","WMiS34QMc9","1j5L8lsQGo",
-"0YAGH9rlg9","RsQUqUvlv4","yEfy9ZhwG1","DQimpNxx9V","64s8NXyPZN","taOXKtjQxs","KASQ80MR5X","5drc6d7vjM","W7cTsJ2mQi","Mm8siK20wK",
-"nlaBynnP8o","BbwgA2ZHdk","pWiOsaL6AJ","xXTI4FPfSE","HzZT8ix74r","QYxC0CqqaD","cShY2a00b5","FnPFBpv0i7","fqypygtCA5","gjUTu45cIH",
-"64s8N0YAGH","9eoRcuAWyp","IBe8kRzaZA","NOHsz7fsYM","suY4xQWxoT","MaJQsXyPZN","C2IrcIKxdL","BGaQYjS1aj","oGu6xBFkb8","1j5L8cL0aE",
-"4W0TljeskS","t59lRFVMxo","hi5X7QYxC0","zFgtBJ2mQi","tl72WCxVEf","t98iWlXFOB","aL6AJQworu","JJs5mk85Ae","I7p2aFxX9q","zY1GYfFDrJ",
-"IBe8kY1mC0","CNHmv9rlg9","MmsIoUmaEv","U3yw5RzaZA","9iGoTa00b5","DcpWBgIYvE","zHF1qAXpwE","TCgPpS77LH","VIlwPpAhR1","aDGtSM3zXL",
-"zY1GYbZLvS","RxrsmpvgjS","Yh1hFlweGy","GXdoHrKDLJ","a00b5580YD","yofH316lHc","xXTI4AgJHQ","5VZjSlXFOB","ogLgclH1kt","UmaEvG1RhS",
-"0MR5Xm4bxU","atef2suY4x","t98iWAIYUu","2ZHdknFqik","VLTy664s8N","yEfy9pvgjS","uJScXK4GS8","pFrrlMmKGJ","FVMxos93Ml","LbRTHCp3mZ",
-"No0Qbfqypy","IjTwPtl72W","5nmWvazIWp","Ta8f6FNYIM","t59lR8TxD7","Y1mC0aez9y","L7cGcRBhp0","AXpwEStlDJ","aDGtSEdBKc","WMiS3JXljW",
-"Chuy3gIYvE","taOXKCfgr3","0YAGHCIShG","5NammhSSvQ","zY1GYtuDyS","POUYScQOnv","2NslmEoToP","mX2GEhi5X7","uJScX3weIF","DQimp7lUXZ",
-"Ta8f6dhSuH","TCgPpcL0aE","k85AepT8wu","oGu6xJKWYR","Kr8yslkMUA","cmXIXnlaBy","AOgEea00b5","EoToPI7p2a","yofH3RsQUq","P6bcgWaim6",
-"QbxXc5nmWv","CK5W72DREs","5Drn07X3uy","taOXKUlU3M","FxX9q5Namm","3otm6fqypy","ZhwG15drc6","oVQp67Ow5C","jeskSFjHXR","7hyVvAIYUu",
-"0YAGHS77LH","HfyNQJkzUn","5VZjSG1RhS","I7p2aHfyNQ","CK5W7fFDrJ","AmdQdvLsmS","HlUbF4QMc9","W3VFHYf2Ec","2NslmTXQ0Z","GXdoHpv0i7",
-"DQimphSSvQ","taOXKlCMxy","LewvM45cIH","AkKTkWmadA","7hyVvBFkb8","G1RhSVjCZq","gjUTuciuWz","HlUbF7lUXZ","Z4I1vcQOnv","HfyNQyvOMI",
-"oGu6x3otm6","RzaZAMK07Y","dpe1vMojnP","9iGoTqQxHP","jSjS3s93Ml","07n1cQWxoT","jzUqR1v5hH","tAOsrhE1Ql","zqH0WaDGtS","Waim6OUYuF",
-"F6PT2v8yFN","2Yz7E580YD","v1HlnWDVWJ","WaWsvn1pmO","Uvlv4Mm8si","GSQwj8TxD7","vOqCEuoStw","7fsYMfcJOy","qQxHPJRJQB","C2IrcpAhR1",
-"AXpwEulk41","atef2PYBf4","v2eC38U2nU","uLtKscQOnv","vOqCEs93Ml","FNYIM2Yz7E","lpF6W2hEEU","JRJQB6AFT0","RmDcrsoy9t","pv0i7CxVEf",
-"9GXkXPYBf4","hSSvQuJScX","uLtKsM3zXL","ru4UGCdyBV","ThjNnvOqCE","WDVWJCp3mZ","Ta8f6vkCHH","n1pmO5Mg9r","CxVEfyvOMI","XyPZNRxrsm",
-"4dEz6s4786","KZamHwiHrZ","M6qcGTwano","0YAGHbrhlQ","uvf7AWPmlx","x3LDeGXdoH","ThjNn4W0Tl","aDGtS9y4lw","AkKTklj07Q","uZPqgv2eC3",
-"HfyNQoQ87r","sx5GlCdyBV","s93MlVprf2","cShY2lsQGo","9XyT948cHL","Gv3FqlweGy","yToGW0PktI","rKDLJkZANm","M6qcG1LB1L","fFDrJQnJ1S",
-"5Mg9rJJs5m","qaofN16lHc","VIlwP0BmCy","0Kyfsl83Ud","qUJMdKsjRK","SWfouQworu","guMb8YjB9t","VerEAuLtKs","Dz1R3K4GS8","FFDuiqaofN",
-"P6bcgpvgjS","64s8NQbxXc","8TxD714FLR","8TxD7bZLvS","W7cTsStlDJ","ni2v1hUTw7","yToGW64s8N","zbIYYWaim6","ZhwG1faHir","SjskQpv0i7",
-"ThjNnQnJ1S","aFFssa00b5","lj07QVIlwP","5VZjSDG4sT","FxX9qBbwgA","prNT6ksJby","tAOsrgjUTu","OxWIHAIYUu","FhtglprNT6","ZJTXHzmLYD",
-"FwEJzuAWyp","ReKEWuupzk","Kr8ysM3zXL","zbIYYCIShG","iqv4k45cIH","hYBCKyEfy9","4QMc9yEfy9","yvOMIjeskS","d7vjMuPX7G","9eoRclpF6W",
-"0h1b1QnJ1S","uPX7GsqVrf","Waim6suY4x","8hJdtIRh48","14FLRThjNn","X6Pin0Kyfs","brhlQEOE1o","XyPZNDLhzM","JRJQBZUnqt","F6PT2i7WMQ",
-"NhXduMezSW","XyPZNoVQp6","uupzk0YAGH","vLsmSciuWz","uJScXB3qem","HRxd8aDGtS","0PktIwDajX","7fKYUYjB9t","CK5W7Qworu","n1pmO2Yz7E",
-"iB08lNxx9V","BpYhV5iGN5","t98iW0MR5X","EOE1oMm8si","t59lR8hJdt","zQt6QnlaBy","24ARFgtCA5","DG4sTFFDui","5NammoVQp6","9rlg9StlDJ",
-"WmadAgdQsS","tl72W7ku1p","KASQ8uPX7G","LbRTH7fsYM","vOqCE7Ow5C","RBhp0WMiS3","X6Pin8FmFH","Pb1paP6bcg","RpBQmCp3mZ","i3pydW7cTs",
-"JKWYRZJTXH","jSjS3suY4x","v2eC3JJs5m","BpYhVhYBCK","cQOnvGv3Fq","o8UydeuZA5","iKqhrRpBQm","jfREumX2GE","BFkb8UlU3M","GSQwj5IhmG",
-"JXljW3weIF","zQt6QMkgy8","wDajXv2eC3","ni2v1EOE1o","W3VFH9XyT9","2Yz7EiwzGk","cL0aEdpe1v","yEfy9s7Mxk","x3LDeECMvU","FnPFBuvf7A",
-"I7p2aYjB9t","FGzgpPOUYS","h1zcH64s8N","suY4xd7vjM","580YDn1pmO","he9IAZJTXH","AIYUuiB08l","0ao3lRBhp0","d85a9vLsmS","ReKEWdhSuH",
-"wiHrZPOUYS","NOHszOHaBz","rz7UtIBe8k","okgRiDG4sT","ECMvUi3pyd","RzaZAv1Hln","3otm6v2eC3","LDk6fFjHXR","tAOsrBFkb8","7fsYMJkzUn",
-"tvdkD9rlg9","0h1b1lkMUA","jeskSyToGW","8xEKzThjNn","hUTw79GXkX","iB08lgtCA5","i7WMQgtCA5","SjskQ9iGoT","hi5X7tAOsr","24ARFHfyNQ",
-"QbxXcdjsrv","QworuMkgy8","aL6AJ07n1c","45cIHpiJSk","DQimpEoToP","UmaEvXflUq","azIWpQssNC","aL6AJZ4I1v","uLtKsFGzgp","VBjhz9rlg9",
-"hE1QlCK5W7","FnPFBt98iW","4dEz69iGoT","yluBxn8pJ9","5IhmGJKWYR","MmsIoZUnqt","AgJHQs4786","55rfBWaim6","Oz8yZd7vjM","t59lRECMvU",
-"jSjS38TxD7","nFqikQChxs","SjskQjiVBP","ulk4148cHL","Z4I1vsqVrf","1LB1L2hEEU","uupzk1j5L8","MK07YWaim6","ni2v15VZjS","ksJby6q6L9",
-"zQt6QFLsph","POUYSRmDcr","rz7Utxciqp","JIqXitvdkD","v1HlnZUnqt","n8pJ9AgJHQ","9rlg95iGN5","8cVD3ru4UG","FFDui8TxD7","xciqpv1Hln",
-"faHirl83Ud","y94nwOUYuF","L7cGcxciqp","5iGN5IKxdL","1LB1LVprf2","U3yw5Oz8yZ","WPmlxFNYIM","TCgPp4dEz6","580YDIjTwP","7fsYMCxVEf",
-"VjCZqxReec","cmXIXhe9IA","yEfy9OHaBz","yToGWs4786","Ta8f68xEKz","iwzGklViBv","mz8gxjS1aj","OxWIHfFDrJ","RmDcrRxrsm","okgRiQChxs",
-"s93MlPYBf4","29QAzFcWrW","2DREss4786","JJs5mpAhR1","WreyPqQxHP","GSQwjrKDLJ","StlDJ7fKYU","HfyNQRxrsm","v1HlnZ4I1v","Gv3FqJ2mQi",
-"Z4I1v618Di","e6e4zIRh48","NhXduL7cGc","CdyBVnFqik","NAFuw8TxD7","oVQp6IjTwP","jfREunFqik","fFDrJt98iW","uTacxoGu6x","KsjRK8U2nU",
-"6q6L9soy9t","uJScXru4UG","tuDyStuDyS","2NslmoQ87r","UmaEvhe9IA","PYBf4ReKEW","0MR5X2Yz7E","nlaByMaJQs","5NammYOfrY","fFDrJjfREu",
-"uPX7G8RCUA","b29RJ7X3uy","zz4ZUPYBf4","QbxXctlILt","3weIFeuZA5","MezSWVBjhz","TXQ0ZJJs5m","FPfSEU3yw5","MojnPQWxoT","TCgPptAOsr",
-"7fKYUCIShG","AIYUuDLhzM","9rlg9d85a9","RkQke45cIH","piJSkKr8ys","NcICAFVMxo","bgJAzEOE1o","iB08l48cHL","yEfy9cL0aE","jfREubrhlQ",
-"n8pJ9fLNg8","VIlwPIKxdL","F6PT2CNHmv","tuDySogLgc","azIWpnnP8o","vLsmS7fKYU","tvdkDHfyNQ","taOXKOUYuF","JRJQBfmIK1","QYxC02Yz7E",
-"K20wKYf2Ec","WDVWJ5IhmG","TwanoYOfrY","Q6hMCECMvU","ZUnqtzQt6Q","WaWsv7fsYM","Kr8ysQnJ1S","5ZaEzK20wK","Yf2Eci7WMQ","SjskQJ2mQi",
-"dQ586rz7Ut","xXTI42DREs","soy9tZUnqt","S2DfuStlDJ","a00b5iB08l","FwEJzLDk6f","fcwDaThjNn","MezSWIKxdL","0Kyfsatef2","OHaBzwDajX",
-"i3pyd618Di","h1zcHDcpWB","ksJbyaDGtS","S77LHaL6AJ","9y4lwBGaQY","D6rBy6q6L9","lsQGopWiOs","fFDrJXflUq","SbRYypWiOs","2Yz7EEoToP",
-"5Mg9r7fKYU","StlDJaDGtS","yToGWAXpwE","djsrvpvgjS","2Yz7EWreyP","IKxdLuTacx","fLNg84W0Tl","atef2LbRTH","7hyVvJkzUn","qQxHPjS1aj",
-"fcwDatAOsr","Yw2oUK4GS8","W7cTs2DREs","ksJbyVprf2","VIlwPcShY2","HlUbF5nmWv","OUqFMsqVrf","NAFuwSmGzv","Chuy3AXpwE","t59lRyToGW",
-"Q6hMCWPmlx","QChxs7Ow5C","d7vjMQYxC0","aez9yVprf2","kZANmuJScX","CK5W7kB5nP","AmdQdfqypy","TCgPpaez9y","hSSvQn8pJ9","tl72WS2Dfu",
-"BFkb8qQxHP","B3qemCqqaD","6q6L9tlILt","qaofNprNT6","tl72WfcwDa","v1HlnaFFss","UmaEvwiHrZ","CK5W7BGaQY","SbRYy5ZaEz","1LB1Ln8pJ9",
-"uupzkpvgjS","HRxd8JkzUn","0MR5XKsjRK","uoStwlsQGo","Yf2EcwDajX","ulk41oVQp6","LbRTHAXpwE","d85a95VZjS","jSjS3ru4UG","azIWp5Namm",
-"Ta8f6hi5X7","S2DfuNAFuw","7fsYMAgJHQ","FGzgpEOE1o","atef2SmGzv","LewvMhi5X7","8U2nUlweGy","i3pydD6rBy","C2IrcMkgy8","0BmCyZ4I1v",
-"oVQp6Cp3mZ","0BmCyCK5W7","ciuWzZJTXH","M6qcGBFkb8","dQ586v1Hln","iwzGk48cHL","8cVD3C2Irc","MmKGJSWfou","8U2nUFLsph","2NslmMGlTF",
-"FcWrWNOHsz","nnP8ot59lR","taOXKfLNg8","v2eC348cHL","rhl0JZv7z0","uupzkEoToP","qQxHPbrhlQ","rz7UtJKWYR","2Yz7E8cVD3","yvOMItlILt",
-"Cp3mZVNCPd","t98iWaFFss","I7p2ajfREu","NAFuw16lHc","sqVrf8hJdt","AmdQdn8pJ9","LewvMfaHir","IjTwPnFqik","cShY2BGaQY","iKqhrHzZT8",
-"suY4xECMvU","Mm8siTa8f6","2ZHdkuZPqg","K20wKfFDrJ","07n1cgjUTu","cShY2MojnP","ZUnqtW7cTs","ReKEWFnPFB","uupzkY1mC0","55rfBRzaZA",
-"lkMUA7X3uy","AOgEeHfyNQ","qUJMdyvOMI","0YAGHkZANm","5NammPb1pa","euZA5fFDrJ","7ku1p9GXkX","kZANmdpe1v","2hEEUnlaBy","NAFuwZ4I1v",
-"8FmFHatef2","iqv4kNcICA","bZLvSdpe1v","a00b5he9IA","0h1b1Dz1R3","0ao3lHfyNQ","xXTI416lHc","v1HlnFxX9q","7fsYMGSQwj","CIShGrKDLJ",
-"L7cGcU3yw5","RsQUqQbxXc","6AFT0Ul4a1","HRxd8lpF6W","fLNg8HP433","QChxs5VZjS","24ARF0BmCy","HP433Vprf2","LbRTHazIWp","9eoRcn8pJ9",
-"LbRTHtvdkD","fqypy14FLR","CNHmvpFrrl","DcpWB8U2nU","iqv4k6AFT0","OUYuFFLsph","lXFOBYjB9t","t59lRVNCPd","piJSkDcpWB","pFrrlMaJQs",
-"fFDrJ4QMc9","6AFT0VerEA","Nxx9VOxWIH","HfyNQlViBv","NOHsz5Drn0","RBhp00PktI","jeskSuvf7A","XflUqWDVWJ","MojnPQClRL","IjTwPl83Ud",
-"FNYIMprNT6","rKDLJjtn0X","5nmWvguMb8","qQxHPHlUbF","GrDg7ksJby","BpYhVjeskS","zz4ZUs4786","fLNg80PktI","14FLRpmeCd","IRh48Waim6",
-"MezSW16lHc","faHirrKDLJ","cShY2KASQ8","C2IrcsqVrf","F6PT2W7cTs","piJSk07n1c","QbxXcIjTwP","tjQxsHfyNQ","cmXIXlweGy","2TRI7CNHmv",
-"vOqCEcQOnv","FxX9qrhl0J","6AFT0fcwDa","soy9tIKxdL","9iGoTvLsmS","3otm62Yz7E","29QAzCfgr3","aFFssHP433","jeskSSWfou","t98iWv8yFN",
-"uTacxi3pyd","BFkb8Rxrsm","8RCUAiqv4k","0PktI16lHc","5iGN5jiVBP","x3LDeTCgPp","bZLvS1v5hH","6q6L9F6PT2","QbxXcW7cTs","RmDcrVerEA",
-"QbxXcvkCHH","kZANmfqypy","M3zXL45cIH","fcJOyUlU3M","GWqqXb29RJ","4QMc99rlg9","lXFOBni2v1","8RCUAbgJAz","zbIYYpvgjS","EoToPt59lR",
-"CIShGMaJQs","48cHLUvlv4","hi5X7zFgtB","iqv4kYh1hF","lCMxyni2v1","kZANmKsjRK","lXFOBpvgjS","QChxstuDyS","3weIF2hEEU","gf8rIjtn0X",
-"tjQxsK20wK","B3qemsqVrf","t98iWK4GS8","pT8wuI7p2a","MmsIouQIcz","s4786QYxC0","jtn0X7lUXZ","uJScXO3iyQ","7hyVvuN6r3","XflUq7fsYM",
-"OHaBzXyPZN","mz8gxKsjRK","Uvlv4uoStw","GSQwjb29RJ","qQxHPqQxHP","9y4lw9XyT9","d85a9MK07Y","4dEz6Gv3Fq","X6PinQWxoT","pv0i76q6L9",
-"GWqqXW3VFH","t98iW0Wr5y","LDk6flViBv","b29RJNhXdu","cShY28RCUA","LbRTHFjHXR","IjTwP2ZHdk","QWxoThYBCK","BFkb8ksJby","Gv3Fq2TRI7",
-"sx5GlFwEJz","0ao3lPb1pa","fmIK1ECMvU","3otm67fsYM","mX2GE5iGN5","gf8rIaez9y","jSjS3ReKEW","JKWYRGWqqX","MmsIo5Mg9r","yvOMIiKqhr",
-"jtn0XlH1kt","oVQp6tl72W","YOfrYy94nw","nFqikB3qem","Waim6uAWyp","SWfoupiJSk","AkKTkVerEA","nlaBy2Nslm","qaofNb29RJ","CNHmvVjCZq",
-"JXljW6q6L9","QYxC0JRJQB","8cVD3y94nw","16lHcv8yFN","L7cGcIRh48","Ta8f63weIF","pvgjSChuy3","KZamHd85a9","Pb1paMmKGJ","y94nwpvgjS",
-"FVMxoa00b5","FwEJzBGaQY","FcWrWzmLYD","StlDJogLgc","WmadAb29RJ","euZA5VBjhz","OxWIHFnPFB","TwanofcJOy","UmaEv1LB1L","zmLYD16lHc",
-"B3qemhi5X7","FwEJzJIqXi","hUTw7ZuDtD","FcWrWlweGy","mz8gxSmGzv","uQIczd85a9","J2mQiFFDui","iwzGktlILt","lXFOBpT8wu","HlUbF0Kyfs",
-"HzZT8RBhp0","zmLYD0BmCy","BbwgAru4UG","8cVD38cVD3","8RCUANAFuw","h1zcH5VZjS","euZA5AXpwE","OUqFMlj07Q","UmaEvhE1Ql","7fsYMuvf7A",
-"RmDcrG1RhS","oQ87rNOHsz","5VZjS8TxD7","pWiOsYOfrY","AkKTkX6Pin","48cHL5ZaEz","VBjhzEoToP","SbRYy64s8N","7fsYMlViBv","yluBxnnP8o",
-"LewvM5iGN5","uAWypOUqFM","tvdkDD6rBy","pmeCdhi5X7","29QAzRzaZA","CNHmvuPX7G","16lHcgdQsS","UlU3MQnJ1S","3weIF4dEz6","MGlTFdhSuH",
-"XyPZNZUnqt","SbRYyVBjhz","Yh1hFdQ586","RzaZALewvM","5ZaEzFjHXR","d7vjM580YD","sqVrfWmadA","x3LDegIYvE","RACujpAhR1","kB5nPQworu",
-"faHiroVQp6","uPX7GuPX7G","OUYuFaL6AJ","BGaQY07n1c","FFDuirhl0J","dpe1vjS1aj","AOgEeni2v1","EOE1oFLsph","2Yz7EWDVWJ","FNYIMtAOsr",
-"Y1mC0MmKGJ","2hEEUAIYUu","I7p2abrhlQ","soy9t5ZaEz","uvf7AfLNg8","yluBxO3iyQ","2Yz7ENOHsz","x3LDe2Yz7E","RpBQms4786","Mm8siqaofN",
-"7X3uyd7vjM","GrDg7blLA9","e6e4zgtCA5","djsrvRkQke","4dEz6RkQke","dmoS79GXkX","IRh489rlg9","No0QbWPmlx","BpYhVzbIYY","Rxrsm9y4lw",
-"y94nw8xEKz","MaJQsRpBQm","ZhwG1Q6hMC","AXpwE5Mg9r","AkKTkY1mC0","OUYuFYOfrY","ni2v1ZhwG1","D6rByjtn0X","580YDvLsmS","uJScX4W0Tl",
-"0ao3lMm8si","ni2v1iKqhr","jtn0X8hJdt","uAWypbrhlQ","jtn0X2Yz7E","qaofNfqypy","wiHrZTa8f6","07n1cZv7z0","KZamHt59lR","lm0pDQClRL",
-"Uvlv4FPfSE","iB08lReKEW","9eoRcyEfy9","wDajXUvlv4","lsQGo5Mg9r","n1pmObgJAz","IjTwPguMb8","AIYUulkMUA","3otm664s8N","QChxsECMvU",
-"VIlwPlH1kt","FnPFBlpF6W","55rfBCxVEf","SmGzv6q6L9","C2Irc16lHc","QnJ1SCIShG","QworuKASQ8","cL0aEv1Hln","Cp3mZtvdkD","8xEKzoQ87r",
-"In3NS1j5L8","24ARFpWiOs","l83UdwiHrZ","5ZaEz8U2nU","MezSWAgJHQ","2hEEUgjUTu","AOgEepFrrl","gIYvE0BmCy","e6e4zt98iW","azIWptAOsr",
-"hUTw7FNYIM","WDVWJ55rfB","ZJTXHZzJHW","uN6r3kZANm","MezSWmX2GE","Q6LixK4GS8","K4GS8KZamH","DLhzMaL6AJ","QssNCazIWp","d85a9X6Pin",
-"piJSkaDGtS","gIYvEpT8wu","uoStwWDVWJ","2TRI70Wr5y","lj07Q9eoRc","W3VFHxXTI4","dQ586ThjNn","2DREsMK07Y","Z4I1v7fsYM","vOqCEuPX7G",
-"cmXIXtAOsr","l83UdCp3mZ","t98iWydG8U","sx5Gld7vjM","Kr8yshe9IA","5Mg9rXyPZN","jtn0XWPmlx","uTacx0BmCy","Zv7z0Z4I1v","v2eC3zHF1q",
-"CxVEfnlaBy","QClRLm4bxU","pv0i7LDk6f","rhl0JhSSvQ","uAWyps4786","iB08lpv0i7","9XyT9BFkb8","7fKYUHP433","pWiOs4QMc9","RACuj5nmWv",
-"WaWsvCxVEf","KZamHvOqCE","MaJQsjfREu","n1pmOF6PT2","ZzJHWdQ586","SWfoulXFOB","9rlg9oGu6x","JIqXicShY2","KZamHdjsrv","fmIK1K4GS8",
-"Z4I1vyvOMI","RpBQmjSjS3","RBhp0okgRi","GWqqXXflUq","QbxXcAkKTk","CK5W7B3qem","piJSkjS1aj","Pb1pav2eC3","7fsYMvkCHH","m4bxUQnJ1S",
-"MmsIoP6bcg","Pb1papiJSk","CdyBVbrhlQ","fcJOypWiOs","DLhzMStlDJ","lweGyReKEW","8xEKzkB5nP","RxrsmlsQGo","K20wKv8yFN","yvOMI4W0Tl",
-"6q6L9pvgjS","yvOMIyToGW","BCxeCUvlv4","h1zcHQworu","JKWYRYw2oU","LDk6fjiVBP","Dz1R3HRxd8","AOgEeh1zcH","LDk6fRxrsm","8FmFHRpBQm",
-"uoStwKsjRK","hi5X7fLNg8","8FmFHgf8rI","mX2GEFhtgl","jtn0XjSjS3","blLA9StlDJ","55rfB3weIF","x3LDeO3iyQ","RpBQmX6Pin","EdBKcP6bcg",
-"ni2v17hyVv","qaofNFwEJz","Ul4a1uPX7G","Y1mC0Yh1hF","0h1b1Yw2oU","QClRL1LB1L","NOHszQnJ1S","aDGtS2ZHdk","8cVD32Nslm","1v5hH1LB1L",
-"hYBCKiqv4k","yEfy9v8yFN","QssNCcL0aE","hi5X7s4786","2NslmWMiS3","FPfSEpWiOs","pvgjSFVMxo","LDk6fPYBf4","pvgjS8cVD3","tjQxsL7cGc",
-"OxWIHRzaZA","EdBKczQt6Q","VBjhzuvf7A","8hJdtW3VFH","Ss0ZuW3VFH","7ku1p29QAz","uoStwqUJMd","8xEKzzY1GY","yvOMItuDyS","kZANmMmsIo",
-"xReecfmIK1","o8UydQworu","xciqpzz4ZU","7X3uyIn3NS","RBhp0GSQwj","lXFOB0h1b1","jzUqRpT8wu","HlUbFKZamH","h1zcHgIYvE","cmXIXJXljW",
-"6AFT0zmLYD","Q6hMCzHF1q","5iGN5B3qem","Dz1R3NAFuw","TCgPpChuy3","0PktIydG8U","soy9t45cIH","fqypyjSjS3","2DREssoy9t","Z4I1vQYxC0",
-"9GXkXTXQ0Z","NcICAQYxC0","yofH3Rxrsm","MmsIoIKxdL","dpe1v4dEz6","sx5GlQWxoT","GrDg78RCUA","2DREsD6rBy","Waim6QWxoT","yEfy9HzZT8",
-"VerEAlpF6W","I7p2aUlU3M","FGzgpFhtgl","tAOsrFhtgl","HP43348cHL","lsQGoLewvM","M6qcGDLhzM","S77LHFVMxo","bgJAzTXQ0Z","mX2GEuPX7G",
-"n8pJ9Uvlv4","F6PT2yvOMI","RmDcrGXdoH","WmadAEOE1o","XyPZNQClRL","29QAzokgRi","pv0i7kZANm","Yf2Ec7ku1p","KASQ8fcwDa","jzUqRaDGtS",
-"nFqik14FLR","Pb1palweGy","AIYUuOz8yZ","64s8NlsQGo","5drc6v2eC3","0KyfsNOHsz","OHaBzlXFOB","JJs5mdhSuH","3weIFdpe1v","pT8wudQ586",
-"8U2nUOUYuF","4QMc9lweGy","jS1ajJJs5m","0YAGHKsjRK","FVMxolj07Q","FwEJz5iGN5","Kr8ysThjNn","FFDuiJKWYR","ZJTXHQWxoT","7ku1pIBe8k",
-"he9IA7hyVv","WDVWJpiJSk","Yw2oU24ARF","d85a9Kr8ys","FLsphHP433","LbRTHpv0i7","AIYUuI7p2a","iqv4kEOE1o","y94nwW7cTs","6q6L9P6bcg",
-"pAhR1BFkb8","djsrvt59lR","NcICA4dEz6","5Mg9r6AFT0","d85a9580YD","X6Pin4QMc9","pmeCdy94nw","MGlTFfcwDa","RBhp0jzUqR","618DiFFDui",
-"W3VFH7hyVv","hYBCKGv3Fq","8cVD3nFqik","qUJMdTCgPp","64s8NkZANm","FjHXR29QAz","rz7UttlILt","YjB9trz7Ut","IRh48guMb8","Kr8ysHlUbF",
-"Cp3mZQworu","8U2nUSWfou","e6e4zHRxd8","GrDg7HP433","fmIK1TCgPp","gdQsSLewvM","prNT6soy9t","FLsphe6e4z","d7vjMQworu","qUJMdNOHsz",
-"uoStw07n1c","WPmlxrKDLJ","0MR5XQWxoT","ogLgcF6PT2","kB5nP7Ow5C","JKWYRMojnP","t59lRdjsrv","RkQkeatef2","DcpWBG1RhS","atef2BGaQY",
-"YjB9tsuY4x","BFkb8nFqik","aFFssgjUTu","dhSuH5IhmG","s7MxkvLsmS","Dz1R3Waim6","xReecfqypy","tl72WMmsIo","7hyVvGv3Fq","i7WMQD6rBy",
-"VIlwPpFrrl","vkCHHHlUbF","M3zXL5ZaEz","3otm607n1c","G1RhSgtCA5","U3yw58TxD7","Chuy3xReec","P6bcgy94nw","7fKYUQ6Lix","TwanoJIqXi",
-"lCMxyGrDg7","Kr8ys9eoRc","JXljWwiHrZ","h1zcHM6qcG","QssNCKZamH","FPfSEXflUq","FhtglhE1Ql","LewvMW3VFH","dhSuHlCMxy","SmGzvsuY4x",
-"WPmlxPb1pa","QbxXcCfgr3","a00b5prNT6","Rxrsm6AFT0","d85a9bZLvS","QClRLlXFOB","k85AeFhtgl","FNYIMb29RJ","Y1mC0S77LH","pv0i7W3VFH",
-"5iGN5S77LH","3weIFTwano","XyPZNprNT6","hSSvQMmsIo","3weIFGv3Fq","rhl0JLewvM","QChxsUvlv4","RsQUqpv0i7","FcWrWzY1GY","hUTw7uvf7A",
-"0MR5X580YD","2ZHdk7lUXZ","GrDg7v2eC3","8FmFHlweGy","QworudQ586","5Mg9ruLtKs","0Wr5y0BmCy","CqqaDt59lR","k85Ae5Mg9r","RxrsmRxrsm",
-"wiHrZpvgjS","soy9tUlU3M","Y1mC0qQxHP","TXQ0Z1LB1L","Zv7z0XflUq","AkKTkDQimp","pAhR1QWxoT","yEfy9okgRi","cQOnv2TRI7","d7vjMIBe8k",
-"HRxd8MmKGJ","brhlQP6bcg","b29RJi7WMQ","oVQp6rz7Ut","uTacxqUJMd","uAWypBFkb8","DLhzMbZLvS","MK07YJRJQB","gjUTuv2eC3","G1RhSx3LDe",
-"618DiFNYIM","FPfSEnlaBy","No0QbY1mC0","5Mg9rzQt6Q","MezSWPOUYS","9rlg90ao3l","lj07Q5nmWv","3weIFY1mC0","GrDg7fqypy","VNCPda00b5",
-"zY1GY0MR5X","QChxs9GXkX","4dEz6fqypy","cQOnv3otm6","AXpwElm0pD","FhtglwiHrZ","h1zcHn1pmO","7ku1pOz8yZ","bZLvSzbIYY","tl72WQnJ1S",
-"64s8NU3yw5","djsrv8TxD7","O3iyQFGzgp","UlU3Mi3pyd","vkCHHIn3NS","CNHmvYOfrY","hSSvQuupzk","lsQGoOUqFM","P6bcgciuWz","QssNCAkKTk",
-"tlILt6q6L9","Waim6taOXK","azIWpzY1GY","tl72W2ZHdk","fLNg8iKqhr","X6PinyEfy9","AXpwE2DREs","Pb1paVBjhz","ZzJHWydG8U","9iGoTNOHsz",
-"ksJbyFNYIM","hYBCKguMb8","9GXkXAgJHQ","RsQUqM3zXL","HlUbF0Wr5y","hE1QlIjTwP","IjTwP2TRI7","x3LDecShY2","5ZaEzQWxoT","VNCPdWPmlx",
-"m4bxUzY1GY","jiVBPxciqp","AIYUuEOE1o","cL0aEMezSW","dpe1vFjHXR","jtn0XSs0Zu","07n1ct59lR","XyPZN9y4lw","lsQGokZANm","Dz1R3OUYuF",
-"MGlTFsoy9t","tlILt5drc6","TXQ0ZPOUYS","7lUXZsx5Gl","BFkb8HfyNQ","sx5Gl8TxD7","Ss0ZuCqqaD","9y4lw24ARF","soy9trKDLJ","hi5X7S2Dfu",
-"uPX7G48cHL","IRh48MaJQs","C2Irc9y4lw","J2mQiSbRYy","lsQGolCMxy","SjskQMezSW","Cfgr3IjTwP","s4786Chuy3","D6rByWaim6","iwzGkzQt6Q",
-"oQ87rI7p2a","CxVEfokgRi","CK5W7OxWIH","Q6hMC2DREs","iwzGk3otm6","ZUnqtO3iyQ","7X3uytuDyS","fcJOysuY4x","SbRYyqaofN","55rfBFPfSE",
-"ogLgccQOnv","gjUTuReKEW","yluBxVprf2","iB08llj07Q","zQt6QuJScX","VLTy6WDVWJ","hi5X7AmdQd","X6PinX6Pin","QClRL4dEz6","B3qemtvdkD",
-"jeskSW3VFH","FPfSE7Ow5C","uupzkjeskS","MezSWEOE1o","QssNCoVQp6","M6qcG618Di","MaJQs48cHL","nnP8oS2Dfu","DG4sTCNHmv","QYxC0jzUqR",
-"K20wKEOE1o","KsjRKrKDLJ","IjTwPuN6r3","lViBvHRxd8","y94nwVprf2","hYBCKhE1Ql","IKxdLHzZT8","KsjRKM6qcG","yofH348cHL","BCxeC8hJdt",
-"lXFOBFhtgl","Kr8ysGSQwj","QYxC0DcpWB","9eoRc5ZaEz","AmdQdFNYIM","SWfousoy9t","rKDLJ8xEKz","FjHXR2TRI7","Gv3FquZPqg","xReecrKDLJ",
-"jiVBP6q6L9","wiHrZJ2mQi","xciqpG1RhS","FVMxouQIcz","prNT6zY1GY","oQ87rK20wK","pmeCdv8yFN","guMb8MojnP","iKqhr8RCUA","zmLYDcmXIX",
-"zqH0WWmadA","HfyNQzFgtB","OxWIH8RCUA","OUYuFCIShG","zFgtB5iGN5","OUYuFaez9y","FxX9q4W0Tl","45cIHVLTy6","HzZT8B3qem","gIYvEmz8gx",
-"Vprf2oVQp6","uLtKsJkzUn","Pb1paHzZT8","v2eC3Pb1pa","tjQxsChuy3","5drc6zFgtB","oQ87rTCgPp","MmsIo5drc6","uQIczThjNn","t98iWn1pmO",
-"h1zcHGv3Fq","RACujbZLvS","F6PT2OxWIH","PYBf4580YD","X6Pin8xEKz","uLtKs0BmCy","xXTI4yvOMI","t98iWs7Mxk","BCxeC0ao3l","BGaQYI7p2a",
-"JIqXiazIWp","pWiOsNcICA","KsjRK9rlg9","v8yFNatef2","qQxHP5Drn0","gjUTuzQt6Q","FPfSEpiJSk","oVQp6Mm8si","X6PinYf2Ec","LbRTHoQ87r",
-"64s8NIjTwP","Z4I1vpT8wu","uoStwRxrsm","Q6hMCMezSW","JRJQBv1Hln","soy9tlweGy","HP433lH1kt","ECMvUfqypy","RxrsmAOgEe","Mm8siAkKTk",
-"9GXkXGSQwj","QbxXcRmDcr","uPX7GkB5nP","GrDg71v5hH","29QAzNo0Qb","CqqaDFcWrW","QssNCjfREu","lj07Q07n1c","pv0i7hi5X7","gf8rIQbxXc",
-"y94nwQssNC","i3pydSbRYy","QWxoTwDajX","P6bcgQ6Lix","UlU3M5VZjS","IjTwPhYBCK","l83UdChuy3","d7vjMVNCPd","uvf7A5Namm","ni2v1VBjhz",
-"W3VFHzFgtB","qaofNNhXdu","Yw2oUi3pyd","GrDg75Mg9r","MmsIoWDVWJ","64s8Nm4bxU","5drc6tl72W","zHF1qOHaBz","1j5L8fcJOy","4W0Tl14FLR",
-"P6bcgdQ586","Gv3FqdhSuH","gf8rIyofH3","Nxx9VGv3Fq","GXdoH9iGoT","UlU3MiwzGk","uJScXa00b5","7ku1poVQp6","xciqpKZamH","cL0aE5IhmG",
-"Yh1hFLbRTH","xReeclViBv","e6e4zFVMxo","D6rByOxWIH","F6PT2G1RhS","FFDuib29RJ","o8UydVLTy6","FLsph2hEEU","uTacxOUqFM","POUYSazIWp",
-"ZhwG17hyVv","uupzkSbRYy","5Mg9rFNYIM","7X3uy7fsYM","o8Uyd16lHc","aDGtSMGlTF","4W0TlFxX9q","S2DfuuJScX","HlUbFiB08l","JRJQBtlILt",
-"MGlTFhi5X7","hYBCKJ2mQi","ThjNnnlaBy","fcwDaHlUbF","FnPFBdjsrv","Mkgy8BFkb8","hi5X7cShY2","blLA9I7p2a","CdyBVyToGW","6q6L9jiVBP",
-"suY4xJKWYR","hUTw7brhlQ","618Div1Hln","lj07Q0h1b1","NcICAfmIK1","cL0aE8hJdt","JKWYRzmLYD","Yf2EcRpBQm","MaJQsxReec","lH1ktQworu",
-"tjQxsnnP8o","DLhzMsx5Gl","D6rBylsQGo","gdQsSv8yFN","9eoRcNcICA","Qworu3weIF","okgRiECMvU","pv0i7yToGW","ydG8UCK5W7","16lHcRkQke",
-"iKqhrdhSuH","vLsmSDLhzM","yEfy9MojnP","v8yFNJ2mQi","W3VFHk85Ae","7fsYMMojnP","AmdQdy94nw","uPX7GMojnP","aL6AJatef2","oQ87rfFDrJ",
-"BbwgAM3zXL","yEfy9jS1aj","mz8gxoVQp6","VerEAaez9y","uoStwYf2Ec","Vprf2yluBx","5NammcShY2","0ao3laez9y","Zv7z0MezSW","fcwDaCK5W7",
-"MmsIoAIYUu","AIYUusqVrf","FxX9qWaWsv","gIYvEJXljW","6AFT0dhSuH","1v5hHLbRTH","IjTwPAIYUu","1j5L8y94nw","5IhmGIKxdL","5iGN5gf8rI",
-"S77LHd7vjM","ZUnqt0h1b1","EoToPOUqFM","d7vjMnFqik","1j5L8oQ87r","wDajXIjTwP","RpBQmJIqXi","AIYUuHRxd8","jSjS3qUJMd","StlDJ4dEz6",
-"jfREuMezSW","uvf7AXyPZN","IKxdLS77LH","5VZjSfcJOy","zY1GYs4786","ulk41sqVrf","vOqCElCMxy","Vprf2CqqaD","EoToPpT8wu","UlU3Mjtn0X",
-"5VZjS14FLR","48cHLBCxeC","29QAzyluBx","AkKTkyluBx","5VZjStlILt","7ku1puN6r3","uQIczmz8gx","soy9tVNCPd","yluBx3weIF","y94nw0BmCy",
-"QClRLXflUq","K4GS8zz4ZU","zQt6Q7hyVv","tvdkDpAhR1","ksJbyrz7Ut","uN6r3vkCHH","e6e4zJIqXi","Vprf28TxD7","FjHXRS2Dfu","XflUqpiJSk",
-"GWqqXBFkb8","IRh48t98iW","ZuDtDn8pJ9","tuDySlCMxy","BbwgAWaim6","aL6AJ64s8N","BGaQYhYBCK","0h1b1aL6AJ","zz4ZUK4GS8","FVMxoprNT6",
-"tlILtQbxXc","BGaQYqUJMd","Zv7z0VLTy6","VIlwPwDajX","qaofN8TxD7","RpBQmAkKTk","iKqhraez9y","CNHmvOz8yZ","CdyBVjeskS","hi5X7soy9t",
-"cL0aEEOE1o","BCxeCyEfy9","soy9tcmXIX","QnJ1Ss4786","EdBKcGXdoH","In3NSQworu","7fKYUKASQ8","pT8wuNxx9V","uQIcz9iGoT","jeskSRmDcr",
-"zHF1q7X3uy","Z4I1vB3qem","a00b55drc6","7Ow5C1j5L8","2hEEUmX2GE","OxWIHxciqp","vkCHHMmKGJ","Dz1R3zmLYD","7X3uy7lUXZ","PYBf424ARF",
-"lkMUAJXljW","v2eC3pmeCd","Gv3FqWaim6","qaofNL7cGc","SbRYyb29RJ","sx5GlQ6Lix","0BmCyOz8yZ","Cfgr3suY4x","AXpwEYOfrY","OUYuF0YAGH",
-"fLNg8FVMxo","n1pmOUlU3M","Twanodpe1v","OUqFMvkCHH","uupzkIBe8k","4QMc9h1zcH","qaofNi3pyd","lkMUANOHsz","QClRLGv3Fq","EdBKcsqVrf",
-"zqH0WSWfou","KZamHkB5nP","0YAGH8FmFH","zz4ZUjtn0X","L7cGcNo0Qb","MojnPtl72W","VjCZqAgJHQ","K4GS8jS1aj","3weIFrhl0J","he9IAJ2mQi",
-"Z4I1vcL0aE","prNT6x3LDe","cL0aECdyBV","ZuDtDyluBx","yvOMIReKEW","BpYhV5Namm","yluBxPb1pa","aL6AJbgJAz","AOgEei3pyd","BpYhV16lHc",
-"AIYUuuN6r3","hUTw78RCUA","guMb8kZANm","9iGoTqaofN","8U2nUVLTy6","EOE1o07n1c","fmIK1RBhp0","pv0i7fFDrJ","jSjS3MmsIo","he9IAL7cGc",
-"CIShGfaHir","rz7Ut7ku1p","jiVBP45cIH","YOfrYWDVWJ","HP433t98iW","e6e4zgdQsS","cQOnvuLtKs","zz4ZUMmKGJ","hi5X7AOgEe","cQOnvv2eC3",
-"AXpwE9rlg9","X6PinO3iyQ","bZLvSLewvM","Oz8yZmz8gx","F6PT25IhmG","AmdQdYOfrY","48cHLy94nw","gjUTujiVBP","aL6AJ5nmWv","GWqqXVerEA",
-"yofH37X3uy","JXljWMkgy8","he9IA7fKYU","sqVrfvkCHH","NAFuw5Namm","8xEKzCdyBV","WaWsvzY1GY","C2IrclpF6W","O3iyQSjskQ","VLTy6BCxeC",
-"X6PinWaWsv","djsrvGXdoH","45cIHfLNg8","XyPZNlj07Q","X6PinQYxC0","CxVEf9eoRc","3otm6fcwDa","9y4lwQChxs","uJScXogLgc","s93Mlmz8gx",
-"2DREsprNT6","MezSWiKqhr","3otm629QAz","LbRTHIjTwP","tjQxsVprf2","i3pydOHaBz","0MR5XpiJSk","SbRYyWPmlx","55rfBk85Ae","6q6L9XyPZN",
-"SmGzvHP433","WPmlx5IhmG","EdBKcStlDJ","n1pmO0YAGH","wiHrZ9rlg9","hUTw7In3NS","5Nammv1Hln","Ul4a1ni2v1","VBjhzqUJMd","0BmCyn8pJ9",
-"lViBvwiHrZ","hi5X7t98iW","RkQkeuLtKs","QworuyEfy9","MK07Yo8Uyd","K4GS85nmWv","yToGWbZLvS","RpBQmVLTy6","xXTI4Pb1pa","zQt6QW3VFH",
-"ECMvUDG4sT","Chuy35Namm","8hJdtOUYuF","faHirtaOXK","M3zXLAXpwE","vOqCEtjQxs","soy9tMojnP","b29RJtvdkD","Uvlv4gf8rI","Cfgr348cHL",
-"MmKGJulk41","yToGWW7cTs","DcpWBpWiOs","oQ87r5Namm","YjB9t1LB1L","zbIYYNo0Qb","P6bcg48cHL","RpBQmPYBf4","07n1cS77LH","aDGtSB3qem",
-"Nxx9VqaofN","0KyfslXFOB","2hEEUQYxC0","AOgEeCqqaD","C2IrcvkCHH","jeskSCfgr3","JRJQBSjskQ","nFqikiqv4k","ECMvU7Ow5C","MezSWqUJMd",
-"4dEz6XflUq","Ul4a11j5L8","ydG8UPb1pa","29QAzAmdQd","0MR5XpAhR1","dhSuH2DREs","gf8rICK5W7","EdBKcCdyBV","In3NSK4GS8","FhtglpmeCd",
-"24ARFFxX9q","XflUq580YD","I7p2aqUJMd","IjTwP07n1c","SjskQQChxs","uN6r3RpBQm","Zv7z0HRxd8","W3VFHogLgc","lweGypFrrl","gtCA5i7WMQ",
-"7Ow5C5Namm","k85Aedpe1v","JXljWRkQke","Ta8f6TCgPp","Vprf24QMc9","0YAGHChuy3","d85a9qUJMd","FNYIMfqypy","P6bcgPYBf4","Yf2EcaDGtS",
-"7Ow5CpT8wu","uAWypzQt6Q","QYxC0RkQke","FxX9q0Wr5y","t98iWYOfrY","Pb1paqUJMd","RkQkeSmGzv","uAWypVprf2","QWxoTRxrsm","nFqik9rlg9",
-"2DREsMmsIo","6q6L9TCgPp","suY4xtuDyS","S77LHJRJQB","BFkb8hE1Ql","d85a9cmXIX","uQIczIn3NS","QClRLIjTwP","t59lR2Yz7E","TCgPpt98iW",
-"GSQwjx3LDe","s93MluTacx","MmsIo07n1c","0h1b1GrDg7","5iGN5zQt6Q","uN6r3FjHXR","WPmlxi7WMQ","aFFssSbRYy","OUqFM2Yz7E","FwEJzvOqCE",
-"tAOsrMezSW","HlUbFX6Pin","lCMxyO3iyQ","0h1b1SmGzv","BGaQYkB5nP","ZUnqt6q6L9","xciqp55rfB","VjCZqBFkb8","OHaBz5iGN5","iwzGkQssNC",
-"atef2ogLgc","Yw2oU7X3uy","9y4lwt98iW","aFFssIjTwP","9XyT9jS1aj","24ARFOUYuF","6AFT0QbxXc","tAOsrQChxs","aFFssFGzgp","O3iyQThjNn",
-"LewvMzqH0W","IjTwP9eoRc","cQOnv8TxD7","ix74rZzJHW","PYBf4pmeCd","RpBQm6AFT0","S2DfuVNCPd","ydG8U14FLR","FPfSE5Mg9r","djsrvoVQp6",
-"dhSuHpv0i7","hSSvQjfREu","hSSvQK20wK","ciuWzW7cTs","WreyPZJTXH","IKxdL4W0Tl","StlDJSs0Zu","mX2GEpT8wu","OUYuFzQt6Q","POUYS580YD",
-"QClRLLDk6f","9y4lwxReec","FwEJzazIWp","WDVWJRxrsm","WmadAgjUTu","zQt6QY1mC0","RACujGWqqX","OHaBzMK07Y","fLNg8DcpWB","FcWrWWaim6",
-"QClRLlweGy","QnJ1SmX2GE","RzaZA7lUXZ","mX2GECxVEf","VerEAOUYuF","fqypyfLNg8","BbwgA8RCUA","ZhwG107n1c","VerEAuQIcz","FPfSEFPfSE",
-"QssNCksJby","Yh1hFBFkb8","KZamHAgJHQ","qaofNCIShG","RmDcrZhwG1","uN6r3KsjRK","gtCA5WreyP","dQ586ciuWz","iqv4kwiHrZ","WreyP5VZjS",
-"zY1GYqaofN","lkMUAxReec","RsQUqW3VFH","FjHXR618Di","zFgtBAXpwE","FxX9qLewvM","t98iWb29RJ","GXdoHG1RhS","rKDLJtaOXK","bgJAzd7vjM",
-"RxrsmogLgc","0PktIyluBx","5NammAmdQd","UlU3MlweGy","JKWYRlm0pD","9GXkXvLsmS","VjCZqQWxoT","oVQp6wiHrZ","xciqpCfgr3","Yh1hFciuWz",
-"d7vjM8hJdt","KsjRKpAhR1","i3pydjSjS3","dpe1vyluBx","In3NSiqv4k","2DREs8TxD7","uoStw4dEz6","OHaBzd85a9","M3zXLtuDyS","0Kyfs5nmWv",
-"uJScXY1mC0","a00b55Namm","zmLYDmz8gx","S77LHTwano","tjQxsjeskS","jiVBP0PktI","bZLvS29QAz","8RCUA24ARF","qQxHPNhXdu","RpBQmcmXIX",
-"9GXkXrKDLJ","7fsYM9y4lw","GWqqXvkCHH","VLTy6LbRTH","rhl0JHRxd8","FxX9qo8Uyd","brhlQIn3NS","3weIFvLsmS","64s8NB3qem","3otm6hSSvQ",
-"9iGoTZhwG1","2Yz7EIjTwP","prNT6aL6AJ","1LB1LAgJHQ","16lHc0BmCy","zHF1qS77LH","rhl0JfFDrJ","v8yFNAXpwE","In3NS0MR5X","WmadAiwzGk",
-"OHaBzRkQke","X6Pin5ZaEz","CqqaDoQ87r","zqH0WuTacx","0KyfsFcWrW","s93MlNcICA","lj07QuoStw","n8pJ9aDGtS","dhSuHtaOXK","RzaZAk85Ae",
-"5Mg9re6e4z","MmKGJHRxd8","dQ586cShY2","EdBKcuTacx","Yf2EcyofH3","zY1GYaFFss","NhXdu1j5L8","55rfBiqv4k","29QAzReKEW","9XyT9tvdkD",
-"gjUTuEdBKc","Ss0ZudhSuH","v2eC3hE1Ql","QChxsFLsph","oQ87rU3yw5","29QAz24ARF","i3pyd3weIF","zHF1qm4bxU","QbxXcEoToP","SWfouRsQUq",
-"ydG8UlXFOB","tuDySulk41","CK5W75Namm","LDk6fyluBx","tlILt580YD","gjUTuRmDcr","AOgEedhSuH","FVMxo24ARF","k85Aet98iW","8RCUAFGzgp",
-"MmsIo7fKYU","fcJOyMGlTF","mX2GElCMxy","07n1cK20wK","FPfSEix74r","hE1Qls93Ml","AgJHQiwzGk","FjHXRKsjRK","xXTI47X3uy","LbRTH8FmFH",
-"Q6LixGSQwj","tvdkDVLTy6","0ao3lZJTXH","7ku1pzHF1q","HfyNQ64s8N","RsQUqSjskQ","TCgPpbrhlQ","qQxHPpvgjS","lweGyQnJ1S","ogLgcxciqp",
-"MezSWzmLYD","vOqCE3otm6","FwEJzIn3NS","4W0Tl0ao3l","JRJQB8TxD7","a00b5fcwDa","dQ586bZLvS","Q6hMClj07Q","xciqpjtn0X","07n1c4QMc9",
-"580YDSmGzv","gIYvElXFOB","LDk6f0PktI","gtCA5ix74r","No0QbTXQ0Z","pmeCdJKWYR","iKqhr5Drn0","Pb1pat98iW","Zv7z0fcJOy","4QMc9e6e4z",
-"OHaBzK20wK","JIqXiwDajX","HzZT8m4bxU","ksJby07n1c","wiHrZZJTXH","KZamHhYBCK","LbRTHWaim6","CK5W7BFkb8","7X3uyZuDtD","blLA9uPX7G",
-"lweGy0YAGH","8FmFHPb1pa","vkCHHUvlv4","yToGWydG8U","iB08luAWyp","CK5W7Mm8si","FxX9qgjUTu","5ZaEzGSQwj","o8Uyd6q6L9","uTacxbZLvS",
-"e6e4znFqik","UlU3M5drc6","FnPFBS77LH","fFDrJP6bcg","bZLvSnlaBy","Mm8sicShY2","zY1GYvOqCE","NOHsz9y4lw","MGlTFaFFss","S2DfuXyPZN",
-"EoToPi3pyd","64s8Nni2v1","fmIK18xEKz","0YAGHfmIK1","8cVD3v2eC3","sqVrfHRxd8","cmXIXCqqaD","jSjS3yToGW","LbRTH07n1c","fqypybgJAz",
-"CK5W7zz4ZU","1v5hHCfgr3","HRxd8FnPFB","JIqXivkCHH","WreyPP6bcg","7fKYUiwzGk","3weIFtjQxs","WMiS3HP433","tjQxsQClRL","uQIcztaOXK",
-"JKWYRDLhzM","GXdoHyvOMI","tlILtIjTwP","GWqqXHlUbF","fcJOyIjTwP","RmDcrStlDJ","8cVD32hEEU","RpBQm8xEKz","fFDrJcQOnv","ZuDtDjSjS3",
-"pvgjSMkgy8","5iGN5L7cGc","aDGtSoQ87r","XflUqlm0pD","ZUnqtJIqXi","QworugdQsS","VerEAJ2mQi","rhl0JZuDtD","J2mQiaDGtS","C2IrcSmGzv",
-"hi5X7OUqFM","K20wKtuDyS","pT8wuQWxoT","s4786FFDui","jiVBPM3zXL","ECMvUnlaBy","atef2HlUbF","Mm8siZuDtD","l83UdKASQ8","fFDrJpmeCd",
-"hi5X7BFkb8","8cVD30h1b1","2DREsd7vjM","QssNC5iGN5","L7cGct98iW","wDajXmz8gx","8TxD7LDk6f","3weIFJRJQB","BGaQYNo0Qb","VNCPdWDVWJ",
-"WaWsvJKWYR","SjskQlsQGo","FNYIMhE1Ql","0Wr5yCK5W7","MGlTFvLsmS","3weIFlH1kt","SmGzvCp3mZ","fLNg8fcJOy","taOXK55rfB","QChxsNAFuw",
-"Chuy3aDGtS","ix74rwDajX","6AFT0uJScX","Nxx9VvkCHH","OUqFMaL6AJ","5NammCp3mZ","HzZT81v5hH","FLsphv1Hln","zqH0WKASQ8","8TxD7I7p2a",
-"QChxsS77LH","XflUqpmeCd","euZA50BmCy","OHaBzThjNn","K4GS8DG4sT","B3qemoVQp6","lCMxyMm8si","iB08l3otm6","5nmWvru4UG","S77LHCqqaD",
-"W7cTsMezSW","GrDg74dEz6","zQt6QIKxdL","QClRLdhSuH","ciuWzZv7z0","MGlTFfqypy","zqH0WpmeCd","7hyVvnnP8o","HP433ZUnqt","hSSvQS77LH",
-"d85a9MojnP","uTacxhe9IA","v2eC3mX2GE","No0QbpAhR1","e6e4zS2Dfu","Nxx9VMGlTF","TXQ0ZNo0Qb","l83Udi3pyd","LewvMUl4a1","KZamHzHF1q",
-"618DifFDrJ","i7WMQGWqqX","1LB1LmX2GE","2ZHdkhSSvQ","X6Pino8Uyd","7fKYUEoToP","AmdQd5IhmG","4W0TlIjTwP","ni2v18RCUA","5IhmGuLtKs",
-"9GXkXThjNn","7fKYU0PktI","Yh1hF3weIF","uQIcz5Mg9r","CK5W7uQIcz","iwzGkHzZT8","zbIYYJIqXi","ydG8UPOUYS","fFDrJYjB9t","4QMc9Y1mC0",
-"faHirjtn0X","zFgtB4W0Tl","tuDySCfgr3","i3pydqQxHP","0MR5Xix74r","WmadA0Wr5y","oGu6xwiHrZ","CqqaDzFgtB","5Mg9rFxX9q","zFgtB07n1c",
-"K4GS8cmXIX","QYxC0LewvM","ix74ruupzk","HzZT8vkCHH","s93Mlb29RJ","tvdkDXyPZN","uAWypuQIcz","SWfou8U2nU","KsjRKKASQ8","RmDcrWreyP",
-"I7p2ajiVBP","TXQ0ZHfyNQ","Yw2oUJXljW","2Yz7Ezz4ZU","tjQxsFNYIM","o8UydBGaQY","EoToPDLhzM","lXFOBcShY2","e6e4zEdBKc","4dEz68U2nU",
-"ZJTXH0BmCy","5Mg9rGrDg7","9iGoTUl4a1","yToGWzz4ZU","s4786d85a9","0MR5XhUTw7","CK5W7azIWp","MGlTF7fKYU","d7vjMS2Dfu","Nxx9Vd7vjM",
-"prNT6AkKTk","HRxd8gf8rI","EoToPHlUbF","580YD0Kyfs","l83UdCxVEf","XflUq0YAGH","QClRLFLsph","wiHrZh1zcH","Ul4a1xReec","W3VFHHP433",
-"oVQp6ThjNn","UmaEv0Kyfs","hYBCKPOUYS","FVMxohSSvQ","GXdoHD6rBy","qaofNnnP8o","euZA5fqypy","FPfSEfcwDa","GrDg7guMb8","x3LDe5IhmG",
-"9XyT9ThjNn","U3yw5qUJMd","HfyNQ7Ow5C","jiVBPMK07Y","JkzUnZzJHW","ydG8UbgJAz","0ao3lpAhR1","lCMxywiHrZ","aFFss8RCUA","Yh1hFVjCZq",
-"Y1mC0618Di","CqqaDK20wK","zqH0Wo8Uyd","uvf7ALDk6f","X6PincShY2","24ARFprNT6","djsrvRpBQm","tAOsrm4bxU","faHiruvf7A","X6PinZJTXH",
-"Q6hMC9iGoT","1v5hHQClRL","WreyPG1RhS","uupzk5IhmG","FjHXRqQxHP","CxVEf5Drn0","v8yFNWaWsv","azIWpx3LDe","cShY2SmGzv","hUTw7LbRTH",
-"Ss0Zu9y4lw","azIWpcQOnv","RBhp0Twano","HRxd82DREs","ydG8UVjCZq","1LB1LcmXIX","tuDyS0PktI","K20wKuTacx","i7WMQ4dEz6","zY1GY5nmWv",
-"MaJQsvkCHH","55rfBDG4sT","rz7Ut55rfB","okgRi5ZaEz","FFDui7ku1p","i3pydBGaQY","Waim60MR5X","8cVD3FxX9q","9XyT9HzZT8","fcJOy5VZjS",
-"FVMxoVLTy6","DQimpqUJMd","jeskSCqqaD","h1zcH9rlg9","b29RJVerEA","O3iyQD6rBy","ni2v1VjCZq","qUJMdX6Pin","KASQ8tuDyS","WaWsvs93Ml",
-"jzUqRjSjS3","7lUXZVLTy6","DcpWBSjskQ","8hJdtdpe1v","v8yFNYw2oU","8xEKz2ZHdk","VLTy607n1c","t59lRMkgy8","ru4UGlsQGo","TXQ0ZSWfou",
-"KASQ8jzUqR","OUYuFWaWsv","Chuy3Dz1R3","S2DfuVerEA","he9IAuZPqg","okgRi6AFT0","5IhmGK4GS8","5ZaEzlm0pD","FPfSEcL0aE","ZuDtDSbRYy",
-"AkKTkjzUqR","xXTI4y94nw","9GXkXfaHir","rKDLJOUqFM","t98iWYf2Ec","XflUqlH1kt","WreyPwDajX","UmaEvU3yw5","fmIK1okgRi","ReKEWcmXIX",
-"LbRTH580YD","hE1QlMm8si","iB08lDG4sT","lkMUAgIYvE","IjTwPFcWrW","uTacxZ4I1v","v8yFNlViBv","JkzUno8Uyd","oQ87rNhXdu","oGu6xNxx9V",
-"618DiGv3Fq","HzZT8ZuDtD","5ZaEzFxX9q","RxrsmIjTwP","GWqqXZJTXH","FwEJzZv7z0","ZUnqtkB5nP","n1pmOI7p2a","Y1mC0tAOsr","DQimpatef2",
-"o8UydwiHrZ","2Yz7EqaofN","dpe1vtAOsr","BbwgAx3LDe","WmadAReKEW","B3qemgdQsS","TCgPp8hJdt","pT8wunnP8o","hUTw7jSjS3","s7MxkWPmlx",
-"FGzgp5Namm","VerEAQChxs","lCMxySWfou","29QAzPb1pa","16lHcRzaZA","Dz1R3tjQxs","uJScXjzUqR","SbRYy9iGoT","tl72Wjtn0X","hi5X7YjB9t",
-"a00b5a00b5","uTacxrz7Ut","Q6LixMojnP","s93MllkMUA","QbxXcF6PT2","JJs5mUmaEv","cShY2QClRL","CNHmvciuWz","9eoRc5IhmG","5nmWvHlUbF",
-"gIYvERACuj","5ZaEzRsQUq","ECMvUbrhlQ","7fKYUWreyP","m4bxUnlaBy","lCMxyzY1GY","pT8wu5iGN5","5Nammru4UG","FGzgpXflUq","lsQGo55rfB",
-"jzUqRlweGy","lweGyzY1GY","MojnPY1mC0","qUJMdzHF1q","lpF6WZzJHW","3weIFGWqqX","G1RhSAmdQd","DG4sTLewvM","FPfSEyToGW","MaJQsECMvU",
-"2TRI7S2Dfu","uAWypW3VFH","AXpwEYjB9t","K20wK0h1b1","pAhR1cQOnv","ZJTXHZhwG1","s93Mlpv0i7","a00b5cQOnv","Qworum4bxU","taOXKDG4sT",
-"fLNg8XflUq","gdQsSTwano","L7cGcVerEA","uN6r35VZjS","oGu6xL7cGc","uN6r3uoStw","zz4ZU16lHc","8cVD3KZamH","RmDcrThjNn","d7vjMvOqCE",
-"s4786RpBQm","HzZT8oQ87r","tjQxsFnPFB","suY4xUl4a1","BCxeCBFkb8","RmDcrsqVrf","s4786KsjRK","uAWypzbIYY","pmeCdwDajX","n8pJ9fcJOy",
-"ksJbyPYBf4","QClRL1j5L8","cShY2TXQ0Z","aL6AJ1v5hH","rhl0JfcwDa","jtn0Xpv0i7","s93Mlaez9y","48cHLguMb8","faHiruAWyp","pvgjS45cIH",
-"PYBf4FjHXR","0YAGHxReec","M6qcGAOgEe","0h1b1pT8wu","GWqqXi7WMQ","yofH3VNCPd","AkKTkfcwDa","yEfy96q6L9","48cHLQ6hMC","SjskQS77LH",
-"bgJAzn8pJ9","vLsmSTa8f6","JRJQBUlU3M","e6e4zGWqqX","aez9ytvdkD","Ta8f6o8Uyd","tjQxsuLtKs","DG4sTpmeCd","6AFT0uvf7A","FNYIMt98iW",
-"2NslmwDajX","pAhR1ix74r","9y4lwxXTI4","x3LDeJXljW","GWqqX2TRI7","kB5nPzmLYD","soy9td7vjM","NAFuw2hEEU","zY1GYFNYIM","9iGoTQClRL",
-"RpBQm7hyVv","HP433WPmlx","FPfSEVNCPd","hUTw7okgRi","Ta8f65VZjS","tjQxsKsjRK","DQimpaDGtS","CdyBVe6e4z","JkzUnYw2oU","StlDJn1pmO",
-"ix74rulk41","FFDuiaL6AJ","618DilweGy","fcJOyK4GS8","QworuFGzgp","v1HlnuN6r3","QssNCSjskQ","hi5X7IjTwP","IBe8kv1Hln","VLTy6ni2v1",
-"7ku1pJXljW","HP433vOqCE","ni2v1uLtKs","gdQsS29QAz","5ZaEzZJTXH","zFgtBYjB9t","n8pJ9l83Ud","tl72WK20wK","6q6L9hE1Ql","FnPFBCdyBV",
-"BFkb8FFDui","zY1GY2TRI7","iB08lZ4I1v","uupzkb29RJ","qaofNQChxs","euZA5HzZT8","NAFuwLewvM","suY4xThjNn","7lUXZ48cHL","0Wr5yUmaEv",
-"nnP8ofLNg8","vOqCEdmoS7","Gv3FqyEfy9","FGzgpzY1GY","fmIK1lpF6W","In3NSWreyP","l83UdjfREu","7lUXZvLsmS","tl72WMGlTF","e6e4zk85Ae",
-"8cVD3LDk6f","EOE1ogjUTu","Cp3mZmz8gx","ni2v1I7p2a","ZzJHWyofH3","pFrrlzQt6Q","lpF6WjfREu","C2IrcokgRi","BGaQYU3yw5","bZLvSlsQGo",
-"l83Ud8RCUA","MK07Y8TxD7","soy9tgIYvE","jeskStjQxs","VIlwP7fKYU","ReKEWuQIcz","3weIFyofH3","dQ586YOfrY","4W0Tld85a9","Gv3FquQIcz",
-"GXdoHYjB9t","aDGtSKZamH","0KyfsTa8f6","FnPFBs7Mxk","ZJTXHkZANm","NcICAfaHir","QWxoT7fKYU","fFDrJSjskQ","dhSuHyofH3","xXTI4DG4sT",
-"qUJMd0ao3l","vOqCEEdBKc","SmGzvoQ87r","lkMUAnlaBy","dpe1vVLTy6","U3yw5iB08l","FhtglHRxd8","Q6hMCKASQ8","tAOsrC2Irc","dhSuH1v5hH",
-"tuDyS7ku1p","P6bcgAIYUu","i3pydv8yFN","OHaBzcmXIX","8TxD7e6e4z","djsrvYf2Ec","LewvMRzaZA","0KyfsQ6hMC","JkzUnrhl0J","uLtKs7X3uy",
-"IKxdLiB08l","gdQsSCK5W7","1j5L8d7vjM","7X3uyuAWyp","lH1ktd85a9","fcwDaVBjhz","5Mg9rWDVWJ","UlU3MPOUYS","AkKTk0h1b1","CdyBV5Drn0",
-"6q6L97hyVv","14FLRMm8si","d85a9QbxXc","gtCA5dQ586","VjCZqQ6hMC","e6e4zuN6r3","0Wr5yZhwG1","U3yw52ZHdk","QChxsfmIK1","3weIFF6PT2",
-"iB08le6e4z","Dz1R3ZJTXH","aL6AJsoy9t","9y4lwlCMxy","rz7Ut16lHc","4dEz6piJSk","NhXducmXIX","hUTw7SbRYy","bgJAzlsQGo","G1RhS64s8N",
-"DQimpuTacx","5VZjStaOXK","cQOnvx3LDe","azIWpdmoS7","VLTy6EoToP","2NslmhYBCK","1v5hHRkQke","pmeCdru4UG","rz7UtXyPZN","AIYUu2hEEU",
-"RzaZAM3zXL","x3LDeaFFss","Yw2oUAmdQd","azIWpFcWrW","gIYvE7fsYM","9iGoTReKEW","xReecSmGzv","v1HlnIn3NS","9eoRcrz7Ut","Vprf2v2eC3",
-"EoToPFcWrW","zz4ZUbgJAz","QClRLYjB9t","NhXdudjsrv","7fsYM6AFT0","hE1Qlk85Ae","b29RJ580YD","oVQp6pAhR1","0BmCyblLA9","Vprf25Mg9r",
-"PYBf4Uvlv4","2hEEUtaOXK","Ul4a1zY1GY","EOE1o7ku1p","Yh1hFtuDyS","16lHcU3yw5","CqqaDLewvM","tl72Ws7Mxk","RBhp0atef2","XflUqnFqik",
-"tjQxsJIqXi","CK5W7Zv7z0","5NammDLhzM","YjB9t07n1c","W7cTslCMxy","0Wr5ysqVrf","CIShGfcJOy","kB5nPKASQ8","48cHLlH1kt","CNHmvVIlwP",
-"cL0aEni2v1","brhlQIjTwP","QClRLBbwgA","RpBQmVerEA","aFFsshe9IA","s93Ml0PktI","QClRL618Di","pFrrl7X3uy","NOHsz8FmFH","s93Ml2TRI7",
-"2ZHdk55rfB","Rxrsmb29RJ","bgJAzlj07Q","iwzGkrhl0J","jtn0Xni2v1","qQxHPuvf7A","F6PT2mz8gx","ru4UGSmGzv","uQIcz2hEEU","FNYIMZJTXH",
-"uAWypfqypy","C2Irc2hEEU","Yf2EcOUYuF","bgJAzjtn0X","5Drn0tvdkD","zbIYY16lHc","POUYSQClRL","qaofNgdQsS","WreyPhUTw7","FjHXRiKqhr",
-"MmKGJuTacx","LDk6fzFgtB","16lHcKZamH","uPX7GWaim6","uQIczs7Mxk","VLTy6AOgEe","K20wKbgJAz","AgJHQtl72W","jSjS3he9IA","y94nwWmadA",
-"QbxXcC2Irc","DQimppT8wu","zbIYY9eoRc","t98iW7lUXZ","s4786gtCA5","ulk41EOE1o","No0Qbulk41","IjTwPCxVEf","3weIFa00b5","DLhzMoVQp6",
-"SbRYydmoS7","8U2nUBbwgA","v8yFN8cVD3","hYBCKFjHXR","Nxx9Vlm0pD","e6e4z8xEKz","cL0aENcICA","RxrsmD6rBy","S77LHdjsrv","RsQUqv8yFN",
-"lCMxy4dEz6","2Yz7EyluBx","D6rBygIYvE","lj07QvkCHH","AmdQd8TxD7","uvf7Arhl0J","iwzGkTXQ0Z","WmadAoVQp6","7X3uyPOUYS","Yw2oUoGu6x",
-"8U2nUlkMUA","wiHrZMkgy8","KZamHaFFss","taOXK5Namm","Nxx9VYjB9t","zHF1qJXljW","lXFOB7X3uy","AmdQdt59lR","J2mQiJJs5m","7fsYM5ZaEz",
-"SjskQGrDg7","RsQUqXflUq","8hJdt0ao3l","2Yz7Ev1Hln","5NammzY1GY","Oz8yZbrhlQ","Cfgr3cQOnv","SjskQ3otm6","5drc6RBhp0","EdBKc0Wr5y",
-"WreyPJJs5m","0PktI5iGN5","7fKYUECMvU","ZuDtDlkMUA","pT8wupv0i7","VjCZq24ARF","KZamHY1mC0","iKqhr8cVD3","29QAzsx5Gl","0MR5XCIShG",
-"uupzklsQGo","RACujJJs5m","jzUqR8xEKz","3weIFW7cTs","ZUnqtlH1kt","piJSkEOE1o","sqVrfjzUqR","Chuy3lH1kt","9y4lwfaHir","jzUqR7X3uy",
-"4dEz6No0Qb","SmGzvSbRYy","AXpwEaL6AJ","vkCHHmz8gx","n8pJ9SmGzv","9XyT9iqv4k","24ARFEoToP","fFDrJpvgjS","tuDySBbwgA","ZUnqtfcwDa",
-"o8UydFhtgl","Cp3mZUvlv4","uJScXjSjS3","t98iW5Namm","QnJ1SAOgEe","BbwgAfqypy","U3yw5Fhtgl","b29RJMezSW","he9IAEoToP","LewvM5VZjS",
-"Dz1R3VNCPd","2DREsbrhlQ","Kr8ys0BmCy","DcpWB8TxD7","qaofNpiJSk","0MR5Xsx5Gl","xXTI4atef2","v1HlnAOgEe","VBjhzoGu6x","uupzkIn3NS",
-"uN6r3ZhwG1","fLNg8IRh48","qaofNwDajX","pv0i7QssNC","BFkb8NhXdu","45cIHRzaZA","Z4I1vd85a9","Cfgr3tuDyS","ZUnqt45cIH","580YDTa8f6",
-"qQxHPn8pJ9","lj07QfLNg8","guMb8pFrrl","zz4ZUBGaQY","UlU3MpWiOs","1j5L8I7p2a","W3VFHGv3Fq","qQxHPyEfy9","WDVWJYOfrY","CxVEfgIYvE",
-"lpF6W4W0Tl","7hyVvb29RJ","IBe8kbZLvS","xReec580YD","1LB1LbrhlQ","FPfSEVLTy6","9GXkXJXljW","yluBxpT8wu","RkQkeh1zcH","7hyVvprNT6",
-"0ao3lhSSvQ","CxVEfsoy9t","0KyfsFhtgl","3otm6GWqqX","ZuDtDiwzGk","X6Pinv8yFN","S2DfuW7cTs","b29RJWaWsv","3weIF5nmWv","yToGWMaJQs",
-"FNYIM3otm6","RBhp0NcICA","xReec9GXkX","IKxdLoQ87r","6q6L9TXQ0Z","ru4UG5Mg9r","HlUbFLbRTH","CIShGpiJSk","nlaBytvdkD","ThjNnTwano",
-"Dz1R3POUYS","NcICAdmoS7","uAWypQWxoT","GSQwj5Namm","JIqXiuPX7G","pT8wuVLTy6","cQOnvECMvU","P6bcgFwEJz","wDajXuLtKs","IBe8kuJScX",
-"vOqCEG1RhS","WaWsvBGaQY","gdQsSQbxXc","iqv4kpT8wu","rhl0JECMvU","lViBvvOqCE","OHaBzoGu6x","s93MlmX2GE","I7p2a8RCUA","faHirK4GS8",
-"SbRYyY1mC0","618DiFcWrW","EdBKcDcpWB","BpYhVWPmlx","pmeCduAWyp","prNT6In3NS","iKqhrwiHrZ","SjskQpWiOs","2NslmEOE1o","cmXIXlpF6W",
-"s93Mli3pyd","lXFOBcL0aE","djsrv0MR5X","v8yFNfFDrJ","LbRTHvLsmS","9y4lwCK5W7","zz4ZUFwEJz","QChxsReKEW","zFgtBsuY4x","tvdkDnlaBy",
-"TCgPprz7Ut","RsQUquZPqg","tuDySnFqik","QWxoTCqqaD","RmDcrt98iW","7X3uykZANm","Ta8f6In3NS","B3qemlm0pD","sqVrfYjB9t","YOfrYs93Ml",
-"DQimpuZPqg","zQt6Q16lHc","hi5X7iqv4k","i3pydYf2Ec","zQt6Q8cVD3","i3pydWmadA","5Drn0S77LH","OHaBz9rlg9","5Mg9rVerEA","ix74rMojnP",
-"he9IApFrrl","HlUbF6AFT0","xciqpqUJMd","2TRI7v2eC3","iB08lM6qcG","7hyVvuAWyp","HP433MmsIo","16lHcMezSW","In3NSogLgc","pT8wuU3yw5",
-"7fsYMDQimp","xciqp8xEKz","qQxHPxReec","1j5L8RzaZA","FLsphJkzUn","2hEEUWMiS3","HP4335Drn0","yEfy9Yh1hF","RmDcrPYBf4","azIWpv8yFN",
-"3weIFHP433","dQ5865nmWv","2Yz7EogLgc","fLNg89XyT9","7fKYUGXdoH","TCgPpEoToP","oGu6xlViBv","HfyNQtuDyS","Ta8f6ni2v1","cL0aEGrDg7",
-"Pb1paFnPFB","ReKEWmz8gx","vkCHH5ZaEz","RpBQmRsQUq","WmadAydG8U","8TxD7uQIcz","NhXduD6rBy","suY4xa00b5","5ZaEzKZamH","WDVWJm4bxU",
-"NcICACIShG","QYxC0zqH0W","Pb1paZ4I1v","cShY26q6L9","guMb8BCxeC","he9IAFnPFB","bZLvS5ZaEz","Dz1R3jeskS","16lHcjeskS","ThjNngf8rI",
-"ydG8U0PktI","ni2v10YAGH","gf8rI8FmFH","blLA9BGaQY","nnP8o5drc6","Yh1hFUvlv4","580YDSWfou","gjUTunFqik","QClRLl83Ud","ogLgcpv0i7",
-"Ul4a1UmaEv","2ZHdkOz8yZ","5Mg9rqaofN","Pb1pa2ZHdk","DLhzMOxWIH","yToGWaDGtS","5drc65iGN5","BCxeC8FmFH","oGu6xd7vjM","h1zcH5drc6",
-"okgRiIKxdL","XyPZN5Mg9r","fLNg8Uvlv4","Cfgr3618Di","ni2v1FLsph","FcWrWSs0Zu","K20wKYw2oU","8cVD3Mm8si","Q6LixSmGzv","jeskS8hJdt",
-"AXpwEyEfy9","ECMvUQWxoT","OUqFMIn3NS","ECMvUZzJHW","uPX7Ga00b5","VNCPdeuZA5","NOHsz1LB1L","PYBf4lweGy","P6bcgkZANm","guMb8VerEA",
-"ogLgc3weIF","yvOMI2ZHdk","Mm8siReKEW","CK5W73weIF","0Wr5yv2eC3","BFkb88xEKz","dhSuH0ao3l","FFDuilkMUA","X6Pin2hEEU","BFkb8sx5Gl",
-"EOE1olpF6W","aez9yyToGW","2NslmJJs5m","zbIYYSWfou","ru4UGF6PT2","TwanofmIK1","aFFssRBhp0","M6qcGfcJOy","fqypyfmIK1","Ss0Zuuvf7A",
-"QworuJKWYR","FNYIMogLgc","rz7Ut7fKYU","Ss0ZufcwDa","k85AexXTI4","nnP8obgJAz","Cp3mZlH1kt","AIYUuCqqaD","gtCA5dhSuH","7X3uyD6rBy",
-"LDk6fXflUq","FPfSEHP433","580YDF6PT2","55rfBjeskS","DG4sTFNYIM","vkCHH0h1b1","gIYvEOUqFM","yluBxZ4I1v","fcwDa45cIH","taOXKX6Pin",
-"64s8N14FLR","pT8wu0BmCy","Uvlv4pv0i7","bZLvSgf8rI","i3pydpv0i7","blLA9gIYvE","8xEKzC2Irc","FxX9q5IhmG","CqqaDMezSW","i7WMQpmeCd",
-"lH1ktfmIK1","VBjhzRpBQm","7Ow5CQ6hMC","2ZHdkMojnP","OUqFMC2Irc","v8yFNQssNC","fqypy45cIH","v8yFNni2v1","blLA9C2Irc","piJSkvOqCE",
-"d85a9QYxC0","YjB9thYBCK","7lUXZtl72W","DcpWBv2eC3","cL0aEpmeCd","BFkb8djsrv","s93Ml0YAGH","oVQp6AXpwE","QWxoTEdBKc","OUYuFh1zcH",
-"G1RhSvLsmS","ZhwG1JJs5m","wiHrZkB5nP","ECMvUQssNC","Ul4a1KASQ8","BFkb85iGN5","FxX9qM3zXL","l83UdI7p2a","MmKGJZuDtD","hUTw7UlU3M",
-"WmadAO3iyQ","b29RJ5Mg9r","uoStw0Wr5y","2ZHdkVjCZq","djsrv9XyT9","zY1GYk85Ae","BCxeCMkgy8","CK5W7fcwDa","kZANmjfREu","qQxHPBbwgA",
-"n1pmOGWqqX","Y1mC0taOXK","K4GS8OUqFM","HfyNQFjHXR","ZJTXHGv3Fq","qUJMd5Mg9r","WDVWJ0BmCy","SWfouiwzGk","piJSkix74r","4QMc9v8yFN",
-"ix74r7ku1p","vLsmSFnPFB","iqv4k9XyT9","UmaEvtuDyS","ni2v116lHc","SjskQThjNn","s93MlGWqqX","nlaByMmKGJ","hi5X7Cp3mZ","uN6r38xEKz",
-"n8pJ90YAGH","hSSvQChuy3","Cfgr3PYBf4","yvOMIPb1pa","NAFuwFLsph","KZamHuupzk","mz8gx1LB1L","QChxs8xEKz","pv0i7fmIK1","EoToPVIlwP",
-"atef2uoStw","hYBCKlH1kt","RzaZAprNT6","uAWypIBe8k","M3zXLpvgjS","h1zcHaFFss","RBhp0uAWyp","n1pmOSWfou","Zv7z0Cfgr3","GWqqXOz8yZ",
-"MezSWJRJQB","RsQUqWMiS3","MezSWEoToP","mX2GEiB08l","cmXIXtjQxs","IRh48LDk6f","s93Ml5ZaEz","wDajXQssNC","BGaQYDcpWB","jtn0XjS1aj",
-"JkzUnEOE1o","HzZT8MmKGJ","B3qemzbIYY","UmaEvJJs5m","K4GS8POUYS","IRh485Drn0","4dEz6cQOnv","GXdoHqaofN","ReKEWQworu","pvgjS0Wr5y",
-"K20wKtaOXK","cQOnvMK07Y","Oz8yZKZamH","yvOMIMaJQs","iqv4kGSQwj","3otm67fKYU","0Kyfs7lUXZ","0ao3l2TRI7","24ARFuPX7G","9rlg9FGzgp",
-"MaJQsMaJQs","Z4I1vS77LH","WaWsvsuY4x","aDGtS5IhmG","Z4I1v0Kyfs","jiVBPtAOsr","Zv7z0VBjhz","RBhp0uLtKs","iwzGkzY1GY","VIlwPWDVWJ",
-"dQ586Mkgy8","5ZaEzAIYUu","uAWypP6bcg","zbIYY0ao3l","IRh48Chuy3","hE1Ql7Ow5C","CxVEfydG8U","cL0aE2hEEU","ru4UGWmadA","s4786brhlQ",
-"7Ow5CCdyBV","hYBCK1v5hH","2DREsG1RhS","ksJbyLewvM","GWqqX2Nslm","POUYSSWfou","64s8N2Yz7E","zQt6QS77LH","bgJAzaDGtS","WaWsvnFqik",
-"UmaEvhi5X7","brhlQY1mC0","jtn0X9iGoT","24ARFG1RhS","HRxd82hEEU","0KyfskZANm","Yw2oUMkgy8","rz7UtJkzUn","piJSkv1Hln","NcICALbRTH",
-"rhl0JVerEA","tlILtBbwgA","ZUnqtAkKTk","WPmlxMaJQs","fqypyQClRL","AOgEeuN6r3","d7vjMK20wK","9y4lwQClRL","TCgPpI7p2a","WmadA5iGN5",
-"xReecG1RhS","FPfSEjeskS","ThjNnLbRTH","WaWsvpAhR1","WPmlxh1zcH","HfyNQhe9IA","FwEJzyofH3","S77LHC2Irc","580YDiqv4k","jzUqRFxX9q",
-"In3NSECMvU","qaofN5nmWv","OHaBzlViBv","QClRLQ6Lix","5Mg9rdjsrv","vkCHH2hEEU","S77LHIjTwP","o8UydZv7z0","t98iWjS1aj","FwEJzeuZA5",
-"fmIK1BpYhV","mz8gxfmIK1","Gv3FqY1mC0","AXpwEFFDui","Q6hMC0YAGH","7hyVvM3zXL","StlDJMK07Y","lj07Q8cVD3","6AFT0IjTwP","s93MlUlU3M",
-"CqqaDazIWp","SWfoudQ586","BbwgAWPmlx","FwEJz4W0Tl","5VZjSwiHrZ","F6PT2FVMxo","KZamHi3pyd","OHaBzWreyP","ogLgcRmDcr","RkQkeRBhp0",
-"pAhR1v1Hln","O3iyQhE1Ql","zbIYYWaWsv","tjQxsHzZT8","0YAGHni2v1","azIWppv0i7","lCMxyZUnqt","HRxd8PYBf4","JRJQBjSjS3","OUqFMFcWrW",
-"Z4I1vm4bxU","tAOsroGu6x","LewvMxciqp","55rfBFVMxo","FGzgpuupzk","0MR5XGrDg7","I7p2ao8Uyd","yvOMIDQimp","AXpwEBpYhV","dpe1v29QAz",
-"HzZT8QWxoT","GrDg7zqH0W","Waim6FNYIM","1v5hH5nmWv","XyPZN5nmWv","JRJQBEoToP","WMiS3VIlwP","SWfouD6rBy","lj07Q7hyVv","nlaByFVMxo",
-"n8pJ9h1zcH","AOgEeCK5W7","Cp3mZIRh48","TCgPphe9IA","RmDcriwzGk","SjskQI7p2a","Ta8f6okgRi","In3NS8xEKz","zz4ZU55rfB","PYBf48xEKz",
-"No0QbDcpWB","JRJQBaFFss","IjTwPjeskS","yofH3e6e4z","xciqpLewvM","zFgtBpvgjS","rhl0JbgJAz","uJScXvkCHH","uN6r3Fhtgl","5NammqQxHP",
-"AIYUuiwzGk","jiVBPGWqqX","iqv4kXyPZN","0PktIJJs5m","WreyPNo0Qb","9XyT9Q6Lix","rz7UtEOE1o","Gv3FqCNHmv","DQimpprNT6","sx5GlEoToP",
-"EdBKcazIWp","2NslmkZANm","MmsIoCfgr3","rz7Uty94nw","uvf7AOHaBz","8TxD7he9IA","AIYUusx5Gl","CK5W73otm6","Y1mC0KZamH","he9IARsQUq",
-"6q6L9yvOMI","tl72WFNYIM","8hJdtYh1hF","lkMUAFjHXR","hSSvQWaWsv","OHaBzlCMxy","FGzgplweGy","ZhwG1FnPFB","S77LHUmaEv","CxVEfUvlv4",
-"8TxD7atef2","In3NSZJTXH","9y4lwSjskQ","VerEA6q6L9","Gv3FqFxX9q","NhXduYOfrY","qQxHP7X3uy","jeskSAIYUu","TXQ0ZF6PT2","FPfSEjiVBP",
-"QWxoT8TxD7","uupzkAIYUu","FPfSENo0Qb","Y1mC0prNT6","uZPqgv8yFN","RACuj5iGN5","v2eC3HzZT8","7Ow5CCNHmv","2TRI75iGN5","rhl0JYw2oU",
-"WmadAuN6r3","BpYhVC2Irc","uQIczgjUTu","s7MxkqUJMd","UlU3MvLsmS","5Namm7hyVv","48cHLNcICA","FGzgplj07Q","FLsphaL6AJ","ydG8UNo0Qb",
-"aez9yBbwgA","64s8NydG8U","s7MxkpAhR1","YjB9tHRxd8","Pb1patuDyS","0KyfsMezSW","DcpWBuN6r3","cShY2Cfgr3","azIWpG1RhS","Oz8yZiKqhr",
-"C2Irc4dEz6","uoStwCdyBV","0Wr5yguMb8","Yw2oUJIqXi","In3NSv8yFN","FPfSEblLA9","X6PinCxVEf","pAhR1pvgjS","48cHLogLgc","ulk41blLA9",
-"NhXdu29QAz","bgJAzjeskS","9GXkXe6e4z","v1HlnVerEA","45cIHAOgEe","qUJMdSs0Zu","FwEJzbgJAz","s93Ml5Mg9r","UlU3MZUnqt","EdBKcyToGW",
-"pmeCdhE1Ql","BbwgAsx5Gl","EoToP9y4lw","5IhmGfFDrJ","618DiQYxC0","i7WMQRpBQm","JRJQB55rfB","L7cGcTa8f6","y94nwJ2mQi","guMb88RCUA",
-"8cVD3Y1mC0","NcICA5VZjS","AIYUuDz1R3","580YD618Di","2Yz7EhSSvQ","Yw2oU6q6L9","fqypyNxx9V","dQ586rhl0J","S77LHsuY4x","EOE1oRkQke",
-"B3qemaFFss","ni2v1FNYIM","zqH0WfcwDa","5VZjS5nmWv","4QMc9qQxHP","pv0i7SmGzv","he9IAzFgtB","lweGyZJTXH","KZamHzQt6Q","dQ586yofH3",
-"suY4x16lHc","qUJMdVprf2","RACujAXpwE","lViBvIn3NS","GrDg7he9IA","dmoS7hUTw7","5ZaEzWDVWJ","yvOMIIjTwP","WDVWJZJTXH","n1pmOiB08l",
-"VLTy6vkCHH","7Ow5C9XyT9","WmadAMK07Y","pmeCdhYBCK","UlU3MMmsIo","JRJQBP6bcg","LDk6faL6AJ","djsrvhi5X7","mz8gxOHaBz","gjUTu8FmFH",
-"zHF1q5ZaEz","xReecNhXdu","ZuDtD618Di","sqVrfWaim6","HRxd82TRI7","5drc6pFrrl","ZJTXHaDGtS","7lUXZuJScX","bgJAzVerEA","zHF1qWDVWJ",
-"7Ow5CGrDg7","vOqCElj07Q","zbIYYfcwDa","QWxoTzFgtB","P6bcgv2eC3","G1RhSuvf7A","fFDrJQChxs","h1zcHD6rBy","xXTI4cL0aE","Yh1hFKsjRK",
-"JJs5muQIcz","MK07YZuDtD","BGaQY2hEEU","FVMxolweGy","dmoS7Zv7z0","s7MxkuZPqg","zHF1qpT8wu","CdyBVlm0pD","i3pydokgRi","OUqFMCIShG",
-"RpBQmVNCPd","7hyVvWaWsv","QbxXculk41","ciuWzpT8wu","C2IrcPb1pa","FNYIMReKEW","v2eC3D6rBy","v2eC3Yf2Ec","RmDcr55rfB","OxWIHAXpwE",
-"0PktIs7Mxk","ZJTXHMm8si","AOgEek85Ae","piJSkVerEA","HfyNQEOE1o","hYBCK2Yz7E","RpBQmtl72W","ksJbyjiVBP","MojnP6q6L9","WDVWJUmaEv",
-"0MR5XYOfrY","jtn0XFjHXR","No0QbRpBQm","uoStwPOUYS","uLtKs7lUXZ","POUYSpAhR1","RBhp0faHir","JIqXi7Ow5C","uLtKs5VZjS","AOgEe2hEEU",
-"W3VFHn1pmO","fcJOy1v5hH","bZLvSEOE1o","jzUqRQChxs","tlILtFnPFB","mX2GEStlDJ","RxrsmIRh48","1j5L8aez9y","FLsphjiVBP","QbxXcSWfou",
-"SmGzvprNT6","HzZT8U3yw5","yvOMIEOE1o","8cVD37ku1p","K4GS8M6qcG","J2mQiP6bcg","P6bcgW3VFH","nnP8o2TRI7","5drc6ZJTXH","MGlTFNhXdu",
-"lsQGoWMiS3","In3NSWmadA","pWiOsGv3Fq","24ARF0h1b1","piJSk5Drn0","VIlwPtlILt","iKqhrW3VFH","Yw2oU2ZHdk","nnP8oMezSW","07n1cVNCPd",
-"pT8wuSjskQ","OxWIHfaHir","wDajXLewvM","QChxsl83Ud","DLhzM0Kyfs","l83UdZzJHW","0ao3lNxx9V","bgJAzcQOnv","FnPFB618Di","EdBKcs93Ml",
-"oGu6xHRxd8","7Ow5ClweGy","FxX9qVBjhz","2TRI7d85a9","BbwgAzqH0W","aFFssydG8U","y94nwk85Ae","JKWYRpAhR1","zz4ZUJXljW","AXpwEaFFss",
-"FFDuiSWfou","ZhwG18xEKz","ciuWzQ6Lix","XflUqdQ586","t98iWQ6Lix","S2DfuGSQwj","ECMvUFFDui","RsQUq2Yz7E","5Mg9roGu6x","K20wKo8Uyd",
-"JRJQB7ku1p","zQt6QDz1R3","h1zcHzbIYY","YOfrYVjCZq","TCgPprhl0J","nlaByHRxd8","LDk6fY1mC0","oVQp6HRxd8","C2IrcydG8U","pvgjSBFkb8",
-"tuDySlViBv","yvOMIaFFss","Ss0ZuhYBCK","29QAzvOqCE","SWfouZJTXH","4W0Tl2hEEU","WreyPjSjS3","Zv7z0cQOnv","JJs5mJRJQB","v8yFNB3qem",
-"P6bcgzbIYY","WMiS37hyVv","v1HlnJkzUn","bZLvSjtn0X","FFDuiy94nw","VNCPdIKxdL","QnJ1SIjTwP","pvgjSMezSW","djsrvzQt6Q","VIlwPKASQ8",
-"CdyBVoVQp6","KASQ8YjB9t","5ZaEzrKDLJ","Yw2oUiB08l","JRJQBGrDg7","MmsIoNo0Qb","zz4ZUNOHsz","Oz8yZfcwDa","x3LDehSSvQ","jfREun8pJ9",
-"VNCPdpFrrl","AIYUu5drc6","FLsphs7Mxk","nlaByfcwDa","atef2CqqaD","No0QbCp3mZ","IRh48CxVEf","jfREuTXQ0Z","AIYUuGv3Fq","oVQp6sx5Gl",
-"sqVrfLDk6f","n1pmODLhzM","FcWrWJKWYR","P6bcgThjNn","GrDg7PYBf4","sx5GltuDyS","55rfBcShY2","uTacx0PktI","xciqppFrrl","MojnPPb1pa",
-"cShY2lj07Q","7fsYMCK5W7","7fsYMhYBCK","fFDrJwiHrZ","lViBvKASQ8","5NammFPfSE","DG4sTEoToP","7lUXZ6AFT0","Z4I1voVQp6","B3qemD6rBy",
-"s93MlSmGzv","B3qemHfyNQ","xReecyEfy9","v2eC3CNHmv","8hJdtAmdQd","soy9tQ6hMC","KsjRK0YAGH","29QAzbrhlQ","aez9yzHF1q","IjTwPfcwDa",
-"ZJTXHXflUq","1LB1LjzUqR","i3pydzQt6Q","2NslmAmdQd","VLTy6OHaBz","9eoRchUTw7","9eoRc8cVD3","WDVWJguMb8","vOqCEDz1R3","nlaBy5IhmG",
-"VNCPdlj07Q","O3iyQhSSvQ","tAOsroQ87r","lXFOBP6bcg","JKWYRFGzgp","Cfgr3CK5W7","FLsphGWqqX","lCMxy1v5hH","TCgPpBbwgA","4W0Tli3pyd",
-"FFDuiSmGzv","uAWypTCgPp","L7cGcd85a9","Waim6U3yw5","M6qcGksJby","AXpwE8cVD3","OUqFM7X3uy","Dz1R3DQimp","CK5W7lkMUA","lViBvsx5Gl",
-"2Yz7EKsjRK","KASQ8Y1mC0","K20wKMkgy8","y94nwQ6hMC","uQIczuZPqg","xXTI4zHF1q","7hyVvru4UG","FGzgpRACuj","lXFOBCK5W7","uLtKsD6rBy",
-"5Drn0JXljW","ThjNnZhwG1","580YDksJby","8xEKznnP8o","pWiOs2TRI7","l83UdJkzUn","Pb1pa8cVD3","KsjRKpiJSk","Q6LixAIYUu","9rlg9y94nw",
-"K20wKulk41","EoToP9XyT9","OUqFMaez9y","ciuWzkZANm","vkCHHrKDLJ","HfyNQoVQp6","S2Dfudjsrv","IRh48BFkb8","K20wKk85Ae","v8yFNQbxXc",
-"YjB9tlweGy","guMb8hi5X7","ix74rrKDLJ","9rlg9NcICA","lViBv2Nslm","lCMxyRACuj","nnP8oaez9y","7hyVvBCxeC","FLsphQworu","FNYIMatef2",
-"ZJTXHYh1hF","F6PT28TxD7","lCMxyvOqCE","45cIHFGzgp","jtn0XblLA9","NAFuw7lUXZ","uQIczl83Ud","mz8gx0ao3l","UmaEv5drc6","MK07Y5IhmG",
-"pv0i7nFqik","SmGzvNOHsz","5VZjSEdBKc","ru4UGTCgPp","pmeCdhUTw7","taOXKQ6Lix","s4786fmIK1","WMiS3RACuj","uLtKsDLhzM","vLsmSyEfy9",
-"tAOsrdQ586","TCgPpCp3mZ","S77LH5IhmG","fcwDa1j5L8","0PktIxXTI4","xReecm4bxU","0h1b1qaofN","fFDrJNOHsz","MmKGJfqypy","kZANmgdQsS",
-"HlUbF3otm6","i7WMQn8pJ9","Yh1hF4QMc9","uZPqgIn3NS","7Ow5Ck85Ae","y94nwhE1Ql","hE1QlazIWp","ni2v1StlDJ","Oz8yZi7WMQ","5iGN5O3iyQ",
-"zqH0W2TRI7","TwanofFDrJ","cmXIXBCxeC","cmXIX24ARF","zFgtBrhl0J","zY1GYD6rBy","Oz8yZThjNn","VLTy6TCgPp","QYxC0ZhwG1","QworuQ6hMC",
-"b29RJJRJQB","ksJbyUvlv4","0ao3lzFgtB","FVMxo0ao3l","IKxdL64s8N","Yf2EcAgJHQ","dQ586dmoS7","VjCZqSbRYy","ogLgczHF1q","KZamHCfgr3",
-"lViBv7fsYM","xciqp0Kyfs","yEfy9ZuDtD","s7Mxk9rlg9","1LB1LOxWIH","5nmWv7lUXZ","d85a9dpe1v","soy9tbZLvS","ogLgc7lUXZ","K20wKpvgjS",
-"he9IA0BmCy","ogLgc4W0Tl","X6PinuQIcz","BGaQY29QAz","DG4sT8FmFH","IKxdLCIShG","nFqikNhXdu","fqypylpF6W","29QAz2TRI7","580YDlj07Q",
-"iKqhrh1zcH","1v5hHxXTI4","wDajXIKxdL","CqqaDfmIK1","dpe1vcmXIX","OUYuFaFFss","4dEz6VBjhz","RkQkeZuDtD","AkKTkhSSvQ","CNHmvMojnP",
-"1LB1LC2Irc","Yw2oUs93Ml","SbRYyI7p2a","tAOsriB08l","Ss0ZuVjCZq","soy9tuN6r3","lH1ktjS1aj","gdQsSRACuj","CdyBVulk41","In3NSEoToP",
-"GSQwjS2Dfu","ulk41No0Qb","ogLgcgIYvE","1v5hHTXQ0Z","OUYuFW7cTs","55rfBs93Ml","ru4UGUl4a1","45cIH5nmWv","lH1ktkZANm","vLsmSnnP8o",
-"WaWsvCfgr3","POUYS7lUXZ","K4GS8ulk41","AmdQdcL0aE","OUqFMHP433","0BmCyuoStw","gtCA5guMb8","zmLYDhe9IA","5IhmGTCgPp","JKWYRPOUYS",
-"Uvlv4l83Ud","ydG8UjzUqR","8TxD7hYBCK","qQxHPK4GS8","UmaEvZv7z0","s4786lCMxy","2TRI7zqH0W","7lUXZ5iGN5","ZJTXHCp3mZ","v8yFN0BmCy",
-"pT8wuBpYhV","Cp3mZMezSW","5ZaEzKsjRK","zz4ZUoQ87r","RBhp0F6PT2","StlDJd85a9","Vprf2S2Dfu","iKqhrd85a9","MezSWlViBv","9iGoTBFkb8",
-"bgJAzJRJQB","X6Pin7fsYM","n1pmOFwEJz","XflUqhe9IA","ogLgcgf8rI","FhtglRsQUq","uN6r3soy9t","tlILttAOsr","Z4I1vlH1kt","ThjNnS2Dfu",
-"07n1czFgtB","l83UdX6Pin","hUTw7OUYuF","Oz8yZXflUq","U3yw57Ow5C","CIShGcQOnv","uQIczsuY4x","Pb1papWiOs","AXpwE9XyT9","nFqikBpYhV",
-"7fsYMJKWYR","IjTwPAOgEe","CNHmvb29RJ","aDGtSjtn0X","rKDLJoVQp6","G1RhSfLNg8","Yw2oUMojnP","IBe8kW3VFH","IKxdLpWiOs","2Yz7EMaJQs",
-"8TxD7RmDcr","k85Ae8cVD3","24ARFChuy3","cShY2gjUTu","BFkb87hyVv","Yh1hFCNHmv","ksJby14FLR","Chuy3fcwDa","faHirNcICA","VjCZq8xEKz",
-"KsjRKkZANm","2hEEUfFDrJ","tvdkDfcJOy","3otm6tl72W","NhXdus4786","i3pydHfyNQ","b29RJK4GS8","G1RhSL7cGc","FLsphZ4I1v","P6bcgpAhR1",
-"8cVD3AXpwE","AkKTkM6qcG","BbwgAF6PT2","9XyT9FjHXR","zmLYDjS1aj","CK5W7HlUbF","JkzUnJJs5m","VNCPdlm0pD","5Nammi7WMQ","4QMc91LB1L",
-"DG4sTlm0pD","oGu6xoQ87r","RpBQmv8yFN","GSQwj29QAz","brhlQZ4I1v","45cIHDz1R3","jiVBPZUnqt","TwanoVerEA","JXljW14FLR","W3VFHpmeCd",
-"ydG8UdhSuH","uN6r3uJScX","VIlwP0ao3l","MaJQsKr8ys","8hJdtRxrsm","tuDyS0YAGH","vLsmStl72W","s4786y94nw","29QAzWaWsv","HP433QnJ1S",
-"S2DfuFLsph","s93MlCK5W7","zqH0WYf2Ec","9XyT9xXTI4","he9IAbrhlQ","vLsmSRmDcr","jfREuECMvU","Mm8siMK07Y","8cVD3lpF6W","DQimpYf2Ec",
-"gIYvEKsjRK","zqH0WD6rBy","cQOnv8FmFH","zmLYDEoToP","WMiS3TXQ0Z","dQ586atef2","0PktIm4bxU","In3NSFcWrW","29QAzMK07Y","s47862DREs",
-"14FLRzFgtB","vOqCEP6bcg","LDk6fpWiOs","IRh487hyVv","W7cTs2hEEU","e6e4zhi5X7","24ARF2TRI7","guMb8v2eC3","SjskQ8FmFH","4W0TlM6qcG",
-"yluBxv8yFN","SmGzvdpe1v","brhlQiwzGk","ReKEWqUJMd","IBe8kuvf7A","JkzUnjeskS","RmDcrh1zcH","KASQ8Gv3Fq","7ku1pCfgr3","lsQGo1LB1L",
-"lm0pDFxX9q","LDk6fLbRTH","CIShGEdBKc","07n1c7ku1p","gjUTuOUYuF","CqqaDdQ586","fmIK11LB1L","iqv4kQbxXc","cQOnvCqqaD","uJScXAgJHQ",
-"ZhwG1uAWyp","Waim6jeskS","6q6L94W0Tl","AkKTk2DREs","LewvMMmKGJ","RBhp0StlDJ","cmXIXS2Dfu","HRxd8Fhtgl","FjHXRTXQ0Z","pmeCdaez9y",
-"FnPFBBFkb8","F6PT27Ow5C","JkzUnksJby","OHaBz1LB1L","7hyVvblLA9","QChxsxReec","xciqprhl0J","ogLgcJIqXi","JXljWbrhlQ","WDVWJyvOMI",
-"WreyPM6qcG","a00b5mX2GE","fFDrJ0MR5X","ZuDtDWMiS3","zHF1quPX7G","Ul4a1zz4ZU","jtn0XReKEW","W7cTsMojnP","XflUqB3qem","JJs5m6AFT0",
-"3otm6JkzUn","TCgPppvgjS","uN6r3Oz8yZ","uTacxQ6hMC","QbxXc3otm6","RsQUqt98iW","uupzkh1zcH","Gv3FqhYBCK","yToGWqQxHP","4QMc9azIWp",
-"580YD0MR5X","CqqaDMm8si","jiVBPAkKTk","SmGzvDcpWB","Y1mC0X6Pin","ReKEWbrhlQ","taOXKfcJOy","5NammCdyBV","BpYhVbgJAz","oVQp6Vprf2",
-"d85a9VIlwP","7fKYUMmsIo","RBhp0v2eC3","L7cGctjQxs","3otm6v1Hln","cL0aEb29RJ","FFDuiJRJQB","VerEA1v5hH","OxWIHMojnP","SWfout59lR",
-"wiHrZhSSvQ","vLsmSvLsmS","hi5X7lXFOB","Cfgr3QbxXc","oVQp6U3yw5","55rfBFnPFB","GSQwjd7vjM","F6PT2FGzgp","aez9y7fKYU","ciuWz5nmWv",
-"8TxD72ZHdk","VLTy6MezSW","BFkb8taOXK","AXpwECK5W7","Ul4a1QssNC","lViBvuAWyp","Zv7z0iwzGk","wiHrZgIYvE","MezSWxReec","07n1cUlU3M",
-"sqVrfVLTy6","Vprf2pvgjS","IRh48No0Qb","BCxeCciuWz","HfyNQfmIK1","Mkgy8iKqhr","azIWpBCxeC","No0QbTCgPp","KsjRKeuZA5","TXQ0Z1v5hH",
-"KZamHQWxoT","o8UydOz8yZ","Rxrsm2Nslm","LDk6fpFrrl","aFFsslsQGo","cL0aE1LB1L","7X3uyGv3Fq","DcpWBulk41","FnPFBKASQ8","LewvMZhwG1",
-"2DREsWmadA","IBe8kRxrsm","zbIYYmz8gx","iqv4kqQxHP","Yw2oU8TxD7","WreyPn8pJ9","Ul4a1CK5W7","lCMxyAmdQd","ThjNnjeskS","WMiS3rKDLJ",
-"Gv3FqZhwG1","SbRYy48cHL","fmIK1DLhzM","8RCUAVIlwP","FnPFB45cIH","UmaEvNcICA","618Diru4UG","KZamHWmadA","EdBKcFPfSE","WreyPVerEA",
-"UmaEv7ku1p","JJs5mv8yFN","U3yw5taOXK","MezSWlsQGo","Ul4a10PktI","lweGyUl4a1","pFrrlCxVEf","3weIFCdyBV","FcWrWFNYIM","CIShGjS1aj",
-"QWxoToGu6x","DcpWBiB08l","LewvM1v5hH","CIShGPb1pa","UmaEvBGaQY","zY1GYwDajX","IBe8kgIYvE","cShY2pAhR1","aL6AJGWqqX","14FLRW3VFH",
-"FFDuiblLA9","lj07QAIYUu","LewvMtl72W","jtn0XlpF6W","BCxeCzQt6Q","4QMc99eoRc","7lUXZB3qem","CNHmvogLgc","x3LDe0BmCy","lweGyKASQ8",
-"QbxXcNo0Qb","6q6L945cIH","JkzUnC2Irc","7hyVvyluBx","dpe1vlsQGo","v1HlnSbRYy","U3yw5VIlwP","lCMxyksJby","vLsmSo8Uyd","ciuWzP6bcg",
-"0ao3l5Namm","uvf7AsuY4x","m4bxUnFqik","hSSvQogLgc","a00b5WreyP","aFFssdQ586","AmdQdpWiOs","45cIHPb1pa","xReecCIShG","5Drn04W0Tl",
-"UlU3M9eoRc","tlILtPYBf4","9iGoTiKqhr","zmLYDzHF1q","s93MlBpYhV","uvf7AECMvU","BGaQYjiVBP","qaofN5Namm","dhSuHVBjhz","bZLvSYf2Ec",
-"Mm8siVprf2","NhXduJXljW","P6bcgMK07Y","uJScX9iGoT","soy9tzz4ZU","ydG8URkQke","uAWypoQ87r","ReKEWtvdkD","07n1cD6rBy","gIYvEuJScX",
-"8cVD3GrDg7","S77LHaez9y","W3VFHJKWYR","s7MxkMm8si","YOfrYOUYuF","m4bxUbgJAz","oGu6xDz1R3","Pb1pahYBCK","y94nwMkgy8","GXdoH8U2nU",
-"Gv3FqtuDyS","W7cTswiHrZ","6AFT05Namm","29QAz4W0Tl","OUqFMXyPZN","8U2nUlj07Q","MmKGJ8FmFH","lweGyC2Irc","v2eC3Kr8ys","IKxdLuAWyp",
-"nFqikgf8rI","wiHrZa00b5","4W0TlMojnP","LbRTH5Drn0","Y1mC0IRh48","55rfB0h1b1","he9IAzY1GY","SWfouHRxd8","AkKTkBGaQY","HzZT829QAz",
-"lViBvThjNn","VNCPdv8yFN","uN6r3MmKGJ","F6PT2qQxHP","gdQsSDLhzM","uoStw9rlg9","wDajXjSjS3","qaofNogLgc","0BmCycL0aE","LDk6fNo0Qb",
-"fcJOyPb1pa","fcwDacShY2","vkCHHK4GS8","FwEJzhSSvQ","wiHrZAkKTk","brhlQL7cGc","JIqXisx5Gl","Ul4a1yvOMI","HzZT8CIShG","uPX7GFcWrW",
-"D6rByYh1hF","2DREstaOXK","5VZjSQnJ1S","Mm8si1v5hH","lkMUAYw2oU","WreyP3weIF","No0Qbrhl0J","Q6hMCBFkb8","cmXIXiwzGk","Yf2EcnFqik",
-"AXpwEcL0aE","wiHrZF6PT2","LDk6fM6qcG","jS1ajcmXIX","2Yz7EHP433","pWiOslj07Q","okgRi0YAGH","wiHrZaDGtS","gtCA5sqVrf","5drc64QMc9",
-"0PktI5Namm","pvgjSjzUqR","Nxx9VAmdQd","HfyNQo8Uyd","KASQ8blLA9","MmKGJUl4a1","4QMc9UmaEv","EdBKc5drc6","bZLvSAgJHQ","aDGtSW3VFH",
-"XyPZNNhXdu","Q6LixW7cTs","rhl0JXyPZN","StlDJ5Mg9r","suY4xFnPFB","F6PT2QbxXc","kB5nPThjNn","rhl0J9rlg9","sx5GlJIqXi","9y4lwPb1pa",
-"zFgtB9GXkX","FnPFB5VZjS","VNCPdpv0i7","WmadAHP433","x3LDeokgRi","uLtKsChuy3","uQIczRBhp0","pAhR1lViBv","pAhR1ThjNn","QChxsQChxs",
-"a00b5wDajX","StlDJMm8si","QWxoTVprf2","zbIYY7lUXZ","Mm8siazIWp","lsQGoGSQwj","AgJHQFPfSE","JKWYRpiJSk","StlDJCp3mZ","rKDLJ580YD",
-"uupzkKASQ8","uZPqgEdBKc","Chuy3gtCA5","5NammfcwDa","xReecAOgEe","fLNg8Oz8yZ","RzaZAjfREu","t98iWSWfou","RkQkeO3iyQ","7X3uyjS1aj",
-"ECMvULewvM","jfREuJKWYR","GrDg72DREs","CxVEfoVQp6","ix74rFPfSE","5drc6FxX9q","9iGoTzHF1q","0BmCyjSjS3","JkzUn7hyVv","FxX9qdhSuH",
-"SbRYyMezSW","lj07QFcWrW","CqqaDW3VFH","lkMUA5nmWv","AgJHQQssNC","5NammyEfy9","Qworu5drc6","AOgEefmIK1","P6bcg5Namm","QWxoTJ2mQi",
-"Uvlv4guMb8","Ul4a1Rxrsm","EdBKcGrDg7","aDGtS2hEEU","taOXK0PktI","iqv4kuLtKs","yEfy924ARF","Y1mC0yEfy9","jzUqRxciqp","2TRI7uupzk",
-"0PktIfcwDa","GrDg707n1c","lweGy4QMc9","dpe1vRpBQm","SmGzvmX2GE","LbRTHWMiS3","FLsphv2eC3","yofH3In3NS","y94nwyluBx","Vprf2ogLgc",
-"5nmWvgdQsS","Dz1R3k85Ae","24ARF7Ow5C","rhl0JLbRTH","wiHrZVNCPd","uupzk2TRI7","kZANmMojnP","ZJTXHRBhp0","GXdoHogLgc","8RCUAfmIK1",
-"tvdkDJIqXi","9rlg9i3pyd","fcwDazz4ZU","s7MxkYh1hF","jS1ajjtn0X","PYBf4prNT6","29QAz64s8N","he9IAS77LH","zmLYDVBjhz","HfyNQbZLvS",
-"aFFssW3VFH","ThjNnM6qcG","D6rByGv3Fq","ulk41M6qcG","WMiS3cL0aE","TXQ0ZQClRL","O3iyQQClRL","JKWYRqUJMd","Dz1R3WaWsv","L7cGcatef2",
-"d85a9NAFuw","9GXkXFGzgp","DLhzMM6qcG","lXFOB07n1c","9rlg9b29RJ","XyPZN24ARF","JJs5mm4bxU","29QAzatef2","MojnPguMb8","suY4xOz8yZ",
-"lViBv9y4lw","AIYUuLDk6f","J2mQiAIYUu","DcpWBo8Uyd","he9IABGaQY","lCMxyiqv4k","soy9t0PktI","BGaQY4W0Tl","h1zcHlkMUA","RBhp0rz7Ut",
-"gtCA50ao3l","gtCA55Drn0","TwanogtCA5","RsQUqKr8ys","5IhmGYf2Ec","EdBKcni2v1","ZuDtD0PktI","sx5GlTa8f6","RpBQmo8Uyd","tuDySAkKTk",
-"5iGN5CIShG","BGaQYsqVrf","IjTwPRmDcr","ciuWz9GXkX","FGzgpvkCHH","fmIK15Namm","i3pydVjCZq","MmsIo618Di","8xEKzciuWz","WreyPx3LDe",
-"S77LHpFrrl","FVMxo2TRI7","gf8rIQClRL","X6PinDcpWB","RxrsmS77LH","EdBKc2ZHdk","gIYvEgdQsS","qQxHPNOHsz","uQIczciuWz","K20wK7X3uy",
-"Z4I1vzQt6Q","vLsmSMmsIo","yofH3ZUnqt","yofH31v5hH","FLsphECMvU","FnPFBFhtgl","azIWpguMb8","G1RhSiqv4k","Cp3mZyvOMI","2TRI7Chuy3",
-"okgRi7fKYU","yvOMIUvlv4","5ZaEz7X3uy","O3iyQhe9IA","UmaEvQbxXc","Zv7z0faHir","K4GS8jzUqR","d7vjM0BmCy","b29RJyluBx","IRh483otm6",
-"yvOMI0BmCy","ReKEWQWxoT","jeskSZhwG1","HfyNQTa8f6","0Kyfsn8pJ9","s4786FVMxo","tAOsrRpBQm","ru4UGGWqqX","LewvMpmeCd","7Ow5CiwzGk",
-"6AFT0OHaBz","n8pJ9Ta8f6","lsQGoNAFuw","dhSuH0BmCy","2hEEUXflUq","WMiS35nmWv","6q6L9KsjRK","mX2GEFNYIM","8RCUA5ZaEz","HlUbFMmKGJ",
-"2DREst98iW","v1Hlna00b5","5drc6VNCPd","RxrsmpWiOs","B3qemcQOnv","Mm8siKr8ys","yofH32ZHdk","v8yFNW7cTs","UlU3McQOnv","K4GS8iqv4k",
-"v2eC3guMb8","Waim6Dz1R3","SjskQYf2Ec","bgJAz0BmCy","OHaBzjiVBP","HRxd8TXQ0Z","b29RJPYBf4","piJSkJJs5m","mX2GEcL0aE","FGzgp2DREs",
-"MK07YfcwDa","faHiroQ87r","FcWrW8TxD7","tlILtVerEA","8FmFHiqv4k","OUYuFVjCZq","tlILtMGlTF","24ARFOz8yZ","8FmFHQ6hMC","okgRiFLsph",
-"b29RJ618Di","faHirBCxeC","fFDrJTa8f6","FGzgp8cVD3","nFqik8FmFH","RACujVNCPd","B3qemuLtKs","RpBQmxciqp","gdQsSpiJSk","8RCUA9rlg9",
-"GWqqX1v5hH","l83UdiKqhr","5Mg9rl83Ud","TwanoQ6hMC","K4GS8pv0i7","48cHLyEfy9","i7WMQrKDLJ","IRh48Ta8f6","sx5GlI7p2a","4dEz629QAz",
-"6q6L95IhmG","RACujDcpWB","WmadAStlDJ","Mm8siVNCPd","Ta8f6Fhtgl","RsQUqqQxHP","FnPFBQbxXc","0ao3l2Yz7E","7fsYMKr8ys","3weIF7X3uy",
-"azIWptuDyS","m4bxUazIWp","soy9tVprf2","VLTy6iKqhr","Z4I1vFjHXR","0MR5XNcICA","580YD8hJdt","MaJQsI7p2a","mz8gxfqypy","aL6AJpiJSk",
-"Pb1paDLhzM","7Ow5CU3yw5","uJScXiKqhr","5IhmG45cIH","ru4UG580YD","S77LHoQ87r","RkQkeOxWIH","uJScXlkMUA","0KyfsAXpwE","qUJMdUvlv4",
-"OHaBzYh1hF","ciuWzX6Pin","FwEJzL7cGc","i3pydsuY4x","zFgtBuoStw","QWxoTyluBx","uN6r3Cp3mZ","QWxoTM6qcG","pvgjS16lHc","v2eC3Yw2oU",
-"Gv3FqVBjhz","Y1mC0AgJHQ","3otm6618Di","1LB1Lfqypy","TCgPp7Ow5C","1v5hHVIlwP","CNHmvfcwDa","JRJQBv2eC3","lXFOBulk41","0BmCyy94nw",
-"LewvM9GXkX","rz7Uts4786","7fKYUZzJHW","vkCHHHfyNQ","PYBf4gf8rI","iqv4kt98iW","ulk41s93Ml","v2eC3gtCA5","kB5nPRzaZA","ThjNnUl4a1",
-"0KyfsJXljW","brhlQpAhR1","Waim6gjUTu","WDVWJVIlwP","Chuy3jfREu","b29RJuQIcz","v8yFNFhtgl","Yh1hF5VZjS","cL0aEfcJOy","CK5W7TXQ0Z",
-"OxWIHb29RJ","m4bxUzFgtB","GWqqXAmdQd","o8Uyd0BmCy","t98iWTXQ0Z","NcICA1LB1L","MmsIo580YD","kB5nPECMvU","LbRTHtuDyS","t59lRlm0pD",
-"CqqaDQClRL","cmXIXLewvM","KZamHpWiOs","S2DfuGv3Fq","W3VFHiB08l","vOqCEqaofN","v1Hlnfqypy","iB08laez9y","ThjNnIjTwP","uAWypgdQsS",
-"StlDJtlILt","zmLYDReKEW","9iGoTzY1GY","tAOsrTXQ0Z","JRJQBAIYUu","618Die6e4z","FjHXRzFgtB","aL6AJ9iGoT","FPfSEoVQp6","RACujK20wK",
-"uZPqglj07Q","he9IAlm0pD","gIYvESWfou","HfyNQKsjRK","GrDg7AXpwE","1LB1L48cHL","CdyBVs7Mxk","IjTwPHRxd8","euZA5SbRYy","ulk41jtn0X",
-"HzZT85drc6","RACujTCgPp","a00b5RpBQm","EoToPFFDui","iB08lRkQke","tvdkDUlU3M","MezSWFhtgl","iqv4k7Ow5C","9y4lwNcICA","Zv7z007n1c",
-"v2eC3lH1kt","LbRTH8xEKz","0MR5XgjUTu","WDVWJhYBCK","zmLYDfcwDa","OUYuFnlaBy","BGaQYqQxHP","CxVEfIKxdL","t59lRhSSvQ","ksJbyFPfSE",
-"cL0aEQClRL","6q6L93weIF","RmDcrjzUqR","FFDuisuY4x","gf8rIJRJQB","fLNg87X3uy","PYBf4i7WMQ","Waim67fKYU","xReecMaJQs","S77LHv1Hln",
-"8xEKzlXFOB","0MR5XVjCZq","Yw2oU5IhmG","AXpwEBbwgA","hUTw7MK07Y","5nmWvDLhzM","CIShGIn3NS","kB5nPAmdQd","ix74r5IhmG","ksJbyhUTw7",
-"xciqpnnP8o","9y4lwHfyNQ","2ZHdkVBjhz","Yw2oUwDajX","t98iWcShY2","QworuOz8yZ","Uvlv48TxD7","euZA5StlDJ","VIlwP5nmWv","S2DfuFPfSE",
-"sqVrfXyPZN","W7cTsFFDui","QClRLP6bcg","brhlQRpBQm","Z4I1vjzUqR","oVQp6Yh1hF","zqH0WO3iyQ","RkQke7lUXZ","JIqXizmLYD","S2DfuHRxd8",
-"5VZjSMaJQs","MaJQsMmKGJ","i7WMQCIShG","Cfgr3WMiS3","0Wr5y9eoRc","5nmWvRmDcr","WreyPyofH3","ogLgclsQGo","yvOMI48cHL","uPX7G4QMc9",
-"16lHculk41","2NslmuQIcz","lViBvfcJOy","dhSuHQWxoT","QChxsx3LDe","FGzgpMmsIo","AIYUun8pJ9","Pb1papT8wu","SbRYyWaim6","Twanot98iW",
-"i7WMQECMvU","he9IAFjHXR","0BmCyoGu6x","n1pmOhE1Ql","PYBf4Mkgy8","LbRTHjiVBP","dpe1voGu6x","4W0TlJXljW","FjHXRaL6AJ","K20wKvOqCE",
-"qaofNgjUTu","3otm6AkKTk","M3zXLKASQ8","RBhp02ZHdk","hE1Ql45cIH","pv0i7l83Ud","lweGyi3pyd","Cfgr3pWiOs","lXFOBK4GS8","8U2nUiwzGk",
-"S2DfuWaWsv","pFrrlpFrrl","AXpwEnFqik","qaofN7ku1p","n8pJ9fmIK1","uoStw7X3uy","JKWYRNo0Qb","bZLvSdjsrv","tAOsrcShY2","VerEA4W0Tl",
-"fqypyFcWrW","VNCPdfcJOy","FFDuiogLgc","uJScXix74r","FNYIMh1zcH","2hEEUv1Hln","POUYSOz8yZ","HRxd8MaJQs","TXQ0ZRmDcr","NAFuwS77LH",
-"9XyT9Ul4a1","okgRini2v1","cQOnv9XyT9","Oz8yZZhwG1","pmeCdlH1kt","RmDcrCxVEf","RACujZ4I1v","CNHmviqv4k","KASQ88xEKz","dQ586AXpwE",
-"2ZHdktl72W","qaofNi7WMQ","suY4x618Di","zFgtBDLhzM","ydG8UzHF1q","e6e4zuvf7A","he9IAk85Ae","14FLRB3qem","M3zXL6q6L9","KZamHjiVBP",
-"zY1GYru4UG","ogLgcgjUTu","wiHrZK20wK","v8yFNtl72W","CqqaDnFqik","NAFuwFwEJz","JJs5mrKDLJ","MmKGJgIYvE","XflUqo8Uyd","AmdQd1v5hH",
-"oQ87rKsjRK","UmaEv6AFT0","i7WMQfFDrJ","4dEz6BFkb8","n1pmOUvlv4","Zv7z0mX2GE","5Mg9r9y4lw","C2IrcyvOMI","WmadAt98iW","uAWyp2TRI7",
-"GrDg7I7p2a","iKqhrFFDui","Uvlv4NhXdu","uupzkuLtKs","QChxs8TxD7","aDGtSFVMxo","WmadAuPX7G","TwanouPX7G","ECMvUhUTw7","k85AeFjHXR",
-"Y1mC0t59lR","dmoS7jSjS3","mz8gxQChxs","qUJMdZzJHW","2TRI7d7vjM","RACujQYxC0","FVMxoSmGzv","Rxrsm55rfB","YjB9ttAOsr","lweGyW3VFH",
-"v8yFNt59lR","29QAz2hEEU","MezSW0PktI","y94nwpmeCd","ZzJHWK4GS8","k85AeHRxd8","fLNg8LbRTH","3otm6StlDJ","n1pmO2DREs","MezSWCp3mZ",
-"VjCZqv2eC3","2hEEUtlILt","7fKYU9XyT9","jSjS3hSSvQ","G1RhSfaHir","Q6LixYjB9t","7fsYMKASQ8","o8UydAOgEe","zFgtBgtCA5","pv0i74dEz6",
-"9XyT9qUJMd","POUYSUmaEv","J2mQivOqCE","cQOnv2Yz7E","uupzkhSSvQ","618Dib29RJ","LDk6f5VZjS","Yf2EcuAWyp","ulk41lj07Q","GXdoH7X3uy",
-"5nmWvuvf7A","YOfrY8RCUA","vLsmSmX2GE","2TRI7CdyBV","jeskSFcWrW","fcwDaLDk6f","55rfBQbxXc","nnP8opFrrl","jSjS36AFT0","vOqCE8xEKz",
-"Vprf28cVD3","ZhwG1DG4sT","Kr8ysrKDLJ","TXQ0ZnFqik","azIWpKZamH","8TxD7mX2GE","VerEAS2Dfu","ogLgcCIShG","MGlTFh1zcH","CxVEfyEfy9",
-"RpBQmkZANm","okgRiQYxC0","SWfouCp3mZ","uPX7Gfqypy","ZuDtDJKWYR","29QAzzqH0W","ZJTXHFFDui","o8UydvkCHH","5drc6NAFuw","uoStw8FmFH",
-"v2eC3v8yFN","v8yFNydG8U","WaWsvtaOXK","X6Pin07n1c","fcwDaPb1pa","gf8rIgf8rI","Cp3mZhe9IA","2DREsI7p2a","8RCUAUl4a1","DLhzMIRh48",
-"7lUXZpAhR1","WreyPfaHir","MGlTFOHaBz","BbwgANo0Qb","Yf2Ec1j5L8","hUTw7580YD","fcwDa4QMc9","HfyNQ9rlg9","s7Mxk8xEKz","WmadAJkzUn",
-"MaJQsrhl0J","zFgtBEOE1o","n1pmOfcJOy","Q6hMCt59lR","NAFuw5ZaEz","QYxC0YOfrY","CdyBVO3iyQ","P6bcgOz8yZ","NOHszn8pJ9","45cIHMaJQs",
-"hYBCK5iGN5","pWiOsOxWIH","uQIczW3VFH","Mm8siLewvM","3otm6VBjhz","lweGyzbIYY","aez9yzQt6Q","jSjS3rhl0J","cShY2yToGW","KZamH0PktI",
-"1LB1LVNCPd","48cHLyofH3","xReecoQ87r","2TRI7dhSuH","blLA9ulk41","QnJ1SNxx9V","vOqCEHlUbF","QClRLoQ87r","CIShGZhwG1","uZPqgpiJSk",
-"o8Uydy94nw","QWxoTZJTXH","BFkb87lUXZ","jS1ajn8pJ9","Pb1payEfy9","Ul4a10ao3l","BFkb8uN6r3","Gv3FqiB08l","prNT6YjB9t","hYBCKcQOnv",
-"9y4lwtjQxs","euZA5lm0pD","FcWrWjfREu","Z4I1vEOE1o","OHaBzrhl0J","8FmFHtuDyS","xReecS2Dfu","OxWIHjzUqR","ksJbyBpYhV","gIYvE5Drn0",
-"ru4UGHlUbF","v1HlnlXFOB","F6PT2BGaQY","lViBvt98iW","cShY2O3iyQ","7fsYMzY1GY","zFgtB3weIF","uZPqgM3zXL","s4786Gv3Fq","qQxHPlpF6W",
-"azIWpXflUq","gf8rINxx9V","K4GS8dmoS7","NAFuw8U2nU","Q6hMCni2v1","5Drn0m4bxU","7X3uyrz7Ut","piJSkt98iW","zY1GY2ZHdk","bZLvSCqqaD",
-"ZzJHWjzUqR","CdyBVCxVEf","HfyNQNAFuw","5Namm5drc6","CqqaDVjCZq","HzZT8uoStw","uJScXPOUYS","G1RhSWMiS3","lj07QIjTwP","fcwDayToGW",
-"DG4sTpAhR1","Chuy3AgJHQ","LbRTHLbRTH","kZANmBCxeC","FhtglVLTy6","6AFT0Yf2Ec","fcwDaS2Dfu","hYBCKEdBKc","VNCPdpvgjS","7lUXZoGu6x",
-"RBhp0Rxrsm","7Ow5CCfgr3","8hJdtqQxHP","Q6Lix8FmFH","cQOnvRpBQm","9iGoTi7WMQ","WMiS3jiVBP","BGaQYTa8f6","QssNCbrhlQ","VBjhzW7cTs",
-"DQimpiwzGk","pv0i7B3qem","v1HlnEOE1o","ru4UGFLsph","RsQUqJXljW","rhl0JuoStw","No0QbUmaEv","cQOnvtvdkD","n8pJ9vkCHH","AmdQdS77LH",
-"uvf7A2Yz7E","uTacx5Namm","MezSWRkQke","CNHmvMaJQs","v2eC37fsYM","VjCZqWPmlx","FnPFBWMiS3","OUYuFatef2","FPfSEQClRL","nFqik0h1b1",
-"okgRiCqqaD","Gv3Fq2Nslm","zbIYYtvdkD","t59lRWaim6","pmeCdciuWz","S2DfutjQxs","HlUbFMm8si","hi5X7ulk41","8TxD7ciuWz","qaofNa00b5",
-"BFkb8AXpwE","lj07QTCgPp","WPmlxSbRYy","dQ586mX2GE","Y1mC0ciuWz","tAOsrGWqqX","ulk41suY4x","blLA9P6bcg","ciuWzMK07Y","NcICAfcJOy",
-"SbRYyRACuj","AkKTkVjCZq","t98iWtvdkD","aDGtSWmadA","DcpWBZhwG1","zbIYYjzUqR","ydG8U1j5L8","UmaEvyofH3","uN6r3atef2","gjUTu7fKYU",
-"8FmFHuJScX","JIqXiRkQke","JKWYRuvf7A","djsrv9iGoT","ru4UGnFqik","Waim6Pb1pa","CdyBVzmLYD","taOXKcQOnv","2Yz7ETa8f6","JRJQBrKDLJ",
-"brhlQHzZT8","fmIK145cIH","LbRTHsuY4x","yofH3JXljW","t98iWyvOMI","taOXKzFgtB","JKWYR7ku1p","uoStwZhwG1","n1pmO9rlg9","7lUXZRsQUq",
-"SbRYyydG8U","S77LHZUnqt","SmGzvoVQp6","jeskSt59lR","xXTI4pmeCd","4QMc9uTacx","GXdoHlkMUA","zz4ZUI7p2a","0PktIG1RhS","kZANmfLNg8",
-"cmXIX7lUXZ","9y4lwCp3mZ","jzUqRaFFss","VNCPdcQOnv","GrDg7VIlwP","6AFT0rKDLJ","ZUnqtuTacx","M6qcGxXTI4","YjB9tCfgr3","ciuWz4W0Tl",
-"5IhmGJJs5m","I7p2a0PktI","Dz1R3yEfy9","aez9yK4GS8","rz7Uta00b5","4dEz6Waim6","pWiOs7fKYU","TwanoDz1R3","AgJHQMmsIo","VIlwPRkQke",
-"ru4UGQworu","F6PT2ix74r","ni2v1AkKTk","XflUqCK5W7","2hEEUix74r","W7cTsRACuj","i7WMQtvdkD","zQt6QWreyP","5drc6HP433","ZUnqtYjB9t",
-"Y1mC0VjCZq","7X3uy4QMc9","brhlQ2TRI7","TwanoXyPZN","WaWsvWmadA","zmLYD5Mg9r","v1Hlni7WMQ","lj07QlpF6W","uTacxgtCA5","8TxD77Ow5C",
-"xXTI4iKqhr","K20wKYjB9t","sqVrfjiVBP","IKxdLpvgjS","BpYhVHzZT8","n1pmOlj07Q","HfyNQMojnP","C2Irc55rfB","oGu6x5VZjS","brhlQru4UG",
-"FwEJzlm0pD","BbwgAjeskS","b29RJRBhp0","2ZHdkaL6AJ","uvf7Av2eC3","UlU3MzqH0W","MGlTFWmadA","ydG8UWmadA","BpYhVm4bxU","RmDcrOUqFM",
-"5Mg9rNxx9V","nlaBy5VZjS","JJs5m580YD","DG4sTbrhlQ","hi5X7EoToP","QClRL8xEKz","618DilsQGo","Pb1paD6rBy","Ul4a1SbRYy","RsQUq7ku1p",
-"oQ87rlViBv","KsjRKMGlTF","0Wr5yRkQke","taOXKtvdkD","gf8rIQYxC0","kZANmMK07Y","Q6LixuLtKs","VNCPdvOqCE","AOgEejSjS3","vLsmS2ZHdk",
-"xciqpt98iW","VNCPdZv7z0","OxWIHZJTXH","M3zXL64s8N","24ARFMK07Y","WPmlxC2Irc","5drc6Oz8yZ","bZLvS0MR5X","Yh1hFJRJQB","s7Mxk7fKYU",
-"rhl0JwiHrZ","k85AegjUTu","gjUTuHfyNQ","FcWrW7ku1p","8FmFHQworu","5nmWvHzZT8","7hyVviwzGk","aFFssmX2GE","d7vjM9rlg9","2DREsuLtKs",
-"IRh48yofH3","IBe8kGSQwj","GXdoHjiVBP","5Nammuvf7A","BGaQYjtn0X","Yw2oU8RCUA","2TRI7vkCHH","tjQxsk85Ae","tjQxsCp3mZ","IjTwPJXljW",
-"48cHLFLsph","b29RJ16lHc","JRJQBs4786","KZamHAmdQd","YOfrYJIqXi","ZzJHWWDVWJ","EdBKcKr8ys","QClRLCIShG","X6PinAgJHQ","y94nwG1RhS",
-"FNYIM2ZHdk","gdQsSFGzgp","jeskS618Di","OxWIHKsjRK","mX2GEHRxd8","5NammdmoS7","nnP8oFxX9q","tuDyS7lUXZ","prNT6e6e4z","tlILt1LB1L",
-"No0Qbn1pmO","mX2GEFjHXR","8TxD7U3yw5","Pb1pasuY4x","2Yz7E0Wr5y","7fsYM45cIH","kB5nPxXTI4","rhl0J1v5hH","lm0pD8U2nU","yEfy9SjskQ",
-"LbRTHRsQUq","NcICAtAOsr","VerEARzaZA","RBhp0FLsph","ogLgcuZPqg","FnPFByEfy9","WPmlxjSjS3","cmXIXPOUYS","zHF1qCIShG","s7Mxk5IhmG",
-"wDajXqUJMd","hE1QlFcWrW","WmadAfcwDa","oQ87rZhwG1","yluBxLbRTH","s4786pFrrl","gjUTuxXTI4","S77LHlH1kt","Twanorhl0J","OxWIHIn3NS",
-"XyPZNjS1aj","cmXIXqQxHP","zmLYDe6e4z","KASQ8aL6AJ","Kr8ysjtn0X","IBe8ke6e4z","pT8wuOHaBz","jtn0XpmeCd","X6PinFPfSE","LewvMnFqik",
-"gjUTuL7cGc","uupzk0MR5X","ix74ryofH3","ReKEWTXQ0Z","d85a9Oz8yZ","QnJ1SSjskQ","9eoRcZuDtD","ZuDtDTCgPp","TwanoNOHsz","XflUqFNYIM",
-"YjB9tBCxeC","QWxoTatef2","suY4xFNYIM","FNYIM9eoRc","0Kyfs2Nslm","hYBCKoGu6x","8xEKzyToGW","n1pmOuJScX","lkMUAFhtgl","aL6AJWMiS3",
-"lsQGoyEfy9","NhXduuN6r3","XyPZN2TRI7","ZhwG1lsQGo","RkQkeGv3Fq","ciuWziqv4k","tAOsra00b5","Zv7z0FFDui","suY4x7X3uy","o8Uyd2Yz7E",
-"OHaBztlILt","a00b5FLsph","VIlwPt98iW","0Wr5y55rfB","mX2GEFcWrW","IBe8kt98iW","s4786fFDrJ","NhXduIjTwP","OxWIH0PktI","MojnP5Mg9r",
-"7ku1pJKWYR","jtn0XHlUbF","zHF1qfmIK1","FxX9qfcwDa","taOXKIBe8k","d7vjM55rfB","NhXduEdBKc","7X3uy2DREs","9iGoTfLNg8","b29RJEOE1o",
-"hSSvQKsjRK","fqypyxReec","JKWYROUqFM","faHirydG8U","gjUTuTwano","GrDg7VNCPd","JJs5mpT8wu","FVMxo4QMc9","LDk6fkB5nP","5iGN5uN6r3",
-"KsjRKTa8f6","ydG8UYw2oU","jiVBPnFqik","SbRYytjQxs","S2DfuZhwG1","DG4sTtAOsr","FVMxoEoToP","uTacxFFDui","LewvMvkCHH","ogLgcqQxHP",
-"6AFT08TxD7","zz4ZUzbIYY","SbRYygf8rI","tuDySCdyBV","GrDg7Nxx9V","XyPZNtvdkD","tl72W55rfB","W7cTsQnJ1S","prNT6FGzgp","nnP8oM6qcG",
-"nFqikWDVWJ","i7WMQFxX9q","QWxoTmz8gx","lpF6WQ6Lix","DG4sTmX2GE","lXFOBuLtKs","6AFT0nlaBy","VBjhzJkzUn","NOHszK4GS8","tuDyS4QMc9",
-"FPfSEzFgtB","cL0aEfcwDa","soy9tfcJOy","tuDySrz7Ut","Ul4a1iB08l","P6bcge6e4z","D6rByPb1pa","O3iyQix74r","618DiOHaBz","tjQxsQbxXc",
-"gdQsS5iGN5","vkCHHBpYhV","zQt6QJRJQB","Yh1hF5iGN5","gIYvE0YAGH","fcwDaXflUq","tuDySIRh48","7X3uyVprf2","fcJOyFnPFB","qaofN14FLR",
-"StlDJLDk6f","dQ586VIlwP","HRxd8d85a9","RBhp0AmdQd","Ss0ZuZv7z0","Chuy3CK5W7","b29RJKsjRK","pv0i7AOgEe","5ZaEzWaWsv","jfREutvdkD",
-"aDGtS4W0Tl","UlU3MMm8si","0YAGHEoToP","sx5GlnFqik","xXTI4sqVrf","StlDJVNCPd","GSQwjgtCA5","PYBf48U2nU","I7p2axciqp","FLsph9XyT9",
-"2DREsxciqp","pAhR1zQt6Q","iwzGkZUnqt","5drc6NOHsz","bgJAzIRh48","yofH3D6rBy","W3VFHpv0i7","5NammQssNC","zz4ZU2DREs","aDGtSGv3Fq",
-"VBjhzFPfSE","2TRI7jiVBP","SmGzvFNYIM","ciuWzL7cGc","QworuzqH0W","Cfgr3RBhp0","hUTw7ReKEW","yofH3h1zcH","4dEz6618Di","fqypyBFkb8",
-"FLsph64s8N","K20wKNxx9V","RxrsmLDk6f","s93Ml2hEEU","8xEKzXyPZN","piJSkhSSvQ","6q6L907n1c","lCMxy8cVD3","o8UydL7cGc","qQxHPtjQxs",
-"SmGzvHfyNQ","07n1cblLA9","2hEEUMm8si","HP433fLNg8","RACujBGaQY","FNYIMSmGzv","FVMxofFDrJ","8xEKzhe9IA","x3LDeAOgEe","Yf2Ec7fsYM",
-"yvOMI24ARF","x3LDeRzaZA","gf8rIMK07Y","HlUbFbgJAz","s4786uAWyp","2hEEUO3iyQ","SWfouuZPqg","9y4lwcmXIX","55rfBCIShG","m4bxUOHaBz",
-"K20wKGSQwj","WreyPlCMxy","3weIFNOHsz","JJs5maez9y","AXpwETwano","YjB9tQWxoT","DLhzMzmLYD","rhl0Jhe9IA","2DREsAOgEe","QnJ1SRBhp0",
-"tlILtVIlwP","ksJbyQworu","fcJOypvgjS","pWiOsgdQsS","WMiS3i7WMQ","MezSWqaofN","0Wr5yY1mC0","aez9ySs0Zu","AIYUufaHir","jS1ajLbRTH",
-"DG4sTazIWp","pmeCdrz7Ut","2NslmFPfSE","lkMUAi3pyd","HlUbFgtCA5","QssNC1v5hH","cL0aEx3LDe","2DREsFhtgl","Waim62Yz7E","SbRYyXflUq",
-"5Drn0zFgtB","TCgPpsx5Gl","lCMxyuQIcz","m4bxUbrhlQ","CdyBVjfREu","iqv4kIBe8k","jiVBPRBhp0","QworulkMUA","uAWypMmKGJ","4dEz6WPmlx",
-"kZANmy94nw","RACujcL0aE","VIlwPK4GS8","XflUqzQt6Q","QYxC0580YD","uupzk8TxD7","lm0pDCdyBV","KZamHzbIYY","0KyfsFVMxo","MojnPaez9y",
-"Vprf2jiVBP","Dz1R38cVD3","pWiOsFFDui","RkQkeo8Uyd","v8yFNnFqik","t59lRgjUTu","7X3uyMmsIo","TwanovkCHH","gtCA5XflUq","MaJQsYjB9t",
-"soy9tlj07Q","ThjNntaOXK","8TxD7euZA5","8cVD3jS1aj","GXdoHJkzUn","zbIYYoGu6x","Z4I1vRzaZA","wiHrZFFDui","cmXIXi7WMQ","5Nammjtn0X",
-"pvgjSlweGy","TwanoSbRYy","Yf2EcFPfSE","1v5hHcmXIX","MmKGJqaofN","2Yz7ESjskQ","WMiS3YOfrY","5nmWvX6Pin","WDVWJYjB9t","55rfB1v5hH",
-"k85AeuoStw","uN6r3VIlwP","RmDcrcL0aE","Qworun8pJ9","gdQsStlILt","uupzkciuWz","OUYuFMm8si","K4GS8gdQsS","Zv7z0fcwDa","NOHszzmLYD",
-"POUYS5VZjS","h1zcHM3zXL","jiVBPOz8yZ","7fKYUdjsrv","prNT6cShY2","pAhR1tl72W","Zv7z07X3uy","WDVWJb29RJ","OUYuFhE1Ql","RBhp0lCMxy",
-"AgJHQWmadA","9rlg9fqypy","pAhR1MK07Y","lweGysoy9t","618Di2hEEU","DLhzMxciqp","hSSvQaDGtS","ulk41BCxeC","e6e4zAgJHQ","Waim65Drn0",
-"FxX9qReKEW","0MR5XOHaBz","s7MxkzY1GY","jeskSDQimp","DcpWBpT8wu","Gv3FqAmdQd","prNT6QssNC","brhlQRBhp0","2ZHdkWaim6","B3qemCfgr3",
-"lj07QhSSvQ","0PktIS77LH","fmIK1jfREu","oGu6xlkMUA","Nxx9VEOE1o","ni2v1euZA5","pAhR13weIF","vOqCElm0pD","v8yFNI7p2a","2ZHdkdjsrv",
-"BCxeC0YAGH","rKDLJoQ87r","TCgPpIBe8k","GWqqXiwzGk","O3iyQCIShG","yvOMI3weIF","RBhp05ZaEz","S2Dfu5Drn0","8U2nU3otm6","0ao3lru4UG",
-"pmeCdlsQGo","2DREshUTw7","24ARFAOgEe","TCgPpX6Pin","Cp3mZZ4I1v","MK07YVIlwP","L7cGcOxWIH","tAOsrv1Hln","zQt6QZUnqt","Yw2oUKASQ8",
-"gjUTuYOfrY","RkQkeQbxXc","qUJMdQChxs","hE1QlqUJMd","BbwgAFcWrW","lViBvpiJSk","ZJTXHydG8U","MaJQsWaim6","Rxrsm14FLR","uZPqgs93Ml",
-"WPmlxSmGzv","y94nwGv3Fq","qQxHPG1RhS","YjB9t0Kyfs","oQ87ruPX7G","hi5X716lHc","BpYhV2DREs","0YAGHZ4I1v","5ZaEzGXdoH","cL0aEpWiOs",
-"0MR5XBFkb8","IRh48zY1GY","yToGW5ZaEz","FPfSE29QAz","DLhzMMezSW","IKxdLOHaBz","FLsphB3qem","iwzGkM3zXL","7lUXZRBhp0","UmaEv4W0Tl",
-"MK07YiwzGk","G1RhSjfREu","pWiOs618Di","S77LHqQxHP","jzUqRhi5X7","e6e4z7lUXZ","5Namm0h1b1","dQ586ogLgc","RxrsmM3zXL","P6bcgqaofN",
-"n8pJ9vOqCE","PYBf4dhSuH","J2mQiZhwG1","O3iyQTCgPp","azIWpRACuj","oVQp6oGu6x","RBhp0Ss0Zu","0MR5XLbRTH","gdQsS5nmWv","4QMc9fmIK1",
-"No0QbECMvU","uZPqg2Yz7E","ni2v12Nslm","BCxeCQnJ1S","MmsIoAmdQd","lweGybgJAz","piJSkAkKTk","7X3uyxXTI4","fFDrJ3weIF","BFkb8cmXIX",
-"kZANmaFFss","RACuji7WMQ","0YAGH3otm6","QnJ1SsuY4x","yluBxQworu","FhtglX6Pin","v1HlnReKEW","FhtglChuy3","uLtKss93Ml","8RCUACdyBV",
-"CIShGpmeCd","GSQwjJkzUn","5IhmGVjCZq","4W0TlvkCHH","iB08lJ2mQi","9XyT9CxVEf","jfREufcwDa","16lHcfFDrJ","QworuprNT6","M3zXLAgJHQ",
-"uJScX8xEKz","8cVD38hJdt","QworuTXQ0Z","RBhp048cHL","FnPFBXflUq","X6PinOz8yZ","YOfrYpmeCd","5Drn0zHF1q","8hJdtK4GS8","Mm8si5ZaEz",
-"b29RJuPX7G","jfREufaHir","djsrvtaOXK","I7p2aCqqaD","sqVrfqQxHP","tlILtjfREu","Yf2EclXFOB","nFqikpv0i7","ThjNnfcwDa","W3VFHni2v1",
-"rz7Utlj07Q","F6PT2FnPFB","TwanoF6PT2","8cVD3G1RhS","3otm6fcJOy","xReecLbRTH","fqypyYf2Ec","9XyT9BCxeC","BFkb8DcpWB","pWiOsVLTy6",
-"VBjhzVprf2","8U2nU55rfB","FxX9qjeskS","brhlQtuDyS","Uvlv4rhl0J","zqH0WVjCZq","xReeci7WMQ","CNHmvUl4a1","45cIH0Wr5y","Y1mC0uPX7G",
-"Q6LixBGaQY","zz4ZUBbwgA","pvgjSBpYhV","jeskSVprf2","RpBQmkB5nP","cShY2J2mQi","0h1b11j5L8","Nxx9VQ6Lix","yluBx2Nslm","pAhR1xciqp",
-"h1zcHzY1GY","24ARFQWxoT","SmGzvpmeCd","PYBf45IhmG","y94nwzHF1q","KZamHBbwgA","ydG8ULDk6f","0KyfsRxrsm","ZUnqtFPfSE","AmdQdzmLYD",
-"ZUnqtHzZT8","5nmWvOxWIH","fmIK1Pb1pa","QChxspWiOs","fmIK1M6qcG","ZJTXHYjB9t","K4GS84QMc9","s4786pAhR1","45cIHK4GS8","EoToP2hEEU",
-"In3NSIn3NS","o8Uydd7vjM","1v5hHokgRi","zFgtBCdyBV","NOHszzQt6Q","RmDcr9iGoT","pmeCdqUJMd","KsjRKG1RhS","zqH0WLewvM","ru4UGKASQ8",
-"No0QbMGlTF","BbwgAksJby","RkQkeYw2oU","MojnPPYBf4","pv0i7azIWp","5Mg9rt98iW","5IhmGZUnqt","WDVWJEOE1o","2TRI724ARF","ix74rQWxoT",
-"MmKGJSmGzv","yluBxAIYUu","FwEJzzqH0W","VjCZqiwzGk","8RCUAqQxHP","2TRI7o8Uyd","7X3uy5drc6","yluBxksJby","NAFuwuN6r3","Vprf2ECMvU",
-"yEfy9OUYuF","rKDLJ7X3uy","Mkgy8Dz1R3","FwEJzHzZT8","RACujqUJMd","0MR5XQ6hMC","AgJHQru4UG","2TRI755rfB","0KyfsfLNg8","jSjS3DG4sT",
-"Pb1pagjUTu","0YAGHrz7Ut","NcICA5nmWv","jS1ajrhl0J","ru4UGAkKTk","5drc6bZLvS","3otm6FPfSE","6AFT0Y1mC0","JJs5m0Wr5y","JkzUnDG4sT",
-"RBhp0LbRTH","WreyPQ6Lix","HfyNQ16lHc","MaJQsogLgc","fFDrJFFDui","zmLYDdQ586","gtCA5ZhwG1","ReKEW9rlg9","5Drn0JJs5m","K20wKQ6hMC",
-"Zv7z0YjB9t","2NslmSWfou","VIlwPs93Ml","v1HlnGv3Fq","QClRLjtn0X","Ul4a1Q6Lix","t59lRAIYUu","I7p2a7Ow5C","Z4I1vYw2oU","Oz8yZ16lHc",
-"zz4ZU6AFT0","BbwgAMmKGJ","cmXIXVprf2","nFqikJIqXi","QClRLMmKGJ","DQimpfcwDa","i3pydcL0aE","LewvMBCxeC","VNCPdzY1GY","zFgtBpv0i7",
-"TXQ0Zxciqp","9GXkX0YAGH","B3qemQ6Lix","FPfSEdhSuH","FVMxoh1zcH","MmsIotaOXK","zQt6QtvdkD","faHirC2Irc","blLA9lweGy","580YDBpYhV",
-"aL6AJLbRTH","fqypyQworu","5Drn0NhXdu","uJScX9eoRc","cL0aEJkzUn","zbIYYeuZA5","atef24dEz6","Zv7z0lweGy","cL0aEt98iW","lCMxyyToGW",
-"WDVWJW3VFH","Z4I1v0MR5X","L7cGc7fKYU","pFrrlv2eC3","BFkb8CqqaD","RxrsmVIlwP","Vprf2RzaZA","SmGzv5Drn0","45cIHUlU3M","VIlwPaez9y",
-"Ss0ZuzFgtB","24ARFMaJQs","iwzGkdpe1v","hi5X7VerEA","pmeCd1v5hH","4QMc9xciqp","fmIK1Gv3Fq","RmDcrF6PT2","BbwgA7lUXZ","24ARFazIWp",
-"cmXIXlH1kt","uPX7G5ZaEz","K4GS8qUJMd","FxX9qZzJHW","djsrvogLgc","KASQ8v8yFN","F6PT2AXpwE","MmKGJlXFOB","2ZHdklweGy","aL6AJx3LDe",
-"xXTI40MR5X","WPmlxK20wK","RmDcrn8pJ9","RmDcr5VZjS","DG4sTYw2oU","Ul4a1lH1kt","48cHLNhXdu","blLA9M6qcG","UlU3MvOqCE","xXTI4suY4x",
-"bZLvSFNYIM","WPmlxSWfou","9XyT9euZA5","uupzkqaofN","QbxXcWaWsv","FxX9q45cIH","ZzJHWGXdoH","TXQ0Zni2v1","K20wKpmeCd","7ku1p0h1b1",
-"IBe8kNcICA","vOqCE0Wr5y","1LB1LydG8U","SjskQTa8f6","07n1cQbxXc","aL6AJJkzUn","FjHXRpAhR1","i7WMQCfgr3","Y1mC0TXQ0Z","fqypy5iGN5",
-"zqH0WiB08l","QWxoTEOE1o","Dz1R3NOHsz","XflUqgIYvE","Ul4a1WPmlx","SmGzvjiVBP","dmoS7XyPZN","oVQp6e6e4z","zQt6QaFFss","DLhzMn8pJ9",
-"580YDCxVEf","JXljWpvgjS","S2DfujzUqR","rKDLJYjB9t","YOfrYxReec","4dEz62DREs","MmKGJ4QMc9","9rlg9fLNg8","3weIFFNYIM","Pb1paKr8ys",
-"Chuy3RkQke","vOqCEKASQ8","Nxx9VksJby","9XyT9IRh48","i7WMQK20wK","P6bcgFGzgp","d7vjMgIYvE","1LB1LMaJQs","RzaZArz7Ut","ciuWz7lUXZ",
-"NhXdutAOsr","OHaBzxciqp","NOHsznlaBy","FcWrWAXpwE","OHaBzS2Dfu","7hyVvQworu","FVMxoOxWIH","tuDySTa8f6","rKDLJAkKTk","0Wr5yVIlwP",
-"jSjS3gdQsS","kZANmd85a9","7Ow5C0Kyfs","K4GS8Y1mC0","07n1cHzZT8","ksJbyxReec","NAFuwThjNn","14FLRIRh48","hYBCKfmIK1","4QMc9zQt6Q",
-"t59lR9iGoT","29QAz3weIF","GrDg7FNYIM","9eoRcDcpWB","0MR5XlpF6W","TCgPpgdQsS","uQIczpAhR1","JIqXi2hEEU","vkCHHNAFuw","blLA9i7WMQ",
-"0h1b1ZUnqt","YOfrYdQ586","wDajXtaOXK","a00b5BbwgA","5Drn0M3zXL","Yf2EcYw2oU","gjUTu7X3uy","HzZT8EoToP","IBe8klpF6W","QYxC0Oz8yZ",
-"Cp3mZNAFuw","yToGWhUTw7","2NslmY1mC0","lj07Qxciqp","FPfSEuQIcz","LewvMn8pJ9","ZUnqtoVQp6","5nmWvni2v1","zz4ZUJkzUn","0Wr5yni2v1",
-"FLsph618Di","Pb1paaez9y","GXdoHciuWz","tl72WfaHir","sx5GlG1RhS","Nxx9V4W0Tl","JKWYRSjskQ","ksJbyazIWp","lViBvlkMUA","HlUbFRmDcr",
-"L7cGcReKEW","0PktIVNCPd","F6PT2Uvlv4","uJScXDcpWB","5iGN5M3zXL","uoStwuTacx","guMb8No0Qb","Cfgr3VIlwP","O3iyQjiVBP","n1pmOBbwgA",
-"RBhp055rfB","soy9tzqH0W","RmDcrRsQUq","QnJ1S9XyT9","Waim68U2nU","zz4ZUPOUYS","POUYSlCMxy","uupzkwDajX","7fsYM9rlg9","a00b5OHaBz",
-"tlILt0h1b1","5Mg9rGXdoH","7lUXZJXljW","16lHcIKxdL","QWxoTzQt6Q","UlU3Mv1Hln","y94nwkB5nP","ydG8UlweGy","6q6L9n8pJ9","xXTI4bZLvS",
-"HlUbFPb1pa","BFkb8hYBCK","n1pmOdQ586","MojnPiqv4k","OUqFMOUYuF","v2eC3k85Ae","i3pydCK5W7","Z4I1vulk41","WmadAyvOMI","2Yz7EokgRi",
-"0ao3l9eoRc","yToGWRsQUq","X6PinuoStw","yvOMIWMiS3","HfyNQvOqCE","45cIHD6rBy","MmKGJCdyBV","qaofNhE1Ql","ulk41FVMxo","nFqikQ6hMC",
-"7X3uyRzaZA","24ARFhUTw7","QworujiVBP","F6PT2lsQGo","yToGW7hyVv","gdQsSzqH0W","uupzkNAFuw","cQOnvlpF6W","5Drn0fcwDa","sqVrfgjUTu",
-"zQt6QfcwDa","pWiOsXyPZN","FjHXRuJScX","ZzJHWpFrrl","2DREsO3iyQ","FcWrWpT8wu","cL0aE55rfB","7X3uyWDVWJ","zHF1qTwano","n8pJ9yofH3",
-"PYBf4aFFss","GrDg7sx5Gl","Ul4a1GSQwj","FPfSEYf2Ec","Mkgy8WDVWJ","RpBQmazIWp","AXpwE4W0Tl","lsQGoyluBx","Y1mC0jtn0X","QClRLCfgr3",
-"faHir618Di","X6Pin8RCUA","VIlwPgtCA5","taOXKrKDLJ","RzaZA29QAz","5nmWv4QMc9","NcICAaFFss","tvdkD5Mg9r","3otm65nmWv","o8UyduZPqg",
-"RzaZA1j5L8","zbIYY14FLR","WDVWJUlU3M","soy9t5Mg9r","0PktIJRJQB","hi5X7JIqXi","zqH0WokgRi","hYBCKnlaBy","dmoS7NOHsz","24ARFFcWrW",
-"MaJQs3otm6","ix74rDG4sT","UmaEvdjsrv","jS1ajHfyNQ","DcpWBECMvU","BFkb8VBjhz","rz7UtOUYuF","fLNg8JKWYR","piJSkZhwG1","Z4I1vWmadA",
-"uAWyp8FmFH","J2mQiW3VFH","t59lRXyPZN","4dEz6D6rBy","AgJHQ7X3uy","zQt6Q48cHL","QWxoT5Drn0","nnP8oHP433","y94nwWDVWJ","FxX9qOHaBz",
-"uPX7GVerEA","jSjS3mX2GE","7X3uyY1mC0","JkzUnVjCZq","AXpwEBGaQY","45cIHokgRi","e6e4zzFgtB","mz8gxGXdoH","WDVWJZuDtD","JkzUn9y4lw",
-"OUYuFlweGy","cL0aEGv3Fq","RpBQmRxrsm","t59lRPYBf4","0KyfsfaHir","U3yw5Mkgy8","MaJQsWMiS3","MmsIoD6rBy","29QAz8RCUA","2Nslmsoy9t",
-"KASQ8uQIcz","2TRI7WaWsv","sqVrfIRh48","fmIK15Mg9r","uQIczrz7Ut","B3qempWiOs","VerEAjzUqR","2TRI73weIF","uoStwprNT6","In3NS8FmFH",
-"9XyT97ku1p","nnP8oYOfrY","WMiS3lH1kt","G1RhSBbwgA","HfyNQRzaZA","lCMxyRzaZA","qaofNStlDJ","2NslmKsjRK","I7p2aBCxeC","cShY2jfREu",
-"lH1ktCxVEf","cQOnvzFgtB","MezSWZuDtD","ZUnqtL7cGc","Z4I1vjeskS","vLsmSn1pmO","07n1cxReec","0Wr5y1v5hH","taOXKiqv4k","29QAzUlU3M",
-"G1RhSuJScX","JRJQBuvf7A","1j5L8StlDJ","uLtKsJKWYR","9y4lwzY1GY","JXljWGXdoH","OHaBzfcwDa","aez9yG1RhS","fFDrJYh1hF","prNT68cVD3",
-"B3qemVBjhz","yluBxjzUqR","0Wr5yQYxC0","NOHszRACuj","fcJOyaez9y","IRh48RsQUq","QWxoTMkgy8","uLtKsvOqCE","QChxs8hJdt","16lHcJKWYR",
-"xciqpd7vjM","5VZjSWmadA","Ss0ZuRsQUq","iB08lTa8f6","prNT6U3yw5","lCMxy3weIF","1j5L8AXpwE","jeskSHRxd8","0h1b10BmCy","WMiS3MezSW",
-"uQIcz8cVD3","euZA50Kyfs","XyPZNCp3mZ","BbwgANhXdu","dpe1vCp3mZ","GWqqXv8yFN","FNYIM5ZaEz","6q6L9aFFss","ECMvUHfyNQ","FLsphMK07Y",
-"NAFuwo8Uyd","faHirMkgy8","yEfy9Y1mC0","piJSks93Ml","ECMvU9GXkX","MezSWGrDg7","x3LDeFVMxo","h1zcHCdyBV","MGlTFMezSW","HRxd8v8yFN",
-"uPX7GbZLvS","Waim6xXTI4","3otm6iqv4k","2NslmzQt6Q","tuDyScShY2","ksJby8cVD3","3weIF8RCUA","7fKYU5Namm","uZPqgvkCHH","ulk41cL0aE",
-"QssNC0h1b1","rz7UtBGaQY","07n1clm0pD","gjUTuy94nw","rKDLJSs0Zu","6q6L9RkQke","618DiEOE1o","0BmCyhSSvQ","aFFss4W0Tl","Cfgr3FLsph",
-"MGlTFCdyBV","e6e4z2Yz7E","0PktIsuY4x","d7vjMZJTXH","W3VFHcQOnv","blLA9lj07Q","ThjNnRACuj","hYBCK7Ow5C","DG4sTfcJOy","lsQGos7Mxk",
-"9rlg9MmKGJ","WmadA1v5hH","uvf7ApT8wu","5ZaEzFwEJz","zHF1qDz1R3","UlU3MLDk6f","7ku1pY1mC0","pWiOspFrrl","AkKTkcmXIX","WPmlxksJby",
-"2hEEUi7WMQ","64s8NHRxd8","MmKGJfmIK1","JIqXiMmsIo","iB08ltuDyS","SbRYyKr8ys","OUYuFfcwDa","EdBKcNOHsz","ZuDtDogLgc","FcWrW2hEEU",
-"0PktIgf8rI","XflUq8RCUA","gIYvEtlILt","GXdoHe6e4z","OxWIH5Drn0","0PktISbRYy","BpYhVlj07Q","RpBQmb29RJ","yEfy9lXFOB","a00b5ZUnqt",
-"aDGtSh1zcH","FGzgpfcwDa","BGaQYIn3NS","piJSkrhl0J","tjQxs0YAGH","uvf7AuoStw","sx5GlDG4sT","aez9yazIWp","uQIczbZLvS","Z4I1vQChxs",
-"BFkb8atef2","uoStwChuy3","uJScXKsjRK","EOE1oChuy3","1j5L8RmDcr","oQ87rBCxeC","uLtKsF6PT2","n8pJ9Twano","WaWsvyEfy9","4dEz6JJs5m",
-"QbxXcRpBQm","8xEKzpv0i7","zY1GYuoStw","m4bxUZv7z0","TwanoKsjRK","48cHLGv3Fq","64s8N580YD","RACujxXTI4","WDVWJxXTI4","yluBxpAhR1",
-"9y4lwtl72W","nnP8o0Kyfs","14FLRMezSW","PYBf4qQxHP","Uvlv4yluBx","1v5hHJRJQB","5Nammb29RJ","pmeCdVLTy6","FPfSEQWxoT","Oz8yZpmeCd",
-"8U2nUuAWyp","8TxD7MK07Y","1j5L8rz7Ut","07n1czQt6Q","MmKGJl83Ud","AkKTkrz7Ut","s93MlLDk6f","MmKGJjSjS3","sqVrfZv7z0","uvf7AzY1GY",
-"IRh48gtCA5","1j5L8v2eC3","i3pydM3zXL","ulk41QnJ1S","jS1ajgtCA5","1v5hHFLsph","SbRYy14FLR","EoToPrKDLJ","euZA5lViBv","4dEz6pvgjS",
-"D6rBy5VZjS","hYBCK5IhmG","RmDcrydG8U","LewvMuupzk","2TRI72Yz7E","tjQxs5IhmG","Nxx9VW3VFH","3otm6b29RJ","pFrrllkMUA","BFkb8tAOsr",
-"wiHrZcQOnv","pWiOsZ4I1v","lXFOB2Yz7E","PYBf4IRh48","prNT6WDVWJ","XflUqSmGzv","JJs5mCK5W7","Cp3mZn1pmO","bgJAzC2Irc","TCgPp6q6L9",
-"cmXIXUlU3M","gf8rIMm8si","BbwgAkB5nP","QClRLoGu6x","uvf7ACdyBV","7fsYMMmKGJ","LDk6fdmoS7","VjCZqReKEW","EOE1oxReec","L7cGcM3zXL",
-"v2eC3X6Pin","X6PinxReec","HlUbFiwzGk","jeskSKASQ8","xciqptl72W","Nxx9VIBe8k","1v5hH8hJdt","qaofNrz7Ut","HfyNQLbRTH","5IhmGdhSuH",
-"9iGoTCNHmv","kB5nPAgJHQ","0YAGHIBe8k","rhl0JJKWYR","AgJHQWaWsv","pvgjSlCMxy","0Wr5yKsjRK","uN6r38hJdt","CK5W7D6rBy","QYxC0Ss0Zu",
-"jeskSdQ586","7Ow5C580YD","Q6Lixn8pJ9","2NslmBCxeC","J2mQiCK5W7","KZamHLbRTH","rz7UtokgRi","GrDg72TRI7","nnP8oCxVEf","t59lRvLsmS",
-"suY4xCdyBV","RBhp0U3yw5","lsQGoJIqXi","KASQ8jS1aj","gf8rIxReec","iqv4ks7Mxk","zz4ZUZ4I1v","55rfBhe9IA","L7cGc0PktI","F6PT2uTacx",
-"9rlg9n8pJ9","hYBCKix74r","TCgPpaFFss","BFkb87Ow5C","1v5hH7ku1p","jSjS3tvdkD","6AFT0v1Hln","KsjRKksJby","GXdoHQClRL","v2eC35ZaEz",
-"pvgjSO3iyQ","AkKTkZzJHW","v8yFN1LB1L","ThjNnAOgEe","v8yFNL7cGc","XflUqcQOnv","Yw2oU9eoRc","MK07YpvgjS","lH1kt618Di","ru4UGyEfy9",
-"POUYS8FmFH","NOHszlkMUA","cQOnv5iGN5","tAOsrOHaBz","StlDJ5Namm","AIYUu7X3uy","618DijiVBP","0Wr5yNAFuw","yEfy9prNT6","In3NSL7cGc",
-"CNHmvzFgtB","tjQxsCdyBV","djsrvdhSuH","BbwgAgjUTu","tAOsrJRJQB","HzZT8WaWsv","mz8gxmX2GE","kB5nPNhXdu","WMiS3yvOMI","5IhmGK20wK",
-"uZPqgulk41","atef2TXQ0Z","Rxrsm8hJdt","zmLYDVerEA","dmoS7d7vjM","5VZjSO3iyQ","WMiS3FxX9q","faHirTwano","Waim6fqypy","d85a964s8N",
-"aez9yCK5W7","QClRLTa8f6","fcJOyGXdoH","fFDrJFVMxo","8xEKziqv4k","Zv7z0kZANm","xReec5ZaEz","TCgPprKDLJ","o8Uyd0ao3l","djsrvUvlv4",
-"2hEEUzHF1q","OUqFM4W0Tl","B3qemAmdQd","WaWsvIRh48","uLtKs9rlg9","B3qemv2eC3","xReecciuWz","5drc6pv0i7","NcICAFNYIM","ZuDtDQ6hMC",
-"FFDuixReec","1v5hHRBhp0","Kr8ysQChxs","S77LHblLA9","uQIcz0YAGH","dpe1v7fKYU","JRJQBk85Ae","AmdQdYw2oU","7fKYUi7WMQ","RzaZASWfou",
-"fqypynFqik","QssNCC2Irc","gf8rIi3pyd","lj07Qm4bxU","O3iyQkB5nP","qUJMdfcJOy","v8yFNrhl0J","kZANm8FmFH","POUYSpv0i7","BGaQYCxVEf",
-"jeskS6AFT0","FFDuiZzJHW","0h1b1AkKTk","ZUnqteuZA5","2Yz7EtaOXK","M6qcGFGzgp","yluBxqQxHP","aDGtSF6PT2","UmaEvJRJQB","vLsmSydG8U",
-"POUYSOUYuF","618DiVIlwP","Zv7z0M3zXL","t98iWFNYIM","No0QbWaim6","ReKEWRxrsm","Uvlv42hEEU","Pb1pa8hJdt","FLsphnlaBy","zqH0WnnP8o",
-"5Namm07n1c","zbIYYuZPqg","v2eC3CqqaD","cShY2lweGy","J2mQi8hJdt","4W0Tl7ku1p","ciuWzNcICA","AOgEeMK07Y","BFkb8uZPqg","euZA5guMb8",
-"5VZjSaez9y","RmDcrzbIYY","sx5Gl3weIF","bgJAz1v5hH","gIYvEjSjS3","SWfouAkKTk","mz8gxoQ87r","tuDySjSjS3","HlUbFZUnqt","bZLvSRzaZA",
-"s7MxkOUYuF","tjQxs2Yz7E","MmKGJY1mC0","AgJHQXflUq","suY4xRxrsm","tjQxsTXQ0Z","07n1cEOE1o","hE1Ql14FLR","faHirjS1aj","tAOsrd85a9",
-"uZPqg9eoRc","i7WMQuZPqg","4QMc9NhXdu","ZzJHWFnPFB","MK07YksJby","8cVD3euZA5","K20wKZhwG1","dQ586WmadA","8U2nUzbIYY","3otm68U2nU",
-"618Di7fKYU","pFrrlk85Ae","pAhR12Nslm","hYBCKbrhlQ","YjB9t48cHL","FnPFBX6Pin","EOE1oydG8U","I7p2aYh1hF","SbRYyd85a9","azIWpYw2oU",
-"EoToPQworu","Pb1pax3LDe","WPmlxWPmlx","VLTy6FNYIM","fqypy9iGoT","F6PT2jfREu","ni2v155rfB","wiHrZVLTy6","lm0pDdhSuH","a00b5b29RJ",
-"Q6LixRpBQm","qUJMdFxX9q","cL0aEzmLYD","F6PT2uPX7G","EdBKcF6PT2","F6PT2IjTwP","EOE1oksJby","8U2nUydG8U","a00b564s8N","cmXIXReKEW",
-"G1RhSJXljW","lm0pDpWiOs","rz7Utd85a9","jSjS32Yz7E","rhl0Jrz7Ut","cQOnvn1pmO","4dEz6yToGW","hSSvQyvOMI","MmsIo16lHc","618DiprNT6",
-"S77LH3otm6","RzaZA618Di","MezSWC2Irc","MmsIotuDyS","prNT6pmeCd","TCgPpuoStw","RxrsmWPmlx","Vprf26AFT0","CqqaDSjskQ","FjHXRSs0Zu",
-"DcpWBWDVWJ","2DREso8Uyd","LbRTHoVQp6","FnPFB7fsYM","Kr8ys14FLR","guMb8HlUbF","zHF1qdmoS7","DLhzMjSjS3","cQOnvpiJSk","tvdkDIRh48",
-"prNT6d85a9","pT8wuAOgEe","29QAzlweGy","sqVrfQnJ1S","FxX9qsuY4x","QssNClCMxy","O3iyQvkCHH","pT8wurz7Ut","TwanoKASQ8","9XyT9JKWYR",
-"L7cGcK20wK","hUTw7qaofN","hYBCKBGaQY","d7vjM0Kyfs","qQxHP07n1c","CdyBVgjUTu","8TxD7GSQwj","he9IA8xEKz","hSSvQ0Kyfs","GrDg7ulk41",
-"uupzkrz7Ut","jeskSSmGzv","WMiS35Mg9r","8TxD7pmeCd","fcwDasuY4x","2hEEUfaHir","lsQGoMojnP","zQt6QFGzgp","QWxoTB3qem","GXdoHl83Ud",
-"UlU3MuZPqg","FjHXR7fsYM","piJSkwDajX","yEfy9TXQ0Z","uN6r3vOqCE","guMb89eoRc","Yw2oUVNCPd","ECMvUs4786","1v5hHk85Ae","8TxD7GXdoH",
-"ZuDtDBpYhV","UmaEvzHF1q","HP433atef2","0PktI2DREs","Yh1hF7fsYM","07n1cvkCHH","vkCHHfcwDa","rz7UtuPX7G","UmaEvjzUqR","Ss0ZuiB08l",
-"KsjRKNo0Qb","B3qemFVMxo","qaofNPOUYS","oQ87rWreyP","OHaBzgtCA5","VjCZq16lHc","yofH3CqqaD","nlaByWaWsv","U3yw5No0Qb","In3NSDz1R3",
-"MmKGJb29RJ","ZzJHWprNT6","hYBCKyluBx","JIqXiHzZT8","L7cGcJkzUn","Pb1paVLTy6","VBjhzDLhzM","jSjS31v5hH","Qworu7ku1p","fcJOyStlDJ",
-"NOHszJKWYR","CxVEf5ZaEz","1j5L8s7Mxk","WmadAfmIK1","7ku1psuY4x","uupzkOHaBz","FFDuiMaJQs","8hJdtMaJQs","s7MxkFGzgp","I7p2aguMb8",
-"jtn0XuTacx","GXdoHvOqCE","7lUXZZ4I1v","6q6L9zbIYY","qaofNRxrsm","JJs5muJScX","8xEKzSbRYy","XyPZNuN6r3","POUYSjeskS","SbRYyDQimp",
-"MmsIoYw2oU","8TxD7uoStw","Oz8yZv2eC3","jiVBPs7Mxk","fqypy1LB1L","5ZaEz8cVD3","jSjS3Twano","MGlTFCIShG","fLNg89rlg9","h1zcHVerEA",
-"9XyT92Nslm","lm0pD2DREs","e6e4zrKDLJ","zQt6QB3qem","BpYhVLbRTH","zQt6QzmLYD","HzZT8LewvM","jeskSblLA9","0MR5X7fKYU","9eoRcwDajX",
-"uN6r3580YD","hYBCKCNHmv","JJs5mUvlv4","brhlQd85a9","uJScX0MR5X","tjQxsaDGtS","k85AelsQGo","OUqFMrhl0J","F6PT2NAFuw","29QAzNcICA",
-"MezSWs4786","7Ow5CCK5W7","5iGN5m4bxU","faHir580YD","GrDg7qQxHP","h1zcHZuDtD","LbRTHRpBQm","fcJOyMkgy8","9GXkXatef2","m4bxUM6qcG",
-"FwEJztuDyS","t59lRgdQsS","AmdQdFcWrW","NhXdulm0pD","ydG8UWaim6","VLTy6bgJAz","t98iWhUTw7","euZA5Chuy3","7lUXZ8cVD3","QYxC0pT8wu",
-"L7cGcXyPZN","qaofNuLtKs","QbxXcAOgEe","3otm65Mg9r","9XyT9JkzUn","GrDg7MmsIo","cL0aEJIqXi","euZA5S2Dfu","atef2lweGy","VjCZqtvdkD",
-"blLA9Z4I1v","2ZHdkni2v1","zQt6QNxx9V","iKqhr8TxD7","ix74rd7vjM","VerEA5drc6","xXTI4QssNC","hYBCKOxWIH","y94nw9iGoT","iB08li3pyd",
-"DG4sTbZLvS","8xEKz7fsYM","gIYvE16lHc","RpBQmWPmlx","t59lRlpF6W","2hEEU64s8N","DcpWB0MR5X","9iGoTF6PT2","9y4lwdmoS7","2ZHdkZuDtD",
-"K20wKVprf2","580YDtuDyS","IKxdLbZLvS","7ku1pt59lR","OxWIHTwano","JKWYRChuy3","VerEAWaim6","FNYIMFLsph","Ta8f6HzZT8","5iGN5sx5Gl",
-"3otm6cmXIX","LDk6f9iGoT","RkQkeF6PT2","n1pmOHfyNQ","QnJ1SCqqaD","DLhzM9XyT9","MGlTFS77LH","DQimpRBhp0","hYBCKNAFuw","KsjRKcQOnv",
-"blLA9piJSk","pT8wuAmdQd","RBhp0KsjRK","hE1Qlx3LDe","4QMc948cHL","9y4lwb29RJ","fqypyaFFss","2Yz7EAXpwE","bgJAzBbwgA","0PktIaFFss",
-"wDajXWMiS3","7hyVvpv0i7","OUYuF618Di","dQ586lpF6W","5drc6ciuWz","lsQGo48cHL","ru4UGRkQke","Uvlv4cShY2","U3yw5aFFss","3otm6OxWIH",
-"5nmWvuoStw","MmsIoJIqXi","jtn0XydG8U","KZamHdmoS7","cmXIXgIYvE","atef2uvf7A","7ku1pIKxdL","XflUqzqH0W","taOXK4QMc9","14FLRfFDrJ",
-"jiVBPfmIK1","fmIK1fFDrJ","FFDui14FLR","TwanojSjS3","okgRiNOHsz","jSjS3Q6hMC","kZANmPb1pa","M6qcGQbxXc","MK07YbZLvS","7ku1pHRxd8",
-"VjCZqYOfrY","Y1mC0RBhp0","ciuWzRzaZA","S2DfuHP433","MezSW6q6L9","tAOsrpAhR1","D6rByF6PT2","JIqXiprNT6","VBjhzzqH0W","tjQxslsQGo",
-"Gv3FqjiVBP","BGaQYtjQxs","7fsYM3weIF","oQ87ruN6r3","jfREu8RCUA","Mkgy85iGN5","2ZHdkyofH3","lXFOBjzUqR","aDGtS7X3uy","5VZjSYw2oU",
-"qaofN9eoRc","s93MlL7cGc","t59lR45cIH","Z4I1vOUqFM","5nmWvMezSW","K20wKv2eC3","QWxoT3otm6","9XyT9lXFOB","S2DfudQ586","Cp3mZMkgy8",
-"jeskSCNHmv","7Ow5CSjskQ","yEfy9atef2","5ZaEzpv0i7","LewvM2DREs","SmGzvAgJHQ","AkKTkn1pmO","24ARFTCgPp","JJs5mWaim6","nFqik2ZHdk",
-"RpBQmUl4a1","5drc6vLsmS","Q6LixRACuj","Waim6IjTwP","pT8wujS1aj","24ARFGWqqX","GWqqXRBhp0","ciuWzguMb8","Rxrsm7fKYU","nlaBy7fKYU",
-"SbRYyUmaEv","ZJTXH0ao3l","i7WMQWreyP","oVQp6nnP8o","suY4xydG8U","hYBCKcL0aE","WMiS3KASQ8","lpF6WvLsmS","Nxx9V2TRI7","hYBCKrKDLJ",
-"hYBCKFhtgl","gjUTuKr8ys","uN6r3DQimp","v1HlnlH1kt","FVMxoOUYuF","QYxC0k85Ae","In3NSRBhp0","aL6AJRsQUq","pWiOs9eoRc","Zv7z0HzZT8",
-"8TxD7EOE1o","QChxsFGzgp","hi5X7qaofN","vkCHHokgRi","MaJQs7hyVv","yvOMIAXpwE","Nxx9VvOqCE","QbxXcZhwG1","JRJQBFjHXR","bZLvScL0aE",
-"ciuWzCdyBV","2DREsqaofN","5Drn0DG4sT","jzUqRzFgtB","CK5W7pFrrl","jS1aj9XyT9","14FLRPYBf4","zbIYYIn3NS","TwanoIBe8k","tlILtl83Ud",
-"RACujMmsIo","Ss0ZuAOgEe","Chuy35VZjS","TwanoMK07Y","he9IAkZANm","ZhwG12Nslm","6q6L9guMb8","Yf2EcO3iyQ","OxWIHlH1kt","uTacx8RCUA",
-"48cHLSjskQ","sqVrfLewvM","PYBf4n8pJ9","14FLRpiJSk","XyPZNyofH3","yvOMIHRxd8","KZamHMezSW","SbRYy9GXkX","kB5nP4dEz6","SjskQCxVEf",
-"9eoRcGrDg7","cShY2Cp3mZ","7ku1pNo0Qb","FnPFBnlaBy","7fsYMFFDui","FLsphoGu6x","tvdkDa00b5","IBe8kni2v1","lXFOBSbRYy","HlUbFqQxHP",
-"UmaEvcQOnv","pT8wuVprf2","2DREsBpYhV","HzZT8RmDcr","VLTy6okgRi","FhtglJRJQB","LewvM8cVD3","7ku1ph1zcH","tAOsr2hEEU","euZA5UmaEv",
-"soy9tiqv4k","zqH0WHRxd8","rhl0JQYxC0","aez9yCxVEf","5nmWvmz8gx","Q6LixECMvU","NOHsz0BmCy","XyPZNlsQGo","pWiOsTwano","Ul4a1ix74r",
-"RxrsmfLNg8","yEfy9rz7Ut","oGu6xiqv4k","8xEKzX6Pin","QYxC0VIlwP","atef2S2Dfu","pAhR1QssNC","sqVrfGSQwj","JKWYRv2eC3","9GXkXvkCHH",
-"Ul4a1OUqFM","OxWIHO3iyQ","O3iyQFnPFB","0MR5Xv1Hln","OxWIHVjCZq","he9IA07n1c","n1pmOksJby","D6rByChuy3","wiHrZfaHir","dQ586WreyP",
-"Gv3FqNcICA","CqqaDkZANm","pmeCdsx5Gl","iwzGkReKEW","Mm8siRmDcr","jzUqRi7WMQ","WaWsvSWfou","StlDJX6Pin","euZA5RBhp0","IBe8kFGzgp",
-"7ku1pLDk6f","5Mg9rChuy3","FNYIMVIlwP","NcICAVBjhz","VBjhzYf2Ec","KASQ8djsrv","zqH0WEdBKc","Pb1paBCxeC","uZPqgbZLvS","jtn0XfLNg8",
-"zQt6QC2Irc","0Kyfs16lHc","AkKTkStlDJ","ZuDtDgtCA5","JJs5myToGW","5Drn0EOE1o","lH1ktGXdoH","dpe1v2Nslm","yofH3cmXIX","CNHmvqaofN",
-"16lHcZUnqt","wDajXdhSuH","cQOnvThjNn","lkMUABpYhV","L7cGc07n1c","v2eC3fmIK1","lH1kt24ARF","S77LHfLNg8","2Yz7EuJScX","nlaByFcWrW",
-"FLsphuN6r3","ix74rCp3mZ","2hEEU7fKYU","lH1ktVLTy6","v8yFNRzaZA","yEfy9CNHmv","yEfy9UmaEv","QYxC0zHF1q","QClRLJKWYR","OHaBzO3iyQ",
-"SWfouJXljW","DG4sTO3iyQ","i3pydiwzGk","VjCZqcmXIX","aDGtSoGu6x","Q6LixStlDJ","s93MlYOfrY","DG4sTdjsrv","VjCZq0PktI","SmGzvI7p2a",
-"jtn0XJ2mQi","okgRiAOgEe","GSQwj8U2nU","nlaByciuWz","M6qcGYOfrY","tAOsr1v5hH","dmoS78cVD3","ZUnqtTa8f6","Cfgr3vkCHH","nnP8orKDLJ",
-"618DijfREu","nnP8oStlDJ","nlaByyluBx","yofH3SWfou","5drc62Yz7E","uQIczYh1hF","GSQwjZ4I1v","D6rByFGzgp","dQ586lXFOB","WaWsvMGlTF",
-"RkQke24ARF","0MR5XzmLYD","D6rBynFqik","yofH3pT8wu","ydG8UZhwG1","5Mg9rrz7Ut","gtCA55iGN5","Pb1paru4UG","QChxsbrhlQ","TXQ0ZUmaEv",
-"lH1ktRBhp0","CIShGuPX7G","mz8gxokgRi","0PktICK5W7","djsrvF6PT2","FLsphxciqp","RBhp0zFgtB","zmLYDChuy3","VIlwPlj07Q","Gv3FqHP433",
-"hUTw7Yf2Ec","jtn0Xru4UG","yofH3YjB9t","U3yw5a00b5","dpe1vHRxd8","hUTw7Dz1R3","FhtglkZANm","Ta8f6vLsmS","he9IAtuDyS","2hEEUa00b5",
-"ReKEWSWfou","U3yw5KASQ8","16lHclXFOB","ThjNnuAWyp","M6qcG0ao3l","RpBQmECMvU","AgJHQIKxdL","SjskQTwano","B3qemLDk6f","Pb1pa5IhmG",
-"24ARFwDajX","xXTI4Ss0Zu","EOE1oHzZT8","QssNCBbwgA","fcwDaW7cTs","GSQwjt59lR","fcJOyFwEJz","5iGN58FmFH","16lHczFgtB","B3qem8xEKz",
-"LewvMpAhR1","tvdkDv8yFN","7X3uyuN6r3","Chuy3jSjS3","tAOsr0PktI","9GXkXNhXdu","gdQsSYOfrY","5Drn0d7vjM","vLsmS1LB1L","ni2v1dmoS7",
-"rKDLJMmKGJ","5ZaEzJ2mQi","2ZHdkvLsmS","X6PinQssNC","d85a94W0Tl","blLA9CIShG","FVMxo0MR5X","SjskQlm0pD","5IhmGix74r","FFDuiCqqaD",
-"fmIK1qQxHP","S2Dfujtn0X","Kr8ysFGzgp","Gv3FqJRJQB","55rfBKASQ8","FLsphlm0pD","3otm6jtn0X","9GXkXJJs5m","6q6L9he9IA","0Wr5ypvgjS",
-"FLsph0Kyfs","QbxXctjQxs","y94nwyofH3","piJSkk85Ae","lsQGoUvlv4","55rfBd85a9","HzZT8Mm8si","zmLYD0ao3l","zHF1quAWyp","Q6hMCEdBKc",
-"jiVBPaez9y","7Ow5CYf2Ec","F6PT2sx5Gl","tAOsrCfgr3","Pb1paksJby","2hEEU0YAGH","uAWypAgJHQ","tvdkDAgJHQ","tl72W8hJdt","lkMUACfgr3",
-"d7vjMo8Uyd","hYBCKHP433","oVQp6Q6hMC","suY4xQworu","BGaQYjzUqR","QClRLgIYvE","BCxeCDG4sT","FFDuiAXpwE","l83UddhSuH","5Mg9rwiHrZ",
-"tvdkDBGaQY","Y1mC08FmFH","0YAGHYjB9t","3weIFblLA9","VBjhzRBhp0","Ul4a1n8pJ9","WaWsvZhwG1","a00b5618Di","iKqhrSWfou","o8Uydfqypy",
-"CK5W764s8N","rKDLJJKWYR","XflUqn8pJ9","5iGN50BmCy","tAOsrHP433","0ao3lQClRL","fFDrJsuY4x","QssNC8hJdt","QbxXc5IhmG","HzZT8D6rBy",
-"NAFuwulk41","GXdoHIBe8k","2hEEUpvgjS","8FmFHfqypy","o8UydlH1kt","5Mg9rfcwDa","lweGysx5Gl","CK5W7GWqqX","lweGyMmKGJ","ydG8US2Dfu",
-"7ku1pSmGzv","FPfSEgf8rI","618DizY1GY","618DiEoToP","tlILtQnJ1S","9eoRc1j5L8","qQxHPaL6AJ","Cfgr3W3VFH","oQ87rS2Dfu","Cfgr30MR5X",
-"rhl0JMGlTF","Cp3mZsqVrf","RmDcrOz8yZ","pmeCdPYBf4","pvgjSTa8f6","5iGN516lHc","MmKGJRBhp0","S2DfuQbxXc","YOfrYhYBCK","24ARF0YAGH",
-"b29RJQClRL","Ta8f6pFrrl","pT8wu3weIF","uoStwJJs5m","L7cGcSmGzv","uvf7AZzJHW","hYBCKC2Irc","jeskSuJScX","ECMvUulk41","n8pJ9ogLgc",
-"No0QbDLhzM","rKDLJPYBf4","gf8rIv2eC3","i3pyds4786","ECMvUGWqqX","FnPFBjzUqR","kB5nPzbIYY","oQ87rd85a9","14FLRFxX9q","1LB1LkB5nP",
-"GrDg7BCxeC","0ao3lGWqqX","fFDrJv2eC3","gdQsSPYBf4","uN6r3ciuWz","bZLvSn8pJ9","CK5W7Waim6","KZamHuPX7G","lViBvfLNg8","FLsphQ6hMC",
-"PYBf4ECMvU","nnP8on1pmO","AkKTkhYBCK","x3LDe24ARF","Yh1hFD6rBy","okgRiGv3Fq","0Wr5yHfyNQ","gjUTu3weIF","GXdoHQ6Lix","tvdkDgf8rI",
-"HlUbFsqVrf","9rlg9C2Irc","C2IrceuZA5","aez9ynlaBy","M6qcGoGu6x","IRh48ciuWz","SmGzvs7Mxk","faHirRsQUq","16lHcFPfSE","rhl0JuPX7G",
-"618Didjsrv","EOE1oZJTXH","OxWIHtlILt","tlILtlsQGo","zz4ZU5IhmG","jiVBP7hyVv","tuDySSbRYy","3weIFG1RhS","BCxeCQworu","RxrsmuAWyp",
-"BFkb8oVQp6","pv0i7pWiOs","0BmCyo8Uyd","W3VFHUvlv4","FVMxoMojnP","iKqhrxciqp","4QMc9gtCA5","Cp3mZZuDtD","MaJQsO3iyQ","Cfgr3zmLYD",
-"uTacxIBe8k","DcpWBZzJHW","ciuWzfcwDa","fcwDauTacx","k85AeDQimp","zqH0WbrhlQ","pAhR10MR5X","8cVD3ZuDtD","5NammaL6AJ","uupzkWaWsv",
-"2TRI7dpe1v","euZA5azIWp","fLNg8dpe1v","oGu6xtaOXK","CxVEfRpBQm","14FLRSjskQ","dpe1v64s8N","2NslmlH1kt","dpe1v0BmCy","bgJAzJJs5m",
-"i7WMQ7ku1p","GSQwjMezSW","C2IrcgjUTu","tjQxswiHrZ","SjskQsuY4x","K4GS8zmLYD","MaJQsCK5W7","QssNCgdQsS","lH1ktFNYIM","gIYvEYf2Ec",
-"ReKEW7hyVv","TXQ0Zdjsrv","sqVrfqaofN","IRh48qUJMd","Yh1hFW3VFH","xciqp2Yz7E","lj07QoQ87r","atef2x3LDe","0MR5XQworu","AgJHQe6e4z",
-"CqqaDtAOsr","uvf7Ahi5X7","FjHXRcQOnv","Mkgy8F6PT2","5nmWvGXdoH","fqypypv0i7","lsQGoI7p2a","jzUqR2TRI7","W3VFHStlDJ","iB08lCfgr3",
-"d7vjMprNT6","POUYSiwzGk","RkQkeD6rBy","QnJ1S5iGN5","qUJMdkB5nP","uTacxdQ586","BCxeCOz8yZ","RpBQm7fKYU","jzUqR8RCUA","CdyBV0ao3l",
-"ogLgcdmoS7","7X3uyQ6hMC","y94nwNo0Qb","5Drn0l83Ud","kZANmZhwG1","cmXIXRpBQm","S2DfuQnJ1S","RpBQm1j5L8","sqVrfBpYhV","DQimpMojnP",
-"hYBCKjfREu","uZPqghYBCK","HfyNQWmadA","suY4xBCxeC","Chuy3rhl0J","7X3uyCdyBV","gIYvEVIlwP","QWxoTvOqCE","cQOnvFjHXR","UlU3ML7cGc",
-"P6bcgUl4a1","9XyT9zFgtB","3otm6uoStw","ECMvUZJTXH","XflUq618Di","RkQke5ZaEz","JIqXi6AFT0","7ku1pU3yw5","yofH3J2mQi","9y4lwQWxoT",
-"1v5hH8xEKz","FcWrWuupzk","QnJ1S580YD","uAWypaFFss","Yw2oU2TRI7","lsQGojSjS3","S77LHru4UG","fcwDaRzaZA","hYBCKjiVBP","hUTw73weIF",
-"FPfSEX6Pin","9GXkXW3VFH","lsQGo2ZHdk","pWiOspmeCd","oVQp6WPmlx","7hyVvzQt6Q","ZJTXHk85Ae","K4GS8DLhzM","FxX9qTXQ0Z","pT8wuZUnqt",
-"WPmlxQYxC0","s7MxkuQIcz","Yw2oUhi5X7","GWqqXReKEW","tlILtZzJHW","fLNg8suY4x","QnJ1Ssx5Gl","UmaEvyEfy9","DQimp4dEz6","iKqhrI7p2a",
-"Ul4a1jfREu","oVQp6nlaBy","xReec7fsYM","yvOMIaez9y","AkKTk4dEz6","fLNg8KZamH","0Wr5yB3qem","In3NScL0aE","3weIFJIqXi","sqVrf7fKYU",
-"5NammpvgjS","ciuWzFcWrW","lCMxys4786","gdQsSRzaZA","FwEJzEdBKc","tlILt5ZaEz","zz4ZUxXTI4","hi5X724ARF","0ao3l5Drn0","hi5X7TXQ0Z",
-"VerEAAkKTk","xReec2hEEU","Chuy348cHL","aDGtS5drc6","jfREu5Drn0","7ku1ps93Ml","L7cGcsx5Gl","MezSW580YD","gdQsSatef2","uupzkdmoS7",
-"FGzgpzHF1q","zQt6QSmGzv","hE1QlBCxeC","CxVEflsQGo","JKWYRUvlv4","uJScX4QMc9","2Yz7E5Mg9r","BCxeCWDVWJ","JkzUnVIlwP","JIqXiDLhzM",
-"Ss0ZuCxVEf","wiHrZjtn0X","55rfBix74r","Y1mC0CqqaD","CdyBVzFgtB","s93Mlhi5X7","7hyVvuQIcz","uoStwKZamH","Kr8ys0Wr5y","cQOnvUl4a1",
-"n8pJ9pWiOs","5drc67Ow5C","5nmWv6q6L9","v8yFNbZLvS","2hEEUfqypy","sqVrfpvgjS","l83UdCIShG","LbRTHMaJQs","aFFssxReec","YOfrYi7WMQ",
-"kZANm0BmCy","tvdkD07n1c","rhl0JtlILt","KASQ8L7cGc","vLsmSfcJOy","2DREsCNHmv","DLhzMMojnP","580YDDz1R3","faHirt59lR","tvdkDYjB9t",
-"HP433gIYvE","s7MxkgdQsS","8RCUAd85a9","B3qemuQIcz","VjCZqyluBx","C2IrccShY2","ZJTXH0MR5X","aL6AJ5ZaEz","faHirXyPZN","CxVEfRsQUq",
-"0MR5X9GXkX","WaWsvNo0Qb","qaofNFLsph","oQ87rjtn0X","ZUnqtCdyBV","Dz1R3CK5W7","1LB1LQ6Lix","yToGW48cHL","GWqqXJXljW","PYBf4NAFuw",
-"TXQ0ZWmadA","VIlwPtjQxs","zHF1qzHF1q","5IhmG5ZaEz","lsQGopiJSk","gtCA5hYBCK","7ku1p07n1c","ni2v1VNCPd","BpYhV45cIH","PYBf4BGaQY",
-"fFDrJIBe8k","azIWpMK07Y","lj07QydG8U","jiVBPPYBf4","Kr8ysSjskQ","VNCPdVBjhz","k85Aepv0i7","2TRI7X6Pin","4dEz6hYBCK","a00b5jtn0X",
-"WPmlxMkgy8","VLTy6jS1aj","AkKTk2ZHdk","Mm8siRzaZA","W7cTsCxVEf","OUYuFtjQxs","soy9tsqVrf","D6rBypT8wu","24ARFzz4ZU","TXQ0Z5IhmG",
-"I7p2afFDrJ","bgJAzhUTw7","Y1mC00BmCy","Kr8ys0YAGH","7hyVvGXdoH","nFqikzFgtB","I7p2aYOfrY","MezSW7fsYM","NAFuwd85a9","WmadAjS1aj",
-"d7vjMIRh48","rhl0JyofH3","VLTy6tjQxs","0BmCy8TxD7","5VZjSF6PT2","Yh1hFJIqXi","WmadAWDVWJ","uZPqgSs0Zu","O3iyQQworu","RpBQmyluBx",
-"pT8wuvOqCE","CdyBVfaHir","EoToPG1RhS","o8UydNOHsz","0BmCyjzUqR","EOE1o45cIH","8FmFHtAOsr","HlUbFbZLvS","No0QbpT8wu","pvgjSt98iW",
-"ZhwG1cQOnv","8U2nUl83Ud","piJSkFxX9q","7Ow5COUqFM","M3zXLQworu","NAFuwUmaEv","5IhmGrhl0J","GSQwjJXljW","DQimpzY1GY","9y4lw7X3uy",
-"jeskSo8Uyd","IRh48QnJ1S","Yh1hF0BmCy","ECMvUOUqFM","0YAGH0PktI","48cHLHzZT8","piJSkYf2Ec","fcwDa5drc6","jfREuCfgr3","pv0i7S77LH",
-"6AFT02hEEU","7hyVv5drc6","SWfou2Nslm","BbwgAvkCHH","HP433euZA5","Y1mC0Oz8yZ","OUqFMYw2oU","cmXIXjtn0X","FjHXRt59lR","jtn0XguMb8",
-"kB5nPYjB9t","okgRiy94nw","SmGzvi7WMQ","FLsphlj07Q","W3VFHe6e4z","EOE1osuY4x","VBjhzcShY2","0KyfsDz1R3","gjUTuQYxC0","8RCUAcmXIX",
-"2Yz7Ee6e4z","HRxd8ksJby","5iGN57hyVv","DG4sTZhwG1","FLsphCNHmv","hSSvQL7cGc","BGaQYMezSW","KZamHRxrsm","hUTw7kB5nP","2Nslmatef2",
-"IRh48nnP8o","gjUTu5ZaEz","uAWyplXFOB","M3zXLEdBKc","NcICAaL6AJ","TXQ0ZM3zXL","GXdoH29QAz","8TxD7Dz1R3","cShY2oQ87r","CIShG0BmCy",
-"AmdQdzFgtB","KZamHgf8rI","NhXduVLTy6","RBhp0VjCZq","m4bxU5iGN5","t59lRaL6AJ","Q6hMCWaWsv","i7WMQX6Pin","iKqhrxReec","AgJHQzY1GY",
-"yEfy9yluBx","45cIHyToGW","yvOMIguMb8","1j5L8618Di","NhXduU3yw5","lj07Q580YD","XyPZNt59lR","QClRLvOqCE","cmXIXWaWsv","Vprf2OxWIH",
-"dmoS7CK5W7","1LB1L45cIH","GrDg7BbwgA","29QAzlCMxy","zFgtBgIYvE","No0QbuAWyp","VerEAPYBf4","ni2v1PYBf4","qaofN3otm6","SbRYyzmLYD",
-"jfREuW7cTs","iKqhrQWxoT","rhl0JMezSW","AOgEeJRJQB","1LB1LyofH3","Z4I1vNhXdu","2TRI7ciuWz","1v5hH7lUXZ","fmIK1ZuDtD","a00b5MojnP",
-"8RCUAEoToP","WPmlxI7p2a","fmIK1W7cTs","5Drn0zmLYD","FPfSEFxX9q","lsQGoQChxs","MK07YkZANm","JKWYR0MR5X","QnJ1Sni2v1","CdyBVG1RhS",
-"aFFssv1Hln","ZUnqtuN6r3","ogLgcGv3Fq","euZA5Mkgy8","OUYuFMGlTF","hUTw7CxVEf","QYxC06q6L9","djsrvPb1pa","0MR5XWaWsv","t98iWlViBv",
-"5iGN545cIH","YjB9tUlU3M","XflUq5Namm","gtCA5Dz1R3","P6bcgZzJHW","GXdoHWPmlx","TCgPpqaofN","Yf2EcYjB9t","BpYhVfaHir","RBhp0JXljW",
-"ru4UGNo0Qb","UlU3M0Wr5y","uN6r3x3LDe","b29RJsqVrf","jtn0XlViBv","zqH0WRACuj","IjTwPCNHmv","CIShGsuY4x","SmGzv2ZHdk","IBe8kD6rBy",
-"JkzUn4QMc9","7fsYMi7WMQ","CdyBVChuy3","ECMvUPYBf4","VjCZq5Mg9r","qaofNuAWyp","8FmFHDQimp","lkMUAa00b5","1v5hHzmLYD","YjB9tAgJHQ",
-"NcICAJIqXi","FhtglHfyNQ","RxrsmMmKGJ","cmXIXFPfSE","SmGzvIBe8k","hE1Qla00b5","gdQsSXflUq","GrDg7t98iW","vkCHH6AFT0","5NammbZLvS",
-"gdQsSAgJHQ","ksJbyOHaBz","lH1ktmz8gx","1LB1LuN6r3","ix74rx3LDe","tlILtZ4I1v","OHaBzBbwgA","MK07YNo0Qb","5Mg9rNcICA","9rlg9sx5Gl",
-"DG4sTVjCZq","fmIK1lj07Q","MmKGJWaWsv","SmGzv7X3uy","ZhwG1t98iW","D6rByCIShG","WaWsvHP433","TXQ0Z24ARF","7fsYMlsQGo","OxWIHIjTwP",
-"7Ow5C5nmWv","6q6L9RzaZA","RsQUqtuDyS","BpYhV2Nslm","BGaQY7Ow5C","RsQUqaDGtS","3weIF45cIH","FjHXRQssNC","bZLvSzHF1q","pWiOsCqqaD",
-"WDVWJ07n1c","RmDcrfcwDa","gdQsS48cHL","6q6L9LbRTH","CIShGJkzUn","CdyBVYf2Ec","WmadA64s8N","rhl0Jsx5Gl","OHaBzFGzgp","XflUqTa8f6",
-"fLNg8euZA5","W7cTs5iGN5","MK07YHfyNQ","No0QbzHF1q","0h1b15Mg9r","Waim6Mkgy8","ZJTXHguMb8","lsQGoVprf2","s93Mld85a9","yToGWdQ586",
-"3weIFix74r","tl72WW7cTs","BFkb8RmDcr","dmoS7s93Ml","2TRI7uTacx","VBjhzjSjS3","tlILt8RCUA","jtn0XFhtgl","he9IAru4UG","0BmCyJJs5m",
-"FwEJz5drc6","jtn0X16lHc","RpBQmsqVrf","4QMc9uQIcz","dmoS7VNCPd","29QAz9GXkX","uQIczd7vjM","U3yw5t59lR","uvf7AaFFss","gjUTuWDVWJ",
-"FGzgphe9IA","2ZHdkTwano","sx5GlBCxeC","oVQp6jiVBP","pFrrlEoToP","dmoS7YOfrY","zFgtBPYBf4","b29RJBbwgA","IKxdLsqVrf","J2mQiAkKTk",
-"ECMvUyvOMI","UlU3MVjCZq","EOE1oECMvU","rhl0J9y4lw","P6bcgQ6hMC","NAFuwY1mC0","5nmWvTCgPp","NOHsz1j5L8","KZamHJ2mQi","ulk4145cIH",
-"QbxXczqH0W","GWqqXSjskQ","ulk41FFDui","rKDLJ5iGN5","okgRin1pmO","qUJMdokgRi","tl72W9XyT9","J2mQiXyPZN","3weIFCxVEf","PYBf41LB1L",
-"zqH0WCK5W7","piJSkAXpwE","AIYUuNAFuw","5nmWv48cHL","MGlTFyEfy9","faHir07n1c","0Kyfs0Kyfs","okgRiFFDui","iwzGkuoStw","7hyVvO3iyQ",
-"2NslmaDGtS","Cp3mZFnPFB","Waim6tAOsr","x3LDelH1kt","ZJTXHNAFuw","uN6r3FnPFB","CdyBVQnJ1S","EoToPRkQke","2Yz7Etl72W","FVMxogjUTu",
-"GrDg7K4GS8","5iGN5KASQ8","Vprf2yvOMI","AXpwEvOqCE","GWqqXqQxHP","MGlTFpWiOs","MmsIoOUYuF","0BmCyni2v1","uvf7AVjCZq","0Wr5yMojnP",
-"oQ87rnFqik","XflUqBGaQY","pv0i7oQ87r","IRh48W3VFH","2ZHdkFLsph","Dz1R3RACuj","cL0aEcQOnv","IjTwPLewvM","7fKYUIBe8k","uN6r3Nxx9V",
-"AgJHQWDVWJ","t59lRM3zXL","0KyfsgIYvE","s4786VjCZq","1LB1L5drc6","faHirUl4a1","DG4sTUlU3M","2TRI77X3uy","a00b5hSSvQ","jzUqR24ARF",
-"aL6AJ0MR5X","SbRYyS2Dfu","Cfgr3qUJMd","8RCUADQimp","t59lRCdyBV","uvf7ACIShG","DLhzMlH1kt","tl72Wv1Hln","KZamHNo0Qb","uN6r3cShY2",
-"faHirECMvU","CxVEfUl4a1","MmsIoPYBf4","IRh48Oz8yZ","Uvlv4MGlTF","9iGoT4dEz6","QWxoT9XyT9","MGlTFKr8ys","brhlQU3yw5","BCxeCMK07Y",
-"v1Hln9GXkX","jeskS7fsYM","Cp3mZpmeCd","45cIHFwEJz","MojnPJRJQB","piJSk2Nslm","ZuDtDatef2","Oz8yZCdyBV","ksJbyciuWz","9rlg91LB1L",
-"8FmFHFxX9q","s7MxktlILt","rKDLJMm8si","qQxHPTCgPp","fmIK1jiVBP","tvdkDZhwG1","i7WMQcQOnv","8RCUAazIWp","uoStwQ6hMC","BpYhVpWiOs",
-"X6PinQbxXc","fqypy07n1c","ksJbynlaBy","IBe8krhl0J","kB5nPC2Irc","lXFOBZJTXH","VIlwP2Yz7E","sx5GlPb1pa","4W0TlhUTw7","vkCHHZv7z0",
-"zmLYDOUYuF","LbRTHVprf2","HRxd89GXkX","l83Ud7ku1p","1v5hHru4UG","yluBxWPmlx","OHaBzpv0i7","SjskQatef2","dmoS7MK07Y","OHaBzSWfou",
-"hYBCKwDajX","RACujnnP8o","BFkb8n1pmO","RBhp0X6Pin","v1Hlndjsrv","LewvMZuDtD","8U2nUxXTI4","Ss0ZuYf2Ec","FPfSEulk41","Ul4a1cShY2",
-"YOfrYv1Hln","dQ586gIYvE","v8yFNfqypy","ECMvUatef2","uTacx8hJdt","iwzGkFwEJz","jSjS3CK5W7","uTacx5VZjS","XflUqZv7z0","580YDFnPFB",
-"uN6r3FcWrW","AXpwEQworu","MaJQsIn3NS","FLsphI7p2a","ciuWzFFDui","8RCUAi7WMQ","9GXkXMaJQs","hSSvQMezSW","FLsphwDajX","fcJOyQbxXc",
-"BCxeC0Wr5y","hUTw7oVQp6","MaJQsv8yFN","8FmFHZJTXH","RmDcr0ao3l","UlU3MtuDyS","6q6L9b29RJ","v2eC37Ow5C","Ul4a1HfyNQ","QChxs2hEEU",
-"2ZHdk7fKYU","jtn0XWDVWJ","NAFuw3weIF","2ZHdkguMb8","ReKEWgjUTu","JIqXiG1RhS","tlILtpT8wu","XflUqHlUbF","HfyNQAkKTk","580YDx3LDe",
-"1j5L8FcWrW","9rlg9lsQGo","ru4UGFFDui","ix74rRmDcr","55rfBZuDtD","oQ87rStlDJ","k85Aev8yFN","pFrrlfaHir","lkMUAK20wK","24ARFBbwgA",
-"MK07Y5nmWv","3otm6tuDyS","FPfSEP6bcg","NOHszuQIcz","RACujt98iW","DG4sTzmLYD","ZUnqtXyPZN","lViBvUmaEv","FNYIMTa8f6","HzZT8FjHXR",
-"WmadARsQUq","1LB1Lt59lR","b29RJaez9y","ThjNnIRh48","J2mQiMGlTF","EdBKctl72W","MezSW0BmCy","7ku1ppiJSk","aDGtSlXFOB","VjCZqokgRi",
-"hE1QlgIYvE","jfREuZuDtD","BCxeC1LB1L","tvdkDo8Uyd","ThjNnP6bcg","FLsphn1pmO","tlILtrhl0J","zFgtBsx5Gl","tAOsr4W0Tl","yToGW6AFT0",
-"uLtKsY1mC0","DQimpLDk6f","v1HlnX6Pin","jiVBPP6bcg","zz4ZU7fsYM","7hyVvAXpwE","azIWpuupzk","zmLYDbgJAz","7hyVvU3yw5","1j5L8yvOMI",
-"UlU3MhSSvQ","Ul4a1HlUbF","zHF1qZuDtD","Rxrsm5IhmG","LewvMuPX7G","RsQUqMkgy8","QChxs7lUXZ","AOgEeulk41","dmoS7OxWIH","2NslmvkCHH",
-"l83UdFLsph","h1zcHOUqFM","8TxD77ku1p","vLsmS2Yz7E","s7MxkLbRTH","HRxd8hUTw7","O3iyQ8FmFH","jiVBPKZamH","WMiS3aez9y","QnJ1SCp3mZ",
-"Cfgr3sqVrf","pv0i748cHL","RpBQmRACuj","lViBvlXFOB","7fKYUpmeCd","5drc6gtCA5","QworuBbwgA","16lHcyToGW","s4786SmGzv","ix74r9y4lw",
-"nFqiklkMUA","YjB9trhl0J","qUJMdDQimp","qQxHPQClRL","55rfBK20wK","IRh48S77LH","jtn0X9y4lw","yluBx2ZHdk","VBjhztvdkD","cmXIXuQIcz",
-"VLTy6lH1kt","55rfB5Drn0","e6e4zciuWz","xReecJXljW","CxVEfpAhR1","Chuy3FGzgp","TXQ0ZCK5W7","EOE1owiHrZ","qUJMdfFDrJ","3weIFWPmlx",
-"h1zcH6q6L9","sx5GlZJTXH","3otm6VerEA","JkzUncL0aE","9y4lwjiVBP","KASQ8DQimp","fmIK1d7vjM","ZJTXHRsQUq","Q6hMC9y4lw","SmGzvGXdoH",
-"fqypyOHaBz","J2mQiiKqhr","JRJQBRkQke","fcJOy0Kyfs","WmadA7fKYU","mX2GEuTacx","14FLRCfgr3","Waim6hSSvQ","v2eC3jzUqR","Yh1hFQChxs",
-"8hJdtEoToP","CK5W707n1c","IjTwPHfyNQ","b29RJIRh48","LbRTHJRJQB","DG4sT9XyT9","0PktIFxX9q","Ul4a15Mg9r","a00b51j5L8","jS1ajBpYhV",
-"POUYSL7cGc","lsQGoFhtgl","Vprf2gdQsS","zbIYYTa8f6","cShY2LewvM","zbIYYuAWyp","Gv3Fq29QAz","uoStwEOE1o","WmadAkZANm","7fKYUrKDLJ",
-"zz4ZUguMb8","d85a9GrDg7","NAFuwPYBf4","aDGtS8xEKz","dhSuHQ6Lix","FVMxouZPqg","VNCPdtjQxs","Yw2oUFLsph","cmXIXCp3mZ","GrDg7n8pJ9",
-"azIWpSmGzv","FxX9qiqv4k","Kr8ysVNCPd","64s8Na00b5","OUYuFuN6r3","TXQ0ZDLhzM","oVQp6hi5X7","KZamHlH1kt","580YDFcWrW","LbRTH1j5L8",
-"K20wKtl72W","64s8NW3VFH","AIYUubgJAz","s4786ECMvU","G1RhSmz8gx","xXTI4lweGy","zHF1qsuY4x","1LB1LBFkb8","mX2GEDG4sT","ThjNnaL6AJ",
-"SmGzvMm8si","AmdQdCxVEf","DQimpF6PT2","2Yz7EOxWIH","45cIHhe9IA","tjQxshYBCK","lm0pDoVQp6","48cHLDcpWB","AkKTkQClRL","y94nw4dEz6",
-"8RCUASjskQ","gtCA5SbRYy","uupzkFNYIM","5Nammk85Ae","t59lR7ku1p","JKWYRD6rBy","1LB1LMK07Y","MGlTFAkKTk","uN6r3RmDcr","OUYuFzmLYD",
-"Vprf2AOgEe","QWxoT48cHL","VBjhzni2v1","Mkgy80Wr5y","vLsmSIjTwP","0h1b1zQt6Q","2NslmX6Pin","ix74rDz1R3","NOHszru4UG","OUqFMkB5nP",
-"S2DfuECMvU","K4GS8rKDLJ","jeskShYBCK","JJs5mLDk6f","GSQwjUl4a1","yluBxRxrsm","vkCHHt59lR","uQIcz5iGN5","HfyNQ0BmCy","IBe8kDz1R3",
-"okgRiSs0Zu","S77LHEoToP","yToGWVLTy6","FhtglNOHsz","Kr8yslj07Q","xReecQnJ1S","W3VFH8TxD7","4QMc9BGaQY","YOfrYAOgEe","LbRTH5iGN5",
-"WMiS3v1Hln","KsjRK7fKYU","aDGtSFLsph","AkKTkprNT6","rKDLJRxrsm","HlUbFydG8U","ZJTXHgdQsS","CqqaDCIShG","gtCA5AkKTk","4dEz6GXdoH",
-"oGu6xpAhR1","ThjNnRxrsm","dmoS7618Di","0YAGHi7WMQ","QClRLsoy9t","v1Hlnhi5X7","580YDNo0Qb","lpF6WsuY4x","S77LHfqypy","lH1ktGSQwj",
-"DLhzMVLTy6","uN6r3yEfy9","Yf2EcGSQwj","bZLvShi5X7","5iGN5jzUqR","lpF6WkB5nP","D6rByokgRi","hSSvQD6rBy","yluBxX6Pin","CIShGoQ87r",
-"euZA5ksJby","8hJdtDQimp","5ZaEz5Drn0","RmDcrm4bxU","s7Mxk5ZaEz","Chuy3S77LH","v2eC3zbIYY","ZuDtD3weIF","fFDrJK20wK","9iGoTUmaEv",
-"07n1cmz8gx","piJSkNxx9V","QbxXcuPX7G","P6bcgKr8ys","FNYIMdpe1v","4W0TlK20wK","yvOMIFnPFB","gtCA5lCMxy","QbxXc5Namm","lXFOBgf8rI",
-"xXTI4uAWyp","FnPFBAXpwE","n1pmOxXTI4","cL0aEzY1GY","MGlTFTXQ0Z","G1RhSydG8U","tlILtGSQwj","fLNg8lH1kt","mX2GEuJScX","kZANmdQ586",
-"vOqCEulk41","cShY2gIYvE","lj07QVerEA","XyPZNTa8f6","Ta8f6xciqp","prNT6tjQxs","IKxdLGv3Fq","FFDuit98iW","SmGzvY1mC0","RmDcrIBe8k",
-"FxX9qfFDrJ","m4bxUiqv4k","gf8rIKASQ8","aDGtSGSQwj","QWxoTtvdkD","Oz8yZ9iGoT","jtn0XJIqXi","5VZjSQYxC0","I7p2a2Nslm","MGlTFWaim6",
-"0BmCylCMxy","hYBCKuPX7G","fLNg8zY1GY","zz4ZUlweGy","prNT6HRxd8","14FLRMGlTF","POUYS48cHL","GWqqXBGaQY","sx5GlqUJMd","XyPZNv2eC3",
-"BGaQYQYxC0","C2Ircdjsrv","v8yFNVLTy6","RmDcrx3LDe","piJSkPYBf4","gIYvEfcJOy","6q6L9gf8rI","he9IAaFFss","Yw2oUiwzGk","n8pJ9Vprf2",
-"lH1kt0BmCy","wiHrZYjB9t","k85AepiJSk","GSQwjWMiS3","QWxoT9eoRc","gIYvEqaofN","VNCPdOUqFM","yvOMIL7cGc","C2IrcnlaBy","48cHL8U2nU",
-"kB5nPogLgc","2hEEUpAhR1","MK07Y8FmFH","nlaByuLtKs","MGlTFciuWz","8cVD3jiVBP","oGu6xCNHmv","hi5X7s93Ml","MaJQsDcpWB","nnP8ol83Ud",
-"P6bcg8RCUA","pT8wulXFOB","FLsph0YAGH","ReKEWcShY2","GWqqXBCxeC","JIqXizQt6Q","TCgPpbZLvS","CK5W7bgJAz","lsQGoXflUq","NcICAhi5X7",
-"YjB9tKsjRK","gtCA5zqH0W","OHaBzvLsmS","EdBKcoQ87r","dhSuHIn3NS","soy9tK20wK","aDGtSD6rBy","LewvMMaJQs","euZA5GXdoH","P6bcgEOE1o",
-"l83UdxXTI4","tuDySMmKGJ","Ta8f6pv0i7","NcICAWPmlx","9GXkXMGlTF","jtn0XQworu","Dz1R3AmdQd","uLtKsI7p2a","aL6AJBpYhV","Ul4a1Qworu",
-"29QAzRpBQm","FGzgp618Di","5Mg9rHzZT8","S77LHdmoS7","hSSvQuLtKs","9iGoTIjTwP","cmXIXP6bcg","QnJ1S8hJdt","EdBKc3otm6","lViBvhE1Ql",
-"pT8wuD6rBy","dhSuHAgJHQ","oQ87rx3LDe","C2Ircrhl0J","CxVEfMGlTF","Pb1pazY1GY","zqH0WciuWz","gtCA5618Di","d7vjMjeskS","0h1b1NcICA",
-"e6e4zBFkb8","zQt6QcShY2","b29RJgf8rI","CxVEfNAFuw","Y1mC0mX2GE","XyPZNGWqqX","TCgPpuupzk","NAFuw48cHL","zFgtBdhSuH","ECMvUHRxd8",
-"7Ow5CKZamH","JXljWYOfrY","bZLvSOUYuF","fFDrJ0Wr5y","iB08lF6PT2","VNCPdKsjRK","uN6r3qaofN","ciuWzyToGW","suY4xlj07Q","1v5hHprNT6",
-"piJSkCp3mZ","iB08ljzUqR","tuDyS4dEz6","kZANm8cVD3","jSjS3FnPFB","uAWypJXljW","l83Udy94nw","BGaQYMkgy8","lweGy5ZaEz","lpF6W5nmWv",
-"14FLRsuY4x","BpYhVfLNg8","dhSuHHzZT8","B3qem0Kyfs","POUYSjS1aj","vOqCEs4786","MaJQs8hJdt","2Yz7EuZPqg","IRh48lH1kt","EoToP0YAGH",
-"m4bxUtvdkD","DG4sT5IhmG","piJSk2Yz7E","wiHrZThjNn","XyPZNVLTy6","lsQGogf8rI","YOfrYM3zXL","QChxsRkQke","RBhp03weIF","jSjS3uvf7A",
-"b29RJIBe8k","ZJTXHNcICA","U3yw5hYBCK","jtn0XUmaEv","HfyNQNOHsz","C2IrcdmoS7","FcWrWTwano","OxWIHfcJOy","piJSkmX2GE","24ARFKASQ8",
-"AkKTkuoStw","29QAzGWqqX","azIWpFVMxo","jfREuMmsIo","CNHmvTXQ0Z","KZamH1j5L8","soy9tkZANm","tjQxsfLNg8","HzZT8Yw2oU","jtn0XDG4sT",
-"FNYIMQClRL","KASQ88FmFH","wDajXMGlTF","W3VFHoQ87r","8TxD7YjB9t","a00b5uPX7G","GrDg7Ta8f6","zQt6QQYxC0","gjUTuru4UG","iqv4k7fKYU",
-"b29RJS2Dfu","RsQUqRsQUq","Z4I1veuZA5","FGzgppvgjS","oQ87rUmaEv","lkMUAoGu6x","9iGoT9y4lw","ReKEWru4UG","oQ87r6q6L9","aDGtSfqypy",
-"Chuy3n1pmO","S2Dfu64s8N","qUJMdHzZT8","yEfy9JkzUn","QClRLFwEJz","BbwgAIKxdL","AkKTkECMvU","BbwgA7hyVv","MezSWLewvM","zY1GYJJs5m",
-"MGlTFJJs5m","GXdoHguMb8","7ku1pNcICA","5Drn05ZaEz","RBhp0uvf7A","YOfrYuupzk","CxVEfjS1aj","NOHszlj07Q","SjskQRACuj","RBhp0FxX9q",
-"lCMxyokgRi","5Mg9ruN6r3","IKxdLJIqXi","BpYhVGv3Fq","hUTw7zFgtB","FPfSEy94nw","48cHLtjQxs","tuDySAIYUu","FLsphCIShG","K20wKdjsrv",
-"IRh48OUYuF","uupzkpiJSk","8FmFHBpYhV","ZuDtDdhSuH","ZuDtDzQt6Q","rhl0Jh1zcH","ECMvUcQOnv","piJSk2hEEU","P6bcgAgJHQ","yEfy9P6bcg",
-"Uvlv42Yz7E","1LB1L4W0Tl","rz7UttuDyS","gdQsSl83Ud","Cfgr3QClRL","TwanozY1GY","J2mQioQ87r","piJSkAIYUu","jtn0XDQimp","FFDuiFhtgl",
-"SjskQ2DREs","uQIczFjHXR","CqqaDfaHir","SWfouZv7z0","UmaEvyvOMI","AgJHQ9XyT9","ReKEWF6PT2","55rfBcQOnv","i3pydi3pyd","8RCUASmGzv",
-"7ku1pWaim6","2Yz7EYw2oU","JJs5mFcWrW","CdyBVjS1aj","pmeCd0ao3l","DcpWBogLgc","W7cTs45cIH","WDVWJFwEJz","VBjhzAXpwE","gdQsSm4bxU",
-"QbxXc7X3uy","618DiTCgPp","oQ87rMkgy8","VIlwP64s8N","YOfrYAIYUu","FNYIMO3iyQ","3otm6dQ586","5ZaEz9XyT9","1LB1LDLhzM","QbxXcBFkb8",
-"s7MxkDLhzM","uLtKsDz1R3","soy9tW3VFH","b29RJ4W0Tl","C2IrcUlU3M","kB5nPlj07Q","KsjRKyEfy9","jeskSl83Ud","bgJAzOxWIH","5Drn0Chuy3",
-"S77LHl83Ud","IKxdL3weIF","FcWrWsoy9t","tjQxsVLTy6","VjCZqAkKTk","e6e4z48cHL","JIqXiVprf2","Ta8f6uJScX","JKWYRAgJHQ","0ao3lyToGW",
-"Q6LixlViBv","FhtglyvOMI","s7MxkoVQp6","faHir3otm6","tvdkDvOqCE","M3zXLJJs5m","OUYuFRACuj","AgJHQ4W0Tl","HP433gf8rI","5Drn0euZA5",
-"Yw2oUGWqqX","nlaBy14FLR","MojnP48cHL","UlU3MYw2oU","fqypy0h1b1","euZA5brhlQ","lXFOBtuDyS","8TxD7tAOsr","NhXduGrDg7","sqVrfpWiOs",
-"fcwDapWiOs","MmKGJDG4sT","MK07YXyPZN","6q6L90Kyfs","JkzUnOHaBz","uN6r3WDVWJ","WPmlxgIYvE","FjHXRk85Ae","FjHXRgIYvE","i3pydRxrsm",
-"sx5GlK4GS8","atef2RkQke","ZJTXHO3iyQ","K20wKlH1kt","POUYSzbIYY","RmDcrGSQwj","oGu6xTCgPp","taOXKCIShG","dmoS7BCxeC","NAFuwhYBCK",
-"soy9tRsQUq","5iGN5oVQp6","HfyNQAmdQd","uTacx4W0Tl","0YAGHoQ87r","dmoS7QnJ1S","55rfBRsQUq","JIqXi1LB1L","EOE1oIBe8k","jiVBPqQxHP",
-"Yh1hF29QAz","0PktIwiHrZ","MGlTFDz1R3","pWiOsd7vjM","suY4xSs0Zu","QChxsQ6Lix","nFqikQnJ1S","XflUqHfyNQ","AXpwEJIqXi","xciqpdpe1v",
-"b29RJiKqhr","n8pJ9IjTwP","2Yz7EjeskS","ulk41y94nw","LbRTHyluBx","mX2GE24ARF","CdyBV8FmFH","i3pyddQ586","WPmlxK4GS8","a00b5QChxs",
-"k85AedmoS7","16lHc14FLR","kZANmhE1Ql","RkQkey94nw","64s8NyofH3","FwEJzPb1pa","Mkgy8taOXK","cShY2ulk41","lH1kte6e4z","uLtKsfmIK1",
-"lXFOBZzJHW","hSSvQ9GXkX","L7cGccL0aE","pWiOsFGzgp","RzaZAgtCA5","CqqaDn1pmO","oQ87riqv4k","MaJQs580YD","suY4xNAFuw","zz4ZUTXQ0Z",
-"HP433FFDui","Qworuhi5X7","fcwDaFFDui","JXljW8hJdt","dpe1vy94nw","WDVWJChuy3","UlU3MjiVBP","0YAGHVNCPd","s93MlKZamH","BbwgA7fsYM",
-"D6rByLewvM","euZA5dmoS7","WPmlx7fsYM","n8pJ9lCMxy","yToGWMmKGJ","FFDui4dEz6","uZPqgYjB9t","lm0pDciuWz","gIYvEHfyNQ","b29RJcShY2",
-"lCMxyuLtKs","fLNg8zFgtB","uAWypVNCPd","jtn0XK20wK","16lHcFnPFB","fFDrJDQimp","OUqFMn8pJ9","Oz8yZYf2Ec","okgRiFPfSE","hUTw7Qworu",
-"StlDJW3VFH","b29RJJJs5m","jSjS3SWfou","MaJQsYh1hF","tuDySlXFOB","gf8rIqaofN","JIqXiCfgr3","ciuWztaOXK","Dz1R38RCUA","FPfSEGWqqX",
-"JXljWYw2oU","WreyPGv3Fq","HP433s93Ml","5NammMGlTF","ZJTXHAmdQd","qQxHPTa8f6","cQOnvXflUq","0MR5XokgRi","Mm8siRsQUq","5drc67hyVv",
-"B3qemOHaBz","WaWsvdjsrv","AmdQdMezSW","aez9y8RCUA","Y1mC0EOE1o","ZuDtDzmLYD","HP433bgJAz","ECMvUAkKTk","1LB1L0Wr5y","F6PT255rfB",
-"uN6r3pWiOs","VLTy6580YD","2hEEUBCxeC","WaWsvHlUbF","BCxeCB3qem","BpYhVFhtgl","prNT6guMb8","1v5hHs93Ml","5Mg9rUlU3M","SbRYyn1pmO",
-"W3VFHpvgjS","jiVBPD6rBy","Uvlv4dQ586","Gv3FqnFqik","U3yw5M3zXL","jzUqRFjHXR","v8yFNBCxeC","aez9yMmsIo","JKWYRblLA9","oGu6xPOUYS",
-"cQOnvs93Ml","W7cTsmz8gx","64s8NTwano","9y4lwQ6Lix","iwzGkNo0Qb","hE1Ql16lHc","iKqhrlsQGo","HP433zY1GY","xXTI4gdQsS","jfREuCdyBV",
-"taOXKW3VFH","zz4ZU9rlg9","Ss0ZuIBe8k","8FmFHD6rBy","uJScXwiHrZ","vkCHHblLA9","uJScXpiJSk","FNYIMM6qcG","hE1Ql580YD","WDVWJnnP8o",
-"7fsYMKsjRK","WPmlxuAWyp","yvOMIGXdoH","MGlTFUmaEv","dpe1v4QMc9","ni2v1VerEA","fcJOyQWxoT","dhSuHdmoS7","AIYUuRpBQm","DG4sTDcpWB",
-"VIlwP9eoRc","aDGtSm4bxU","MaJQsC2Irc","d85a9Q6Lix","nnP8oCNHmv","Nxx9V7Ow5C","b29RJ07n1c","uZPqgZv7z0","zqH0WksJby","618Di16lHc",
-"aL6AJVerEA","fmIK1uZPqg","55rfBdmoS7","uTacxydG8U","5ZaEzn8pJ9","0YAGHaFFss","3weIFReKEW","FFDuiChuy3","DQimplH1kt","VIlwPqaofN",
-"dhSuH55rfB","hi5X7hUTw7","vOqCEQ6Lix","yToGW2Yz7E","s93MloGu6x","Pb1palm0pD","pmeCd7ku1p","jeskSzqH0W","lViBvhYBCK","VerEAa00b5",
-"8TxD7lsQGo","QWxoTNcICA","J2mQiMezSW","TXQ0ZaFFss","hYBCKKASQ8","ZJTXHoVQp6","euZA5RsQUq","5ZaEzVerEA","ReKEWHP433","45cIHB3qem",
-"dhSuHdjsrv","Uvlv4SmGzv","jfREu45cIH","m4bxUuN6r3","FNYIMNxx9V","aez9ylXFOB","14FLRksJby","POUYSGXdoH","VjCZqDcpWB","GXdoHBFkb8",
-"pFrrlFjHXR","okgRiJKWYR","piJSk9y4lw","FjHXRS77LH","MmsIociuWz","NhXdusqVrf","RzaZAWPmlx","YOfrYdhSuH","prNT6KZamH","KASQ8iqv4k",
-"faHiruQIcz","oGu6xtjQxs","nlaByiKqhr","TXQ0ZlweGy","lXFOB14FLR","b29RJ2hEEU","JKWYRPb1pa","HP433QWxoT","cQOnvpmeCd","ksJbyGv3Fq",
-"pFrrlfcwDa","fcJOyOUYuF","d85a9tjQxs","7hyVvUvlv4","fqypyhE1Ql","VBjhzazIWp","v1HlncShY2","FhtgltlILt","LewvMzmLYD","uupzkGWqqX",
-"5iGN5l83Ud","VIlwPjeskS","Qworuhe9IA","NOHsznnP8o","n1pmOOz8yZ","zz4ZU8RCUA","s4786uJScX","rhl0J45cIH","DcpWBjfREu","XyPZNFwEJz",
-"t98iWChuy3","aDGtSTXQ0Z","AXpwEBCxeC","StlDJgdQsS","IjTwP0BmCy","tuDyStaOXK","vLsmS9y4lw","RACujgjUTu","9eoRc8RCUA","s478607n1c",
-"RzaZAtl72W","WreyPEoToP","qUJMdzmLYD","n8pJ97fsYM","MezSWCNHmv","5IhmGHlUbF","07n1c1LB1L","d7vjM9eoRc","MmKGJJ2mQi","RACujWmadA",
-"F6PT2uAWyp","jeskSqUJMd","BFkb8qUJMd","5Drn0ECMvU","uLtKs3otm6","QWxoT5IhmG","RsQUq16lHc","OHaBzMezSW","i7WMQVLTy6","cQOnvCxVEf",
-"M6qcGDG4sT","nlaByQworu","OxWIHVBjhz","Uvlv4rz7Ut","LewvMQClRL","JIqXiLewvM","Vprf2Yw2oU","45cIHrz7Ut","GSQwjS77LH","Mm8situDyS",
-"iKqhrChuy3","MezSW5Mg9r","oVQp6ECMvU","VIlwPZzJHW","No0QbfaHir","bgJAzL7cGc","RsQUqAOgEe","lm0pDyToGW","BpYhVTa8f6","azIWpoGu6x",
-"7X3uyiwzGk","2ZHdklj07Q","uZPqgXflUq","1j5L845cIH","EdBKcZJTXH","lpF6WDcpWB","8hJdtFPfSE","GSQwj8cVD3","IKxdL8RCUA","v8yFNEoToP",
-"Uvlv4RzaZA","7fsYMLewvM","KZamHsqVrf","HfyNQfcwDa","CxVEfEdBKc","C2IrcECMvU","cQOnv0BmCy","ciuWzQssNC","9y4lwsuY4x","d7vjMBpYhV",
-"bgJAzn1pmO","ZzJHWvOqCE","B3qemNhXdu","DcpWBNo0Qb","uAWypru4UG","RxrsmJRJQB","aez9yO3iyQ","RpBQmbgJAz","1v5hHsoy9t","faHirAmdQd",
-"3weIFQ6hMC","HlUbF5iGN5","AgJHQ8U2nU","hYBCKd85a9","RkQkejiVBP","QWxoTsuY4x","4W0Tluupzk","Mkgy8Cfgr3","tl72WtlILt","2TRI7s4786",
-"FVMxoSs0Zu","lweGyUlU3M","Chuy3EOE1o","mX2GEru4UG","CIShGHfyNQ","TXQ0Zrhl0J","580YDBbwgA","D6rByjzUqR","aL6AJSjskQ","4QMc9O3iyQ",
-"45cIH48cHL","24ARFpAhR1","MojnPQ6hMC","UlU3MyEfy9","rhl0JzHF1q","X6PintAOsr","QssNCnlaBy","uoStwG1RhS","xciqpCdyBV","Chuy3yToGW",
-"J2mQixciqp","n1pmOiKqhr","B3qemB3qem","YjB9tI7p2a","S77LHLbRTH","qQxHPiqv4k","iwzGkAOgEe","iB08lLewvM","djsrvxXTI4","uvf7A7X3uy",
-"kZANm5Drn0","iKqhrUlU3M","2hEEU9XyT9","JRJQBlsQGo","UlU3MK20wK","CxVEfJXljW","n1pmOvkCHH","8FmFHKr8ys","rhl0JKsjRK","zHF1q2ZHdk",
-"lweGyJkzUn","0KyfsuZPqg","faHirkB5nP","HRxd8618Di","AXpwEx3LDe","DQimps4786","kZANmG1RhS","vkCHHuupzk","dhSuHzmLYD","TwanoZJTXH",
-"2DREs7fsYM","JJs5mfmIK1","14FLRn8pJ9","M6qcG5drc6","UmaEv5Drn0","vkCHHXyPZN","8xEKzhE1Ql","SjskQ5Namm","a00b5EdBKc","ciuWzJRJQB",
-"dhSuHtvdkD","ni2v1gjUTu","7Ow5CFLsph","fqypyciuWz","ThjNn5nmWv","S77LHGrDg7","kB5nPmX2GE","KASQ8Cfgr3","m4bxUv8yFN","VIlwPgf8rI",
-"oQ87rVerEA","zY1GYokgRi","M6qcGI7p2a","uJScXsqVrf","oVQp6GXdoH","cmXIXx3LDe","uTacxdpe1v","C2IrcAOgEe","In3NSuQIcz","5ZaEzChuy3",
-"TXQ0ZhE1Ql","RsQUqPOUYS","Chuy3IKxdL","MaJQsTCgPp","Q6LixIKxdL","Cfgr3faHir","prNT616lHc","Q6Lix5nmWv","8cVD3No0Qb","9XyT9DG4sT",
-"5VZjSfaHir","Z4I1vQbxXc","tuDyShE1Ql","azIWpiKqhr","atef2VNCPd","Kr8yseuZA5","DcpWBxciqp","8RCUAyToGW","CxVEfaFFss","Ss0ZuuN6r3",
-"uJScXn1pmO","VjCZqnFqik","h1zcHnFqik","HlUbFEdBKc","CxVEfZuDtD","8FmFHd7vjM","YjB9ts93Ml","v8yFN5drc6","D6rByvLsmS","pFrrlIKxdL",
-"D6rByHlUbF","uZPqgtAOsr","zmLYDuLtKs","kB5nPQssNC","ydG8UksJby","hE1QlfaHir","BpYhVyToGW","0ao3ljSjS3","OHaBzFnPFB","JIqXizY1GY",
-"Kr8yskZANm","4QMc92Nslm","0h1b1FnPFB","ZUnqtJJs5m","zmLYDiqv4k","I7p2asqVrf","7hyVvStlDJ","fFDrJfLNg8","Yh1hFuJScX","1j5L89y4lw",
-"EdBKcQClRL","RpBQmWaim6","xXTI4yEfy9","HlUbF8U2nU","XyPZNYjB9t","vLsmSG1RhS","MGlTFBpYhV","uAWypSs0Zu","RmDcrRmDcr","lweGy2TRI7",
-"BCxeCqUJMd","dhSuH3otm6","1v5hHrz7Ut","8FmFH9GXkX","lj07QSs0Zu","Zv7z029QAz","KASQ8pFrrl","2DREsvOqCE","LewvMCfgr3","FnPFBgtCA5",
-"blLA9lpF6W","tlILtStlDJ","qQxHPNxx9V","MojnPW3VFH","QChxsqaofN","Mm8siMm8si","9eoRcMkgy8","jtn0Xuupzk","rKDLJMK07Y","rKDLJJ2mQi",
-"5VZjSCfgr3","jzUqRRkQke","4dEz6gjUTu","FVMxolkMUA","v2eC3tlILt","0PktI5ZaEz","lH1ktcQOnv","Yf2EcFGzgp","8FmFHuLtKs","taOXKBGaQY",
-"BpYhVFxX9q","PYBf4a00b5","hSSvQ14FLR","Vprf2pv0i7","618DigIYvE","blLA9FLsph","0ao3lxReec","AmdQdU3yw5","K20wKzmLYD","KsjRKMkgy8",
-"ThjNnJJs5m","J2mQivLsmS","AOgEeRpBQm","blLA92Nslm","SbRYyThjNn","gjUTuC2Irc","P6bcgm4bxU","piJSk5drc6","okgRi0MR5X","2NslmYf2Ec",
-"lm0pDlpF6W","n8pJ90BmCy","jSjS3WreyP","aez9ybrhlQ","HRxd8uvf7A","ydG8UJRJQB","gdQsSCfgr3","pWiOshE1Ql","iwzGkKr8ys","DQimpWreyP",
-"oVQp6hUTw7","M6qcGQworu","FPfSEBpYhV","J2mQi9XyT9","lXFOBGv3Fq","MaJQsPb1pa","FxX9qGrDg7","gtCA55IhmG","Kr8ysy94nw","pT8wu6AFT0",
-"tAOsrRBhp0","yofH3uAWyp","C2IrccmXIX","JkzUnZuDtD","8FmFHVIlwP","jS1ajv1Hln","6q6L9ReKEW","YOfrYWaim6","pFrrljzUqR","uPX7G1j5L8",
-"0YAGHa00b5","580YDfFDrJ","hYBCK0Wr5y","Mm8siKsjRK","FcWrWUmaEv","zY1GYpvgjS","iB08l8TxD7","24ARFGrDg7","5NammI7p2a","GWqqXjiVBP",
-"XflUqJRJQB","CqqaDsoy9t","DG4sTGrDg7","zFgtBSjskQ","24ARFjfREu","FGzgpKr8ys","gf8rIvkCHH","OUYuFSjskQ","618DiQ6hMC","7Ow5CUl4a1",
-"zY1GYECMvU","qaofNlj07Q","oGu6xhe9IA","XyPZN5iGN5","M3zXLMkgy8","CdyBV9iGoT","vOqCE8TxD7","YjB9tfmIK1","Oz8yZBGaQY","F6PT2KsjRK",
-"StlDJZzJHW","5VZjSTCgPp","zFgtBbgJAz","EoToPTa8f6","guMb8cmXIX","QbxXcVNCPd","aFFssn1pmO","ZhwG1tvdkD","3weIFgf8rI","brhlQbZLvS",
-"fmIK1MK07Y","XflUqRzaZA","iKqhrkB5nP","lXFOB7hyVv","nlaBy1v5hH","tAOsrGrDg7","FVMxoRACuj","5drc6FFDui","L7cGcDQimp","pvgjS4dEz6",
-"JKWYRm4bxU","Cp3mZt98iW","dmoS7RpBQm","4dEz6lj07Q","cQOnvyEfy9","CxVEfaez9y","VIlwPulk41","5ZaEzNxx9V","SbRYyCfgr3","0BmCyv2eC3",
-"ni2v1d7vjM","CNHmvydG8U","BFkb8rKDLJ","3otm6NhXdu","JRJQBh1zcH","DG4sTAgJHQ","zz4ZUAmdQd","9rlg95ZaEz","zFgtBgdQsS","RzaZA24ARF",
-"55rfBFLsph","AkKTkJJs5m","RpBQmCIShG","5ZaEz2hEEU","o8UydpT8wu","uTacx1LB1L","JXljW0Kyfs","gf8rIYw2oU","s7Mxk5nmWv","PYBf4jSjS3",
-"K4GS87ku1p","OxWIH07n1c","WmadAW7cTs","ogLgcokgRi","5IhmGoGu6x","blLA9Cfgr3","prNT6DG4sT","jSjS3ZUnqt","ru4UG2DREs","bZLvSksJby",
-"RpBQm6q6L9","C2IrczmLYD","QnJ1S7fKYU","CIShG0Wr5y","F6PT2LbRTH","ZJTXHfcJOy","aDGtSprNT6","9y4lwjtn0X","uoStwnFqik","ix74rB3qem",
-"Cfgr30BmCy","P6bcgqUJMd","t98iWblLA9","S77LHulk41","ogLgc4QMc9","AIYUu29QAz","Vprf2ulk41","lweGyogLgc","okgRiMezSW","aDGtSDQimp",
-"64s8NbZLvS","dhSuHfLNg8","ix74riB08l","4dEz6P6bcg","cL0aEMm8si","dhSuHiwzGk","QWxoTv8yFN","hi5X7ZUnqt","55rfBW3VFH","d7vjM8U2nU",
-"LDk6ffqypy","AmdQdhe9IA","ru4UGv1Hln","9eoRcMmsIo","No0QbNxx9V","O3iyQzQt6Q","pmeCd9eoRc","qaofN07n1c","AIYUuFNYIM","8cVD3fqypy",
-"VIlwPdhSuH","FhtglMmKGJ","I7p2aUvlv4","QChxsK4GS8","SWfou1j5L8","kB5nP0PktI","WPmlxuTacx","cQOnvMmKGJ","fLNg8MezSW","0BmCyVIlwP",
-"kZANmiKqhr","o8Uyd5drc6","U3yw50YAGH","9rlg92Nslm","W7cTsiB08l","uN6r307n1c","uupzkNxx9V","07n1caL6AJ","IjTwPK20wK","VIlwP7ku1p",
-"mz8gxCp3mZ","Gv3FqTa8f6","iKqhrKASQ8","Vprf2s93Ml","4QMc9uPX7G","FjHXRhUTw7","xciqpSWfou","BbwgAQbxXc","v2eC3QYxC0","QClRLJIqXi",
-"d85a9uPX7G","SmGzvMojnP","VBjhzi7WMQ","Dz1R324ARF","d7vjMSbRYy","0BmCybrhlQ","5Drn02Yz7E","3otm6lViBv","PYBf4Mm8si","FcWrWBGaQY",
-"WmadAxReec","Yw2oU5iGN5","Yh1hFAgJHQ","hE1Ql0BmCy","5Mg9rzmLYD","OUqFMAgJHQ","AIYUuv2eC3","FnPFBuN6r3","RmDcrHlUbF","OHaBz48cHL",
-"m4bxUS2Dfu","hUTw7F6PT2","XflUqKr8ys","PYBf4MojnP","Ta8f60PktI","RzaZAuvf7A","tvdkD9XyT9","JJs5mSbRYy","uoStwgIYvE","P6bcgSs0Zu",
-"yvOMIpFrrl","JIqXiThjNn","5iGN5tAOsr","8TxD7brhlQ","vOqCEzFgtB","zY1GYd7vjM","vLsmSjS1aj","ReKEWGrDg7","I7p2aY1mC0","B3qemWaim6",
-"618DiuN6r3","VIlwPyEfy9","8xEKzzz4ZU","XyPZNEOE1o","QnJ1SYOfrY","JKWYRuAWyp","dhSuHU3yw5","24ARF3otm6","7fKYUlCMxy","Q6LixY1mC0",
-"UmaEvKZamH","fqypyuPX7G","QbxXcGrDg7","3weIFzFgtB","hYBCKYf2Ec","k85AepFrrl","OxWIH64s8N","tAOsrOxWIH","6AFT0FLsph","QbxXcb29RJ",
-"5iGN5Ta8f6","d7vjMhE1Ql","lkMUATwano","4QMc97ku1p","l83Ud5iGN5","IRh48CdyBV","lH1kt0PktI","Gv3FqKsjRK","jiVBPRkQke","BCxeCLewvM",
-"pFrrlW3VFH","Waim6CNHmv","aFFss1LB1L","xXTI4he9IA","S77LHh1zcH","VjCZquJScX","Z4I1vs7Mxk","UmaEvF6PT2","JXljWGWqqX","KsjRKCIShG",
-"m4bxUcmXIX","pWiOsm4bxU","cmXIXF6PT2","Dz1R3fmIK1","Z4I1vF6PT2","b29RJdjsrv","FcWrWXyPZN","3otm6QWxoT","e6e4zzbIYY","HfyNQFhtgl",
-"RzaZAa00b5","8cVD3M6qcG","zbIYYYh1hF","Gv3FqlpF6W","FnPFB5iGN5","dpe1vS77LH","4QMc9RmDcr","VerEAW3VFH","Uvlv4t98iW","wiHrZTXQ0Z",
-"JkzUnAXpwE","piJSkuLtKs","vOqCEhYBCK","4QMc9gjUTu","WreyPDG4sT","n8pJ9FjHXR","m4bxUqQxHP","i3pyd2ZHdk","jS1ajK4GS8","8FmFHhE1Ql",
-"FNYIMuPX7G","brhlQlH1kt","fFDrJbZLvS","0YAGH7lUXZ","vOqCEpmeCd","FGzgpfFDrJ","gjUTuChuy3","pWiOsVIlwP","Ss0ZuB3qem","JkzUn8U2nU",
-"mz8gx7X3uy","dmoS7ydG8U","LewvMBpYhV","hi5X7GSQwj","CdyBVwDajX","ZhwG1Twano","FnPFBhe9IA","5Nammgf8rI","IRh48yluBx","cQOnv8hJdt",
-"8U2nU5IhmG","h1zcHdpe1v","FPfSEzbIYY","7hyVvRBhp0","h1zcH9iGoT","1LB1LdmoS7","lkMUABCxeC","CqqaDgdQsS","mX2GEFxX9q","Gv3Fqn8pJ9",
-"ciuWzJ2mQi","SjskQVprf2","5IhmGpiJSk","9XyT9NOHsz","Y1mC0zFgtB","m4bxUxXTI4","HzZT8IRh48","F6PT2StlDJ","GrDg78hJdt","CIShGs4786",
-"Cp3mZJRJQB","d7vjMQ6hMC","gf8rIS77LH","7lUXZChuy3","i7WMQ5VZjS","zz4ZUciuWz","4dEz6AIYUu","618DiqaofN","8hJdtsuY4x","FcWrW0Kyfs",
-"RpBQmAOgEe","FFDuiNo0Qb","v1HlnYw2oU","tlILt8xEKz","580YDZzJHW","QworuCp3mZ","Z4I1vIRh48","MGlTFCNHmv","ThjNnjtn0X","ZUnqtv2eC3",
-"iKqhr5ZaEz","7hyVvChuy3","Vprf2uoStw","64s8NwiHrZ","d85a9lm0pD","5NammaFFss","0Wr5yCp3mZ","VNCPdQYxC0","29QAzcL0aE","s7MxkBGaQY",
-"lH1ktZv7z0","he9IAs7Mxk","sx5GlFLsph","14FLRFVMxo","2Yz7ECNHmv","cmXIXtlILt","ZJTXHZUnqt","zY1GYpT8wu","0BmCyfLNg8","580YDqUJMd",
-"uZPqgyvOMI","RsQUqdpe1v","VIlwPIRh48","MK07Y5Drn0","zHF1qCp3mZ","16lHcSmGzv","lm0pDBbwgA","JIqXi8xEKz","a00b5ZzJHW","FnPFBlXFOB",
-"5NammfcJOy","YOfrYJJs5m","0KyfsHlUbF","i7WMQ45cIH","J2mQid85a9","uupzk5nmWv","FVMxoSWfou","4QMc9FjHXR","TwanoTCgPp","euZA5zbIYY",
-"h1zcH2ZHdk","D6rBy9eoRc","Gv3Fquvf7A","nFqikO3iyQ","DLhzMsuY4x","I7p2asoy9t","QworuWDVWJ","Ta8f6QWxoT","t98iWtuDyS","MmKGJbZLvS",
-"dhSuHwDajX","rz7Utd7vjM","uvf7A9eoRc","I7p2av2eC3","Q6hMCFFDui","UlU3M8hJdt","SbRYyogLgc","iB08l0MR5X","tjQxsGWqqX","QYxC0dmoS7",
-"L7cGcYw2oU","7X3uylH1kt","vOqCERmDcr","aFFssVBjhz","OUYuFWreyP","BGaQYjfREu","t59lRZhwG1","RmDcrHP433","IKxdLcmXIX","hE1QlmX2GE",
-"JIqXi5VZjS","Zv7z05iGN5","oQ87rhUTw7","aDGtSlpF6W","t59lRWreyP","pmeCdI7p2a","C2IrcAkKTk","sqVrfIKxdL","55rfBlkMUA","hi5X7oVQp6",
-"hE1QlyofH3","WreyPmX2GE","AmdQdDG4sT","fcwDaEoToP","ZJTXHatef2","WMiS3iKqhr","AkKTkQssNC","nnP8ocQOnv","IKxdLPOUYS","SmGzvpvgjS",
-"FVMxoXflUq","AIYUuPYBf4","cmXIXO3iyQ","cmXIXjSjS3","07n1cCxVEf","hE1QlJXljW","iwzGkKZamH","MaJQsXflUq","8RCUAnFqik","y94nwKASQ8",
-"jfREuQbxXc","8hJdtCfgr3","1j5L8OHaBz","lkMUAXyPZN","cQOnvVLTy6","e6e4zaDGtS","uAWypFGzgp","QworupiJSk","blLA9jS1aj","fFDrJuPX7G",
-"KASQ8WreyP","fcJOyQClRL","9iGoT7Ow5C","TXQ0Z0h1b1","yEfy9yvOMI","FjHXRGv3Fq","jfREuzFgtB","lm0pDEOE1o","RsQUqjiVBP","l83Udh1zcH",
-"4QMc929QAz","Cfgr3zFgtB","BpYhVrz7Ut","zY1GYXflUq","VNCPdRzaZA","2ZHdkDQimp","Mm8siyvOMI","MGlTFHRxd8","KASQ8fFDrJ","JKWYRHP433",
-"FnPFBHzZT8","0ao3lpmeCd","vkCHHFPfSE","CK5W7Gv3Fq","0Wr5yMaJQs","AIYUucQOnv","618DiuJScX","lH1ktIn3NS","8FmFH0Kyfs","soy9tpmeCd",
-"IKxdLYjB9t","GSQwjqQxHP","StlDJNcICA","X6PinFVMxo","QChxs4QMc9","JXljW8RCUA","9rlg9ix74r","zbIYYd7vjM","ogLgczY1GY","3weIFDcpWB",
-"XyPZN2hEEU","KsjRKuLtKs","aez9yciuWz","zz4ZU8xEKz","MmsIo9rlg9","uupzkRxrsm","Q6Lix618Di","b29RJYh1hF","Zv7z0AmdQd","bZLvS9GXkX",
-"uupzk4dEz6","SjskQrhl0J","QnJ1SUl4a1","yofH3O3iyQ","gjUTu55rfB","CqqaD4W0Tl","tuDySiKqhr","9rlg9NOHsz","ciuWzZzJHW","5Mg9rIjTwP",
-"5IhmGdmoS7","IBe8kmz8gx","0h1b1K4GS8","fqypyuZPqg","okgRik85Ae","YOfrYM6qcG","ciuWzQWxoT","48cHLZJTXH","1v5hHbrhlQ","uLtKsfaHir",
-"ogLgcfFDrJ","RmDcruPX7G","TXQ0ZoGu6x","tlILtGXdoH","VIlwPjfREu","sqVrfGWqqX","oQ87r9XyT9","BGaQYl83Ud","KASQ8JRJQB","SjskQx3LDe",
-"CqqaDh1zcH","NAFuwtuDyS","JJs5mJXljW","K4GS8lkMUA","5VZjS2Yz7E","9iGoTwDajX","atef2FNYIM","5Namm8xEKz","GWqqXlm0pD","IRh486q6L9",
-"zFgtB64s8N","JJs5mtlILt","QYxC0cShY2","fFDrJyofH3","lViBvXflUq","CNHmv1j5L8","UmaEvHfyNQ","I7p2a4QMc9","a00b5Q6hMC","VNCPduZPqg",
-"JKWYRb29RJ","v1HlnZzJHW","ECMvUhSSvQ","cShY2vLsmS","lCMxyi3pyd","MmKGJOUqFM","blLA92TRI7","7ku1pRsQUq","mz8gxfLNg8","IjTwPCdyBV",
-"CqqaD8hJdt","I7p2avOqCE","OUYuFa00b5","Yw2oU8cVD3","HRxd8FFDui","ECMvUThjNn","s93MlgjUTu","lH1ktprNT6","AIYUuVBjhz","ZJTXHUl4a1",
-"pmeCdJkzUn","9rlg9d7vjM","Nxx9Vzz4ZU","rz7Ut7Ow5C","Chuy37fKYU","7Ow5CaDGtS","uvf7AFNYIM","Gv3FqOxWIH","D6rByh1zcH","HlUbFXyPZN",
-"d7vjMD6rBy","TCgPplkMUA","M6qcG3weIF","POUYSydG8U","uPX7Giqv4k","uN6r3jzUqR","GSQwjhE1Ql","LewvMogLgc","ix74rpmeCd","fqypyl83Ud",
-"2hEEUk85Ae","OxWIHpAhR1","8xEKzRACuj","AkKTkyvOMI","Cfgr3ZuDtD","gf8rIZJTXH","Cfgr3fqypy","Oz8yZ2hEEU","uLtKsGXdoH","ZuDtD9XyT9",
-"ZUnqtcShY2","jiVBPPOUYS","IKxdLJ2mQi","5Mg9rv8yFN","7fKYUl83Ud","8FmFHYf2Ec","Kr8ysAgJHQ","5drc6pmeCd","uLtKsFVMxo","2ZHdkfcJOy",
-"brhlQAIYUu","a00b5ogLgc","LbRTHxXTI4","FVMxo8U2nU","KZamH8cVD3","AOgEe24ARF","fLNg82Nslm","IBe8kECMvU","oQ87rMojnP","lweGyYh1hF",
-"uLtKsWMiS3","cQOnvvOqCE","DcpWBeuZA5","VNCPdUl4a1","rhl0J24ARF","fcwDav1Hln","gf8rISmGzv","brhlQix74r","4W0TlTCgPp","mz8gxAmdQd",
-"K4GS8pmeCd","UlU3MoQ87r","i3pyd7ku1p","580YDlViBv","5VZjSKsjRK","cShY2jzUqR","cQOnvX6Pin","WreyPzFgtB","MaJQslm0pD","m4bxUqaofN",
-"o8UydSbRYy","sx5GlmX2GE","iqv4kCNHmv","nnP8oQChxs","bgJAzqUJMd","guMb8dQ586","rz7UtzY1GY","DQimpuPX7G","FPfSEIBe8k","YjB9tK20wK",
-"cL0aE5drc6","C2Ircdpe1v","AXpwE16lHc","5drc6ru4UG","aL6AJSbRYy","jzUqRAgJHQ","ThjNnM3zXL","a00b5Yf2Ec","ni2v1e6e4z","pvgjSRpBQm",
-"0PktIazIWp","faHirCdyBV","JkzUnFnPFB","VerEAn8pJ9","5nmWvFnPFB","piJSkC2Irc","QssNCFnPFB","uLtKsuoStw","HRxd84W0Tl","QClRLSbRYy",
-"8FmFHdmoS7","64s8N07n1c","Waim6ZhwG1","64s8NRsQUq","lj07QKsjRK","S2DfueuZA5","t59lRZv7z0","No0QbGSQwj","6q6L9NhXdu","5ZaEzI7p2a",
-"7fKYUFPfSE","M3zXLxReec","n8pJ9pAhR1","RzaZAQnJ1S","7hyVvRzaZA","9rlg9m4bxU","BCxeC4QMc9","4W0Tl8xEKz","uZPqgJJs5m","45cIHbrhlQ",
-"Ta8f6CNHmv","pAhR1taOXK","0BmCyMezSW","Vprf2RkQke","m4bxUs93Ml","jSjS38hJdt","StlDJJkzUn","qQxHPiwzGk","jtn0XNo0Qb","IjTwPCIShG",
-"pvgjSQWxoT","24ARFsoy9t","RBhp0jiVBP","hE1QlZJTXH","Gv3Fqsx5Gl","1j5L8VLTy6","CIShGfcwDa","gtCA5VNCPd","7Ow5CW7cTs","yluBxOxWIH",
-"FFDuiqUJMd","QYxC0jfREu","k85AeCNHmv","yluBxogLgc","55rfBlpF6W","Cfgr3tl72W","CqqaDXflUq","MojnPdpe1v","nlaByZv7z0","fFDrJ0YAGH",
-"tAOsrhi5X7","WreyPni2v1","fmIK129QAz","ix74r64s8N","HfyNQ0h1b1","5drc6FPfSE","pmeCd7Ow5C","ksJbywiHrZ","lCMxygjUTu","VNCPdReKEW",
-"9iGoT5Drn0","gf8rIgtCA5","LewvMYjB9t","gtCA5GXdoH","9iGoTdQ586","6AFT0KsjRK","euZA5kZANm","QnJ1S1LB1L","yvOMIxReec","JJs5muoStw",
-"618DiwDajX","Yf2EcEoToP","dmoS7iKqhr","14FLRNhXdu","wDajXfqypy","n1pmO3weIF","o8UydaFFss","Uvlv4ZJTXH","29QAzfcJOy","MK07YQYxC0",
-"O3iyQ4W0Tl","lCMxyMmsIo","OUYuFRzaZA","aL6AJblLA9","OUYuFVprf2","lsQGoW7cTs","8cVD3EdBKc","MojnPtAOsr","HlUbFni2v1","L7cGcsoy9t",
-"jSjS3taOXK","FLsphuvf7A","BFkb8JXljW","s7Mxk7lUXZ","rhl0J1j5L8","mz8gxtaOXK","VIlwPMGlTF","5VZjSSjskQ","MGlTFMkgy8","IKxdL0YAGH",
-"guMb8suY4x","qaofNydG8U","C2Irc580YD","07n1cnnP8o","VjCZqSjskQ","In3NSpFrrl","SbRYyMkgy8","o8Uyduupzk","yofH3EoToP","GSQwjjfREu",
-"NOHszUlU3M","I7p2acQOnv","nlaByRxrsm","I7p2afqypy","BCxeCmX2GE","Kr8ysPOUYS","8FmFHWMiS3","vkCHHuTacx","h1zcHJJs5m","DQimpFhtgl",
-"M6qcGpmeCd","piJSk8U2nU","9eoRcK20wK","KsjRKlm0pD","t98iW0BmCy","blLA9AkKTk","taOXKKASQ8","MaJQshi5X7","6AFT0BbwgA","Ta8f6yvOMI",
-"07n1chE1Ql","oVQp65iGN5","mz8gxRmDcr","CqqaD29QAz","FjHXRK20wK","I7p2aHRxd8","FPfSElViBv","LbRTHh1zcH","DLhzMt59lR","W7cTszmLYD",
-"8U2nU24ARF","9XyT9580YD","CIShGFFDui","RACujKsjRK","fcwDax3LDe","Mkgy85VZjS","jiVBP7fsYM","VNCPd5ZaEz","9eoRcMK07Y","v8yFNoVQp6",
-"oVQp6pv0i7","KASQ8h1zcH","iKqhrpvgjS","UmaEvprNT6","wDajXAmdQd","FFDuiAgJHQ","zbIYYFPfSE","48cHLaFFss","FwEJzBCxeC","0KyfsblLA9",
-"tuDyS5nmWv","In3NSPb1pa","xciqplj07Q","X6PinzbIYY","AXpwEd7vjM","RsQUqnlaBy","AOgEe9rlg9","GrDg7lH1kt","O3iyQQChxs","Yw2oU48cHL",
-"X6Pink85Ae","yToGWyvOMI","4dEz62Nslm","0KyfsjzUqR","ydG8UiwzGk","NhXduVjCZq","0Wr5yfqypy","GSQwjoGu6x","suY4xdpe1v","XyPZN580YD",
-"iKqhrl83Ud","64s8NpiJSk","uTacx7Ow5C","16lHctaOXK","AmdQdRxrsm","jfREuMmKGJ","oVQp6ZuDtD","WDVWJFLsph","14FLRK20wK","atef2ThjNn",
-"QClRLQYxC0","xciqpWaim6","VjCZqzFgtB","0ao3lM6qcG","qQxHPUl4a1","FnPFBxXTI4","6q6L9I7p2a","dmoS7oQ87r","CxVEfL7cGc","G1RhSY1mC0",
-"fFDrJIn3NS","xReecrhl0J","piJSkQYxC0","64s8N7Ow5C","nFqikRxrsm","nnP8oFFDui","P6bcg7Ow5C","QssNCuvf7A","okgRi9y4lw","DG4sTWaWsv",
-"cmXIXbZLvS","IBe8kFxX9q","Oz8yZFFDui","oQ87rVNCPd","n1pmOhYBCK","LewvMfLNg8","0ao3lUlU3M","i7WMQt98iW","RmDcrjiVBP","CxVEfxReec",
-"CdyBVhE1Ql","tlILtDQimp","M6qcG0Kyfs","tl72WNo0Qb","AkKTkMmKGJ","xXTI4d85a9","48cHLCxVEf","29QAzuLtKs","8cVD3Z4I1v","iB08lVLTy6",
-"K4GS8BGaQY","QbxXcCxVEf","jS1ajzbIYY","RzaZAHlUbF","d85a9s4786","Nxx9VzmLYD","zY1GYl83Ud","MK07YVLTy6","yluBxQWxoT","vLsmSAkKTk",
-"KZamHvLsmS","iwzGkv1Hln","WDVWJCqqaD","8xEKzWPmlx","OUqFMLewvM","618Di0Kyfs","JIqXilm0pD","s7MxkThjNn","JkzUnulk41","djsrvd85a9",
-"tjQxsyluBx","7fKYUnFqik","piJSk9iGoT","Mm8siRpBQm","MmsIo8U2nU","DQimpfmIK1","ni2v1DLhzM","0PktIQworu","45cIHd7vjM","7fKYU8U2nU",
-"QssNCjSjS3","AmdQd0ao3l","FwEJzn1pmO","xReecCNHmv","jtn0Xi3pyd","RACujsx5Gl","oGu6xFxX9q","oGu6xStlDJ","7fKYUjS1aj","JIqXiNOHsz",
-"Q6LixjzUqR","suY4x5Drn0","AgJHQ5Namm","ogLgc16lHc","uAWyphYBCK","Z4I1vguMb8","kZANmtlILt","EOE1o5IhmG","AgJHQWaim6","2ZHdkMK07Y",
-"uQIcz55rfB","POUYSO3iyQ","VLTy6FjHXR","7fKYU29QAz","lViBv6q6L9","OxWIHjS1aj","Y1mC0GXdoH","WaWsvMmsIo","S2DfuNOHsz","CNHmvt59lR",
-"aFFss2hEEU","fmIK1Cfgr3","Ul4a1BGaQY","uN6r324ARF","yEfy9vLsmS","IBe8k45cIH","pT8wu9eoRc","zmLYD1v5hH","Y1mC0UlU3M","jfREulkMUA",
-"In3NSuvf7A","jiVBP4dEz6","YjB9tl83Ud","WmadADLhzM","9iGoTAOgEe","lpF6WJKWYR","4W0TlpWiOs","DG4sTvOqCE","qaofNWaWsv","HfyNQJRJQB",
-"XyPZNSWfou","lm0pD7fsYM","AIYUuX6Pin","SWfourz7Ut","tvdkDZuDtD","9GXkXSjskQ","okgRih1zcH","fFDrJuQIcz","vkCHHlCMxy","5IhmGgjUTu",
-"zY1GYAgJHQ","DG4sTOUYuF","fmIK1iqv4k","FwEJz5Mg9r","i3pydOUYuF","zmLYDyluBx","Mkgy8AXpwE","e6e4z5Namm","blLA95IhmG","zFgtBlH1kt",
-"WmadASmGzv","GSQwjIjTwP","Uvlv4HzZT8","jtn0XcQOnv","0Wr5yzFgtB","1j5L8P6bcg","sx5GluPX7G","JXljW64s8N","FLsph2ZHdk","NhXduyofH3",
-"l83UdxReec","d85a9v8yFN","i7WMQjfREu","5drc6he9IA","tlILtnlaBy","7fKYUIn3NS","ZuDtDRzaZA","d85a945cIH","hSSvQ9rlg9","n1pmOJIqXi",
-"BFkb8v2eC3","Yw2oUKsjRK","5IhmG5iGN5","14FLRiB08l","FGzgpUmaEv","v1HlnpWiOs","qaofNyvOMI","uLtKs4W0Tl","QClRLFVMxo","aez9yydG8U",
-"GrDg7mX2GE","POUYSdhSuH","ix74rbrhlQ","soy9tjS1aj","2NslmksJby","2ZHdkB3qem","2ZHdkbZLvS","pFrrlWMiS3","fFDrJJ2mQi","J2mQiJRJQB",
-"nlaByydG8U","nlaByYOfrY","atef2UlU3M","5Mg9rprNT6","7fKYUFjHXR","MK07Y5Mg9r","gjUTuDQimp","lpF6W7ku1p","JRJQBFFDui","RkQkeSWfou",
-"n8pJ9GSQwj","fFDrJ5drc6","uvf7AS2Dfu","uPX7GCp3mZ","uvf7A3otm6","oVQp6Chuy3","5ZaEzCqqaD","2DREs0BmCy","TwanoiKqhr","zFgtBoGu6x",
-"tl72WnnP8o","nnP8ooGu6x","J2mQiQChxs","RmDcrd7vjM","hi5X7ZJTXH","lkMUA2hEEU","aDGtSgdQsS","Pb1pauoStw","CNHmvFGzgp","WreyPVNCPd",
-"VIlwPlweGy","dhSuHprNT6","lpF6WWMiS3","t98iWmX2GE","L7cGcmX2GE","CqqaDnlaBy","mz8gx5nmWv","lCMxyQbxXc","MmsIoWreyP","WmadAAgJHQ",
-"OHaBzAgJHQ","Z4I1vM3zXL","ciuWz9iGoT","lsQGoOz8yZ","tjQxsv2eC3","okgRiRACuj","EOE1oVjCZq","7fKYUi3pyd","vkCHHChuy3","djsrvhUTw7",
-"b29RJRACuj","y94nwFjHXR","OUqFMfcJOy","atef2taOXK","JkzUnmX2GE","IRh48jSjS3","gIYvEW3VFH","uTacxzqH0W","4QMc945cIH","2NslmOUqFM",
-"FnPFBQ6Lix","RpBQmGrDg7","e6e4zFnPFB","5ZaEzStlDJ","gdQsS8FmFH","FFDuiStlDJ","2ZHdkAgJHQ","Dz1R3uPX7G","580YDYf2Ec","NAFuwpAhR1",
-"LDk6fU3yw5","a00b55VZjS","jfREu1LB1L","NAFuwYw2oU","W3VFHWDVWJ","RsQUqxXTI4","1v5hHJJs5m","No0QbReKEW","55rfBuoStw","G1RhS14FLR",
-"UmaEvv8yFN","F6PT2DQimp","ksJbygjUTu","Dz1R32hEEU","aez9ywDajX","HP4335drc6","tAOsrs93Ml","iB08lMmsIo","LDk6fwiHrZ","M3zXLjiVBP",
-"Chuy39eoRc","cL0aEHRxd8","x3LDedQ586","xciqps93Ml","ksJbyCdyBV","TXQ0ZOHaBz","G1RhSKASQ8","2DREsUl4a1","d7vjMjSjS3","X6PinLewvM",
-"a00b5azIWp","0MR5XSjskQ","IjTwP64s8N","uLtKsix74r","J2mQiIjTwP","h1zcHxXTI4","IKxdLMK07Y","m4bxUVprf2","14FLRPOUYS","RsQUqs4786",
-"OxWIHZUnqt","iqv4k5ZaEz","sqVrffLNg8","MK07YAmdQd","dpe1vd7vjM","tl72Wlm0pD","aDGtSvLsmS","0ao3lKZamH","lViBvCxVEf","guMb8MmKGJ",
-"2DREsVprf2","fmIK1ogLgc","55rfBbZLvS","Yf2EcThjNn","ECMvUlViBv","VjCZqChuy3","WaWsvMmKGJ","cShY2Oz8yZ","CqqaD5VZjS","DcpWBOUYuF",
-"jSjS30h1b1","618Diaez9y","jiVBPBpYhV","jiVBPo8Uyd","O3iyQjtn0X","S77LH6AFT0","Uvlv4tuDyS","hE1Ql5drc6","AkKTkLbRTH","rhl0JVLTy6",
-"vOqCEiKqhr","cL0aEZ4I1v","lXFOB8xEKz","Chuy3In3NS","LbRTHFVMxo","RkQkeSs0Zu","WDVWJfFDrJ","fLNg8S2Dfu","YOfrYvkCHH","DLhzM6q6L9",
-"MmsIoJRJQB","e6e4z1v5hH","MaJQs618Di","xciqpFnPFB","yofH3Pb1pa","1j5L8SbRYy","IRh48RBhp0","Vprf2taOXK","guMb8nlaBy","U3yw52Nslm",
-"jtn0XOz8yZ","zbIYYJKWYR","rz7UtWaWsv","fqypy6AFT0","wiHrZNAFuw","2hEEUM6qcG","WMiS3azIWp","jtn0XRpBQm","HP433fcJOy","zz4ZUcmXIX",
-"Y1mC0Mm8si","NhXdu7fKYU","HlUbFW3VFH","0ao3lThjNn","pmeCduQIcz","ydG8UCp3mZ","MaJQsBbwgA","s47864QMc9","J2mQiOUqFM","blLA914FLR",
-"G1RhSs4786","5ZaEzFnPFB","Waim6AXpwE","NAFuwb29RJ","VNCPdYjB9t","ZhwG1lm0pD","yluBxRmDcr","FxX9qlViBv","45cIHiqv4k","0ao3lpv0i7",
-"3weIFSWfou","BGaQY8RCUA","d85a9WPmlx","4W0Tl2TRI7","ciuWzcShY2","Yh1hFNcICA","oQ87rKZamH","0ao3lYh1hF","Pb1paThjNn","iB08l8xEKz",
-"vOqCEBFkb8","AXpwEZhwG1","W7cTsAmdQd","pFrrl0Wr5y","8hJdtWreyP","RmDcrs4786","K20wKTa8f6","VjCZq7ku1p","jiVBPlkMUA","uN6r35Mg9r",
-"zmLYDb29RJ","WaWsvRACuj","PYBf48RCUA","b29RJe6e4z","hi5X78FmFH","TXQ0ZydG8U","Gv3FqbrhlQ","s93MlRkQke","wiHrZ29QAz","qaofNjtn0X",
-"RkQkeni2v1","ulk410PktI","v1HlnwiHrZ","taOXK2TRI7","EOE1oJXljW","DQimpAkKTk","QbxXc7hyVv","o8UydcmXIX","lpF6Wrz7Ut","lsQGoPYBf4",
-"Cp3mZTwano","9GXkXDG4sT","VLTy69y4lw","WmadAatef2","DLhzMpT8wu","Uvlv4WMiS3","FPfSEAgJHQ","t98iW2Nslm","4W0Tl5VZjS","SmGzvCIShG",
-"SmGzvv2eC3","RACujX6Pin","jS1aj4dEz6","ReKEWFVMxo","ECMvUJKWYR","RzaZAChuy3","s93Mlix74r","cmXIXOxWIH","o8UydOUqFM","ni2v1VIlwP",
-"QworuQWxoT","RmDcryofH3","KASQ8okgRi","RBhp0fqypy","MojnPbZLvS","fFDrJHlUbF","3weIFlViBv","yluBx0h1b1","zmLYDgIYvE","Yw2oUYw2oU",
-"uQIczWaWsv","2TRI7OUqFM","uAWypb29RJ","CqqaDsuY4x","aFFssAgJHQ","OUYuFbrhlQ","JXljWaL6AJ","NhXduiB08l","FcWrWgIYvE","0KyfsRsQUq",
-"tvdkDWmadA","blLA9fmIK1","qQxHPoVQp6","zbIYYDQimp","rz7UtAkKTk","e6e4zgjUTu","ulk41jzUqR","Mm8sio8Uyd","guMb84W0Tl","FjHXRYh1hF",
-"h1zcHGWqqX","hi5X7rz7Ut","cmXIXKZamH","vLsmSuupzk","G1RhSBGaQY","o8Uyd2hEEU","gIYvEBbwgA","v8yFN8xEKz","aez9ySjskQ","mz8gx8U2nU",
-"7ku1p8FmFH","taOXKvLsmS","yToGW0BmCy","cL0aEAkKTk","gtCA5iKqhr","SmGzvYjB9t","64s8NjS1aj","F6PT2IKxdL","euZA5HfyNQ","jzUqRFwEJz",
-"IBe8kvkCHH","zmLYDrhl0J","KsjRKpT8wu","8FmFHDz1R3","y94nw3otm6","580YD0h1b1","MGlTFx3LDe","B3qemhUTw7","JXljWv1Hln","HfyNQ45cIH",
-"DG4sTM6qcG","tjQxsCqqaD","0Wr5y2hEEU","he9IAokgRi","TwanocL0aE","9eoRcSmGzv","lH1ktVprf2","YjB9t6AFT0","W7cTsIjTwP","azIWp6AFT0",
-"D6rBy9rlg9","GSQwj0Wr5y","nlaByd85a9","hYBCKjS1aj","x3LDemz8gx","qQxHPFNYIM","hUTw7FwEJz","pmeCdRxrsm","gtCA5a00b5","QYxC0qUJMd",
-"S2DfuYjB9t","yluBxFGzgp","Gv3FqDz1R3","iB08lmX2GE","9GXkX5nmWv","yvOMI0Kyfs","IjTwPt98iW","9eoRcM3zXL","WDVWJ29QAz","1j5L8xReec",
-"ix74r0YAGH","55rfBRpBQm","aFFssKsjRK","cmXIXsx5Gl","qQxHPAXpwE","RkQkepmeCd","24ARF8cVD3","aFFssRkQke","0h1b148cHL","tvdkDM6qcG",
-"7ku1pW3VFH","Q6hMCRsQUq","azIWpX6Pin","uPX7Guupzk","yvOMIJ2mQi","Ta8f6MaJQs","Uvlv4iwzGk","m4bxUNcICA","J2mQiokgRi","HfyNQhUTw7",
-"IBe8kWPmlx","hYBCKOUqFM","fqypyKsjRK","LewvMGXdoH","i3pydzmLYD","FVMxoO3iyQ","uPX7GAOgEe","ZUnqtyEfy9","BGaQY4QMc9","MGlTF5ZaEz",
-"JkzUnlpF6W","ru4UG5Namm","OHaBzTwano","vLsmSaez9y","U3yw5QClRL","he9IAeuZA5","AkKTkogLgc","uTacxzbIYY","F6PT2n1pmO","7X3uyuZPqg",
-"7Ow5CuAWyp","3otm6Yh1hF","qaofN2Nslm","v1Hln5ZaEz","Uvlv4brhlQ","CK5W7lH1kt","jzUqRaez9y","Yw2oUciuWz","4dEz67Ow5C","hi5X7CK5W7",
-"uLtKs5drc6","ZUnqtjzUqR","45cIH1v5hH","8cVD3prNT6","AkKTkfLNg8","FFDuiyluBx","Mm8sijeskS","FPfSExXTI4","pvgjSFhtgl","dQ586SbRYy",
-"t59lRrz7Ut","tAOsr5iGN5","uoStwMojnP","rhl0JJXljW","piJSkHlUbF","PYBf44W0Tl","QWxoTJJs5m","NcICAZhwG1","Ul4a1FwEJz","7ku1pqUJMd",
-"BGaQYfmIK1","HzZT8KsjRK","yofH3oQ87r","aDGtSiB08l","MezSWcmXIX","ksJbyogLgc","jzUqRPb1pa","lsQGox3LDe","MmKGJ8TxD7","LewvM7Ow5C",
-"qQxHP7lUXZ","8U2nUJRJQB","FLsphuoStw","Mm8sioVQp6","FhtglKsjRK","VLTy6fcwDa","jtn0XOUqFM","RBhp0fcwDa","XflUqoGu6x","C2IrcxXTI4",
-"s7Mxkpv0i7","64s8NWDVWJ","gtCA5K20wK","9y4lwuZPqg","FFDuitlILt","2hEEUK20wK","MmsIoHzZT8","vLsmSFPfSE","J2mQiKASQ8","iB08lPYBf4",
-"dmoS70ao3l","tjQxsl83Ud","5iGN5hSSvQ","OHaBzCK5W7","FxX9qyToGW","dhSuHQChxs","yofH3bZLvS","piJSk3weIF","Yh1hFGv3Fq","pv0i7ydG8U",
-"AOgEeAkKTk","cL0aEGSQwj","lXFOBS77LH","POUYS45cIH","ni2v1RBhp0","7hyVvkB5nP","MezSWrKDLJ","zbIYYfmIK1","OUYuFIn3NS","sqVrf580YD",
-"uQIczFLsph","tl72WMojnP","Dz1R3dhSuH","ulk41C2Irc","sqVrfYf2Ec","jSjS31j5L8","lpF6WlViBv","pWiOsulk41","Rxrsm3weIF","zQt6Q3otm6",
-"Nxx9Viqv4k","h1zcH7hyVv","FwEJzRsQUq","JkzUnLDk6f","5VZjSAgJHQ","8RCUAMmKGJ","QworuGWqqX","ydG8UB3qem","hi5X7pvgjS","RmDcrXflUq",
-"nnP8ouJScX","vkCHHKASQ8","TXQ0ZNcICA","AmdQd3otm6","aez9yqaofN","oVQp6EoToP","qaofNqQxHP","9GXkX5drc6","0ao3ls93Ml","djsrvpT8wu",
-"9iGoTogLgc","5NammVerEA","zz4ZUWPmlx","mX2GEuvf7A","TCgPpIKxdL","azIWpO3iyQ","RzaZAn8pJ9","uvf7AuN6r3","G1RhSRACuj","MK07YrKDLJ",
-"Yh1hFogLgc","P6bcgrz7Ut","cQOnvaDGtS","nnP8otjQxs","WreyPOUqFM","Cfgr3brhlQ","6q6L90MR5X","uTacx5iGN5","FLsphzbIYY","tuDySzFgtB",
-"d7vjMpvgjS","jSjS3iKqhr","B3qemkB5nP","0Wr5yhYBCK","jzUqRix74r","OUqFMmz8gx","GWqqXAIYUu","ydG8U4W0Tl","lpF6Wlm0pD","8TxD7VNCPd",
-"fFDrJGWqqX","Waim6ksJby","pv0i7o8Uyd","fFDrJd7vjM","he9IAF6PT2","tlILtaFFss","lXFOB3otm6","FPfSEpAhR1","RBhp01v5hH","QworuNcICA",
-"YOfrYtl72W","DQimplViBv","tjQxsZzJHW","CdyBVb29RJ","a00b5t59lR","VLTy68hJdt","5nmWvIjTwP","uAWypFnPFB","NhXdu5ZaEz","fcwDaIKxdL",
-"Zv7z0CNHmv","4dEz6ru4UG","hYBCKuupzk","zbIYYYf2Ec","hSSvQEOE1o","pmeCdWreyP","s93MlRmDcr","zFgtBNhXdu","AgJHQCqqaD","soy9tZhwG1",
-"lsQGo0PktI","0Wr5yDcpWB","6AFT0QWxoT","VLTy6yToGW","uJScXGrDg7","iB08lFPfSE","FPfSE0MR5X","AXpwEs7Mxk","iwzGkWDVWJ","0BmCyDQimp",
-"BbwgA3weIF","2DREsMmKGJ","MezSWW7cTs","i3pydYh1hF","X6PinCqqaD","jzUqRMGlTF","azIWpIjTwP","JIqXizbIYY","4QMc96q6L9","FGzgpdpe1v",
-"aez9yhE1Ql","580YDQClRL","AgJHQ7ku1p","DLhzM0Wr5y","5nmWvCK5W7","cShY2he9IA","1j5L80BmCy","RsQUqFcWrW","Vprf2Z4I1v","5drc6VerEA",
-"guMb8zz4ZU","dQ586jfREu","h1zcHDQimp","n8pJ9HlUbF","fqypyoGu6x","Ta8f614FLR","wiHrZW3VFH","DcpWB0h1b1","uZPqgFNYIM","jfREuBbwgA",
-"5VZjSCIShG","tuDySRmDcr","5nmWvSbRYy","MojnPgIYvE","ZhwG155rfB","s93Ml5Namm","FVMxo2hEEU","K4GS8UmaEv","mz8gxU3yw5","EOE1otvdkD",
-"NAFuwtvdkD","ix74r0MR5X","blLA9ciuWz","fmIK1WmadA","n1pmOtAOsr","9eoRcfmIK1","MGlTFaL6AJ","pT8wuQYxC0","BCxeCDQimp","pvgjSCK5W7",
-"7fKYU16lHc","2Yz7ETCgPp","d7vjMcQOnv","JkzUnh1zcH","Zv7z0Oz8yZ","JkzUnIRh48","jiVBPwiHrZ","IBe8kpmeCd","SmGzv618Di","0ao3l8RCUA",
-"5drc68cVD3","Nxx9VRzaZA","zFgtBQ6Lix","lViBve6e4z","07n1cpWiOs","LewvMOUYuF","5Drn0kZANm","FFDui24ARF","9rlg9aL6AJ","9iGoT2Nslm",
-"SbRYylH1kt","No0QblCMxy","Chuy3n8pJ9","SjskQOHaBz","5Namm4dEz6","kZANmulk41","MGlTFCp3mZ","pWiOsfqypy","EoToPdpe1v","lj07QCxVEf",
-"0BmCylH1kt","IjTwPlViBv","M3zXLDQimp","StlDJsqVrf","8xEKzGSQwj","pWiOsvLsmS","fFDrJ7X3uy","Yf2Ec5ZaEz","fmIK1VerEA","gtCA5Cp3mZ",
-"Kr8ys2Nslm","5IhmGlm0pD","tlILtUlU3M","YjB9tsx5Gl","gIYvEFhtgl","qUJMd2Nslm","HfyNQNo0Qb","yluBx5drc6","Mkgy8lViBv","pFrrlhE1Ql",
-"zbIYYCp3mZ","X6Pint59lR","gf8rIdhSuH","uvf7AqUJMd","5nmWv8FmFH","YOfrY7fKYU","QbxXcHP433","e6e4z5nmWv","dmoS7zbIYY","qaofNJIqXi",
-"4dEz6qUJMd","7hyVvOxWIH","pmeCdfLNg8","C2IrcB3qem","Zv7z0FnPFB","djsrveuZA5","4QMc97X3uy","okgRi2TRI7","bZLvSSWfou","atef2pT8wu",
-"MezSWe6e4z","iwzGkIKxdL","QnJ1SfcwDa","dQ586Oz8yZ","DG4sTQClRL","K4GS8GXdoH","iqv4kdQ586","IRh48euZA5","Mkgy8POUYS","JKWYRFNYIM",
-"yToGWRxrsm","AXpwEThjNn","7fsYMIjTwP","BGaQYuLtKs","I7p2aJKWYR","s7MxkNhXdu","hYBCKn8pJ9","0ao3lWPmlx","VjCZqIjTwP","6q6L9WPmlx",
-"vkCHHMezSW","MaJQsyEfy9","8TxD7gdQsS","C2IrcFLsph","MmsIobrhlQ","HfyNQl83Ud","AIYUuWPmlx","EdBKczz4ZU","QnJ1SciuWz","iKqhrb29RJ",
-"Q6LixpWiOs","WMiS3Yf2Ec","RkQkevLsmS","7Ow5C7X3uy","WmadAGXdoH","iqv4k0YAGH","RACujSjskQ","ZzJHWYh1hF","Chuy3YjB9t","7ku1puPX7G",
-"2Yz7E4QMc9","5NammFcWrW","uPX7GRACuj","zHF1qqQxHP","FVMxouAWyp","euZA5LDk6f","KASQ8l83Ud","zHF1qdjsrv","ix74rcL0aE","AmdQdpiJSk",
-"qaofNzbIYY","EOE1oaez9y","Zv7z0ix74r","WMiS3jzUqR","qaofNB3qem","tuDySJRJQB","LewvMgtCA5","VjCZqQworu","POUYSfqypy","8RCUAv8yFN",
-"4W0TlLDk6f","lXFOB5Namm","GrDg7RACuj","24ARFjiVBP","v8yFNKr8ys","SjskQyEfy9","618DiUl4a1","uTacxuTacx","i7WMQeuZA5","piJSksoy9t",
-"nFqika00b5","pAhR1xReec","5NammAXpwE","bZLvSyToGW","yluBxSmGzv","NhXduazIWp","xciqpokgRi","W3VFH5IhmG","rz7UtuN6r3","5iGN5HfyNQ",
-"nlaBy9eoRc","JKWYRkZANm","pAhR1zY1GY","yvOMImX2GE","16lHcOUYuF","Ta8f6qUJMd","Pb1pasoy9t","ru4UGksJby","zY1GYdjsrv","24ARFU3yw5",
-"XflUquN6r3","jtn0XokgRi","ni2v1GSQwj","yvOMItaOXK","QWxoThSSvQ","rKDLJ2Nslm","cmXIXfFDrJ","i7WMQzY1GY","SmGzvVLTy6","QClRLwiHrZ",
-"lXFOBVIlwP","OUqFMYjB9t","FnPFBDQimp","yvOMIlweGy","DcpWB5nmWv","5Drn0ulk41","Cp3mZyluBx","HlUbFv2eC3","SWfouMaJQs","s7MxklViBv",
-"16lHcbgJAz","Zv7z0v1Hln","i3pydTCgPp","JkzUnjfREu","4dEz6taOXK","ThjNnxciqp","gf8rIqUJMd","W3VFHSbRYy","WDVWJMkgy8","DcpWB5ZaEz",
-"QYxC00BmCy","ReKEWWaWsv","VLTy6GXdoH","WreyPJkzUn","XflUqKsjRK","cQOnvFNYIM","blLA97hyVv","OUYuFix74r","Q6hMClCMxy","n8pJ9FGzgp",
-"PYBf4BCxeC","9rlg9tlILt","hYBCKvOqCE","tvdkDF6PT2","dpe1vaFFss","wiHrZ2hEEU","pv0i7t98iW","Oz8yZfmIK1","WMiS32DREs","5iGN5yluBx",
-"jS1ajuLtKs","kB5nPBFkb8","jiVBP5IhmG","RxrsmTCgPp","FVMxobgJAz","U3yw5RsQUq","rz7UtksJby","JJs5m8hJdt","pT8wu0YAGH","Q6hMCd85a9",
-"5Namm9y4lw","D6rBytl72W","DcpWBlpF6W","7Ow5CECMvU","ZJTXHjtn0X","lj07QIRh48","LewvMuLtKs","QYxC0RBhp0","JRJQBQWxoT","Chuy3X6Pin",
-"prNT6UlU3M","TCgPpZ4I1v","aDGtS5Drn0","EOE1oSs0Zu","tjQxsv1Hln","FnPFBaL6AJ","nnP8oSbRYy","NcICAZuDtD","Waim6vOqCE","mX2GEL7cGc",
-"cShY2KZamH","Pb1pauupzk","RkQkecmXIX","ZuDtDD6rBy","IBe8kaFFss","9iGoTn8pJ9","ReKEW9GXkX","VLTy6NOHsz","s7MxkMezSW","5ZaEzFGzgp",
-"FnPFBtuDyS","JIqXihYBCK","Oz8yZOUYuF","SjskQhe9IA","cL0aEtAOsr","lViBvVLTy6","5Drn0MmsIo","jfREulpF6W","b29RJHfyNQ","xReecb29RJ",
-"o8UydpvgjS","a00b5GSQwj","dQ5866q6L9","yluBxDz1R3","uupzk5Mg9r","vkCHHFcWrW","zmLYDBCxeC","2Yz7EOUqFM","AmdQdCqqaD","RzaZAqUJMd",
-"3weIFhE1Ql","atef2s7Mxk","VIlwPhSSvQ","djsrvMm8si","8hJdttl72W","0Wr5yDLhzM","Chuy3piJSk","5nmWvC2Irc","mz8gxMezSW","JJs5mQYxC0",
-"16lHcni2v1","MmKGJS2Dfu","iqv4kFcWrW","Mkgy8s7Mxk","t98iWKr8ys","580YDRxrsm","v1Hlngf8rI","0Wr5yJRJQB","jfREuCK5W7","QssNCF6PT2",
-"cShY2AOgEe","0PktI0Kyfs","K20wK5IhmG","ZuDtDRmDcr","QYxC0K20wK","wiHrZulk41","SWfouv8yFN","tAOsrk85Ae","CK5W7fcJOy","GSQwj0PktI",
-"RkQkeyvOMI","AOgEeMmsIo","zbIYYvLsmS","v2eC3DQimp","he9IA5Mg9r","SjskQJXljW","lm0pD0h1b1","MmKGJnnP8o","5Mg9raL6AJ","VNCPdlkMUA",
-"7X3uyI7p2a","FLspht59lR","XyPZN3otm6","n8pJ9hUTw7","Nxx9VGrDg7","BbwgAHRxd8","xReecEOE1o","Q6hMCjtn0X","guMb8EOE1o","DQimpMezSW",
-"ydG8U3otm6","dpe1v4W0Tl","QssNC9rlg9","VIlwPZ4I1v","IjTwPksJby","LDk6fCNHmv","S2DfutuDyS","uupzkGSQwj","45cIHatef2","pWiOsS77LH",
-"1LB1LTa8f6","UmaEvSs0Zu","VLTy62TRI7","s7MxkaFFss","gjUTuQClRL","SbRYyCNHmv","QnJ1S618Di","L7cGcvkCHH","FxX9q5nmWv","Ul4a1fqypy",
-"cQOnvuN6r3","FLsph1v5hH","l83UdazIWp","hYBCKZuDtD","6q6L9pWiOs","Kr8ystlILt","hYBCKsqVrf","qUJMdtuDyS","hE1QlS2Dfu","FLsphjzUqR",
-"IKxdLiKqhr","uPX7GMGlTF","J2mQilm0pD","zHF1qHP433","AgJHQtuDyS","yvOMIsoy9t","Cp3mZFxX9q","DLhzMRxrsm","t98iWpiJSk","AIYUuzbIYY",
-"QYxC06AFT0","lpF6WDQimp","MmKGJ8U2nU","M6qcG9iGoT","Y1mC0oVQp6","YOfrYW7cTs","F6PT2h1zcH","qaofNVIlwP","kB5nPQbxXc","BbwgAm4bxU",
-"vkCHHksJby","jiVBPJRJQB","K20wK8cVD3","HzZT8BFkb8","ZUnqtAmdQd","1j5L8nnP8o","U3yw5vkCHH","FFDuiOHaBz","45cIHKr8ys","7ku1p3otm6",
-"xciqpBCxeC","HzZT8QnJ1S","pv0i7hYBCK","jfREu7fKYU","uPX7Gs4786","xXTI4nnP8o","nnP8oy94nw","zqH0WUvlv4","UmaEv9eoRc","WPmlx4QMc9",
-"ogLgc0h1b1","AkKTkI7p2a","EOE1oAOgEe","J2mQiFVMxo","IRh48he9IA","EdBKcMaJQs","EOE1o9rlg9","HfyNQLDk6f","pWiOsuAWyp","FPfSEeuZA5",
-"gf8rIv8yFN","DQimpSs0Zu","IBe8k5iGN5","zHF1q5Namm","AmdQdlkMUA","14FLRAXpwE","lCMxyTXQ0Z","CK5W7ThjNn","VBjhzn8pJ9","aez9y0h1b1",
-"8FmFHyToGW","jeskSBpYhV","GrDg7ogLgc","faHirQssNC","y94nwM6qcG","ZhwG1OUYuF","suY4x8FmFH","fcwDatjQxs","dQ586piJSk","iwzGks93Ml",
-"jS1ajECMvU","IRh48x3LDe","kZANmd7vjM","zbIYYFNYIM","Waim6i3pyd","FFDuiThjNn","vLsmSGv3Fq","pvgjS3otm6","8RCUAuupzk","cQOnv618Di",
-"tuDySuZPqg","fqypyjeskS","3weIFU3yw5","FjHXRWDVWJ","VjCZqW3VFH","pmeCdk85Ae","jS1ajDLhzM","X6PinW3VFH","KZamHX6Pin","Yw2oUThjNn",
-"WmadAU3yw5","55rfBrKDLJ","5iGN5RpBQm","Q6hMCix74r","jzUqRlViBv","5IhmG7hyVv","iqv4kx3LDe","kB5nPn1pmO","7ku1pi7WMQ","Gv3FqvLsmS",
-"7fsYMNo0Qb","a00b5i3pyd","OHaBzoVQp6","WmadAUmaEv","DQimpsoy9t","MezSWoGu6x","qQxHPfLNg8","MaJQseuZA5","fcwDaFcWrW","DQimpZhwG1",
-"m4bxUU3yw5","Yw2oUPOUYS","WmadA0PktI","jSjS3fLNg8","gf8rIgjUTu","tAOsruQIcz","24ARFK20wK","2Nslmy94nw","ciuWzfqypy","uJScXhe9IA",
-"AkKTkSmGzv","SWfouCK5W7","FNYIMK4GS8","euZA5zqH0W","pvgjS5Mg9r","fmIK1LDk6f","DQimpXflUq","9XyT93weIF","rz7Ut0BmCy","pT8wuQssNC",
-"uZPqgLbRTH","0YAGHgf8rI","FcWrWmz8gx","gIYvEFNYIM","0MR5XhYBCK","LbRTHQworu","ciuWzvOqCE","ZJTXHuN6r3","suY4xWDVWJ","uTacxzHF1q",
-"ZJTXHiqv4k","uLtKsB3qem","WaWsvWaim6","ZJTXH2TRI7","M3zXLAmdQd","VNCPdlH1kt","hE1QlcmXIX","64s8N8xEKz","atef2StlDJ","ydG8Uv1Hln",
-"QbxXcAIYUu","aDGtSCfgr3","S2DfuuPX7G","tl72WGv3Fq","FNYIMMm8si","s7Mxk45cIH","tjQxsHP433","VIlwPQWxoT","l83Ud2hEEU","14FLRCp3mZ",
-"soy9tQYxC0","bZLvSgtCA5","IRh488U2nU","580YDD6rBy","7ku1pqaofN","JXljWJIqXi","29QAzWPmlx","uPX7GDQimp","k85Ae2DREs","4QMc9vOqCE",
-"RzaZAguMb8","9iGoTuTacx","tvdkDOUYuF","yluBxAgJHQ","Waim6L7cGc","zHF1qWaim6","ru4UG5drc6","blLA9Waim6","gjUTu48cHL","07n1cMm8si",
-"o8UydQChxs","yEfy9XflUq","MezSWulk41","9rlg9CdyBV","jeskSMmKGJ","dpe1v8cVD3","hUTw7zbIYY","QbxXcUlU3M","U3yw5CNHmv","QChxsv2eC3",
-"CqqaDuupzk","sqVrf16lHc","Pb1pahe9IA","VIlwP4dEz6","uupzkcShY2","NOHszG1RhS","GrDg7tl72W","cShY2MGlTF","AmdQds93Ml","cQOnvNxx9V",
-"OUYuFMezSW","rKDLJjiVBP","jtn0XHfyNQ","tAOsrIKxdL","v8yFNIRh48","VNCPd07n1c","OHaBzKr8ys","Fhtgl6AFT0","Yw2oU2Nslm","fmIK1hYBCK",
-"CxVEfgdQsS","HP433S77LH","fLNg8CNHmv","POUYSfLNg8","l83Udv2eC3","No0QbvLsmS","45cIHFPfSE","HfyNQY1mC0","yluBxHlUbF","pAhR1hUTw7",
-"tl72WKZamH","RzaZAOUqFM","AXpwEJXljW","ogLgciqv4k","8hJdtokgRi","jS1ajUvlv4","vkCHHaL6AJ","zQt6QFnPFB","iqv4kRxrsm","cmXIXpmeCd",
-"iqv4kUmaEv","07n1clXFOB","Z4I1vW3VFH","7lUXZ4QMc9","aFFssZhwG1","jzUqRpWiOs","HzZT8oVQp6","NOHszLewvM","fFDrJrKDLJ","Q6LixlXFOB",
-"QbxXcbrhlQ","hE1QlYh1hF","VLTy614FLR","uJScXaez9y","IjTwPtlILt","9rlg9Yf2Ec","t98iWyToGW","zFgtBQnJ1S","U3yw5uN6r3","h1zcHtvdkD",
-"ECMvUJRJQB","pT8wusuY4x","yToGWIBe8k","zY1GYWreyP","fFDrJs7Mxk","kZANmHRxd8","EdBKc4dEz6","XflUq4QMc9","tlILtW3VFH","dQ586jSjS3",
-"JXljWfmIK1","lkMUAFwEJz","RkQkeFxX9q","IRh4814FLR","WPmlxjS1aj","0ao3lL7cGc","2Nslm9y4lw","WMiS3XyPZN","F6PT2tjQxs","BbwgAvLsmS",
-"7X3uywiHrZ","0YAGHVBjhz","dpe1vOUqFM","okgRiiB08l","4QMc9M6qcG","guMb8l83Ud","3weIFAgJHQ","FcWrWPOUYS","StlDJCfgr3","tAOsrZ4I1v",
-"ix74rMkgy8","Zv7z0PYBf4","4QMc95Namm","yToGWy94nw","GSQwjcShY2","zz4ZU8hJdt","FPfSEjSjS3","OxWIHMezSW","hYBCKh1zcH","CIShGDz1R3",
-"QnJ1SLDk6f","sx5GldQ586","FLsphW3VFH","k85AeqaofN","O3iyQbgJAz","2ZHdkzmLYD","FwEJzpv0i7","AkKTkuJScX","48cHLSWfou","WDVWJReKEW",
-"ulk41WDVWJ","K4GS8WaWsv","48cHLblLA9","ru4UGPb1pa","IRh48ru4UG","prNT6MojnP","WaWsv8hJdt","9iGoTYOfrY","wDajXazIWp","Waim6uLtKs",
-"d7vjM1j5L8","s4786FnPFB","5ZaEz29QAz","uQIczQ6Lix","29QAzJKWYR","2ZHdk6AFT0","0YAGHJkzUn","MGlTFVIlwP","zY1GYbgJAz","ZzJHWazIWp",
-"FGzgpW7cTs","tAOsrB3qem","5Namm48cHL","GSQwjtjQxs","JXljWNOHsz","RkQkeCfgr3","djsrvK4GS8","tjQxsUmaEv","7X3uyRACuj","Chuy30YAGH",
-"lweGyQworu","jfREu64s8N","JkzUnBCxeC","soy9tRkQke","LewvM6q6L9","kB5nPl83Ud","BFkb8GSQwj","jtn0XNOHsz","pmeCdqaofN","hi5X7TCgPp",
-"CNHmvGXdoH","ZuDtDVLTy6","QChxs0Kyfs","gIYvE2Nslm","16lHcfcwDa","0ao3l2ZHdk","5Mg9rRsQUq","qaofN5drc6","AIYUu4QMc9","FLsph5iGN5",
-"wiHrZAmdQd","oGu6x5iGN5","5iGN52TRI7","m4bxUXyPZN","2Yz7EzqH0W","GrDg7xciqp","dQ586K20wK","CdyBV2DREs","pv0i755rfB","5Mg9rTwano",
-"IBe8kuQIcz","FjHXRlCMxy","xciqpx3LDe","lweGyuAWyp","FVMxo48cHL","uvf7AI7p2a","1v5hHXflUq","Yh1hF5IhmG","GWqqXWaWsv","tAOsrmz8gx",
-"BbwgACNHmv","CxVEfPb1pa","d7vjMxReec","9y4lwVNCPd","29QAz2ZHdk","3otm6IjTwP","n1pmOqUJMd","HRxd80PktI","FnPFBd85a9","Chuy3CqqaD",
-"24ARFJRJQB","v2eC3FxX9q","WmadAYjB9t","yvOMICIShG","kB5nPuoStw","bZLvSfcwDa","580YDO3iyQ","WPmlx7fKYU","xReecFPfSE","OHaBzpT8wu",
-"ni2v10Kyfs","LDk6fDz1R3","lj07QmX2GE","B3qemYOfrY","8U2nUQ6Lix","OUqFMTwano","mX2GEZUnqt","0MR5Xx3LDe","Pb1paRACuj","zQt6Q9eoRc",
-"ThjNns4786","vLsmSDcpWB","FnPFB7hyVv","iwzGkOUYuF","5VZjSIn3NS","Yw2oUpmeCd","k85AeuLtKs","WDVWJFNYIM","sqVrfkZANm","uLtKsSWfou",
-"zmLYDWaWsv","azIWpMaJQs","I7p2alViBv","BCxeCJJs5m","ksJbyJJs5m","JXljW8TxD7","Nxx9V5iGN5","NhXdu3weIF","RmDcrAOgEe","jeskS5Drn0",
-"aDGtS2DREs","uZPqgPOUYS","Z4I1v5Namm","S2DfuFhtgl","bZLvS5iGN5","FVMxoX6Pin","AOgEegtCA5","wiHrZWaWsv","5iGN5HP433","PYBf4Oz8yZ",
-"1v5hHKsjRK","jiVBPFGzgp","2TRI7AkKTk","P6bcgt98iW","CK5W7UmaEv","EoToPCxVEf","1j5L8piJSk","NAFuw8hJdt","lm0pDzmLYD","wDajXMezSW",
-"AXpwEuAWyp","RACujQbxXc","9XyT9yluBx","yofH3WreyP","sx5GlM3zXL","cShY2vOqCE","JkzUnRACuj","RmDcrfaHir","Fhtglpv0i7","7hyVvguMb8",
-"48cHLoGu6x","RACujLbRTH","x3LDefaHir","7fKYUprNT6","MaJQsAmdQd","U3yw5HP433","uJScXQWxoT","M3zXLdpe1v","v1HlnF6PT2","Mm8siyToGW",
-"fFDrJHzZT8","QChxsU3yw5","2Yz7EDG4sT","i7WMQIKxdL","guMb8sqVrf","9GXkXRmDcr","In3NSdmoS7","FcWrWZUnqt","8cVD3NOHsz","24ARFCK5W7",
-"ix74rIBe8k","yvOMIpWiOs","fcJOyzHF1q","2TRI7B3qem","t98iWYjB9t","POUYSoQ87r","prNT6d7vjM","POUYS0Wr5y","uoStwRkQke","xXTI4L7cGc",
-"Z4I1vAIYUu","Y1mC0Ul4a1","wiHrZpmeCd","DG4sT9iGoT","5Mg9rCK5W7","s7MxkjS1aj","9GXkX64s8N","wiHrZRzaZA","M3zXL7fKYU","dmoS72ZHdk",
-"WPmlxuJScX","StlDJlCMxy","FGzgp0Kyfs","dQ586BFkb8","gdQsSn8pJ9","X6PinJIqXi","IRh48UmaEv","ZhwG1iKqhr","Rxrsmatef2","ThjNnpWiOs",
-"VerEAuupzk","uZPqg7fsYM","k85AeNhXdu","cShY2Fhtgl","JIqXiOUYuF","YjB9tyvOMI","NhXduv2eC3","dmoS7LewvM","gtCA5EoToP","iqv4kMGlTF",
-"k85AeyEfy9","S77LH7fsYM","QYxC0zFgtB","2hEEUqaofN","Dz1R3aez9y","0BmCyEdBKc","Nxx9VKr8ys","lH1ktuN6r3","lm0pDGSQwj","OHaBzOz8yZ",
-"DLhzMgdQsS","yofH3ix74r","4QMc9s93Ml","FNYIMZ4I1v","dQ5860Kyfs","LDk6fSWfou","2TRI7Rxrsm","HP433AgJHQ","lj07QJIqXi","ksJbyxciqp",
-"jzUqRh1zcH","Yf2EcMm8si","rKDLJChuy3","yToGWXyPZN","uvf7AuTacx","ulk412DREs","yvOMIlj07Q","nnP8oJRJQB","C2IrcZ4I1v","Chuy3hUTw7",
-"ni2v1pFrrl","RkQkepvgjS","xciqpiwzGk","8xEKzCNHmv","5IhmGv1Hln","gtCA5zHF1q","EdBKcb29RJ","2hEEUhi5X7","gIYvENcICA","Oz8yZFLsph",
-"FVMxoNAFuw","IRh48F6PT2","UlU3MzFgtB","uZPqgzFgtB","lpF6WJJs5m","i7WMQVjCZq","Waim69XyT9","JRJQBIBe8k","d85a9OxWIH","kB5nPcShY2",
-"NhXduuupzk","yEfy9Zv7z0","FhtgldmoS7","BCxeCuPX7G","RpBQmv2eC3","2TRI7FNYIM","KZamHXyPZN","POUYSDLhzM","Cfgr3yEfy9","BGaQY5Mg9r",
-"OUqFMTXQ0Z","s7Mxk3otm6","4dEz6bgJAz","JkzUnwDajX","9GXkXFhtgl","FcWrWlpF6W","gdQsSe6e4z","RBhp0CqqaD","wDajX14FLR","IjTwPMK07Y",
-"U3yw5KsjRK","RsQUqGrDg7","9GXkXL7cGc","YjB9tWaim6","TXQ0Zd85a9","Waim6JXljW","Y1mC0WaWsv","y94nwM3zXL","YOfrYFhtgl","8FmFHd85a9",
-"yEfy9lkMUA","WDVWJGrDg7","sx5Gl7fsYM","7hyVv2Nslm","dQ5869rlg9","s93MlQYxC0","0YAGHh1zcH","yToGWzbIYY","NOHszksJby","AIYUuFjHXR",
-"uupzkRACuj","4W0TlxXTI4","Zv7z0aL6AJ","GWqqXjzUqR","45cIHZv7z0","GSQwjWDVWJ","lj07QzY1GY","ECMvU5VZjS","zz4ZUa00b5","VLTy6prNT6",
-"xXTI4n8pJ9","O3iyQRpBQm","CIShGtjQxs","U3yw5nnP8o","IBe8klm0pD","sqVrfrhl0J","FnPFBlm0pD","RpBQmzQt6Q","yEfy9LDk6f","ciuWzCIShG",
-"24ARF8FmFH","ni2v1jiVBP","lViBvCIShG","uAWypAIYUu","Ss0ZugdQsS","2DREs0ao3l","BbwgAIBe8k","D6rBy07n1c","LDk6fjzUqR","W3VFHs4786",
-"fcJOy5Mg9r","o8UydSmGzv","48cHLgjUTu","F6PT2ZzJHW","v2eC38xEKz","ZzJHWPb1pa","zz4ZUCIShG","WaWsvuQIcz","ru4UGsx5Gl","yvOMINxx9V",
-"DcpWBuoStw","ulk41LDk6f","6q6L9No0Qb","Vprf2uZPqg","45cIHogLgc","ix74reuZA5","nlaByJ2mQi","3weIF9iGoT","FcWrWY1mC0","S77LH0PktI",
-"QbxXc5Drn0","FGzgpQWxoT","tlILt48cHL","x3LDehi5X7","gf8rIPOUYS","zY1GYoGu6x","1v5hHjzUqR","UlU3Muupzk","blLA9d7vjM","YjB9tdhSuH",
-"lpF6WB3qem","wiHrZ8FmFH","uAWypfaHir","uZPqgFjHXR","hi5X7nlaBy","uoStwZzJHW","prNT62TRI7","Ss0ZugIYvE","Kr8yss4786","gf8rIUmaEv",
-"oQ87rdmoS7","0PktIk85Ae","Yw2oU16lHc","BCxeCCdyBV","pFrrljiVBP","i7WMQvOqCE","JRJQBfcJOy","cmXIXm4bxU","FjHXRF6PT2","LbRTHOUYuF",
-"Zv7z0n8pJ9","lsQGo64s8N","gjUTuSjskQ","Pb1paaL6AJ","FLsph8RCUA","07n1c5Drn0","7fsYMlm0pD","JIqXiMaJQs","pT8wuS77LH","8xEKzsoy9t",
-"LDk6fHP433","tjQxsD6rBy","In3NSdQ586","FjHXRQ6hMC","zqH0WFVMxo","4dEz6Zv7z0","O3iyQZ4I1v","In3NS29QAz","4QMc90BmCy","CNHmvuJScX",
-"v1HlnJRJQB","zbIYY1j5L8","TCgPpb29RJ","RmDcrmz8gx","vkCHH7lUXZ","Vprf20BmCy","7Ow5CNo0Qb","gdQsS14FLR","Zv7z0pmeCd","suY4xaL6AJ",
-"n1pmOuZPqg","RzaZAlCMxy","1LB1LZuDtD","iKqhrOUqFM","3otm6rKDLJ","uZPqgVprf2","Dz1R3rhl0J","taOXKUmaEv","J2mQiC2Irc","zFgtBIBe8k",
-"faHirD6rBy","lm0pDJkzUn","e6e4zZuDtD","ix74rXflUq","gIYvEQ6Lix","9eoRcFjHXR","XflUqwiHrZ","dpe1vk85Ae","lj07QQ6hMC","ReKEWokgRi",
-"580YDkZANm","ogLgc9rlg9","zz4ZUfmIK1","ZzJHWAkKTk","VLTy6DcpWB","Twano2ZHdk","hUTw7ThjNn","WDVWJIjTwP","EdBKc5Namm","JRJQBkB5nP",
-"S77LH24ARF","WreyPJIqXi","4QMc9FnPFB","TCgPpG1RhS","9XyT9iwzGk","sqVrf64s8N","jfREuBpYhV","55rfBMmsIo","uTacxQ6Lix","FcWrWQClRL",
-"14FLRuAWyp","8xEKzY1mC0","QWxoTiqv4k","BGaQYJIqXi","k85AeHP433","yofH31j5L8","OUYuFd85a9","UlU3M7X3uy","dpe1vuoStw","Qworua00b5",
-"uQIcznlaBy","lsQGoAOgEe","16lHcJkzUn","K20wKi7WMQ","zQt6QMGlTF","0YAGH9XyT9","nFqikAgJHQ","blLA9hE1Ql","bZLvSjiVBP","zmLYDxXTI4",
-"pFrrlGrDg7","qaofNzHF1q","Zv7z0AkKTk","StlDJZJTXH","pvgjSfaHir","8RCUAd7vjM","5Mg9rTXQ0Z","xReecNo0Qb","JJs5mYw2oU","CqqaDMaJQs",
-"GXdoHuN6r3","D6rByguMb8","ZzJHWzQt6Q","Y1mC09XyT9","GrDg7jiVBP","W7cTs07n1c","F6PT2oGu6x","bZLvS0Wr5y","tvdkDWPmlx","OxWIH7fsYM",
-"blLA9iKqhr","3weIFQssNC","cmXIXpT8wu","AgJHQQWxoT","6q6L92ZHdk","0h1b1guMb8","kB5nPcmXIX","16lHcDQimp","he9IALewvM","0KyfsKr8ys",
-"pWiOsCp3mZ","RmDcr9GXkX","07n1cGv3Fq","Dz1R3pT8wu","9y4lwHP433","uZPqgpmeCd","0KyfsGWqqX","SmGzvb29RJ","Ul4a145cIH","5VZjSjS1aj",
-"k85AerKDLJ","No0QbZJTXH","9y4lwdpe1v","dmoS7MmsIo","2Yz7Euvf7A","5Drn0ksJby","SbRYyMmsIo","WMiS3Qworu","I7p2aVBjhz","sqVrfBbwgA",
-"lj07QxReec","1LB1LRsQUq","hE1QlAIYUu","cL0aEYw2oU","GSQwjyofH3","okgRilH1kt","jS1ajGWqqX","5drc6J2mQi","DG4sTx3LDe","2Nslmo8Uyd",
-"MezSWrhl0J","n8pJ9SWfou","2hEEUYOfrY","lpF6WxXTI4","0Wr5yrhl0J","WDVWJ0MR5X","2DREstAOsr","kB5nPNxx9V","VjCZqs7Mxk","lCMxyCxVEf",
-"yofH3Dz1R3","J2mQirKDLJ","zHF1qxciqp","e6e4zWreyP","AIYUuTCgPp","soy9taDGtS","Vprf2K4GS8","s7MxkZhwG1","Waim6OHaBz","b29RJksJby",
-"fcJOyCp3mZ","fLNg8nlaBy","ni2v1OxWIH","ZuDtDkB5nP","aDGtSQWxoT","1v5hHuLtKs","aDGtSbZLvS","y94nwAkKTk","Vprf2JRJQB","7fKYUbgJAz",
-"UlU3MWaim6","vOqCEtl72W","v8yFNSWfou","rz7Ut2DREs","uTacxFLsph","CIShGVjCZq","zmLYDQworu","pmeCds93Ml","X6PiniKqhr","gjUTuTCgPp",
-"zHF1qzbIYY","euZA5gIYvE","Yf2EcY1mC0","VLTy6RBhp0","MK07YtlILt","Pb1pazQt6Q","lpF6WlH1kt","gdQsSZuDtD","iwzGkTa8f6","fLNg8MmsIo",
-"ydG8UK4GS8","FxX9qi7WMQ","t59lRTwano","J2mQicShY2","aDGtSEOE1o","rhl0JMojnP","aL6AJ8xEKz","XyPZN0BmCy","JXljWtvdkD","pvgjSUl4a1",
-"d85a9aFFss","Gv3FqD6rBy","VLTy6P6bcg","lsQGo618Di","PYBf4h1zcH","2Yz7Ei3pyd","2ZHdkrhl0J","lm0pDLbRTH","jSjS3tuDyS","7X3uyZ4I1v",
-"hE1QlnlaBy","ZUnqtQssNC","CNHmvOUqFM","HzZT8NcICA","uQIczazIWp","fFDrJRpBQm","uZPqgChuy3","WreyP48cHL","XflUqTXQ0Z","Ul4a116lHc",
-"HzZT8a00b5","ThjNnhSSvQ","n8pJ95VZjS","6AFT0ulk41","CqqaDPOUYS","LewvM9iGoT","LbRTHlH1kt","5drc6yvOMI","VBjhzuLtKs","iqv4kjzUqR",
-"DLhzMChuy3","KZamH24ARF","brhlQb29RJ","AkKTkv1Hln","7fsYMNOHsz","nFqikHlUbF","gf8rItAOsr","lXFOBRmDcr","2TRI7DcpWB","5iGN5Mm8si",
-"48cHLzHF1q","JJs5m14FLR","580YDiKqhr","FjHXRhi5X7","EOE1ouupzk","faHire6e4z","TCgPpt59lR","sqVrf0h1b1","WmadAKr8ys","QWxoTxciqp",
-"he9IAVLTy6","KZamHuZPqg","AXpwEdpe1v","7fsYMxciqp","IjTwPpT8wu","SWfouAgJHQ","hi5X7n8pJ9","pv0i7Waim6","MGlTFZzJHW","AIYUujzUqR",
-"sqVrf9XyT9","RpBQmMkgy8","DG4sTyToGW","MmKGJaez9y","lweGy55rfB","Waim6StlDJ","NcICAwiHrZ","YOfrY4dEz6","QYxC0GrDg7","sqVrfgIYvE",
-"uAWypZJTXH","lXFOBCdyBV","djsrvMK07Y","O3iyQjeskS","FxX9qxReec","CqqaDTa8f6","DcpWBsoy9t","xReecZv7z0","s93Ml14FLR","d85a9pWiOs",
-"m4bxUokgRi","P6bcgJXljW","Waim6TXQ0Z","gjUTuWaWsv","fcwDaRpBQm","FGzgpAXpwE","NcICAiB08l","MK07YStlDJ","F6PT2rz7Ut","QssNCYjB9t",
-"OxWIHZuDtD","iKqhrGWqqX","tjQxsW3VFH","QssNCYh1hF","pv0i7MmKGJ","zbIYYTwano","ZuDtDblLA9","lCMxyrKDLJ","fLNg8dhSuH","QClRLtAOsr",
-"TwanoogLgc","Dz1R3b29RJ","ZJTXHgIYvE","OUYuFKr8ys","DG4sTfqypy","F6PT2fcJOy","aDGtSYf2Ec","FVMxoZzJHW","Mm8sitjQxs","CIShGXyPZN",
-"8hJdtxXTI4","aez9y8cVD3","ksJbyDz1R3","618DiReKEW","qQxHPhi5X7","14FLReuZA5","zz4ZUMm8si","24ARFv2eC3","24ARFtvdkD","Pb1paydG8U",
-"y94nwWaim6","5Drn0n8pJ9","yToGWBCxeC","qaofNIn3NS","GXdoH5Namm","fFDrJsx5Gl","s7MxkGSQwj","fqypy5Drn0","qUJMdix74r","Ul4a1dpe1v",
-"HRxd8djsrv","lsQGoNOHsz","5Drn0ix74r","FVMxo5iGN5","d7vjMatef2","29QAzQYxC0","QworuNAFuw","Mkgy8jS1aj","7fKYUt59lR","Uvlv4K20wK",
-"brhlQrhl0J","okgRihYBCK","TwanoHzZT8","dpe1vNcICA","aDGtSy94nw","AkKTkKZamH","x3LDevOqCE","UmaEvUmaEv","ru4UG0ao3l","FhtglAkKTk",
-"zHF1qgtCA5","qQxHPYOfrY","JkzUnhUTw7","JKWYRMmKGJ","WPmlx1j5L8","WMiS3ZJTXH","ciuWz5ZaEz","OUYuFguMb8","8TxD75IhmG","Uvlv4t59lR",
-"s93Mln1pmO","WreyPHzZT8","AmdQds7Mxk","piJSkKZamH","nFqikVIlwP","n8pJ90PktI","0h1b1AIYUu","M3zXLpWiOs","Pb1paW3VFH","jfREuWPmlx",
-"AgJHQni2v1","FPfSEfaHir","Nxx9VsuY4x","n1pmOWaWsv","lpF6W7hyVv","FNYIM29QAz","AOgEevkCHH","he9IAdQ586","7fsYMhSSvQ","16lHcRxrsm",
-"pvgjSLewvM","7X3uyuvf7A","Ss0Zu7fKYU","W7cTss4786","n8pJ9tl72W","K20wK2Nslm","JkzUnn8pJ9","FGzgpEdBKc","O3iyQFjHXR","VerEAhi5X7",
-"oVQp6djsrv","WreyPMGlTF","ZhwG1pAhR1","XflUqoVQp6","yToGWL7cGc","Ul4a18xEKz","b29RJwiHrZ","pT8wuhE1Ql","uQIczxciqp","DLhzMFNYIM",
-"dpe1vgf8rI","zY1GYCfgr3","m4bxUZUnqt","ZzJHWFcWrW","oQ87rFNYIM","YOfrYFGzgp","nnP8oM3zXL","Yf2EcXyPZN","FjHXRpmeCd","9iGoTOUqFM",
-"ogLgcSbRYy","zmLYDlkMUA","BbwgAOUqFM","MojnPcL0aE","blLA9dmoS7","2NslmpvgjS","MGlTFVBjhz","cShY2BpYhV","45cIHjtn0X","PYBf4zHF1q",
-"uJScXnnP8o","FhtglNxx9V","zFgtBuN6r3","uoStwk85Ae","tAOsrP6bcg","XyPZNTwano","CdyBV4dEz6","tuDySFPfSE","lweGyZuDtD","dpe1vmX2GE",
-"LDk6fogLgc","dhSuHHlUbF","dpe1v55rfB","Waim60PktI","PYBf4OUqFM","8xEKzOxWIH","ydG8UL7cGc","YjB9toQ87r","cShY229QAz","uvf7AZuDtD",
-"aL6AJrKDLJ","uLtKsKASQ8","FNYIM5VZjS","fcJOyzFgtB","0h1b1Ta8f6","MaJQsmz8gx","24ARFXflUq","aDGtSZUnqt","uN6r3SjskQ","DLhzMdpe1v",
-"uLtKsuJScX","YjB9tXflUq","jSjS3Waim6","pv0i7rKDLJ","LewvMAIYUu","RpBQmChuy3","yEfy99rlg9","zqH0WGrDg7","Gv3FqpFrrl","jzUqRt98iW",
-"7lUXZkZANm","StlDJAIYUu","2TRI7RzaZA","16lHcPb1pa","RACujUl4a1","cQOnvVerEA","EdBKcfFDrJ","euZA5faHir","8U2nU9iGoT","EdBKczqH0W",
-"EdBKcHlUbF","CqqaDK4GS8","Gv3FquAWyp","07n1chUTw7","In3NSEdBKc","1j5L8MGlTF","LewvMgdQsS","uLtKsTa8f6","UmaEvyToGW","sqVrfIjTwP",
-"LbRTHQ6hMC","zY1GYrhl0J","OHaBzNxx9V","JIqXiVLTy6","Rxrsm0MR5X","m4bxUoGu6x","ciuWzv8yFN","FnPFBix74r","fcwDaLbRTH","GSQwjMkgy8",
-"W3VFHuupzk","Zv7z08hJdt","d85a98xEKz","FLsphJ2mQi","VNCPdQssNC","2ZHdkZv7z0","wDajXpFrrl","OUYuFulk41","fcJOyAXpwE","P6bcgtl72W",
-"xXTI4djsrv","0PktIJkzUn","Mm8si2Yz7E","d7vjMGWqqX","In3NSYh1hF","RsQUqfcJOy","HlUbF5IhmG","FwEJz45cIH","RsQUqGWqqX","I7p2aFnPFB",
-"QworubrhlQ","8hJdtNhXdu","JRJQBfLNg8","lkMUASmGzv","7fKYUZhwG1","Q6LixJJs5m","hi5X7zHF1q","Yh1hFsqVrf","YOfrYlViBv","Mm8si5Namm",
-"HfyNQQ6Lix","t98iW55rfB","RBhp0580YD","pWiOsxXTI4","lViBvs93Ml","TwanoFVMxo","AgJHQt98iW","JIqXiSWfou","azIWpUvlv4","gIYvEk85Ae",
-"BCxeCjiVBP","GSQwj5ZaEz","DLhzMdjsrv","jfREuPb1pa","yofH3uvf7A","ThjNnCfgr3","IKxdL2ZHdk","pT8wufLNg8","JJs5mAIYUu","QYxC0AOgEe",
-"GWqqX8hJdt","9iGoTfcJOy","cL0aE580YD","he9IAyluBx","IjTwPS2Dfu","5VZjSydG8U","nlaByCxVEf","aL6AJ9y4lw","5ZaEz0h1b1","BGaQYWmadA",
-"5Drn0MGlTF","MaJQsNOHsz","Mm8si0BmCy","v8yFNRBhp0","mz8gxVIlwP","gtCA5UlU3M","rKDLJqQxHP","0h1b1ZzJHW","oQ87rHfyNQ","Q6LixOUYuF",
-"Gv3Fq8TxD7","fmIK1CNHmv","k85AeMm8si","iKqhrfFDrJ","YjB9tPYBf4","1v5hHThjNn","pmeCd2Nslm","mX2GEix74r","MezSW5nmWv","6q6L9azIWp",
-"v1HlnoGu6x","FjHXR6q6L9","RmDcrJRJQB","14FLR7Ow5C","DcpWBMmKGJ","lj07Q2ZHdk","fqypyK20wK","KASQ8BFkb8","oQ87r14FLR","5Drn0POUYS",
-"a00b5d85a9","L7cGcd7vjM","v2eC3aDGtS","v1HlnCfgr3","BFkb8RACuj","dQ586cmXIX","0h1b1MezSW","P6bcg6q6L9","Dz1R3iKqhr","qUJMd7lUXZ",
-"7fKYUVjCZq","8RCUA9GXkX","WPmlxB3qem","WPmlxPOUYS","XflUqfLNg8","e6e4zCK5W7","XyPZNFNYIM","G1RhSSbRYy","2ZHdkv1Hln","Gv3FqdmoS7",
-"I7p2a0YAGH","AmdQdWaWsv","8TxD7lm0pD","pmeCdogLgc","FjHXRU3yw5","Mkgy8MezSW","tvdkD7ku1p","C2Ircd85a9","x3LDe8cVD3","StlDJazIWp",
-"4QMc98hJdt","lweGypAhR1","XyPZNZJTXH","JXljWhYBCK","yToGWOUYuF","fFDrJW7cTs","aez9yiwzGk","zqH0WL7cGc","RBhp014FLR","jtn0XzQt6Q",
-"vkCHH7hyVv","gjUTuv8yFN","TXQ0Z9iGoT","HRxd8ZJTXH","atef2v1Hln","AXpwE64s8N","W3VFHF6PT2","jzUqRJXljW","ni2v1POUYS","fcwDaWMiS3",
-"4QMc9VjCZq","tjQxsnlaBy","nnP8ohE1Ql","lH1ktvLsmS","s7MxklweGy","O3iyQ64s8N","Vprf229QAz","ZuDtDtlILt","U3yw5aez9y","GrDg7CxVEf",
-"FGzgp6q6L9","4W0TllkMUA","Mkgy8SmGzv","CIShGDG4sT","9GXkXNxx9V","ReKEWKASQ8","WDVWJGSQwj","suY4xCxVEf","QbxXcjeskS","Y1mC0pv0i7",
-"rz7UttjQxs","RzaZAFLsph","uvf7AFcWrW","cQOnvYOfrY","yluBxNOHsz","EdBKcdpe1v","NcICA16lHc","xXTI4Fhtgl","okgRiksJby","jzUqRkZANm",
-"iB08lHRxd8","fFDrJFnPFB","dmoS7t59lR","Mkgy8pmeCd","WPmlxfFDrJ","HzZT8k85Ae","WDVWJfaHir","pmeCdCIShG","FcWrWsqVrf","7lUXZYw2oU",
-"StlDJjeskS","ZhwG1Pb1pa","RsQUqIjTwP","o8UydjiVBP","7X3uyJJs5m","pmeCd4dEz6","sqVrfDG4sT","GXdoHVIlwP","nFqikFGzgp","dpe1vl83Ud",
-"S2Dfu07n1c","NcICArhl0J","pv0i7Cfgr3","Oz8yZyvOMI","Ul4a1P6bcg","DcpWBSWfou","aL6AJ4QMc9","HlUbFlweGy","StlDJ2hEEU","Yw2oUsqVrf",
-"cmXIXAgJHQ","IKxdLb29RJ","wiHrZhE1Ql","8RCUARzaZA","lCMxySjskQ","uQIczAIYUu","5Mg9ruZPqg","Ta8f6SjskQ","SmGzvni2v1","2hEEUYh1hF",
-"KsjRK64s8N","blLA9uAWyp","BGaQYlH1kt","ni2v1fLNg8","3weIFsx5Gl","tvdkDBCxeC","W7cTs3otm6","RmDcrvLsmS","vkCHHDz1R3","ZUnqte6e4z",
-"AmdQdVLTy6","MmsIoBCxeC","s7MxkgtCA5","5Mg9rB3qem","JKWYRuZPqg","9XyT9lkMUA","Dz1R3lkMUA","CxVEf4QMc9","e6e4z64s8N","W7cTs7Ow5C",
-"Z4I1v3otm6","AOgEe5Drn0","MmsIoUlU3M","9rlg9v8yFN","iB08l4W0Tl","8TxD79eoRc","Ul4a1Yh1hF","SmGzv2Yz7E","BbwgACp3mZ","gtCA5lViBv",
-"2Yz7Erz7Ut","F6PT22DREs","ZuDtDAmdQd","IBe8kHP433","5Mg9rL7cGc","WDVWJNo0Qb","tjQxsOxWIH","3otm6SmGzv","GrDg7lweGy","AmdQdqUJMd",
-"U3yw5BGaQY","JRJQBatef2","Ul4a1M6qcG","ksJbyK20wK","b29RJAkKTk","9GXkXSWfou","0PktI9eoRc","45cIHUmaEv","Mkgy8oGu6x","Q6hMCS77LH",
-"7hyVvJXljW","pAhR1CdyBV","Pb1paGv3Fq","JXljWpmeCd","Ta8f6zY1GY","guMb8F6PT2","GWqqXa00b5","F6PT2rhl0J","QChxsO3iyQ","bZLvSCNHmv",
-"uN6r3wiHrZ","I7p2aogLgc","suY4xW7cTs","lj07QMezSW","Vprf2lm0pD","n8pJ9gf8rI","Pb1pa4W0Tl","lj07QyToGW","ThjNn48cHL","BpYhV7X3uy",
-"pmeCd16lHc","Vprf2BbwgA","fcwDaOz8yZ","W7cTsHfyNQ","v2eC3djsrv","vkCHHuvf7A","8cVD3MK07Y","ZuDtDPb1pa","JIqXit98iW","cShY2LbRTH",
-"iKqhr618Di","zz4ZUjfREu","LDk6fHzZT8","zz4ZUKr8ys","B3qemCNHmv","ECMvURACuj","dhSuHZuDtD","oVQp6EOE1o","DG4sTHfyNQ","7hyVvQnJ1S",
-"JJs5m0Kyfs","MK07YP6bcg","2TRI79y4lw","pWiOspAhR1","zY1GYuN6r3","nFqikh1zcH","vkCHH5Mg9r","MojnPReKEW","zHF1qW7cTs","nnP8ocmXIX",
-"taOXKfFDrJ","I7p2aDQimp","YOfrYfcwDa","fLNg8pv0i7","k85AeAgJHQ","CK5W7m4bxU","OHaBzlweGy","jSjS3IRh48","fcwDaIjTwP","Zv7z0RACuj",
-"v8yFNulk41","7Ow5CzmLYD","CK5W7uAWyp","x3LDeTwano","zbIYY7X3uy","Cp3mZZzJHW","7ku1pSWfou","cQOnvCp3mZ","Ul4a1BCxeC","kZANmQClRL",
-"7fsYMTXQ0Z","hE1QlgdQsS","0YAGHzbIYY","MojnPlpF6W","U3yw5Twano","JXljWhi5X7","MmKGJZUnqt","WDVWJY1mC0","uPX7GgdQsS","JXljWYjB9t",
-"MK07YbgJAz","8U2nUGXdoH","GXdoHWaWsv","WaWsvbZLvS","UmaEvb29RJ","lViBvzbIYY","t98iWSjskQ","Yf2EcRxrsm","VerEAXyPZN","jtn0XlCMxy",
-"S77LHfaHir","prNT6FVMxo","jzUqR7fsYM","pAhR1KASQ8","zHF1qRACuj","X6PinFGzgp","8xEKzFjHXR","5iGN50Wr5y","fLNg8uupzk","VNCPdnlaBy",
-"iKqhrSbRYy","brhlQYjB9t","sx5GlSmGzv","GrDg7wDajX","1LB1L5Namm","iKqhr7fKYU","ZuDtDb29RJ","kZANmDcpWB","gtCA5jeskS","cmXIXtl72W",
-"Waim6MojnP","ZJTXHblLA9","qUJMdBGaQY","WMiS35iGN5","l83UdTa8f6","5Drn0yvOMI","pT8wu2hEEU","BpYhVFNYIM","Pb1paCdyBV","LbRTHLDk6f",
-"kZANmAOgEe","uJScXokgRi","AIYUuhi5X7","x3LDeNcICA","tlILtix74r","SmGzvuvf7A","RxrsmGWqqX","W7cTsJIqXi","Ta8f6vOqCE","vOqCETwano",
-"RmDcrVBjhz","FwEJzOHaBz","DG4sT3weIF","GXdoHjtn0X","qUJMdpiJSk","YjB9tKr8ys","piJSkfqypy","lsQGo16lHc","jeskS29QAz","ZJTXHlH1kt",
-"EOE1onlaBy","ulk41tlILt","SjskQazIWp","BGaQYaL6AJ","xXTI4h1zcH","tAOsrI7p2a","bZLvS2Nslm","Y1mC0Dz1R3","QWxoTtlILt","64s8NSbRYy",
-"07n1cVjCZq","8cVD39y4lw","MezSWuTacx","D6rBylweGy","POUYSP6bcg","ix74rCNHmv","zFgtBHRxd8","jtn0X8TxD7","OxWIH8FmFH","9eoRcBbwgA",
-"jtn0XS77LH","lj07QguMb8","DQimpDQimp","jzUqRQWxoT","Gv3FqfFDrJ","ulk412Nslm","8RCUAMojnP","TwanoYw2oU","lXFOBMmsIo","HP433ThjNn",
-"Twano14FLR","JXljWOUYuF","OxWIH4W0Tl","F6PT2uLtKs","9iGoT0h1b1","fmIK18TxD7","U3yw59GXkX","W7cTstl72W","ogLgcksJby","VIlwP580YD",
-"GXdoHChuy3","LDk6fK20wK","WPmlx2Yz7E","i7WMQOHaBz","EdBKcI7p2a","blLA9FwEJz","DcpWBtl72W","AOgEeyToGW","F6PT2OUqFM","zbIYYlXFOB",
-"jS1ajv8yFN","y94nwQChxs","faHir7Ow5C","5nmWvOUYuF","ni2v1BCxeC","aFFssaFFss","QbxXcdpe1v","yofH3LbRTH","uN6r3W7cTs","aez9ytAOsr",
-"MezSWkZANm","nlaByfmIK1","Vprf2L7cGc","n1pmOXflUq","0ao3lNhXdu","GWqqXvLsmS","m4bxUjtn0X","hi5X7iKqhr","48cHLatef2","lpF6WLDk6f",
-"Oz8yZzFgtB","16lHc64s8N","wDajXzbIYY","9rlg9HlUbF","FcWrWzbIYY","FcWrW618Di","Q6LixP6bcg","tl72WxReec","ciuWzFPfSE","AOgEeksJby",
-"iwzGkfLNg8","ciuWzpv0i7","AgJHQ9iGoT","SmGzv8TxD7","Q6LixdmoS7","prNT6uPX7G","In3NS5drc6","YOfrYHP433","CK5W7v8yFN","Uvlv46q6L9",
-"FPfSEbZLvS","QssNCjiVBP","rz7UtfFDrJ","v1HlnBFkb8","bgJAzd85a9","FjHXRM6qcG","Yf2EcaL6AJ","Ta8f6Ul4a1","MaJQszz4ZU","lCMxy7ku1p",
-"580YDKsjRK","ciuWzUlU3M","HRxd8AmdQd","uoStwNhXdu","580YDuQIcz","jfREusuY4x","KASQ8CdyBV","aDGtSIRh48","2hEEUS77LH","5drc6Yw2oU",
-"EdBKcxciqp","zbIYY0BmCy","C2Irche9IA","azIWpfmIK1","suY4xbrhlQ","EOE1oW7cTs","6AFT0lm0pD","cQOnvGSQwj","Kr8ysEdBKc","JRJQBCdyBV",
-"blLA9jSjS3","8FmFHX6Pin","618DiFGzgp","OUqFMFGzgp","HlUbFuvf7A","B3qemjSjS3","gtCA5s4786","jSjS3WDVWJ","n8pJ9euZA5","FjHXRlpF6W",
-"Rxrsmjtn0X","MaJQsFFDui","Dz1R3zY1GY","OHaBz7Ow5C","zz4ZUJ2mQi","YOfrYJ2mQi","1LB1Llj07Q","2hEEUjS1aj","8FmFHMaJQs","O3iyQ5ZaEz",
-"J2mQikB5nP","O3iyQYh1hF","n8pJ9ni2v1","WDVWJ9GXkX","45cIHIBe8k","dQ586EoToP","tjQxs14FLR","TCgPpQYxC0","VIlwPUmaEv","UlU3M8RCUA",
-"Dz1R3cQOnv","aFFssSWfou","wDajX64s8N","euZA5ZhwG1","VIlwP0YAGH","aL6AJHzZT8","BGaQY7X3uy","zbIYYM3zXL","D6rBylCMxy","0KyfsYh1hF",
-"OUYuFLDk6f","gjUTu7hyVv","PYBf4FxX9q","0Kyfs5Mg9r","Yh1hFHzZT8","IRh48Z4I1v","wDajX4QMc9","Mm8siIjTwP","MmKGJMaJQs","aez9yF6PT2",
-"zmLYDRmDcr","jS1ajQ6hMC","BCxeCgf8rI","Ta8f6yToGW","rz7Utn8pJ9","kZANmpT8wu","M6qcGQssNC","QnJ1SQClRL","CqqaDvLsmS","fmIK1MGlTF",
-"D6rByReKEW","bZLvS3otm6","uZPqgIjTwP","VLTy6Ta8f6","9eoRcPOUYS","DcpWBZuDtD","VNCPddpe1v","KsjRKhe9IA","wiHrZFjHXR","W7cTs5Mg9r",
-"GXdoH2TRI7","tlILtFjHXR","uQIczAmdQd","CNHmvdhSuH","IKxdL9iGoT","Uvlv4F6PT2","55rfBWreyP","o8UydK4GS8","RkQke5Mg9r","gtCA5y94nw",
-"8cVD3Gv3Fq","Kr8yspT8wu","jfREuhYBCK","iwzGkuAWyp","6q6L9atef2","HRxd8SbRYy","yofH3CdyBV","Qworu9rlg9","s47869y4lw","FVMxoi7WMQ",
-"QClRLs93Ml","ReKEWRpBQm","VLTy6fmIK1","hE1QlpiJSk","7fsYMZv7z0","0YAGHfLNg8","Y1mC0QChxs","RpBQmEoToP","IBe8k5Namm","UlU3M1v5hH",
-"UmaEvyluBx","RkQke2hEEU","JKWYR9rlg9","d85a9LewvM","tlILtC2Irc","QClRL3otm6","GSQwj5iGN5","e6e4zChuy3","8hJdtCp3mZ","Cp3mZNxx9V",
-"AgJHQ8TxD7","Mkgy8fLNg8","StlDJGv3Fq","Kr8yst98iW","8xEKz5IhmG","QYxC0hE1Ql","zFgtBVprf2","gIYvEeuZA5","taOXKMkgy8","GSQwjD6rBy",
-"Mm8siC2Irc","zqH0W48cHL","Q6LixzHF1q","i3pyds93Ml","Vprf25nmWv","aL6AJ7lUXZ","pvgjSvkCHH","WmadAZUnqt","Ul4a1azIWp","GSQwjGrDg7",
-"e6e4zuQIcz","EdBKce6e4z","580YD1v5hH","yToGW7lUXZ","WmadAzQt6Q","45cIHnFqik","DLhzMv1Hln","JKWYRL7cGc","rz7UtdQ586","YjB9tuoStw",
-"Gv3Fq5VZjS","7hyVvuLtKs","5Mg9rmX2GE","taOXKQnJ1S","blLA95Mg9r","JXljWDLhzM","wiHrZmz8gx","M3zXLzHF1q","GWqqXB3qem","45cIHXflUq",
-"CdyBVRpBQm","IRh48B3qem","2hEEUhSSvQ","HzZT80Wr5y","pmeCdHlUbF","lm0pDtuDyS","lCMxyMK07Y","O3iyQyofH3","aFFssv8yFN","vLsmScQOnv",
-"sqVrfl83Ud","Nxx9VNxx9V","mz8gxcmXIX","ZhwG15Mg9r","OUYuF48cHL","lViBvZzJHW","I7p2aNo0Qb","S77LHv2eC3","Z4I1vTCgPp","2NslmIRh48",
-"Chuy30MR5X","16lHceuZA5","uZPqg7X3uy","Nxx9VUl4a1","ogLgcI7p2a","9rlg99eoRc","bZLvSjfREu","rKDLJyEfy9","hYBCKCIShG","ZhwG1SWfou",
-"QChxsNhXdu","WaWsvNhXdu","AkKTklsQGo","ZJTXHuTacx","gjUTuO3iyQ","SmGzvECMvU","2TRI7AgJHQ","cL0aEfqypy","yvOMIhYBCK","FGzgpxciqp",
-"Mkgy8CK5W7","ZuDtDJkzUn","ydG8Ut98iW","JRJQBOz8yZ","uTacxcQOnv","16lHc4W0Tl","U3yw50PktI","3weIFKASQ8","pFrrlKsjRK","2DREsSbRYy",
-"1LB1L5Drn0","4W0TlJkzUn","uQIcz0h1b1","xciqpD6rBy","tAOsrFwEJz","6AFT0IBe8k","K20wKNo0Qb","dhSuHrKDLJ","uLtKs9XyT9","lH1ktpFrrl",
-"NhXduStlDJ","OxWIH7fKYU","EdBKcv1Hln","lH1ktVerEA","GSQwj5VZjS","4dEz6d85a9","5Drn0aez9y","KsjRKPOUYS","zY1GYNo0Qb","BbwgAtAOsr",
-"hi5X7guMb8","euZA5m4bxU","LDk6f29QAz","JXljWjzUqR","2Yz7EnlaBy","ksJby7X3uy","n8pJ9RsQUq","lkMUAblLA9","NhXduoQ87r","7fKYUNhXdu",
-"lj07QM3zXL","Kr8ysD6rBy","RmDcrKASQ8","K20wKOHaBz","O3iyQFLsph","DLhzMlm0pD","7ku1pDz1R3","Fhtgl618Di","9y4lwKZamH","azIWpn1pmO",
-"Q6LixM3zXL","yEfy93weIF","soy9tS77LH","ru4UGpiJSk","45cIHEoToP","mX2GEQworu","hUTw75Mg9r","FLsphwiHrZ","S2DfuyEfy9","6AFT0KZamH",
-"NAFuw0Kyfs","blLA9ogLgc","m4bxUfFDrJ","y94nwIRh48","ThjNnZJTXH","soy9t5IhmG","JXljWfFDrJ","EOE1oYw2oU","QbxXcoGu6x","yToGW9iGoT",
-"BFkb8fLNg8","jzUqRECMvU","8xEKzNxx9V","jzUqRoGu6x","618DiCK5W7","1LB1LNOHsz","8RCUAL7cGc","tAOsrY1mC0","1v5hHOUYuF","IBe8kCp3mZ",
-"nlaByfqypy","7fKYU9eoRc","B3qemL7cGc","QWxoTDQimp","CIShGZUnqt","jtn0XpAhR1","Q6LixKASQ8","AmdQdgf8rI","618Div2eC3","45cIH3weIF",
-"qaofNHRxd8","b29RJlH1kt","BbwgAZzJHW","9XyT9CdyBV","vkCHHY1mC0","uoStw2ZHdk","L7cGcJIqXi","iB08l0Kyfs","Q6hMCJIqXi","CIShGzFgtB",
-"Rxrsmuupzk","2NslmuLtKs","x3LDeBbwgA","lpF6WRBhp0","JkzUnHzZT8","AkKTkkB5nP","oQ87rqUJMd","brhlQRkQke","FwEJz8U2nU","FPfSEuupzk",
-"QnJ1SSWfou","yEfy9S2Dfu","sx5GlEdBKc","GXdoHiqv4k","8RCUA8TxD7","ECMvUDLhzM","5Mg9r29QAz","gIYvEAXpwE","0h1b1DG4sT","uoStwFwEJz",
-"oVQp6n1pmO","VBjhzSWfou","SWfouW3VFH","DG4sTS2Dfu","mz8gxni2v1","UmaEv8xEKz","ru4UGbrhlQ","taOXKCqqaD","ECMvUAgJHQ","RkQkehYBCK",
-"8FmFHNAFuw","y94nwm4bxU","uTacxPOUYS","GSQwjdjsrv","MojnPsuY4x","v1HlnqUJMd","HlUbFK20wK","Q6hMCTa8f6","gf8rIWmadA","sqVrfL7cGc",
-"EdBKckZANm","PYBf4oGu6x","zz4ZUVerEA","FNYIMlpF6W","e6e4zAXpwE","d7vjMzY1GY","n8pJ9yEfy9","ix74re6e4z","Cp3mZ9y4lw","D6rByZv7z0",
-"s93MlZJTXH","qUJMdlViBv","gIYvESjskQ","oQ87rRzaZA","LbRTHPb1pa","QChxsmz8gx","uAWypKZamH","Ul4a1jSjS3","lsQGo4QMc9","HzZT8Cfgr3",
-"FnPFB3weIF","v1HlnMmKGJ","In3NS9XyT9","HfyNQX6Pin","kB5nP2DREs","Nxx9VydG8U","dmoS7lj07Q","0PktId7vjM","NOHszSs0Zu","dmoS74W0Tl",
-"BGaQY0h1b1","WPmlxxciqp","lj07QzFgtB","64s8NJ2mQi","0ao3lFVMxo","Z4I1vYf2Ec","FGzgpjfREu","Mm8siZzJHW","wiHrZ8U2nU","Nxx9VZzJHW",
-"FxX9qlweGy","FxX9qpWiOs","UlU3MMojnP","ZzJHW580YD","t98iWAkKTk","ogLgckB5nP","l83UdWmadA","d7vjMKZamH","HzZT8Waim6","W3VFHUl4a1",
-"YjB9tRACuj","Z4I1vAmdQd","48cHL64s8N","CdyBV7Ow5C","uoStwMmKGJ","tAOsrydG8U","cL0aE9y4lw","TCgPpIRh48","ThjNnjS1aj","QYxC05Drn0",
-"rhl0Jzz4ZU","ZzJHWnlaBy","Uvlv4zFgtB","AXpwEQYxC0","Ul4a1aez9y","iqv4k0Wr5y","hSSvQSmGzv","d7vjM2TRI7","4QMc9dpe1v","QYxC0kB5nP",
-"EOE1o8hJdt","JIqXiuupzk","zQt6QqUJMd","euZA5zz4ZU","UmaEvSWfou","QWxoTksJby","xXTI4d7vjM","bgJAzru4UG","S2Dfus7Mxk","F6PT2TCgPp",
-"L7cGcgdQsS","5VZjSPOUYS","Waim6aez9y","e6e4z0Wr5y","gIYvEReKEW","ZUnqtrhl0J","s4786IBe8k","uN6r35Drn0","RkQke1j5L8","lH1ktAOgEe",
-"ECMvUuoStw","uoStwFhtgl","VLTy6Pb1pa","fcJOyReKEW","BbwgAQChxs","0ao3lzqH0W","QworuQ6Lix","b29RJThjNn","Yw2oUQClRL","AIYUuMm8si",
-"MojnPWPmlx","nnP8o0ao3l","uPX7GMaJQs","5nmWvxXTI4","oQ87r7lUXZ","Y1mC0uN6r3","oQ87rDcpWB","ThjNns7Mxk","P6bcgXyPZN","aDGtSQbxXc",
-"OHaBzQYxC0","TCgPpfcJOy","Mm8siv1Hln","uAWypzqH0W","7fKYUlm0pD","M3zXLtjQxs","CNHmvsoy9t","zY1GYRpBQm","XflUqulk41","lm0pDFFDui",
-"fmIK1JIqXi","QYxC0ksJby","6q6L9uLtKs","lsQGo1v5hH","yvOMIyluBx","NhXdu8cVD3","ni2v1lweGy","P6bcg0Kyfs","8FmFHGWqqX","tlILtFVMxo",
-"dQ5866AFT0","zHF1qtjQxs","bZLvSAmdQd","ni2v1pAhR1","5nmWvAmdQd","qQxHPcShY2","1j5L8FFDui","RkQketlILt","EdBKc2hEEU","zz4ZUpiJSk",
-"lkMUAFPfSE","5nmWvQnJ1S","CdyBVJRJQB","VNCPdiqv4k","gIYvEbZLvS","vLsmSO3iyQ","0KyfsQWxoT","RACujMm8si","pmeCdZJTXH","b29RJ2ZHdk",
-"14FLR7fKYU","B3qemJJs5m","e6e4zYf2Ec","2hEEUs93Ml","oQ87rRmDcr","e6e4z6q6L9","iB08lvOqCE","azIWpl83Ud","aDGtSAOgEe","Yf2Eci3pyd",
-"6AFT0yvOMI","ksJbys4786","ZuDtD9iGoT","16lHc5Mg9r","CK5W7iKqhr","zY1GYuTacx","3weIF64s8N","KsjRKuN6r3","lj07QMK07Y","fLNg8n8pJ9",
-"gf8rItjQxs","1v5hHZv7z0","CNHmvZuDtD","CIShGyvOMI","SjskQtjQxs","64s8NRmDcr","S2DfuJXljW","lkMUAZuDtD","qQxHPni2v1","y94nwQ6Lix",
-"Yh1hFlm0pD","k85Aes93Ml","jeskS2TRI7","i7WMQFwEJz","CqqaD7ku1p","EOE1o4W0Tl","VLTy6ReKEW","n8pJ9QWxoT","uLtKsOz8yZ","9rlg95Drn0",
-"Nxx9VS77LH","piJSkSWfou","CNHmvRzaZA","X6Pin580YD","IBe8k7X3uy","AmdQdQworu","MmsIo2Nslm","FhtglPOUYS","mz8gxWmadA","xciqp9iGoT",
-"xXTI4tlILt","l83UdnFqik","kB5nPxciqp","kB5nPgtCA5","faHiri7WMQ","ZzJHWuJScX","i3pydLbRTH","QssNC4dEz6","AgJHQG1RhS","MmKGJtlILt",
-"9eoRcWaim6","aFFssRmDcr","hSSvQ64s8N","5VZjSQssNC","LewvM4W0Tl","iKqhr3weIF","HzZT8zqH0W","5Drn0lkMUA","ThjNnUvlv4","4QMc92DREs",
-"uoStwuQIcz","FGzgpgIYvE","JXljWzY1GY","DG4sTQChxs","S2DfuMK07Y","QbxXcKr8ys","l83UdPOUYS","lweGy2hEEU","DQimpt98iW","NOHszFxX9q",
-"9y4lwFhtgl","POUYSiB08l","ksJbyyEfy9","7lUXZlViBv","Ul4a1k85Ae","dpe1vqQxHP","Oz8yZMm8si","S77LH0Kyfs","CNHmvtaOXK","MK07YFGzgp",
-"ZUnqtFjHXR","618DixXTI4","TXQ0Z5Drn0","1LB1LvOqCE","jzUqRVprf2","Pb1paOUqFM","K4GS8wiHrZ","G1RhSFLsph","mz8gx4QMc9","UlU3MokgRi",
-"7fKYUBpYhV","lViBv0h1b1","AIYUuW3VFH","5ZaEzblLA9","NhXduWreyP","tuDyS24ARF","JRJQBDG4sT","zFgtBzHF1q","NAFuwjS1aj","64s8Naez9y",
-"WMiS3xReec","taOXKFwEJz","yToGWFhtgl","0YAGH9GXkX","lpF6W2TRI7","OxWIHThjNn","QnJ1STXQ0Z","EdBKcFhtgl","zY1GYn8pJ9","0ao3lLewvM",
-"fqypyGSQwj","pAhR1dmoS7","sx5Gl5IhmG","HfyNQEoToP","jiVBPEoToP","K20wKIBe8k","M3zXLX6Pin","OHaBzK4GS8","14FLRJ2mQi","lXFOB9rlg9",
-"MGlTFvOqCE","suY4xzmLYD","0Wr5yiqv4k","d7vjMO3iyQ","LDk6fQnJ1S","b29RJEdBKc","GWqqXcL0aE","guMb8euZA5","prNT6yvOMI","wDajXWaWsv",
-"F6PT22ZHdk","bZLvSNcICA","xXTI4QWxoT","8TxD7cShY2","n8pJ9S77LH","vOqCEpFrrl","hE1QlQnJ1S","0YAGHVjCZq","SjskQHP433","uQIczCqqaD",
-"o8UyduPX7G","hE1QlTCgPp","VNCPd6q6L9","yluBxo8Uyd","v2eC3jeskS","MmsIocmXIX","ZzJHWs4786","5Drn0JKWYR","KASQ8pWiOs","Zv7z0L7cGc",
-"xXTI4YOfrY","LbRTHVjCZq","RpBQmO3iyQ","AkKTkni2v1","FNYIMYjB9t","6AFT0VjCZq","k85AeRkQke","gtCA59XyT9","ulk411LB1L","vkCHHFwEJz",
-"In3NSlXFOB","Z4I1vSmGzv","24ARFzqH0W","RpBQmQChxs","Y1mC0fcwDa","S2DfuvLsmS","EoToPFhtgl","YOfrY5nmWv","StlDJDG4sT","580YD4QMc9",
-"uvf7ASbRYy","xReecvOqCE","OxWIHOUYuF","uTacxatef2","ogLgctlILt","vkCHHWMiS3","29QAzv8yFN","VNCPd8xEKz","FFDuiJJs5m","h1zcHO3iyQ",
-"SjskQ5IhmG","AXpwE7Ow5C","iwzGkm4bxU","OUqFMZUnqt","nlaByHlUbF","Waim6oGu6x","JXljWyEfy9","mz8gxtuDyS","M3zXLEOE1o","taOXKAmdQd",
-"3weIFkB5nP","QWxoTRzaZA","zHF1qQYxC0","h1zcHaL6AJ","zmLYDtlILt","2NslmsqVrf","he9IAMaJQs","Fhtgl5iGN5","bZLvSK4GS8","GWqqX2Yz7E",
-"sx5Glpv0i7","oVQp6mX2GE","d7vjMgjUTu","7X3uyjSjS3","ThjNnn8pJ9","StlDJFPfSE","HP433RpBQm","iKqhrnlaBy","xReec7ku1p","tvdkDoQ87r",
-"55rfBlCMxy","D6rByHzZT8","e6e4zCfgr3","jS1ajS77LH","NhXduM6qcG","zbIYYvkCHH","m4bxUGWqqX","5nmWvpWiOs","OUqFMv8yFN","s4786Kr8ys",
-"cShY2FNYIM","QworuQworu","MaJQshUTw7","CqqaDEOE1o","prNT6MmsIo","O3iyQblLA9","2hEEUb29RJ","HfyNQnnP8o","FGzgpdjsrv","SmGzvpWiOs",
-"jtn0XYh1hF","iB08lMm8si","QClRLAgJHQ","7Ow5CL7cGc","l83UdpvgjS","WDVWJ2Yz7E","HzZT8dhSuH","tjQxsDcpWB","pv0i7lsQGo","yToGWHRxd8",
-"n8pJ9Rxrsm","YOfrYD6rBy","cQOnvWreyP","8FmFH5iGN5","LDk6fQChxs","l83UdReKEW","Mm8siEdBKc","JkzUnFhtgl","2Yz7ERBhp0","WaWsvlkMUA",
-"QbxXcguMb8","6AFT08xEKz","TXQ0ZLbRTH","8cVD3Fhtgl","bgJAz24ARF","JIqXiQClRL","WPmlxjeskS","S2DfusqVrf","Ta8f6RsQUq","t98iWuJScX",
-"KASQ8jtn0X","FxX9qe6e4z","FLsphs93Ml","zmLYDpvgjS","ECMvUjiVBP","d85a97lUXZ","FGzgpDQimp","FxX9qprNT6","dpe1vVBjhz","yEfy9brhlQ",
-"7fsYMQWxoT","Q6hMC0MR5X","FNYIMXflUq","ydG8UQChxs","uN6r3AXpwE","atef2i3pyd","QYxC0TXQ0Z","yToGWyluBx","RACujnlaBy","5nmWv9iGoT",
-"xReeca00b5","FnPFBUmaEv","RmDcrZUnqt","GWqqXMGlTF","8xEKzNhXdu","W7cTsgjUTu","hUTw74W0Tl","F6PT2djsrv","2ZHdkulk41","lViBvY1mC0",
-"pAhR1DG4sT","pAhR1DcpWB","8cVD3dmoS7","8hJdtvLsmS","3weIFiKqhr","l83Udrz7Ut","Cp3mZSs0Zu","HzZT8jS1aj","SWfouNOHsz","XyPZNYf2Ec",
-"MmKGJjzUqR","0Wr5ye6e4z","mX2GERsQUq","yToGWO3iyQ","2ZHdkGrDg7","RsQUqIBe8k","dhSuHtuDyS","BGaQYpiJSk","pvgjSzbIYY","suY4xEOE1o",
-"WPmlxatef2","kZANmpFrrl","64s8NMkgy8","l83UdL7cGc","Ul4a1bZLvS","mX2GEmz8gx","zz4ZUuoStw","U3yw5DG4sT","dmoS70Wr5y","RpBQmmX2GE",
-"tuDySdhSuH","dQ586RkQke","s7MxkJXljW","azIWpFjHXR","ZzJHW0Kyfs","cmXIX3otm6","Cfgr3LbRTH","5nmWvLbRTH","5nmWvzqH0W","pAhR1dQ586",
-"uJScXMkgy8","gf8rIW7cTs","suY4xfLNg8","GSQwjW3VFH","aDGtSGrDg7","9iGoThUTw7","OUYuFsuY4x","OHaBz7fsYM","JXljWIjTwP","piJSkokgRi",
-"pvgjS5Drn0","RzaZApvgjS","blLA9s7Mxk","2TRI7fLNg8","JIqXiZhwG1","gf8rITCgPp","DG4sTXflUq","QworuYjB9t","dQ5864QMc9","ReKEWpvgjS",
-"fmIK1Oz8yZ","Cfgr3lCMxy","TXQ0ZMmKGJ","IKxdLZuDtD","gdQsSOUqFM","3weIFrKDLJ","C2IrcS77LH","8TxD7d85a9","FVMxo5IhmG","IRh48azIWp",
-"wiHrZSs0Zu","7fKYUd7vjM","fcJOyCNHmv","tAOsrK20wK","BpYhVpvgjS","x3LDeo8Uyd","3weIFDLhzM","5Drn0tjQxs","Q6hMC48cHL","AmdQdM3zXL",
-"BpYhV3weIF","Oz8yZNOHsz","taOXKlkMUA","NcICApWiOs","S2Dfun1pmO","MK07Y5iGN5","uPX7GAkKTk","8U2nUk85Ae","SWfoulH1kt","ix74rfFDrJ",
-"tl72W1LB1L","JIqXiOHaBz","pvgjSyluBx","4W0TlWmadA","aDGtSO3iyQ","lXFOBn8pJ9","FcWrWFwEJz","jeskSazIWp","ru4UGD6rBy","jS1ajKASQ8",
-"sx5GlDLhzM","ZhwG1S2Dfu","sx5GlQnJ1S","taOXKix74r","sqVrfMkgy8","FwEJzyvOMI","fmIK1uJScX","zqH0WoGu6x","WPmlxdpe1v","uZPqgMGlTF",
-"AOgEevLsmS","Q6LixyluBx","HfyNQ5iGN5","W3VFHuPX7G","2Yz7EFFDui","fqypyn1pmO","Mkgy8UlU3M","EoToPo8Uyd","vOqCEYf2Ec","t59lRFxX9q",
-"uAWypdpe1v","Yw2oUQbxXc","SbRYyAkKTk","oGu6xfaHir","lH1ktogLgc","yEfy9DG4sT","Nxx9VQssNC","djsrvDG4sT","X6Pin0BmCy","RxrsmM6qcG",
-"580YD0Wr5y","yluBxB3qem","8FmFHo8Uyd","8FmFH8hJdt","yEfy9tl72W","OUqFMd85a9","n1pmOGv3Fq","JkzUn8xEKz","VjCZqDG4sT","VIlwP7fsYM",
-"VNCPd3otm6","lpF6WQbxXc","nnP8o0YAGH","SbRYyfcwDa","HfyNQrKDLJ","CIShGL7cGc","RzaZAcQOnv","HlUbFzHF1q","StlDJGWqqX","IjTwPSbRYy",
-"jzUqRDG4sT","I7p2aru4UG","h1zcHCp3mZ","BGaQYKZamH","b29RJ55rfB","0MR5X07n1c","HRxd80YAGH","FNYIM4QMc9","xXTI4blLA9","1LB1LLbRTH",
-"n1pmOIjTwP","DLhzMpvgjS","iqv4kKZamH","IRh48ThjNn","wiHrZzY1GY","OUYuFDLhzM","kB5nPpT8wu","AmdQdWDVWJ","lsQGoi3pyd","FGzgpVjCZq",
-"8FmFH9iGoT","DcpWBL7cGc","gtCA5aez9y","kB5nPJKWYR","Yh1hFEdBKc","TXQ0ZUvlv4","Zv7z0JKWYR","OUYuFOz8yZ","lkMUAgtCA5","gjUTuNxx9V",
-"s93MlzmLYD","Kr8ysni2v1","DcpWBksJby","1LB1LEOE1o","OHaBzZzJHW","nlaByxXTI4","jS1ajHP433","2NslmMK07Y","ksJbybrhlQ","uoStwzqH0W",
-"tl72WzbIYY","vLsmSCp3mZ","uN6r3taOXK","dhSuHpvgjS","tlILt07n1c","8xEKzStlDJ","FNYIMzz4ZU","qUJMdK4GS8","WPmlxuoStw","HRxd8qQxHP",
-"HP433x3LDe","YjB9tQChxs","faHirYf2Ec","1j5L8Y1mC0","v8yFNx3LDe","taOXKpvgjS","DLhzMUlU3M","HRxd8fLNg8","iqv4kZJTXH","0KyfslCMxy",
-"I7p2a2ZHdk","aL6AJjeskS","ix74rDLhzM","uupzk2DREs","k85AezHF1q","XyPZN8TxD7","RmDcrTa8f6","hSSvQM3zXL","P6bcglj07Q","yluBxK20wK",
-"5IhmGbZLvS","9rlg9gf8rI","5drc6s7Mxk","ZzJHWjS1aj","Gv3FqkB5nP","WreyPv1Hln","VIlwPStlDJ","ZhwG1POUYS","iwzGkgf8rI","MGlTFt59lR",
-"S2DfuPYBf4","5Drn00YAGH","WPmlxFLsph","Q6hMCo8Uyd","zFgtBReKEW","MK07YC2Irc","aL6AJUmaEv","8TxD71LB1L","WMiS3Ul4a1","gIYvE55rfB",
-"Pb1pa580YD","gf8rI24ARF","FwEJzv2eC3","FLspheuZA5","uN6r3OHaBz","8cVD3POUYS","wDajXTa8f6","tuDySKASQ8","d7vjMuTacx","pv0i7WMiS3",
-"M6qcGZUnqt","lkMUAHfyNQ","0YAGHK20wK","lsQGo9y4lw","WPmlxpmeCd","dhSuHs4786","2NslmYh1hF","TwanoJJs5m","P6bcg5iGN5","DcpWBpmeCd",
-"K4GS8gtCA5","ulk41e6e4z","ydG8Uhe9IA","ogLgc9y4lw","BbwgA2DREs","2hEEUUlU3M","HfyNQfFDrJ","jS1aj24ARF","5VZjSdhSuH","i3pydJKWYR",
-"POUYSMaJQs","Oz8yZpAhR1","MmsIoCdyBV","JkzUnMojnP","ni2v1ru4UG","QYxC0iKqhr","Mm8sizFgtB","rKDLJlCMxy","FVMxo618Di","3otm6wiHrZ",
-"Mkgy824ARF","oGu6xYw2oU","W3VFHlCMxy","RkQkeuupzk","gf8rIFVMxo","iKqhr8hJdt","ix74rHfyNQ","GWqqXgIYvE","55rfBvLsmS","5NammKr8ys",
-"guMb87Ow5C","pWiOs2Nslm","64s8N9XyT9","4W0TlciuWz","WPmlxfcwDa","8FmFHuAWyp","gjUTupiJSk","tvdkDdhSuH","RpBQmDLhzM","IjTwPe6e4z",
-"Cfgr3sx5Gl","K20wKydG8U","lj07QpvgjS","RBhp0hE1Ql","fcwDaB3qem","uvf7AMGlTF","Cfgr3KASQ8","EdBKcjtn0X","kZANmMmKGJ","oQ87ryofH3",
-"oQ87rJKWYR","tAOsratef2","uAWyp4dEz6","FxX9qIBe8k","uoStwn8pJ9","jiVBPjzUqR","bgJAzJXljW","ulk41lkMUA","MmsIoDQimp","GXdoHTwano",
-"lsQGosoy9t","uLtKsru4UG","GWqqXl83Ud","JJs5mW7cTs","gf8rIbgJAz","W3VFHFxX9q","ZhwG1aL6AJ","oQ87rS77LH","7fsYMDcpWB","pFrrlOHaBz",
-"EoToPzFgtB","ZUnqtSWfou","fLNg83weIF","tlILtThjNn","SbRYy5iGN5","RmDcrIRh48","zqH0W5drc6","9y4lwuTacx","AkKTk64s8N","aFFssguMb8",
-"jfREuMkgy8","2DREsYh1hF","rhl0JjS1aj","zmLYDECMvU","RpBQm4QMc9","qQxHP5Namm","yEfy9FFDui","QnJ1SLbRTH","mX2GEKASQ8","cmXIXogLgc",
-"tvdkDlXFOB","CqqaDwiHrZ","pmeCdU3yw5","7X3uyVIlwP","8FmFHpFrrl","HP433Oz8yZ","mz8gxWMiS3","BFkb8hSSvQ","VerEAx3LDe","7ku1pMkgy8",
-"5drc6lCMxy","8cVD3OUqFM","v1HlnIKxdL","FFDuiRmDcr","NcICAgdQsS","Pb1pannP8o","a00b5zQt6Q","NcICAJKWYR","d85a9hi5X7","MK07Y5drc6",
-"hYBCKWMiS3","UlU3MpAhR1","HfyNQoGu6x","fLNg8IjTwP","ogLgcJkzUn","aDGtSd85a9","I7p2aDcpWB","OHaBzdjsrv","Dz1R3gtCA5","FNYIMxXTI4",
-"dQ586ECMvU","8xEKzS2Dfu","dpe1v7X3uy","fcJOyAIYUu","Chuy3FcWrW","07n1chi5X7","U3yw5QssNC","4dEz6QnJ1S","cmXIX5iGN5","tlILti7WMQ",
-"yEfy9W7cTs","14FLR5Drn0","fqypyVLTy6","OxWIH5nmWv","jiVBP3otm6","WmadAMkgy8","QbxXcFGzgp","n1pmONxx9V","euZA5h1zcH","zz4ZUK20wK",
-"v8yFNrz7Ut","WreyPcShY2","D6rByTCgPp","sx5GlCK5W7","0YAGHdmoS7","lj07Quupzk","t98iWy94nw","J2mQi55rfB","I7p2aFVMxo","v1HlnuQIcz",
-"8TxD7x3LDe","BCxeChE1Ql","iqv4kbZLvS","xReecnnP8o","cmXIXfmIK1","PYBf4SWfou","QClRL5Namm","NOHszni2v1","i3pydM6qcG","s4786P6bcg",
-"gIYvECIShG","29QAzAgJHQ","LbRTHQWxoT","9XyT9SWfou","FNYIMWmadA","L7cGcG1RhS","8U2nURmDcr","lsQGoMmsIo","5drc6WreyP","hUTw7IRh48",
-"K20wKZv7z0","ciuWzECMvU","QClRLpAhR1","ZuDtD48cHL","J2mQiS2Dfu","QWxoTokgRi","48cHLciuWz","ciuWz7ku1p","PYBf4dmoS7","cShY2wDajX",
-"MaJQsCNHmv","29QAz4QMc9","yluBxuAWyp","kB5nPW3VFH","B3qemv1Hln","AXpwEOUqFM","K4GS8GWqqX","e6e4zWaim6","xReecfFDrJ","yvOMIrhl0J",
-"d7vjMJkzUn","s93MlDz1R3","0Wr5ytvdkD","x3LDetvdkD","cQOnvBpYhV","MK07YUl4a1","55rfBFFDui","faHirdQ586","oGu6x7Ow5C","x3LDeoVQp6",
-"pmeCdAIYUu","Zv7z0zFgtB","faHirhYBCK","S2DfuzFgtB","BpYhVdjsrv","lj07Q5ZaEz","Nxx9Vx3LDe","MmKGJ0PktI","x3LDeF6PT2","GWqqXe6e4z",
-"uAWypLDk6f","J2mQipT8wu","hE1QlVIlwP","WaWsviqv4k","HzZT8NhXdu","IRh48CNHmv","UmaEvblLA9","07n1cMojnP","FnPFBtvdkD","8TxD7CdyBV",
-"24ARFZ4I1v","WMiS3okgRi","qaofN3weIF","yluBxfLNg8","Z4I1vKASQ8","dQ586BGaQY","FwEJzGrDg7","8FmFHuN6r3","fLNg89eoRc","LDk6ftAOsr",
-"lH1ktoVQp6","48cHLoQ87r","AOgEeUmaEv","HfyNQ2DREs","Kr8ys9GXkX","4QMc9IjTwP","YjB9t2TRI7","vLsmSRACuj","9iGoTQYxC0","IBe8klj07Q",
-"fLNg88TxD7","v8yFNuoStw","IBe8kblLA9","rKDLJaL6AJ","bgJAzNhXdu","14FLR6q6L9","RsQUqhE1Ql","fcJOyHP433","he9IAReKEW","AmdQdb29RJ",
-"xciqpMezSW","fqypyZhwG1","9GXkXU3yw5","tjQxsyEfy9","SmGzvcL0aE","GXdoHNo0Qb","uvf7An1pmO","Nxx9VAIYUu","gdQsS6q6L9","jtn0XQ6hMC",
-"VBjhzG1RhS","M6qcGni2v1","WaWsvgf8rI","SWfouuQIcz","gjUTuJKWYR","29QAzKsjRK","0h1b1lweGy","aL6AJtaOXK","Ta8f62DREs","B3qemTCgPp",
-"FFDui1LB1L","MezSWOxWIH","ulk41lpF6W","5nmWv7ku1p","7hyVvh1zcH","Mkgy8uvf7A","Q6LixzmLYD","nFqikEdBKc","s7Mxko8Uyd","No0QbRBhp0",
-"i7WMQtaOXK","5iGN5iwzGk","POUYSuvf7A","Nxx9VzFgtB","fcJOyru4UG","n1pmOEOE1o","Fhtgl4dEz6","CqqaDYw2oU","DLhzMulk41","ZzJHWt59lR",
-"zz4ZUIKxdL","lH1ktDz1R3","guMb8yEfy9","5ZaEz8hJdt","M6qcGl83Ud","uQIczuupzk","580YDtAOsr","okgRilXFOB","M6qcGazIWp","LbRTHVBjhz",
-"pWiOsZzJHW","v8yFNjeskS","qQxHPnFqik","OHaBzhUTw7","NOHsz618Di","uvf7ArKDLJ","yvOMI3otm6","Yf2Ec0ao3l","2TRI7m4bxU","HfyNQWPmlx",
-"DLhzMtuDyS","OUqFMblLA9","K20wKdpe1v","L7cGcSs0Zu","prNT6uQIcz","iqv4kqUJMd","NcICAtlILt","i7WMQxXTI4","cL0aEBFkb8","2Yz7EQYxC0",
-"TXQ0ZIjTwP","P6bcgTCgPp","uPX7GeuZA5","sqVrfhE1Ql","CdyBV3weIF","64s8N9iGoT","MGlTFRkQke","9eoRccL0aE","WPmlxQ6hMC","2hEEUSbRYy",
-"zz4ZUyToGW","ZzJHWFLsph","uupzkDQimp","W7cTst59lR","UlU3MOUYuF","4W0TlpiJSk","8hJdtDLhzM","lpF6Ws93Ml","pv0i7AIYUu","FwEJzQssNC",
-"OUqFMCfgr3","QbxXcDcpWB","0KyfsWmadA","yluBx7hyVv","lj07Qx3LDe","xReecuJScX","lweGyCqqaD","Ta8f6fFDrJ","tAOsrlXFOB","48cHL29QAz",
-"618DizHF1q","brhlQCK5W7","pvgjStlILt","pv0i7U3yw5","CK5W7lCMxy","580YDo8Uyd","sx5GlzQt6Q","h1zcHJIqXi","TXQ0ZogLgc","uAWypXyPZN",
-"2DREswiHrZ","vLsmSFxX9q","lViBv8hJdt","Waim64dEz6","Ss0ZuJkzUn","zmLYDjfREu","lsQGozFgtB","i7WMQMezSW","JXljWfcwDa","dmoS7i7WMQ",
-"2DREsIBe8k","zY1GYzmLYD","BGaQYcQOnv","RxrsmYjB9t","t59lRjtn0X","S2Dfuaez9y","tjQxsQChxs","xReec4dEz6","4dEz6pFrrl","dQ5868RCUA",
-"RBhp0UlU3M","v2eC3EoToP","Yf2EcqUJMd","iqv4kGXdoH","azIWpzHF1q","jSjS3No0Qb","x3LDe8xEKz","IBe8kCNHmv","4W0Tlix74r","suY4xYf2Ec",
-"n8pJ9sx5Gl","jfREuCp3mZ","Uvlv4ECMvU","MGlTFPYBf4","ZUnqtgjUTu","Yw2oUIRh48","pv0i7d7vjM","o8UydEoToP","SmGzvfFDrJ","kB5nPoGu6x",
-"5VZjSZv7z0","oGu6xzz4ZU","rKDLJciuWz","24ARFiKqhr","64s8Nh1zcH","nlaBysoy9t","AkKTkNhXdu","Dz1R3tl72W","vLsmSZv7z0","VLTy6POUYS",
-"7X3uya00b5","8xEKzO3iyQ","W3VFHtuDyS","Q6hMCI7p2a","jfREuokgRi","24ARFFjHXR","RzaZAuupzk","iwzGkVNCPd","wDajX8xEKz","ZUnqtNo0Qb",
-"vkCHHs93Ml","iqv4kzFgtB","AkKTkjtn0X","9eoRcQYxC0","i3pydJRJQB","WreyPtAOsr","fcJOyjiVBP","k85AeVjCZq","v2eC3cShY2","zFgtBCNHmv",
-"rhl0JReKEW","Yh1hFd85a9","s93MlfmIK1","Pb1pataOXK","qUJMdGWqqX","5VZjSMm8si","S77LHrhl0J","i7WMQb29RJ","WDVWJi3pyd","qUJMdL7cGc",
-"No0Qbi7WMQ","9XyT9OUYuF","piJSkpvgjS","AXpwEi7WMQ","Y1mC0AXpwE","QWxoTECMvU","h1zcHQbxXc","64s8NhYBCK","5Drn02TRI7","sx5GlJJs5m",
-"FPfSEcmXIX","9y4lwuAWyp","djsrvVjCZq","OUqFMqQxHP","29QAzuoStw","iB08lYOfrY","LbRTHZuDtD","WreyP8hJdt","S77LHprNT6","8hJdtPOUYS",
-"cQOnvS2Dfu","e6e4zoVQp6","OUYuF64s8N","fLNg8uPX7G","Qworu8cVD3","K20wK0ao3l","FxX9qkB5nP","0h1b145cIH","CIShGksJby","WPmlxDLhzM",
-"5Nammmz8gx","n1pmOjtn0X","xXTI4jS1aj","pvgjSBGaQY","EoToPaez9y","vLsmSgIYvE","2ZHdk9rlg9","Uvlv45Namm","QWxoTn8pJ9","GrDg77hyVv",
-"Q6hMC8TxD7","2NslmokgRi","14FLRGrDg7","In3NSLDk6f","n8pJ9zHF1q","iwzGkQ6Lix","ThjNnB3qem","0Wr5yAIYUu","zmLYDzQt6Q","DLhzMaez9y",
-"ciuWzbrhlQ","lweGy24ARF","2hEEUOHaBz","HfyNQFxX9q","gdQsSgdQsS","GrDg7HlUbF","X6PinOUqFM","dpe1vlViBv","UlU3M45cIH","S2Dfu29QAz",
-"GSQwjuZPqg","m4bxUuJScX","9iGoT4QMc9","XflUqZuDtD","W7cTsIRh48","v1HlnFPfSE","WreyPsoy9t","Ta8f6bZLvS","xReecru4UG","7fsYMiwzGk",
-"8TxD7dQ586","aez9y24ARF","MaJQsl83Ud","RkQke64s8N","Gv3FquJScX","No0QbO3iyQ","9iGoTRBhp0","prNT6yofH3","5NammuJScX","Ss0Zu580YD",
-"azIWpRsQUq","Gv3FqqUJMd","ZJTXHCNHmv","VjCZqS77LH","fqypyVjCZq","o8UydECMvU","FhtglvLsmS","gIYvEdmoS7","D6rByiB08l","SmGzv64s8N",
-"hSSvQZuDtD","WDVWJvLsmS","07n1cWaim6","ZhwG1uQIcz","0ao3lTa8f6","3otm6euZA5","580YDuLtKs","Yf2EcC2Irc","POUYS4dEz6","CxVEflXFOB",
-"2TRI7iKqhr","pmeCdlj07Q","CqqaD9XyT9","W3VFHfcJOy","m4bxUfmIK1","ydG8UNOHsz","MmsIoWmadA","HlUbFCIShG","s4786AgJHQ","2NslmzmLYD",
-"8hJdtiB08l","nnP8oFcWrW","0BmCykZANm","t98iWRxrsm","P6bcgkB5nP","OHaBzFLsph","Y1mC00MR5X","cQOnvzz4ZU","aez9yGSQwj","BpYhViwzGk",
-"9eoRcLbRTH","WDVWJ580YD","tl72Wni2v1","POUYSyluBx","fcJOy07n1c","7lUXZoVQp6","lkMUALewvM","RkQkeyEfy9","7hyVvgjUTu","zbIYYFhtgl",
-"NhXduMaJQs","4dEz6oGu6x","0ao3lOUYuF","wiHrZ5IhmG","BbwgA7fKYU","uZPqgZuDtD","JIqXilXFOB","AkKTkMkgy8","yToGWkB5nP","BFkb8ulk41",
-"s7MxkFPfSE","HlUbFwDajX","IBe8kFVMxo","ZUnqtx3LDe","8hJdtHP433","StlDJ14FLR","2TRI7FFDui","nlaByjtn0X","Q6Lixni2v1","I7p2a0Wr5y",
-"Zv7z0Rxrsm","U3yw5jtn0X","o8UydNAFuw","Y1mC0lweGy","0MR5Xzz4ZU","lCMxy5Mg9r","EoToPIBe8k","iqv4k0PktI","ix74rZuDtD","WPmlxx3LDe",
-"brhlQZUnqt","bgJAzgtCA5","8xEKzlweGy","tuDyS4W0Tl","WmadAMm8si","IRh48SbRYy","soy9t9XyT9","9XyT9atef2","pFrrllXFOB","Twano5Drn0",
-"L7cGcC2Irc","9GXkXv2eC3","RpBQmRkQke","guMb8rKDLJ","0YAGH2Nslm","oGu6xjeskS","X6Pinlm0pD","XflUqYh1hF","FxX9qQClRL","LbRTHsx5Gl",
-"o8UydPYBf4","yluBxCp3mZ","3otm6BGaQY","7lUXZWmadA","JXljWJRJQB","mz8gxFNYIM","tl72WpAhR1","guMb8Fhtgl","Pb1pa0Kyfs","IjTwPzmLYD",
-"5nmWvtaOXK","9rlg9Zv7z0","SWfouJkzUn","JJs5mprNT6","vkCHHkZANm","zHF1qXflUq","t59lRReKEW","dmoS7XflUq","pv0i7t59lR","IBe8kCdyBV",
-"MmKGJ55rfB","uN6r3a00b5","In3NSsqVrf","d85a9uZPqg","No0QbxReec","nFqikW7cTs","WDVWJlj07Q","RmDcrcmXIX","POUYSHRxd8","618Di4W0Tl",
-"AgJHQtjQxs","I7p2aGWqqX","k85Aejtn0X","J2mQiB3qem","C2IrcYh1hF","8xEKzP6bcg","Oz8yZSjskQ","zFgtBDz1R3","Zv7z0DG4sT","Cfgr3Oz8yZ",
-"ZzJHWQYxC0","i7WMQ8U2nU","OHaBzBGaQY","uLtKsLbRTH","FFDuiFGzgp","7fKYU5VZjS","1j5L8lViBv","lViBv1v5hH","tAOsr7X3uy","4W0TluPX7G",
-"v8yFNGv3Fq","IRh48VNCPd","8RCUApmeCd","RACujpvgjS","5nmWvThjNn","Z4I1vYjB9t","WmadA5drc6","sqVrftlILt","VNCPdZJTXH","uPX7GIKxdL",
-"pT8wuGv3Fq","QssNCfqypy","uTacxFxX9q","FhtglzbIYY","FnPFB0BmCy","blLA9FVMxo","MK07Ytl72W","zY1GYM6qcG","7lUXZd7vjM","5NammgdQsS",
-"hSSvQMm8si","FcWrWJRJQB","QWxoTUmaEv","kZANmFNYIM","G1RhSQworu","i3pydMmsIo","jS1ajpv0i7","8U2nUFPfSE","qaofNK20wK","2TRI7JJs5m",
-"MmKGJwDajX","jeskSFVMxo","SmGzvVprf2","AgJHQuQIcz","BFkb8Uvlv4","t98iWPb1pa","4W0Tlpv0i7","FcWrWaez9y","TwanojeskS","zmLYD14FLR",
-"M3zXLUvlv4","ni2v1lsQGo","U3yw5yEfy9","W3VFHuJScX","lCMxy2hEEU","8TxD7lweGy","FGzgpPYBf4","djsrvLewvM","S77LH2hEEU","UmaEvt59lR",
-"8cVD3JKWYR","suY4xt98iW","lXFOBaDGtS","oQ87rWDVWJ","vOqCEa00b5","EOE1okZANm","soy9tuLtKs","5IhmGzmLYD","GSQwjiKqhr","MGlTFOUqFM",
-"5iGN59eoRc","fcwDaGv3Fq","S77LH0h1b1","9iGoTYw2oU","pT8wuh1zcH","0Kyfs5Drn0","W7cTsFVMxo","IRh48WMiS3","J2mQi5Drn0","pvgjSwiHrZ",
-"Q6LixMm8si","cShY2t59lR","Cp3mZhSSvQ","uoStwQssNC","LDk6fBCxeC","lkMUAHlUbF","ZJTXHs4786","pAhR1FGzgp","KASQ8MmKGJ","nlaBy1j5L8",
-"AmdQdvOqCE","Cfgr3G1RhS","QClRLb29RJ","Uvlv4Oz8yZ","1j5L8BpYhV","gdQsSGv3Fq","6q6L9piJSk","dpe1vYh1hF","O3iyQZUnqt","O3iyQoGu6x",
-"pFrrltAOsr","AIYUuWmadA","5iGN5Chuy3","he9IAQ6hMC","pAhR1soy9t","07n1ci7WMQ","GXdoH4dEz6","Z4I1vIBe8k","sqVrfRpBQm","I7p2aMojnP",
-"dhSuHxXTI4","gdQsSkZANm","NOHszlpF6W","lkMUAlH1kt","5Drn0W7cTs","0h1b1RpBQm","pFrrls93Ml","Uvlv4DQimp","6q6L914FLR","LewvMD6rBy",
-"DG4sTBGaQY","tl72WvkCHH","uPX7GCIShG","JRJQBfqypy","7Ow5CRkQke","iB08lRpBQm","KsjRKhi5X7","AOgEeFhtgl","7lUXZiqv4k","5drc6cL0aE",
-"blLA9WPmlx","No0Qb2hEEU","5Mg9rcQOnv","TCgPpThjNn","SWfouOxWIH","QbxXcGXdoH","7fKYUAkKTk","FLsph1LB1L","64s8NBCxeC","8U2nUIBe8k",
-"Waim6D6rBy","OHaBzYw2oU","5VZjSqQxHP","FLsphYh1hF","ZhwG1jzUqR","s93Mls4786","TCgPpRBhp0","StlDJ0Wr5y","oGu6xQClRL","MojnPWmadA",
-"jeskSi3pyd","oGu6xaL6AJ","ksJbydQ586","CxVEfmz8gx","618DiYjB9t","ru4UG0h1b1","suY4xAmdQd","zz4ZUKASQ8","M3zXLwiHrZ","taOXKxReec",
-"Nxx9V2hEEU","FNYIMpFrrl","AXpwEDz1R3","GWqqXd7vjM","POUYSLewvM","POUYSB3qem","64s8NpAhR1","RACujdhSuH","RxrsmLewvM","RBhp0JKWYR",
-"okgRilsQGo","lkMUATCgPp","gf8rIDcpWB","W7cTsFwEJz","Q6hMCQ6hMC","MojnPpFrrl","SWfouMmsIo","ZUnqtrKDLJ","FhtgljfREu","jtn0Xgf8rI",
-"1j5L84dEz6","Uvlv4i7WMQ","bZLvSokgRi","gIYvEFnPFB","EoToPjSjS3","POUYSBCxeC","lpF6Wn8pJ9","RACujMmKGJ","CIShGh1zcH","FPfSENhXdu",
-"9eoRc5nmWv","XflUqS77LH","LbRTHWaWsv","tuDySJKWYR","AmdQdIjTwP","64s8N7hyVv","cL0aETXQ0Z","uupzkC2Irc","SWfout98iW","cL0aEaL6AJ",
-"tvdkDsqVrf","5drc6uAWyp","i7WMQQworu","X6PinzFgtB","Mm8siRBhp0","lViBvCK5W7","O3iyQv1Hln","hYBCK618Di","0h1b17X3uy","rKDLJuoStw",
-"0YAGHTa8f6","cL0aERBhp0","CxVEfU3yw5","64s8NyluBx","QssNC580YD","HzZT8lViBv","QnJ1SvLsmS","piJSkpAhR1","ru4UGSbRYy","e6e4zatef2",
-"BpYhVZUnqt","1j5L8tAOsr","zqH0WOz8yZ","VBjhz0Kyfs","QbxXcQ6hMC","rKDLJhE1Ql","JKWYRFcWrW","t98iWMm8si","oVQp68cVD3","djsrv1LB1L",
-"VBjhzWMiS3","jSjS3XyPZN","XflUqhE1Ql","IjTwPLbRTH","GWqqXOUYuF","J2mQio8Uyd","9rlg9l83Ud","55rfBBCxeC","UlU3MOz8yZ","1j5L8Cp3mZ",
-"HP433pT8wu","uAWyp64s8N","QworuMGlTF","iKqhratef2","FwEJzVprf2","euZA5EoToP","EoToPv1Hln","Nxx9VVBjhz","FGzgpnnP8o","BFkb8JKWYR",
-"jiVBPI7p2a","B3qem1j5L8","ogLgcqUJMd","uN6r3e6e4z","rz7UtcShY2","bgJAzCIShG","pmeCdWMiS3","qUJMdKASQ8","3otm6bZLvS","bZLvSUmaEv",
-"lm0pDuJScX","fqypy2Yz7E","ni2v1xReec","FLsphTCgPp","zz4ZU48cHL","2hEEUy94nw","4dEz6vOqCE","L7cGc14FLR","yvOMI64s8N","OUYuFfLNg8",
-"7lUXZYjB9t","atef2lsQGo","C2Irc7Ow5C","4QMc9piJSk","uvf7AQChxs","I7p2apmeCd","uQIczgf8rI","FFDuilXFOB","WreyPm4bxU","piJSkVBjhz",
-"mX2GEUvlv4","uZPqg9rlg9","G1RhStl72W","S77LHk85Ae","DG4sT580YD","IBe8kQClRL","pWiOsM6qcG","Nxx9VSWfou","ksJbyStlDJ","lm0pDFNYIM",
-"hE1QlyToGW","Pb1pa0BmCy","zz4ZUGWqqX","S2DfuWreyP","sx5GlFVMxo","AOgEeM6qcG","Dz1R3iqv4k","AXpwEzz4ZU","zQt6Quupzk","48cHLUlU3M",
-"ulk41GXdoH","Ss0ZuAmdQd","VLTy68cVD3","LewvMJJs5m","SbRYyyluBx","QworuuPX7G","SWfouyluBx","RkQkeQ6Lix","Q6Lix2DREs","JRJQBDcpWB",
-"7fsYM9XyT9","K20wKh1zcH","n1pmOv1Hln","pWiOsAmdQd","MmsIoqUJMd","hUTw7AmdQd","okgRiatef2","dhSuHh1zcH","xReecY1mC0","suY4xsx5Gl",
-"Q6LixcL0aE","CK5W7aez9y","fmIK1EoToP","UmaEvk85Ae","iqv4kDQimp","GSQwjVNCPd","jtn0XCK5W7","FxX9qjiVBP","YjB9tTa8f6","7fKYUB3qem",
-"nlaByChuy3","5ZaEzIjTwP","1LB1LsqVrf","xReec5nmWv","9GXkXtAOsr","FwEJzAgJHQ","gjUTu0PktI","CIShGmz8gx","pmeCdS2Dfu","blLA9lkMUA",
-"K20wKqQxHP","FNYIMPOUYS","7ku1pOHaBz","tl72WfmIK1","4dEz6AgJHQ","WMiS3n1pmO","FcWrWIjTwP","AmdQdfcwDa","uLtKslCMxy","9y4lwpAhR1",
-"I7p2a8hJdt","ogLgcjzUqR","wDajXDLhzM","t98iW4QMc9","jfREuPYBf4","1j5L8jeskS","In3NSNcICA","o8UydMezSW","DG4sTJIqXi","VjCZq45cIH",
-"ReKEWiqv4k","OxWIHZhwG1","6q6L9MmsIo","n1pmOVIlwP","3weIF5iGN5","ulk41azIWp","24ARFVLTy6","FcWrWYf2Ec","lCMxyThjNn","dQ586v8yFN",
-"aFFssvkCHH","dmoS7kZANm","lViBvFhtgl","7fsYMn1pmO","aez9yGrDg7","4dEz61LB1L","NOHszStlDJ","tvdkDv2eC3","oQ87rcL0aE","wiHrZWmadA",
-"zmLYDLbRTH","dmoS7b29RJ","sqVrfMaJQs","wDajXStlDJ","2Yz7EPb1pa","NcICA5Drn0","hYBCKQworu","BCxeCCp3mZ","CIShGNOHsz","JRJQBSWfou",
-"0ao3l16lHc","suY4xtvdkD","8TxD7uAWyp","yofH3uTacx","MezSWsuY4x","AIYUuru4UG","0PktIFLsph","Waim65IhmG","OHaBznlaBy","VLTy6L7cGc",
-"JJs5m7fsYM","ZzJHWuN6r3","cQOnvHfyNQ","e6e4zFcWrW","dhSuHRBhp0","Yh1hFtl72W","Cp3mZjzUqR","5Mg9rwDajX","5ZaEzG1RhS","IKxdLrz7Ut",
-"lXFOB3weIF","Nxx9Vb29RJ","uoStw4QMc9","5IhmGgtCA5","dmoS7dmoS7","djsrv1j5L8","8TxD7azIWp","5nmWvqUJMd","Yw2oUWDVWJ","WDVWJprNT6",
-"IKxdL7hyVv","WPmlxgjUTu","KZamHUl4a1","t98iWqQxHP","KsjRK5drc6","pWiOsxReec","4QMc9fFDrJ","SbRYyrhl0J","L7cGcQssNC","pWiOsqQxHP",
-"yEfy9JXljW","tlILtSWfou","gIYvEdpe1v","K4GS8zbIYY","6AFT0AkKTk","ECMvUkZANm","VBjhzaFFss","EoToP8xEKz","O3iyQQ6hMC","DLhzM7lUXZ",
-"0ao3l9iGoT","AgJHQfLNg8","v1HlnWreyP","lj07Q4dEz6","StlDJyEfy9","S77LH5ZaEz","2TRI7W7cTs","brhlQBCxeC","xReecMmKGJ","K20wKuvf7A",
-"tl72WNOHsz","Z4I1v9GXkX","FFDuiP6bcg","0PktIrz7Ut","RpBQmZ4I1v","EOE1oBbwgA","FLsphTa8f6","gdQsS9XyT9","qUJMdcmXIX","n8pJ9uTacx",
-"EoToPlweGy","oQ87rRpBQm","iB08lWmadA","EOE1oUmaEv","GrDg7pvgjS","AmdQdlXFOB","5VZjSfmIK1","5VZjSjSjS3","16lHcYOfrY","SbRYyQnJ1S",
-"FFDuit59lR","lm0pDRzaZA","vOqCE0ao3l","SbRYy7fsYM","JXljWNAFuw","7fsYM0ao3l","IKxdLuZPqg","gjUTuYw2oU","GXdoHoVQp6","blLA9nnP8o",
-"lm0pDiKqhr","HzZT8pmeCd","pmeCdAXpwE","SmGzvzz4ZU","uvf7ASs0Zu","fqypy48cHL","PYBf4uJScX","k85AeCIShG","5Mg9rdhSuH","vOqCEhSSvQ",
-"ix74r9rlg9","In3NS4W0Tl","9rlg9WmadA","zFgtBHfyNQ","azIWpdjsrv","Twano3weIF","VNCPdVIlwP","KsjRK9XyT9","hSSvQ0MR5X","FVMxouoStw",
-"cL0aEgIYvE","zQt6Qdjsrv","QssNClj07Q","5ZaEzyEfy9","MaJQsFnPFB","KsjRKtlILt","DQimpnlaBy","FVMxoIjTwP","OUqFMqUJMd","yToGWYw2oU",
-"24ARF07n1c","U3yw5MmKGJ","7Ow5CThjNn","azIWpXyPZN","VerEA9rlg9","okgRi4QMc9","lm0pD8TxD7","MmKGJJKWYR","gf8rI580YD","9eoRcxReec",
-"hE1Ql3otm6","DQimplj07Q","lpF6WJXljW","07n1cfmIK1","JIqXiS77LH","OUqFMuPX7G","POUYSChuy3","FLsphVLTy6","W3VFHHfyNQ","zmLYDwiHrZ",
-"2hEEUuN6r3","xXTI4lpF6W","0ao3lbZLvS","AIYUuNcICA","pWiOsVjCZq","VLTy6jtn0X","2hEEUFjHXR","8U2nU0BmCy","Cp3mZ8hJdt","7Ow5CTwano",
-"JkzUnjtn0X","In3NSMojnP","7Ow5CRACuj","RzaZAZuDtD","IKxdLatef2","pmeCdYw2oU","64s8NjeskS","GXdoHFVMxo","14FLRCqqaD","29QAzciuWz",
-"nnP8oXflUq","HzZT8rz7Ut","hUTw7aDGtS","bZLvSLDk6f","CxVEfxXTI4","2ZHdkSWfou","Ss0ZuS77LH","ogLgcuAWyp","lkMUAECMvU","zqH0WpFrrl",
-"djsrvuJScX","7ku1pEoToP","Ss0ZutaOXK","sx5GlpvgjS","ReKEWUl4a1","d7vjM5Namm","fLNg8RpBQm","uupzk5ZaEz","gIYvELbRTH","kB5nPmz8gx",
-"FcWrW9y4lw","zqH0WcQOnv","jeskSmz8gx","uLtKslj07Q","1LB1LyToGW","h1zcHs7Mxk","gdQsSEdBKc","uAWyp2hEEU","nlaByS77LH","WDVWJk85Ae",
-"SmGzvCqqaD","SjskQ5Drn0","Oz8yZuTacx","QChxsRACuj","uQIczYOfrY","tl72WjzUqR","5VZjS1j5L8","yToGWJIqXi","580YDkB5nP","GWqqX7hyVv",
-"Cfgr3yvOMI","AXpwEnnP8o","VNCPdTCgPp","GSQwjlweGy","AXpwEpiJSk","kZANmhe9IA","QClRLZuDtD","B3qemS77LH","0h1b1pWiOs","tuDySk85Ae",
-"ix74r7X3uy","7hyVvhSSvQ","2ZHdk29QAz","he9IAVerEA","zQt6Qe6e4z","9GXkXogLgc","jfREuy94nw","oQ87rCK5W7","oGu6xDLhzM","uPX7GlCMxy",
-"mz8gxeuZA5","KZamHguMb8","bZLvSs7Mxk","hUTw7W7cTs","U3yw5RmDcr","NcICAlpF6W","PYBf49eoRc","hE1QlhE1Ql","8cVD35Drn0","9GXkXMezSW",
-"FjHXRUvlv4","d85a93weIF","hE1QlQ6Lix","v1HlnMGlTF","xciqplXFOB","L7cGc5ZaEz","FwEJzGXdoH","GXdoH9eoRc","zmLYDsx5Gl","x3LDeDG4sT",
-"0YAGHhe9IA","VIlwP8RCUA","y94nwsoy9t","iwzGkVprf2","Yf2EcpFrrl","3otm6piJSk","BCxeCStlDJ","2ZHdkfaHir","JJs5m618Di","Chuy3Q6Lix",
-"Yh1hFhi5X7","VIlwPhYBCK","LewvMK20wK","FLsphazIWp","uupzkMGlTF","2ZHdk14FLR","14FLRoGu6x","5drc6FwEJz","rhl0JkB5nP","aFFssNxx9V",
-"5ZaEzAmdQd","zFgtBCqqaD","AIYUuIBe8k","ksJbycShY2","RmDcr7fKYU","AkKTk0Wr5y","Dz1R30Kyfs","bgJAzQClRL","QYxC0In3NS","1LB1LPOUYS",
-"gIYvEECMvU","7lUXZ0Wr5y","faHirYw2oU","Gv3FqogLgc","Ss0ZuQYxC0","vOqCEF6PT2","IRh48TCgPp","3weIFo8Uyd","cQOnvh1zcH","zY1GYYf2Ec",
-"StlDJeuZA5","0Wr5yRzaZA","lkMUArKDLJ","vkCHHAOgEe","HP4330PktI","7Ow5C0ao3l","zY1GYKZamH","No0QbQClRL","LewvMfmIK1","ix74ruPX7G",
-"SjskQDG4sT","rz7UtoQ87r","4dEz6ogLgc","dQ586I7p2a","9GXkXhE1Ql","tl72WMm8si","Zv7z0Q6Lix","FPfSEFjHXR","hE1Qlgf8rI","yvOMICK5W7",
-"uQIczOUqFM","FnPFBkZANm","azIWp8hJdt","HRxd8EOE1o","580YDW3VFH","iKqhrtlILt","yvOMIOUqFM","d85a9Vprf2","oVQp6gf8rI","0KyfsuLtKs",
-"lm0pDkB5nP","KsjRKZzJHW","U3yw5pvgjS","IRh48JkzUn","nnP8ooQ87r","jfREurKDLJ","RzaZAuAWyp","FFDuiIBe8k","RsQUqDQimp","NcICA7X3uy",
-"AIYUuzHF1q","mX2GE1LB1L","Dz1R3Twano","a00b58RCUA","2TRI7XyPZN","djsrvRBhp0","NhXdutaOXK","vkCHHAXpwE","7ku1p0MR5X","lViBvjeskS",
-"lm0pDhUTw7","jiVBPBCxeC","POUYSSjskQ","JJs5mpvgjS","QYxC09XyT9","5IhmG2TRI7","tl72WVIlwP","RxrsmNhXdu","jtn0XAXpwE","n8pJ9VBjhz",
-"Vprf2QbxXc","Pb1pa9XyT9","nFqikrKDLJ","5VZjS9GXkX","HRxd8t59lR","WPmlxrz7Ut","bgJAzWPmlx","QnJ1SFhtgl","soy9tSbRYy","qQxHPv1Hln",
-"SbRYy2DREs","OUYuFPYBf4","nFqikcL0aE","FwEJzFLsph","OHaBzhe9IA","k85AeEoToP","m4bxUTwano","07n1c5Namm","zFgtBQssNC","ZhwG1ogLgc",
-"RkQkeciuWz","IBe8kuLtKs","BpYhV8cVD3","DQimpHfyNQ","RsQUqSs0Zu","iB08lyofH3","WPmlx5Namm","aDGtS48cHL","FFDuifcJOy","6AFT07Ow5C",
-"uLtKsv8yFN","XyPZNVerEA","2hEEUQWxoT","OUqFM8FmFH","P6bcgtuDyS","OUYuFpAhR1","FFDuiv2eC3","zY1GYjfREu","9XyT9wiHrZ","7ku1pBbwgA",
-"29QAzQssNC","WaWsvpT8wu","LDk6fDcpWB","ECMvUIn3NS","JRJQBlweGy","uJScXWMiS3","faHir0MR5X","WreyPWPmlx","iB08lguMb8","lkMUAL7cGc",
-"EdBKcS2Dfu","GrDg7vkCHH","HlUbFSs0Zu","aL6AJVBjhz","55rfBrhl0J","AXpwEnlaBy","h1zcH7X3uy","iqv4kWMiS3","3weIFb29RJ","fcJOy2hEEU",
-"LbRTH9y4lw","3otm6BpYhV","VerEAQ6hMC","k85Ae7ku1p","Mm8sixReec","SmGzvSs0Zu","hUTw77lUXZ","uQIczVNCPd","uPX7Ghe9IA","6q6L9Vprf2",
-"G1RhSF6PT2","7fsYMni2v1","GrDg7HRxd8","yvOMItjQxs","nlaBy07n1c","7lUXZYf2Ec","BbwgA6AFT0","FVMxozFgtB","uZPqgy94nw","dpe1vAkKTk",
-"O3iyQb29RJ","9GXkXuoStw","QClRL45cIH","KsjRKuvf7A","NOHszlweGy","2Yz7E7lUXZ","Y1mC0pT8wu","6q6L9jSjS3","BCxeClH1kt","O3iyQnFqik",
-"UlU3M2Yz7E","U3yw5POUYS","wiHrZtAOsr","lsQGo1j5L8","okgRiZuDtD","0BmCyCqqaD","EOE1ot59lR","4W0Tl6q6L9","F6PT2ECMvU","8cVD3nlaBy",
-"iwzGklXFOB","nlaByrz7Ut","pvgjSfmIK1","ulk41x3LDe","ZJTXHpWiOs","jiVBPfqypy","zHF1qBGaQY","7X3uy0Wr5y","QnJ1SNo0Qb","9y4lwSs0Zu",
-"IRh48gdQsS","iqv4kdjsrv","t59lRBpYhV","XflUqcShY2","lCMxy580YD","XflUqguMb8","StlDJb29RJ","b29RJ7fKYU","kB5nPfcJOy","nlaBy7fsYM",
-"ix74rmz8gx","blLA99eoRc","lXFOBtl72W","RACujYjB9t","AkKTk0YAGH","kB5nPhUTw7","FcWrWpFrrl","vOqCEUvlv4","EdBKc8RCUA","I7p2ahUTw7",
-"AmdQdVNCPd","TCgPpECMvU","RBhp0DLhzM","cmXIXtaOXK","FFDuibrhlQ","zHF1qFNYIM","zHF1qQWxoT","JRJQB07n1c","dmoS7FnPFB","TCgPpWPmlx",
-"DLhzMUl4a1","lViBvVerEA","GSQwjpmeCd","hYBCKIn3NS","VjCZqDQimp","EoToPfFDrJ","Cp3mZuupzk","8xEKzuJScX","VNCPd9GXkX","OUqFM8U2nU",
-"2hEEUX6Pin","jtn0X0Wr5y","2TRI75Mg9r","oQ87rrz7Ut","16lHc2Yz7E","7Ow5CokgRi","azIWpuQIcz","U3yw5ni2v1","n8pJ9HRxd8","7ku1p7fKYU",
-"2Yz7E2hEEU","FNYIMpiJSk","o8Uyd2Nslm","zQt6Qn8pJ9","mX2GEZhwG1","64s8Nt59lR","B3qem2Yz7E","Mkgy8uQIcz","No0QbHfyNQ","aez9ydQ586",
-"Yf2EcKZamH","zFgtBulk41","KZamHciuWz","gdQsSCdyBV","lViBvuvf7A","Chuy3KZamH","WPmlxMGlTF","tjQxs0Kyfs","FhtgluJScX","cmXIXC2Irc",
-"DQimpIjTwP","fqypyuoStw","azIWpfcJOy","GSQwjuAWyp","zY1GYatef2","S2DfuWPmlx","4W0TlI7p2a","3weIFcL0aE","XflUq7ku1p","taOXKdmoS7",
-"DQimpNOHsz","i3pydcShY2","uZPqgzqH0W","VIlwPRsQUq","0YAGHmz8gx","lsQGoEdBKc","8cVD3xReec","nnP8o5Mg9r","QssNCuZPqg","FhtglAmdQd",
-"jiVBPgtCA5","0PktIYjB9t","yToGWDQimp","55rfBQ6hMC","fLNg8MK07Y","hSSvQZJTXH","TCgPpVBjhz","zY1GYy94nw","O3iyQbrhlQ","WaWsvFLsph",
-"Q6LixvOqCE","QbxXcydG8U","vLsmSWaim6","9XyT9sqVrf","Pb1paTa8f6","dmoS7QChxs","pmeCdGSQwj","NAFuwguMb8","XyPZNdQ586","8cVD3BGaQY",
-"7lUXZlweGy","PYBf4mz8gx","PYBf4In3NS","S2DfuNhXdu","guMb8Kr8ys","iB08loGu6x","4W0Tl2Yz7E","oGu6xFVMxo","dhSuH0h1b1","gdQsSWreyP",
-"POUYSs4786","ksJbyRxrsm","uTacx2DREs","uPX7GZhwG1","HfyNQDLhzM","fFDrJ0Kyfs","zbIYY8RCUA","ECMvUuQIcz","0ao3l9XyT9","ni2v1gf8rI",
-"Mkgy8ECMvU","Z4I1vJkzUn","AXpwEKASQ8","LewvMpFrrl","rKDLJprNT6","EdBKcv8yFN","cShY2l83Ud","zmLYDuupzk","7hyVvzFgtB","Waim6dQ586",
-"uQIczUlU3M","7lUXZhSSvQ","zmLYDfFDrJ","d7vjM1v5hH","BpYhVix74r","7fKYUpWiOs","L7cGchSSvQ","UmaEvYjB9t","2hEEULewvM","FxX9qzQt6Q",
-"8xEKz2hEEU","piJSkRpBQm","TwanoReKEW","OUqFMyToGW","zQt6QcQOnv","Mm8si1LB1L","9GXkXhSSvQ","rz7UthYBCK","7hyVv0ao3l","JIqXiKZamH",
-"DcpWB1j5L8","BCxeChYBCK","lsQGouPX7G","KASQ8MaJQs","qUJMdJKWYR","FhtglS77LH","SmGzviqv4k","S77LHQWxoT","P6bcgCfgr3","Twanon8pJ9",
-"hUTw7EoToP","kZANmtjQxs","Ss0ZuNcICA","5nmWvLDk6f","VjCZqlViBv","lXFOBxciqp","7fKYUpiJSk","djsrvD6rBy","4QMc9FcWrW","BFkb89iGoT",
-"okgRilj07Q","EOE1oEoToP","2Yz7Ex3LDe","0YAGHNxx9V","FnPFBZuDtD","l83UdYOfrY","XflUqvkCHH","okgRi8hJdt","azIWpjtn0X","WmadAQWxoT",
-"F6PT2cQOnv","DQimpTXQ0Z","pWiOsLDk6f","FGzgpJJs5m","2NslmfaHir","ksJbybZLvS","VerEAqQxHP","yEfy9d85a9","vOqCEFVMxo","tlILtFwEJz",
-"5NammHP433","b29RJYw2oU","BGaQYMK07Y","8U2nUQClRL","atef2ZuDtD","tjQxsRACuj","zbIYYECMvU","UmaEvoQ87r","QssNCzQt6Q","lkMUApT8wu",
-"No0QbtjQxs","8FmFH0YAGH","RsQUqoQ87r","Mkgy814FLR","djsrvMmsIo","MmsIoFwEJz","i7WMQhYBCK","9y4lwL7cGc","ciuWz2DREs","pWiOs2DREs",
-"RkQkeokgRi","0KyfswDajX","M3zXLVIlwP","64s8NmX2GE","fmIK1DcpWB","1v5hHcShY2","Yf2EcgjUTu","5Drn0CNHmv","618DiYOfrY","RxrsmydG8U",
-"fLNg8VLTy6","Yf2EcTa8f6","Cfgr3MK07Y","QWxoTAkKTk","fcwDam4bxU","5NammZhwG1","iB08l4QMc9","ECMvUMmKGJ","EdBKcsuY4x","Gv3Fqatef2",
-"QssNCmX2GE","s7Mxkfqypy","KZamH9XyT9","TwanolsQGo","0YAGH45cIH","d7vjMulk41","7fKYUzFgtB","2NslmUlU3M","uQIczHlUbF","lj07QNAFuw",
-"ThjNnzmLYD","RpBQmNhXdu","DQimpHRxd8","0MR5X9iGoT","MK07YnlaBy","7lUXZZhwG1","KZamHAIYUu","1LB1LFNYIM","WmadA618Di","jiVBPOxWIH",
-"bZLvSDQimp","GWqqXJ2mQi","KASQ8K20wK","Ta8f6FGzgp","WaWsvVprf2","KsjRKqaofN","XflUqm4bxU","7ku1ppv0i7","zHF1qUmaEv","FxX9qy94nw",
-"gtCA5BGaQY","e6e4zCNHmv","zFgtBrz7Ut","ru4UGFPfSE","uupzk5VZjS","soy9tblLA9","9eoRcPb1pa","X6Pinh1zcH","5nmWvStlDJ","kZANmGWqqX",
-"uN6r3m4bxU","ThjNnSmGzv","guMb8tlILt","vkCHHZUnqt","cShY2EOE1o","FPfSE45cIH","nFqikyEfy9","ni2v1zz4ZU","8FmFHuvf7A","2hEEUECMvU",
-"7X3uyxciqp","9XyT9FLsph","n8pJ9UlU3M","euZA5rhl0J","9y4lwuLtKs","Gv3FqJJs5m","BCxeCGrDg7","EoToPKZamH","45cIHaL6AJ","14FLROHaBz",
-"Ta8f6DLhzM","uLtKsCqqaD","sx5GlUvlv4","vOqCEiB08l","b29RJsx5Gl","KASQ8atef2","KsjRKCdyBV","m4bxU24ARF","lH1ktNOHsz","QbxXceuZA5",
-"IjTwP16lHc","CIShG9rlg9","SWfouG1RhS","AmdQdVIlwP","6AFT0v2eC3","b29RJMGlTF","8TxD7No0Qb","ZzJHWFFDui","jiVBPJKWYR","5ZaEz7ku1p",
-"1LB1LjfREu","XyPZNfFDrJ","FGzgpJXljW","StlDJFwEJz","Fhtgl1j5L8","rhl0JTwano","QssNCStlDJ","29QAzgf8rI","v8yFN07n1c","O3iyQ2TRI7",
-"hE1QllCMxy","o8UydXflUq","ZJTXHW3VFH","uPX7GW7cTs","SWfouPOUYS","pAhR1LbRTH","AOgEetvdkD","WDVWJBGaQY","zbIYYh1zcH","HzZT8X6Pin",
-"jzUqRiB08l","ZhwG1lCMxy","dhSuHVerEA","okgRiDQimp","qaofNTwano","5Nammatef2","GXdoHRpBQm","3weIF9GXkX","cmXIX5IhmG","mz8gxBGaQY",
-"RmDcrxXTI4","JRJQBXyPZN","0Wr5y5iGN5","Dz1R33otm6","DG4sTCIShG","pFrrlazIWp","FLspho8Uyd","tvdkDTXQ0Z","SbRYyk85Ae","t59lRlweGy",
-"0ao3lyluBx","Yh1hFSbRYy","8cVD3VBjhz","vOqCELewvM","K4GS8W3VFH","FPfSERkQke","580YD7Ow5C","5iGN5ksJby","SjskQ7ku1p","M6qcGHlUbF",
-"iqv4ksqVrf","2DREs4dEz6","aDGtSOUYuF","580YDFPfSE","S77LH55rfB","euZA5l83Ud","Nxx9VuPX7G","IBe8kuN6r3","9eoRcgIYvE","kZANmNo0Qb",
-"U3yw5wDajX","ksJbyAgJHQ","UmaEvTwano","TCgPp24ARF","m4bxUAIYUu","0h1b1ECMvU","StlDJMmsIo","dpe1vhe9IA","zFgtBVLTy6","MojnPHRxd8",
-"yToGW8TxD7","h1zcHFhtgl","KZamHlweGy","Cfgr3s4786","QnJ1S5IhmG","nnP8ohi5X7","kZANm6q6L9","ru4UGfaHir","uN6r3AmdQd","07n1cIjTwP",
-"taOXKGSQwj","NAFuwLbRTH","5iGN5hUTw7","lCMxy45cIH","mX2GEokgRi","FcWrWGv3Fq","lm0pDvOqCE","okgRiWPmlx","pmeCdEoToP","2NslmAkKTk",
-"ulk411j5L8","taOXKzY1GY","v8yFNFLsph","5ZaEzZUnqt","3weIFru4UG","SWfouzQt6Q","vkCHHtvdkD","fLNg8BGaQY","iqv4kcShY2","618Di4dEz6",
-"lCMxyK20wK","14FLRs93Ml","fFDrJvOqCE","5iGN5vLsmS","9y4lwO3iyQ","KZamH55rfB","KASQ8s7Mxk","fqypys7Mxk","zz4ZUtAOsr","zmLYDCxVEf",
-"OHaBzQClRL","S77LHB3qem","cL0aEqaofN","hUTw7hYBCK","Cfgr3AXpwE","lpF6WChuy3","L7cGcbrhlQ","RpBQmfcJOy","SmGzvSjskQ","D6rByThjNn",
-"GXdoHUmaEv","M3zXLuPX7G","s93Mlm4bxU","YjB9t8xEKz","s93Mliqv4k","Chuy3faHir","NOHszjiVBP","vOqCEfqypy","4dEz6d7vjM","okgRiqaofN",
-"Cp3mZ7fKYU","7Ow5Cd7vjM","h1zcHogLgc","h1zcH9XyT9","Chuy37Ow5C","2Yz7EpvgjS","tvdkDOUqFM","tuDySjfREu","n8pJ9RpBQm","lCMxyQChxs",
-"FGzgpECMvU","9rlg9iqv4k","ix74rWMiS3","gtCA5QClRL","QbxXct98iW","blLA9LbRTH","ZuDtDLbRTH","4W0TlBCxeC","jtn0Xhe9IA","RzaZA3otm6",
-"ni2v1MaJQs","gjUTuQssNC","3weIFprNT6","9XyT9s93Ml","2ZHdkpvgjS","wiHrZQClRL","AOgEe8cVD3","hUTw7cL0aE","uupzk5Namm","e6e4zcL0aE",
-"Pb1paYf2Ec","I7p2aJ2mQi","Ta8f6QChxs","Dz1R3lViBv","gjUTun8pJ9","FPfSEguMb8","BbwgA9iGoT","45cIH0BmCy","GXdoH5VZjS","Cfgr3pmeCd",
-"x3LDeGWqqX","xXTI4Yw2oU","TCgPpYf2Ec","yEfy9U3yw5","FVMxonFqik","SWfouzmLYD","VBjhziqv4k","aez9yQssNC","GrDg7DG4sT","ni2v1AIYUu",
-"BbwgA14FLR","Yw2oUpWiOs","07n1c0Wr5y","FLsphZv7z0","v8yFNQClRL","tlILtsuY4x","StlDJM6qcG","EdBKc8FmFH","G1RhSRmDcr","EOE1o8cVD3",
-"NAFuwCK5W7","ECMvU2Nslm","PYBf4hYBCK","D6rBynnP8o","CxVEfFVMxo","s93Ml1v5hH","FnPFBFPfSE","FxX9qZUnqt","cShY20h1b1","XflUqlCMxy",
-"0PktIRzaZA","Mm8sipFrrl","kB5nPuLtKs","M6qcGAgJHQ","Z4I1vZ4I1v","e6e4z9rlg9","zqH0WQnJ1S","X6PinTa8f6","24ARFFFDui","uPX7Gru4UG",
-"FcWrWdQ586","AkKTkP6bcg","lH1ktru4UG","29QAzZJTXH","he9IAv1Hln","M3zXLfLNg8","8U2nUfLNg8","suY4xlXFOB","JkzUnix74r","v8yFNQnJ1S",
-"tvdkDlsQGo","e6e4zix74r","h1zcHAgJHQ","RkQkerhl0J","jtn0X1v5hH","Q6hMCM3zXL","CNHmvHRxd8","VNCPdtaOXK","SbRYyQssNC","VNCPd7fKYU",
-"24ARFuLtKs","9y4lwpWiOs","v2eC3dQ586","YOfrYZhwG1","MK07YNcICA","0KyfsAOgEe","W3VFH8xEKz","S77LHNOHsz","zQt6Qv1Hln","tvdkDuPX7G",
-"RzaZAVIlwP","5VZjSUlU3M","XyPZNzHF1q","dhSuHSbRYy","gjUTuKASQ8","Ul4a1OxWIH","RsQUqmz8gx","0ao3loVQp6","cL0aEDz1R3","DcpWBxXTI4",
-"Uvlv4B3qem","Oz8yZ29QAz","ix74rn8pJ9","BFkb8Y1mC0","sx5GlqaofN","jiVBPjeskS","fLNg8d7vjM","VBjhzCqqaD","aez9ysuY4x","EdBKc5Mg9r",
-"e6e4zfFDrJ","MezSWPb1pa","he9IAG1RhS","RACujStlDJ","nnP8oO3iyQ","fFDrJ7fKYU","WDVWJmX2GE","NcICAIn3NS","DQimp3weIF","bZLvSIn3NS",
-"1LB1LHP433","bZLvSJRJQB","6q6L98TxD7","8RCUAqaofN","uoStwn1pmO","uTacx0Kyfs","7fsYMDG4sT","vLsmSpFrrl","iB08lWreyP","2ZHdkjtn0X",
-"gtCA5ThjNn","Oz8yZ9y4lw","ru4UGEdBKc","qaofNcL0aE","2hEEUDQimp","8FmFHb29RJ","yofH329QAz","MojnPpmeCd","CK5W7FFDui","WMiS3MmKGJ",
-"Ta8f6NhXdu","EdBKcTa8f6","5nmWvgtCA5","55rfBwDajX","sx5Gls4786","pAhR1OUYuF","No0QbF6PT2","5Mg9rblLA9","pAhR1GWqqX","ru4UGSs0Zu",
-"8TxD7guMb8","Mm8si64s8N","HP433s4786","ECMvUiwzGk","Gv3FqBpYhV","vkCHHBGaQY","1j5L8iwzGk","tl72WaFFss","yToGWAOgEe","IKxdLv8yFN",
-"jSjS3nlaBy","In3NSGv3Fq","4QMc9uAWyp","NAFuwNhXdu","okgRie6e4z","KZamHfLNg8","LbRTH3otm6","mX2GETXQ0Z","4dEz6QChxs","RACujxReec",
-"CdyBVUlU3M","VLTy648cHL","hE1Qll83Ud","tlILtTa8f6","VjCZqdjsrv","ReKEW0PktI","VBjhz4W0Tl","6q6L9FnPFB","cmXIXCNHmv","Dz1R38TxD7",
-"xXTI4aDGtS","5IhmG2DREs","dQ586wiHrZ","mX2GEC2Irc","Y1mC048cHL","QChxs9iGoT","ulk41soy9t","QChxsUlU3M","0h1b155rfB","M3zXLuZPqg",
-"IBe8ktvdkD","Nxx9VBGaQY","SmGzvlpF6W","UmaEvHRxd8","14FLRjtn0X","JRJQBUmaEv","Oz8yZuPX7G","kB5nPX6Pin","9y4lw9eoRc","0YAGHGXdoH",
-"l83UdjiVBP","hYBCK9y4lw","NhXduWmadA","Qworu1LB1L","blLA9NOHsz","U3yw57X3uy","lkMUAe6e4z","mX2GEDz1R3","WreyPgf8rI","VerEA64s8N",
-"lj07Qfqypy","8xEKzvLsmS","Yh1hFeuZA5","O3iyQpv0i7","yofH3dQ586","ogLgcB3qem","D6rByRzaZA","uN6r3NAFuw","Yw2oUksJby","uQIczJIqXi",
-"ru4UGtl72W","i3pyddmoS7","hYBCKFGzgp","Chuy307n1c","CdyBVEOE1o","zY1GYEOE1o","qQxHPWDVWJ","6AFT0WPmlx","F6PT2MaJQs","618DifaHir",
-"FjHXRuLtKs","JRJQBF6PT2","mz8gxTCgPp","FjHXRCp3mZ","VLTy6NhXdu","RkQkeiB08l","5iGN5gjUTu","9rlg9POUYS","Q6hMClm0pD","6q6L98RCUA",
-"l83UdiwzGk","BGaQYfFDrJ","7fsYMSmGzv","uvf7ATa8f6","4QMc9aL6AJ","CIShGEoToP","TCgPpJ2mQi","FwEJzFGzgp","QWxoTdmoS7","2Yz7ExXTI4",
-"n1pmO55rfB","dhSuHi3pyd","zz4ZUAIYUu","FnPFB07n1c","ydG8UJXljW","qaofNRzaZA","ThjNnIn3NS","d85a9h1zcH","tjQxsb29RJ","pAhR10PktI",
-"ZzJHWRmDcr","sx5GllweGy","xciqpxXTI4","4dEz6mz8gx","blLA9VLTy6","fmIK12TRI7","azIWpOUYuF","tjQxs9y4lw","GrDg78xEKz","fFDrJcmXIX",
-"gdQsScL0aE","yEfy9FVMxo","suY4xy94nw","qUJMdlkMUA","RkQkeHfyNQ","pvgjSNAFuw","Yf2EcWDVWJ","ksJbyZhwG1","lsQGorhl0J","LewvMRACuj",
-"lXFOBOz8yZ","t59lRnnP8o","RsQUqL7cGc","FPfSENAFuw","fcJOyP6bcg","nFqikNcICA","zbIYYy94nw","hUTw7GWqqX","Mkgy8MaJQs","kZANmDLhzM",
-"gIYvEzHF1q","ru4UG9rlg9","0h1b1BGaQY","HlUbF9rlg9","uLtKsBGaQY","WmadAMezSW","zz4ZUe6e4z","618DizbIYY","HlUbFlkMUA","d7vjMk85Ae",
-"v2eC3M3zXL","2Yz7EpiJSk","jtn0XxReec","6AFT0IKxdL","8U2nUuupzk","7fsYMlj07Q","POUYSbrhlQ","lViBvwDajX","dhSuHIKxdL","StlDJIjTwP",
-"Fhtgl07n1c","blLA9Y1mC0","tl72WgtCA5","0h1b1jfREu","yluBx14FLR","n8pJ9oGu6x","Gv3FqYw2oU","rhl0JbZLvS","5ZaEzru4UG","SjskQQnJ1S",
-"gdQsStl72W","e6e4zpWiOs","dpe1vStlDJ","C2IrcbZLvS","bgJAz6AFT0","GSQwjeuZA5","guMb8DcpWB","aL6AJ7X3uy","BbwgAlkMUA","2hEEURxrsm",
-"2NslmHlUbF","taOXKwDajX","KsjRKoQ87r","UmaEvtjQxs","zFgtBHP433","4W0Tluvf7A","5IhmGhi5X7","NAFuw4QMc9","8U2nURBhp0","Vprf20PktI",
-"CqqaD2TRI7","cQOnvDcpWB","NAFuwFxX9q","yofH3QssNC","Zv7z0s7Mxk","QWxoTcShY2","prNT6uoStw","64s8N9rlg9","IKxdLOz8yZ","iKqhruupzk",
-"AXpwEpvgjS","zz4ZUvOqCE","QssNCiB08l","FwEJzQWxoT","gIYvEG1RhS","M3zXLFjHXR","RmDcrs7Mxk","MmsIo48cHL","ydG8UoVQp6","lXFOB8RCUA",
-"ciuWz5Drn0","2ZHdkjiVBP","J2mQifcJOy","BbwgA5VZjS","CIShGRxrsm","FcWrWChuy3","Dz1R3618Di","3weIFfFDrJ","UlU3Mi7WMQ","zY1GYC2Irc",
-"mz8gxEoToP","9XyT9GWqqX","BpYhVRxrsm","FNYIMulk41","uAWyppT8wu","IjTwPRACuj","DLhzMgIYvE","5ZaEz618Di","QClRL2Yz7E","VBjhzZhwG1",
-"VNCPdDcpWB","cmXIXyToGW","16lHcQbxXc","uJScX5IhmG","AIYUu9y4lw","AXpwEZzJHW","J2mQiuoStw","oQ87rMmKGJ","NhXduZuDtD","9XyT9zqH0W",
-"YOfrYcL0aE","5Drn0Yw2oU","C2Irc3weIF","cmXIXAIYUu","dmoS7fLNg8","EOE1ooVQp6","yEfy9K20wK","KsjRKsqVrf","HfyNQMmsIo","JkzUnI7p2a",
-"jS1ajNhXdu","FGzgpbZLvS","F6PT2tlILt","5ZaEzlweGy","FnPFBfmIK1","uupzkazIWp","azIWpM3zXL","pv0i7uJScX","zQt6QQ6hMC","CIShGVIlwP",
-"lweGynFqik","Ul4a1QbxXc","WmadAzbIYY","tlILtPb1pa","tuDySblLA9","yEfy9he9IA","nFqik3otm6","lViBvyEfy9","K4GS87hyVv","v1Hln9eoRc",
-"2Yz7EDLhzM","IKxdLGrDg7","Nxx9Vulk41","VNCPdMojnP","tvdkDlj07Q","Q6LixZuDtD","JIqXisqVrf","zz4ZUuQIcz","W7cTsblLA9","7lUXZogLgc",
-"Mm8siaFFss","FFDuin1pmO","wiHrZQworu","MK07Y9XyT9","zFgtBQworu","xXTI4NOHsz","m4bxUMGlTF","sx5GlRsQUq","RmDcr24ARF","pv0i7aDGtS",
-"JJs5mMaJQs","zz4ZUuvf7A","nnP8oFLsph","24ARFYh1hF","580YDbZLvS","5VZjSReKEW","uZPqgxXTI4","5nmWve6e4z","GSQwjSWfou","jzUqRAmdQd",
-"AXpwEzmLYD","55rfBEdBKc","QssNC5ZaEz","okgRiK20wK","580YDfaHir","4W0TlY1mC0","VIlwPt59lR","k85AeG1RhS","7lUXZWaWsv","StlDJksJby",
-"lCMxyFLsph","4QMc9cmXIX","POUYSxReec","b29RJtuDyS","kB5nPo8Uyd","No0QbBpYhV","Pb1palj07Q","7lUXZnlaBy","ZzJHWcShY2","DG4sTHlUbF",
-"mz8gxn1pmO","fcwDai3pyd","AkKTk5Mg9r","FPfSE8TxD7","VLTy6hE1Ql","WreyP16lHc","suY4xF6PT2","RmDcrDG4sT","cL0aEJXljW","M6qcGQWxoT",
-"gdQsScShY2","RsQUqyToGW","i7WMQtAOsr","CqqaDHfyNQ","azIWpuvf7A","GXdoHhUTw7","MezSWpWiOs","uLtKsRpBQm","UlU3Muvf7A","GrDg7GWqqX",
-"QYxC0VjCZq","KsjRK580YD","3weIFpWiOs","NhXduOUYuF","ciuWzsuY4x","EdBKcD6rBy","8RCUAVerEA","0h1b1s93Ml","prNT6HlUbF","zmLYDFPfSE",
-"0Wr5ytAOsr","GXdoHsoy9t","zmLYDK20wK","IKxdLnnP8o","0ao3lGSQwj","4QMc9J2mQi","oGu6xQ6Lix","ECMvU14FLR","2DREsOHaBz","blLA9Dz1R3",
-"6AFT0Kr8ys","yEfy9S77LH","OxWIHEoToP","9iGoT9GXkX","RmDcrHRxd8","rhl0JQworu","W7cTstuDyS","dmoS7bgJAz","pvgjSAIYUu","iKqhrogLgc",
-"aFFss1j5L8","L7cGc8TxD7","t98iWVLTy6","lm0pDn8pJ9","8U2nUUvlv4","iB08l5iGN5","EoToPiB08l","gjUTuYf2Ec","G1RhSzqH0W","O3iyQk85Ae",
-"55rfBGv3Fq","LDk6f07n1c","jeskSJIqXi","14FLR3weIF","K4GS8X6Pin","14FLRyvOMI","Q6hMCMojnP","P6bcg9rlg9","jtn0XbgJAz","lViBv0YAGH",
-"IRh48YjB9t","tjQxsqaofN","Pb1paI7p2a","Yf2EcfFDrJ","3weIFQChxs","DG4sTMmsIo","Y1mC0sx5Gl","tuDySdmoS7","OHaBz8U2nU","5VZjS5VZjS",
-"ogLgcNo0Qb","bZLvSFcWrW","lViBvVNCPd","JRJQBuQIcz","zFgtBtvdkD","5IhmGNxx9V","soy9tBCxeC","Fhtglt98iW","KsjRKzY1GY","oVQp6dpe1v",
-"cmXIXHfyNQ","faHir5Drn0","OxWIH29QAz","aDGtSgf8rI","oQ87rhSSvQ","8xEKzHlUbF","a00b5lsQGo","uZPqgEOE1o","4dEz62hEEU","NAFuwi7WMQ",
-"FhtglCIShG","pv0i7VNCPd","lsQGofaHir","piJSkxciqp","MK07Yru4UG","In3NShi5X7","y94nwJRJQB","qQxHPOUqFM","QClRLhUTw7","yvOMIlsQGo",
-"tl72WFnPFB","BpYhV8U2nU","yluBxUlU3M","6q6L9jeskS","nlaByFGzgp","Ul4a10Wr5y","7X3uyazIWp","AkKTkBpYhV","AXpwEAIYUu","cQOnvUmaEv",
-"cShY2gdQsS","3otm6LewvM","EdBKcciuWz","FPfSE9XyT9","rz7UtQYxC0","M3zXLfcwDa","kZANmfcwDa","nlaBys93Ml","TXQ0ZuN6r3","CK5W7uPX7G",
-"Uvlv4he9IA","BFkb8zz4ZU","MK07YuoStw","zqH0WtlILt","FNYIM580YD","8TxD7BFkb8","fLNg8QnJ1S","yToGWK4GS8","2TRI7zbIYY","tvdkDt98iW",
-"Zv7z0jtn0X","cQOnvnFqik","1LB1Lt98iW","RkQkeUl4a1","d85a9F6PT2","zmLYD3otm6","3weIFni2v1","W3VFHi3pyd","1v5hHnlaBy","b29RJs4786",
-"FLsphlViBv","DLhzMksJby","ZzJHWlm0pD","Yw2oUNxx9V","YjB9t0h1b1","2DREs24ARF","bZLvSVNCPd","fLNg8NhXdu","IRh48FcWrW","Waim6lkMUA",
-"2ZHdktvdkD","2Yz7E9rlg9","SjskQtaOXK","QYxC0vLsmS","8hJdtrhl0J","IjTwPyvOMI","rKDLJs93Ml","XflUqMmKGJ","XyPZNsuY4x","48cHLksJby",
-"F6PT25Drn0","W7cTs29QAz","EOE1oFwEJz","FNYIMm4bxU","IBe8kCIShG","IBe8kFjHXR","zQt6QIjTwP","BbwgAMmsIo","VIlwP7lUXZ","vLsmS2TRI7",
-"580YDzmLYD","brhlQJIqXi","IBe8kksJby","bgJAzsx5Gl","C2IrcuLtKs","5ZaEzUlU3M","9GXkX2Yz7E","5drc6v8yFN","ydG8UW7cTs","tvdkD9eoRc",
-"Vprf2he9IA","QClRLmX2GE","0YAGHnFqik","GSQwj8hJdt","GSQwj2hEEU","cShY2BbwgA","oQ87rblLA9","16lHc7hyVv","JIqXipT8wu","KsjRKjSjS3",
-"8RCUAIjTwP","piJSktAOsr","AIYUulCMxy","0Wr5y8U2nU","zQt6QVjCZq","Waim65ZaEz","QChxsBpYhV","d85a9XflUq","8hJdtBpYhV","AmdQdpvgjS",
-"5IhmGJXljW","fLNg8VIlwP","dmoS72Nslm","FwEJzHP433","pAhR1pAhR1","yofH3vLsmS","KZamH8TxD7","uZPqgQworu","qQxHPTXQ0Z","qQxHPW3VFH",
-"8xEKztAOsr","Fhtglo8Uyd","8FmFHkB5nP","atef2VerEA","dhSuHWreyP","VjCZq0h1b1","OHaBzzHF1q","DG4sThUTw7","cShY2VBjhz","X6Pin5IhmG",
-"k85AecmXIX","vLsmSNxx9V","KZamHAXpwE","OUYuF9GXkX","NcICANAFuw","cShY2D6rBy","sqVrft98iW","DcpWBVerEA","dmoS7vkCHH","CIShG9y4lw",
-"IBe8kpiJSk","vkCHHGrDg7","sqVrf8xEKz","n1pmOrz7Ut","VerEAWDVWJ","0h1b1HP433","atef28cVD3","iB08lMaJQs","SmGzv7hyVv","TwanoOz8yZ",
-"euZA5M3zXL","5Mg9rjS1aj","pFrrlgdQsS","dpe1vRBhp0","o8Uyd8RCUA","8U2nUAmdQd","vOqCEQnJ1S","iwzGkZJTXH","ydG8UVLTy6","O3iyQGWqqX",
-"PYBf4rz7Ut","QssNCG1RhS","GWqqXatef2","GWqqX14FLR","Twano2TRI7","MmKGJFVMxo","GSQwjSs0Zu","Kr8yszY1GY","G1RhSJJs5m","xXTI4Zv7z0",
-"AOgEe9GXkX","YjB9tWPmlx","yofH3VjCZq","Vprf2IKxdL","07n1c0h1b1","uoStwX6Pin","P6bcgZUnqt","yEfy9Fhtgl","Yh1hFRACuj","8U2nUfFDrJ",
-"0h1b1uJScX","o8UydAIYUu","5Drn0jtn0X","yofH35drc6","AkKTkIn3NS","hi5X7oQ87r","aFFss9iGoT","WDVWJfcJOy","uJScXMGlTF","euZA55iGN5",
-"ogLgchYBCK","soy9t14FLR","RmDcr1v5hH","MmsIotlILt","0ao3lgdQsS","Zv7z0ECMvU","VerEAIBe8k","07n1cni2v1","RxrsmxXTI4","zbIYYprNT6",
-"ZJTXH0Kyfs","yEfy9Oz8yZ","W3VFHJXljW","brhlQ5IhmG","X6PinpFrrl","CNHmvrz7Ut","Oz8yZ1LB1L","azIWpFGzgp","FVMxoMmsIo","lsQGo6q6L9",
-"h1zcHaDGtS","lpF6WzHF1q","jSjS3ECMvU","618Dizz4ZU","RpBQmfFDrJ","zHF1qAgJHQ","M6qcGAIYUu","X6PinzY1GY","14FLRGv3Fq","VIlwP8hJdt",
-"RpBQmfmIK1","VLTy60MR5X","blLA9sx5Gl","rKDLJyofH3","v8yFNaL6AJ","uQIcz7Ow5C","pvgjShSSvQ","pvgjSDcpWB","F6PT2pFrrl","8U2nUfqypy",
-"POUYSPOUYS","Oz8yZ0MR5X","ix74rzbIYY","fLNg8GrDg7","guMb8B3qem","MaJQskB5nP","iB08ls7Mxk","DLhzM5Drn0","qaofNUvlv4","P6bcgWreyP",
-"3weIFRpBQm","uupzkAmdQd","9y4lw0h1b1","lweGy9y4lw","y94nwMK07Y","jfREuFFDui","hSSvQJIqXi","Q6hMCsqVrf","aFFss14FLR","aDGtSmz8gx",
-"ZhwG19rlg9","AgJHQZ4I1v","hSSvQgIYvE","SbRYyWDVWJ","StlDJ8RCUA","prNT66AFT0","uLtKsSmGzv","iKqhrMezSW","rKDLJiqv4k","mX2GE1j5L8",
-"45cIHHP433","KsjRKChuy3","lCMxyKr8ys","LDk6fxciqp","14FLRStlDJ","IjTwPjtn0X","SbRYy29QAz","L7cGc3otm6","G1RhSW3VFH","0YAGHsuY4x",
-"s93MlnlaBy","nFqiklCMxy","EOE1oDQimp","soy9tIn3NS","x3LDeZ4I1v","8FmFHblLA9","0h1b1nlaBy","vkCHHRBhp0","LbRTHP6bcg","xciqpThjNn",
-"MmKGJogLgc","FLsphn8pJ9","d85a9aez9y","xciqpfmIK1","guMb8XflUq","Y1mC0LDk6f","9eoRchSSvQ","QssNCDcpWB","IBe8kJXljW","d7vjMjiVBP",
-"MezSWFGzgp","Yh1hF48cHL","uLtKsuAWyp","lXFOBGXdoH","VIlwPfcwDa","HfyNQgf8rI","8cVD3ciuWz","5Drn0taOXK","DG4sTdhSuH","9GXkXcShY2",
-"MezSWNcICA","ThjNnQChxs","YOfrYpWiOs","5IhmGBCxeC","S2DfuPb1pa","KASQ8IKxdL","9y4lwIn3NS","5Drn0uQIcz","BFkb8nlaBy","uQIczRkQke",
-"Oz8yZoVQp6","hi5X75Drn0","3weIFjzUqR","pT8wuGXdoH","CIShG8xEKz","Nxx9VQnJ1S","jS1ajP6bcg","HfyNQF6PT2","Zv7z04W0Tl","YjB9tHlUbF",
-"RsQUqulk41","5VZjSYf2Ec","uupzkWDVWJ","yvOMI8xEKz","2ZHdks4786","zY1GY8FmFH","7lUXZ618Di","8U2nUrhl0J","pFrrli3pyd","Yh1hFB3qem",
-"0BmCydhSuH","a00b5Ss0Zu","J2mQiv2eC3","d7vjMWaWsv","djsrvtjQxs","9y4lwGv3Fq","jS1ajMK07Y","S77LHsqVrf","OUqFMYOfrY","3otm6iB08l",
-"Nxx9V45cIH","vLsmS8RCUA","55rfB8RCUA","BGaQYNhXdu","FNYIMJJs5m","7ku1plsQGo","NOHszVNCPd","LbRTH2TRI7","Yw2oUUmaEv","gdQsS0ao3l",
-"ogLgcAOgEe","FjHXRazIWp","uLtKsoVQp6","SjskQuQIcz","zQt6Qulk41","Fhtgl1v5hH","lViBvXyPZN","a00b5MezSW","KZamHo8Uyd","kB5nPuvf7A",
-"NhXduFFDui","7fsYMnlaBy","FjHXR8TxD7","580YD5Mg9r","HzZT8OUqFM","29QAzDcpWB","oQ87rtlILt","v8yFNpFrrl","Kr8ysDQimp","brhlQjeskS",
-"v2eC34dEz6","d85a94dEz6","AXpwEguMb8","okgRitaOXK","fFDrJReKEW","he9IAM3zXL","Uvlv4DcpWB","0BmCy3otm6","rhl0JZUnqt","5Mg9rru4UG",
-"bZLvSQ6Lix","uJScXRsQUq","Ss0ZugjUTu","C2IrcM3zXL","atef2QssNC","Kr8yscmXIX","S77LHnlaBy","lViBvEoToP","hSSvQvOqCE","BGaQY580YD",
-"okgRipvgjS","yvOMIZzJHW","580YD5nmWv","SmGzvd7vjM","16lHcSjskQ","ZuDtDBGaQY","hSSvQGXdoH","QYxC0uupzk","2TRI70PktI","jfREuzbIYY",
-"L7cGcBbwgA","cQOnvsqVrf","2Yz7EZhwG1","pAhR1Kr8ys","8cVD3cmXIX","I7p2aoGu6x","JKWYRdmoS7","5drc6No0Qb","DcpWBjSjS3","uN6r31j5L8",
-"GSQwjMmsIo","4W0TlcL0aE","8TxD7qaofN","K20wKChuy3","K4GS8tvdkD","IBe8kHRxd8","Ul4a16q6L9","RkQkeMmsIo","uN6r3azIWp","he9IACK5W7",
-"Q6hMCUl4a1","0BmCyhUTw7","5Drn00h1b1","O3iyQ29QAz","ZhwG1XyPZN","he9IAzmLYD","VIlwPUl4a1","zFgtBs93Ml","uoStwtvdkD","x3LDeJRJQB",
-"yToGWaez9y","TwanoFLsph","hUTw7bgJAz","WaWsv8RCUA","07n1czz4ZU","AIYUuZuDtD","ZJTXHOUYuF","F6PT2NcICA","lH1ktaez9y","QYxC0lweGy",
-"IKxdLhYBCK","h1zcHuvf7A","WaWsvPb1pa","FGzgpNAFuw","gIYvEv1Hln","iqv4kpvgjS","euZA5iB08l","x3LDeIBe8k","pmeCdTCgPp","yofH3GrDg7",
-"MezSWjSjS3","ix74rqaofN","RkQkedhSuH","K20wKNOHsz","KsjRKprNT6","1j5L8IjTwP","BFkb82Nslm","0h1b1WPmlx","fcJOyVLTy6","0h1b15Drn0",
-"FhtglRpBQm","VBjhzkZANm","FwEJz64s8N","5IhmGMm8si","64s8NRBhp0","taOXKdpe1v","1v5hHi3pyd","HRxd8h1zcH","ogLgc55rfB","s93Ml4W0Tl",
-"e6e4zMm8si","dmoS7euZA5","zFgtBogLgc","pvgjSnFqik","HzZT8hUTw7","dhSuHVprf2","cL0aE5Drn0","jeskS6q6L9","RACujDLhzM","tuDySYf2Ec",
-"d85a95Namm","ulk41v1Hln","I7p2azHF1q","4W0Tl2ZHdk","D6rByoVQp6","qQxHPhUTw7","FFDuiYw2oU","x3LDe0PktI","K4GS8t59lR","EOE1okB5nP",
-"5drc6i7WMQ","Ta8f6Q6Lix","mz8gxJkzUn","Gv3FqNo0Qb","BGaQY3weIF","5NammB3qem","lj07QgtCA5","h1zcHIBe8k","h1zcH24ARF","5Mg9rcL0aE",
-"X6Pinfqypy","Mm8siVBjhz","iB08loVQp6","0h1b11LB1L","HfyNQyToGW","oGu6xv8yFN","pmeCdzQt6Q","uJScX0h1b1","AIYUuRBhp0","AIYUuCdyBV",
-"ciuWzuvf7A","hYBCKsoy9t","D6rBy48cHL","MK07YoVQp6","oGu6x9eoRc","lj07QFNYIM","gjUTuK20wK","euZA5ECMvU","ni2v1oGu6x","2NslmqUJMd",
-"1v5hHcL0aE","suY4xokgRi","14FLRlweGy","jtn0XEdBKc","prNT6LbRTH","OUqFMVprf2","LewvMSjskQ","XyPZNFVMxo","In3NSUvlv4","W7cTsLDk6f",
-"nnP8oJXljW","7hyVvhe9IA","Uvlv4jzUqR","C2IrcHzZT8","64s8NaDGtS","OUqFMwiHrZ","Gv3Fq9iGoT","lXFOBIjTwP","brhlQuN6r3","WDVWJ6q6L9",
-"uPX7G6AFT0","FLsphvkCHH","hUTw7SmGzv","tlILtZv7z0","LewvMsx5Gl","0BmCyaL6AJ","uN6r3fFDrJ","9iGoTqUJMd","FFDuiFxX9q","taOXKU3yw5",
-"JRJQBPb1pa","Yf2Ec5drc6","RzaZAEoToP","djsrvzHF1q","k85AeprNT6","FwEJzYh1hF","UlU3MAXpwE","lm0pD3weIF","GWqqX5Namm","qUJMd5ZaEz",
-"EdBKcC2Irc","ZUnqtFFDui","StlDJHP433","uQIczaez9y","7X3uyQnJ1S","DcpWBJXljW","WreyP1LB1L","OHaBz9XyT9","HlUbFPYBf4","v8yFNMaJQs",
-"8xEKzDG4sT","jS1ajL7cGc","GrDg7dmoS7","8hJdta00b5","blLA9GrDg7","SjskQqaofN","0KyfslH1kt","uoStwK20wK","FjHXRe6e4z","BbwgAAgJHQ",
-"UlU3M07n1c","Gv3FqnlaBy","B3qemyToGW","GXdoHW3VFH","L7cGcZ4I1v","FcWrWFnPFB","6q6L9zY1GY","jfREujzUqR","I7p2aStlDJ","0PktIFcWrW",
-"WaWsvAmdQd","S77LHvLsmS","K20wKStlDJ","C2IrcFGzgp","SWfou6q6L9","W3VFHn8pJ9","NhXdu24ARF","9GXkX7X3uy","IjTwPjSjS3","QChxsd7vjM",
-"ogLgcbrhlQ","8hJdtbrhlQ","4W0TlydG8U","W7cTsX6Pin","QbxXcciuWz","yvOMIciuWz","azIWpciuWz","9rlg9QWxoT","POUYSa00b5","ZJTXHmX2GE",
-"vkCHHVIlwP","OUYuFDcpWB","kB5nPtjQxs","5IhmGeuZA5","9eoRcaez9y","rhl0JD6rBy","EOE1oprNT6","lj07Q5Namm","XyPZN618Di","UmaEvM3zXL",
-"k85AetjQxs","fmIK14W0Tl","d7vjMzbIYY","FcWrWtjQxs","gtCA5cShY2","7X3uy0ao3l","EoToPIn3NS","DG4sTKsjRK","GWqqX0ao3l","2ZHdkKASQ8",
-"WaWsvJRJQB","0PktIzQt6Q","EoToP0PktI","qaofNLDk6f","GXdoH14FLR","pmeCdOz8yZ","2DREsK20wK","vOqCEzbIYY","Yw2oUprNT6","zz4ZUCfgr3",
-"2NslmD6rBy","8U2nUksJby","ReKEW0Wr5y","uJScXvLsmS","FLsphd85a9","14FLR0BmCy","lXFOBIBe8k","zHF1q45cIH","L7cGcFLsph","0YAGHqUJMd",
-"In3NSt98iW","MojnPZhwG1","yluBxwDajX","uPX7GFPfSE","jiVBPJ2mQi","F6PT2UlU3M","zQt6QDLhzM","4dEz62Yz7E","DLhzMK4GS8","t59lRoGu6x",
-"WreyPLbRTH","K20wK5VZjS","8xEKzb29RJ","LbRTHDLhzM","jS1ajb29RJ","nlaBy24ARF","pWiOsl83Ud","MmsIouAWyp","VLTy6ydG8U","tAOsrni2v1",
-"8FmFHtvdkD","Qworuo8Uyd","5Drn0iKqhr","6q6L9gtCA5","lpF6WGrDg7","fcJOytaOXK","hYBCKSWfou","1LB1LWPmlx","GXdoHF6PT2","n8pJ9taOXK",
-"brhlQ0h1b1","QClRL16lHc","LDk6fG1RhS","bZLvSP6bcg","d85a9iKqhr","16lHcMojnP","gtCA5No0Qb","xciqpuoStw","VBjhza00b5","uupzkUmaEv",
-"Kr8ysK20wK","wDajXCfgr3","AgJHQjSjS3","7fKYU0Wr5y","v1HlnfFDrJ","atef27fsYM","1j5L8o8Uyd","lH1ktEOE1o","s7MxkmX2GE","sqVrffcJOy",
-"euZA5D6rBy","fcwDaYOfrY","GrDg7Twano","ZUnqtCK5W7","kB5nPKZamH","Q6LixsqVrf","VLTy6gf8rI","cL0aE3otm6","VerEApmeCd","Dz1R3uAWyp",
-"StlDJuTacx","TCgPpQClRL","lj07QhUTw7","lXFOB0YAGH","GrDg7S2Dfu","TXQ0ZpFrrl","ZUnqtKsjRK","rz7Utt98iW","e6e4zvkCHH","lkMUAJ2mQi",
-"dhSuHOHaBz","WDVWJVLTy6","SmGzve6e4z","2TRI7ZJTXH","O3iyQMkgy8","m4bxU8TxD7","prNT6Dz1R3","Cfgr3m4bxU","HRxd8MmsIo","9GXkXEOE1o",
-"5Mg9rNAFuw","uQIczOxWIH","nnP8oWaWsv","Q6hMCv8yFN","Chuy3WmadA","0KyfszqH0W","pmeCdXyPZN","sqVrfprNT6","VBjhzydG8U","QssNC8xEKz",
-"pFrrljtn0X","pAhR1OUqFM","S77LHXflUq","5iGN51v5hH","S2DfuQChxs","4W0TlDQimp","fmIK1Q6Lix","aez9yZuDtD","guMb8SmGzv","fcJOyMmsIo",
-"AOgEeFLsph","HzZT8MmsIo","Waim6blLA9","uLtKsSbRYy","Z4I1vKsjRK","uZPqgoQ87r","lH1ktfcwDa","bgJAzXyPZN","RzaZAuLtKs","2DREs1LB1L",
-"gdQsSZv7z0","UmaEvpT8wu","aL6AJDcpWB","45cIHzY1GY","EoToP9iGoT","mX2GEjSjS3","M6qcG6q6L9","pWiOsb29RJ","MGlTFTa8f6","sqVrf8RCUA",
-"xXTI45ZaEz","J2mQiSs0Zu","lCMxyI7p2a","sx5GlgtCA5","pv0i7EdBKc","SmGzvvLsmS","9iGoTRzaZA","45cIHpv0i7","zbIYYZ4I1v","XflUqZhwG1",
-"7X3uy8xEKz","piJSke6e4z","OxWIHokgRi","BbwgATXQ0Z","HfyNQjiVBP","HfyNQqQxHP","POUYSWreyP","okgRiJkzUn","x3LDeFPfSE","ciuWzMkgy8",
-"4QMc97fKYU","yofH3ThjNn","jSjS3sx5Gl","qQxHPblLA9","cmXIXjiVBP","uPX7Gl83Ud","8cVD3Waim6","D6rByFwEJz","P6bcgMojnP","s7MxkFjHXR",
-"gdQsS7fKYU","KASQ8yToGW","EOE1o9GXkX","kB5nPy94nw","MK07YsuY4x","JXljWAgJHQ","VjCZqQ6Lix","lm0pDMaJQs","IRh48LbRTH","cQOnv6q6L9",
-"yEfy91LB1L","bgJAzCK5W7","iB08lhUTw7","t98iWS2Dfu","Y1mC0GWqqX","ksJbynFqik","fFDrJbgJAz","cmXIXSbRYy","ECMvUWDVWJ","mz8gxVLTy6",
-"9rlg97lUXZ","soy9t9rlg9","24ARFru4UG","ReKEWlH1kt","zY1GYCK5W7","ZuDtDdmoS7","o8Uydulk41","ReKEWkB5nP","oGu6xNhXdu","Cfgr38cVD3",
-"LbRTHhUTw7","pT8wu580YD","lm0pDdmoS7","8TxD7zHF1q","v2eC3VNCPd","0h1b1lsQGo","QChxscmXIX","0h1b1BpYhV","zbIYY7hyVv","SmGzvhe9IA",
-"jS1ajPb1pa","Ta8f6HRxd8","0Kyfs7Ow5C","QworuzHF1q","ulk41dmoS7","5nmWvlkMUA","Cfgr3iKqhr","QnJ1S0Wr5y","y94nwSs0Zu","07n1cVprf2",
-"OUYuFNxx9V","iqv4kBpYhV","618Ditl72W","uvf7A0BmCy","5Drn05drc6","PYBf4M6qcG","JXljWs93Ml","J2mQizqH0W","CNHmvIKxdL","RsQUqrz7Ut",
-"nFqik29QAz","8cVD37fKYU","55rfBy94nw","5Drn0jfREu","xReecReKEW","n8pJ9ZzJHW","9rlg9JJs5m","MmKGJo8Uyd","Kr8ys16lHc","yToGWJkzUn",
-"AXpwEZuDtD","iwzGk0Wr5y","I7p2apiJSk","MojnPSbRYy","Ul4a1RzaZA","9rlg9RACuj","L7cGciqv4k","7X3uyzY1GY","EOE1ov2eC3","yofH3dmoS7",
-"zFgtBuJScX","BpYhVzQt6Q","jSjS3RpBQm","KsjRKD6rBy","Cfgr3RACuj","5iGN5MmKGJ","7fKYU0h1b1","EOE1oqaofN","2ZHdkM3zXL","SbRYyRxrsm",
-"fLNg8WPmlx","gjUTuzY1GY","vOqCEgtCA5","hUTw7jS1aj","K20wKJXljW","xXTI4zQt6Q","VLTy6e6e4z","y94nwvOqCE","xXTI4brhlQ","618DiDQimp",
-"IKxdLlkMUA","ZJTXHVprf2","ECMvUWPmlx","tlILtxciqp","jzUqRJJs5m","l83UdbZLvS","JXljWrKDLJ","DLhzMFnPFB","GXdoHNcICA","fcJOy9iGoT",
-"IBe8k3weIF","WaWsvQworu","QWxoTVNCPd","uZPqgCxVEf","VerEA5ZaEz","2hEEUNcICA","lViBvL7cGc","KZamHaDGtS","Chuy3SWfou","K4GS8lpF6W",
-"7X3uyhSSvQ","atef2azIWp","6q6L9W7cTs","sx5GlX6Pin","UlU3MrKDLJ","jS1ajW7cTs","PYBf4Nxx9V","pT8wuzQt6Q","8hJdt3weIF","yEfy9uAWyp",
-"VBjhzYw2oU","pv0i7No0Qb","x3LDes93Ml","fLNg8BFkb8","xciqpRsQUq","29QAzFVMxo","4dEz6W7cTs","ZzJHWlXFOB","XflUqn1pmO","gtCA5LewvM",
-"M3zXL5VZjS","iKqhrAOgEe","VBjhzKZamH","MojnPMkgy8","AmdQdiB08l","W3VFHtjQxs","cQOnvF6PT2","CqqaDCdyBV","8cVD3v8yFN","VjCZqYf2Ec",
-"oVQp6fcwDa","RmDcrksJby","JKWYRCK5W7","lXFOBatef2","pvgjSZUnqt","FnPFBKZamH","9rlg92TRI7","JIqXiPYBf4","JIqXiqaofN","JRJQBdhSuH",
-"i3pydtAOsr","he9IAMkgy8","3weIFLbRTH","aL6AJJJs5m","JKWYRpvgjS","tAOsrNhXdu","BpYhVuupzk","S77LHyluBx","xXTI4JJs5m","uN6r3uvf7A",
-"pv0i78TxD7","ZuDtDksJby","VerEAXflUq","14FLR5iGN5","bZLvS618Di","fcJOyQworu","Pb1paAmdQd","ni2v1SmGzv","Ul4a1580YD","ogLgc2Yz7E",
-"CqqaDt98iW","aL6AJl83Ud","pT8wulj07Q","HlUbFM3zXL","okgRiYf2Ec","pvgjSqaofN","Chuy3fmIK1","lkMUAIBe8k","45cIHZUnqt","5Mg9reuZA5",
-"gtCA5i3pyd","QYxC0yofH3","NcICA5ZaEz","xReec0MR5X","tuDySGWqqX","HlUbFSmGzv","jtn0XKASQ8","0BmCyMm8si","uvf7AMm8si","k85AeVIlwP",
-"RzaZAxReec","QClRL2DREs","FwEJzAmdQd","pT8wulsQGo","0BmCypmeCd","zFgtBI7p2a","PYBf41j5L8","5Mg9rOz8yZ","lCMxyUlU3M","6q6L9C2Irc",
-"d7vjMy94nw","bZLvSG1RhS","faHir8cVD3","lCMxyGXdoH","cL0aEWMiS3","Gv3FqTXQ0Z","7ku1p9eoRc","gIYvEd7vjM","2TRI7Q6hMC","uAWypF6PT2",
-"MmKGJQssNC","Ul4a1RsQUq","kZANmSbRYy","ZzJHWiB08l","9GXkXjfREu","YOfrY8hJdt","faHirHRxd8","QWxoTdpe1v","tl72WlCMxy","ZzJHWStlDJ",
-"iwzGkk85Ae","uZPqgblLA9","0MR5XjSjS3","55rfBCfgr3","7X3uytl72W","Waim6yvOMI","KZamH7fsYM","0ao3l9rlg9","IjTwPdmoS7","pmeCdJXljW",
-"k85AeP6bcg","uupzk14FLR","pvgjSt59lR","fcJOyciuWz","qQxHPzqH0W","jSjS3t98iW","DLhzMAIYUu","fLNg8jiVBP","i3pyduN6r3","iKqhruZPqg",
-"cmXIXDQimp","2NslmQbxXc","tjQxsRxrsm","h1zcHbrhlQ","lpF6WxReec","5nmWvyvOMI","uQIczRmDcr","5Mg9rQ6hMC","iB08lFhtgl","SjskQfqypy",
-"S77LHStlDJ","0BmCyWreyP","euZA5aDGtS","MGlTF8TxD7","3otm6AXpwE","y94nwxReec","HlUbFLewvM","pmeCdCfgr3","CxVEfY1mC0","atef2OUYuF",
-"FwEJzbZLvS","EoToPgIYvE","580YD48cHL","ulk417lUXZ","RACuj0Kyfs","7ku1plm0pD","o8Uyddpe1v","POUYSLDk6f","hUTw7uQIcz","FjHXRbgJAz",
-"WPmlxa00b5","KZamHMK07Y","lj07QGXdoH","BpYhVWaim6","OxWIHyvOMI","Uvlv4mX2GE","K4GS8Dz1R3","okgRiHfyNQ","mz8gxTwano","iwzGkjSjS3",
-"Z4I1vNo0Qb","guMb8HP433","pFrrlRsQUq","yEfy9jeskS","45cIHHfyNQ","AkKTkTXQ0Z","WreyP5Mg9r","lm0pDru4UG","KsjRKUl4a1","D6rByuupzk",
-"5ZaEz7hyVv","s93MlfcJOy","9y4lwJkzUn","Waim6EdBKc","v8yFNFFDui","K20wKlViBv","dhSuHAIYUu","pT8wuIn3NS","nFqikhe9IA","lpF6W0BmCy",
-"Yh1hFhSSvQ","GWqqXyEfy9","lj07Qmz8gx","cShY2ciuWz","4QMc9taOXK","bgJAzAgJHQ","DG4sTMGlTF","5Mg9rQworu","vLsmSOUYuF","8FmFHfcJOy",
-"AmdQdsqVrf","8FmFHUmaEv","qUJMdRpBQm","KZamH9GXkX","atef2nlaBy","TwanoDG4sT","0h1b1QWxoT","24ARFydG8U","uTacxJJs5m","OxWIHCp3mZ",
-"qQxHP580YD","jeskSCp3mZ","1v5hHLewvM","AIYUufLNg8","0PktIuupzk","okgRiFxX9q","WreyPHlUbF","fLNg8piJSk","lm0pDzHF1q","AIYUudmoS7",
-"Pb1pan8pJ9","FPfSEmz8gx","pFrrloGu6x","ThjNnPb1pa","yvOMIjiVBP","QYxC0MojnP","pvgjSMojnP","lm0pDlm0pD","UmaEvIRh48","fqypyy94nw",
-"DQimpZ4I1v","nlaBy5iGN5","tAOsrn1pmO","k85AeCqqaD","pmeCduJScX","JXljW4QMc9","RkQkeQYxC0","sqVrfM3zXL","DG4sTSjskQ","CK5W7zHF1q",
-"0Wr5yGWqqX","CqqaDOUqFM","yofH3uupzk","NAFuwblLA9","DG4sTRsQUq","KZamHfaHir","OxWIHzHF1q","Gv3FqRzaZA","wDajX9iGoT","2hEEUIKxdL",
-"ZUnqtD6rBy","nnP8odhSuH","WDVWJ9rlg9","zqH0WZzJHW","kZANmB3qem","uvf7A1v5hH","9XyT964s8N","MmsIo24ARF","DQimpB3qem","WmadAlsQGo",
-"cQOnvgf8rI","jfREuWaWsv","zFgtB9XyT9","sqVrfWaWsv","SbRYyfLNg8","VNCPdd85a9","MmsIo6q6L9","GSQwjgIYvE","yluBxkZANm","wDajX45cIH",
-"wiHrZ5Mg9r","nnP8o0h1b1","sx5GlVerEA","MmKGJtl72W","uZPqg45cIH","jiVBPl83Ud","suY4xv8yFN","QssNCdhSuH","8FmFHUl4a1","brhlQkZANm",
-"UmaEvTXQ0Z","k85Ae24ARF","xciqpfFDrJ","tjQxsWaWsv","aFFss45cIH","pmeCd5nmWv","Cfgr3gtCA5","KsjRKJJs5m","dQ5860YAGH","sx5Gluupzk",
-"618Di8TxD7","55rfBv8yFN","zmLYD9y4lw","azIWpOz8yZ","TCgPpK20wK","FNYIMokgRi","KASQ8faHir","HfyNQ8RCUA","iB08lEdBKc","a00b5qaofN",
-"In3NSGXdoH","rhl0JdhSuH","jtn0XQnJ1S","nlaBy8RCUA","IjTwPYOfrY","kB5nPBGaQY","mX2GEaDGtS","YjB9th1zcH","a00b5UmaEv","5drc6POUYS",
-"5iGN5lXFOB","pWiOs5Mg9r","tAOsrBbwgA","0BmCyx3LDe","tvdkDDz1R3","64s8NDz1R3","JJs5mNcICA","uJScXLDk6f","h1zcHs4786","UlU3MMGlTF",
-"07n1cuvf7A","TCgPpQWxoT","Nxx9VzY1GY","JKWYRru4UG","XflUq9GXkX","uPX7GkZANm","Zv7z01v5hH","FPfSEOz8yZ","zmLYD6AFT0","45cIHYjB9t",
-"zHF1qBpYhV","wiHrZ8cVD3","NAFuwi3pyd","9y4lwnlaBy","JJs5muPX7G","48cHLFGzgp","d85a97hyVv","ulk41WMiS3","JRJQBTwano","C2IrcnnP8o",
-"RACujxciqp","K4GS88TxD7","blLA9FFDui","yvOMIY1mC0","07n1cAkKTk","DQimpjeskS","iKqhrYh1hF","XflUq7Ow5C","Dz1R3X6Pin","48cHLbrhlQ",
-"ECMvUru4UG","blLA9DG4sT","djsrv48cHL","EOE1oVLTy6","jfREugtCA5","zqH0W8FmFH","VLTy6MmsIo","fcJOyh1zcH","OUqFMSjskQ","lkMUAkB5nP",
-"s4786IKxdL","MezSWIRh48","Mm8sidhSuH","RpBQmFVMxo","uoStwGv3Fq","2TRI7mz8gx","pmeCdhe9IA","IBe8k2TRI7","No0Qbmz8gx","aDGtSHRxd8",
-"jSjS37lUXZ","aDGtSMezSW","8RCUARkQke","gjUTuLDk6f","ECMvUrz7Ut","HzZT8QbxXc","0ao3lKsjRK","BGaQYgIYvE","jeskSwDajX","PYBf4s7Mxk",
-"suY4xJRJQB","0MR5XUl4a1","Zv7z0AIYUu","ydG8Uix74r","U3yw5cL0aE","aez9yzmLYD","QssNCJ2mQi","vLsmSFNYIM","piJSkQ6Lix","RmDcrUmaEv",
-"sqVrfFGzgp","uJScXGv3Fq","7hyVvJKWYR","xXTI49rlg9","BCxeC24ARF","kZANmbZLvS","14FLRCK5W7","jS1ajRkQke","lXFOBbgJAz","Cp3mZ7Ow5C",
-"mz8gxYjB9t","4W0TllXFOB","CK5W7faHir","2ZHdkNAFuw","lXFOBlweGy","uJScXP6bcg","AkKTkpiJSk","9XyT92Yz7E","618Di6AFT0","O3iyQJRJQB",
-"CIShGtlILt","NcICAzz4ZU","B3qemHP433","AIYUu4W0Tl","Ss0ZurKDLJ","fFDrJ8RCUA","5IhmG2ZHdk","9XyT9WDVWJ","2TRI7nFqik","HzZT8MaJQs",
-"Yw2oUkB5nP","kB5nPWDVWJ","lpF6W4dEz6","KsjRK2ZHdk","yvOMIuZPqg","soy9tCdyBV","EOE1os7Mxk","8U2nUpv0i7","LewvMiwzGk","0ao3lNo0Qb",
-"9iGoTLDk6f","JKWYRVBjhz","5nmWvS77LH","oVQp69rlg9","s7MxkCp3mZ","iB08lJkzUn","y94nwCqqaD","QbxXc16lHc","ydG8UIKxdL","jiVBP55rfB",
-"9rlg9No0Qb","9XyT9HfyNQ","uZPqgaez9y","aez9yZhwG1","8hJdt4W0Tl","SbRYy5drc6","POUYSd85a9","lpF6W9GXkX","jS1aj29QAz","B3qempFrrl",
-"VIlwP45cIH","zbIYYFVMxo","ZJTXHG1RhS","AgJHQDz1R3","Pb1pamX2GE","ZzJHWVBjhz","s93MlX6Pin","gf8rId85a9","8FmFHCK5W7","fmIK1VIlwP",
-"gjUTueuZA5","U3yw5GSQwj","lpF6WK20wK","7lUXZTa8f6","b29RJ5VZjS","zmLYDdmoS7","6AFT0Cp3mZ","7lUXZ7ku1p","lkMUAjeskS","piJSkfcJOy",
-"taOXKfaHir","ReKEWEoToP","OxWIHJJs5m","fqypyAkKTk","2Yz7ENxx9V","gf8rI07n1c","CdyBVJKWYR","JKWYRI7p2a","ECMvUFjHXR","S2DfuUl4a1",
-"AXpwE6AFT0","gjUTutlILt","5iGN50Kyfs","rhl0JfLNg8","CqqaDS77LH","t59lR6AFT0","ydG8UGXdoH","prNT6Mm8si","OxWIH0YAGH","RpBQmFxX9q",
-"O3iyQRACuj","o8UydtlILt","MmKGJ29QAz","WDVWJksJby","6q6L9FcWrW","S2DfuL7cGc","8hJdt0Wr5y","YjB9ttaOXK","RxrsmyluBx","tAOsrvkCHH",
-"9rlg9tl72W","hE1QluTacx","fcwDaFPfSE","GSQwjhe9IA","OUYuFpmeCd","jfREuZhwG1","pWiOsL7cGc","W3VFHdQ586","ulk41Gv3Fq","gf8rIhe9IA",
-"ciuWzzz4ZU","jSjS3v2eC3","StlDJfqypy","pmeCdjtn0X","jiVBPAgJHQ","NAFuwBFkb8","S77LH2ZHdk","ix74rFjHXR","iwzGkUl4a1","VIlwPEdBKc",
-"Vprf2WreyP","0h1b1FFDui","BGaQYEoToP","wiHrZxReec","oGu6xwDajX","MGlTFksJby","tl72W618Di","4QMc9RsQUq","fcJOyfLNg8","QYxC0uAWyp",
-"faHir5IhmG","5iGN5618Di","s4786jfREu","hE1Ql9GXkX","8RCUACfgr3","uvf7AZUnqt","ydG8UxReec","Ul4a1tAOsr","K4GS8s93Ml","5iGN5ZzJHW",
-"OUqFMru4UG","SmGzvuoStw","hE1QlK20wK","v1HlnStlDJ","lXFOBM3zXL","JkzUnJ2mQi","StlDJFFDui","i7WMQLewvM","1v5hHFVMxo","he9IAd85a9",
-"qQxHPlm0pD","pmeCdOHaBz","hUTw7RmDcr","JRJQBKZamH","jeskSEoToP","14FLRe6e4z","F6PT22Yz7E","lpF6WAIYUu","uoStw8xEKz","taOXK16lHc",
-"JXljWCp3mZ","Chuy3tAOsr","zbIYY5iGN5","t98iWcmXIX","zz4ZUQClRL","5nmWv5IhmG","9y4lwh1zcH","9XyT9VNCPd","FcWrWuJScX","9GXkXfcwDa",
-"7Ow5CYw2oU","OHaBzF6PT2","uJScX2DREs","DG4sTCfgr3","F6PT2uN6r3","o8UydKZamH","Mkgy8MmKGJ","xXTI4faHir","KZamHyofH3","5Mg9rJ2mQi",
-"ksJbyzqH0W","uLtKsGSQwj","rhl0Juupzk","x3LDe7X3uy","Ss0ZuFnPFB","IjTwPtaOXK","HlUbFguMb8","wiHrZZhwG1","yvOMIfmIK1","ksJbyCp3mZ",
-"VNCPd9XyT9","jS1ajPYBf4","JRJQBCIShG","d7vjM0ao3l","DG4sT2hEEU","Rxrsm0PktI","RxrsmZv7z0","piJSky94nw","7lUXZQWxoT","hi5X7ZzJHW",
-"9XyT9i3pyd","DLhzMZ4I1v","S2Dfutl72W","Ss0ZublLA9","K4GS8HP433","pv0i7hUTw7","Oz8yZDcpWB","lH1kt9GXkX","gf8rIpv0i7","hUTw7lCMxy",
-"Chuy3ogLgc","piJSkYw2oU","hYBCKmz8gx","4QMc9y94nw","0MR5X4QMc9","iwzGkuupzk","pFrrle6e4z","KASQ8VLTy6","BFkb8uupzk","ZhwG1jtn0X",
-"Cp3mZgdQsS","oQ87rOUqFM","24ARFyofH3","n8pJ9K20wK","9eoRcuvf7A","BFkb86AFT0","F6PT2VjCZq","IRh48GSQwj","8hJdt2Yz7E","VerEAMmKGJ",
-"3weIFuLtKs","16lHcW3VFH","RpBQmuQIcz","fcwDaFVMxo","bgJAzWreyP","fqypyD6rBy","uN6r3X6Pin","NAFuwZJTXH","uPX7GMK07Y","n1pmO3otm6",
-"fqypya00b5","MaJQss7Mxk","hUTw79XyT9","WPmlxgf8rI","hUTw7MGlTF","uTacxMojnP","8xEKzFLsph","RxrsmMaJQs","StlDJbZLvS","1v5hHl83Ud",
-"ru4UGtvdkD","fLNg8Cp3mZ","9GXkXoGu6x","IjTwPhSSvQ","tl72WQClRL","blLA9uLtKs","ZhwG1tuDyS","Yh1hFxciqp","IBe8kiB08l","8FmFHjiVBP",
-"lsQGo7lUXZ","vkCHHzqH0W","dhSuH8TxD7","7ku1p2TRI7","GrDg7pWiOs","Dz1R3FjHXR","AgJHQLewvM","zQt6QvLsmS","zz4ZUn1pmO","LDk6flH1kt",
-"mz8gxSWfou","0MR5XbrhlQ","Cp3mZHzZT8","5ZaEzb29RJ","8TxD707n1c","GWqqX6q6L9","NhXduXyPZN","s478616lHc","v8yFNZv7z0","tvdkDgtCA5",
-"ZUnqtS2Dfu","NhXduCp3mZ","TwanoAgJHQ","TXQ0Z7hyVv","SmGzvzmLYD","taOXKtuDyS","IjTwPWaWsv","FnPFBKsjRK","JRJQBix74r","MmKGJzqH0W",
-"HRxd8hE1Ql","zQt6QAkKTk","OxWIH0ao3l","d7vjM7X3uy","zY1GYfaHir","s47865nmWv","55rfBjiVBP","faHirCfgr3","JIqXiYf2Ec","djsrvStlDJ",
-"S2DfuiwzGk","0MR5X9XyT9","h1zcHv8yFN","WDVWJVerEA","BCxeCuQIcz","IKxdLGWqqX","FnPFBdpe1v","Yh1hFHlUbF","uupzkQbxXc","t59lRRBhp0",
-"yToGWZUnqt","uPX7GlpF6W","gjUTuZv7z0","BbwgAEoToP","ogLgc0PktI","W7cTsSs0Zu","6AFT0QChxs","ReKEWv1Hln","nlaByLewvM","d7vjMwiHrZ",
-"8hJdtJIqXi","fmIK1zqH0W","IKxdLtuDyS","MaJQsnlaBy","618Di9eoRc","POUYSG1RhS","vLsmStlILt","HRxd8azIWp","XyPZNUl4a1","Oz8yZTCgPp",
-"vkCHHWPmlx","SjskQ7X3uy","gIYvE8cVD3","gf8rIx3LDe","WDVWJQClRL","xXTI4C2Irc","taOXKrz7Ut","EdBKclj07Q","iqv4kL7cGc","07n1cazIWp",
-"JXljWJXljW","2Yz7Em4bxU","K4GS8IKxdL","Ul4a1VerEA","M6qcG9y4lw","ZhwG1gIYvE","oGu6x2hEEU","0Wr5yZ4I1v","m4bxUpvgjS","8U2nUkB5nP",
-"kB5nPFcWrW","JkzUnFVMxo","jfREuRpBQm","s4786guMb8","QChxsEdBKc","rz7UtW7cTs","B3qemeuZA5","rKDLJqUJMd","5iGN5cmXIX","24ARF4W0Tl",
-"tl72Wt98iW","LbRTHM3zXL","dQ586ydG8U","RkQkesoy9t","Mm8siDLhzM","8FmFHJ2mQi","CNHmvQChxs","gf8rI8hJdt","aFFssnnP8o","dhSuHhE1Ql",
-"9XyT9lsQGo","P6bcgK4GS8","Yw2oUZv7z0","Chuy316lHc","Ta8f6yluBx","YOfrYaL6AJ","WmadAWMiS3","FwEJzwDajX","CNHmvAOgEe","FcWrWtl72W",
-"IjTwPU3yw5","RpBQmJ2mQi","2DREsYf2Ec","yluBxWMiS3","DG4sTDQimp","S77LHkB5nP","uQIcz8U2nU","FLsphDQimp","RACuj9rlg9","oQ87rlH1kt",
-"YjB9tPb1pa","QnJ1S0ao3l","ciuWzlViBv","Mm8siIn3NS","RACujReKEW","uupzkzz4ZU","jfREulsQGo","vLsmS2DREs","7ku1pJRJQB","hE1QlUvlv4",
-"DcpWBhSSvQ","D6rByFFDui","jeskS2DREs","JIqXis7Mxk","07n1cKZamH","0PktIFGzgp","RmDcr2hEEU","iqv4kyluBx","x3LDeHzZT8","7X3uyC2Irc",
-"l83Udhe9IA","tvdkDVBjhz","gf8rITa8f6","DLhzM0MR5X","ulk41LbRTH","Pb1paS77LH","jiVBPrhl0J","ix74rJ2mQi","L7cGcZuDtD","xciqpTa8f6",
-"ni2v11j5L8","QYxC0SjskQ","In3NSdpe1v","pWiOsdhSuH","ydG8UPYBf4","ix74rGXdoH","pvgjSF6PT2","QnJ1S8xEKz","e6e4zOHaBz","brhlQKZamH",
-"B3qemIn3NS","7ku1pRkQke","0PktINcICA","ReKEW5iGN5","RxrsmqQxHP","ni2v1Yh1hF","AXpwEDG4sT","vOqCEe6e4z","L7cGcjS1aj","Pb1paZuDtD",
-"KsjRKLewvM","ZuDtDoQ87r","EoToPLDk6f","djsrvGrDg7","a00b5wiHrZ","EOE1o2Nslm","wiHrZ7hyVv","IjTwPYw2oU","hSSvQZhwG1","0ao3lFnPFB",
-"guMb80PktI","IRh48ydG8U","qQxHPZhwG1","yvOMIeuZA5","t59lRxReec","JXljWECMvU","XyPZNl83Ud","IKxdL6q6L9","yvOMIatef2","pvgjSiwzGk",
-"iKqhrsqVrf","55rfBsoy9t","CdyBVMaJQs","Zv7z0B3qem","5Mg9rCxVEf","VNCPdni2v1","zqH0Wni2v1","ZhwG1oGu6x","pmeCdVIlwP","WmadAdmoS7",
-"Ss0ZuqQxHP","6AFT0uPX7G","2TRI78U2nU","Waim6HfyNQ","gf8rIvOqCE","kZANm8TxD7","CNHmvVerEA","jSjS3Yw2oU","suY4x0MR5X","iwzGkiwzGk",
-"J2mQia00b5","AmdQdtl72W","BCxeCcShY2","VBjhzfcwDa","7X3uyeuZA5","X6Pinrz7Ut","n1pmOfFDrJ","CdyBVfLNg8","ogLgcogLgc","pvgjSWreyP",
-"pFrrlyvOMI","CK5W7K20wK","s93Ml3otm6","FPfSE8xEKz","2ZHdkhE1Ql","Oz8yZB3qem","AOgEeAOgEe","y94nwD6rBy","OHaBzt59lR","FwEJzm4bxU",
-"07n1cQ6Lix","2DREs9XyT9","Yh1hF8TxD7","9y4lw580YD","suY4xn8pJ9","No0QbsuY4x","fcwDaUvlv4","RzaZA5IhmG","MmsIoiB08l","5Drn08U2nU",
-"Yh1hFbrhlQ","lXFOB55rfB","XyPZN7X3uy","ydG8UEoToP","IBe8kOxWIH","soy9tuQIcz","8FmFH0ao3l","pmeCdvLsmS","cmXIXqaofN","lweGyv8yFN",
-"0ao3lzHF1q","CdyBVPb1pa","UlU3MwDajX","ZuDtDZhwG1","qaofNUlU3M","GXdoHlH1kt","CdyBVeuZA5","L7cGcoVQp6","8xEKz8xEKz","VNCPdQnJ1S",
-"AOgEe2ZHdk","ciuWzh1zcH","s93MllpF6W","07n1cfFDrJ","MmsIoC2Irc","ciuWzUvlv4","iKqhrFPfSE","7ku1p8TxD7","MojnPoVQp6","TCgPpvLsmS",
-"rz7UtAXpwE","gf8rIK20wK","QWxoTYjB9t","TwanoxXTI4","kZANmmX2GE","618DiiKqhr","AkKTk5Drn0","PYBf42ZHdk","JJs5myluBx","0MR5XlsQGo",
-"IRh481v5hH","Vprf2FnPFB","5Mg9ryluBx","v8yFNMK07Y","lCMxyWaim6","580YDHzZT8","Ss0ZuZhwG1","n8pJ99GXkX","AmdQdulk41","JkzUnQbxXc",
-"fmIK1Ss0Zu","GWqqXnlaBy","azIWpulk41","djsrvbZLvS","n1pmO8TxD7","M3zXLnnP8o","DQimppvgjS","atef2rhl0J","tvdkD7Ow5C","CxVEffFDrJ",
-"Rxrsme6e4z","7ku1po8Uyd","uZPqgciuWz","BFkb8J2mQi","KASQ8lj07Q","uTacx5Mg9r","Chuy3DG4sT","BbwgAtjQxs","pFrrl618Di","0h1b1atef2",
-"2Nslm7lUXZ","G1RhShSSvQ","CK5W7iwzGk","xciqpk85Ae","S77LH0Wr5y","UlU3M48cHL","fcJOylkMUA","brhlQZv7z0","POUYSYf2Ec","b29RJxReec",
-"580YDru4UG","jeskSGXdoH","jSjS3VIlwP","IRh48fLNg8","yToGWIn3NS","AIYUuJ2mQi","uAWypOxWIH","tl72WwDajX","KsjRKFwEJz","MK07YnnP8o",
-"S2DfuCxVEf","QssNCciuWz","djsrvEdBKc","Mm8si5iGN5","JJs5mhi5X7","29QAzQ6hMC","EoToPSbRYy","v2eC3iB08l","Chuy3Cfgr3","iwzGklweGy",
-"NAFuwHP433","NhXduCNHmv","Q6hMCVerEA","7X3uyMK07Y","okgRihSSvQ","WPmlxKASQ8","L7cGc7ku1p","nlaByt59lR","HfyNQtjQxs","6AFT0U3yw5",
-"2Nslm7fsYM","BFkb8gf8rI","s93MlxXTI4","GWqqX8xEKz","iqv4k2hEEU","hi5X7BGaQY","K20wK64s8N","LbRTHG1RhS","djsrvpmeCd","LewvMHP433",
-"hE1QlOUqFM","CdyBV5drc6","qQxHPVprf2","L7cGc7lUXZ","OUqFM9GXkX","LbRTHRACuj","wDajXdQ586","gf8rINhXdu","Ss0Zu14FLR","JKWYRn8pJ9",
-"QChxsFFDui","SWfoufLNg8","SmGzvRkQke","RBhp0brhlQ","e6e4z4QMc9","QnJ1SP6bcg","5nmWvv1Hln","bZLvSRBhp0","OxWIHUvlv4","AXpwEoVQp6",
-"8hJdtJkzUn","FPfSEgjUTu","d7vjMAmdQd","UmaEvRkQke","nlaBy0Wr5y","2DREs9eoRc","5VZjSmz8gx","16lHc9y4lw","JRJQBCxVEf","ReKEW2Yz7E",
-"ulk414QMc9","VIlwPhUTw7","FPfSEm4bxU","wDajXprNT6","1LB1LlsQGo","1j5L82ZHdk","C2IrciB08l","GrDg7NhXdu","EdBKcFFDui","RBhp0K20wK",
-"aL6AJOz8yZ","HRxd8JRJQB","7Ow5CydG8U","iqv4kSWfou","VNCPdFcWrW","16lHc7lUXZ","7fsYM5Namm","8cVD3uN6r3","iwzGk8hJdt","FPfSEZv7z0",
-"DG4sT5Drn0","BCxeCsoy9t","sqVrfa00b5","QYxC0zmLYD","JIqXi4W0Tl","8xEKzB3qem","ix74r2hEEU","16lHcm4bxU","kB5nPfcwDa","IjTwPjfREu",
-"CqqaDzQt6Q","5Namm6q6L9","QnJ1SMkgy8","m4bxUY1mC0","EOE1oRzaZA","QbxXcpiJSk","uTacx64s8N","vkCHHUlU3M","iwzGkpT8wu","m4bxUksJby",
-"Nxx9VU3yw5","NcICAbZLvS","e6e4zyvOMI","CNHmvU3yw5","aDGtSFxX9q","GSQwjZzJHW","GXdoHkB5nP","QYxC0POUYS","yvOMI5Mg9r","rhl0JsqVrf",
-"K4GS8MezSW","0KyfsnnP8o","DG4sTzQt6Q","JRJQBlkMUA","m4bxUjiVBP","Mkgy8ZuDtD","Uvlv4Yf2Ec","7fKYUuoStw","yEfy9lj07Q","jtn0Xd85a9",
-"2DREsQChxs","JJs5mOUYuF","QnJ1SblLA9","CdyBVZhwG1","OUYuFPOUYS","5IhmGS77LH","rhl0JtjQxs","dmoS7dhSuH","aez9y9XyT9","WPmlxMojnP",
-"pAhR1d7vjM","5Mg9ryofH3","5Drn0BpYhV","WPmlxVIlwP","K20wKI7p2a","YOfrY1v5hH","iKqhrpv0i7","tlILtHRxd8","2TRI7vOqCE","5nmWv8xEKz",
-"ZUnqtn8pJ9","oQ87rXyPZN","prNT6Pb1pa","9XyT9zbIYY","Rxrsmlj07Q","NOHszCqqaD","29QAzSWfou","HRxd8prNT6","sx5GlECMvU","W7cTst98iW",
-"uvf7AdmoS7","5nmWvEoToP","RBhp0n1pmO","b29RJguMb8","5Drn0mX2GE","AmdQdk85Ae","iB08l9y4lw","F6PT2FLsph","EdBKcRkQke","2Yz7EYf2Ec",
-"lH1ktlViBv","iKqhrHlUbF","brhlQzHF1q","4QMc9DQimp","s93MlhUTw7","OUqFM1v5hH","FLsphRmDcr","MojnPprNT6","vLsmSfaHir","n8pJ9lsQGo",
-"Cp3mZCfgr3","5drc6YOfrY","tlILtkZANm","Cfgr3lsQGo","BCxeCcQOnv","yofH3vkCHH","qUJMdZ4I1v","fmIK10PktI","VBjhzlsQGo","W7cTs8RCUA",
-"GrDg7ix74r","KASQ8iKqhr","iqv4katef2","kB5nPNcICA","uTacx9iGoT","hi5X7LDk6f","0BmCyIRh48","X6PinFwEJz","MaJQs0Kyfs","Ta8f6VNCPd",
-"FFDuiZuDtD","jS1ajfaHir","bgJAzokgRi","rKDLJtlILt","Nxx9VguMb8","wiHrZd85a9","okgRi9GXkX","580YDQWxoT","DQimpZv7z0","2DREsHfyNQ",
-"AXpwEuJScX","ydG8UK20wK","G1RhSZJTXH","tjQxsAmdQd","taOXK1j5L8","wDajXxXTI4","e6e4zzz4ZU","Zv7z0GrDg7","2NslmcmXIX","5Drn0XflUq",
-"VIlwPmz8gx","DG4sTFhtgl","UlU3MBFkb8","hSSvQGWqqX","lsQGoYh1hF","07n1cBbwgA","VLTy6WmadA","uupzkO3iyQ","0ao3l14FLR","FLsphFVMxo",
-"6AFT0WDVWJ","ZUnqtuupzk","BFkb85Mg9r","nFqikK20wK","9iGoTMezSW","XyPZNiwzGk","faHirBFkb8","CIShGnFqik","Yh1hFMmKGJ","ZuDtDfcwDa",
-"BCxeCGXdoH","S77LHFcWrW","piJSka00b5","jS1ajyToGW","uJScXHP433","h1zcH8hJdt","v1HlnxReec","O3iyQNcICA","FxX9qhi5X7","Pb1pawDajX",
-"aez9ylm0pD","2Yz7ENcICA","pFrrlsx5Gl","0PktI9GXkX","Z4I1vPYBf4","kB5nPWreyP","2NslmCp3mZ","P6bcgs4786","lViBvqQxHP","7hyVvtl72W",
-"jS1ajGXdoH","YjB9t0Wr5y","atef2Gv3Fq","yEfy9xciqp","XyPZNgIYvE","2ZHdkMkgy8","zz4ZU3weIF","2ZHdkFnPFB","VNCPdqQxHP","atef2hSSvQ",
-"QssNC7Ow5C","Nxx9VK4GS8","k85AeKASQ8","0PktIuLtKs","7X3uy14FLR","BGaQYVNCPd","7fKYUiB08l","ogLgcCfgr3","pvgjSK20wK","ZUnqtsx5Gl",
-"pAhR1lm0pD","48cHLWDVWJ","n1pmOtaOXK","Waim68cVD3","lj07QFFDui","bZLvSa00b5","O3iyQtlILt","e6e4zrhl0J","64s8NNhXdu","O3iyQ8cVD3",
-"dmoS7AOgEe","tjQxsuoStw","o8UydJ2mQi","1v5hH2Nslm","y94nw2TRI7","FwEJzgf8rI","qaofNY1mC0","gdQsSCNHmv","2TRI7TXQ0Z","W7cTs9rlg9",
-"FhtglyToGW","pmeCdK20wK","VNCPdJXljW","BFkb8fqypy","ZhwG1618Di","0KyfsYf2Ec","8cVD3hi5X7","BpYhV3otm6","he9IARBhp0","5Mg9rJIqXi",
-"HRxd8JJs5m","uvf7AuPX7G","5IhmGQ6hMC","LDk6fMaJQs","xXTI4B3qem","FxX9qv2eC3","xXTI4Qworu","oQ87rnlaBy","lCMxyFhtgl","Zv7z0jS1aj",
-"cL0aEW7cTs","2TRI7Oz8yZ","Uvlv4Cp3mZ","uTacxG1RhS","aL6AJQnJ1S","uQIczCIShG","oGu6xbgJAz","2NslmEdBKc","KASQ8sqVrf","Twano618Di",
-"QworuVNCPd","FNYIMydG8U","EOE1o5Drn0","64s8NPYBf4","POUYScmXIX","atef2RpBQm","yEfy9h1zcH","hYBCK1j5L8","e6e4zYw2oU","FhtglSbRYy",
-"jS1ajwDajX","gjUTuHRxd8","NhXdu2ZHdk","AkKTkkZANm","24ARFWPmlx","aez9yrhl0J","JKWYRZ4I1v","1v5hHuN6r3","UmaEvFwEJz","KASQ85ZaEz",
-"L7cGctl72W","Z4I1vzbIYY","RpBQmaDGtS","QbxXcTXQ0Z","suY4xL7cGc","fqypyYw2oU","CIShGRkQke","vkCHHVLTy6","VIlwPqQxHP","uPX7G64s8N",
-"vOqCEaez9y","zz4ZUBFkb8","ThjNndjsrv","EoToPmz8gx","WreyPo8Uyd","FPfSENxx9V","QworuFFDui","pvgjS5drc6","yvOMIMkgy8","lkMUANAFuw",
-"DG4sTdmoS7","M6qcGECMvU","JXljWBFkb8","WMiS30Wr5y","Ta8f6pmeCd","kZANmo8Uyd","J2mQiChuy3","OUYuFfFDrJ","WaWsviKqhr","lpF6WYh1hF",
-"8hJdtECMvU","SjskQuvf7A","Yh1hFxXTI4","brhlQydG8U","7fsYMfFDrJ","vOqCEAIYUu","jeskSF6PT2","QChxsm4bxU","qQxHPGv3Fq","aDGtSWPmlx",
-"vLsmSgf8rI","4QMc99y4lw","QChxss7Mxk","DG4sTuupzk","zqH0WVBjhz","aL6AJKASQ8","zqH0W29QAz","jS1aj618Di","618DiRmDcr","zHF1q4QMc9",
-"bgJAzQYxC0","e6e4zfqypy","5VZjSS77LH","FPfSE3weIF","G1RhSIjTwP","K4GS8RkQke","8U2nUgdQsS","SbRYyTCgPp","7Ow5C2TRI7","lXFOBbrhlQ",
-"pAhR12TRI7","WmadAv2eC3","TwanoQWxoT","M3zXLyEfy9","7lUXZMaJQs","t59lRLewvM","nFqiksuY4x","7lUXZaFFss","pmeCdtlILt","Q6LixDQimp",
-"Z4I1vxXTI4","Rxrsmm4bxU","FVMxoe6e4z","FcWrWiqv4k","4W0TlzQt6Q","hE1QlLbRTH","n1pmOHzZT8","W7cTsPYBf4","TCgPpZuDtD","8TxD7tlILt",
-"uN6r3AOgEe","AOgEelXFOB","ogLgc24ARF","XyPZNZzJHW","1v5hHVLTy6","iqv4kzmLYD","lsQGoBGaQY","2Yz7EUl4a1","MezSWfmIK1","FGzgpiqv4k",
-"tl72W6q6L9","Chuy3IjTwP","jS1ajazIWp","Cp3mZlj07Q","KASQ8VNCPd","ZhwG1MmKGJ","BpYhVjtn0X","6AFT0Ta8f6","ZJTXHjiVBP","gdQsS0PktI",
-"D6rByVLTy6","tvdkD14FLR","5Mg9rx3LDe","aDGtSXyPZN","DQimp2ZHdk","m4bxUKsjRK","0Wr5yjeskS","7lUXZXyPZN","e6e4zs93Ml","7lUXZ8hJdt",
-"pWiOst59lR","k85Ae2ZHdk","DLhzMoGu6x","suY4xMK07Y","HlUbFiKqhr","JkzUnt59lR","uAWypd7vjM","1v5hHjeskS","t59lRW3VFH","5iGN5fcwDa",
-"580YD7fsYM","2DREsDQimp","8FmFHWaWsv","MezSWn8pJ9","KASQ8ni2v1","1v5hHKZamH","5drc6mz8gx","L7cGcfcwDa","55rfBJIqXi","TwanoqaofN",
-"0KyfsFxX9q","OUYuFD6rBy","7Ow5CksJby","VBjhzGv3Fq","TXQ0Zhe9IA","bZLvSWreyP","ZhwG1fcwDa","atef2e6e4z","7lUXZVBjhz","U3yw5lViBv",
-"Ss0ZuFVMxo","ZzJHWyluBx","guMb85ZaEz","BCxeCVjCZq","uvf7AzFgtB","5iGN5lm0pD","xXTI47Ow5C","AOgEexXTI4","piJSkAgJHQ","No0QbyvOMI",
-"ZhwG19y4lw","jSjS3dmoS7","v8yFNHfyNQ","8hJdtGWqqX","Uvlv4jtn0X","BbwgASjskQ","L7cGcZhwG1","jzUqRWmadA","VIlwPtvdkD","StlDJAkKTk",
-"WreyPru4UG","W3VFH5nmWv","PYBf4RBhp0","5iGN5iB08l","MGlTF9XyT9","SbRYypmeCd","Gv3FqJXljW","U3yw58xEKz","PYBf4Vprf2","S77LHpAhR1",
-"MK07YChuy3","2ZHdkuJScX","7X3uym4bxU","yEfy9FxX9q","ThjNniB08l","he9IApT8wu","kZANmfmIK1","BGaQYBbwgA","BGaQYRkQke","he9IAlXFOB",
-"IBe8kgf8rI","fcJOyLDk6f","VLTy65drc6","Yf2Ecv8yFN","F6PT25nmWv","h1zcHSWfou","CqqaDBGaQY","5IhmGxXTI4","hE1QlydG8U","FnPFBzqH0W",
-"MmKGJ5Namm","RmDcrYw2oU","uPX7GzqH0W","l83UdNxx9V","ECMvUpvgjS","HlUbFNAFuw","ThjNnDcpWB","bZLvSNOHsz","pFrrlQssNC","m4bxUlkMUA",
-"jzUqR07n1c","mX2GEMm8si","cmXIXlXFOB","jiVBPksJby","ECMvUv8yFN","jzUqRblLA9","KZamH0Kyfs","IjTwPQbxXc","lweGyJXljW","W7cTsjS1aj",
-"Vprf2rhl0J","h1zcH4QMc9","14FLRFjHXR","8cVD32TRI7","HzZT8StlDJ","9eoRck85Ae","618DiSjskQ","lXFOBJJs5m","gdQsSChuy3","WreyPHRxd8",
-"0h1b1n1pmO","jtn0XuJScX","FxX9qWaim6","uQIczGWqqX","HfyNQiKqhr","07n1cyvOMI","7fsYMcQOnv","LbRTHl83Ud","faHirUmaEv","MaJQscL0aE",
-"BCxeCYjB9t","QssNCNcICA","0Wr5y14FLR","ThjNnjzUqR","MezSWNxx9V","WDVWJcmXIX","aFFss5VZjS","a00b55Mg9r","ZJTXHVNCPd","lCMxyiKqhr",
-"0BmCyAgJHQ","0Wr5yIRh48","FPfSEDcpWB","5NammUvlv4","pv0i7TCgPp","16lHcGWqqX","lXFOBb29RJ","zqH0W5Namm","oVQp6o8Uyd","8xEKzMmsIo",
-"ogLgczbIYY","AOgEeKASQ8","C2IrcStlDJ","Yw2oUCfgr3","qUJMd5iGN5","yluBxyEfy9","Pb1parKDLJ","2ZHdkmz8gx","atef2QChxs","x3LDeYw2oU",
-"hSSvQThjNn","oGu6xPb1pa","yEfy9vkCHH","rhl0JsuY4x","pT8wucQOnv","okgRicL0aE","WaWsvuvf7A","6AFT0ZJTXH","TXQ0ZWDVWJ","IRh48uupzk",
-"ni2v1IjTwP","uAWypxReec","Chuy3uoStw","64s8NM3zXL","5Mg9rU3yw5","LDk6fzbIYY","Yf2EcM6qcG","2NslmUvlv4","x3LDeThjNn","F6PT2fqypy",
-"2hEEUCdyBV","618Di1j5L8","CxVEfWreyP","ZJTXHLewvM","zQt6QHzZT8","MK07Y29QAz","cShY2fLNg8","9eoRcMmKGJ","UmaEvi3pyd","OHaBzU3yw5",
-"WMiS3b29RJ","yofH3pmeCd","5NammMm8si","fmIK1atef2","ZJTXHIjTwP","GSQwjRACuj","FGzgpJIqXi","wDajXgtCA5","W3VFHvOqCE","FLsphChuy3",
-"d85a9wDajX","prNT6VNCPd","Ss0ZuNAFuw","gIYvEl83Ud","y94nw618Di","rz7UttAOsr","BFkb8Twano","brhlQxciqp","9rlg9rKDLJ","uoStw3weIF",
-"FjHXRrz7Ut","RpBQmhi5X7","CdyBVEdBKc","LbRTHjSjS3","JKWYRjSjS3","jS1ajQ6Lix","BGaQYOxWIH","7hyVv1v5hH","45cIHtjQxs","CdyBVDG4sT",
-"RzaZApWiOs","ThjNnTCgPp","ru4UG7fsYM","sqVrfnlaBy","FjHXRRkQke","QWxoTvkCHH","0h1b1xciqp","Pb1paix74r","dpe1vgdQsS","i7WMQCNHmv",
-"8RCUAFFDui","suY4xxciqp","hUTw7o8Uyd","5drc6G1RhS","Fhtgljtn0X","YOfrYY1mC0","i3pydGv3Fq","hE1Qlhe9IA","CqqaDQ6hMC","GSQwjCdyBV",
-"ZJTXHRmDcr","P6bcg2DREs","DLhzMThjNn","Ta8f6GrDg7","Cfgr3Dz1R3","zz4ZUyEfy9","uAWypni2v1","cShY27hyVv","lm0pDyvOMI","VerEAd7vjM",
-"GWqqXulk41","Chuy3TXQ0Z","uoStwO3iyQ","StlDJblLA9","pv0i7qQxHP","7ku1pUvlv4","dQ5869y4lw","WDVWJ2Nslm","zHF1qfaHir","qaofNRsQUq",
-"s93Mllj07Q","azIWphSSvQ","C2Irc0YAGH","9y4lwFGzgp","RkQkeRxrsm","JRJQBLDk6f","zQt6QJIqXi","4dEz6lpF6W","0ao3l5VZjS","b29RJaFFss",
-"lViBv8RCUA","FLsphYf2Ec","M3zXLBFkb8","MmKGJaFFss","WPmlx7ku1p","bgJAzVBjhz","VjCZqtaOXK","DQimpG1RhS","EdBKcBpYhV","TXQ0ZuJScX",
-"VBjhzy94nw","WPmlx14FLR","d7vjMkZANm","faHirX6Pin","atef2L7cGc","fLNg8FGzgp","HzZT8zY1GY","55rfBDQimp","M6qcGaFFss","l83UdS2Dfu",
-"7hyVvMGlTF","faHir0BmCy","5nmWvb29RJ","gIYvEU3yw5","dpe1vQbxXc","GrDg7xReec","W7cTsOUYuF","IRh48BpYhV","FNYIMCdyBV","x3LDeJJs5m",
-"tjQxsBFkb8","OxWIHRmDcr","blLA9uJScX","29QAzoVQp6","QnJ1So8Uyd","he9IAuN6r3","UmaEvtvdkD","PYBf4DcpWB","OxWIHpmeCd","45cIH1j5L8",
-"pWiOsjS1aj","8xEKzlpF6W","qaofNaDGtS","nlaByJkzUn","FFDuivkCHH","FxX9qix74r","2hEEUtjQxs","24ARF8U2nU","SbRYyhUTw7","Ul4a16AFT0",
-"lpF6WNOHsz","JKWYRfFDrJ","iqv4kBCxeC","hi5X7Mkgy8","xXTI45iGN5","S77LH9y4lw","ZJTXHGSQwj","zz4ZUOUqFM","Waim6rhl0J","64s8N7lUXZ",
-"UmaEv2ZHdk","zHF1qTa8f6","cQOnvlsQGo","MmsIoECMvU","lXFOB0Kyfs","45cIHSmGzv","S77LHzY1GY","ydG8Uuvf7A","0YAGHpvgjS","JJs5mlH1kt",
-"qaofNlH1kt","QworujSjS3","uvf7AMezSW","guMb8DLhzM","y94nw1LB1L","bgJAzPYBf4","7hyVv5IhmG","8RCUAP6bcg","ulk41WmadA","ksJbyvkCHH",
-"RACujlViBv","JRJQBNAFuw","d85a9Twano","7ku1pWmadA","Yf2EcKsjRK","bZLvShE1Ql","aDGtSjiVBP","AgJHQiKqhr","48cHLLDk6f","jfREuIjTwP",
-"UmaEvfFDrJ","9eoRcIn3NS","ThjNnCdyBV","Mm8siJ2mQi","AOgEe7ku1p","DcpWBzqH0W","bgJAzGXdoH","6q6L9EoToP","HRxd8gdQsS","zHF1qJJs5m",
-"JJs5m48cHL","3weIFOz8yZ","v2eC3UmaEv","ReKEWzQt6Q","QworuwiHrZ","DLhzMHfyNQ","AIYUuS77LH","SWfoujtn0X","RzaZA2Yz7E","7ku1p2ZHdk",
-"l83UdUl4a1","cShY22TRI7","W3VFHpFrrl","Rxrsms4786","55rfBFhtgl","8U2nUjzUqR","5Drn0VBjhz","atef2i7WMQ","uAWypUmaEv","ulk418TxD7",
-"lViBv5IhmG","XflUqDz1R3","48cHLsqVrf","FLsphZzJHW","JJs5m2DREs","xReecMezSW","LewvMeuZA5","uPX7GNxx9V","5ZaEzgdQsS","fFDrJQClRL",
-"cShY2L7cGc","SbRYyYf2Ec","JJs5mlXFOB","m4bxUciuWz","IRh489y4lw","taOXK5iGN5","dQ586ZJTXH","ReKEWlj07Q","rz7UtIKxdL","hi5X7he9IA",
-"lViBviqv4k","t59lRzHF1q","JJs5moQ87r","CqqaDD6rBy","4QMc9VLTy6","oGu6xEoToP","zY1GY5iGN5","HzZT81j5L8","G1RhSnlaBy","VBjhzOxWIH",
-"EdBKcZv7z0","FGzgpuZPqg","aFFssKASQ8","GrDg7ydG8U","ZUnqt7X3uy","fqypyEOE1o","X6PinB3qem","ReKEWydG8U","4QMc9zbIYY","O3iyQIRh48",
-"0PktIAkKTk","ZUnqtWaWsv","9iGoTSbRYy","0PktIyToGW","AmdQdxReec","Ss0Zu9rlg9","0Kyfsv2eC3","SbRYyIRh48","JIqXilweGy","B3qemNxx9V",
-"t59lRJRJQB","oVQp6soy9t","K20wKRsQUq","CNHmvuN6r3","a00b52Yz7E","IRh484dEz6","MGlTFbgJAz","FPfSE2hEEU","JRJQBuAWyp","o8UydU3yw5",
-"MmsIohi5X7","MaJQs9y4lw","zqH0WvOqCE","3otm6he9IA","TCgPpxReec","XflUqiKqhr","Yf2EcogLgc","uJScXh1zcH","Yh1hFQWxoT","lH1ktAIYUu",
-"l83UdzbIYY","Dz1R3SWfou","n8pJ9jiVBP","Z4I1vydG8U","UlU3Ml83Ud","ni2v16q6L9","DG4sTpiJSk","yvOMIRpBQm","7lUXZ5Mg9r","iwzGkGrDg7",
-"IRh48oVQp6","Mm8siSjskQ","64s8Nix74r","Oz8yZuQIcz","P6bcgQYxC0","HRxd848cHL","tjQxss93Ml","lsQGoFLsph","jfREuzHF1q","s93Ml7lUXZ",
-"F6PT2SjskQ","QYxC0sx5Gl","QssNCCxVEf","55rfBZzJHW","suY4xbgJAz","9eoRcHlUbF","DG4sTkB5nP","Ss0ZuDz1R3","ReKEWdmoS7","7fKYU580YD",
-"9XyT9uPX7G","45cIHcmXIX","2hEEUZJTXH","5Mg9r7lUXZ","dQ586FnPFB","hi5X7hSSvQ","8FmFH7lUXZ","n8pJ98cVD3","I7p2aI7p2a","5Mg9rsqVrf",
-"2NslmnlaBy","guMb8IRh48","WMiS3QnJ1S","TCgPpBCxeC","jfREuxciqp","Yf2Ec7lUXZ","i3pyd7fKYU","lpF6Whi5X7","MojnPulk41","9rlg9uupzk",
-"Zv7z0In3NS","Dz1R37fKYU","CxVEfuTacx","AkKTkaFFss","fqypyUlU3M","uvf7AYf2Ec","v1HlnlweGy","gtCA5AmdQd","FnPFBJJs5m","MGlTFJkzUn",
-"EOE1oMmsIo","Mkgy8jSjS3","wiHrZaFFss","BpYhVF6PT2","djsrvyvOMI","7Ow5Cgf8rI","IRh48ulk41","pFrrlEOE1o","HRxd8lsQGo","2NslmvLsmS",
-"Vprf2kZANm","jiVBPW7cTs","S77LHhE1Ql","8FmFHB3qem","taOXKjSjS3","0ao3lNOHsz","oQ87r0Kyfs","Vprf2sqVrf","QbxXcDQimp","XyPZN5VZjS",
-"dQ586aDGtS","HfyNQWMiS3","UmaEvRpBQm","pv0i7LbRTH","5iGN5VNCPd","YOfrYCNHmv","piJSkcShY2","ni2v1YOfrY","X6PinxXTI4","MaJQsRkQke",
-"zqH0WQYxC0","iqv4khSSvQ","euZA5JkzUn","6AFT014FLR","B3qem1LB1L","Dz1R3wiHrZ","aDGtS9rlg9","ZJTXHPb1pa","JJs5mU3yw5","AgJHQgdQsS",
-"zz4ZUlkMUA","iKqhrGrDg7","HRxd8CK5W7","HRxd8s93Ml","FPfSEQssNC","yToGWtl72W","RzaZAVNCPd","GrDg7VLTy6","faHirlCMxy","5Mg9ry94nw",
-"tAOsrCqqaD","PYBf4FNYIM","VNCPdnFqik","C2IrcfcJOy","1v5hHAmdQd","soy9tAkKTk","Nxx9VEoToP","0PktI29QAz","tjQxsmz8gx","bZLvSRxrsm",
-"Yw2oUNAFuw","n1pmOX6Pin","O3iyQv8yFN","lCMxyhi5X7","14FLR5nmWv","yToGW4W0Tl","euZA5wDajX","uZPqgFGzgp","XyPZNIRh48","Mm8siEOE1o",
-"lm0pDO3iyQ","POUYSD6rBy","DLhzMBbwgA","rz7UtIjTwP","ZhwG1mz8gx","uAWypn1pmO","0Wr5yn1pmO","SWfouSWfou","b29RJQnJ1S","jS1ajd85a9",
-"FnPFBFjHXR","iwzGkCp3mZ","xciqpoGu6x","BbwgAFwEJz","uoStwpAhR1","ulk41o8Uyd","BGaQYwDajX","pT8wuix74r","618Di9GXkX","sx5GlZ4I1v",
-"YOfrYNAFuw","t59lRP6bcg","t59lR48cHL","QWxoTyToGW","aL6AJlViBv","atef22Yz7E","AkKTkksJby","lm0pDxReec","dmoS74QMc9","zqH0W6q6L9",
-"SbRYyVLTy6","B3qemBFkb8","6AFT0lH1kt","soy9tJJs5m","GrDg7Pb1pa","iwzGkyToGW","7lUXZMezSW","dmoS7AIYUu","LbRTHY1mC0","FLsphiqv4k",
-"uN6r3fcwDa","2TRI7RmDcr","l83Udni2v1","lXFOBrKDLJ","v1HlnSWfou","jeskSru4UG","FPfSEtl72W","VIlwP8U2nU","JKWYRcShY2","d85a9IBe8k",
-"ciuWzDLhzM","CqqaDMK07Y","d7vjMzFgtB","6AFT0WmadA","vkCHHEoToP","Ss0ZuDLhzM","3otm6qaofN","CK5W7AOgEe","WaWsvhe9IA","Mm8siRkQke",
-"d85a90MR5X","G1RhSDG4sT","0h1b1FGzgp","F6PT2GrDg7","rz7UtF6PT2","jeskSHlUbF","WDVWJS77LH","WDVWJQ6hMC","qUJMdnFqik","zqH0WIjTwP",
-"ydG8UfcwDa","2NslmgdQsS","xciqpiKqhr","TwanolweGy","6q6L9Dz1R3","4W0Tla00b5","BGaQYksJby","kZANmyofH3","i3pyd24ARF","EOE1ojtn0X",
-"45cIHIjTwP","Waim6Oz8yZ","RACujRkQke","K20wKMojnP","oQ87r5ZaEz","0Wr5yvOqCE","RxrsmKr8ys","zbIYYThjNn","7Ow5CPOUYS","BbwgAFjHXR",
-"9y4lwgf8rI","y94nwt59lR","Kr8ysjeskS","ZhwG1MojnP","0h1b12TRI7","X6PinfLNg8","Mm8siulk41","v2eC30PktI","8xEKzru4UG","M6qcGaez9y",
-"QChxsHfyNQ","AOgEexciqp","FGzgpQ6Lix","tlILtYf2Ec","QChxs64s8N","EdBKcdmoS7","ksJbyJ2mQi","zmLYD5Drn0","IKxdLM3zXL","gtCA5mz8gx",
-"xReec7fKYU","iwzGkFnPFB","PYBf4hUTw7","y94nwaFFss","v1HlnEoToP","RsQUq3otm6","1v5hHvLsmS","D6rByb29RJ","YOfrYAkKTk","07n1cfqypy",
-"WDVWJStlDJ","ZhwG1Zv7z0","i3pydlViBv","OHaBzQnJ1S","WreyPrz7Ut","S2DfugdQsS","Ta8f6m4bxU","AXpwEfFDrJ","W7cTspWiOs","n8pJ92DREs",
-"OxWIHXflUq","qQxHP8xEKz","VNCPdFGzgp","n1pmO0MR5X","M6qcGZzJHW","Kr8ys7fsYM","wiHrZChuy3","Y1mC0GSQwj","AkKTktl72W","dQ586euZA5",
-"lj07Q1v5hH","pv0i7NhXdu","MojnPl83Ud","k85AeTa8f6","uAWypAOgEe","45cIHThjNn","TwanosqVrf","DcpWBD6rBy","ydG8UI7p2a","5VZjSsx5Gl",
-"ZzJHWiKqhr","atef2DQimp","WMiS3aDGtS","J2mQizY1GY","tjQxsF6PT2","uoStwIn3NS","580YDMK07Y","WaWsvyToGW","uLtKsZhwG1","CNHmvdQ586",
-"AkKTk5IhmG","16lHcF6PT2","yToGWfFDrJ","BFkb8uPX7G","29QAzxXTI4","SWfouNcICA","0h1b1hUTw7","sqVrfyEfy9","Pb1pa5ZaEz","5Drn0O3iyQ",
-"RkQkepT8wu","VLTy6ksJby","9GXkX8U2nU","K20wKNhXdu","aez9yYw2oU","Dz1R3jS1aj","lsQGolXFOB","FwEJzuN6r3","5NammuoStw","VBjhzkB5nP",
-"uN6r3CIShG","lH1ktzFgtB","2NslmiKqhr","hSSvQcmXIX","ni2v10Wr5y","RpBQmQYxC0","nFqikxXTI4","t59lRkZANm","Chuy3t98iW","Nxx9VCIShG",
-"aL6AJzFgtB","OUqFMoVQp6","OxWIHmX2GE","ZhwG129QAz","ZJTXHRpBQm","TXQ0Zd7vjM","gf8rI8RCUA","16lHcvOqCE","3otm6lweGy","0BmCyFjHXR",
-"UmaEvW7cTs","pWiOsWmadA","RxrsmzQt6Q","s7MxklsQGo","FVMxogtCA5","9XyT9uAWyp","pvgjSazIWp","TCgPpCIShG","pvgjSd7vjM","QClRL0ao3l",
-"rKDLJlH1kt","i7WMQ4W0Tl","bgJAzF6PT2","yluBxDcpWB","zQt6Q2Yz7E","VjCZqt59lR","zFgtB8FmFH","HP433QChxs","bZLvSGrDg7","uJScXdQ586",
-"jzUqRKZamH","FwEJzPOUYS","qQxHPyToGW","sqVrf8TxD7","MojnP9XyT9","RACujoQ87r","uoStw9XyT9","s47863otm6","5nmWvPb1pa","lweGyhe9IA",
-"55rfBpiJSk","YOfrYAXpwE","Y1mC0VerEA","hUTw7iKqhr","LbRTHTCgPp","7X3uyuJScX","DQimpDz1R3","lsQGohSSvQ","fcwDaGSQwj","WDVWJcL0aE",
-"KZamHRACuj","a00b5lH1kt","Vprf2tl72W","LDk6fSbRYy","hE1QldhSuH","t59lRhE1Ql","0ao3lazIWp","lH1ktblLA9","VjCZqwiHrZ","4W0Tl3otm6",
-"4W0TlVerEA","JIqXilj07Q","zqH0WCNHmv","KZamHZv7z0","5drc6P6bcg","aFFssuZPqg","hUTw7pWiOs","yToGWpvgjS","cQOnvJJs5m","7ku1pfaHir",
-"5Mg9r16lHc","3otm6S77LH","Mm8sibZLvS","tvdkDWDVWJ","TCgPpcShY2","Mkgy8uAWyp","W7cTsQ6Lix","tuDySK20wK","sx5GlCxVEf","v2eC3pAhR1",
-"d85a9JKWYR","5IhmGDcpWB","fcwDaTwano","Yh1hFnlaBy","8hJdtWmadA","Qworu618Di","uvf7ABGaQY","0h1b1lH1kt","TwanojfREu","lm0pDJRJQB",
-"OxWIHiqv4k","xciqpcmXIX","iqv4kFwEJz","x3LDev8yFN","tvdkDt59lR","0PktIKZamH","tjQxsNxx9V","5nmWvQ6hMC","D6rBytvdkD","IBe8kM3zXL",
-"o8UydBbwgA","F6PT2lpF6W","K4GS8jSjS3","5nmWvP6bcg","euZA5OUYuF","cL0aEC2Irc","QbxXcDLhzM","FwEJz07n1c","0MR5XLDk6f","qQxHPprNT6",
-"9iGoTNAFuw","VBjhzVBjhz","NOHszcmXIX","aDGtSbgJAz","GSQwjzQt6Q","SWfouNo0Qb","wDajXVprf2","OUqFMdQ586","faHirru4UG","uAWypRkQke",
-"zFgtBpAhR1","7lUXZ55rfB","8TxD7QbxXc","Dz1R3Fhtgl","x3LDed85a9","DLhzMFGzgp","55rfBdjsrv","7fKYUVNCPd","nFqikuQIcz","rz7UtnFqik",
-"h1zcHydG8U","yvOMIzbIYY","M6qcGXyPZN","uLtKsqUJMd","oQ87rlj07Q","hYBCKL7cGc","BCxeChe9IA","EoToPqaofN","i3pydFVMxo","WaWsvpvgjS",
-"POUYSuJScX","OxWIHprNT6","i3pydG1RhS","D6rByuTacx","tvdkDhSSvQ","FnPFBlH1kt","y94nwJKWYR","Ta8f655rfB","jtn0XZJTXH","IBe8ktaOXK",
-"prNT6NhXdu","iqv4kuTacx","o8UydpFrrl","P6bcgFPfSE","uoStwuvf7A","Mm8si3otm6","QnJ1SgjUTu","qaofN0PktI","hYBCKfcwDa","FFDuiYf2Ec",
-"64s8NChuy3","sqVrfsoy9t","gIYvEpmeCd","uPX7GbgJAz","POUYShYBCK","TCgPpLDk6f","HlUbFciuWz","IBe8kJJs5m","Uvlv4pT8wu","MojnPydG8U",
-"zQt6Q0BmCy","MmKGJkB5nP","OUqFM55rfB","8cVD3HRxd8","7Ow5CC2Irc","Yw2oUjeskS","aL6AJOxWIH","LDk6fqaofN","pmeCdCdyBV","QWxoTC2Irc",
-"ZJTXH3weIF","BbwgA5Namm","a00b5BGaQY","1v5hHQ6hMC","EOE1os93Ml","55rfBAOgEe","VNCPds7Mxk","9y4lwwiHrZ","kB5nPRkQke","Mm8siaez9y",
-"ZuDtDGSQwj","LewvMm4bxU","sqVrfuN6r3","GSQwjThjNn","fcwDaUmaEv","9GXkXlj07Q","yofH3pFrrl","yofH37lUXZ","Rxrsm7lUXZ","cQOnvlweGy",
-"okgRi16lHc","QworugjUTu","QChxsVLTy6","suY4xfcwDa","ogLgc2hEEU","3otm67lUXZ","zFgtBNAFuw","9XyT9KASQ8","gjUTucmXIX","YjB9tt59lR",
-"Yw2oUpv0i7","VNCPd8U2nU","AXpwEVBjhz","RpBQmyEfy9","Q6hMCS2Dfu","ZzJHWZuDtD","I7p2a7hyVv","gIYvEJIqXi","B3qemhSSvQ","ZuDtDK20wK",
-"MmsIoVjCZq","HzZT8xReec","he9IA0ao3l","K4GS8L7cGc","580YD29QAz","HfyNQpFrrl","QworuogLgc","BpYhV2hEEU","guMb8gIYvE","AkKTkpWiOs",
-"CK5W7FLsph","PYBf4qaofN","LewvMoQ87r","JkzUnpiJSk","MmKGJazIWp","fcJOySjskQ","v8yFNUlU3M","Ta8f6y94nw","9y4lwnFqik","jeskSy94nw",
-"EOE1oNo0Qb","qaofNKZamH","k85AeY1mC0","FVMxo9GXkX","CK5W7gtCA5","fcJOyHzZT8","8RCUAAgJHQ","dpe1v618Di","64s8NS2Dfu","M6qcGlj07Q",
-"C2IrcRzaZA","QbxXcKASQ8","RmDcrQssNC","BCxeCi7WMQ","HlUbFJIqXi","NhXduhe9IA","yluBxoVQp6","cmXIXZ4I1v","pFrrlcL0aE","I7p2axReec",
-"tlILtyofH3","qaofNvOqCE","cShY2JRJQB","lm0pDWaWsv","uupzkQworu","m4bxUD6rBy","wDajXYf2Ec","AmdQdKsjRK","FwEJz3weIF","prNT6EOE1o",
-"IKxdLd85a9","Ul4a1Yf2Ec","7fsYMmX2GE","W3VFHWPmlx","UlU3M0Kyfs","RACujVLTy6","8cVD3ogLgc","ru4UGAOgEe","Cp3mZi3pyd","FPfSEVBjhz",
-"iqv4ko8Uyd","HzZT89XyT9","AkKTk4QMc9","VNCPdfaHir","Nxx9VNOHsz","4dEz6tAOsr","RkQkezqH0W","pvgjSFnPFB","0BmCyMojnP","Vprf2HlUbF",
-"gIYvEguMb8","VerEAm4bxU","KZamHDLhzM","JkzUnZhwG1","wiHrZuPX7G","lXFOBkB5nP","XflUq16lHc","5ZaEz2ZHdk","vkCHH1v5hH","0YAGHQ6hMC",
-"ru4UGHfyNQ","BCxeCUmaEv","3weIFcmXIX","RxrsmuLtKs","brhlQBGaQY","rz7UtuTacx","1LB1LEdBKc","YOfrYCqqaD","ThjNnguMb8","lsQGoHRxd8",
-"n8pJ9uoStw","KsjRKWreyP","Gv3Fq6q6L9","rz7UtRACuj","mX2GEHlUbF","EOE1oXyPZN","hYBCKQChxs","DG4sTprNT6","rKDLJOHaBz","fcwDanlaBy",
-"iB08lpFrrl","cShY2vkCHH","bZLvShe9IA","VNCPdFLsph","K20wKqUJMd","lm0pDIn3NS","d7vjMs4786","LbRTHaFFss","jSjS3blLA9","i7WMQv1Hln",
-"48cHLJJs5m","yluBxd7vjM","lViBvi3pyd","s4786FNYIM","F6PT2C2Irc","AkKTkRmDcr","uAWypQssNC","WMiS3FGzgp","nFqikFnPFB","IBe8kGWqqX",
-"RzaZAkZANm","zbIYYVNCPd","iwzGkulk41","uN6r3ECMvU","WmadAUl4a1","uAWyppiJSk","MaJQsgjUTu","7X3uyNAFuw","8hJdtHlUbF","tl72W5VZjS",
-"RxrsmbgJAz","XflUqQChxs","D6rByIjTwP","lXFOB8hJdt","KZamHYw2oU","HP433uJScX","Cp3mZ1v5hH","U3yw5JKWYR","nnP8oRpBQm","ydG8UtaOXK",
-"2ZHdkK4GS8","xciqpzHF1q","OUYuFMmKGJ","B3qemGrDg7","zbIYYVerEA","LewvMFwEJz","uTacxCdyBV","ksJbyblLA9","iqv4kuN6r3","FVMxorKDLJ",
-"K4GS8NcICA","d85a955rfB","suY4xfcJOy","yluBxAmdQd","atef2pFrrl","ni2v1dpe1v","zz4ZUW7cTs","Ss0ZuMmsIo","0KyfsSbRYy","azIWpIn3NS",
-"oQ87rP6bcg","pvgjSJJs5m","DG4sT5ZaEz","xciqpulk41","ZzJHWThjNn","s93Ml2Nslm","s7MxkvkCHH","TXQ0ZGXdoH","AOgEezz4ZU","FcWrW2Yz7E",
-"ReKEWVIlwP","RsQUqQClRL","vLsmSs93Ml","dQ586Yh1hF","bgJAzqaofN","2ZHdkpAhR1","vkCHHuQIcz","lXFOBxXTI4","ksJbyEdBKc","Dz1R3DG4sT",
-"RBhp0gjUTu","ni2v1bZLvS","fcwDaFGzgp","MK07YyEfy9","RBhp0IRh48","uPX7GQnJ1S","vkCHHM6qcG","guMb829QAz","DQimpuLtKs","BFkb8QssNC",
-"lpF6WWPmlx","xciqpaez9y","kZANmvOqCE","lViBvuTacx","qUJMdQYxC0","MojnPJJs5m","SbRYy0Wr5y","9eoRczmLYD","MmKGJ4W0Tl","iwzGk5nmWv",
-"RACujx3LDe","D6rBysqVrf","uQIczkZANm","fcwDaRmDcr","tAOsrzbIYY","QWxoT3weIF","t98iWFFDui","TCgPpDQimp","3otm6ru4UG","v1Hln8hJdt",
-"pWiOsyEfy9","faHir9iGoT","5IhmGQbxXc","RkQke0PktI","X6PinNAFuw","8xEKzSmGzv","ogLgcTwano","QClRLYOfrY","M6qcGGXdoH","vLsmSQbxXc",
-"Q6hMCcL0aE","9y4lwZhwG1","TCgPpjzUqR","SmGzvKASQ8","BGaQYMmsIo","ksJbyVLTy6","4dEz6nlaBy","piJSkTXQ0Z","EoToPEdBKc","lH1ktsqVrf",
-"suY4xvOqCE","6q6L9OHaBz","uvf7AUvlv4","K4GS8CxVEf","Cp3mZJKWYR","BCxeCJ2mQi","zFgtBJIqXi","m4bxUCdyBV","pAhR1ru4UG","0BmCyI7p2a",
-"Nxx9VtaOXK","zz4ZUWmadA","IjTwPgdQsS","FwEJzuPX7G","WDVWJTa8f6","Oz8yZ0YAGH","oVQp6tAOsr","cmXIXiB08l","FFDuiS2Dfu","ECMvU8cVD3",
-"wDajXRACuj","FVMxoru4UG","pAhR1BpYhV","JKWYRNAFuw","vOqCElkMUA","lkMUAYf2Ec","ydG8UaFFss","oVQp6uJScX","y94nwmz8gx","Yw2oUdmoS7",
-"uN6r3JkzUn","tjQxsmX2GE","580YDpWiOs","0Wr5yPYBf4","6AFT07fsYM","QbxXcfqypy","jiVBPJJs5m","blLA9sqVrf","1LB1Ls4786","9XyT9prNT6",
-"atef2s4786","rhl0JpWiOs","RsQUq6AFT0","tAOsruoStw","POUYSm4bxU","IKxdLx3LDe","ZzJHWFjHXR","4W0TlwiHrZ","GXdoHxXTI4","5iGN5Waim6",
-"OUqFMydG8U","Twano7lUXZ","BpYhVblLA9","a00b59y4lw","EoToPK4GS8","bgJAzU3yw5","ECMvUprNT6","Nxx9VFjHXR","ulk413weIF","FcWrWuTacx",
-"0h1b1Yf2Ec","pmeCdeuZA5","Vprf27ku1p","JkzUnvOqCE","618DiTa8f6","48cHLni2v1","AIYUuVNCPd","8RCUAOUqFM","djsrvaDGtS","tjQxsFVMxo",
-"BpYhVvLsmS","L7cGck85Ae","m4bxUi7WMQ","Yh1hFSjskQ","oQ87rydG8U","5NammvkCHH","PYBf4GWqqX","JKWYRPYBf4","lXFOBpAhR1","cL0aE9XyT9",
-"zqH0W4QMc9","ZuDtDQClRL","DG4sTaez9y","RkQkeG1RhS","fcwDauZPqg","s93MlqaofN","VIlwPU3yw5","4W0Tl1j5L8","EoToPXflUq","s93MlFjHXR",
-"YjB9tJRJQB","pvgjShE1Ql","kB5nPJkzUn","AkKTk6AFT0","OxWIHaL6AJ","vLsmScmXIX","uAWypfLNg8","CK5W7jfREu","Yf2EcbrhlQ","BbwgAaL6AJ",
-"S77LHVNCPd","SWfoufaHir","fcwDa4dEz6","pFrrlgIYvE","fmIK1yEfy9","FcWrWX6Pin","hUTw74dEz6","gtCA5tjQxs","fcwDaksJby","euZA51v5hH",
-"nlaBytlILt","8U2nUdhSuH","BCxeCjS1aj","K4GS8Yf2Ec","tvdkDhUTw7","hYBCK0YAGH","QChxs4W0Tl","pmeCdni2v1","AgJHQrKDLJ","ZhwG1NcICA",
-"4W0Tl4QMc9","Dz1R3M3zXL","WmadAVprf2","n1pmOx3LDe","Chuy3zY1GY","jzUqRKr8ys","Ta8f6i7WMQ","64s8NKsjRK","HzZT84dEz6","BFkb8MezSW",
-"ru4UGtlILt","9eoRct98iW","lkMUAG1RhS","GSQwjStlDJ","9iGoTXyPZN","Chuy36AFT0","EoToPkZANm","55rfBRmDcr","kB5nPuTacx","6q6L9IKxdL",
-"XflUqD6rBy","h1zcHChuy3","M3zXLaez9y","VNCPdtvdkD","NAFuwv8yFN","jiVBPYjB9t","EOE1otAOsr","fcJOyblLA9","0PktIIn3NS","uPX7Go8Uyd",
-"VBjhz5drc6","FNYIMPb1pa","VLTy62Nslm","MGlTF3weIF","ZUnqtpWiOs","X6Pin0Wr5y","pT8wuKZamH","TXQ0ZAIYUu","0BmCyVprf2","uAWyp7Ow5C",
-"FPfSE5VZjS","F6PT2ru4UG","B3qemwDajX","blLA9t59lR","5ZaEzQssNC","64s8NO3iyQ","zQt6Q9XyT9","FnPFB5ZaEz","9GXkXpv0i7","UmaEvjtn0X",
-"Q6hMCX6Pin","jSjS3I7p2a","Cfgr3L7cGc","Ta8f6gIYvE","EoToPyofH3","ulk41FcWrW","lXFOB5ZaEz","B3qemPYBf4","TCgPp07n1c","9XyT9No0Qb",
-"6q6L9FPfSE","tjQxsazIWp","zFgtBWMiS3","SjskQQbxXc","b29RJRsQUq","jzUqRd7vjM","9XyT90Wr5y","M3zXL3otm6","MK07YBbwgA","JXljWoGu6x",
-"Cfgr3VjCZq","9eoRcQChxs","7fsYM8TxD7","xXTI4AIYUu","VBjhziwzGk","uoStwWMiS3","7X3uyZUnqt","ciuWzChuy3","hE1Qln1pmO","taOXKAXpwE",
-"JXljWChuy3","jtn0XOHaBz","oGu6xk85Ae","uPX7GU3yw5","MK07Y5Namm","uoStwJKWYR","pWiOsdpe1v","Dz1R3S2Dfu","CK5W7jeskS","dhSuHuTacx",
-"YjB9ttuDyS","J2mQi4W0Tl","Oz8yZRACuj","jiVBPFhtgl","d7vjMsx5Gl","tuDySXyPZN","Chuy3lViBv","FLsphrz7Ut","8U2nUprNT6","Q6hMCPb1pa",
-"ZuDtDlm0pD","gtCA5OUqFM","9XyT9YjB9t","JkzUn7ku1p","IjTwPZUnqt","7hyVvlm0pD","KZamHUmaEv","7Ow5C07n1c","JKWYRBbwgA","IRh48SmGzv",
-"tl72Whi5X7","G1RhSxReec","VLTy6azIWp","FxX9q1LB1L","VjCZqWmadA","5Drn0uLtKs","tlILtTwano","ni2v1n8pJ9","MezSWCqqaD","CIShGCqqaD",
-"vLsmSprNT6","2ZHdkQ6Lix","5Mg9roQ87r","KsjRKydG8U","fmIK1ReKEW","K20wK9y4lw","K4GS8hUTw7","7X3uyzHF1q","0ao3l8cVD3","sqVrfgdQsS",
-"FjHXRJKWYR","i7WMQK4GS8","K4GS89iGoT","gf8rIbrhlQ","uPX7GRxrsm","uZPqg4QMc9","rz7UtVLTy6","6AFT0P6bcg","pFrrlKr8ys","hYBCKe6e4z",
-"580YDGrDg7","lXFOByToGW","d85a98hJdt","XflUqK20wK","3weIFRzaZA","DLhzM0YAGH","dhSuHjSjS3","AOgEeCp3mZ","fcwDaDz1R3","KsjRKAkKTk",
-"0ao3l5ZaEz","bgJAzjfREu","i3pydHzZT8","0PktIWaim6","Yf2EcOz8yZ","WaWsvlH1kt","Pb1paX6Pin","rz7UtkB5nP","lm0pDpT8wu","taOXKuTacx",
-"DLhzM7X3uy","SWfou7fKYU","XyPZNJ2mQi","5Mg9rS2Dfu","UmaEvVerEA","hSSvQB3qem","s4786soy9t","qQxHPStlDJ","48cHLxXTI4","NhXdu9iGoT",
-"Gv3FqxXTI4","gdQsSqaofN","0h1b1faHir","5Nammix74r","bZLvSL7cGc","ni2v1fmIK1","fLNg8s7Mxk","FPfSEi7WMQ","vOqCEMmsIo","8RCUAIn3NS",
-"BFkb8KASQ8","XflUqIn3NS","kB5nPpWiOs","3weIFRxrsm","6AFT0jeskS","Ul4a1BbwgA","s478655rfB","OUYuF7ku1p","No0Qb9GXkX","e6e4z4W0Tl",
-"VLTy6wDajX","s4786jtn0X","zmLYDk85Ae","cShY2yluBx","5IhmG1j5L8","tAOsrwDajX","JXljW0YAGH","Uvlv4HRxd8","jeskSpAhR1","nlaBy6q6L9",
-"FcWrWs93Ml","VIlwPguMb8","Z4I1vBCxeC","KASQ8C2Irc","Waim6Qworu","n1pmOsoy9t","gf8rIvLsmS","MK07YFNYIM","8FmFHeuZA5","No0Qb5iGN5",
-"d7vjMsoy9t","Cfgr3atef2","WMiS3HzZT8","xciqpLDk6f","HlUbFI7p2a","W7cTsIBe8k","P6bcg2Nslm","DG4sTzHF1q","djsrvRACuj","StlDJhe9IA",
-"oQ87rwDajX","8FmFHsx5Gl","BCxeCFxX9q","HP433uLtKs","Chuy3Z4I1v","2hEEUIRh48","MezSWzFgtB","I7p2aFwEJz","RpBQmFPfSE","CdyBVIRh48",
-"5Nammzz4ZU","sqVrfJ2mQi","L7cGcuvf7A","P6bcguvf7A","oQ87r7Ow5C","vLsmS5Namm","pFrrlzbIYY","yluBxtlILt","AgJHQQChxs","yluBxY1mC0",
-"FLsphO3iyQ","yvOMI5nmWv","8RCUAuN6r3","tl72WjiVBP","lCMxyCIShG","jS1ajMGlTF","FVMxopWiOs","GWqqXQChxs","0MR5XYh1hF","MmKGJzFgtB",
-"48cHLOz8yZ","dhSuHGSQwj","BCxeCs4786","hSSvQzY1GY","Cp3mZO3iyQ","NAFuwuJScX","7hyVvWDVWJ","CdyBVFFDui","tjQxsKZamH","DLhzMbgJAz",
-"Cfgr3zHF1q","rz7UtYw2oU","StlDJJXljW","faHirVBjhz","RBhp0KASQ8","ydG8UBpYhV","0MR5XStlDJ","POUYSn8pJ9","580YDiwzGk","tvdkDTwano",
-"gtCA5iB08l","Oz8yZ8cVD3","hE1QllH1kt","y94nw55rfB","StlDJuZPqg","hE1QllsQGo","dpe1vRzaZA","FGzgptjQxs","W7cTsWaim6","dhSuHVIlwP",
-"ThjNn2DREs","JKWYRmz8gx","hE1Qld7vjM","zmLYDFcWrW","GrDg7taOXK","prNT6faHir","FhtglfcwDa","1j5L8BFkb8","29QAzLDk6f","YjB9tfaHir",
-"0PktIeuZA5","14FLRbrhlQ","QssNCThjNn","pFrrlbgJAz","h1zcH3otm6","Chuy3VerEA","gIYvEyEfy9","vOqCE618Di","dhSuHk85Ae","5iGN5YjB9t",
-"kZANm9eoRc","nFqikQworu","3otm6YOfrY","KASQ8UlU3M","POUYSpFrrl","QssNCfFDrJ","tlILtVjCZq","5ZaEzZzJHW","v8yFN16lHc","7X3uy4W0Tl",
-"lViBvDLhzM","Dz1R36q6L9","5iGN5Zv7z0","JXljWWaWsv","uN6r30MR5X","GXdoH5drc6","0ao3luZPqg","jfREuKsjRK","ZUnqtJ2mQi","y94nwP6bcg",
-"KsjRKQworu","Oz8yZhSSvQ","kB5nPFNYIM","aFFssnlaBy","AkKTkFnPFB","Ss0ZuU3yw5","FhtgldQ586","tvdkDFhtgl","QYxC045cIH","QbxXcSs0Zu",
-"uupzkVerEA","LbRTH5Mg9r","VjCZqVjCZq","O3iyQxXTI4","jeskSuoStw","XyPZNJkzUn","zqH0WjfREu","4QMc9JJs5m","jtn0X9XyT9","NhXdu5VZjS",
-"IRh488xEKz","m4bxUQYxC0","jtn0XX6Pin","lm0pD7hyVv","rz7UtQWxoT","5nmWv7hyVv","uupzkQYxC0","Rxrsmru4UG","Ss0ZuRACuj","dmoS7RACuj",
-"CK5W7ZzJHW","kB5nP07n1c","t98iWVjCZq","k85AeyofH3","euZA5qUJMd","JJs5mQnJ1S","16lHcJXljW","55rfBkZANm","i7WMQEoToP","KsjRKWmadA",
-"piJSkQssNC","0MR5XzbIYY","0PktI8TxD7","qQxHPVNCPd","8xEKzfFDrJ","DLhzMRzaZA","RkQkeKr8ys","JIqXifaHir","FPfSE07n1c","8TxD7hUTw7",
-"lkMUApiJSk","X6Pin8U2nU","XyPZNMmKGJ","ksJbySWfou","i3pydaez9y","Mkgy8sx5Gl","Z4I1vlweGy","16lHcnFqik","euZA58xEKz","64s8NcmXIX",
-"2DREsFxX9q","AXpwEOHaBz","AgJHQ2Nslm","yluBxpmeCd","8xEKzMaJQs","ksJbyguMb8","gtCA5FjHXR","t98iWJRJQB","GXdoHrhl0J","9eoRcF6PT2",
-"jeskSXyPZN","Y1mC0okgRi","zY1GY6q6L9","d7vjMMaJQs","t59lRogLgc","580YDFhtgl","UmaEvKsjRK","Cp3mZ618Di","nFqikuAWyp","uTacxzFgtB",
-"Chuy3WreyP","LewvMCNHmv","FwEJzWmadA","CK5W724ARF","DcpWBa00b5","No0QbRxrsm","0Kyfs3weIF","ThjNnReKEW","lH1ktLewvM","bgJAzkZANm",
-"iqv4kuJScX","yofH33weIF","In3NSS77LH","lj07QZJTXH","C2IrcQbxXc","a00b5FVMxo","0h1b1s4786","CNHmvgIYvE","TXQ0ZvLsmS","yluBxuZPqg",
-"Z4I1v2Nslm","zQt6QKr8ys","nFqikFNYIM","uN6r3lH1kt","yofH3FNYIM","wiHrZ7ku1p","okgRiaDGtS","1v5hHVerEA","ksJbypv0i7","aL6AJTwano",
-"DG4sTQ6Lix","v8yFNmz8gx","iB08lIKxdL","mX2GEuLtKs","ciuWzPYBf4","6q6L9K4GS8","LbRTHMm8si","ZhwG1iwzGk","pvgjSprNT6","CdyBV0YAGH",
-"uoStw8RCUA","Ss0ZuvkCHH","Ss0ZuQnJ1S","bZLvSgjUTu","BbwgAM6qcG","iwzGkECMvU","8hJdtX6Pin","lsQGoaez9y","bgJAzzFgtB","yvOMIJJs5m",
-"X6Pinpv0i7","IjTwP55rfB","s7MxkX6Pin","PYBf4X6Pin","VLTy6LDk6f","fLNg8lXFOB","uZPqgStlDJ","AIYUuNo0Qb","Yh1hFCp3mZ","tl72WFxX9q",
-"hi5X7UmaEv","ulk41s4786","lCMxyjfREu","B3qemMmsIo","nFqikpFrrl","nnP8oIRh48","5NammP6bcg","taOXKt98iW","wDajXQ6hMC","nnP8oWreyP",
-"U3yw5nFqik","kB5nPIBe8k","MezSWWmadA","s93MlTwano","dhSuHWPmlx","In3NScmXIX","4QMc9RzaZA","uTacxZuDtD","rKDLJQClRL","RzaZAgdQsS",
-"yEfy9bZLvS","BCxeCrKDLJ","l83UdcL0aE","8FmFHjzUqR","hE1Ql64s8N","b29RJfmIK1","1v5hHqUJMd","uN6r3ZJTXH","KsjRKuQIcz","1v5hHfqypy",
-"5ZaEzdQ586","nlaBybrhlQ","8xEKzgjUTu","cQOnvulk41","24ARF1v5hH","2DREsazIWp","2DREstjQxs","FGzgpxReec","DG4sTFwEJz","HzZT8uN6r3",
-"ogLgcCp3mZ","W7cTszY1GY","0BmCyzqH0W","BFkb8M6qcG","lViBvtlILt","WDVWJvOqCE","AOgEeQssNC","zY1GYaez9y","tlILtk85Ae","9y4lwStlDJ",
-"5ZaEz580YD","mz8gxsqVrf","GXdoH7lUXZ","EdBKc1v5hH","ReKEWHzZT8","aDGtSvOqCE","brhlQFPfSE","7X3uyb29RJ","4W0TlAOgEe","fFDrJh1zcH",
-"rKDLJGv3Fq","0BmCytl72W","s93Mld7vjM","i3pydJkzUn","FwEJzGv3Fq","1j5L8n1pmO","CdyBVFGzgp","EOE1ocQOnv","No0QbUvlv4","uPX7G8hJdt",
-"uupzk7fsYM","RkQkeuJScX","Uvlv48hJdt","jiVBPRxrsm","48cHLs4786","jzUqRuAWyp","24ARFrKDLJ","v2eC3In3NS","AkKTkMezSW","zQt6QThjNn",
-"ZuDtDbZLvS","okgRiOxWIH","s93MlQChxs","atef2nFqik","v2eC3AIYUu","uZPqgxciqp","h1zcHEdBKc","bZLvSC2Irc","o8Uyda00b5","0YAGHzqH0W",
-"Kr8ysd7vjM","cShY2n8pJ9","0BmCysqVrf","dhSuHRsQUq","TCgPpuTacx","POUYSDz1R3","jiVBPNxx9V","Cp3mZbgJAz","lj07QVBjhz","9XyT9n1pmO",
-"S77LH4QMc9","zbIYYtaOXK","BCxeC2DREs","WMiS3Pb1pa","mz8gxbrhlQ","pAhR1sx5Gl","fcJOydmoS7","KASQ84W0Tl","lpF6Wjtn0X","EoToPyEfy9",
-"S2DfuaDGtS","brhlQSs0Zu","gdQsSpWiOs","ZUnqtDLhzM","zbIYYCxVEf","8RCUAs4786","O3iyQdhSuH","ydG8UBFkb8","iB08liB08l","i7WMQlCMxy",
-"C2IrcQ6Lix","lH1ktkB5nP","ydG8URACuj","BbwgAb29RJ","BbwgA2Yz7E","MK07Yx3LDe","ksJbyl83Ud","NhXdu618Di","guMb8zbIYY","Ta8f6DcpWB",
-"580YDaez9y","W3VFHYjB9t","uvf7AX6Pin","CK5W7nnP8o","mz8gx7hyVv","VLTy6uLtKs","aDGtS5nmWv","8hJdts4786","29QAzyEfy9","HRxd8EdBKc",
-"5VZjSxReec","5iGN5i7WMQ","JRJQBNcICA","zmLYDY1mC0","D6rByFPfSE","Q6LixI7p2a","RBhp0uoStw","Q6LixuPX7G","fLNg8In3NS","ru4UGuoStw",
-"tl72WKASQ8","brhlQ8TxD7","GXdoHd7vjM","Y1mC0SjskQ","4QMc9hUTw7","cQOnvB3qem","AOgEelCMxy","yEfy95iGN5","TXQ0Zs4786","No0Qb9y4lw",
-"VerEAs7Mxk","I7p2ayvOMI","Zv7z0ZUnqt","okgRihe9IA","ogLgcG1RhS","uAWypIRh48","7Ow5C9eoRc","RsQUqVprf2","faHirh1zcH","wDajXFjHXR",
-"OUqFMlViBv","ogLgcn1pmO","d7vjMgf8rI","iB08l5Drn0","CNHmvQWxoT","IKxdLP6bcg","djsrvVerEA","XflUqpv0i7","e6e4zThjNn","yofH3uoStw",
-"Mkgy8Oz8yZ","aez9ydpe1v","xReeceuZA5","lkMUAuZPqg","uLtKs9iGoT","7lUXZJIqXi","zQt6QSs0Zu","sx5GlMGlTF","s93Mly94nw","CNHmvFjHXR",
-"9XyT9ksJby","618Dijtn0X","tAOsrgIYvE","S2Dfu2Nslm","uZPqgNcICA","Yh1hFjS1aj","Chuy3lCMxy","RzaZAG1RhS","4dEz6AkKTk","zHF1qReKEW",
-"pT8wu07n1c","LewvMyToGW","iKqhryToGW","uLtKsUl4a1","ReKEWv8yFN","KASQ8qUJMd","iB08l8cVD3","uN6r3WreyP","4dEz645cIH","lj07QCfgr3",
-"jzUqRbrhlQ","lweGyVLTy6","m4bxU9iGoT","OHaBz2Nslm","dQ586WaWsv","h1zcHyvOMI","JRJQBfaHir","JIqXiiqv4k","NOHszcShY2","t98iW07n1c",
-"VBjhzQworu","7hyVv5ZaEz","soy9tuoStw","RpBQmuJScX","Waim6J2mQi","okgRid7vjM","AmdQdQClRL","azIWpsqVrf","guMb85iGN5","0YAGHRpBQm",
-"FxX9q7lUXZ","IRh4864s8N","NAFuw7hyVv","S77LHLewvM","zbIYYQYxC0","blLA9FjHXR","SjskQSmGzv","jSjS3yluBx","iqv4kOUYuF","D6rByRmDcr",
-"7Ow5CYOfrY","JRJQBFnPFB","Q6hMCGXdoH","jeskShUTw7","uLtKsxciqp","zQt6QyToGW","No0QbZzJHW","JkzUn580YD","Kr8ysciuWz","uTacxt98iW",
-"cQOnvlj07Q","y94nw4QMc9","EdBKc9GXkX","9eoRc2TRI7","Yw2oU2DREs","uupzkVBjhz","qaofNbZLvS","O3iyQvOqCE","pvgjSRkQke","618Diiqv4k",
-"zQt6QgIYvE","y94nwguMb8","gdQsSuN6r3","Zv7z05ZaEz","FcWrW1v5hH","rhl0JS77LH","bgJAzix74r","MaJQsRxrsm","zY1GYMmsIo","Mkgy8v1Hln",
-"hi5X72Yz7E","FcWrWDLhzM","RmDcro8Uyd","zmLYDhi5X7","zHF1q0YAGH","X6PinsuY4x","dpe1vZzJHW","h1zcHCNHmv","ru4UGjS1aj","KASQ8Rxrsm",
-"wDajXjfREu","ECMvUlXFOB","MK07Y7lUXZ","zQt6QQssNC","KASQ89iGoT","TCgPpAXpwE","BGaQYzY1GY","8RCUAFhtgl","7lUXZOxWIH","sx5GljS1aj",
-"MGlTFFcWrW","K4GS8lXFOB","gdQsSMK07Y","8cVD3zmLYD","IRh48AgJHQ","fqypyM3zXL","ix74rRxrsm","VerEA0Wr5y","O3iyQh1zcH","VerEACfgr3",
-"VBjhzxReec","GXdoH2DREs","oGu6xl83Ud","CNHmvpvgjS","uTacxEdBKc","qQxHPVerEA","uN6r30Wr5y","8RCUABbwgA","Ss0Zu1v5hH","ThjNn55rfB",
-"dQ586uAWyp","OxWIHgIYvE","MmKGJWPmlx","ksJby0h1b1","lViBvuQIcz","O3iyQIn3NS","t59lRSs0Zu","mX2GEYw2oU","rKDLJQworu","rKDLJCdyBV",
-"jiVBPfcJOy","zz4ZUgf8rI","yToGWAmdQd","okgRikB5nP","0Wr5ytlILt","JkzUnBpYhV","qUJMdAkKTk","Vprf2aez9y","9y4lwEdBKc","lsQGoRACuj",
-"5drc6FcWrW","lsQGoiB08l","Mkgy8qUJMd","Q6Lix8xEKz","DcpWBs4786","cShY2uoStw","S2DfuCqqaD","zz4ZULewvM","tjQxs5Drn0","n8pJ95nmWv",
-"dmoS7WmadA","FGzgp2TRI7","P6bcglViBv","Yf2Ecv2eC3","CqqaDSWfou","d85a9gtCA5","5ZaEz55rfB","a00b5nFqik","aL6AJJIqXi","K20wKJ2mQi",
-"9iGoT1j5L8","gtCA50PktI","Oz8yZFwEJz","lH1ktgjUTu","ReKEWRsQUq","RACujFPfSE","EOE1oAXpwE","NhXduoGu6x","9y4lw0BmCy","IRh48FjHXR",
-"fcwDaSjskQ","xReecsx5Gl","iKqhr6q6L9","Oz8yZaDGtS","SjskQAXpwE","n8pJ9e6e4z","rhl0JjeskS","7lUXZ9GXkX","7hyVvjzUqR","jeskSjzUqR",
-"KASQ8TXQ0Z","Cp3mZGrDg7","hUTw7Yw2oU","uupzkCK5W7","45cIHhSSvQ","RACuj2ZHdk","IjTwP4W0Tl","M3zXLi7WMQ","2ZHdkYOfrY","BFkb8QClRL",
-"v1HlnZJTXH","lweGyyvOMI","580YD2hEEU","hE1QltuDyS","MaJQs2TRI7","v2eC3yofH3","BCxeCYh1hF","tl72WbrhlQ","tuDyS8xEKz","4dEz6vLsmS",
-"W3VFHOxWIH","OUYuFkB5nP","7fsYMGXdoH","Kr8ysd85a9","cmXIXzHF1q","pWiOsEOE1o","cL0aEv8yFN","SbRYyx3LDe","hUTw75Namm","FNYIMk85Ae",
-"mX2GE4QMc9","ZJTXHMkgy8","rhl0Jfqypy","uoStwQnJ1S","4QMc9I7p2a","U3yw5RpBQm","FFDuioQ87r","gdQsSoGu6x","GWqqX9eoRc","2NslmgIYvE",
-"CK5W7y94nw","ru4UGhUTw7","WreyPPOUYS","gIYvEvkCHH","X6PinydG8U","brhlQTwano","fqypyZ4I1v","lpF6WIjTwP","7fKYUdQ586","JIqXi07n1c",
-"mX2GE5Drn0","3otm648cHL","OUqFM2Nslm","QClRL0h1b1","a00b5dmoS7","Chuy3tl72W","HRxd8HzZT8","n1pmOpFrrl","Yw2oUo8Uyd","5ZaEzd7vjM",
-"tvdkDTa8f6","ZJTXHY1mC0","5ZaEzbgJAz","6q6L9FVMxo","AmdQd48cHL","fLNg8m4bxU","Nxx9VkZANm","EdBKciwzGk","GSQwjuupzk","d7vjMrz7Ut",
-"RpBQmlsQGo","StlDJpT8wu","Mm8si3weIF","jiVBPpiJSk","2Nslm2Yz7E","cmXIXiKqhr","RsQUqn1pmO","SWfoujfREu","KASQ8TCgPp","e6e4zdjsrv",
-"lkMUAVprf2","nnP8oMojnP","VBjhzb29RJ","QssNCS2Dfu","lj07QZhwG1","iB08lQworu","aL6AJU3yw5","piJSkWPmlx","o8Uyd14FLR","hi5X7Gv3Fq",
-"EdBKcUlU3M","6AFT0FVMxo","dhSuH8xEKz","GrDg7WMiS3","pv0i7FcWrW","IKxdLJXljW","uoStwjfREu","IjTwPlpF6W","07n1clj07Q","S77LHCIShG",
-"yvOMI8hJdt","CNHmvOHaBz","h1zcHd7vjM","B3qemWDVWJ","D6rByiKqhr","qQxHPaFFss","lCMxyGv3Fq","GSQwj4dEz6","IBe8ks93Ml","Q6hMCMaJQs",
-"0MR5XL7cGc","ni2v1jzUqR","AXpwEfqypy","HfyNQWDVWJ","1LB1L3otm6","Cp3mZpFrrl","DLhzMKASQ8","W3VFHRxrsm","DcpWBuTacx","BbwgAGXdoH",
-"5nmWvhUTw7","0BmCyXyPZN","0h1b1Fhtgl","cShY2qUJMd","CK5W7Mkgy8","MezSWjfREu","64s8NTXQ0Z","a00b59GXkX","AOgEejeskS","qUJMdOUqFM",
-"jSjS3gtCA5","uoStwpv0i7","580YDrKDLJ","PYBf4bZLvS","xReecEoToP","StlDJSbRYy","1j5L8J2mQi","EOE1oSWfou","pFrrl0Kyfs","NcICANhXdu",
-"EoToPAgJHQ","faHir0Kyfs","xReec9XyT9","7lUXZzqH0W","Oz8yZ6AFT0","5Drn0LDk6f","DQimpM6qcG","qQxHPNo0Qb","KASQ8NAFuw","uQIczFFDui",
-"5NammRsQUq","UlU3MM6qcG","GrDg7StlDJ","v2eC3nnP8o","KZamHWaim6","Yw2oUfaHir","fqypyMGlTF","D6rByjSjS3","8hJdt2DREs","SWfouGSQwj",
-"4QMc9PYBf4","CxVEfUmaEv","pWiOsUl4a1","O3iyQWaWsv","FnPFBVprf2","ECMvUZv7z0","LewvM0BmCy","fmIK148cHL","2TRI77ku1p","vOqCESmGzv",
-"FFDui7Ow5C","vkCHHMaJQs","mX2GEpiJSk","tl72WAgJHQ","dQ586K4GS8","iqv4klpF6W","2TRI7JkzUn","2hEEUtl72W","d7vjMSjskQ","uZPqgNAFuw",
-"VjCZq14FLR","O3iyQNxx9V","JkzUnNhXdu","ZuDtD8U2nU","5Mg9r1j5L8","W3VFHjeskS","t59lRDcpWB","FVMxocL0aE","LewvMpv0i7","ksJbySmGzv",
-"ksJbydhSuH","lm0pDx3LDe","XyPZNhYBCK","v2eC3sx5Gl","5VZjS64s8N","OUYuFuoStw","ogLgcUmaEv","RACujbgJAz","5iGN5okgRi","zbIYYzqH0W",
-"JKWYRo8Uyd","zFgtBwDajX","b29RJWDVWJ","Gv3FqFVMxo","HP433uZPqg","CK5W7he9IA","0YAGHSbRYy","taOXKSWfou","tl72WFLsph","S2DfuUvlv4",
-"0Kyfs14FLR","ogLgchUTw7","jeskSpWiOs","xciqp29QAz","J2mQiMm8si","CqqaDtaOXK","AmdQd1LB1L","2ZHdkC2Irc","SjskQKsjRK","2TRI7jfREu",
-"Oz8yZ64s8N","OHaBzAmdQd","pvgjSW3VFH","ZJTXHt98iW","9XyT9O3iyQ","CIShGYf2Ec","h1zcHSs0Zu","rhl0JHfyNQ","64s8NdQ586","Nxx9VNo0Qb",
-"aL6AJtjQxs","SbRYytlILt","OUYuFRBhp0","tvdkDn8pJ9","a00b5WaWsv","U3yw5GrDg7","rKDLJIBe8k","uLtKsIBe8k","fFDrJuZPqg","JkzUnQnJ1S",
-"FhtgliKqhr","RBhp0tjQxs","djsrvOxWIH","SbRYyuZPqg","vOqCEpiJSk","fmIK1mX2GE","t59lRtvdkD","GrDg7SbRYy","IRh48FGzgp","Waim6ru4UG",
-"ZhwG1JXljW","guMb8I7p2a","gIYvErKDLJ","yToGWK20wK","xXTI4iqv4k","djsrvS77LH","yluBxPYBf4","UlU3MQssNC","WreyPCIShG","Ss0Zub29RJ",
-"s93MlK4GS8","yluBxnlaBy","8FmFHaFFss","5drc6hE1Ql","soy9tb29RJ","WMiS3AmdQd","MaJQslCMxy","2TRI7ZhwG1","Gv3FqLDk6f","Waim6WaWsv",
-"2TRI7fcJOy","7X3uys7Mxk","xXTI40Wr5y","F6PT2I7p2a","8hJdtxReec","iKqhruAWyp","29QAzQnJ1S","HlUbFlpF6W","lCMxypvgjS","FxX9qiB08l",
-"jeskS7fKYU","vkCHHtjQxs","faHirBGaQY","48cHLYf2Ec","oQ87rJRJQB","TCgPp8xEKz","lCMxygtCA5","sx5Gl24ARF","i3pydydG8U","pFrrlNAFuw",
-"fmIK12Yz7E","n1pmOazIWp","5VZjSFwEJz","HRxd8yvOMI","5Mg9rMojnP","lweGyIjTwP","JKWYRtuDyS","8FmFHlj07Q","n8pJ9n1pmO","nnP8oZhwG1",
-"jeskSiwzGk","Gv3FqP6bcg","6AFT0Mkgy8","MK07YyToGW","hUTw7O3iyQ","fLNg8EOE1o","W3VFHM6qcG","aez9ydmoS7","fmIK19XyT9","BpYhV9iGoT",
-"OUqFMpT8wu","5Drn0uAWyp","prNT6jiVBP","07n1cOUqFM","VjCZqv8yFN","NcICAcQOnv","F6PT2Cp3mZ","OUYuFZhwG1","iqv4krKDLJ","XflUqatef2",
-"SmGzvyToGW","RsQUquAWyp","Cfgr37fsYM","8hJdt5Mg9r","xReeco8Uyd","fcJOyBpYhV","lm0pDStlDJ","FNYIMAgJHQ","P6bcggtCA5","yToGWpWiOs",
-"L7cGc0MR5X","9iGoT0Wr5y","t98iWs4786","Waim6i7WMQ","2Yz7Egf8rI","yEfy9DLhzM","Mm8sihe9IA","Cfgr3oQ87r","Y1mC02hEEU","Rxrsm580YD",
-"BCxeCNOHsz","HfyNQgtCA5","Y1mC0I7p2a","n1pmOjiVBP","JKWYRiB08l","RsQUqfcwDa","48cHLChuy3","QworuGSQwj","Z4I1vXflUq","07n1cuPX7G",
-"ni2v1LbRTH","rhl0JoGu6x","MojnP9y4lw","RzaZACK5W7","lViBvokgRi","MK07YVjCZq","guMb8M6qcG","G1RhSnFqik","cShY29rlg9","yofH3xXTI4",
-"tl72W5drc6","JRJQBOUYuF","JRJQBuPX7G","FnPFBzY1GY","BbwgAt59lR","pAhR14dEz6","xReecM3zXL","5IhmGsx5Gl","CNHmv7ku1p","7ku1pwiHrZ",
-"lXFOBiB08l","euZA5zY1GY","KsjRKVIlwP","aFFssjeskS","aL6AJIRh48","S2DfuEOE1o","GrDg77ku1p","B3qemThjNn","StlDJS77LH","pmeCdiKqhr",
-"fFDrJRmDcr","i7WMQkZANm","hYBCKtuDyS","oGu6xQWxoT","580YDStlDJ","x3LDe14FLR","Yh1hFjiVBP","lH1ktIKxdL","TwanoOUYuF","P6bcglsQGo",
-"2NslmPOUYS","9eoRcuTacx","Oz8yZbgJAz","uZPqgYw2oU","RsQUqQworu","djsrvChuy3","jS1ajjS1aj","CxVEfdpe1v","cmXIXChuy3","WPmlxKZamH",
-"Cp3mZpT8wu","Ul4a148cHL","lweGyLbRTH","5Drn0SWfou","uAWypDLhzM","FNYIMfcwDa","lkMUA0BmCy","lweGydjsrv","dpe1vBbwgA","NcICAOHaBz",
-"0h1b1DLhzM","GSQwjuLtKs","oQ87rgtCA5","CqqaDZzJHW","ZuDtDhi5X7","pvgjSJkzUn","IBe8kS77LH","uZPqgi7WMQ","EdBKcAIYUu","8FmFHk85Ae",
-"CqqaDhi5X7","Ul4a1h1zcH","FLsphVprf2","Ta8f6PYBf4","G1RhSK20wK","nnP8oGrDg7","2NslmFjHXR","zHF1qeuZA5","RBhp0jS1aj","fmIK1BFkb8",
-"fcwDa64s8N","64s8NuZPqg","pFrrlVBjhz","hi5X7ru4UG","FNYIMBpYhV","WreyPOHaBz","0Wr5ykB5nP","1j5L8zz4ZU","zqH0WYOfrY","ZuDtDWmadA",
-"BFkb81LB1L","OUqFM5Mg9r","2ZHdkDG4sT","OUqFM5IhmG","2NslmlkMUA","zHF1q5nmWv","OUqFMh1zcH","Yf2EcOHaBz","48cHLzY1GY","brhlQlsQGo",
-"K20wKCqqaD","oGu6x64s8N","8hJdtQ6hMC","a00b5aFFss","8hJdtd7vjM","7lUXZYh1hF","JRJQBvOqCE","he9IA7Ow5C","5ZaEzAXpwE","ix74rMm8si",
-"AmdQd8FmFH","l83Udmz8gx","VBjhz9iGoT","m4bxUFPfSE","L7cGcXflUq","piJSkI7p2a","G1RhSW7cTs","AOgEeoVQp6","5iGN5Dz1R3","oQ87rChuy3",
-"kZANmrKDLJ","14FLR0ao3l","ZuDtD7Ow5C","d7vjM5ZaEz","U3yw5jS1aj","gIYvE2TRI7","gdQsS7X3uy","qUJMdM3zXL","lH1ktB3qem","HlUbFC2Irc",
-"FcWrWYw2oU","blLA9xciqp","s7Mxk580YD","9GXkX2ZHdk","Dz1R3QYxC0","8xEKzEoToP","zbIYY7fKYU","NhXduFGzgp","KsjRKxReec","dpe1vfmIK1",
-"WmadAIn3NS","7hyVvjS1aj","OxWIHFFDui","Waim6GrDg7","aDGtSxXTI4","KsjRK1v5hH","4W0TlZJTXH","jzUqRL7cGc","GSQwjm4bxU","ZUnqt2Nslm",
-"RmDcr14FLR","pWiOsaez9y","0h1b1fcwDa","n8pJ96AFT0","JJs5mLewvM","48cHLJIqXi","S77LHuTacx","uPX7GEdBKc","s7MxkK4GS8","tuDySI7p2a",
-"OxWIHsqVrf","QnJ1SThjNn","9rlg9MojnP","1v5hHFFDui","hi5X79y4lw","Kr8yshE1Ql","J2mQiulk41","MGlTF4dEz6","No0QbBFkb8","QChxsMmKGJ",
-"t59lRi7WMQ","uvf7A24ARF","ksJby8TxD7","rz7UtpWiOs","cmXIX5Drn0","VIlwPuvf7A","piJSkQ6hMC","MGlTFuTacx","StlDJ55rfB","ZUnqtpmeCd",
-"oQ87rdQ586","LewvMTXQ0Z","mz8gxReKEW","Ss0ZuFxX9q","MaJQshYBCK","blLA9uvf7A","POUYS5Namm","tlILtCxVEf","WmadAhi5X7","ogLgcNOHsz",
-"pT8wuQ6Lix","hYBCKQnJ1S","KASQ8RsQUq","5IhmG7X3uy","uLtKsVLTy6","gdQsSydG8U","O3iyQUl4a1","euZA5lH1kt","jtn0XUl4a1","n1pmOyvOMI",
-"FLsphsuY4x","RkQkebZLvS","618Di3otm6","DQimpokgRi","OxWIHCNHmv","FFDui0Kyfs","nlaByNOHsz","ZuDtDd85a9","MaJQsJkzUn","uvf7AvOqCE",
-"CIShG55rfB","yToGW5VZjS","gjUTuyluBx","VNCPdCIShG","s7Mxk0BmCy","8cVD3WmadA","v8yFNo8Uyd","9iGoTKASQ8","Yh1hFDQimp","gdQsS5drc6",
-"WreyPfmIK1","POUYSFNYIM","JkzUn4W0Tl","v2eC3Twano","lj07QlH1kt","AOgEeqUJMd","bgJAzlXFOB","8RCUA8FmFH","FGzgpnlaBy","mz8gxFxX9q",
-"8TxD7uvf7A","8xEKzOUYuF","CK5W7MGlTF","9y4lwRBhp0","ni2v1ni2v1","oGu6x0ao3l","8xEKzi7WMQ","AkKTk0PktI","he9IAogLgc","zqH0WMGlTF",
-"07n1cHlUbF","atef2Mkgy8","618DiMK07Y","v2eC3fqypy","14FLR6AFT0","Q6hMCiqv4k","In3NS45cIH","LDk6fuN6r3","JJs5mHRxd8","bgJAzM6qcG",
-"dmoS7Z4I1v","Q6hMC2ZHdk","POUYSgtCA5","Cp3mZjiVBP","tjQxszbIYY","aez9yECMvU","uPX7GYjB9t","0MR5XOUYuF","MezSW4QMc9","zmLYDXflUq",
-"QYxC0LDk6f","rKDLJ7Ow5C","ogLgcWaim6","5iGN5lsQGo","ix74rBCxeC","QworuYOfrY","HfyNQtAOsr","lj07Qt59lR","v1HlnSmGzv","OxWIHW7cTs",
-"RkQke2DREs","I7p2a1LB1L","5NammNxx9V","oVQp6Mkgy8","Kr8ysiB08l","FGzgpO3iyQ","Yf2Ec8FmFH","8FmFH8TxD7","pWiOsMGlTF","LDk6fvkCHH",
-"i3pydThjNn","BGaQYKASQ8","yEfy95IhmG","VerEAKsjRK","FVMxoLewvM","xciqp8hJdt","2Nslmv1Hln","KASQ82Nslm","qQxHPvOqCE","5IhmGiB08l",
-"IBe8kxReec","K4GS81LB1L","s7MxkAOgEe","AgJHQAgJHQ","3weIFAOgEe","In3NSAmdQd","NhXdurz7Ut","pvgjSeuZA5","XflUqjSjS3","lm0pDWmadA",
-"MaJQsS2Dfu","QWxoTMojnP","Waim629QAz","HzZT8In3NS","s4786D6rBy","nlaBy9rlg9","2DREsQWxoT","16lHclweGy","ECMvU0PktI","Uvlv4FLsph",
-"CxVEfCdyBV","mz8gxDz1R3","8hJdt07n1c","XyPZNhUTw7","okgRizQt6Q","nnP8oF6PT2","WmadA48cHL","gtCA5ciuWz","y94nwZuDtD","CqqaDWmadA",
-"zY1GY0YAGH","mz8gxwiHrZ","POUYSWmadA","2hEEU0h1b1","5IhmGSmGzv","mz8gxgtCA5","VIlwPyofH3","MK07YLbRTH","o8UydMGlTF","ix74ra00b5",
-"ReKEWatef2","qaofNqaofN","oVQp6faHir","WPmlxCp3mZ","L7cGcbZLvS","zmLYD9GXkX","fLNg8mX2GE","uJScXuLtKs","2hEEUGXdoH","PYBf4yofH3",
-"StlDJXflUq","vkCHHOUYuF","fqypy7Ow5C","lm0pDCfgr3","FFDui55rfB","GXdoHMkgy8","v1HlncQOnv","gIYvEVprf2","zbIYYaFFss","Mkgy8KsjRK",
-"Yf2Eche9IA","AXpwEqQxHP","wDajXOUqFM","LDk6fW3VFH","G1RhSQWxoT","uZPqgOUYuF","618DiChuy3","dmoS73weIF","pvgjSiKqhr","SjskQpiJSk",
-"G1RhSM3zXL","Uvlv4U3yw5","yToGWbgJAz","IRh48QssNC","fcwDaHzZT8","VBjhzP6bcg","rhl0JIn3NS","IBe8koVQp6","Ss0ZuAkKTk","KsjRK5VZjS",
-"iqv4k5Namm","SmGzvn8pJ9","suY4x24ARF","CIShGQworu","JRJQBtvdkD","Uvlv4CK5W7","fcJOysoy9t","FhtglW3VFH","5ZaEz0Wr5y","B3qemSjskQ",
-"Gv3FqEdBKc","tlILtCdyBV","CxVEfvkCHH","nnP8oSWfou","K4GS8P6bcg","0KyfsgtCA5","ydG8UjeskS","t59lRaDGtS","zz4ZUZhwG1","9eoRc4W0Tl",
-"6AFT0uupzk","GWqqXyluBx","6q6L916lHc","vLsmSuLtKs","0BmCyeuZA5","S2Dfu8hJdt","XyPZNMK07Y","dhSuH5Drn0","ZJTXHS2Dfu","rz7Ut3otm6",
-"oQ87rY1mC0","aFFssAmdQd","i7WMQGXdoH","VNCPdCp3mZ","P6bcgB3qem","Oz8yZ0Wr5y","fLNg8i7WMQ","FwEJzxciqp","Ta8f6EOE1o","4QMc9oGu6x",
-"i3pydSWfou","VjCZqYjB9t","BFkb8aFFss","sx5Glrhl0J","FcWrWCdyBV","MojnPyluBx","zHF1qokgRi","zFgtBDQimp","OxWIHWPmlx","FhtglVprf2",
-"Oz8yZNhXdu","618Dix3LDe","AgJHQSjskQ","S77LHxReec","faHirzHF1q","I7p2aAkKTk","29QAz0YAGH","VBjhzdjsrv","C2IrcMezSW","FVMxoUvlv4",
-"fLNg8O3iyQ","6q6L9jzUqR","Ta8f6lj07Q","DcpWBwDajX","5nmWvgjUTu","IRh48pAhR1","KZamHsuY4x","Q6LixFjHXR","x3LDeCdyBV","iqv4kG1RhS",
-"iqv4kAOgEe","HlUbF48cHL","n1pmOvOqCE","Yh1hFZUnqt","8U2nUHfyNQ","zbIYYG1RhS","h1zcHpWiOs","FFDuicL0aE","aez9y5IhmG","uQIczatef2",
-"wDajXVjCZq","gf8rIjzUqR","5drc68TxD7","ciuWzHRxd8","x3LDepmeCd","5nmWviB08l","5iGN50MR5X","uvf7At98iW","5nmWvHRxd8","atef2hE1Ql",
-"GrDg7D6rBy","7Ow5CCp3mZ","azIWpm4bxU","5Namm5IhmG","MmKGJECMvU","xciqpe6e4z","i7WMQogLgc","ZzJHWKZamH","14FLRpvgjS","9y4lwYw2oU",
-"CNHmv29QAz","tlILtsx5Gl","taOXKeuZA5","618DiNo0Qb","JIqXiIRh48","Ta8f69rlg9","Uvlv4JJs5m","X6PinVNCPd","x3LDex3LDe","AOgEeOUqFM",
-"pv0i74W0Tl","faHircL0aE","NhXduI7p2a","pWiOsv8yFN","mX2GE2Yz7E","d85a9zz4ZU","7Ow5Cru4UG","7hyVv2TRI7","7ku1p45cIH","fqypyd85a9",
-"FcWrWOz8yZ","taOXKS77LH","RmDcr5IhmG","jeskS5Namm","Y1mC07ku1p","piJSk5IhmG","5iGN5QbxXc","In3NSXyPZN","QssNCOz8yZ","uPX7GWaWsv",
-"ThjNnCK5W7","ECMvUtl72W","m4bxUzmLYD","K20wKRpBQm","SjskQIKxdL","580YDmX2GE","QYxC0OUYuF","S77LHuN6r3","EdBKcL7cGc","7ku1pZzJHW",
-"fcwDaRxrsm","ZUnqthe9IA","zFgtBVerEA","FGzgpAIYUu","POUYSzqH0W","5ZaEzh1zcH","OUqFMQworu","Q6Lixx3LDe","2TRI7faHir","6AFT0dmoS7",
-"Cfgr3Cp3mZ","ru4UGTXQ0Z","Yw2oUB3qem","4W0Tl8U2nU","Gv3FqOHaBz","7hyVv8hJdt","dpe1vFwEJz","s93MlgIYvE","9GXkX7lUXZ","AkKTkJXljW",
-"ZuDtDSmGzv","0ao3lgtCA5","fmIK1gdQsS","EoToPSjskQ","5VZjSRpBQm","3weIFKZamH","8hJdt5nmWv","jSjS3RmDcr","tAOsrbZLvS","2Nslma00b5",
-"CdyBVnnP8o","D6rByrhl0J","0PktI9rlg9","uQIcz1v5hH","IjTwPpmeCd","JXljWaDGtS","7fsYMhi5X7","CxVEfm4bxU","MezSWBCxeC","soy9tQClRL",
-"M3zXLsx5Gl","J2mQilViBv","Dz1R3h1zcH","uvf7Aa00b5","aFFssRxrsm","WPmlxOUYuF","nnP8otlILt","tAOsryToGW","3weIFBbwgA","F6PT2Kr8ys",
-"sqVrf5Drn0","cQOnvfaHir","VjCZqTXQ0Z","hYBCKokgRi","h1zcHix74r","PYBf4QbxXc","DG4sT1j5L8","ogLgc5ZaEz","Y1mC02Yz7E","Yf2EcDG4sT",
-"Ss0Zu8xEKz","vOqCEZzJHW","2DREsokgRi","Ul4a1zmLYD","h1zcHjtn0X","GWqqX0Wr5y","2Yz7EdmoS7","rz7UtQnJ1S","Dz1R3qUJMd","Oz8yZVBjhz",
-"bgJAzFPfSE","JJs5mvOqCE","Cfgr3pFrrl","lXFOBNcICA","Kr8ysi3pyd","jS1ajFPfSE","yluBx4QMc9","NcICAlkMUA","dQ586QnJ1S","lXFOB1LB1L",
-"AXpwEJRJQB","5Mg9rYw2oU","ogLgcMezSW","L7cGclkMUA","zqH0WvLsmS","0h1b1aez9y","L7cGccmXIX","Zv7z0UlU3M","618DilpF6W","8cVD3FLsph",
-"pWiOssx5Gl","t98iWWaWsv","MojnPksJby","lj07QdmoS7","tuDySiqv4k","2Yz7EoQ87r","nlaBy0Kyfs","WaWsvazIWp","oQ87rb29RJ","djsrvNAFuw",
-"4dEz6U3yw5","7Ow5CEOE1o","OUqFMIRh48","W7cTsVLTy6","hSSvQTa8f6","UmaEvlj07Q","zqH0WQbxXc","Vprf2Fhtgl","BGaQY8U2nU","07n1cQworu",
-"FxX9qmX2GE","1v5hHNxx9V","WreyPl83Ud","4QMc9Twano","6q6L9XflUq","8cVD30YAGH","8xEKzReKEW","sqVrfoGu6x","fmIK1AXpwE","FjHXRBFkb8",
-"Cfgr3azIWp","IBe8k7lUXZ","vLsmSuvf7A","Zv7z0GSQwj","JJs5mAOgEe","K4GS88xEKz","IBe8kWaWsv","t59lR0Kyfs","fcJOykB5nP","UlU3MCIShG",
-"lXFOBd7vjM","ReKEWzmLYD","bZLvSxReec","G1RhSMaJQs","Mm8siS2Dfu","OUqFM4dEz6","yvOMIOxWIH","RpBQmd7vjM","guMb8ydG8U","OUYuF5ZaEz",
-"WMiS3y94nw","vOqCEIKxdL","0Wr5y580YD","14FLRYf2Ec","LbRTHtjQxs","QnJ1SlweGy","pv0i7FxX9q","8TxD7tvdkD","ulk41WPmlx","MaJQstAOsr",
-"RxrsmIBe8k","CxVEfjzUqR","TCgPpksJby","7lUXZS2Dfu","OHaBzxReec","yEfy9pmeCd","ciuWzyluBx","ThjNn0MR5X","JkzUnFPfSE","TCgPpCfgr3",
-"7Ow5ClViBv","0ao3lTXQ0Z","LbRTHuupzk","G1RhSksJby","TwanoM6qcG","0ao3liwzGk","2DREsaez9y","oVQp6euZA5","UmaEvZUnqt","YOfrY2ZHdk",
-"okgRiulk41","nlaByzmLYD","IKxdLqUJMd","FnPFBk85Ae","TCgPpZv7z0","azIWppmeCd","vkCHH9iGoT","zqH0WKsjRK","0h1b1fmIK1","qQxHP5Mg9r",
-"4dEz6qaofN","pmeCdpAhR1","uoStwW3VFH","aez9y618Di","lsQGoL7cGc","vkCHHn1pmO","JRJQBxXTI4","4dEz6LewvM","EOE1oVNCPd","nFqiksx5Gl",
-"BFkb8WmadA","7ku1pjfREu","Zv7z03otm6","9XyT9AOgEe","P6bcgsuY4x","RsQUqF6PT2","5Mg9rM3zXL","fcwDaRkQke","tvdkDFcWrW","5iGN5ulk41",
-"9iGoT55rfB","uQIczCdyBV","x3LDeZhwG1","oQ87ruAWyp","ReKEWS77LH","lH1ktgf8rI","Dz1R3FVMxo","gjUTunlaBy","EdBKc9eoRc","pvgjSEdBKc",
-"Pb1pacShY2","Q6hMCY1mC0","fcwDa7Ow5C","v2eC3fcJOy","wiHrZ2Nslm","2ZHdkbgJAz","n8pJ9ix74r","EdBKcUmaEv","fqypyzQt6Q","jS1ajBGaQY",
-"2ZHdkFFDui","uAWypQChxs","HRxd8Twano","yvOMIyofH3","v8yFNBpYhV","kZANmt59lR","VjCZqW7cTs","JIqXiEOE1o","MezSWU3yw5","lsQGoRxrsm",
-"FwEJzKZamH","RkQkeQWxoT","RsQUqsoy9t","zHF1qqaofN","29QAzfLNg8","KsjRKEdBKc","7X3uyO3iyQ","SmGzv9eoRc","580YDzHF1q","OxWIHTCgPp",
-"jS1ajhSSvQ","8U2nU5ZaEz","Q6hMCt98iW","ZuDtDEdBKc","prNT6SmGzv","SWfouLbRTH","7lUXZ0YAGH","U3yw5zHF1q","4QMc9OUYuF","FPfSEuJScX",
-"AkKTkUmaEv","WaWsv5VZjS","0PktIoVQp6","blLA9RzaZA","s93MlVIlwP","ZuDtDuTacx","n1pmODG4sT","gtCA5C2Irc","ZhwG1XflUq","wiHrZNhXdu",
-"5iGN5AIYUu","0KyfsCqqaD","ThjNnk85Ae","gdQsSQClRL","AgJHQ0Wr5y","5ZaEz64s8N","FxX9qs93Ml","lH1ktYOfrY","zqH0WjiVBP","cShY2y94nw",
-"ZJTXHCIShG","kB5nPzQt6Q","NAFuwRkQke","aL6AJCNHmv","rKDLJNo0Qb","n8pJ9jfREu","uTacxfmIK1","HfyNQcL0aE","VIlwP2DREs","4W0TlrKDLJ",
-"sqVrfHP433","azIWpRmDcr","7fKYUxciqp","lH1ktAmdQd","Oz8yZciuWz","JJs5mWMiS3","NhXdutl72W","RxrsmZuDtD","bgJAzuAWyp","pAhR1POUYS",
-"SmGzvFFDui","BbwgAoVQp6","RzaZAd85a9","JkzUn4dEz6","5VZjSGv3Fq","qaofN55rfB","IjTwPb29RJ","5nmWvjfREu","mX2GEmX2GE","JIqXiZuDtD",
-"VerEAjtn0X","vLsmSHRxd8","iB08lS2Dfu","pvgjSogLgc","4W0Tl9y4lw","Oz8yZTXQ0Z","AkKTkFcWrW","s4786HfyNQ","pvgjSHlUbF","FwEJzFPfSE",
-"v8yFN6AFT0","zbIYYP6bcg","7lUXZuPX7G","MK07YdQ586","gIYvEF6PT2","3weIFpiJSk","O3iyQcmXIX","aFFssaDGtS","580YDl83Ud","9GXkXyEfy9",
-"uN6r3iqv4k","RmDcrS77LH","s93MlfFDrJ","QClRLGWqqX","J2mQini2v1","GWqqXWMiS3","NAFuwsoy9t","0MR5XWPmlx","o8UydrKDLJ","xXTI4POUYS",
-"fcJOyyToGW","qQxHPCdyBV","FFDui64s8N","yofH31LB1L","SmGzvVjCZq","NAFuw07n1c","v1Hlnxciqp","JIqXiFFDui","AmdQdCp3mZ","CIShGdQ586",
-"RkQkeYOfrY","UmaEv8TxD7","Z4I1vGSQwj","ECMvUGSQwj","IRh489iGoT","uTacxZhwG1","7hyVv7hyVv","16lHcd85a9","uN6r3RACuj","AOgEelkMUA",
-"2ZHdk9y4lw","I7p2aazIWp","t59lR5Drn0","FVMxoBbwgA","MK07YciuWz","Oz8yZ8FmFH","kB5nPZUnqt","9iGoTZUnqt","pWiOsuvf7A","pv0i7MojnP",
-"BCxeCtuDyS","DcpWB5Drn0","TCgPpMezSW","dQ586sx5Gl","QClRLHRxd8","HzZT88TxD7","a00b52DREs","9y4lwru4UG","580YDhe9IA","0h1b1Oz8yZ",
-"Dz1R3hSSvQ","MaJQscQOnv","FnPFB0ao3l","s4786fcJOy","48cHLokgRi","1j5L8ksJby","ZUnqtZzJHW","cmXIXWaim6","Waim6fLNg8","UmaEvatef2",
-"MGlTFI7p2a","v2eC3aL6AJ","J2mQitAOsr","lCMxy618Di","uupzkFFDui","zY1GYS77LH","P6bcgZhwG1","bZLvSUl4a1","d7vjM0Wr5y","lweGyvkCHH",
-"FNYIMJIqXi","5VZjSokgRi","gf8rILDk6f","sqVrfrz7Ut","aDGtSuLtKs","MezSWJ2mQi","rKDLJVerEA","he9IA24ARF","blLA9d85a9","ZzJHW7fsYM",
-"Nxx9VMkgy8","ydG8UzQt6Q","M3zXLe6e4z","uJScXTXQ0Z","WreyPReKEW","9rlg9RmDcr","s4786AkKTk","4QMc9d7vjM","MGlTFJXljW","sx5GlDz1R3",
-"tjQxs5Mg9r","guMb8tl72W","PYBf4aL6AJ","3weIFGXdoH","s93MlC2Irc","hi5X7MK07Y","Ta8f6AIYUu","XyPZNM6qcG","6AFT0zY1GY","EOE1ov8yFN",
-"pFrrlx3LDe","In3NSCK5W7","2Yz7EThjNn","7Ow5CRzaZA","OxWIHcmXIX","580YDcShY2","AOgEev2eC3","m4bxU0ao3l","HfyNQ29QAz","JkzUnDcpWB",
-"gtCA5CqqaD","6AFT0yToGW","ix74rCdyBV","yToGWx3LDe","2NslmaFFss","O3iyQt98iW","64s8NfmIK1","9y4lwyToGW","64s8NK20wK","oQ87rfLNg8",
-"FcWrW0PktI","n8pJ9lpF6W","UlU3M8TxD7","5Drn0tlILt","kZANmgtCA5","FwEJzoGu6x","JkzUnRpBQm","24ARFtl72W","cShY28cVD3","SWfouzqH0W",
-"wDajX3weIF","RkQke8hJdt","DcpWBWaim6","X6PinbZLvS","jeskSaFFss","6AFT0bZLvS","yluBxDG4sT","2hEEUuTacx","RpBQmguMb8","Yw2oUaez9y",
-"RmDcrhYBCK","4QMc9NAFuw","cQOnvW3VFH","ni2v1v1Hln","OUYuFhe9IA","AIYUuLewvM","t98iWEdBKc","rz7UtlweGy","hE1QlAkKTk","7fKYUO3iyQ",
-"AXpwE07n1c","FLsphhe9IA","NOHszsuY4x","Waim6XflUq","JRJQBuTacx","he9IAnnP8o","zmLYDvLsmS","F6PT2CqqaD","U3yw55Drn0","CqqaDTXQ0Z",
-"ydG8UhSSvQ","Yf2Ecjtn0X","ThjNn5Mg9r","xReecrz7Ut","prNT6OHaBz","h1zcHi3pyd","2Yz7EIKxdL","yluBx5VZjS","K20wKix74r","nFqikksJby",
-"0BmCyCNHmv","XflUqSjskQ","cmXIXhUTw7","jtn0XWaWsv","YjB9tFLsph","HfyNQIKxdL","AIYUue6e4z","24ARF0ao3l","W7cTsjiVBP","4dEz6ciuWz",
-"KASQ8618Di","CK5W7cShY2","RsQUqyluBx","Vprf2Cfgr3","FPfSEpFrrl","P6bcgnlaBy","VIlwPy94nw","uJScXcShY2","hSSvQfaHir","d7vjMa00b5",
-"Ul4a1s7Mxk","JXljWtAOsr","ix74rXyPZN","MmsIohSSvQ","5iGN5JkzUn","Ta8f6rKDLJ","AXpwEMm8si","XyPZNfqypy","uZPqg5Namm","vLsmS5IhmG",
-"mX2GEVerEA","AgJHQ1LB1L","5Namm29QAz","CxVEfWMiS3","azIWpLbRTH","ZuDtDFjHXR","Z4I1vZuDtD","pv0i7n1pmO","14FLRGSQwj","Cfgr38xEKz",
-"n1pmOzHF1q","wDajX9y4lw","s7MxkNOHsz","W7cTstjQxs","MezSWUl4a1","yvOMI7hyVv","MojnPW7cTs","Rxrsmaez9y","cQOnvpWiOs","TwanoStlDJ",
-"WmadAqQxHP","Cp3mZdmoS7","VjCZqgtCA5","ZuDtDZ4I1v","lweGy5Namm","zqH0WIRh48","fqypyWMiS3","AmdQd5VZjS","4dEz6VjCZq","dpe1vh1zcH",
-"Mm8sisuY4x","oVQp68TxD7","LbRTHWreyP","Ss0ZutjQxs","uoStwzz4ZU","WreyPFGzgp","8TxD7Ss0Zu","ZuDtD07n1c","s7MxkUlU3M","NAFuw8cVD3",
-"Ss0Zu3weIF","Mkgy80ao3l","ZzJHWF6PT2","FPfSExReec","JIqXitAOsr","In3NSwDajX","Mm8sicL0aE","ni2v1JRJQB","bZLvSyEfy9","hE1Ql2Nslm",
-"RkQke55rfB","FjHXRwDajX","X6Pinn8pJ9","lm0pD6AFT0","ZUnqtIRh48","DG4sTqUJMd","pv0i7DLhzM","HzZT85nmWv","5NammQ6Lix","v1HlnRkQke",
-"cQOnvuTacx","zz4ZUW3VFH","MezSWv8yFN","8cVD32ZHdk","ZuDtDHlUbF","8xEKzdmoS7","i3pydCxVEf","s4786h1zcH","dQ586CK5W7","uvf7AWaim6",
-"zY1GYWDVWJ","ECMvU4dEz6","tjQxsZ4I1v","VBjhznFqik","cShY2tAOsr","8RCUAGSQwj","h1zcHsqVrf","v1HlnUmaEv","IBe8kMezSW","rz7UtZuDtD",
-"BFkb8SjskQ","e6e4zKsjRK","9eoRcTa8f6","7ku1pix74r","Mkgy8IjTwP","qUJMd8FmFH","VNCPdrKDLJ","TCgPp5IhmG","Cp3mZ5VZjS","yToGW8FmFH",
-"e6e4zSs0Zu","Fhtgl2TRI7","XflUq0MR5X","pvgjS6AFT0","LewvML7cGc","MojnPChuy3","07n1cGrDg7","oQ87rFwEJz","rz7UtbrhlQ","nlaByfFDrJ",
-"9GXkXHRxd8","AkKTko8Uyd","WPmlxulk41","m4bxUfcJOy","xciqp7lUXZ","5Drn03otm6","0Wr5yLewvM","0Wr5yuQIcz","dQ586pv0i7","M6qcGbrhlQ",
-"QbxXcgjUTu","OUqFMNxx9V","zHF1qjiVBP","7X3uyiB08l","aFFss9rlg9","kZANmDz1R3","9y4lwtAOsr","MGlTFDLhzM","uvf7Agf8rI","MaJQsM3zXL",
-"K20wKBGaQY","SWfoui7WMQ","x3LDe2TRI7","d85a9B3qem","FcWrW9iGoT","D6rByOHaBz","YOfrYpvgjS","3otm6sx5Gl","OUYuFv2eC3","y94nwL7cGc",
-"QssNCMGlTF","2Yz7E5nmWv","Q6hMChYBCK","OUqFMB3qem","uLtKsReKEW","jfREu5Mg9r","NcICA0Kyfs","J2mQiQbxXc","uLtKspFrrl","pvgjSYOfrY",
-"RBhp07fKYU","dmoS75drc6","HzZT84QMc9","pAhR1U3yw5","4dEz68FmFH","qUJMdGv3Fq","vkCHHyvOMI","d7vjM7Ow5C","S77LHatef2","OxWIHFxX9q",
-"IKxdLWmadA","taOXKyluBx","mX2GEsx5Gl","JKWYRuupzk","ix74rhE1Ql","suY4xK4GS8","sx5GlcL0aE","mz8gx48cHL","CxVEfW7cTs","RkQkes4786",
-"Ul4a1WreyP","S77LHGSQwj","ni2v1s7Mxk","K4GS8NAFuw","0h1b1OUYuF","Ss0ZuFjHXR","ECMvU5Namm","ReKEWFxX9q","LDk6fDG4sT","FnPFByToGW",
-"soy9tUvlv4","VLTy6Cfgr3","EOE1oyluBx","LewvM9eoRc","brhlQDz1R3","Ta8f6HfyNQ","cmXIXY1mC0","5Drn0AkKTk","JIqXiMGlTF","9GXkXi3pyd",
-"HlUbFFxX9q","9GXkXVBjhz","oGu6xY1mC0","G1RhSpFrrl","FPfSEECMvU","EdBKcfLNg8","tAOsrYjB9t","mz8gx0PktI","HlUbFUlU3M","PYBf4iB08l",
-"rKDLJGrDg7","GXdoHDz1R3","uPX7GM3zXL","5ZaEzUmaEv","Kr8ysAOgEe","tuDySGSQwj","KZamH5ZaEz","TXQ0Za00b5","QWxoTyEfy9","jS1aj45cIH",
-"uTacxblLA9","oVQp60PktI","7fKYUfaHir","Yf2Ec14FLR","tl72WqQxHP","WmadAtlILt","GXdoHa00b5","guMb8JJs5m","3weIF580YD","hE1QlhYBCK",
-"pv0i7FFDui","6q6L9NAFuw","7X3uyOz8yZ","GrDg7s93Ml","CqqaDfcJOy","n8pJ9x3LDe","WMiS32Yz7E","rKDLJUl4a1","brhlQJXljW","hi5X7sx5Gl",
-"JRJQBQnJ1S","8cVD3jeskS","F6PT2zFgtB","07n1cNhXdu","0MR5XTwano","1LB1L5VZjS","IBe8klsQGo","BFkb8jfREu","RACujCNHmv","sx5GloGu6x",
-"m4bxUqUJMd","DcpWBRmDcr","TCgPpFPfSE","YOfrYfcJOy","UmaEvVjCZq","M6qcGpT8wu","pAhR1v8yFN","BbwgAAkKTk","OxWIHd85a9","b29RJmX2GE",
-"yofH3taOXK","AmdQdNo0Qb","oVQp6i7WMQ","dQ586ix74r","rz7UtVerEA","i3pyd9y4lw","lpF6WSWfou","ix74rRzaZA","8hJdttlILt","07n1cDz1R3",
-"JJs5msoy9t","FwEJzVLTy6","uAWypCNHmv","s93MlpT8wu","blLA9Ss0Zu","vLsmSd7vjM","M6qcGciuWz","NAFuwpFrrl","dpe1vF6PT2","s93MlvkCHH",
-"v1HlnKZamH","7fsYMOxWIH","0Wr5ySbRYy","h1zcH2Yz7E","pWiOsnFqik","aez9y5nmWv","d7vjM2DREs","Pb1pazbIYY","64s8N5Mg9r","5NammZ4I1v",
-"Vprf2k85Ae","MmsIo8FmFH","bgJAzNo0Qb","FGzgpcmXIX","e6e4zzY1GY","618DiXflUq","Fhtgl580YD","pmeCdfaHir","yvOMIG1RhS","QYxC0pAhR1",
-"48cHLtuDyS","lXFOBuvf7A","EOE1oL7cGc","2ZHdkKZamH","n1pmO6q6L9","uAWypAkKTk","BGaQYwiHrZ","uTacxNOHsz","RpBQmsx5Gl","VBjhzhE1Ql",
-"atef2iB08l","FVMxotl72W","ydG8U7lUXZ","5nmWvWaWsv","he9IABpYhV","h1zcHIKxdL","jzUqRazIWp","cQOnvKASQ8","lH1ktUl4a1","d85a9SWfou",
-"AOgEeGSQwj","POUYSTa8f6","TXQ0ZCqqaD","QChxs3otm6","azIWp8cVD3","3otm6aL6AJ","TXQ0ZPb1pa","rz7UtKASQ8","QssNCgtCA5","he9IALDk6f",
-"pFrrllCMxy","m4bxU8cVD3","2hEEUB3qem","U3yw5WreyP","iqv4ksuY4x","FxX9qlsQGo","oGu6x5Mg9r","ReKEWStlDJ","lm0pDJKWYR","GXdoHFjHXR",
-"SWfou0Kyfs","wDajXP6bcg","OUqFMFPfSE","wDajX6AFT0","24ARFd7vjM","WDVWJCxVEf","Y1mC0e6e4z","B3qem9XyT9","nFqikVjCZq","2NslmDQimp",
-"bZLvSQ6hMC","ZuDtDNAFuw","JJs5mqQxHP","gf8rIQWxoT","5IhmG07n1c","Fhtgl55rfB","e6e4zX6Pin","IRh48wDajX","oQ87rK4GS8","7ku1ps7Mxk",
-"uJScXcmXIX","HzZT8dQ586","SjskQydG8U","5iGN5guMb8","9iGoTyofH3","4W0TlMGlTF","WaWsvS77LH","DcpWBuPX7G","UmaEvuLtKs","NOHszlCMxy",
-"uupzk9eoRc","AmdQdNhXdu","aez9ytuDyS","ThjNnt59lR","zHF1qblLA9","ZzJHWBFkb8","Ul4a1RmDcr","a00b5In3NS","QworuDQimp","HRxd8tvdkD",
-"7hyVvNOHsz","EdBKctaOXK","rz7UtECMvU","y94nwhe9IA","HlUbFFPfSE","MK07YuTacx","guMb8tvdkD","AOgEei7WMQ","9y4lwZ4I1v","WreyPGSQwj",
-"9rlg9HRxd8","AmdQdWPmlx","lweGyYjB9t","QClRLDz1R3","uTacxRACuj","FGzgpLbRTH","4dEz616lHc","DLhzMFhtgl","pFrrlVprf2","tuDySqQxHP",
-"OxWIH7hyVv","aDGtSIBe8k","Mm8siFVMxo","QnJ1Sfqypy","GWqqXFcWrW","7lUXZ1v5hH","I7p2asx5Gl","lkMUAuupzk","ZuDtDNxx9V","JJs5mMm8si",
-"pvgjSFwEJz","zHF1qUl4a1","m4bxUJRJQB","MaJQsoQ87r","5Namm8TxD7","CqqaDIRh48","zFgtBtaOXK","6q6L9Nxx9V","lj07QsuY4x","rKDLJFGzgp",
-"okgRiru4UG","5nmWveuZA5","MmsIorKDLJ","suY4x8xEKz","RsQUqjSjS3","K4GS86AFT0","Waim6BbwgA","QnJ1ShYBCK","RpBQm2Yz7E","6q6L9s7Mxk",
-"XyPZNeuZA5","i3pyd1LB1L","YOfrYSs0Zu","1j5L8kB5nP","JXljW2ZHdk","0Wr5yfLNg8","QChxsbZLvS","8FmFHVprf2","BGaQYDLhzM","ThjNntjQxs",
-"618DihE1Ql","yToGWNOHsz","9GXkXS2Dfu","2Yz7ECqqaD","gIYvEK20wK","d7vjMhYBCK","jfREuDcpWB","VLTy6CqqaD","k85Ae8RCUA","vLsmS5Drn0",
-"BbwgAcmXIX","9rlg9hi5X7","WPmlxWDVWJ","HP433yluBx","y94nwDG4sT","3otm6GSQwj","OUqFM7Ow5C","ix74rDQimp","FNYIMEoToP","MmsIoK20wK",
-"8TxD7djsrv","FhtgllsQGo","pv0i7Rxrsm","ECMvUPb1pa","jS1ajiqv4k","Y1mC03otm6","xReec2DREs","RxrsmuJScX","DQimpzHF1q","X6PinAOgEe",
-"3weIFtvdkD","vLsmSazIWp","RkQkeEoToP","9eoRc8TxD7","5IhmGUmaEv","OxWIHguMb8","SWfouQbxXc","v2eC3cL0aE","VerEA2Yz7E","8U2nUtuDyS",
-"VjCZqMmKGJ","Q6hMCIRh48","fFDrJCfgr3","7fKYUJRJQB","JkzUnZv7z0","hi5X7RmDcr","RACujtuDyS","No0QbCIShG","Ul4a1gIYvE","Z4I1vgf8rI",
-"CqqaDXyPZN","QssNCjS1aj","fLNg8okgRi","JRJQBQworu","iwzGkd85a9","580YD8cVD3","In3NSyofH3","Cfgr3GXdoH","XflUquQIcz","7Ow5CpFrrl",
-"v2eC38RCUA","dhSuH2hEEU","rz7UtIn3NS","VerEAv2eC3","0YAGH4W0Tl","tl72WyToGW","pAhR1Ul4a1","xciqpi7WMQ","Y1mC0QWxoT","IKxdLjSjS3",
-"Ss0ZuuLtKs","Uvlv4XyPZN","gjUTuhe9IA","Q6hMCtaOXK","sx5GlpiJSk","okgRiNcICA","WMiS3Yw2oU","zFgtB1j5L8","lpF6WmX2GE","fLNg8P6bcg",
-"fcwDa9y4lw","618Dihi5X7","e6e4zTa8f6","uPX7GlXFOB","vkCHHoVQp6","DLhzMXflUq","F6PT2M6qcG","brhlQmz8gx","dQ586JkzUn","suY4xzqH0W",
-"hYBCK4W0Tl","JkzUnOz8yZ","QnJ1Satef2","QnJ1SksJby","uTacxJXljW","FwEJzlXFOB","3weIFYf2Ec","bgJAz2hEEU","QnJ1SDLhzM","jS1ajjSjS3",
-"fFDrJtvdkD","W7cTsDLhzM","6AFT0J2mQi","6q6L9cQOnv","KASQ8D6rBy","uAWyplCMxy","VIlwPfFDrJ","64s8NFhtgl","WPmlxnFqik","RBhp0zY1GY",
-"WreyP0PktI","kZANmECMvU","vLsmSzQt6Q","Mm8sirhl0J","HRxd8yofH3","l83UdKr8ys","ksJby0BmCy","yluBxix74r","vOqCEBbwgA","gtCA5YjB9t",
-"WaWsvJ2mQi","Zv7z0n1pmO","l83Udv8yFN","Ta8f60ao3l","ZzJHW1j5L8","yofH3jSjS3","k85AegIYvE","BbwgAtlILt","fcJOyMm8si","Yw2oUGv3Fq",
-"9eoRcvOqCE","BFkb80YAGH","FNYIMAkKTk","lkMUADLhzM","sqVrfSjskQ","Yw2oUDG4sT","azIWprhl0J","VLTy6nFqik","jSjS3CIShG","DLhzMAkKTk",
-"k85AejfREu","uZPqgjSjS3","zmLYDgjUTu","Pb1paUmaEv","i7WMQiB08l","YOfrYJKWYR","8RCUAdpe1v","CIShGCxVEf","CK5W7mz8gx","BCxeC48cHL",
-"7fKYURBhp0","e6e4zUmaEv","7fsYM1LB1L","e6e4zG1RhS","cmXIXzY1GY","kZANmMm8si","AXpwEVIlwP","nnP8o2ZHdk","ZhwG1580YD","Mm8siBFkb8",
-"tuDySMkgy8","sqVrfYw2oU","cmXIXNOHsz","tl72WK4GS8","0BmCyWDVWJ","lH1ktlweGy","0YAGHRxrsm","X6Pinmz8gx","MojnPs93Ml","zmLYDUlU3M",
-"ru4UGuJScX","KZamHwDajX","EOE1ofFDrJ","JRJQBBCxeC","kZANm48cHL","WaWsvBpYhV","yEfy98hJdt","jtn0XzbIYY","8U2nUNxx9V","uoStw45cIH",
-"Mkgy8JJs5m","580YDUl4a1","4dEz6Yf2Ec","zQt6QLbRTH","5IhmG0Wr5y","45cIHtuDyS","UmaEv3weIF","RBhp024ARF","sx5Gl1LB1L","xReec07n1c",
-"e6e4zHlUbF","S77LHmz8gx","tuDySRsQUq","iwzGkpAhR1","5IhmG8TxD7","sqVrfOxWIH","5drc6Kr8ys","7lUXZIjTwP","FwEJznnP8o","EOE1ouQIcz",
-"Ss0Zu1j5L8","FLsphqaofN","UmaEvuTacx","he9IAVBjhz","8cVD3oGu6x","euZA5ulk41","I7p2aulk41","AmdQd618Di","rz7UtCqqaD","AgJHQIjTwP",
-"JIqXilH1kt","he9IAydG8U","o8UydWaim6","JXljWGSQwj","fFDrJzQt6Q","pvgjSpAhR1","hi5X7FxX9q","O3iyQyluBx","MezSWKASQ8","I7p2arhl0J",
-"mz8gx8RCUA","2Yz7EGXdoH","OHaBzsuY4x","i3pyddjsrv","XyPZNix74r","djsrv9rlg9","brhlQG1RhS","prNT6pAhR1","guMb8WDVWJ","HP433hE1Ql",
-"2ZHdk8cVD3","HRxd8uoStw","D6rBy1LB1L","nFqikVBjhz","In3NSuN6r3","QssNCs7Mxk","uvf7Auupzk","WaWsvLewvM","Ta8f6ZUnqt","kZANmazIWp",
-"xXTI4yluBx","AXpwEReKEW","G1RhSaez9y","VIlwPm4bxU","5drc6OxWIH","KZamHKr8ys","t98iWSs0Zu","DLhzMBCxeC","rz7UtrKDLJ","ReKEWrhl0J",
-"zQt6QiKqhr","FxX9qW7cTs","DG4sT45cIH","uTacxwiHrZ","EoToP07n1c","MmKGJDcpWB","ZuDtDt59lR","VBjhztl72W","2DREsVLTy6","FxX9q7X3uy",
-"o8UydblLA9","uTacxCp3mZ","QworuMK07Y","uZPqgGv3Fq","4W0Tls7Mxk","hYBCKAkKTk","gtCA5Q6hMC","nlaByrKDLJ","lkMUArz7Ut","9XyT9RBhp0",
-"ZJTXHnFqik","OUqFMpAhR1","tlILtK20wK","Yf2EcjSjS3","FPfSEiwzGk","5Drn00PktI","J2mQiqaofN","JJs5m5drc6","0MR5XJKWYR","jeskSQssNC",
-"CxVEfVjCZq","CNHmvxXTI4","hi5X7GWqqX","blLA9rKDLJ","rKDLJtjQxs","lsQGoyvOMI","RACujUlU3M","7hyVv8TxD7","djsrvWmadA","x3LDeGrDg7",
-"IRh48yToGW","VLTy6XflUq","Dz1R35drc6","EdBKcqQxHP","jeskS9eoRc","soy9t0MR5X","zY1GYLbRTH","QworuIjTwP","Y1mC0lCMxy","1v5hHRzaZA",
-"gdQsSFhtgl","DLhzM9rlg9","Gv3Fqv1Hln","FnPFBJ2mQi","7lUXZt98iW","Ul4a1YjB9t","lXFOBt98iW","gf8rIFhtgl","fcJOy7fKYU","618Dipv0i7",
-"2hEEUJ2mQi","iqv4kMezSW","K20wKEdBKc","OUqFMI7p2a","MezSWciuWz","RpBQmlweGy","fqypygdQsS","HRxd8SjskQ","MaJQsKsjRK","FGzgpMkgy8",
-"5Namms7Mxk","lH1ktNhXdu","K4GS8ReKEW","yEfy9yToGW","ReKEWMK07Y","JKWYRJRJQB","lpF6WAmdQd","hSSvQTXQ0Z","uZPqgVjCZq","yToGWDG4sT",
-"xciqphi5X7","iqv4k7hyVv","ogLgcRsQUq","W3VFH9eoRc","29QAz5nmWv","s7MxkZuDtD","uZPqg16lHc","d85a9Fhtgl","WPmlxQClRL","oVQp6RBhp0",
-"Y1mC0brhlQ","ni2v1WaWsv","qQxHPNcICA","ix74r4W0Tl","fcwDaYw2oU","WDVWJ618Di","0Wr5yHRxd8","2ZHdkuLtKs","zY1GYQ6hMC","ECMvUTwano",
-"zQt6QwDajX","QClRLpFrrl","cShY2JkzUn","aL6AJ16lHc","faHirOxWIH","LewvMrKDLJ","nlaByYh1hF","QssNC9y4lw","XyPZND6rBy","zHF1qY1mC0",
-"uN6r3QWxoT","Rxrsm24ARF","hi5X7Zv7z0","lj07QSWfou","FjHXROxWIH","pFrrlK4GS8","D6rBys93Ml","atef25nmWv","8TxD7SbRYy","VBjhzx3LDe",
-"OxWIHGSQwj","cL0aEsx5Gl","QChxsrz7Ut","xReecGrDg7","h1zcHtuDyS","64s8NlCMxy","5ZaEzIKxdL","ni2v1taOXK","iKqhrlkMUA","RxrsmuN6r3",
-"Q6LixThjNn","LDk6fjS1aj","uPX7GQChxs","cQOnvBFkb8","ReKEWYh1hF","l83UdjS1aj","n8pJ9o8Uyd","ZzJHWYjB9t","uvf7AXflUq","blLA9DQimp",
-"tAOsrKsjRK","9eoRcAmdQd","uAWypNAFuw","StlDJy94nw","KsjRKI7p2a","yluBxCK5W7","FNYIMQworu","cShY2RmDcr","POUYStAOsr","0Kyfs2hEEU",
-"pvgjSpmeCd","Q6hMC7hyVv","yofH3FFDui","07n1cjfREu","cmXIX14FLR","ZJTXHe6e4z","lCMxy8TxD7","NcICAFGzgp","618DiW7cTs","1v5hHvOqCE",
-"WmadAZuDtD","lkMUAs7Mxk","fmIK15iGN5","VLTy68FmFH","8TxD7pAhR1","2TRI7ksJby","euZA5v2eC3","KASQ8hUTw7","7fsYMlweGy","iqv4kgjUTu",
-"yluBxhE1Ql","Chuy39y4lw","WMiS3ReKEW","yluBxRkQke","55rfBKZamH","suY4xIBe8k","oGu6xt98iW","0Wr5yAkKTk","djsrvFGzgp","KsjRKEOE1o",
-"48cHLK20wK","16lHcI7p2a","xReec9eoRc","zmLYDF6PT2","0Wr5ypiJSk","euZA5pvgjS","0MR5Xy94nw","Zv7z0JXljW","8cVD3M3zXL","IRh48sqVrf",
-"uQIczM6qcG","5drc6ZzJHW","dhSuHDG4sT","29QAzazIWp","CxVEfuvf7A","hi5X7In3NS","Yf2EcAOgEe","HP433NAFuw","VLTy6l83Ud","nnP8oni2v1",
-"suY4xiqv4k","dQ586QssNC","iKqhrJIqXi","tvdkD7lUXZ","VNCPd7lUXZ","TCgPpRsQUq","Oz8yZuupzk","blLA9dhSuH","0MR5Xaez9y","VIlwPX6Pin",
-"Yh1hFX6Pin","ogLgcoQ87r","Ta8f68FmFH","Q6hMCJKWYR","3weIFlweGy","TXQ0ZeuZA5","cL0aEjiVBP","M6qcGguMb8","taOXKYf2Ec","W7cTscQOnv",
-"ogLgc618Di","Y1mC0Q6Lix","U3yw5YjB9t","RBhp0oGu6x","v1HlnTa8f6","5IhmGMkgy8","yEfy9fcwDa","azIWpL7cGc","fFDrJogLgc","StlDJvOqCE",
-"lXFOBs4786","FLsph9eoRc","JkzUnlXFOB","7fsYMaL6AJ","4QMc9pT8wu","jtn0X8RCUA","JkzUn0Kyfs","s93MlRBhp0","EOE1oRsQUq","t98iWJkzUn",
-"lweGyqUJMd","CIShGiwzGk","hYBCKG1RhS","VIlwP5drc6","FhtglnFqik","hYBCK8FmFH","gIYvEtl72W","cQOnvzY1GY","vOqCEDQimp","X6PinlXFOB",
-"ZUnqtdQ586","cL0aEd85a9","ReKEWVprf2","7Ow5CQworu","7Ow5CBCxeC","lCMxyJkzUn","ogLgck85Ae","uTacxzmLYD","G1RhSNhXdu","i3pydGrDg7",
-"WreyP0MR5X","Chuy3Uvlv4","6AFT0tjQxs","lj07QFwEJz","VLTy6bZLvS","dQ586RBhp0","FnPFBdmoS7","9iGoT1LB1L","fcJOyAkKTk","64s8NIn3NS",
-"RzaZAS77LH","xciqppAhR1","Gv3Fq1v5hH","In3NSuoStw","piJSkzqH0W","pmeCdiqv4k","48cHLVNCPd","zqH0Wfqypy","yluBxtaOXK","FxX9qfcJOy",
-"tvdkDs93Ml","gtCA5WaWsv","pFrrlNOHsz","MGlTF7hyVv","zHF1qFFDui","2hEEUStlDJ","OUYuF2hEEU","FPfSEMmsIo","zY1GYuupzk","atef2vLsmS",
-"v8yFNaFFss","jzUqRMojnP","FLsphfcJOy","OxWIHazIWp","7Ow5C7lUXZ","FjHXRfcwDa","6q6L9WDVWJ","WMiS3taOXK","v2eC3BbwgA","8TxD7a00b5",
-"xciqpDQimp","Ss0Zu1LB1L","WPmlxMezSW","d7vjMuN6r3","7hyVvfFDrJ","soy9tWaWsv","IjTwPqaofN","i3pydnFqik","iwzGkokgRi","4dEz6aFFss",
-"Mm8si5Drn0","4QMc9QChxs","Uvlv4ZhwG1","RACujdpe1v","0MR5XIn3NS","7lUXZHP433","he9IAQYxC0","dQ586uQIcz","dQ586o8Uyd","WmadAlm0pD",
-"iKqhrBGaQY","SbRYyrKDLJ","DQimpAIYUu","y94nwFhtgl","JIqXiiB08l","LDk6fIBe8k","l83UdGrDg7","uPX7G5IhmG","dmoS71v5hH","Kr8ys8FmFH",
-"t98iWsoy9t","0BmCyZzJHW","m4bxUO3iyQ","nlaBypT8wu","55rfByluBx","WaWsvLDk6f","Mm8siM3zXL","hUTw7IBe8k","DLhzMx3LDe","EdBKcjSjS3",
-"m4bxUUlU3M","AXpwEtjQxs","GWqqX48cHL","9rlg9kB5nP","55rfBPb1pa","oGu6xa00b5","jiVBP9rlg9","uN6r3suY4x","0MR5XRmDcr","618DiVNCPd",
-"uvf7AaDGtS","6q6L9B3qem","W7cTsC2Irc","lpF6WFjHXR","dhSuHlkMUA","IKxdLYf2Ec","tjQxs8TxD7","kB5nPVprf2","JIqXi4dEz6","StlDJTXQ0Z",
-"oVQp6dmoS7","FNYIMRkQke","9iGoTChuy3","lj07Qk85Ae","MezSWGv3Fq","Pb1paNAFuw","BbwgAprNT6","4QMc98FmFH","uAWypIn3NS","D6rByiwzGk",
-"d85a98U2nU","RkQkepv0i7","0Wr5yM6qcG","PYBf4cmXIX","0PktI5drc6","D6rByEoToP","kB5nPMkgy8","2TRI7U3yw5","Dz1R3FnPFB","CdyBVGrDg7",
-"i3pydCfgr3","1LB1L9y4lw","8RCUAZ4I1v","MmKGJcShY2","KASQ8vLsmS","iKqhrciuWz","RpBQmU3yw5","lsQGoSmGzv","9iGoTIBe8k","ru4UGKr8ys",
-"s4786bgJAz","5VZjS2DREs","AkKTkQYxC0","5IhmGjeskS","qQxHPChuy3","MK07YOz8yZ","I7p2aG1RhS","kZANmru4UG","SbRYyRBhp0","uQIczcShY2",
-"7Ow5CIBe8k","Waim6ZUnqt","jS1ajDG4sT","yvOMI9rlg9","SmGzvh1zcH","yEfy9CIShG","DLhzM7hyVv","LbRTHRkQke","LewvM7lUXZ","he9IAAgJHQ",
-"nFqikFxX9q","JXljWFcWrW","Y1mC0XflUq","EdBKcpAhR1","VNCPdYw2oU","jSjS37fsYM","DG4sTeuZA5","Ta8f6VBjhz","SmGzvLbRTH","4W0Tl5Mg9r",
-"VerEAHzZT8","DLhzMd7vjM","jSjS3YOfrY","WmadAqUJMd","YjB9tKASQ8","Qworusoy9t","No0QbChuy3","VBjhzLewvM","J2mQipWiOs","fmIK1YOfrY",
-"In3NSZv7z0","UmaEvYOfrY","gIYvEuQIcz","RzaZAPOUYS","618DiHzZT8","gdQsSI7p2a","Ul4a1AkKTk","5Mg9rAkKTk","CqqaDSbRYy","TXQ0Zsx5Gl",
-"2ZHdkRsQUq","8TxD7WMiS3","7ku1pWDVWJ","I7p2aMK07Y","W7cTsK20wK","ydG8UgjUTu","ksJbyYw2oU","GSQwjGWqqX","WPmlx8TxD7","48cHLDG4sT",
-"vkCHHRzaZA","hE1QlcShY2","oGu6xGv3Fq","t98iWAOgEe","uTacxQnJ1S","d85a9uQIcz","hSSvQv2eC3","P6bcgBbwgA","CIShGTwano","AXpwEsx5Gl",
-"gtCA5tlILt","iwzGk8U2nU","rhl0JYf2Ec","RzaZA4dEz6","ZzJHWC2Irc","CxVEfk85Ae","iB08lzz4ZU","DcpWBLbRTH","U3yw5FVMxo","Mm8siJkzUn",
-"FnPFB5drc6","LewvMPOUYS","9XyT9XflUq","4QMc9guMb8","he9IADG4sT","vLsmSQ6hMC","pAhR1KZamH","m4bxU0PktI","d7vjM9XyT9","NOHszuN6r3",
-"5iGN5ECMvU","PYBf4MezSW","sx5Gl29QAz","DG4sTbgJAz","fcwDa0YAGH","In3NSHP433","gdQsSGSQwj","MK07Ye6e4z","yluBxI7p2a","AXpwEFwEJz",
-"zHF1qVerEA","1v5hHoGu6x","dhSuHPOUYS","s7MxkqQxHP","fqypy7X3uy","soy9tGSQwj","QChxs2Nslm","AgJHQWPmlx","2TRI7SjskQ","SjskQdmoS7",
-"Yf2EcMaJQs","SjskQRsQUq","dhSuHFjHXR","Q6LixpvgjS","W7cTs0Wr5y","HP4334dEz6","zFgtBMkgy8","TXQ0Zmz8gx","9iGoTsoy9t","qQxHPuJScX",
-"AkKTkKsjRK","kZANmn1pmO","6q6L9qQxHP","ydG8UjiVBP","fmIK1RkQke","aL6AJs93Ml","0MR5Xo8Uyd","hSSvQQChxs","CK5W7MmKGJ","pv0i78xEKz",
-"FjHXR0Kyfs","fLNg8Y1mC0","29QAzkZANm","ZuDtDi3pyd","ogLgcUlU3M","hSSvQs93Ml","pv0i7nlaBy","X6PinReKEW","wDajXGrDg7","CxVEf24ARF",
-"cmXIXbgJAz","HfyNQgdQsS","QssNCQbxXc","HlUbFTCgPp","yEfy95Mg9r","Ta8f6djsrv","zz4ZU8TxD7","0KyfsCdyBV","1j5L8tuDyS","RsQUqtvdkD",
-"prNT6lweGy","okgRiFjHXR","lViBvcL0aE","zmLYDZv7z0","wDajXi3pyd","fmIK1n1pmO","QYxC0gtCA5","FxX9qBpYhV","zbIYYrz7Ut","AmdQd4W0Tl",
-"tl72Wl83Ud","lj07Q8hJdt","SjskQKASQ8","ReKEWMojnP","pvgjSo8Uyd","AIYUuCxVEf","WreyPWaWsv","brhlQoGu6x","7fKYUjzUqR","vkCHHThjNn",
-"zmLYDgtCA5","Q6hMC7fsYM","o8UydUlU3M","cL0aElm0pD","fmIK1AmdQd","gIYvExciqp","UmaEvFFDui","Mkgy8D6rBy","lXFOB5iGN5","2Yz7EaDGtS",
-"7ku1pv1Hln","v1HlnUlU3M","OUYuFt59lR","8cVD38FmFH","YOfrYguMb8","K20wKHzZT8","yofH3tAOsr","gtCA5NhXdu","kB5nP3weIF","Ul4a1MezSW",
-"1LB1LFLsph","U3yw5hUTw7","s93Mluupzk","POUYSVIlwP","FcWrWWPmlx","WDVWJh1zcH","Nxx9VcL0aE","cmXIXQworu","JkzUnGWqqX","oQ87r16lHc",
-"lweGyOUqFM","RBhp0VerEA","iKqhrP6bcg","tAOsri7WMQ","lweGyvLsmS","jS1aj7lUXZ","5Mg9rdmoS7","Yf2Ec45cIH","uZPqg0h1b1","WMiS3WPmlx",
-"soy9twiHrZ","BGaQYydG8U","zmLYDydG8U","hE1QlQbxXc","uJScX5ZaEz","lkMUAW3VFH","OUqFMpmeCd","oVQp6FcWrW","xciqpogLgc","suY4x5Mg9r",
-"0MR5X9rlg9","QYxC0MGlTF","lweGygdQsS","QworuGrDg7","mz8gxzmLYD","jfREu8xEKz","bZLvSaez9y","OUqFM48cHL","i3pydgf8rI","CqqaDMkgy8",
-"5Drn0sqVrf","QWxoTHzZT8","55rfB55rfB","he9IABbwgA","Ta8f6fcwDa","FhtgleuZA5","oQ87rjSjS3","SWfouciuWz","v8yFNlXFOB","5VZjS9rlg9",
-"VIlwPpiJSk","MojnP0ao3l","16lHcNOHsz","Yw2oUqaofN","OHaBzVNCPd","In3NSD6rBy","M3zXLzz4ZU","wDajXFwEJz","OUqFMhUTw7","Mm8siWaWsv",
-"3otm6B3qem","gtCA5xciqp","QWxoTlm0pD","JKWYRTwano","fmIK1fLNg8","bgJAzRkQke","Zv7z0HfyNQ","zz4ZU4W0Tl","D6rByJkzUn","ru4UGMezSW",
-"yluBxDLhzM","5Nammni2v1","Uvlv4OUqFM","jSjS3lm0pD","Cfgr3RmDcr","i3pydFNYIM","5nmWvK4GS8","aFFss29QAz","RzaZAFPfSE","CxVEfHzZT8",
-"7fsYM0Wr5y","dQ586Ul4a1","Cfgr32hEEU","2Nslmhi5X7","StlDJ48cHL","uvf7ApAhR1","DQimpydG8U","uupzkCp3mZ","Zv7z07fsYM","07n1cNxx9V",
-"MmsIo0MR5X","S2DfucShY2","AIYUuM6qcG","RBhp0gf8rI","3weIFzz4ZU","Q6Lixi7WMQ","zFgtB8TxD7","RpBQm7ku1p","fmIK1L7cGc","gtCA5Z4I1v",
-"GXdoHPYBf4","ru4UGvOqCE","hYBCKVBjhz","prNT6I7p2a","FcWrW8U2nU","1v5hHCp3mZ","8xEKzhUTw7","aFFss5ZaEz","Waim68FmFH","Mkgy8S2Dfu",
-"JIqXi0ao3l","v1Hln1j5L8","gdQsSThjNn","MmsIogIYvE","he9IAWaim6","qaofN8cVD3","s7MxkW3VFH","fLNg8pT8wu","ni2v14QMc9","pmeCdHzZT8",
-"8FmFHRsQUq","HzZT8taOXK","Pb1pa3weIF","Fhtgl14FLR","gjUTul83Ud","zFgtBTCgPp","ru4UGS2Dfu","Zv7z08TxD7","BCxeCm4bxU","6AFT0suY4x",
-"tuDySKZamH","14FLRyEfy9","CIShGBFkb8","AOgEe4dEz6","ECMvU0ao3l","X6Pinhe9IA","16lHcxReec","uoStwtjQxs","aFFsslm0pD","k85AeB3qem",
-"07n1cFhtgl","zFgtBRsQUq","W3VFHpiJSk","Qworuv1Hln","rKDLJn8pJ9","7X3uy5ZaEz","OHaBzD6rBy","jS1aj9eoRc","S77LH0ao3l","BbwgAciuWz",
-"Mkgy8DcpWB","pv0i77ku1p","yofH3P6bcg","SbRYyFcWrW","e6e4zcmXIX","cL0aEU3yw5","Vprf2ZhwG1","6AFT0l83Ud","d7vjMXyPZN","ulk41uPX7G",
-"yEfy9FjHXR","uQIczMGlTF","v2eC32TRI7","24ARFfqypy","9eoRcAXpwE","WreyPjS1aj","n8pJ9Z4I1v","29QAztl72W","zY1GYAmdQd","JJs5m5VZjS"
-] } }
-}
- ],
- "_connections":[
- {
- "_name": "connection1",
- "_factory": "connectionfactory",
- "_sessions": [
- {
- "_sessionName": "session1",
- "_acknowledgeMode": 1,
- "_producers": [
- {
- "_name": "Producer1",
- "_destinationName": "direct://amq.direct//sorted-queue?durable='true'",
- "_deliveryMode": 2,
- "_messageSize": 1024,
- "_numberOfMessages": 200000,
- "_messageProviderName": "messageProvider"
- }
- ]
- }
- ]
- }
- ]
- },
- {
- "_name": "consumingClient",
- "_connections":[
- {
- "_name": "connection1",
- "_factory": "connectionfactory",
- "_sessions": [
- {
- "_sessionName": "session1",
- "_acknowledgeMode": 1,
- "_consumers": [
- {
- "_name": "Consumer1",
- "_destinationName": "direct://amq.direct//sorted-queue?durable='true'",
- "_numberOfMessages": 200000
- }
- ]
- }
- ]
- }
- ]
- }
- ]
- },
- {
- "_name": "queue-type:simple-queue";
- "_queues":[
- {
- "_name": "direct://amq.direct//simple-queue?durable='true'",
- "_durable": true,
- "_attributes":
- {
- "x-qpid-capacity": 10485760,
- "x-qpid-flow-resume-capacity": 8388608
- }
- }
- ],
- "_clients":[
- {
- "_name": "producingClient",
- "_connections":[
- {
- "_name": "connection1",
- "_factory": "connectionfactory",
- "_sessions": [
- {
- "_sessionName": "session1",
- "_acknowledgeMode": 1,
- "_producers": [
- {
- "_name": "Producer1",
- "_destinationName": "direct://amq.direct//simple-queue?durable='true'",
- "_deliveryMode": 2,
- "_messageSize": 1024,
- "_numberOfMessages": 200000
- }
- ]
- }
- ]
- }
- ]
- },
- {
- "_name": "consumingClient",
- "_connections":[
- {
- "_name": "connection1",
- "_factory": "connectionfactory",
- "_sessions": [
- {
- "_sessionName": "session1",
- "_acknowledgeMode": 1,
- "_consumers": [
- {
- "_name": "Consumer1",
- "_destinationName": "direct://amq.direct//simple-queue?durable='true'",
- "_numberOfMessages": 200000
- }
- ]
- }
- ]
- }
- ]
- }
- ]
- }
- {
- "_name": "queue-type:priority-queue";
- "_queues":[
- {
- "_name": "direct://amq.direct//priority-queue?durable='true'",
- "_durable": true,
- "_attributes":
- {
- "x-qpid-priorities": 10
- }
- }
- ],
- "_clients":[
- {
- "_name": "producingClient",
- "_messageProviders": [
- {
- "_name": "messageProvider",
- "_messageProperties":{ "priority": {"@def": "range", "_lower": 0, "_upper": 9, "_type": "int"} }
- }
- ],
- "_connections":[
- {
- "_name": "connection1",
- "_factory": "connectionfactory",
- "_sessions": [
- {
- "_sessionName": "session1",
- "_acknowledgeMode": 1,
- "_producers": [
- {
- "_name": "Producer1",
- "_destinationName": "direct://amq.direct//priority-queue?durable='true'",
- "_deliveryMode": 2,
- "_messageSize": 1024,
- "_numberOfMessages": 20000,
- "_messageProviderName": "messageProvider"
- }
- ]
- }
- ]
- }
- ]
- },
- {
- "_name": "consumingClient",
- "_connections":[
- {
- "_name": "connection1",
- "_factory": "connectionfactory",
- "_sessions": [
- {
- "_sessionName": "session1",
- "_acknowledgeMode": 1,
- "_consumers": [
- {
- "_name": "Consumer1",
- "_destinationName": "direct://amq.direct//priority-queue?durable='true'",
- "_numberOfMessages": 20000
- }
- ]
- }
- ]
- }
- ]
- }
- ]
- }
- ]
-}
diff --git a/java/perftests/example/log4j.properties b/java/perftests/example/log4j.properties
index 8af70ebef2..cabb774156 100644
--- a/java/perftests/example/log4j.properties
+++ b/java/perftests/example/log4j.properties
@@ -25,11 +25,11 @@ log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.Threshold=all
log4j.appender.console.layout=org.apache.log4j.PatternLayout
-log4j.appender.console.layout.ConversionPattern=%d %p [%c{1}] %m%n
+log4j.appender.console.layout.ConversionPattern=%d %p [%t] [%c{1}] %m%n
log4j.appender.fileApp=org.apache.log4j.FileAppender
log4j.appender.fileApp.file=perftests.log
log4j.appender.fileApp.Threshold=info
log4j.appender.fileApp.append=false
log4j.appender.fileApp.layout=org.apache.log4j.PatternLayout
-log4j.appender.fileApp.layout.ConversionPattern=%d %p [%c{1}] %m%n \ No newline at end of file
+log4j.appender.fileApp.layout.ConversionPattern=%d %p [%t] [%c{1}] %m%n
diff --git a/java/perftests/example/perftests-jndi.properties b/java/perftests/example/perftests-jndi.properties
index 8ad0decaad..04a8ad9101 100644
--- a/java/perftests/example/perftests-jndi.properties
+++ b/java/perftests/example/perftests-jndi.properties
@@ -23,4 +23,4 @@ java.naming.factory.initial = org.apache.qpid.jndi.PropertiesFileInitialContextF
# use QpidBrokerTestCase's default port
connectionfactory.connectionfactory = amqp://guest:guest@clientid/test?brokerlist='tcp://localhost:5672'
-destination.controllerqueue = direct://amq.direct//controllerqueue
+destination.controllerqueue = direct://amq.direct//controllerqueue?autodelete='true'
diff --git a/java/perftests/example/perftests.js b/java/perftests/example/perftests.js
new file mode 100644
index 0000000000..51160e7214
--- /dev/null
+++ b/java/perftests/example/perftests.js
@@ -0,0 +1,106 @@
+
+var jsonObject = {
+ _tests:[]
+};
+
+jsonObject._tests= jsonObject._tests.concat(
+ QPID.transform(
+ {
+ "_name": "Multiple clients: 1 consumer - 1 producer - PERSISTENT - message size=1024",
+ "_queues":[
+ {
+ "_name": "direct://amq.direct//varying-consumers?durable='true'",
+ "_durable": true,
+ "_attributes":
+ {
+ "x-qpid-capacity": 10485760,
+ "x-qpid-flow-resume-capacity": 8388608
+ }
+ }
+ ],
+ "_clients":[
+ {
+ "_name": "producingClient",
+ "_connections":[
+ {
+ "_name": "connection__INDEX_",
+ "_factory": "connectionfactory",
+ "_sessions": [
+ {
+ "_sessionName": "session__INDEX_",
+ "_acknowledgeMode": 1,
+ "_producers": [
+ {
+ "_name": "Producer__INDEX_",
+ "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
+ "_maximumDuration": 60000,
+ "_deliveryMode": 2,
+ "_messageSize": 1024
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_name": "consumingClient",
+ "_connections":[
+ {
+ "_name": "connection__INDEX_",
+ "_factory": "connectionfactory",
+ "_sessions": [
+ {
+ "_sessionName": "session__INDEX_",
+ "_acknowledgeMode": 1,
+ "_consumers": [
+ {
+ "_name": "Consumer__INDEX_",
+ "_destinationName": "direct://amq.direct//varying-consumers?durable='true'",
+ "_maximumDuration": 60000
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ function(json)
+ {
+ var producerNumbers = [1, 2, 5, 10];
+ var consumerNumbers = [1, 2, 5, 10];
+ var results = [];
+ for( var i =0; i < producerNumbers.length; i++)
+ {
+ for( var j = 0; j < consumerNumbers.length; j++)
+ {
+ var test = QPID.cloneJSON(json);
+ test._name = "Multiple clients: " + consumerNumbers[j] + " consumer - " + producerNumbers[i] + " producer";
+ results.push(test);
+ test._clients[0]._connections = QPID.times(producerNumbers[i], test._clients[0]._connections[0], "__INDEX_")
+ test._clients[1]._connections = QPID.times(consumerNumbers[j], test._clients[1]._connections[0], "__INDEX_")
+ for (var k =0; k< consumerNumbers[j]; k++)
+ {
+ test._clients[1]._connections[k]._sessions[0]._consumers[0]._name = "consumer_" + k;
+ test._clients[1]._connections[k]._sessions[0]._sessionName = "session_" + k;
+ test._clients[1]._connections[k]._name = "connection_" + k;
+ test._clients[1]._connections[k]._sessions[0]._consumers[0]._maximumDuration = 30000;
+ }
+ for (var k =0; k< producerNumbers[i]; k++)
+ {
+ test._clients[0]._connections[k]._sessions[0]._producers[0]._name = "producer_" + k;
+ test._clients[0]._connections[k]._sessions[0]._sessionName = "session_" + k;
+ test._clients[0]._connections[k]._name = "connection_" + k;
+ test._clients[0]._connections[k]._sessions[0]._producers[0]._maximumDuration= 30000;
+ test._queues[0]._attributes["x-qpid-capacity"] = Math.round(10485760/producerNumbers[i]);
+ test._queues[0]._attributes["x-qpid-flow-resume-capacity"] = Math.round(8388608/producerNumbers[i]);
+ }
+ }
+ }
+ return results;
+ }
+ )
+);
+
diff --git a/java/perftests/src/main/java/json2.js b/java/perftests/src/main/java/json2.js
new file mode 100644
index 0000000000..2dbf60d398
--- /dev/null
+++ b/java/perftests/src/main/java/json2.js
@@ -0,0 +1,487 @@
+/*
+ http://www.JSON.org/json2.js
+ 2011-10-19
+
+ Public Domain.
+
+ NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
+
+ See http://www.JSON.org/js.html
+
+
+ This code should be minified before deployment.
+ See http://javascript.crockford.com/jsmin.html
+
+ USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO
+ NOT CONTROL.
+
+
+ This file creates a global JSON object containing two methods: stringify
+ and parse.
+
+ JSON.stringify(value, replacer, space)
+ value any JavaScript value, usually an object or array.
+
+ replacer an optional parameter that determines how object
+ values are stringified for objects. It can be a
+ function or an array of strings.
+
+ space an optional parameter that specifies the indentation
+ of nested structures. If it is omitted, the text will
+ be packed without extra whitespace. If it is a number,
+ it will specify the number of spaces to indent at each
+ level. If it is a string (such as '\t' or '&nbsp;'),
+ it contains the characters used to indent at each level.
+
+ This method produces a JSON text from a JavaScript value.
+
+ When an object value is found, if the object contains a toJSON
+ method, its toJSON method will be called and the result will be
+ stringified. A toJSON method does not serialize: it returns the
+ value represented by the name/value pair that should be serialized,
+ or undefined if nothing should be serialized. The toJSON method
+ will be passed the key associated with the value, and this will be
+ bound to the value
+
+ For example, this would serialize Dates as ISO strings.
+
+ Date.prototype.toJSON = function (key) {
+ function f(n) {
+ // Format integers to have at least two digits.
+ return n < 10 ? '0' + n : n;
+ }
+
+ return this.getUTCFullYear() + '-' +
+ f(this.getUTCMonth() + 1) + '-' +
+ f(this.getUTCDate()) + 'T' +
+ f(this.getUTCHours()) + ':' +
+ f(this.getUTCMinutes()) + ':' +
+ f(this.getUTCSeconds()) + 'Z';
+ };
+
+ You can provide an optional replacer method. It will be passed the
+ key and value of each member, with this bound to the containing
+ object. The value that is returned from your method will be
+ serialized. If your method returns undefined, then the member will
+ be excluded from the serialization.
+
+ If the replacer parameter is an array of strings, then it will be
+ used to select the members to be serialized. It filters the results
+ such that only members with keys listed in the replacer array are
+ stringified.
+
+ Values that do not have JSON representations, such as undefined or
+ functions, will not be serialized. Such values in objects will be
+ dropped; in arrays they will be replaced with null. You can use
+ a replacer function to replace those with JSON values.
+ JSON.stringify(undefined) returns undefined.
+
+ The optional space parameter produces a stringification of the
+ value that is filled with line breaks and indentation to make it
+ easier to read.
+
+ If the space parameter is a non-empty string, then that string will
+ be used for indentation. If the space parameter is a number, then
+ the indentation will be that many spaces.
+
+ Example:
+
+ text = JSON.stringify(['e', {pluribus: 'unum'}]);
+ // text is '["e",{"pluribus":"unum"}]'
+
+
+ text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t');
+ // text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]'
+
+ text = JSON.stringify([new Date()], function (key, value) {
+ return this[key] instanceof Date ?
+ 'Date(' + this[key] + ')' : value;
+ });
+ // text is '["Date(---current time---)"]'
+
+
+ JSON.parse(text, reviver)
+ This method parses a JSON text to produce an object or array.
+ It can throw a SyntaxError exception.
+
+ The optional reviver parameter is a function that can filter and
+ transform the results. It receives each of the keys and values,
+ and its return value is used instead of the original value.
+ If it returns what it received, then the structure is not modified.
+ If it returns undefined then the member is deleted.
+
+ Example:
+
+ // Parse the text. Values that look like ISO date strings will
+ // be converted to Date objects.
+
+ myData = JSON.parse(text, function (key, value) {
+ var a;
+ if (typeof value === 'string') {
+ a =
+/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value);
+ if (a) {
+ return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4],
+ +a[5], +a[6]));
+ }
+ }
+ return value;
+ });
+
+ myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) {
+ var d;
+ if (typeof value === 'string' &&
+ value.slice(0, 5) === 'Date(' &&
+ value.slice(-1) === ')') {
+ d = new Date(value.slice(5, -1));
+ if (d) {
+ return d;
+ }
+ }
+ return value;
+ });
+
+
+ This is a reference implementation. You are free to copy, modify, or
+ redistribute.
+*/
+
+/*jslint evil: true, regexp: true */
+
+/*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply,
+ call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours,
+ getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join,
+ lastIndex, length, parse, prototype, push, replace, slice, stringify,
+ test, toJSON, toString, valueOf
+*/
+
+
+// Create a JSON object only if one does not already exist. We create the
+// methods in a closure to avoid creating global variables.
+
+var JSON;
+if (!JSON) {
+ JSON = {};
+}
+
+(function () {
+ 'use strict';
+
+ function f(n) {
+ // Format integers to have at least two digits.
+ return n < 10 ? '0' + n : n;
+ }
+
+ if (typeof Date.prototype.toJSON !== 'function') {
+
+ Date.prototype.toJSON = function (key) {
+
+ return isFinite(this.valueOf())
+ ? this.getUTCFullYear() + '-' +
+ f(this.getUTCMonth() + 1) + '-' +
+ f(this.getUTCDate()) + 'T' +
+ f(this.getUTCHours()) + ':' +
+ f(this.getUTCMinutes()) + ':' +
+ f(this.getUTCSeconds()) + 'Z'
+ : null;
+ };
+
+ String.prototype.toJSON =
+ Number.prototype.toJSON =
+ Boolean.prototype.toJSON = function (key) {
+ return this.valueOf();
+ };
+ }
+
+ var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
+ escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
+ gap,
+ indent,
+ meta = { // table of character substitutions
+ '\b': '\\b',
+ '\t': '\\t',
+ '\n': '\\n',
+ '\f': '\\f',
+ '\r': '\\r',
+ '"' : '\\"',
+ '\\': '\\\\'
+ },
+ rep;
+
+
+ function quote(string) {
+
+// If the string contains no control characters, no quote characters, and no
+// backslash characters, then we can safely slap some quotes around it.
+// Otherwise we must also replace the offending characters with safe escape
+// sequences.
+
+ escapable.lastIndex = 0;
+ return escapable.test(string) ? '"' + string.replace(escapable, function (a) {
+ var c = meta[a];
+ return typeof c === 'string'
+ ? c
+ : '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
+ }) + '"' : '"' + string + '"';
+ }
+
+
+ function str(key, holder) {
+
+// Produce a string from holder[key].
+
+ var i, // The loop counter.
+ k, // The member key.
+ v, // The member value.
+ length,
+ mind = gap,
+ partial,
+ value = holder[key];
+
+// If the value has a toJSON method, call it to obtain a replacement value.
+
+ if (value && typeof value === 'object' &&
+ typeof value.toJSON === 'function') {
+ value = value.toJSON(key);
+ }
+
+// If we were called with a replacer function, then call the replacer to
+// obtain a replacement value.
+
+ if (typeof rep === 'function') {
+ value = rep.call(holder, key, value);
+ }
+
+// What happens next depends on the value's type.
+
+ switch (typeof value) {
+ case 'string':
+ return quote(value);
+
+ case 'number':
+
+// JSON numbers must be finite. Encode non-finite numbers as null.
+
+ return isFinite(value) ? String(value) : 'null';
+
+ case 'boolean':
+ case 'null':
+
+// If the value is a boolean or null, convert it to a string. Note:
+// typeof null does not produce 'null'. The case is included here in
+// the remote chance that this gets fixed someday.
+
+ return String(value);
+
+// If the type is 'object', we might be dealing with an object or an array or
+// null.
+
+ case 'object':
+
+// Due to a specification blunder in ECMAScript, typeof null is 'object',
+// so watch out for that case.
+
+ if (!value) {
+ return 'null';
+ }
+
+// Make an array to hold the partial results of stringifying this object value.
+
+ gap += indent;
+ partial = [];
+
+// Is the value an array?
+
+ if (Object.prototype.toString.apply(value) === '[object Array]') {
+
+// The value is an array. Stringify every element. Use null as a placeholder
+// for non-JSON values.
+
+ length = value.length;
+ for (i = 0; i < length; i += 1) {
+ partial[i] = str(i, value) || 'null';
+ }
+
+// Join all of the elements together, separated with commas, and wrap them in
+// brackets.
+
+ v = partial.length === 0
+ ? '[]'
+ : gap
+ ? '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']'
+ : '[' + partial.join(',') + ']';
+ gap = mind;
+ return v;
+ }
+
+// If the replacer is an array, use it to select the members to be stringified.
+
+ if (rep && typeof rep === 'object') {
+ length = rep.length;
+ for (i = 0; i < length; i += 1) {
+ if (typeof rep[i] === 'string') {
+ k = rep[i];
+ v = str(k, value);
+ if (v) {
+ partial.push(quote(k) + (gap ? ': ' : ':') + v);
+ }
+ }
+ }
+ } else {
+
+// Otherwise, iterate through all of the keys in the object.
+
+ for (k in value) {
+ if (Object.prototype.hasOwnProperty.call(value, k)) {
+ v = str(k, value);
+ if (v) {
+ partial.push(quote(k) + (gap ? ': ' : ':') + v);
+ }
+ }
+ }
+ }
+
+// Join all of the member texts together, separated with commas,
+// and wrap them in braces.
+
+ v = partial.length === 0
+ ? '{}'
+ : gap
+ ? '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}'
+ : '{' + partial.join(',') + '}';
+ gap = mind;
+ return v;
+ }
+ }
+
+// If the JSON object does not yet have a stringify method, give it one.
+
+ if (typeof JSON.stringify !== 'function') {
+ JSON.stringify = function (value, replacer, space) {
+
+// The stringify method takes a value and an optional replacer, and an optional
+// space parameter, and returns a JSON text. The replacer can be a function
+// that can replace values, or an array of strings that will select the keys.
+// A default replacer method can be provided. Use of the space parameter can
+// produce text that is more easily readable.
+
+ var i;
+ gap = '';
+ indent = '';
+
+// If the space parameter is a number, make an indent string containing that
+// many spaces.
+
+ if (typeof space === 'number') {
+ for (i = 0; i < space; i += 1) {
+ indent += ' ';
+ }
+
+// If the space parameter is a string, it will be used as the indent string.
+
+ } else if (typeof space === 'string') {
+ indent = space;
+ }
+
+// If there is a replacer, it must be a function or an array.
+// Otherwise, throw an error.
+
+ rep = replacer;
+ if (replacer && typeof replacer !== 'function' &&
+ (typeof replacer !== 'object' ||
+ typeof replacer.length !== 'number')) {
+ throw new Error('JSON.stringify');
+ }
+
+// Make a fake root object containing our value under the key of ''.
+// Return the result of stringifying the value.
+
+ return str('', {'': value});
+ };
+ }
+
+
+// If the JSON object does not yet have a parse method, give it one.
+
+ if (typeof JSON.parse !== 'function') {
+ JSON.parse = function (text, reviver) {
+
+// The parse method takes a text and an optional reviver function, and returns
+// a JavaScript value if the text is a valid JSON text.
+
+ var j;
+
+ function walk(holder, key) {
+
+// The walk method is used to recursively walk the resulting structure so
+// that modifications can be made.
+
+ var k, v, value = holder[key];
+ if (value && typeof value === 'object') {
+ for (k in value) {
+ if (Object.prototype.hasOwnProperty.call(value, k)) {
+ v = walk(value, k);
+ if (v !== undefined) {
+ value[k] = v;
+ } else {
+ delete value[k];
+ }
+ }
+ }
+ }
+ return reviver.call(holder, key, value);
+ }
+
+
+// Parsing happens in four stages. In the first stage, we replace certain
+// Unicode characters with escape sequences. JavaScript handles many characters
+// incorrectly, either silently deleting them, or treating them as line endings.
+
+ text = String(text);
+ cx.lastIndex = 0;
+ if (cx.test(text)) {
+ text = text.replace(cx, function (a) {
+ return '\\u' +
+ ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
+ });
+ }
+
+// In the second stage, we run the text against regular expressions that look
+// for non-JSON patterns. We are especially concerned with '()' and 'new'
+// because they can cause invocation, and '=' because it can cause mutation.
+// But just to be safe, we want to reject all unexpected forms.
+
+// We split the second stage into 4 regexp operations in order to work around
+// crippling inefficiencies in IE's and Safari's regexp engines. First we
+// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we
+// replace all simple value tokens with ']' characters. Third, we delete all
+// open brackets that follow a colon or comma or that begin the text. Finally,
+// we look to see that the remaining characters are only whitespace or ']' or
+// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.
+
+ if (/^[\],:{}\s]*$/
+ .test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@')
+ .replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']')
+ .replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
+
+// In the third stage we use the eval function to compile the text into a
+// JavaScript structure. The '{' operator is subject to a syntactic ambiguity
+// in JavaScript: it can begin a block or an object literal. We wrap the text
+// in parens to eliminate the ambiguity.
+
+ j = eval('(' + text + ')');
+
+// In the optional fourth stage, we recursively walk the new structure, passing
+// each name/value pair to a reviver function for possible transformation.
+
+ return typeof reviver === 'function'
+ ? walk({'': j}, '')
+ : j;
+ }
+
+// If the text is not JSON parseable, then a SyntaxError is thrown.
+
+ throw new SyntaxError('JSON.parse');
+ };
+ }
+}());
diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/ConfigFileHelper.java b/java/perftests/src/main/java/org/apache/qpid/disttest/ConfigFileHelper.java
new file mode 100644
index 0000000000..fb4c1b700b
--- /dev/null
+++ b/java/perftests/src/main/java/org/apache/qpid/disttest/ConfigFileHelper.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.disttest;
+
+import java.io.File;
+import java.io.FilenameFilter;
+import java.util.ArrayList;
+import java.util.List;
+
+public class ConfigFileHelper
+{
+ /**
+ * Returns absolute paths to the config file(s).
+ * <p/>
+ * If testConfigPath is a directory, its .js and .json files are returned.
+ * Otherwise, the returned list just contains testConfigPath.
+ */
+ public List<String> getTestConfigFiles(String testConfigPath)
+ {
+ final List<String> testConfigFile = new ArrayList<String>();
+ final File configFileOrDirectory = new File(testConfigPath);
+
+ if (configFileOrDirectory.isDirectory())
+ {
+ final String[] configFiles = configFileOrDirectory.list(new FilenameFilter()
+ {
+ @Override
+ public boolean accept(File dir, String name)
+ {
+ boolean suffixOk = name.endsWith(".json") || name.endsWith(".js");
+ return new File(dir, name).isFile() && suffixOk;
+ }
+ });
+
+ for (String configFile : configFiles)
+ {
+ testConfigFile.add(new File(configFileOrDirectory, configFile).getAbsolutePath());
+ }
+ }
+ else
+ {
+ testConfigFile.add(configFileOrDirectory.getAbsolutePath());
+ }
+
+ return testConfigFile;
+ }
+
+ /**
+ * generateOutputCsvNameFrom("/config/testConfigFile.js", "/output") returns /output/testConfigFile.csv
+ */
+ public String generateOutputCsvNameFrom(String testConfigFile, String outputDir)
+ {
+ final String filenameOnlyWithExtension = new File(testConfigFile).getName();
+ final String cvsFile = filenameOnlyWithExtension.replaceFirst(".?\\w*$", ".csv");
+
+ return new File(outputDir, cvsFile).getAbsolutePath();
+ }
+}
diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/ControllerRunner.java b/java/perftests/src/main/java/org/apache/qpid/disttest/ControllerRunner.java
index aa9c582bf8..aea0ea301a 100644
--- a/java/perftests/src/main/java/org/apache/qpid/disttest/ControllerRunner.java
+++ b/java/perftests/src/main/java/org/apache/qpid/disttest/ControllerRunner.java
@@ -19,13 +19,9 @@
*/
package org.apache.qpid.disttest;
-import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter;
-import java.io.FilenameFilter;
import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Arrays;
import java.util.List;
import javax.naming.Context;
@@ -54,6 +50,7 @@ public class ControllerRunner extends AbstractRunner
private final Aggregator _aggregator = new Aggregator();
+ private final ConfigFileHelper _configFileHelper = new ConfigFileHelper();
public ControllerRunner()
{
@@ -89,7 +86,8 @@ public class ControllerRunner extends AbstractRunner
{
Controller controller = new Controller(jmsDelegate, DistributedTestConstants.REGISTRATION_TIMEOUT, DistributedTestConstants.COMMAND_RESPONSE_TIMEOUT);
- final List<String> testConfigFiles = getTestConfigFiles();
+ String testConfigPath = getCliOptions().get(ControllerRunner.TEST_CONFIG_PROP);
+ List<String> testConfigFiles = _configFileHelper.getTestConfigFiles(testConfigPath);
createClientsIfNotDistributed(testConfigFiles);
try
@@ -105,11 +103,14 @@ public class ControllerRunner extends AbstractRunner
runTest(controller, testConfigFile);
}
}
+ catch(Exception e)
+ {
+ LOGGER.error("Problem running test", e);
+ }
finally
{
controller.stopAllRegisteredClients();
}
-
}
private void runTest(Controller controller, String testConfigFile)
@@ -120,7 +121,8 @@ public class ControllerRunner extends AbstractRunner
ResultsForAllTests rawResultsForAllTests = controller.runAllTests();
ResultsForAllTests resultsForAllTests = _aggregator.aggregateResults(rawResultsForAllTests);
- final String outputFile = generateOutputCsvNameFrom(testConfigFile);
+ String outputDir = getCliOptions().get(ControllerRunner.OUTPUT_DIR_PROP);
+ final String outputFile = _configFileHelper.generateOutputCsvNameFrom(testConfigFile, outputDir);
writeResultsToFile(resultsForAllTests, outputFile);
}
@@ -176,44 +178,6 @@ public class ControllerRunner extends AbstractRunner
}
}
- private String generateOutputCsvNameFrom(String testConfigFile)
- {
- final String filenameOnlyWithExtension = new File(testConfigFile).getName();
- final String cvsFile = filenameOnlyWithExtension.replaceFirst(".?\\w*$", ".csv");
- final String outputDir = String.valueOf(getCliOptions().get(ControllerRunner.OUTPUT_DIR_PROP));
-
- return new File(outputDir, cvsFile).getAbsolutePath();
- }
-
- private List<String> getTestConfigFiles()
- {
- final List<String> testConfigFile = new ArrayList<String>();
- final File configFileOrDirectory = new File(getCliOptions().get(ControllerRunner.TEST_CONFIG_PROP));
-
- if (configFileOrDirectory.isDirectory())
- {
- final String[] configFiles = configFileOrDirectory.list(new FilenameFilter()
- {
- @Override
- public boolean accept(File dir, String name)
- {
- return new File(dir, name).isFile() && name.endsWith(".json");
- }
- });
-
- for (String configFile : configFiles)
- {
- testConfigFile.add(new File(configFileOrDirectory, configFile).getAbsolutePath());
- }
- }
- else
- {
- testConfigFile.add(configFileOrDirectory.getAbsolutePath());
- }
-
- return testConfigFile;
- }
-
private Config buildTestConfigFrom(String testConfigFile)
{
ConfigReader configReader = new ConfigReader();
diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/DistributedTestConstants.java b/java/perftests/src/main/java/org/apache/qpid/disttest/DistributedTestConstants.java
index c4892edca9..a6f872e841 100644
--- a/java/perftests/src/main/java/org/apache/qpid/disttest/DistributedTestConstants.java
+++ b/java/perftests/src/main/java/org/apache/qpid/disttest/DistributedTestConstants.java
@@ -26,8 +26,10 @@ public abstract class DistributedTestConstants
public static final String MSG_COMMAND_PROPERTY = "COMMAND";
public static final String MSG_JSON_PROPERTY = "JSON";
- public static final long REGISTRATION_TIMEOUT = 60000;
- public static final long COMMAND_RESPONSE_TIMEOUT = 10000;
+ public static final long REGISTRATION_TIMEOUT = 60 * 1000;
+
+ /** set to a long time out because stopping clients can take a long time */
+ public static final long COMMAND_RESPONSE_TIMEOUT = 120 * 1000;
public static final String CONTROLLER_QUEUE_JNDI_NAME = "controllerqueue";
}
diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/client/Client.java b/java/perftests/src/main/java/org/apache/qpid/disttest/client/Client.java
index 1d2d862301..0d5457c992 100644
--- a/java/perftests/src/main/java/org/apache/qpid/disttest/client/Client.java
+++ b/java/perftests/src/main/java/org/apache/qpid/disttest/client/Client.java
@@ -103,9 +103,9 @@ public class Client
public void processInstruction(final Command command)
{
- if (LOGGER.isInfoEnabled())
+ if (LOGGER.isDebugEnabled())
{
- LOGGER.info("Client " + getClientName() + " received command: " + command);
+ LOGGER.debug("Client " + getClientName() + " received command: " + command);
}
String responseMessage = null;
try
@@ -174,9 +174,9 @@ public class Client
{
if (_state.compareAndSet(ClientState.RUNNING_TEST, ClientState.READY))
{
- LOGGER.info("Tearing down test on client: " + _clientJmsDelegate.getClientName());
+ LOGGER.debug("Tearing down test on client: " + _clientJmsDelegate.getClientName());
- _clientJmsDelegate.closeTestConnections();
+ _clientJmsDelegate.tearDownTest();
}
else
{
@@ -190,7 +190,7 @@ public class Client
public void sendResults(ParticipantResult testResult)
{
_clientJmsDelegate.sendResponseMessage(testResult);
- LOGGER.info("Sent test results " + testResult);
+ LOGGER.debug("Sent test results " + testResult);
}
@Override
diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/client/ConsumerParticipant.java b/java/perftests/src/main/java/org/apache/qpid/disttest/client/ConsumerParticipant.java
index 1b5e8276c2..f9d50e8e64 100644
--- a/java/perftests/src/main/java/org/apache/qpid/disttest/client/ConsumerParticipant.java
+++ b/java/perftests/src/main/java/org/apache/qpid/disttest/client/ConsumerParticipant.java
@@ -20,13 +20,16 @@
package org.apache.qpid.disttest.client;
+import java.util.ArrayList;
import java.util.Date;
+import java.util.List;
import java.util.NavigableSet;
import java.util.concurrent.ConcurrentSkipListSet;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
+import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
@@ -53,12 +56,17 @@ public class ConsumerParticipant implements Participant
private long _startTime;
private volatile Exception _asyncMessageListenerException;
+ private List<Long> _messageLatencies;
public ConsumerParticipant(final ClientJmsDelegate delegate, final CreateConsumerCommand command)
{
_jmsDelegate = delegate;
_command = command;
_resultFactory = new ParticipantResultFactory();
+ if (command.isEvaluateLatency())
+ {
+ _messageLatencies = new ArrayList<Long>();
+ }
}
@Override
@@ -78,6 +86,8 @@ public class ConsumerParticipant implements Participant
}
else
{
+ LOGGER.info("Consumer {} registering listener", getName());
+
_jmsDelegate.registerListener(_command.getParticipantName(), new MessageListener(){
@Override
@@ -105,14 +115,14 @@ public class ConsumerParticipant implements Participant
numberOfMessagesSent,
payloadSize,
totalPayloadSize,
- start, end);
+ start, end, _messageLatencies);
return result;
}
private void synchronousRun()
{
- LOGGER.debug("entered synchronousRun: " + this);
+ LOGGER.info("Consumer {} about to consume messages", getName());
_startTime = System.currentTimeMillis();
@@ -130,25 +140,42 @@ public class ConsumerParticipant implements Participant
*/
private boolean processMessage(Message message)
{
- int messageCount = _totalNumberOfMessagesReceived.incrementAndGet();
- if (LOGGER.isTraceEnabled())
- {
- LOGGER.trace("message " + messageCount + " received by " + this);
- }
- int messagePayloadSize = _jmsDelegate.calculatePayloadSizeFrom(message);
- _allConsumedPayloadSizes.add(messagePayloadSize);
- _totalPayloadSizeOfAllMessagesReceived.addAndGet(messagePayloadSize);
-
+ int messageCount = message == null? _totalNumberOfMessagesReceived.get() : _totalNumberOfMessagesReceived.incrementAndGet() ;
boolean batchEnabled = _command.getBatchSize() > 0;
boolean batchComplete = batchEnabled && messageCount % _command.getBatchSize() == 0;
-
- if (!batchEnabled || batchComplete)
+ if (message != null)
{
- if (LOGGER.isTraceEnabled() && batchEnabled)
+ if (LOGGER.isTraceEnabled())
{
- LOGGER.trace("Committing: batch size " + _command.getBatchSize() );
+ LOGGER.trace("message " + messageCount + " received by " + this);
+ }
+ int messagePayloadSize = _jmsDelegate.calculatePayloadSizeFrom(message);
+ _allConsumedPayloadSizes.add(messagePayloadSize);
+ _totalPayloadSizeOfAllMessagesReceived.addAndGet(messagePayloadSize);
+
+ if (_command.isEvaluateLatency())
+ {
+ long mesageTimestamp;
+ try
+ {
+ mesageTimestamp = message.getJMSTimestamp();
+ }
+ catch (JMSException e)
+ {
+ throw new DistributedTestException("Cannot get message timestamp!", e);
+ }
+ long latency = System.currentTimeMillis() - mesageTimestamp;
+ _messageLatencies.add(latency);
+ }
+
+ if (!batchEnabled || batchComplete)
+ {
+ if (LOGGER.isTraceEnabled() && batchEnabled)
+ {
+ LOGGER.trace("Committing: batch size " + _command.getBatchSize() );
+ }
+ _jmsDelegate.commitOrAcknowledgeMessage(message, _command.getSessionName());
}
- _jmsDelegate.commitOrAcknowledgeMessage(message, _command.getSessionName());
}
boolean reachedExpectedNumberOfMessages = _command.getNumberOfMessages() > 0 && messageCount >= _command.getNumberOfMessages();
diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/client/MessageProvider.java b/java/perftests/src/main/java/org/apache/qpid/disttest/client/MessageProvider.java
index 2dcf8940b6..6af1e1316a 100644
--- a/java/perftests/src/main/java/org/apache/qpid/disttest/client/MessageProvider.java
+++ b/java/perftests/src/main/java/org/apache/qpid/disttest/client/MessageProvider.java
@@ -169,8 +169,14 @@ public class MessageProvider
protected Message createTextMessage(Session ssn, final CreateProducerCommand command) throws JMSException
{
String payload = getMessagePayload(command);
- TextMessage msg = ssn.createTextMessage();
+
+ TextMessage msg = null;
+ synchronized(ssn)
+ {
+ msg = ssn.createTextMessage();
+ }
msg.setText(payload);
+
return msg;
}
diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/client/ParticipantExecutor.java b/java/perftests/src/main/java/org/apache/qpid/disttest/client/ParticipantExecutor.java
index d5e307d50f..bb9ce26f7e 100644
--- a/java/perftests/src/main/java/org/apache/qpid/disttest/client/ParticipantExecutor.java
+++ b/java/perftests/src/main/java/org/apache/qpid/disttest/client/ParticipantExecutor.java
@@ -56,7 +56,7 @@ public class ParticipantExecutor
{
_client = client;
- LOGGER.info("Starting test participant in background thread: " + this);
+ LOGGER.debug("Starting test participant in background thread: " + this);
_executor.execute(new ParticipantRunnable());
}
@@ -94,9 +94,9 @@ public class ParticipantExecutor
ParticipantResult result = null;
try
{
- if (LOGGER.isInfoEnabled())
+ if (LOGGER.isDebugEnabled())
{
- LOGGER.info("About to run participant " + _participant);
+ LOGGER.debug("About to run participant " + _participant);
}
result = _participant.doIt(_client.getClientName());
}
diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/client/ParticipantResultFactory.java b/java/perftests/src/main/java/org/apache/qpid/disttest/client/ParticipantResultFactory.java
index 7f6b96b87c..50c0a74ccd 100644
--- a/java/perftests/src/main/java/org/apache/qpid/disttest/client/ParticipantResultFactory.java
+++ b/java/perftests/src/main/java/org/apache/qpid/disttest/client/ParticipantResultFactory.java
@@ -18,6 +18,7 @@
*/
package org.apache.qpid.disttest.client;
+import java.util.Collection;
import java.util.Date;
import org.apache.qpid.disttest.message.ConsumerParticipantResult;
@@ -26,12 +27,24 @@ import org.apache.qpid.disttest.message.CreateParticpantCommand;
import org.apache.qpid.disttest.message.CreateProducerCommand;
import org.apache.qpid.disttest.message.ParticipantResult;
import org.apache.qpid.disttest.message.ProducerParticipantResult;
+import org.apache.qpid.disttest.results.aggregation.SeriesStatistics;
public class ParticipantResultFactory
{
- public ConsumerParticipantResult createForConsumer(String participantName, String clientRegisteredName, CreateConsumerCommand command, int acknowledgeMode, int numberOfMessagesReceived, int payloadSize, long totalPayloadReceived, Date start, Date end)
+ public ConsumerParticipantResult createForConsumer(String participantName, String clientRegisteredName,
+ CreateConsumerCommand command, int acknowledgeMode, int numberOfMessagesReceived, int payloadSize,
+ long totalPayloadReceived, Date start, Date end)
+ {
+ return createForConsumer(participantName, clientRegisteredName, command, acknowledgeMode, numberOfMessagesReceived,
+ payloadSize, totalPayloadReceived, start, end, null);
+ }
+
+ public ConsumerParticipantResult createForConsumer(String participantName, String clientRegisteredName,
+ CreateConsumerCommand command, int acknowledgeMode, int numberOfMessagesReceived, int payloadSize,
+ long totalPayloadReceived, Date start, Date end, Collection<Long> messageLatencies)
{
ConsumerParticipantResult consumerParticipantResult = new ConsumerParticipantResult();
+ consumerParticipantResult.setMessageLatencies(messageLatencies);
setTestProperties(consumerParticipantResult, command, participantName, clientRegisteredName, acknowledgeMode);
setTestResultProperties(consumerParticipantResult, numberOfMessagesReceived, payloadSize, totalPayloadReceived, start, end);
@@ -45,6 +58,11 @@ public class ParticipantResultFactory
consumerParticipantResult.setTotalNumberOfConsumers(1);
consumerParticipantResult.setTotalNumberOfProducers(0);
+ SeriesStatistics statistics = new SeriesStatistics(messageLatencies);
+ consumerParticipantResult.setAverageLatency(statistics.getAverage());
+ consumerParticipantResult.setMinLatency(statistics.getMinimum());
+ consumerParticipantResult.setMaxLatency(statistics.getMaximum());
+ consumerParticipantResult.setLatencyStandardDeviation(statistics.getStandardDeviation());
return consumerParticipantResult;
}
diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/client/ProducerParticipant.java b/java/perftests/src/main/java/org/apache/qpid/disttest/client/ProducerParticipant.java
index bcad81b4aa..63cbe98b5c 100644
--- a/java/perftests/src/main/java/org/apache/qpid/disttest/client/ProducerParticipant.java
+++ b/java/perftests/src/main/java/org/apache/qpid/disttest/client/ProducerParticipant.java
@@ -22,10 +22,14 @@ package org.apache.qpid.disttest.client;
import java.util.Date;
import java.util.NavigableSet;
import java.util.TreeSet;
+import java.util.concurrent.Callable;
+import java.util.concurrent.CancellationException;
import javax.jms.Message;
import org.apache.qpid.disttest.DistributedTestException;
+import org.apache.qpid.disttest.client.utils.ExecutorWithLimits;
+import org.apache.qpid.disttest.client.utils.ExecutorWithLimitsFactory;
import org.apache.qpid.disttest.jms.ClientJmsDelegate;
import org.apache.qpid.disttest.message.CreateProducerCommand;
import org.apache.qpid.disttest.message.ParticipantResult;
@@ -40,7 +44,9 @@ public class ProducerParticipant implements Participant
private final CreateProducerCommand _command;
- private ParticipantResultFactory _resultFactory;
+ private final ParticipantResultFactory _resultFactory;
+
+ private ExecutorWithLimits _limiter;
public ProducerParticipant(final ClientJmsDelegate jmsDelegate, final CreateProducerCommand command)
{
@@ -59,10 +65,10 @@ public class ProducerParticipant implements Participant
int acknowledgeMode = _jmsDelegate.getAcknowledgeMode(_command.getSessionName());
- long expectedDuration = _command.getMaximumDuration() - _command.getStartDelay();
-
doSleepForStartDelay();
+ final long requiredDuration = _command.getMaximumDuration() - _command.getStartDelay();
+
final long startTime = System.currentTimeMillis();
Message lastPublishedMessage = null;
@@ -70,11 +76,30 @@ public class ProducerParticipant implements Participant
long totalPayloadSizeOfAllMessagesSent = 0;
NavigableSet<Integer> allProducedPayloadSizes = new TreeSet<Integer>();
+ _limiter = ExecutorWithLimitsFactory.createExecutorWithLimit(startTime, requiredDuration);
+
+ LOGGER.info("Producer {} about to send messages", getName());
+
while (true)
{
- numberOfMessagesSent++;
+ try
+ {
+ lastPublishedMessage = _limiter.execute(new Callable<Message>()
+ {
+ @Override
+ public Message call() throws Exception
+ {
+ return _jmsDelegate.sendNextMessage(_command);
+ }
+ });
+ }
+ catch (CancellationException ce)
+ {
+ LOGGER.debug("Producer send was cancelled due to maximum duration {} ms", requiredDuration);
+ break;
+ }
- lastPublishedMessage = _jmsDelegate.sendNextMessage(_command);
+ numberOfMessagesSent++;
int lastPayloadSize = _jmsDelegate.calculatePayloadSizeFrom(lastPublishedMessage);
totalPayloadSizeOfAllMessagesSent += lastPayloadSize;
@@ -96,15 +121,11 @@ public class ProducerParticipant implements Participant
}
_jmsDelegate.commitOrAcknowledgeMessage(lastPublishedMessage, _command.getSessionName());
- if (_command.getInterval() > 0)
- {
- // sleep for given time
- Thread.sleep(_command.getInterval());
- }
+ doSleepForInterval();
}
if (_command.getNumberOfMessages() > 0 && numberOfMessagesSent >= _command.getNumberOfMessages()
- || expectedDuration > 0 && System.currentTimeMillis() - startTime >= expectedDuration)
+ || requiredDuration > 0 && System.currentTimeMillis() - startTime >= requiredDuration)
{
break;
}
@@ -140,23 +161,43 @@ public class ProducerParticipant implements Participant
private void doSleepForStartDelay()
{
- if (_command.getStartDelay() > 0)
+ long sleepTime = _command.getStartDelay();
+ if (sleepTime > 0)
{
+ LOGGER.debug("{} sleeping for {} milliseconds before starting", getName(), sleepTime);
// start delay is specified. Sleeping...
- try
- {
- Thread.sleep(_command.getStartDelay());
- }
- catch (final InterruptedException e)
- {
- Thread.currentThread().interrupt();
- }
+ doSleep(sleepTime);
+ }
+ }
+
+ private void doSleepForInterval() throws InterruptedException
+ {
+ long sleepTime = _command.getInterval();
+ if (sleepTime > 0)
+ {
+ doSleep(sleepTime);
+ }
+ }
+
+ private void doSleep(long sleepTime)
+ {
+ try
+ {
+ Thread.sleep(sleepTime);
+ }
+ catch (final InterruptedException e)
+ {
+ Thread.currentThread().interrupt();
}
}
@Override
public void releaseResources()
{
+ if (_limiter != null)
+ {
+ _limiter.shutdown();
+ }
_jmsDelegate.closeTestProducer(_command.getParticipantName());
}
@@ -171,4 +212,5 @@ public class ProducerParticipant implements Participant
{
return "ProducerParticipant [command=" + _command + "]";
}
+
}
diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ManagedObject.java b/java/perftests/src/main/java/org/apache/qpid/disttest/client/utils/ExecutorWithLimits.java
index 96e0fa46c6..f64107c125 100644
--- a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ManagedObject.java
+++ b/java/perftests/src/main/java/org/apache/qpid/disttest/client/utils/ExecutorWithLimits.java
@@ -1,5 +1,4 @@
/*
- *
* Licensed 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,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
@@ -18,23 +17,19 @@
* under the License.
*
*/
-package org.apache.qpid.management.ui;
+package org.apache.qpid.disttest.client.utils;
+
+import java.util.concurrent.Callable;
+import java.util.concurrent.CancellationException;
/**
- * Abstract class representing a managed object
- * @author Bhupendra Bhardwaj
+ * Implementations of this interface execute a {@link Callable} but place some
+ * kind of limit on that execution, such as time.
*/
-public abstract class ManagedObject
+public interface ExecutorWithLimits
{
- private String _name;
+ <T> T execute(Callable<T> callback) throws CancellationException, Exception;
- public String getName()
- {
- return _name;
- }
+ void shutdown();
- public void setName(String name)
- {
- this._name = name;
- }
}
diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/client/utils/ExecutorWithLimitsFactory.java b/java/perftests/src/main/java/org/apache/qpid/disttest/client/utils/ExecutorWithLimitsFactory.java
new file mode 100644
index 0000000000..4d17d76568
--- /dev/null
+++ b/java/perftests/src/main/java/org/apache/qpid/disttest/client/utils/ExecutorWithLimitsFactory.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.disttest.client.utils;
+
+import java.util.concurrent.Callable;
+
+public class ExecutorWithLimitsFactory
+{
+ /**
+ * Creates an {@link ExecutorWithLimits} that will permit the execution of {@link Callable} implementations until
+ * until <code>allowedTimeInMillis</code> milliseconds have elapsed beyond <code>startTime</code>.
+ * If <code>allowedTimeInMillis</code> is less than or equal to zero, a {@link ExecutorWithNoLimits}
+ * is created that enforces no time-limit.
+ *
+ * @param startTime start time (milliseconds)
+ * @param allowedTimeInMillis allowed time (milliseconds)
+ *
+ * @return ExecutionLimiter implementation
+ */
+ public static ExecutorWithLimits createExecutorWithLimit(long startTime, long allowedTimeInMillis)
+ {
+ if (allowedTimeInMillis > 0)
+ {
+ return new ExecutorWithTimeLimit(startTime, allowedTimeInMillis);
+ }
+ else
+ {
+ return new ExecutorWithNoLimits();
+ }
+ }
+
+}
diff --git a/java/broker/src/test/java/org/apache/qpid/server/store/TestableMemoryMessageStoreFactory.java b/java/perftests/src/main/java/org/apache/qpid/disttest/client/utils/ExecutorWithNoLimits.java
index 44070f22ad..f729a72fa5 100644
--- a/java/broker/src/test/java/org/apache/qpid/server/store/TestableMemoryMessageStoreFactory.java
+++ b/java/perftests/src/main/java/org/apache/qpid/disttest/client/utils/ExecutorWithNoLimits.java
@@ -17,21 +17,26 @@
* under the License.
*
*/
-package org.apache.qpid.server.store;
+package org.apache.qpid.disttest.client.utils;
-public class TestableMemoryMessageStoreFactory implements MessageStoreFactory
+import java.util.concurrent.Callable;
+
+/**
+ * Executes a {@link Callable} without any limits.
+ */
+public class ExecutorWithNoLimits implements ExecutorWithLimits
{
@Override
- public MessageStore createMessageStore()
+ public <T> T execute(Callable<T> _callback) throws Exception
{
- return new TestableMemoryMessageStore();
+ return _callback.call();
}
@Override
- public String getStoreClassName()
+ public void shutdown()
{
- return TestableMemoryMessageStore.class.getSimpleName();
+ // Deliberately blank
}
}
diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/client/utils/ExecutorWithTimeLimit.java b/java/perftests/src/main/java/org/apache/qpid/disttest/client/utils/ExecutorWithTimeLimit.java
new file mode 100644
index 0000000000..4fa3960d92
--- /dev/null
+++ b/java/perftests/src/main/java/org/apache/qpid/disttest/client/utils/ExecutorWithTimeLimit.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.disttest.client.utils;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Executes a {@link Callable} but limits the execution time. If the execution
+ * time is exceeded the callable will be cancelled.
+ */
+public class ExecutorWithTimeLimit implements ExecutorWithLimits
+{
+ private final long _endTime;
+ private final ExecutorService _singleThreadExecutor = Executors.newSingleThreadExecutor();
+
+ public ExecutorWithTimeLimit(long startTime, long allowedTimeInMillis)
+ {
+ _endTime = startTime + allowedTimeInMillis;
+ }
+
+ @Override
+ public <T> T execute(Callable<T> callback) throws CancellationException, Exception
+ {
+ final long timeRemaining = _endTime - System.currentTimeMillis();
+ if (timeRemaining <= 0)
+ {
+ throw new CancellationException("Too little time remains to schedule callable");
+ }
+
+ List<Future<T>> l = _singleThreadExecutor.invokeAll(Collections.singletonList(callback), timeRemaining, TimeUnit.MILLISECONDS);
+ return l.get(0).get();
+ }
+
+ @Override
+ public void shutdown()
+ {
+ _singleThreadExecutor.shutdown();
+ }
+
+
+}
diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/controller/Controller.java b/java/perftests/src/main/java/org/apache/qpid/disttest/controller/Controller.java
index 7c935065f0..513e633566 100644
--- a/java/perftests/src/main/java/org/apache/qpid/disttest/controller/Controller.java
+++ b/java/perftests/src/main/java/org/apache/qpid/disttest/controller/Controller.java
@@ -92,15 +92,18 @@ public class Controller
}
}
- private void awaitLatch(CountDownLatch latch, long timeout, String messageWithOneDecimalPlaceholder)
+ private void awaitStopResponses(CountDownLatch latch, long timeout)
{
+ String message = "Timed out after %d waiting for stop command responses. Expecting %d more responses.";
+
try
{
- final boolean countedDownOK = latch.await(timeout, TimeUnit.MILLISECONDS);
+ boolean countedDownOK = latch.await(timeout, TimeUnit.MILLISECONDS);
if (!countedDownOK)
{
- final long latchCount = latch.getCount();
- String formattedMessage = String.format(messageWithOneDecimalPlaceholder, latchCount);
+ long latchCount = latch.getCount();
+ String formattedMessage = String.format(message, timeout, latchCount);
+ LOGGER.error(formattedMessage);
throw new DistributedTestException(formattedMessage);
}
}
@@ -141,7 +144,7 @@ public class Controller
_jmsDelegate.sendCommandToClient(clientName, command);
}
- awaitLatch(_stopClientsResponseLatch, _commandResponseTimeout, "Timed out waiting for stop command responses. Expecting %d more responses.");
+ awaitStopResponses(_stopClientsResponseLatch, _commandResponseTimeout);
LOGGER.info("Stopped all clients");
}
diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/controller/TestRunner.java b/java/perftests/src/main/java/org/apache/qpid/disttest/controller/TestRunner.java
index 30595269b3..e973f07c12 100644
--- a/java/perftests/src/main/java/org/apache/qpid/disttest/controller/TestRunner.java
+++ b/java/perftests/src/main/java/org/apache/qpid/disttest/controller/TestRunner.java
@@ -104,6 +104,11 @@ public class TestRunner
return _testResult;
}
+ catch(RuntimeException e)
+ {
+ LOGGER.error("Couldn't run test", e);
+ throw e;
+ }
finally
{
_jmsDelegate.removeCommandListener(participantResultListener);
@@ -140,7 +145,6 @@ public class TestRunner
}
Runtime.getRuntime().removeShutdownHook(_removeQueuesShutdownHook);
-
}
}
@@ -176,7 +180,7 @@ public class TestRunner
void awaitCommandResponses()
{
- awaitLatch(_commandResponseLatch, _commandResponseTimeout, "Timed out waiting for command responses. Expecting %d more responses.");
+ awaitLatch(_commandResponseLatch, _commandResponseTimeout, "Timed out waiting for command responses");
}
@@ -204,7 +208,7 @@ public class TestRunner
{
try
{
- awaitLatch(_testResultsLatch, interval, "Waiting for participant results... Expecting %d more responses.");
+ awaitLatch(_testResultsLatch, interval, "still waiting for participant results");
}
catch (DistributedTestException e)
{
@@ -253,7 +257,7 @@ public class TestRunner
setOriginalTestDetailsOn(result);
_testResult.addParticipantResult(result);
- LOGGER.info("Received result " + result);
+ LOGGER.debug("Received result " + result);
_testResultsLatch.countDown();
checkForResponseError(result);
@@ -276,7 +280,7 @@ public class TestRunner
_jmsDelegate.sendCommandToClient(registeredClientName, command);
}
- private void awaitLatch(CountDownLatch latch, long timeout, String messageWithOneDecimalPlaceholder)
+ private void awaitLatch(CountDownLatch latch, long timeout, String message)
{
try
{
@@ -284,7 +288,8 @@ public class TestRunner
if (!countedDownOK)
{
final long latchCount = latch.getCount();
- String formattedMessage = String.format(messageWithOneDecimalPlaceholder, latchCount);
+ String formattedMessage = "After " + timeout + "ms ... " + message + " ... Expecting " + latchCount + " more responses.";
+ LOGGER.info(formattedMessage); // info rather than error because we time out periodically so we can log progress
throw new DistributedTestException(formattedMessage);
}
}
diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/controller/config/ConfigReader.java b/java/perftests/src/main/java/org/apache/qpid/disttest/controller/config/ConfigReader.java
index 6288b42eac..bd7d239a90 100644
--- a/java/perftests/src/main/java/org/apache/qpid/disttest/controller/config/ConfigReader.java
+++ b/java/perftests/src/main/java/org/apache/qpid/disttest/controller/config/ConfigReader.java
@@ -22,24 +22,44 @@ package org.apache.qpid.disttest.controller.config;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.Reader;
+import java.io.StringReader;
import org.apache.qpid.disttest.client.property.PropertyValue;
import org.apache.qpid.disttest.json.PropertyValueAdapter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
public class ConfigReader
{
+ private static final Logger LOGGER = LoggerFactory.getLogger(ConfigReader.class);
public Config getConfigFromFile(String fileName) throws FileNotFoundException
{
- FileReader reader = new FileReader(fileName);
+ Reader reader = getConfigReader(fileName);
Config config = readConfig(reader);
return config;
}
+ protected Reader getConfigReader(String fileName) throws FileNotFoundException
+ {
+ Reader reader = null;
+ if (fileName.endsWith(".js"))
+ {
+ LOGGER.info("Evaluating javascript:" + fileName);
+ reader = new StringReader(new JavaScriptConfigEvaluator().evaluateJavaScript(fileName));
+ }
+ else
+ {
+ LOGGER.info("Loading JSON:" + fileName);
+ reader = new FileReader(fileName);
+ }
+ return reader;
+ }
+
public Config readConfig(Reader reader)
{
Gson gson = new GsonBuilder()
diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/controller/config/ConsumerConfig.java b/java/perftests/src/main/java/org/apache/qpid/disttest/controller/config/ConsumerConfig.java
index ed47e02667..110de8a4ea 100644
--- a/java/perftests/src/main/java/org/apache/qpid/disttest/controller/config/ConsumerConfig.java
+++ b/java/perftests/src/main/java/org/apache/qpid/disttest/controller/config/ConsumerConfig.java
@@ -1,3 +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.
+ *
+ */
package org.apache.qpid.disttest.controller.config;
import org.apache.qpid.disttest.message.CreateConsumerCommand;
@@ -10,6 +30,7 @@ public class ConsumerConfig extends ParticipantConfig
private String _selector;
private boolean _noLocal;
private boolean _synchronous;
+ private boolean _evaluateLatency;
// For Gson
public ConsumerConfig()
@@ -58,6 +79,7 @@ public class ConsumerConfig extends ParticipantConfig
createConsumerCommand.setSelector(_selector);
createConsumerCommand.setNoLocal(_noLocal);
createConsumerCommand.setSynchronous(_synchronous);
+ createConsumerCommand.setEvaluateLatency(_evaluateLatency);
return createConsumerCommand;
}
diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/controller/config/JavaScriptConfigEvaluator.java b/java/perftests/src/main/java/org/apache/qpid/disttest/controller/config/JavaScriptConfigEvaluator.java
new file mode 100644
index 0000000000..bbc22af00f
--- /dev/null
+++ b/java/perftests/src/main/java/org/apache/qpid/disttest/controller/config/JavaScriptConfigEvaluator.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.disttest.controller.config;
+
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.InputStreamReader;
+
+import javax.script.ScriptEngine;
+import javax.script.ScriptEngineManager;
+import javax.script.ScriptException;
+
+import org.apache.qpid.disttest.DistributedTestException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * A helper class to load and evaluate JavaScript configuration, producing a JSON string.
+ */
+public class JavaScriptConfigEvaluator
+{
+ private static final Logger LOGGER = LoggerFactory.getLogger(JavaScriptConfigEvaluator.class);
+
+ public static final String TEST_CONFIG_VARIABLE_NAME = "jsonObject";
+
+ public String evaluateJavaScript(String fileName) throws FileNotFoundException
+ {
+ ScriptEngineManager mgr = new ScriptEngineManager();
+ ScriptEngine engine = mgr.getEngineByName("JavaScript");
+ try
+ {
+ engine.eval(new InputStreamReader(getClass().getClassLoader().getResourceAsStream("json2.js")));
+ engine.eval(new InputStreamReader(getClass().getClassLoader().getResourceAsStream("test-utils.js")));
+ engine.eval(new FileReader(fileName));
+ engine.eval("jsonString = JSON.stringify(" + TEST_CONFIG_VARIABLE_NAME + ")");
+ }
+ catch (ScriptException e)
+ {
+ throw new DistributedTestException("Exception while evaluating test config", e);
+ }
+ String result = (String) engine.get("jsonString");
+
+ LOGGER.debug("Evaluated javascript file " + fileName + ". Generated the following JSON: " + result);
+ return result;
+ }
+}
diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/controller/config/ParticipantConfig.java b/java/perftests/src/main/java/org/apache/qpid/disttest/controller/config/ParticipantConfig.java
index 31037a3038..16f7b0d18d 100644
--- a/java/perftests/src/main/java/org/apache/qpid/disttest/controller/config/ParticipantConfig.java
+++ b/java/perftests/src/main/java/org/apache/qpid/disttest/controller/config/ParticipantConfig.java
@@ -18,10 +18,20 @@
*/
package org.apache.qpid.disttest.controller.config;
+import org.apache.commons.lang.ObjectUtils;
import org.apache.qpid.disttest.message.CreateParticpantCommand;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
public abstract class ParticipantConfig
{
+ private static final Logger LOGGER = LoggerFactory.getLogger(ParticipantConfig.class);
+
+ public static final String DURATION_OVERRIDE_SYSTEM_PROPERTY = "qpid.disttest.duration";
+
+ /** used to ensure we only log about the overridden duration once */
+ private boolean _alreadyLoggedAboutOverriddenDuration;
+
private String _destinationName;
private long _numberOfMessages;
private String _name;
@@ -58,7 +68,34 @@ public abstract class ParticipantConfig
createParticipantCommand.setDestinationName(_destinationName);
createParticipantCommand.setNumberOfMessages(_numberOfMessages);
createParticipantCommand.setBatchSize(_batchSize);
- createParticipantCommand.setMaximumDuration(_maximumDuration);
+
+ Long maximumDuration = (Long)ObjectUtils.defaultIfNull(getOverriddenDuration(), _maximumDuration);
+ createParticipantCommand.setMaximumDuration(maximumDuration);
}
+ private Long getOverriddenDuration()
+ {
+ String overriddenDurationString = System.getProperty(DURATION_OVERRIDE_SYSTEM_PROPERTY);
+ if(overriddenDurationString != null)
+ {
+ try
+ {
+ long overriddenDuration = Long.valueOf(overriddenDurationString);
+
+ if(!_alreadyLoggedAboutOverriddenDuration)
+ {
+ LOGGER.info("Applied overridden maximum duration " + overriddenDuration);
+ _alreadyLoggedAboutOverriddenDuration = true;
+ }
+
+ return overriddenDuration;
+ }
+ catch (NumberFormatException e)
+ {
+ LOGGER.error("Couldn't parse overridden duration " + overriddenDurationString, e);
+ }
+ }
+
+ return null;
+ }
} \ No newline at end of file
diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/controller/config/ProducerConfig.java b/java/perftests/src/main/java/org/apache/qpid/disttest/controller/config/ProducerConfig.java
index 7806528a8c..f2369ed671 100644
--- a/java/perftests/src/main/java/org/apache/qpid/disttest/controller/config/ProducerConfig.java
+++ b/java/perftests/src/main/java/org/apache/qpid/disttest/controller/config/ProducerConfig.java
@@ -37,7 +37,7 @@ public class ProducerConfig extends ParticipantConfig
public ProducerConfig()
{
_deliveryMode = Message.DEFAULT_DELIVERY_MODE;
- _messageSize = 0;
+ _messageSize = 1024;
_priority = Message.DEFAULT_PRIORITY;
_timeToLive = Message.DEFAULT_TIME_TO_LIVE;
_interval = 0;
diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/controller/config/QueueConfig.java b/java/perftests/src/main/java/org/apache/qpid/disttest/controller/config/QueueConfig.java
index cffc2b7c50..45a4551cbc 100644
--- a/java/perftests/src/main/java/org/apache/qpid/disttest/controller/config/QueueConfig.java
+++ b/java/perftests/src/main/java/org/apache/qpid/disttest/controller/config/QueueConfig.java
@@ -38,7 +38,6 @@ public class QueueConfig
public QueueConfig(String name, boolean durable, Map<String, Object> attributes)
{
- super();
this._name = name;
this._durable = durable;
this._attributes = attributes;
@@ -49,8 +48,6 @@ public class QueueConfig
return _name;
}
- // TODO x-qpid-capacity and x-qpid-flow-resume-capacity need to be typed as numeric but we currrently
- // pass these as a string.
public Map<String, Object> getAttributes()
{
return _attributes;
diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/jms/ClientJmsDelegate.java b/java/perftests/src/main/java/org/apache/qpid/disttest/jms/ClientJmsDelegate.java
index d68fc86a0e..3f8afc9a9a 100644
--- a/java/perftests/src/main/java/org/apache/qpid/disttest/jms/ClientJmsDelegate.java
+++ b/java/perftests/src/main/java/org/apache/qpid/disttest/jms/ClientJmsDelegate.java
@@ -35,6 +35,7 @@ import javax.jms.MessageProducer;
import javax.jms.Queue;
import javax.jms.Session;
import javax.jms.TextMessage;
+import javax.jms.Topic;
import javax.naming.Context;
import javax.naming.NamingException;
@@ -72,6 +73,7 @@ public class ClientJmsDelegate
private Map<String, Session> _testSessions;
private Map<String, MessageProducer> _testProducers;
private Map<String, MessageConsumer> _testConsumers;
+ private Map<String, Session> _testSubscriptions;
private Map<String, MessageProvider> _testMessageProviders;
private final MessageProvider _defaultMessageProvider;
@@ -92,6 +94,7 @@ public class ClientJmsDelegate
_testSessions = new HashMap<String, Session>();
_testProducers = new HashMap<String, MessageProducer>();
_testConsumers = new HashMap<String, MessageConsumer>();
+ _testSubscriptions = new HashMap<String, Session>();
_testMessageProviders = new HashMap<String, MessageProvider>();
_defaultMessageProvider = new MessageProvider(null);
}
@@ -193,7 +196,7 @@ public class ClientJmsDelegate
final boolean transacted = command.getAcknowledgeMode() == Session.SESSION_TRANSACTED;
final Session newSession = connection.createSession(transacted, command.getAcknowledgeMode());
- LOGGER.info("Created session " + command.getSessionName() + " with transacted = " + newSession.getTransacted() + " and acknowledgeMode = " + newSession.getAcknowledgeMode());
+ LOGGER.debug("Created session " + command.getSessionName() + " with transacted = " + newSession.getTransacted() + " and acknowledgeMode = " + newSession.getAcknowledgeMode());
addSession(command.getSessionName(), newSession);
}
@@ -212,30 +215,35 @@ public class ClientJmsDelegate
{
throw new DistributedTestException("No test session found called: " + command.getSessionName(), command);
}
- final Destination destination = session.createQueue(command.getDestinationName());
- final MessageProducer jmsProducer = session.createProducer(destination);
- if (command.getPriority() != -1)
- {
- jmsProducer.setPriority(command.getPriority());
- }
- if (command.getTimeToLive() > 0)
- {
- jmsProducer.setTimeToLive(command.getTimeToLive());
- }
- if (command.getDeliveryMode() == DeliveryMode.NON_PERSISTENT
- || command.getDeliveryMode() == DeliveryMode.PERSISTENT)
+ synchronized(session)
{
- jmsProducer.setDeliveryMode(command.getDeliveryMode());
- }
+ final Destination destination = session.createQueue(command.getDestinationName());
+
+ final MessageProducer jmsProducer = session.createProducer(destination);
- addProducer(command.getParticipantName(), jmsProducer);
+ if (command.getPriority() != -1)
+ {
+ jmsProducer.setPriority(command.getPriority());
+ }
+ if (command.getTimeToLive() > 0)
+ {
+ jmsProducer.setTimeToLive(command.getTimeToLive());
+ }
+
+ if (command.getDeliveryMode() == DeliveryMode.NON_PERSISTENT
+ || command.getDeliveryMode() == DeliveryMode.PERSISTENT)
+ {
+ jmsProducer.setDeliveryMode(command.getDeliveryMode());
+ }
+
+ addProducer(command.getParticipantName(), jmsProducer);
+ }
}
catch (final JMSException jmse)
{
throw new DistributedTestException("Unable to create new producer: " + command, jmse);
}
-
}
public void createConsumer(final CreateConsumerCommand command)
@@ -247,11 +255,37 @@ public class ClientJmsDelegate
{
throw new DistributedTestException("No test session found called: " + command.getSessionName(), command);
}
- final Destination destination = command.isTopic() ? session.createTopic(command.getDestinationName())
- : session.createQueue(command.getDestinationName());
- final MessageConsumer jmsConsumer = session.createConsumer(destination, command.getSelector());
- _testConsumers.put(command.getParticipantName(), jmsConsumer);
+ synchronized(session)
+ {
+ Destination destination;
+ MessageConsumer jmsConsumer;
+ if(command.isTopic())
+ {
+ Topic topic = session.createTopic(command.getDestinationName());
+ if(command.isDurableSubscription())
+ {
+ String subscription = "subscription-" + command.getParticipantName() + System.currentTimeMillis();
+ jmsConsumer = session.createDurableSubscriber(topic, subscription);
+
+ _testSubscriptions.put(subscription, session);
+ LOGGER.debug("created durable suscription " + subscription + " to topic " + topic);
+ }
+ else
+ {
+ jmsConsumer = session.createConsumer(topic, command.getSelector());
+ }
+
+ destination = topic;
+ }
+ else
+ {
+ destination = session.createQueue(command.getDestinationName());
+ jmsConsumer = session.createConsumer(destination, command.getSelector());
+ }
+
+ _testConsumers.put(command.getParticipantName(), jmsConsumer);
+ }
}
catch (final JMSException jmse)
{
@@ -346,7 +380,10 @@ public class ClientJmsDelegate
final Session session = _testSessions.get(sessionName);
if (session.getTransacted())
{
- session.commit();
+ synchronized(session)
+ {
+ session.commit();
+ }
}
else if (message != null && session.getAcknowledgeMode() == Session.CLIENT_ACKNOWLEDGE)
{
@@ -461,13 +498,16 @@ public class ClientJmsDelegate
try
{
final Session session = _testSessions.get(sessionName);
- if (session.getTransacted())
+ synchronized(session)
{
- session.rollback();
- }
- else if (session.getAcknowledgeMode() == Session.CLIENT_ACKNOWLEDGE)
- {
- session.recover();
+ if (session.getTransacted())
+ {
+ session.rollback();
+ }
+ else if (session.getAcknowledgeMode() == Session.CLIENT_ACKNOWLEDGE)
+ {
+ session.recover();
+ }
}
}
catch (final JMSException jmse)
@@ -482,13 +522,16 @@ public class ClientJmsDelegate
try
{
final Session session = _testSessions.get(sessionName);
- if (session.getTransacted())
- {
- session.rollback();
- }
- else
+ synchronized(session)
{
- session.recover();
+ if (session.getTransacted())
+ {
+ session.rollback();
+ }
+ else
+ {
+ session.recover();
+ }
}
}
catch (final JMSException jmse)
@@ -503,38 +546,62 @@ public class ClientJmsDelegate
return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE).append("clientName", _clientName).toString();
}
- public void closeTestConnections()
+ public void tearDownTest()
{
StringBuilder jmsErrorMessages = new StringBuilder();
- int failedCloseCounter = 0;
- for (final Map.Entry<String, Connection> entry : _testConnections.entrySet())
+ int failureCounter = 0;
+
+ for(String subscription : _testSubscriptions.keySet())
+ {
+ Session session = _testSubscriptions.get(subscription);
+ try
+ {
+ session.unsubscribe(subscription);
+ }
+ catch (JMSException e)
+ {
+ LOGGER.error("Failed to unsubscribe '" + subscription + "' :" + e.getLocalizedMessage(), e);
+ failureCounter++;
+ appendErrorMessage(jmsErrorMessages, e);
+ }
+ }
+
+ for (Map.Entry<String, Connection> entry : _testConnections.entrySet())
{
- final Connection connection = entry.getValue();
+ Connection connection = entry.getValue();
try
{
connection.close();
}
- catch (final JMSException e)
+ catch (JMSException e)
{
LOGGER.error("Failed to close connection '" + entry.getKey() + "' :" + e.getLocalizedMessage(), e);
- failedCloseCounter++;
- if (jmsErrorMessages.length() > 0)
- {
- jmsErrorMessages.append('\n');
- }
- jmsErrorMessages.append(e.getMessage());
+ failureCounter++;
+ appendErrorMessage(jmsErrorMessages, e);
}
}
+
_testConnections.clear();
+ _testSubscriptions.clear();
_testSessions.clear();
_testProducers.clear();
_testConsumers.clear();
- if (failedCloseCounter > 0)
+
+ if (failureCounter > 0)
{
- throw new DistributedTestException("Close failed for " + failedCloseCounter + " connection(s) with the following errors: " + jmsErrorMessages.toString());
+ throw new DistributedTestException("Tear down test encountered " + failureCounter + " failures with the following errors: " + jmsErrorMessages.toString());
}
}
+ private void appendErrorMessage(StringBuilder errorMessages, JMSException e)
+ {
+ if (errorMessages.length() > 0)
+ {
+ errorMessages.append('\n');
+ }
+ errorMessages.append(e.getMessage());
+ }
+
public void closeTestConsumer(String consumerName)
{
MessageConsumer consumer = _testConsumers.get(consumerName);
@@ -543,7 +610,7 @@ public class ClientJmsDelegate
try
{
consumer.close();
- LOGGER.info("Closed test consumer " + consumerName);
+ LOGGER.debug("Closed test consumer " + consumerName);
}
catch (JMSException e)
{
@@ -568,15 +635,16 @@ public class ClientJmsDelegate
}
}
+ /** only supports text messages - returns 0 for other message types */
public int calculatePayloadSizeFrom(Message message)
{
try
{
if (message != null && message instanceof TextMessage)
{
- return ((TextMessage) message).getText().getBytes().length;
+ return ((TextMessage) message).getText().getBytes().length;
}
- // TODO support other message types
+
return 0;
}
catch (JMSException e)
diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/jms/ControllerJmsDelegate.java b/java/perftests/src/main/java/org/apache/qpid/disttest/jms/ControllerJmsDelegate.java
index 69da409be5..c80e641e5c 100644
--- a/java/perftests/src/main/java/org/apache/qpid/disttest/jms/ControllerJmsDelegate.java
+++ b/java/perftests/src/main/java/org/apache/qpid/disttest/jms/ControllerJmsDelegate.java
@@ -48,11 +48,13 @@ public class ControllerJmsDelegate
{
private static final Logger LOGGER = LoggerFactory.getLogger(ControllerJmsDelegate.class);
+ private static final String QUEUE_CREATOR_CLASS_NAME_SYSTEM_PROPERTY = "qpid.disttest.queue.creator.class";
+
private final Map<String, Destination> _clientNameToQueueMap = new ConcurrentHashMap<String, Destination>();
private final Connection _connection;
private final Destination _controllerQueue;
private final Session _session;
- private final QueueCreator _queueCreator;
+ private QueueCreator _queueCreator;
private List<CommandListener> _commandListeners = new CopyOnWriteArrayList<CommandListener>();
@@ -63,7 +65,39 @@ public class ControllerJmsDelegate
_connection.start();
_controllerQueue = (Destination) context.lookup("controllerqueue");
_session = _connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
- _queueCreator = new QpidQueueCreator();
+
+ createVendorSpecificQueueCreator();
+ }
+
+ private void createVendorSpecificQueueCreator()
+ {
+ String queueCreatorClassName = System.getProperty(QUEUE_CREATOR_CLASS_NAME_SYSTEM_PROPERTY);
+ if(queueCreatorClassName == null)
+ {
+ queueCreatorClassName = QpidQueueCreator.class.getName();
+ }
+ else
+ {
+ LOGGER.info("Using overridden queue creator class " + queueCreatorClassName);
+ }
+
+ try
+ {
+ Class<? extends QueueCreator> queueCreatorClass = (Class<? extends QueueCreator>) Class.forName(queueCreatorClassName);
+ _queueCreator = queueCreatorClass.newInstance();
+ }
+ catch (ClassNotFoundException e)
+ {
+ throw new DistributedTestException("Unable to instantiate queue creator using class name " + queueCreatorClassName, e);
+ }
+ catch (InstantiationException e)
+ {
+ throw new DistributedTestException("Unable to instantiate queue creator using class name " + queueCreatorClassName, e);
+ }
+ catch (IllegalAccessException e)
+ {
+ throw new DistributedTestException("Unable to instantiate queue creator using class name " + queueCreatorClassName, e);
+ }
}
public void start()
diff --git a/java/systests/src/main/java/org/apache/qpid/server/store/SlowMessageStoreFactory.java b/java/perftests/src/main/java/org/apache/qpid/disttest/jms/NoOpQueueCreator.java
index 6497a640d2..4d4850eccf 100644
--- a/java/systests/src/main/java/org/apache/qpid/server/store/SlowMessageStoreFactory.java
+++ b/java/perftests/src/main/java/org/apache/qpid/disttest/jms/NoOpQueueCreator.java
@@ -15,23 +15,23 @@
* 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;
+package org.apache.qpid.disttest.jms;
-public class SlowMessageStoreFactory implements MessageStoreFactory
-{
+import java.util.List;
+
+import javax.jms.Session;
+import org.apache.qpid.disttest.controller.config.QueueConfig;
+public class NoOpQueueCreator implements QueueCreator
+{
@Override
- public MessageStore createMessageStore()
+ public void createQueues(Session session, List<QueueConfig> configs)
{
- return new SlowMessageStore();
}
@Override
- public String getStoreClassName()
+ public void deleteQueues(Session session, List<QueueConfig> configs)
{
- return SlowMessageStore.class.getSimpleName();
}
-
}
diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/jms/QpidQueueCreator.java b/java/perftests/src/main/java/org/apache/qpid/disttest/jms/QpidQueueCreator.java
index 912ce54495..6874abe7d4 100644
--- a/java/perftests/src/main/java/org/apache/qpid/disttest/jms/QpidQueueCreator.java
+++ b/java/perftests/src/main/java/org/apache/qpid/disttest/jms/QpidQueueCreator.java
@@ -21,7 +21,6 @@ package org.apache.qpid.disttest.jms;
import java.util.List;
import javax.jms.Session;
-
import org.apache.qpid.client.AMQDestination;
import org.apache.qpid.client.AMQSession;
import org.apache.qpid.disttest.DistributedTestException;
@@ -29,11 +28,9 @@ import org.apache.qpid.disttest.controller.config.QueueConfig;
import org.apache.qpid.framing.FieldTable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-
public class QpidQueueCreator implements QueueCreator
{
private static final Logger LOGGER = LoggerFactory.getLogger(QpidQueueCreator.class);
-
private static final FieldTable EMPTY_QUEUE_BIND_ARGUMENTS = new FieldTable();
@Override
@@ -69,7 +66,7 @@ public class QpidQueueCreator implements QueueCreator
EMPTY_QUEUE_BIND_ARGUMENTS, destination.getExchangeName(),
destination, autoDelete);
- LOGGER.info("Created queue " + queueConfig);
+ LOGGER.debug("Created queue " + queueConfig);
}
catch (Exception e)
{
@@ -86,12 +83,11 @@ public class QpidQueueCreator implements QueueCreator
// use #deleteQueue.
AMQDestination destination = (AMQDestination) session.createQueue(queueConfig.getName());
session.sendQueueDelete(destination.getAMQQueueName());
- LOGGER.info("Deleted queue " + queueConfig.getName());
+ LOGGER.debug("Deleted queue " + queueConfig.getName());
}
catch (Exception e)
{
throw new DistributedTestException("Failed to delete queue:" + queueConfig.getName(), e);
}
}
-
}
diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/message/ConsumerParticipantResult.java b/java/perftests/src/main/java/org/apache/qpid/disttest/message/ConsumerParticipantResult.java
index f92e3ea538..ad9aa31472 100644
--- a/java/perftests/src/main/java/org/apache/qpid/disttest/message/ConsumerParticipantResult.java
+++ b/java/perftests/src/main/java/org/apache/qpid/disttest/message/ConsumerParticipantResult.java
@@ -18,13 +18,15 @@
*/
package org.apache.qpid.disttest.message;
-import static org.apache.qpid.disttest.message.ParticipantAttribute.IS_BROWSIING_SUBSCRIPTION;
+import static org.apache.qpid.disttest.message.ParticipantAttribute.IS_BROWSING_SUBSCRIPTION;
import static org.apache.qpid.disttest.message.ParticipantAttribute.IS_DURABLE_SUBSCRIPTION;
import static org.apache.qpid.disttest.message.ParticipantAttribute.IS_NO_LOCAL;
import static org.apache.qpid.disttest.message.ParticipantAttribute.IS_SELECTOR;
import static org.apache.qpid.disttest.message.ParticipantAttribute.IS_SYNCHRONOUS_CONSUMER;
import static org.apache.qpid.disttest.message.ParticipantAttribute.IS_TOPIC;
+import java.util.Collection;
+
public class ConsumerParticipantResult extends ParticipantResult
{
private boolean _topic;
@@ -34,6 +36,12 @@ public class ConsumerParticipantResult extends ParticipantResult
private boolean _noLocal;
private boolean _synchronousConsumer;
+ private Collection<Long> _messageLatencies;
+ private long _minLatency;
+ private long _maxLatency;
+ private double _averageLatency;
+ private double _latencyStandardDeviation;
+
public ConsumerParticipantResult()
{
super(CommandType.CONSUMER_PARTICIPANT_RESULT);
@@ -57,7 +65,7 @@ public class ConsumerParticipantResult extends ParticipantResult
}
- @OutputAttribute(attribute=IS_BROWSIING_SUBSCRIPTION)
+ @OutputAttribute(attribute=IS_BROWSING_SUBSCRIPTION)
public boolean isBrowsingSubscription()
{
return _browsingSubscription;
@@ -115,4 +123,59 @@ public class ConsumerParticipantResult extends ParticipantResult
{
return _topic;
}
+
+ public Collection<Long> getMessageLatencies()
+ {
+ return _messageLatencies;
+ }
+
+ public void setMessageLatencies(Collection<Long> messageLatencies)
+ {
+ _messageLatencies = messageLatencies;
+ }
+
+ @OutputAttribute(attribute=ParticipantAttribute.MIN_LATENCY)
+ public long getMinLatency()
+ {
+ return _minLatency;
+ }
+
+ public void setMinLatency(long minLatency)
+ {
+ _minLatency = minLatency;
+ }
+
+ @OutputAttribute(attribute=ParticipantAttribute.MAX_LATENCY)
+ public long getMaxLatency()
+ {
+ return _maxLatency;
+ }
+
+ public void setMaxLatency(long maxLatency)
+ {
+ _maxLatency = maxLatency;
+ }
+
+ @OutputAttribute(attribute=ParticipantAttribute.AVERAGE_LATENCY)
+ public double getAverageLatency()
+ {
+ return _averageLatency;
+ }
+
+ public void setAverageLatency(double averageLatency)
+ {
+ _averageLatency = averageLatency;
+ }
+
+ @OutputAttribute(attribute=ParticipantAttribute.LATENCY_STANDARD_DEVIATION)
+ public double getLatencyStandardDeviation()
+ {
+ return _latencyStandardDeviation;
+ }
+
+ public void setLatencyStandardDeviation(double latencyStandardDeviation)
+ {
+ _latencyStandardDeviation = latencyStandardDeviation;
+ }
+
}
diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/message/CreateConsumerCommand.java b/java/perftests/src/main/java/org/apache/qpid/disttest/message/CreateConsumerCommand.java
index 678e428f94..68c21fbf83 100644
--- a/java/perftests/src/main/java/org/apache/qpid/disttest/message/CreateConsumerCommand.java
+++ b/java/perftests/src/main/java/org/apache/qpid/disttest/message/CreateConsumerCommand.java
@@ -28,7 +28,7 @@ public class CreateConsumerCommand extends CreateParticpantCommand
private boolean _noLocal;
private boolean _synchronous;
private long _receiveTimeout = 5000;
-
+ private boolean _evaluateLatency;
public CreateConsumerCommand()
{
@@ -105,4 +105,14 @@ public class CreateConsumerCommand extends CreateParticpantCommand
{
return _receiveTimeout;
}
+
+ public boolean isEvaluateLatency()
+ {
+ return _evaluateLatency;
+ }
+
+ public void setEvaluateLatency(boolean evaluateLatency)
+ {
+ _evaluateLatency = evaluateLatency;
+ }
}
diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/message/ParticipantAttribute.java b/java/perftests/src/main/java/org/apache/qpid/disttest/message/ParticipantAttribute.java
index ccc7c0d9fb..0418562a2d 100644
--- a/java/perftests/src/main/java/org/apache/qpid/disttest/message/ParticipantAttribute.java
+++ b/java/perftests/src/main/java/org/apache/qpid/disttest/message/ParticipantAttribute.java
@@ -45,7 +45,7 @@ public enum ParticipantAttribute
PRODUCER_INTERVAL("producerIntervalMs"),
IS_TOPIC("isTopic"),
IS_DURABLE_SUBSCRIPTION("isDurableSubscription"),
- IS_BROWSIING_SUBSCRIPTION("isBrowsingSubscription"),
+ IS_BROWSING_SUBSCRIPTION("isBrowsingSubscription"),
IS_SELECTOR("isSelector"),
IS_NO_LOCAL("isNoLocal"),
IS_SYNCHRONOUS_CONSUMER("isSynchronousConsumer"),
@@ -54,7 +54,12 @@ public enum ParticipantAttribute
TOTAL_PAYLOAD_PROCESSED("totalPayloadProcessedB"),
THROUGHPUT("throughputKbPerS"),
TIME_TAKEN("timeTakenMs"),
- ERROR_MESSAGE("errorMessage");
+ ERROR_MESSAGE("errorMessage"),
+ MIN_LATENCY("minLatency"),
+ MAX_LATENCY("maxLatency"),
+ AVERAGE_LATENCY("averageLatency"),
+ LATENCY_STANDARD_DEVIATION("latencyStandardDeviation")
+ ;
private String _displayName;
diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/results/aggregation/ParticipantResultAggregator.java b/java/perftests/src/main/java/org/apache/qpid/disttest/results/aggregation/ParticipantResultAggregator.java
index 207d0131eb..4dcabe6c7b 100644
--- a/java/perftests/src/main/java/org/apache/qpid/disttest/results/aggregation/ParticipantResultAggregator.java
+++ b/java/perftests/src/main/java/org/apache/qpid/disttest/results/aggregation/ParticipantResultAggregator.java
@@ -23,7 +23,9 @@ import java.util.Date;
import java.util.NavigableSet;
import java.util.TreeSet;
+import org.apache.qpid.disttest.message.ConsumerParticipantResult;
import org.apache.qpid.disttest.message.ParticipantResult;
+import org.apache.qpid.disttest.message.ProducerParticipantResult;
public class ParticipantResultAggregator
{
@@ -42,8 +44,13 @@ public class ParticipantResultAggregator
private NavigableSet<Integer> _encounteredIterationNumbers = new TreeSet<Integer>();
private NavigableSet<Integer> _encounteredBatchSizes = new TreeSet<Integer>();
private NavigableSet<Integer> _encounteredAcknowledgeMode = new TreeSet<Integer>();
+ private NavigableSet<Integer> _encounteredDeliveryModes = new TreeSet<Integer>();
+ private NavigableSet<Boolean> _encounteredDurableSubscriptions = new TreeSet<Boolean>();
+ private NavigableSet<Boolean> _encounteredTopics = new TreeSet<Boolean>();
private NavigableSet<String> _encountedTestNames = new TreeSet<String>();
+ private SeriesStatistics _latencyStatistics = new SeriesStatistics();
+
public ParticipantResultAggregator(Class<? extends ParticipantResult> targetClass, String aggregateResultName)
{
_aggregatedResultName = aggregateResultName;
@@ -56,12 +63,31 @@ public class ParticipantResultAggregator
{
rollupConstantAttributes(result);
computeVariableAttributes(result);
+ if (result instanceof ConsumerParticipantResult)
+ {
+ ConsumerParticipantResult consumerParticipantResult = (ConsumerParticipantResult)result;
+ _latencyStatistics.addMessageLatencies(consumerParticipantResult.getMessageLatencies());
+ _latencyStatistics.aggregate();
+ }
}
}
public ParticipantResult getAggregatedResult()
{
- ParticipantResult aggregatedResult = new ParticipantResult(_aggregatedResultName);
+ ParticipantResult aggregatedResult;
+ if (_targetClass == ConsumerParticipantResult.class)
+ {
+ ConsumerParticipantResult consumerParticipantResult = new ConsumerParticipantResult(_aggregatedResultName);
+ consumerParticipantResult.setAverageLatency(_latencyStatistics.getAverage());
+ consumerParticipantResult.setMinLatency(_latencyStatistics.getMinimum());
+ consumerParticipantResult.setMaxLatency(_latencyStatistics.getMaximum());
+ consumerParticipantResult.setLatencyStandardDeviation(_latencyStatistics.getStandardDeviation());
+ aggregatedResult = consumerParticipantResult;
+ }
+ else
+ {
+ aggregatedResult = new ParticipantResult(_aggregatedResultName);
+ }
setRolledUpConstantAttributes(aggregatedResult);
setComputedVariableAttributes(aggregatedResult);
@@ -94,6 +120,17 @@ public class ParticipantResultAggregator
_encounteredIterationNumbers.add(result.getIterationNumber());
_encounteredBatchSizes.add(result.getBatchSize());
_encounteredAcknowledgeMode.add(result.getAcknowledgeMode());
+ if (result instanceof ProducerParticipantResult)
+ {
+ ProducerParticipantResult producerParticipantResult = (ProducerParticipantResult) result;
+ _encounteredDeliveryModes.add(producerParticipantResult.getDeliveryMode());
+ }
+ else if(result instanceof ConsumerParticipantResult)
+ {
+ ConsumerParticipantResult consumerParticipantResult = (ConsumerParticipantResult)result;
+ _encounteredDurableSubscriptions.add(consumerParticipantResult.isDurableSubscription());
+ _encounteredTopics.add(consumerParticipantResult.isTopic());
+ }
}
private void setComputedVariableAttributes(ParticipantResult aggregatedResult)
@@ -129,6 +166,26 @@ public class ParticipantResultAggregator
{
aggregatedResult.setAcknowledgeMode(_encounteredAcknowledgeMode.first());
}
+ if (aggregatedResult instanceof ProducerParticipantResult)
+ {
+ ProducerParticipantResult producerParticipantResult = (ProducerParticipantResult) aggregatedResult;
+ if(_encounteredDeliveryModes.size() == 1)
+ {
+ producerParticipantResult.setDeliveryMode(_encounteredDeliveryModes.first());
+ }
+ }
+ if (aggregatedResult instanceof ConsumerParticipantResult)
+ {
+ ConsumerParticipantResult consumerParticipantResult = (ConsumerParticipantResult) aggregatedResult;
+ if(_encounteredDurableSubscriptions.size() == 1)
+ {
+ consumerParticipantResult.setDurableSubscription(_encounteredDurableSubscriptions.first());
+ }
+ if(_encounteredTopics.size() == 1)
+ {
+ consumerParticipantResult.setTopic(_encounteredTopics.first());
+ }
+ }
}
private double calculateThroughputInKiloBytesPerSecond()
diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/results/aggregation/SeriesStatistics.java b/java/perftests/src/main/java/org/apache/qpid/disttest/results/aggregation/SeriesStatistics.java
new file mode 100644
index 0000000000..b93c210473
--- /dev/null
+++ b/java/perftests/src/main/java/org/apache/qpid/disttest/results/aggregation/SeriesStatistics.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.disttest.results.aggregation;
+
+import java.util.Collection;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+public class SeriesStatistics
+{
+ private long _minValue;
+ private long _maxValue;
+ private double _mean;
+ private double _standardDeviation;
+ private Collection<Long> _series = new CopyOnWriteArrayList<Long>();
+
+ public SeriesStatistics()
+ {
+ super();
+ }
+
+ public SeriesStatistics(Collection<Long> messageLatencies)
+ {
+ setMessageLatencies(messageLatencies);
+ }
+
+ public void addMessageLatencies(Collection<Long> messageLatencies)
+ {
+ if (messageLatencies != null)
+ {
+ _series.addAll(messageLatencies);
+ }
+ }
+
+ public void setMessageLatencies(Collection<Long> messageLatencies)
+ {
+ _series = messageLatencies;
+ aggregate();
+ }
+
+ public void aggregate()
+ {
+ if (_series != null && _series.size() > 0)
+ {
+ long minLatency = Long.MAX_VALUE;
+ long maxLatency = Long.MIN_VALUE;
+ long totalLatency = 0;
+ for (Long latency : _series)
+ {
+ totalLatency += latency;
+ minLatency = Math.min(minLatency, latency);
+ maxLatency = Math.max(maxLatency, latency);
+ }
+ _mean = ((double) totalLatency) / (double) _series.size();
+ _minValue = minLatency;
+ _maxValue = maxLatency;
+ double sum = 0;
+ for (Long latency : _series)
+ {
+ double diff = latency - _mean;
+ sum += diff * diff;
+ }
+ long size = _series.size() == 1 ? 1: _series.size() - 1;
+ _standardDeviation = Math.sqrt(sum / (double) size);
+ }
+ else
+ {
+ _mean = 0;
+ _minValue = 0;
+ _maxValue = 0;
+ _standardDeviation = 0;
+ }
+ }
+
+ public long getMinimum()
+ {
+ return _minValue;
+ }
+
+ public long getMaximum()
+ {
+ return _maxValue;
+ }
+
+ public double getAverage()
+ {
+ return _mean;
+ }
+
+ public double getStandardDeviation()
+ {
+ return _standardDeviation;
+ }
+}
diff --git a/java/perftests/src/main/java/test-utils.js b/java/perftests/src/main/java/test-utils.js
new file mode 100644
index 0000000000..7bfe233266
--- /dev/null
+++ b/java/perftests/src/main/java/test-utils.js
@@ -0,0 +1,85 @@
+var QPID;
+if (!QPID) {
+ QPID = {};
+}
+(function () {
+ 'use strict';
+
+ if (typeof QPID.times !== 'function') {
+ QPID.times = function (multiplicity, template, timeIndexName)
+ {
+ var retVal = new Array();
+ for (var i = 0; i < multiplicity; i++)
+ {
+ var templateName = template._name;
+ var teamplateAsString = JSON.stringify(template);
+ if (timeIndexName)
+ {
+ teamplateAsString = teamplateAsString.replace(new RegExp(timeIndexName, "g"), i);
+ }
+ var expandedObject = JSON.parse(teamplateAsString);
+ if (!(timeIndexName))
+ {
+ expandedObject._name = templateName + "_" + i;
+ }
+ retVal[i] = expandedObject;
+ }
+ return retVal;
+ }
+ }
+
+ if (typeof QPID.iterations !== 'function') {
+ QPID.iterations = function (values, template)
+ {
+ var retVal = new Array()
+
+ var iterationNumber = 0;
+
+ for (variableName in values)
+ {
+ var variableValues = values[variableName]
+ for (i in variableValues)
+ {
+ var variableValue = variableValues[i]
+ var templateTestString = JSON.stringify(template)
+ var actualString = templateTestString.replace(new RegExp(variableName, "g"), variableValue)
+ var iteration = JSON.parse(actualString)
+ iteration._iterationNumber = iterationNumber
+ retVal[iterationNumber] = iteration
+ iterationNumber++
+ }
+ }
+
+ return retVal
+ }
+ }
+
+ if (typeof QPID.transform !== 'function') {
+
+ /**
+ * Function to transform JSON using specified transformation function.
+ * Any number of transformation function could be passed after the template argument.
+ * Each function should return a transformed JSON object.
+ * Example
+ * var json = transform({"name": "Test1"}, function(json){json.name="Test"; return json;});
+ */
+ QPID.transform = function (template)
+ {
+ var json = template;
+ for (var i=1, len=arguments.length; i<len; i++)
+ {
+ json = arguments[i](json);
+ }
+ return json;
+ }
+ }
+
+ if (typeof QPID.cloneJSON !== 'function') {
+ QPID.cloneJSON = function (json)
+ {
+ return JSON.parse( JSON.stringify( json ));
+ }
+ }
+
+}());
+
diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/ConfigFileHelperTest.java b/java/perftests/src/test/java/org/apache/qpid/disttest/ConfigFileHelperTest.java
new file mode 100644
index 0000000000..a10b3b359e
--- /dev/null
+++ b/java/perftests/src/test/java/org/apache/qpid/disttest/ConfigFileHelperTest.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.disttest;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.qpid.test.utils.QpidTestCase;
+import org.apache.qpid.test.utils.TestFileUtils;
+
+public class ConfigFileHelperTest extends QpidTestCase
+{
+ private File _testDir;
+ private ConfigFileHelper _configFileHelper = new ConfigFileHelper();
+
+ @Override
+ protected void setUp() throws Exception
+ {
+ _testDir = TestFileUtils.createTestDirectory();
+ }
+
+ public void testGenerateOutputCsvNameFrom()
+ {
+ String outputDir = "/tmp/outputDir";
+
+ assertEquals("/tmp/outputDir/my.json.file.csv", _configFileHelper.generateOutputCsvNameFrom("/tmp/my.json.file.json", outputDir));
+ assertEquals("/tmp/outputDir/my.js.file.csv", _configFileHelper.generateOutputCsvNameFrom("/tmp/my.js.file.js", outputDir));
+ }
+
+ public void testGetTestConfigFilesForDirectory() throws Exception
+ {
+ String jsFile = createFile("file1.js");
+ String jsonFile = createFile("file2.json");
+ createFile("file.txt");
+ createDir("dir.js");
+
+ String testConfigPath = _testDir.getAbsolutePath();
+
+ List<String> configFiles = _configFileHelper.getTestConfigFiles(testConfigPath);
+
+ Set<String> expectedFiles = new HashSet<String>(Arrays.asList(jsFile, jsonFile));
+ Set<String> actualFiles = new HashSet<String>(configFiles);
+
+ assertEquals(expectedFiles, actualFiles);
+ }
+
+ private void createDir(String dirName)
+ {
+ File dir = new File(_testDir, dirName);
+ dir.mkdir();
+ }
+
+ private String createFile(String fileName) throws IOException
+ {
+ File file = new File(_testDir, fileName);
+ file.createNewFile();
+ return file.getAbsolutePath();
+ }
+}
diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/ConfigFileHelper.java b/java/perftests/src/test/java/org/apache/qpid/disttest/ConfigFileTestHelper.java
index 12ba3b56ad..71cd61db82 100644
--- a/java/perftests/src/test/java/org/apache/qpid/disttest/ConfigFileHelper.java
+++ b/java/perftests/src/test/java/org/apache/qpid/disttest/ConfigFileTestHelper.java
@@ -26,7 +26,7 @@ import java.io.Reader;
import org.apache.qpid.disttest.controller.config.Config;
import org.apache.qpid.disttest.controller.config.ConfigReader;
-public class ConfigFileHelper
+public class ConfigFileTestHelper
{
public static Reader getConfigFileReader(Class<?> testClass, String resourceName)
{
diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/client/ClientTest.java b/java/perftests/src/test/java/org/apache/qpid/disttest/client/ClientTest.java
index 198baa6ef4..dd50766918 100644
--- a/java/perftests/src/test/java/org/apache/qpid/disttest/client/ClientTest.java
+++ b/java/perftests/src/test/java/org/apache/qpid/disttest/client/ClientTest.java
@@ -125,7 +125,7 @@ public class ClientTest extends TestCase
_client.tearDownTest();
- verify(_delegate).closeTestConnections();
+ verify(_delegate).tearDownTest();
verify(_participantRegistry).clear();
}
diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/client/ConsumerParticipantTest.java b/java/perftests/src/test/java/org/apache/qpid/disttest/client/ConsumerParticipantTest.java
index ff7cfd2b41..58589d36f4 100644
--- a/java/perftests/src/test/java/org/apache/qpid/disttest/client/ConsumerParticipantTest.java
+++ b/java/perftests/src/test/java/org/apache/qpid/disttest/client/ConsumerParticipantTest.java
@@ -29,6 +29,8 @@ import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import java.util.Collection;
+
import javax.jms.Message;
import javax.jms.Session;
@@ -36,6 +38,7 @@ import junit.framework.TestCase;
import org.apache.qpid.disttest.DistributedTestException;
import org.apache.qpid.disttest.jms.ClientJmsDelegate;
+import org.apache.qpid.disttest.message.ConsumerParticipantResult;
import org.apache.qpid.disttest.message.CreateConsumerCommand;
import org.apache.qpid.disttest.message.ParticipantResult;
import org.mockito.InOrder;
@@ -177,4 +180,24 @@ public class ConsumerParticipantTest extends TestCase
verify(_delegate).closeTestConsumer(PARTICIPANT_NAME1);
}
+ public void testLatency() throws Exception
+ {
+ int numberOfMessages = 1;
+ long totalPayloadSize = PAYLOAD_SIZE_PER_MESSAGE * numberOfMessages;
+ _command.setNumberOfMessages(numberOfMessages);
+ _command.setEvaluateLatency(true);
+ _consumerParticipant = new ConsumerParticipant(_delegate, _command);
+ ParticipantResult result = _consumerParticipant.doIt(CLIENT_NAME);
+
+ assertExpectedConsumerResults(result, PARTICIPANT_NAME1, CLIENT_NAME, _testStartTime,
+ Session.CLIENT_ACKNOWLEDGE, null, numberOfMessages, PAYLOAD_SIZE_PER_MESSAGE, totalPayloadSize, null);
+
+ _inOrder.verify(_delegate).consumeMessage(PARTICIPANT_NAME1, RECEIVE_TIMEOUT);
+ _inOrder.verify(_delegate).calculatePayloadSizeFrom(_mockMessage);
+ _inOrder.verify(_delegate).commitOrAcknowledgeMessage(_mockMessage, SESSION_NAME1);
+ assertTrue("Unexpected consuemr results", result instanceof ConsumerParticipantResult);
+ Collection<Long> latencies = ((ConsumerParticipantResult)result).getMessageLatencies();
+ assertNotNull("Message latency is not cllected", latencies);
+ assertEquals("Unexpected message latency results", 1, latencies.size());
+ }
}
diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/client/MessageProviderTest.java b/java/perftests/src/test/java/org/apache/qpid/disttest/client/MessageProviderTest.java
index ffc3733eb7..1ff8d3e5d7 100644
--- a/java/perftests/src/test/java/org/apache/qpid/disttest/client/MessageProviderTest.java
+++ b/java/perftests/src/test/java/org/apache/qpid/disttest/client/MessageProviderTest.java
@@ -59,6 +59,7 @@ public class MessageProviderTest extends TestCase
{
MessageProvider messageProvider = new MessageProvider(null)
{
+ @Override
public String getMessagePayload(CreateProducerCommand command)
{
return super.getMessagePayload(command);
diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/client/ProducerParticipantTest.java b/java/perftests/src/test/java/org/apache/qpid/disttest/client/ProducerParticipantTest.java
index cf05623e8f..a3ac11b756 100644
--- a/java/perftests/src/test/java/org/apache/qpid/disttest/client/ProducerParticipantTest.java
+++ b/java/perftests/src/test/java/org/apache/qpid/disttest/client/ProducerParticipantTest.java
@@ -121,7 +121,7 @@ public class ProducerParticipantTest extends TestCase
_command.setBatchSize(batchSize);
_command.setDeliveryMode(deliveryMode);
- ParticipantResult result = (ParticipantResult) _producer.doIt(CLIENT_NAME);
+ ParticipantResult result = _producer.doIt(CLIENT_NAME);
assertExpectedProducerResults(result, PARTICIPANT_NAME1, CLIENT_NAME, _testStartTime,
Session.AUTO_ACKNOWLEDGE, null, numberOfMessages, PAYLOAD_SIZE_PER_MESSAGE, totalPayloadSize, null);
diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/client/property/ListPropertyValueTest.java b/java/perftests/src/test/java/org/apache/qpid/disttest/client/property/ListPropertyValueTest.java
index 75a634ba54..c54355bc76 100644
--- a/java/perftests/src/test/java/org/apache/qpid/disttest/client/property/ListPropertyValueTest.java
+++ b/java/perftests/src/test/java/org/apache/qpid/disttest/client/property/ListPropertyValueTest.java
@@ -32,6 +32,7 @@ public class ListPropertyValueTest extends TestCase
private ListPropertyValue _generator;
private List<PropertyValue> _items;
+ @Override
public void setUp() throws Exception
{
super.setUp();
diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/client/property/PropertyValueFactoryTest.java b/java/perftests/src/test/java/org/apache/qpid/disttest/client/property/PropertyValueFactoryTest.java
index 2d560163c2..17397db5b8 100644
--- a/java/perftests/src/test/java/org/apache/qpid/disttest/client/property/PropertyValueFactoryTest.java
+++ b/java/perftests/src/test/java/org/apache/qpid/disttest/client/property/PropertyValueFactoryTest.java
@@ -24,6 +24,7 @@ public class PropertyValueFactoryTest extends TestCase
{
private PropertyValueFactory _factory;
+ @Override
public void setUp() throws Exception
{
super.setUp();
diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/client/property/RandomPropertyValueTest.java b/java/perftests/src/test/java/org/apache/qpid/disttest/client/property/RandomPropertyValueTest.java
index bd5de3e370..878141895c 100644
--- a/java/perftests/src/test/java/org/apache/qpid/disttest/client/property/RandomPropertyValueTest.java
+++ b/java/perftests/src/test/java/org/apache/qpid/disttest/client/property/RandomPropertyValueTest.java
@@ -26,6 +26,7 @@ public class RandomPropertyValueTest extends TestCase
{
private RandomPropertyValue _generator;
+ @Override
public void setUp() throws Exception
{
super.setUp();
diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/client/property/RangePropertyValueTest.java b/java/perftests/src/test/java/org/apache/qpid/disttest/client/property/RangePropertyValueTest.java
index 91791c9d55..6932919bed 100644
--- a/java/perftests/src/test/java/org/apache/qpid/disttest/client/property/RangePropertyValueTest.java
+++ b/java/perftests/src/test/java/org/apache/qpid/disttest/client/property/RangePropertyValueTest.java
@@ -26,6 +26,7 @@ public class RangePropertyValueTest extends TestCase
{
private RangePropertyValue _generator;
+ @Override
public void setUp() throws Exception
{
super.setUp();
diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/client/utils/ExecutorWithNoLimitsTest.java b/java/perftests/src/test/java/org/apache/qpid/disttest/client/utils/ExecutorWithNoLimitsTest.java
new file mode 100644
index 0000000000..37820d2582
--- /dev/null
+++ b/java/perftests/src/test/java/org/apache/qpid/disttest/client/utils/ExecutorWithNoLimitsTest.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.disttest.client.utils;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.util.concurrent.Callable;
+
+import junit.framework.TestCase;
+
+public class ExecutorWithNoLimitsTest extends TestCase
+{
+ private final static Object RESULT = new Object();
+
+ private ExecutorWithLimits _limiter = new ExecutorWithNoLimits();
+ @SuppressWarnings("unchecked")
+ private Callable<Object> _callback = mock(Callable.class);
+
+ public void testNormalExecution() throws Exception
+ {
+ when(_callback.call()).thenReturn(RESULT);
+ final Object actualResult = _limiter.execute(_callback);
+ verify(_callback).call();
+ assertEquals(RESULT, actualResult);
+ }
+
+ public void testCallableThrowsException() throws Exception
+ {
+ when(_callback.call()).thenThrow(new Exception("mocked exception"));
+
+ try
+ {
+ _limiter.execute(_callback);
+ fail("Exception not thrown");
+ }
+ catch (Exception e)
+ {
+ // PASS
+ }
+ verify(_callback).call();
+ }
+}
diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/client/utils/ExecutorWithTimeLimitTest.java b/java/perftests/src/test/java/org/apache/qpid/disttest/client/utils/ExecutorWithTimeLimitTest.java
new file mode 100644
index 0000000000..a201a7bacf
--- /dev/null
+++ b/java/perftests/src/test/java/org/apache/qpid/disttest/client/utils/ExecutorWithTimeLimitTest.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.disttest.client.utils;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.never;
+
+import java.util.concurrent.Callable;
+import java.util.concurrent.CancellationException;
+
+import junit.framework.TestCase;
+
+public class ExecutorWithTimeLimitTest extends TestCase
+{
+ private static final int TIMEOUT = 500;
+ private static final Object RESULT = new Object();
+
+ private ExecutorWithLimits _limiter;
+ @SuppressWarnings("unchecked")
+ private Callable<Object> _callback = mock(Callable.class);
+
+ @Override
+ protected void setUp() throws Exception
+ {
+ super.setUp();
+ _limiter = new ExecutorWithTimeLimit(System.currentTimeMillis(), TIMEOUT);
+ }
+
+ @Override
+ protected void tearDown() throws Exception
+ {
+ super.tearDown();
+ if (_limiter != null)
+ {
+ _limiter.shutdown();
+ }
+ }
+
+ public void testCallableCompletesNormally() throws Exception
+ {
+ when(_callback.call()).thenReturn(RESULT);
+
+ final Object actualResult = _limiter.execute(_callback);
+
+ verify(_callback).call();
+ assertEquals(RESULT, actualResult);
+ }
+
+ public void testCallableThrowsException() throws Exception
+ {
+ when(_callback.call()).thenThrow(new Exception("mocked exception"));
+
+ try
+ {
+ _limiter.execute(_callback);
+ fail("Exception not thrown");
+ }
+ catch (CancellationException ce)
+ {
+ fail("Wrong exception thrown");
+ }
+ catch (Exception e)
+ {
+ // PASS
+ }
+ verify(_callback).call();
+ }
+
+ public void testCallableNotRunDueToInsufficentTimeRemaining() throws Exception
+ {
+ long now = System.currentTimeMillis();
+ ExecutorWithLimits shortTimeLimiter = new ExecutorWithTimeLimit(now - 100, 100);
+ try
+ {
+ shortTimeLimiter.execute(_callback);
+ fail("Exception not thrown");
+ }
+ catch (CancellationException ca)
+ {
+ // PASS
+ }
+ finally
+ {
+ shortTimeLimiter.shutdown();
+ }
+
+ verify(_callback, never()).call();
+ }
+
+ public void testExecutionInterruptedByTimeout() throws Exception
+ {
+ Callable<Void> oversleepingCallback = new Callable<Void>()
+ {
+ @Override
+ public Void call() throws Exception
+ {
+ Thread.sleep(TIMEOUT * 2);
+ return null;
+ }
+ };
+
+ try
+ {
+ _limiter.execute(oversleepingCallback);
+ fail("Exception not thrown");
+ }
+ catch (CancellationException ca)
+ {
+ // PASS
+ }
+ }
+}
diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/ConfigReaderTest-test-config.js b/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/ConfigReaderTest-test-config.js
new file mode 100644
index 0000000000..07f8bf9d92
--- /dev/null
+++ b/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/ConfigReaderTest-test-config.js
@@ -0,0 +1,34 @@
+jsonObject = {
+ "_tests":
+ QPID.iterations( { "__ACK_MODE": [ 0, 1 ] },
+ {
+ // this is a comment - it wouldn't be allowed if this were pure JSON
+
+ "_name": "Test 1",
+ "_queues": [
+ {
+ "_name": "Json-Queue-Name"
+ }
+ ],
+
+ "_clients": QPID.times(2,
+ {
+ "_name": "repeatingClient__CLIENT_INDEX",
+ "_connections": [
+ {
+ "_name": "connection1",
+ "_sessions": [
+ {
+ "_sessionName": "session1",
+ "_acknowledgeMode": "__ACK_MODE",
+ "_consumers": []
+ }
+ ]
+ }
+ ]
+ },
+ "__CLIENT_INDEX"
+ )
+ })
+
+} \ No newline at end of file
diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/ConfigReaderTest.java b/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/ConfigReaderTest.java
index af9ec28db0..257f139849 100644
--- a/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/ConfigReaderTest.java
+++ b/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/ConfigReaderTest.java
@@ -25,10 +25,8 @@ import java.util.Map;
import junit.framework.TestCase;
-import org.apache.qpid.disttest.ConfigFileHelper;
-import org.apache.qpid.disttest.client.MessageProvider;
+import org.apache.qpid.disttest.ConfigFileTestHelper;
import org.apache.qpid.disttest.client.property.PropertyValue;
-import org.apache.qpid.disttest.controller.CommandForClient;
public class ConfigReaderTest extends TestCase
{
@@ -38,7 +36,7 @@ public class ConfigReaderTest extends TestCase
protected void setUp()
{
ConfigReader configReader = new ConfigReader();
- Reader reader = ConfigFileHelper.getConfigFileReader(getClass(), "sampleConfig.json");
+ Reader reader = ConfigFileTestHelper.getConfigFileReader(getClass(), "sampleConfig.json");
_config = configReader.readConfig(reader);
}
@@ -110,4 +108,38 @@ public class ConfigReaderTest extends TestCase
assertNotNull("id property is not found", properties.get("id"));
}
+ public void testReadsJS() throws Exception
+ {
+ ConfigReader configReader = new ConfigReader();
+ String path = getClass().getResource("ConfigReaderTest-test-config.js").toURI().getPath();
+ _config = configReader.getConfigFromFile(path);
+ List<TestConfig> testConfigs = _config.getTestConfigs();
+ assertEquals("Unexpected number of tests", 2, testConfigs.size());
+ TestConfig testConfig1 = _config.getTestConfigs().get(0);
+ List<ClientConfig> cleintConfigs = testConfig1.getClients();
+ assertEquals("Unexpected number of test 1 clients", 2, cleintConfigs.size());
+ List<QueueConfig> queueConfigs = testConfig1.getQueues();
+ assertEquals("Unexpected number of test 1 queue", 1, queueConfigs.size());
+ assertEquals("Unexpected queue name", "Json-Queue-Name", queueConfigs.get(0).getName());
+ ClientConfig cleintConfig = cleintConfigs.get(0);
+ List<ConnectionConfig> connectionConfigs = cleintConfig.getConnections();
+ assertEquals("Unexpected number of connections", 1, connectionConfigs.size());
+ List<SessionConfig> sessionConfigs = connectionConfigs.get(0).getSessions();
+ assertEquals("Unexpected number of sessions", 1, sessionConfigs.size());
+ assertEquals("Unexpected ack mode", 0, sessionConfigs.get(0).getAcknowledgeMode());
+
+ TestConfig testConfig2 = _config.getTestConfigs().get(1);
+ List<ClientConfig> cleintConfigs2 = testConfig2.getClients();
+ assertEquals("Unexpected number of test 1 clients", 2, cleintConfigs2.size());
+ List<QueueConfig> queueConfigs2 = testConfig2.getQueues();
+ assertEquals("Unexpected number of test 1 queue", 1, queueConfigs2.size());
+ assertEquals("Unexpected queue name", "Json-Queue-Name", queueConfigs2.get(0).getName());
+ ClientConfig cleintConfig2 = cleintConfigs2.get(0);
+ List<ConnectionConfig> connectionConfigs2 = cleintConfig2.getConnections();
+ assertEquals("Unexpected number of connections", 1, connectionConfigs2.size());
+ List<SessionConfig> sessionConfigs2 = connectionConfigs2.get(0).getSessions();
+ assertEquals("Unexpected number of sessions", 1, sessionConfigs2.size());
+ assertEquals("Unexpected ack mode", 1, sessionConfigs2.get(0).getAcknowledgeMode());
+ }
+
}
diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/IterationValueTest.java b/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/IterationValueTest.java
index 7998eae37e..860f6af565 100644
--- a/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/IterationValueTest.java
+++ b/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/IterationValueTest.java
@@ -22,19 +22,19 @@ import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyZeroInteractions;
-import java.util.Collections;
+import java.util.HashMap;
import java.util.Map;
-import junit.framework.TestCase;
-
+import org.apache.qpid.disttest.message.CreateConnectionCommand;
import org.apache.qpid.disttest.message.CreateConsumerCommand;
-import org.apache.qpid.disttest.message.CreateProducerCommand;
+import org.apache.qpid.test.utils.QpidTestCase;
-public class IterationValueTest extends TestCase
+public class IterationValueTest extends QpidTestCase
{
- private static final int MESSAGE_SIZE = 10;
+ private static final int MAXIMUM_DURATION = 10;
+
+ private static final boolean IS_DURABLE_SUBSCRIPTION = true;
- private CreateProducerCommand _createProducerCommand;
private CreateConsumerCommand _createConsumerCommand;
private Map<String, String> _iterationValueMap;
@@ -42,37 +42,40 @@ public class IterationValueTest extends TestCase
protected void setUp() throws Exception
{
super.setUp();
- _createProducerCommand = mock(CreateProducerCommand.class);
_createConsumerCommand = mock(CreateConsumerCommand.class);
- _iterationValueMap = Collections.singletonMap("_messageSize", String.valueOf(MESSAGE_SIZE));
+ _iterationValueMap = new HashMap<String, String>();
+ _iterationValueMap.put("_maximumDuration", String.valueOf(MAXIMUM_DURATION));
+ _iterationValueMap.put("_durableSubscription", String.valueOf(IS_DURABLE_SUBSCRIPTION));
}
public void testApplyPopulatedIterationValueToCommandWithMatchingProperties() throws Exception
{
IterationValue iterationValue = new IterationValue(_iterationValueMap);
- iterationValue.applyToCommand(_createProducerCommand);
+ iterationValue.applyToCommand(_createConsumerCommand);
- verify(_createProducerCommand).setMessageSize(MESSAGE_SIZE);
+ verify(_createConsumerCommand).setMaximumDuration(MAXIMUM_DURATION);
+ verify(_createConsumerCommand).setDurableSubscription(IS_DURABLE_SUBSCRIPTION);
}
public void testApplyPopulatedIterationValueToCommandWithoutMatchingProperties() throws Exception
{
IterationValue iterationValue = new IterationValue(_iterationValueMap);
- iterationValue.applyToCommand(_createConsumerCommand);
+ CreateConnectionCommand createConnectionCommand = mock(CreateConnectionCommand.class);
+ iterationValue.applyToCommand(createConnectionCommand);
- verifyZeroInteractions(_createConsumerCommand);
+ verifyZeroInteractions(createConnectionCommand);
}
public void testApplyUnpopulatedIterationValueToCommand() throws Exception
{
IterationValue iterationValue = new IterationValue();
- iterationValue.applyToCommand(_createProducerCommand);
+ iterationValue.applyToCommand(_createConsumerCommand);
- verifyZeroInteractions(_createProducerCommand);
+ verifyZeroInteractions(_createConsumerCommand);
}
}
diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/JavaScriptConfigEvaluatorTest-test-config.js b/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/JavaScriptConfigEvaluatorTest-test-config.js
new file mode 100644
index 0000000000..f64af82feb
--- /dev/null
+++ b/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/JavaScriptConfigEvaluatorTest-test-config.js
@@ -0,0 +1,23 @@
+jsonObject = {
+ "_countries":
+ QPID.iterations( { "__ITERATING_VALUE": [ 0, 1 ] },
+ {
+ // this is a comment - it wouldn't be allowed if this were pure JSON
+
+ "_name": "Country",
+ "_regions": QPID.times(2,
+ {
+ "_name": "repeatingRegion__REGION_INDEX",
+ "_towns": [
+ {
+ "_name": "town1",
+ "_iteratingAttribute": "__ITERATING_VALUE",
+ "_consumers": []
+ }
+ ]
+ },
+ "__REGION_INDEX"
+ )
+ })
+
+} \ No newline at end of file
diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/JavaScriptConfigEvaluatorTest.java b/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/JavaScriptConfigEvaluatorTest.java
new file mode 100644
index 0000000000..eb4063888b
--- /dev/null
+++ b/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/JavaScriptConfigEvaluatorTest.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.disttest.controller.config;
+
+import static org.apache.commons.beanutils.PropertyUtils.getProperty;
+
+import java.util.List;
+import java.util.TreeMap;
+
+import junit.framework.TestCase;
+
+import com.google.gson.Gson;
+
+public class JavaScriptConfigEvaluatorTest extends TestCase
+{
+ public void testEvaluateJavaScript() throws Exception
+ {
+ String jsFilePath = getClass().getResource("JavaScriptConfigEvaluatorTest-test-config.js").toURI().getPath();
+
+ String rawConfig = new JavaScriptConfigEvaluator().evaluateJavaScript(jsFilePath);
+
+ Object configAsObject = getObject(rawConfig);
+
+ // Tests are produced by the QPID.iterations js function
+ assertEquals("Unexpected number of countries", 2, getPropertyAsList(configAsObject, "_countries").size());
+
+ Object country0 = getProperty(configAsObject, "_countries.[0]");
+ assertEquals("Unexpected country name", "Country", getProperty(country0, "_name"));
+ assertEquals("Unexpected country iteration number", 0, getPropertyAsInt(country0, "_iterationNumber"));
+
+ assertEquals("Unexpected number of regions", 2, getPropertyAsList(country0, "_regions").size());
+ // Region names are produced by the QPID.times js function
+ assertEquals("Unexpected region name", "repeatingRegion0", getProperty(country0, "_regions.[0]._name"));
+ assertEquals("Unexpected region name", "repeatingRegion1", getProperty(country0, "_regions.[1]._name"));
+ // Iterating attribute are produced by the QPID.iterations js function
+ assertEquals("Unexpected iterating attribute", "0", getProperty(country0, "_regions.[0]._towns.[0]._iteratingAttribute"));
+
+ Object country1 = getProperty(configAsObject, "_countries.[1]");
+ assertEquals("Unexpected country iteration number", 1, getPropertyAsInt(country1, "_iterationNumber"));
+ assertEquals("Unexpected iterating attribute", "1", getProperty(country1, "_regions.[0]._towns.[0]._iteratingAttribute"));
+ }
+
+ private int getPropertyAsInt(Object configAsObject, String property) throws Exception
+ {
+ Number propertyValue = (Number) getProperty(configAsObject, property);
+
+ return propertyValue.intValue();
+ }
+
+ private List<?> getPropertyAsList(Object configAsObject, String property)
+ throws Exception
+ {
+ return (List<?>)getProperty(configAsObject, property);
+ }
+
+ private Object getObject(String jsonStringIn)
+ {
+ Gson gson = new Gson();
+ @SuppressWarnings("rawtypes")
+ TreeMap object = gson.fromJson(jsonStringIn, TreeMap.class);
+ return object;
+ }
+}
diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/ParticipantConfigTest.java b/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/ParticipantConfigTest.java
new file mode 100644
index 0000000000..f58cc628a4
--- /dev/null
+++ b/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/ParticipantConfigTest.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.disttest.controller.config;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+
+import org.apache.qpid.disttest.message.CreateParticpantCommand;
+import org.apache.qpid.test.utils.QpidTestCase;
+
+public class ParticipantConfigTest extends QpidTestCase
+{
+ public void testCreateProducerCommandAppliesDurationOverride()
+ {
+ long overriddenDuration = 123;
+ setTestSystemProperty(ParticipantConfig.DURATION_OVERRIDE_SYSTEM_PROPERTY, String.valueOf(overriddenDuration));
+
+ CreateParticpantCommand createParticipantCommand = mock(CreateParticpantCommand.class);
+ ParticipantConfig participantConfig = new ParticipantConfig("name", "destinationName", 1, 2, 5000)
+ {
+ };
+
+ participantConfig.setParticipantProperties(createParticipantCommand);
+
+ verify(createParticipantCommand).setMaximumDuration(overriddenDuration);
+ }
+}
diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/message/ParticipantResultTest.java b/java/perftests/src/test/java/org/apache/qpid/disttest/message/ParticipantResultTest.java
index 12731c06f4..34727a7b8d 100644
--- a/java/perftests/src/test/java/org/apache/qpid/disttest/message/ParticipantResultTest.java
+++ b/java/perftests/src/test/java/org/apache/qpid/disttest/message/ParticipantResultTest.java
@@ -22,7 +22,7 @@ import static org.apache.qpid.disttest.message.ParticipantAttribute.*;
import static org.apache.qpid.disttest.message.ParticipantAttribute.CONFIGURED_CLIENT_NAME;
import static org.apache.qpid.disttest.message.ParticipantAttribute.DELIVERY_MODE;
import static org.apache.qpid.disttest.message.ParticipantAttribute.ERROR_MESSAGE;
-import static org.apache.qpid.disttest.message.ParticipantAttribute.IS_BROWSIING_SUBSCRIPTION;
+import static org.apache.qpid.disttest.message.ParticipantAttribute.IS_BROWSING_SUBSCRIPTION;
import static org.apache.qpid.disttest.message.ParticipantAttribute.IS_DURABLE_SUBSCRIPTION;
import static org.apache.qpid.disttest.message.ParticipantAttribute.IS_NO_LOCAL;
import static org.apache.qpid.disttest.message.ParticipantAttribute.IS_SELECTOR;
@@ -127,7 +127,7 @@ public class ParticipantResultTest extends TestCase
assertEquals(topic, result.getAttributes().get(IS_TOPIC));
assertEquals(durable, result.getAttributes().get(IS_DURABLE_SUBSCRIPTION));
- assertEquals(browsingSubscription, result.getAttributes().get(IS_BROWSIING_SUBSCRIPTION));
+ assertEquals(browsingSubscription, result.getAttributes().get(IS_BROWSING_SUBSCRIPTION));
assertEquals(selector, result.getAttributes().get(IS_SELECTOR));
assertEquals(noLocal, result.getAttributes().get(IS_NO_LOCAL));
assertEquals(synchronousConsumer, result.getAttributes().get(IS_SYNCHRONOUS_CONSUMER));
diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/logging/LoggingTableContentProvider.java b/java/perftests/src/test/java/org/apache/qpid/disttest/results/aggregation/SeriesStatisticsTest.java
index 8a618580a2..ec8da8418f 100644
--- a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/logging/LoggingTableContentProvider.java
+++ b/java/perftests/src/test/java/org/apache/qpid/disttest/results/aggregation/SeriesStatisticsTest.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
@@ -18,34 +18,26 @@
* under the License.
*
*/
-package org.apache.qpid.management.ui.views.logging;
-
-import org.eclipse.jface.viewers.IStructuredContentProvider;
-import org.eclipse.jface.viewers.Viewer;
+package org.apache.qpid.disttest.results.aggregation;
-import javax.management.openmbean.TabularDataSupport;
+import java.util.Arrays;
import java.util.Collection;
-/**
- * Content Provider class for theLogging Management table viewers
- */
-public class LoggingTableContentProvider implements IStructuredContentProvider
+import junit.framework.TestCase;
+
+public class SeriesStatisticsTest extends TestCase
{
-
- public void inputChanged(Viewer v, Object oldInput, Object newInput)
- {
-
- }
-
- public void dispose()
- {
-
- }
-
- public Object[] getElements(Object parent)
+ public static Collection<Long> SERIES = Arrays.asList(new Long[] { 2l, 4l, 4l, 4l, 5l, 5l, 7l, 9l, 5l });
+
+ public void testAggregate()
{
- Collection<Object> rowCollection = ((TabularDataSupport) parent).values();
-
- return rowCollection.toArray();
+ SeriesStatistics results = new SeriesStatistics();
+ results.addMessageLatencies(SERIES);
+ results.aggregate();
+ assertEquals("Unexpected average", 5.0, results.getAverage(), 0.01);
+ assertEquals("Unexpected min", 2, results.getMinimum());
+ assertEquals("Unexpected max", 9, results.getMaximum());
+ assertEquals("Unexpected standard deviation", 2.0, results.getStandardDeviation(), 0.01);
}
-} \ No newline at end of file
+
+}
diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/results/aggregation/TestResultAggregatorTest.java b/java/perftests/src/test/java/org/apache/qpid/disttest/results/aggregation/TestResultAggregatorTest.java
index a803120cc6..9c00e7cf1c 100644
--- a/java/perftests/src/test/java/org/apache/qpid/disttest/results/aggregation/TestResultAggregatorTest.java
+++ b/java/perftests/src/test/java/org/apache/qpid/disttest/results/aggregation/TestResultAggregatorTest.java
@@ -19,6 +19,7 @@
package org.apache.qpid.disttest.results.aggregation;
import java.util.Date;
+import java.util.List;
import junit.framework.TestCase;
@@ -26,8 +27,6 @@ import org.apache.qpid.disttest.controller.TestResult;
import org.apache.qpid.disttest.message.ConsumerParticipantResult;
import org.apache.qpid.disttest.message.ParticipantResult;
import org.apache.qpid.disttest.message.ProducerParticipantResult;
-import org.apache.qpid.disttest.results.aggregation.AggregatedTestResult;
-import org.apache.qpid.disttest.results.aggregation.TestResultAggregator;
public class TestResultAggregatorTest extends TestCase
{
@@ -105,6 +104,55 @@ public class TestResultAggregatorTest extends TestCase
assertEquals(TestResultAggregator.AGGREGATED_ERROR_MESSAGE, aggregatedTestResult.getAllParticipantResult().getErrorMessage());
}
+ public void testAggregateResultsForConsumerWithLatencyResults() throws Exception
+ {
+ TestResult originalTestResult = createResultsFromTest();
+ List<ParticipantResult> results = originalTestResult.getParticipantResults();
+ for (ParticipantResult participantResult : results)
+ {
+ if (participantResult instanceof ConsumerParticipantResult)
+ {
+ ((ConsumerParticipantResult)participantResult).setMessageLatencies(SeriesStatisticsTest.SERIES);
+ break;
+ }
+ }
+
+ int numberOfOriginalParticipantResults = originalTestResult.getParticipantResults().size();
+ int expectedNumberOfResults = numberOfOriginalParticipantResults + EXPECTED_NUMBER_OF_AGGREGATED_RESULTS;
+
+ AggregatedTestResult aggregatedTestResult = _aggregator.aggregateTestResult(originalTestResult);
+
+ aggregatedTestResult.getAllConsumerParticipantResult().getTotalPayloadProcessed();
+ assertEquals(expectedNumberOfResults, aggregatedTestResult.getParticipantResults().size());
+
+ assertMinimalAggregatedResults(
+ aggregatedTestResult.getAllConsumerParticipantResult(),
+ TEST1_NAME, TEST1_ITERATION_NUMBER,
+ BATCH_SIZE, NUMBER_OF_MESSAGES_CONSUMED_IN_TOTAL, 2, 0);
+
+ assertLatencyAggregatedResults(aggregatedTestResult.getAllConsumerParticipantResult());
+
+ assertMinimalAggregatedResults(
+ aggregatedTestResult.getAllProducerParticipantResult(),
+ TEST1_NAME, TEST1_ITERATION_NUMBER,
+ BATCH_SIZE, NUMBER_OF_MESSAGES_PRODUCED, 0, 1);
+
+ assertMinimalAggregatedResults(
+ aggregatedTestResult.getAllParticipantResult(),
+ TEST1_NAME, TEST1_ITERATION_NUMBER,
+ BATCH_SIZE, NUMBER_OF_MESSAGES_CONSUMED_IN_TOTAL, 2, 1);
+ }
+
+ private void assertLatencyAggregatedResults(ParticipantResult allConsumerParticipantResult)
+ {
+ assertTrue("Unexpected result", allConsumerParticipantResult instanceof ConsumerParticipantResult);
+ ConsumerParticipantResult results = (ConsumerParticipantResult)allConsumerParticipantResult;
+ assertEquals("Unexpected average", 5.0, results.getAverageLatency(), 0.01);
+ assertEquals("Unexpected min", 2, results.getMinLatency());
+ assertEquals("Unexpected max", 9, results.getMaxLatency());
+ assertEquals("Unexpected standard deviation", 2.0, results.getLatencyStandardDeviation(), 0.01);
+ }
+
private void assertMinimalAggregatedResults(ParticipantResult result, String expectedTestName, int expectedIterationNumber, int expectedBatchSize, long expectedNumberOfMessagesProcessed, int expectedTotalNumberOfConsumers, int expectedTotalNumberOfProducers)
{
assertEquals("Unexpected test name in " + result.getParticipantName(), expectedTestName, result.getTestName());
diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/results/formatting/CSVFormaterTest.java b/java/perftests/src/test/java/org/apache/qpid/disttest/results/formatting/CSVFormaterTest.java
index 088746d8cd..565f59d25b 100644
--- a/java/perftests/src/test/java/org/apache/qpid/disttest/results/formatting/CSVFormaterTest.java
+++ b/java/perftests/src/test/java/org/apache/qpid/disttest/results/formatting/CSVFormaterTest.java
@@ -22,7 +22,7 @@ import static org.apache.qpid.disttest.message.ParticipantAttribute.BATCH_SIZE;
import static org.apache.qpid.disttest.message.ParticipantAttribute.CONFIGURED_CLIENT_NAME;
import static org.apache.qpid.disttest.message.ParticipantAttribute.*;
import static org.apache.qpid.disttest.message.ParticipantAttribute.ERROR_MESSAGE;
-import static org.apache.qpid.disttest.message.ParticipantAttribute.IS_BROWSIING_SUBSCRIPTION;
+import static org.apache.qpid.disttest.message.ParticipantAttribute.IS_BROWSING_SUBSCRIPTION;
import static org.apache.qpid.disttest.message.ParticipantAttribute.IS_DURABLE_SUBSCRIPTION;
import static org.apache.qpid.disttest.message.ParticipantAttribute.IS_NO_LOCAL;
import static org.apache.qpid.disttest.message.ParticipantAttribute.IS_SELECTOR;
@@ -58,7 +58,6 @@ import org.apache.qpid.disttest.controller.ResultsForAllTests;
import org.apache.qpid.disttest.controller.TestResult;
import org.apache.qpid.disttest.message.ParticipantAttribute;
import org.apache.qpid.disttest.message.ParticipantResult;
-import org.apache.qpid.qmf.QMFProperty.AccessCode;
public class CSVFormaterTest extends TestCase
{
@@ -109,7 +108,7 @@ public class CSVFormaterTest extends TestCase
participantAttributes.put(PRODUCER_INTERVAL, 9);
participantAttributes.put(IS_TOPIC, true);
participantAttributes.put(IS_DURABLE_SUBSCRIPTION, false);
- participantAttributes.put(IS_BROWSIING_SUBSCRIPTION, true);
+ participantAttributes.put(IS_BROWSING_SUBSCRIPTION, true);
participantAttributes.put(IS_SELECTOR, false);
participantAttributes.put(IS_NO_LOCAL, true);
participantAttributes.put(IS_SYNCHRONOUS_CONSUMER, false);
@@ -119,7 +118,10 @@ public class CSVFormaterTest extends TestCase
participantAttributes.put(THROUGHPUT, 2048);
participantAttributes.put(TIME_TAKEN, 1000);
participantAttributes.put(ERROR_MESSAGE, "error");
-
+ participantAttributes.put(MIN_LATENCY, 2l);
+ participantAttributes.put(MAX_LATENCY, 9l);
+ participantAttributes.put(AVERAGE_LATENCY, 5.0f);
+ participantAttributes.put(LATENCY_STANDARD_DEVIATION, 2.0f);
return participantAttributes;
}
diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/results/formatting/expectedOutput.csv b/java/perftests/src/test/java/org/apache/qpid/disttest/results/formatting/expectedOutput.csv
index cfffb1e549..ada2303d46 100644
--- a/java/perftests/src/test/java/org/apache/qpid/disttest/results/formatting/expectedOutput.csv
+++ b/java/perftests/src/test/java/org/apache/qpid/disttest/results/formatting/expectedOutput.csv
@@ -1,2 +1,2 @@
-testName,iterationNumber,clientName,participantName,numberOfMessages,payloadSizeB,priority,timeToLiveMs,acknowledgeMode,deliveryMode,batchSize,maximumDurationMs,producerStartDelayMs,producerIntervalMs,isTopic,isDurableSubscription,isBrowsingSubscription,isSelector,isNoLocal,isSynchronousConsumer,totalNumberOfConsumers,totalNumberOfProducers,totalPayloadProcessedB,throughputKbPerS,timeTakenMs,errorMessage
-TEST1,0,CONFIGURED_CLIENT1,PARTICIPANT,0,1,2,3,4,5,6,7,8,9,true,false,true,false,true,false,1,2,1024,2048,1000,error \ No newline at end of file
+testName,iterationNumber,clientName,participantName,numberOfMessages,payloadSizeB,priority,timeToLiveMs,acknowledgeMode,deliveryMode,batchSize,maximumDurationMs,producerStartDelayMs,producerIntervalMs,isTopic,isDurableSubscription,isBrowsingSubscription,isSelector,isNoLocal,isSynchronousConsumer,totalNumberOfConsumers,totalNumberOfProducers,totalPayloadProcessedB,throughputKbPerS,timeTakenMs,errorMessage,minLatency,maxLatency,averageLatency,latencyStandardDeviation
+TEST1,0,CONFIGURED_CLIENT1,PARTICIPANT,0,1,2,3,4,5,6,7,8,9,true,false,true,false,true,false,1,2,1024,2048,1000,error,2,9,5.0,2.0
diff --git a/java/perftests/src/test/java/org/apache/qpid/systest/disttest/clientonly/ControllerQueue.java b/java/perftests/src/test/java/org/apache/qpid/systest/disttest/clientonly/ControllerQueue.java
index 7f0c23eb38..75783eef4b 100644
--- a/java/perftests/src/test/java/org/apache/qpid/systest/disttest/clientonly/ControllerQueue.java
+++ b/java/perftests/src/test/java/org/apache/qpid/systest/disttest/clientonly/ControllerQueue.java
@@ -1,3 +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.
+ *
+ */
package org.apache.qpid.systest.disttest.clientonly;
import java.util.Map;
@@ -66,7 +86,7 @@ public class ControllerQueue
public <T extends Command> T getNext(boolean assertMessageExists) throws JMSException
{
- final Message message = _controllerQueueMessageConsumer.receive(1000);
+ final Message message = _controllerQueueMessageConsumer.receive(2000);
if(assertMessageExists)
{
Assert.assertNotNull("No message received from control queue", message);
diff --git a/java/perftests/src/test/java/org/apache/qpid/systest/disttest/clientonly/DistributedClientTest.java b/java/perftests/src/test/java/org/apache/qpid/systest/disttest/clientonly/DistributedClientTest.java
index 4a872a7ee2..5b5a60ac43 100644
--- a/java/perftests/src/test/java/org/apache/qpid/systest/disttest/clientonly/DistributedClientTest.java
+++ b/java/perftests/src/test/java/org/apache/qpid/systest/disttest/clientonly/DistributedClientTest.java
@@ -32,6 +32,7 @@ import javax.jms.MessageProducer;
import javax.jms.Queue;
import javax.jms.Session;
+import org.apache.qpid.client.AMQSession;
import org.apache.qpid.disttest.client.Client;
import org.apache.qpid.disttest.client.ClientState;
import org.apache.qpid.disttest.jms.ClientJmsDelegate;
@@ -158,7 +159,7 @@ public class DistributedClientTest extends DistributedTestSystemTestBase
assertState(_client, RUNNING_TEST);
}
- public void testParticipantsSendResults() throws JMSException
+ public void testParticipantsSendResults() throws Exception
{
createTestProducer(TEST_SESSION_NAME, TEST_PRODUCER_NAME, TEST_DESTINATION);
@@ -204,20 +205,21 @@ public class DistributedClientTest extends DistributedTestSystemTestBase
assertState(_client, READY);
}
- private void sendCommandToClient(final Command command) throws JMSException
+ private void sendCommandToClient(final Command command) throws Exception
{
final Message message = JmsMessageAdaptor.commandToMessage(_session, command);
_clientQueueProducer.send(message);
+ ((AMQSession<?, ?>)_session).sync();
}
- private void sendCommandAndValidateResponse(final Command command, boolean shouldSucceed) throws JMSException
+ private void sendCommandAndValidateResponse(final Command command, boolean shouldSucceed) throws Exception
{
sendCommandToClient(command);
Response response = _controllerQueue.getNext();
validateResponse(command.getType(), response, shouldSucceed);
}
- private void sendCommandAndValidateResponse(final Command command) throws JMSException
+ private void sendCommandAndValidateResponse(final Command command) throws Exception
{
sendCommandAndValidateResponse(command, true);
}
@@ -258,7 +260,7 @@ public class DistributedClientTest extends DistributedTestSystemTestBase
createTestSession(connectionName, sessionName, true);
}
- private void createTestProducer(String sessionName, String producerName, String destinationName, boolean shouldSucceed) throws JMSException
+ private void createTestProducer(String sessionName, String producerName, String destinationName, boolean shouldSucceed) throws Exception
{
final CreateProducerCommand createProducerCommand = new CreateProducerCommand();
createProducerCommand.setParticipantName(producerName);
@@ -269,12 +271,12 @@ public class DistributedClientTest extends DistributedTestSystemTestBase
sendCommandAndValidateResponse(createProducerCommand, shouldSucceed);
}
- private void createTestProducer(String sessionName, String producerName, String destinationName) throws JMSException
+ private void createTestProducer(String sessionName, String producerName, String destinationName) throws Exception
{
createTestProducer(sessionName, producerName, destinationName, true);
}
- private void createTestConsumer(String sessionName, String consumerName, String destinationName, boolean shouldSucceed) throws JMSException
+ private void createTestConsumer(String sessionName, String consumerName, String destinationName, boolean shouldSucceed) throws Exception
{
final CreateConsumerCommand createConsumerCommand = new CreateConsumerCommand();
createConsumerCommand.setSessionName(sessionName);
@@ -285,7 +287,7 @@ public class DistributedClientTest extends DistributedTestSystemTestBase
sendCommandAndValidateResponse(createConsumerCommand, shouldSucceed);
}
- private void createTestConsumer(String sessionName, String consumerName, String destinationName) throws JMSException
+ private void createTestConsumer(String sessionName, String consumerName, String destinationName) throws Exception
{
createTestConsumer(sessionName, consumerName, destinationName, true);
}
diff --git a/java/perftests/src/test/java/org/apache/qpid/systest/disttest/controllerandclient/ControllerAndClientTest.java b/java/perftests/src/test/java/org/apache/qpid/systest/disttest/controllerandclient/ControllerAndClientTest.java
index 9fd90d3215..ddb4cb7e51 100644
--- a/java/perftests/src/test/java/org/apache/qpid/systest/disttest/controllerandclient/ControllerAndClientTest.java
+++ b/java/perftests/src/test/java/org/apache/qpid/systest/disttest/controllerandclient/ControllerAndClientTest.java
@@ -23,6 +23,7 @@ import static org.apache.qpid.systest.disttest.SystemTestConstants.COMMAND_RESPO
import static org.apache.qpid.systest.disttest.SystemTestConstants.REGISTRATION_TIMEOUT;
import static org.apache.qpid.systest.disttest.SystemTestConstants.TEST_RESULT_TIMEOUT;
+import java.util.Collection;
import java.util.List;
import javax.jms.Message;
@@ -31,7 +32,7 @@ import javax.jms.Queue;
import javax.jms.Session;
import javax.naming.NamingException;
-import org.apache.qpid.disttest.ConfigFileHelper;
+import org.apache.qpid.disttest.ConfigFileTestHelper;
import org.apache.qpid.disttest.client.Client;
import org.apache.qpid.disttest.client.ClientState;
import org.apache.qpid.disttest.controller.Controller;
@@ -73,6 +74,19 @@ public class ControllerAndClientTest extends DistributedTestSystemTestBase
List<ParticipantResult> test1ParticipantResults = testResult1.getParticipantResults();
assertEquals("Unexpected number of participant results for test 1", 2, test1ParticipantResults.size());
assertParticipantNames(test1ParticipantResults, "participantConsumer1", "participantProducer1");
+ ConsumerParticipantResult result = null;
+ for (ParticipantResult participantResult : test1ParticipantResults)
+ {
+ if (participantResult instanceof ConsumerParticipantResult)
+ {
+ result = (ConsumerParticipantResult)participantResult;
+ break;
+ }
+ }
+ assertNotNull("Consumer results not recived", result);
+ Collection<Long> latencies = result.getMessageLatencies();
+ assertNotNull("Latency results are not collected", latencies);
+ assertEquals("Unexpected latency results", 1, latencies.size());
}
public void testProducerClient() throws Exception
@@ -86,7 +100,7 @@ public class ControllerAndClientTest extends DistributedTestSystemTestBase
// cleaning manually
while(consumer.receive(1000l) != null);
- final Config config = ConfigFileHelper.getConfigFromResource(getClass(), "produceClient.json");
+ final Config config = ConfigFileTestHelper.getConfigFromResource(getClass(), "produceClient.json");
_controller.setConfig(config);
final Client client1 = new Client(new ClientJmsDelegate(_context));
final Thread client1Thread = createBackgroundClientThread(client1);
@@ -151,7 +165,7 @@ public class ControllerAndClientTest extends DistributedTestSystemTestBase
List<ParticipantResult> test1ParticipantResults = testResult.getParticipantResults();
assertEquals("Unexpected number of participant results for test", 2, test1ParticipantResults.size());
- ParticipantResult producer1 = (ParticipantResult) test1ParticipantResults.get(1);
+ ParticipantResult producer1 = test1ParticipantResults.get(1);
assertEquals(expectedMessageSize, producer1.getPayloadSize());
assertEquals(iterationNumber, producer1.getIterationNumber());
@@ -167,7 +181,7 @@ public class ControllerAndClientTest extends DistributedTestSystemTestBase
private List<TestResult> runTestsForTwoClients(String jsonConfigFile, int expectedNumberOfTests) throws NamingException, InterruptedException
{
- final Config config = ConfigFileHelper.getConfigFromResource(getClass(), jsonConfigFile);
+ final Config config = ConfigFileTestHelper.getConfigFromResource(getClass(), jsonConfigFile);
_controller.setConfig(config);
final Client client1 = new Client(new ClientJmsDelegate(_context));
diff --git a/java/perftests/src/test/java/org/apache/qpid/systest/disttest/controllerandclient/producerAndConsumerInSeparateClients.json b/java/perftests/src/test/java/org/apache/qpid/systest/disttest/controllerandclient/producerAndConsumerInSeparateClients.json
index 8d210dce84..a008dc40d8 100644
--- a/java/perftests/src/test/java/org/apache/qpid/systest/disttest/controllerandclient/producerAndConsumerInSeparateClients.json
+++ b/java/perftests/src/test/java/org/apache/qpid/systest/disttest/controllerandclient/producerAndConsumerInSeparateClients.json
@@ -42,7 +42,8 @@
{
"_name": "participantConsumer1",
"_destinationName": "direct://amq.direct//testQueue",
- "_numberOfMessages": 1
+ "_numberOfMessages": 1,
+ "_evaluateLatency": true
}
]
}
diff --git a/java/perftests/src/test/java/org/apache/qpid/systest/disttest/controlleronly/DistributedControllerTest.java b/java/perftests/src/test/java/org/apache/qpid/systest/disttest/controlleronly/DistributedControllerTest.java
index ad7f0e0682..74c4724901 100644
--- a/java/perftests/src/test/java/org/apache/qpid/systest/disttest/controlleronly/DistributedControllerTest.java
+++ b/java/perftests/src/test/java/org/apache/qpid/systest/disttest/controlleronly/DistributedControllerTest.java
@@ -38,7 +38,7 @@ import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TemporaryQueue;
-import org.apache.qpid.disttest.ConfigFileHelper;
+import org.apache.qpid.disttest.ConfigFileTestHelper;
import org.apache.qpid.disttest.controller.Controller;
import org.apache.qpid.disttest.controller.config.Config;
import org.apache.qpid.disttest.jms.ControllerJmsDelegate;
@@ -96,7 +96,7 @@ public class DistributedControllerTest extends DistributedTestSystemTestBase
public void testControllerSendsOneCommandToSingleClient() throws Exception
{
- Config config = ConfigFileHelper.getConfigFromResource(getClass(), "distributedControllerTest.json");
+ Config config = ConfigFileTestHelper.getConfigFromResource(getClass(), "distributedControllerTest.json");
_controller.setConfig(config);
sendRegistration(CLIENT1);
diff --git a/java/perftests/src/test/java/org/apache/qpid/systest/disttest/endtoend/EndToEndTest.java b/java/perftests/src/test/java/org/apache/qpid/systest/disttest/endtoend/EndToEndTest.java
index 63c9b42858..7e58e1b5b1 100644
--- a/java/perftests/src/test/java/org/apache/qpid/systest/disttest/endtoend/EndToEndTest.java
+++ b/java/perftests/src/test/java/org/apache/qpid/systest/disttest/endtoend/EndToEndTest.java
@@ -62,10 +62,10 @@ public class EndToEndTest extends QpidBrokerTestCase
assertEquals("Unexpected number of lines in CSV", numberOfExpectedRows, csvLines.length);
assertDataRowsHaveCorrectTestAndClientName("End To End 1", "producingClient", "participantProducer1", csvLines[1], 1);
- assertDataRowsHaveCorrectTestAndClientName("End To End 1", "consumingClient", "participantConsumer1", csvLines[2], 1);
+ assertDataRowsHaveCorrectTestAndClientName("End To End 1", "consumingClient", "participantConsumer1", csvLines[3], 1);
- assertDataRowsHaveCorrectTestAndClientName("End To End 1", "", TestResultAggregator.ALL_PARTICIPANTS_NAME, csvLines[3], 1);
- assertDataRowsHaveCorrectTestAndClientName("End To End 1", "", TestResultAggregator.ALL_CONSUMER_PARTICIPANTS_NAME, csvLines[4], 1);
+ assertDataRowsHaveCorrectTestAndClientName("End To End 1", "", TestResultAggregator.ALL_PARTICIPANTS_NAME, csvLines[4], 1);
+ assertDataRowsHaveCorrectTestAndClientName("End To End 1", "", TestResultAggregator.ALL_CONSUMER_PARTICIPANTS_NAME, csvLines[2], 1);
assertDataRowsHaveCorrectTestAndClientName("End To End 1", "", TestResultAggregator.ALL_PRODUCER_PARTICIPANTS_NAME, csvLines[5], 1);
}
diff --git a/java/perftests/visualisation-jfc/build.xml b/java/perftests/visualisation-jfc/build.xml
index b838855e8b..02c9f5dcbd 100644
--- a/java/perftests/visualisation-jfc/build.xml
+++ b/java/perftests/visualisation-jfc/build.xml
@@ -16,37 +16,59 @@
- specific language governing permissions and limitations
- under the License.
-->
-<project name="visualisation-jfc" default="build">
+<project name="visualisation-jfc" xmlns:ivy="antlib:org.apache.ivy.ant" default="build">
<property name="module.depends" value="common perftests" />
- <property name="module.test.depends" value="test" />
+ <property name="module.test.depends" value="test common/test" />
+
+ <property name="module.manifest" value="true" />
<import file="../../module.xml" />
+ <!-- Overridden to produce Manifest containing Main-Class and Class-Path -->
+ <target name="jar.manifest" depends="compile" if="module.manifest">
+ <path id="class.path">
+ <fileset dir="${build.lib}" >
+ <include name="*.jar"/>
+ <exclude name="${qpid.jar.name}"/>
+ </fileset>
+ </path>
+ <pathconvert property="qpid.jar.classpath" pathsep=" " dirsep="/">
+ <path refid="class.path"/>
+ <globmapper from="${build.lib}${file.separator}*" to="*"/>
+ </pathconvert>
+
+ <jar destfile="${module.jar}" basedir="${module.classes}">
+ <manifest>
+ <attribute name="Class-Path" value="${qpid.jar.classpath}"/>
+ <attribute name="Main-Class" value="org.apache.qpid.disttest.charting.ChartingUtil"/>
+ </manifest>
+ </jar>
+ </target>
<!-- JFreeChart and JFreeCommon -->
-
- <property name="jfree.lib.dir" value="${project.root}/lib/jfree" />
- <property name="jfreechart.version" value="1.0.13" />
- <property name="jfreecommon.version" value="1.0.16" />
- <property name="jfreechart.download.url" value="http://repo1.maven.org/maven2/jfree/jfreechart/${jfreechart.version}/jfreechart-${jfreechart.version}.jar" />
- <property name="jfreecommon.download.url" value="http://repo1.maven.org/maven2/jfree/jcommon/${jfreecommon.version}/jcommon-${jfreecommon.version}.jar" />
- <property name="jfreechart.jar.file" value="${jfree.lib.dir}/jfreechart-${jfreechart.version}.jar" />
- <property name="jfreecommon.jar.file" value="${jfree.lib.dir}/jfreecommon-${jfreecommon.version}.jar" />
+ <condition property="download.jfree.jars">
+ <or>
+ <istrue value="${download-jfree}"/>
+ <istrue value="${optional.dependencies}"/>
+ <istrue value="${optional}"/>
+ </or>
+ </condition>
<!-- CSVJDBC -->
-
- <property name="csvjdbc.lib.dir" value="${project.root}/lib/csvjdbc" />
- <property name="csvjdbc.version" value="1.0.8" />
- <property name="csvjdbc.download.url" value="http://csvjdbc.sourceforge.net/maven2/net/sourceforge/csvjdbc/csvjdbc/${csvjdbc.version}/csvjdbc-${csvjdbc.version}.jar" />
-
- <property name="csvjdbc.jar.file" value="${csvjdbc.lib.dir}/csvjdbc-${csvjdbc.version}.jar" />
+ <condition property="download.csvjdbc.jar">
+ <or>
+ <istrue value="${download-csvjdbc}"/>
+ <istrue value="${optional.dependencies}"/>
+ <istrue value="${optional}"/>
+ </or>
+ </condition>
<!--check whether the JFree jar is present, possibly after download-->
<target name="check-jfree-jars">
<condition property="jfree.available">
<and>
- <available file="${jfreechart.jar.file}"/>
- <available file="${jfreecommon.jar.file}"/>
+ <available file="${project.root}/${jfreechart.jar}"/>
+ <available file="${project.root}/${jcommon.jar}"/>
</and>
</condition>
</target>
@@ -81,12 +103,12 @@ http://www.gnu.org/licenses/lgpl.html
<target name="check-csvjdbc-jars">
<condition property="csvjdbc.available">
- <available file="${csvjdbc.jar.file}"/>
+ <available file="${project.root}/${csvjdbc.jar}"/>
</condition>
</target>
<!--check if an inline JFree download was requested with the build-->
- <target name="checkjfree-request-props" if="download-jfree">
+ <target name="checkjfree-request-props" if="download.jfree.jars">
<antcall target="download-jfree"/>
</target>
@@ -119,21 +141,22 @@ http://www.gnu.org/licenses/lgpl.html
</target>
<!--download JFree, with licencing note-->
- <target name="download-jfree" depends="jfree-licence-note">
- <mkdir dir="${jfree.lib.dir}"/>
- <echo>Downloading JFreeChart</echo>
- <get src="${jfreechart.download.url}" dest="${jfreechart.jar.file}" usetimestamp="true" />
- <get src="${jfreecommon.download.url}" dest="${jfreecommon.jar.file}" usetimestamp="true" />
+ <target name="download-jfree" depends="jfree-licence-note, load-ivy, configure-ivy" unless="${ivy.dont.retrieve}">
+ <echo message="Resolving and retrieving dependencies..."/>
+ <ivy:resolve type="jar" file="${project.root}/ivy.retrieve.xml" conf="jfree"/>
+ <ivy:retrieve type="jar" conf="jfree" sync="true"
+ pattern="${project.root}/lib/jfree/[artifact]-[revision].[ext]" />
</target>
- <target name="checkcsvjdbc-request-props" if="download-csvjdbc">
+ <target name="checkcsvjdbc-request-props" if="download.csvjdbc.jar">
<antcall target="download-csvjdbc"/>
</target>
- <target name="download-csvjdbc" depends="csvjdbc-licence-note">
- <mkdir dir="${csvjdbc.lib.dir}"/>
- <echo>Downloading csvjdbc</echo>
- <get src="${csvjdbc.download.url}" dest="${csvjdbc.jar.file}" usetimestamp="true" />
+ <target name="download-csvjdbc" depends="csvjdbc-licence-note, load-ivy, configure-ivy" unless="${ivy.dont.retrieve}">
+ <echo message="Resolving and retrieving dependencies..."/>
+ <ivy:resolve type="jar" file="${project.root}/ivy.retrieve.xml" conf="csvjdbc"/>
+ <ivy:retrieve type="jar" conf="csvjdbc" sync="true"
+ pattern="${project.root}/lib/csvjdbc/[artifact]-[revision].[ext]" />
</target>
<target name="build" depends="checkjfree-request-props, jfree-jar-required, checkcsvjdbc-request-props, csvjdbc-jar-required, module.build" />
diff --git a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/ChartType.java b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/ChartType.java
index 2803f2d767..ed09f4a77e 100644
--- a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/ChartType.java
+++ b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/ChartType.java
@@ -21,6 +21,5 @@ package org.apache.qpid.disttest.charting;
public enum ChartType
{
- LINE, BAR
-
+ LINE, LINE3D, BAR, BAR3D, XYLINE, STATISTICAL_BAR
}
diff --git a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/ChartingUtil.java b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/ChartingUtil.java
index a149d1a097..e00859855e 100644
--- a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/ChartingUtil.java
+++ b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/ChartingUtil.java
@@ -20,11 +20,7 @@
*/
package org.apache.qpid.disttest.charting;
-import java.io.BufferedOutputStream;
import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -34,11 +30,24 @@ import org.apache.qpid.disttest.charting.chartbuilder.ChartBuilder;
import org.apache.qpid.disttest.charting.chartbuilder.ChartBuilderFactory;
import org.apache.qpid.disttest.charting.definition.ChartingDefinition;
import org.apache.qpid.disttest.charting.definition.ChartingDefinitionCreator;
-import org.jfree.chart.ChartUtilities;
+import org.apache.qpid.disttest.charting.seriesbuilder.JdbcCsvSeriesBuilder;
+import org.apache.qpid.disttest.charting.seriesbuilder.SeriesBuilder;
+import org.apache.qpid.disttest.charting.writer.ChartWriter;
import org.jfree.chart.JFreeChart;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+/**
+ * Draws charts for data drawn from CSV datasources using rules described in
+ * charting definitions (.chartdef) files.
+ * <p>
+ * The following arguments are understood:
+ * </p>
+ * <ol>
+ * <li>chart-defs=<i>directory contain chartdef file(s)</i></li>
+ * <li>output-dir=<i>directory in which to produce the PNGs</i></li>
+ * </ol>
+ */
public class ChartingUtil
{
private static final Logger LOGGER = LoggerFactory.getLogger(ChartingUtil.class);
@@ -59,7 +68,7 @@ public class ChartingUtil
{
try
{
- LOGGER.debug("Starting charting");
+ LOGGER.info("Starting charting");
ChartingUtil chartingUtil = new ChartingUtil();
chartingUtil.parseArgumentsIntoConfig(args);
@@ -67,56 +76,32 @@ public class ChartingUtil
}
finally
{
- LOGGER.debug("Charting complete");
+ LOGGER.info("Charting complete");
}
}
private void produceAllCharts()
{
final String chartingDefsDir = _cliOptions.get(CHART_DEFINITIONS_PROP);
+ final File chartDirectory = new File(_cliOptions.get(OUTPUT_DIR_PROP));
+ LOGGER.info("Chart chartdef directory/file: {} output directory : {}", chartingDefsDir, chartDirectory);
+
List<ChartingDefinition> definitions = loadChartDefinitions(chartingDefsDir);
- LOGGER.debug("There are {} chart(s) to produce", definitions.size());
+ LOGGER.info("There are {} chart(s) to produce", definitions.size());
+
+ final ChartWriter writer = new ChartWriter();
+ writer.setOutputDirectory(chartDirectory);
+ final SeriesBuilder seriesBuilder = new JdbcCsvSeriesBuilder();
for (ChartingDefinition chartingDefinition : definitions)
{
- ChartBuilder chartBuilder = ChartBuilderFactory.createChartBuilder(chartingDefinition.getChartType());
+ ChartBuilder chartBuilder = ChartBuilderFactory.createChartBuilder(chartingDefinition.getChartType(), seriesBuilder);
JFreeChart chart = chartBuilder.buildChart(chartingDefinition);
- writeChartToFileSystem(chart, chartingDefinition.getChartStemName());
+ writer.writeChartToFileSystem(chart, chartingDefinition.getChartStemName());
}
- }
-
- private void writeChartToFileSystem(JFreeChart chart, String chartStemName)
- {
- OutputStream pngOutputStream = null;
- try
- {
-
- File pngFile = new File(chartStemName + ".png");
- pngOutputStream = new BufferedOutputStream(new FileOutputStream(pngFile));
- ChartUtilities.writeChartAsPNG(pngOutputStream, chart, 600, 400, true, 0);
- pngOutputStream.close();
- LOGGER.debug("Written {} chart", pngFile);
- }
- catch (IOException e)
- {
- throw new ChartingException("Failed to create chart", e);
- }
- finally
- {
- if (pngOutputStream != null)
- {
- try
- {
- pngOutputStream.close();
- }
- catch (IOException e)
- {
- throw new ChartingException("Failed to create chart", e);
- }
- }
- }
+ writer.writeHtmlSummaryToFileSystem();
}
private List<ChartingDefinition> loadChartDefinitions(String chartingDefsDir)
@@ -130,6 +115,4 @@ public class ChartingUtil
ArgumentParser argumentParser = new ArgumentParser();
argumentParser.parseArgumentsIntoConfig(_cliOptions, args);
}
-
-
}
diff --git a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/BarChart3DBuilder.java b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/BarChart3DBuilder.java
new file mode 100644
index 0000000000..491bb1c67d
--- /dev/null
+++ b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/BarChart3DBuilder.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.disttest.charting.chartbuilder;
+
+
+import org.apache.qpid.disttest.charting.seriesbuilder.SeriesBuilder;
+import org.jfree.chart.ChartFactory;
+import org.jfree.chart.JFreeChart;
+import org.jfree.chart.plot.PlotOrientation;
+import org.jfree.data.category.CategoryDataset;
+import org.jfree.data.general.Dataset;
+
+public class BarChart3DBuilder extends CategoryDataSetBasedChartBuilder
+{
+
+ public BarChart3DBuilder(SeriesBuilder seriesBuilder)
+ {
+ super(seriesBuilder);
+ }
+
+ @Override
+ public JFreeChart createChartImpl(String title, String xAxisTitle,
+ String yAxisTitle, final Dataset dataset, PlotOrientation plotOrientation,
+ boolean showLegend, boolean showToolTips, boolean showUrls)
+ {
+ JFreeChart chart = ChartFactory.createBarChart3D(title,
+ xAxisTitle,
+ yAxisTitle,
+ (CategoryDataset)dataset,
+ plotOrientation,
+ showLegend,
+ showToolTips,
+ showUrls);
+
+ return chart;
+ }
+
+
+}
diff --git a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/BarChartBuilder.java b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/BarChartBuilder.java
index 302263a604..b5c6a38067 100644
--- a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/BarChartBuilder.java
+++ b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/BarChartBuilder.java
@@ -19,23 +19,30 @@
*/
package org.apache.qpid.disttest.charting.chartbuilder;
+import org.apache.qpid.disttest.charting.seriesbuilder.SeriesBuilder;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.plot.PlotOrientation;
-import org.jfree.data.category.DefaultCategoryDataset;
+import org.jfree.data.category.CategoryDataset;
+import org.jfree.data.general.Dataset;
-public class BarChartBuilder extends DataSetBasedChartBuilder
+public class BarChartBuilder extends CategoryDataSetBasedChartBuilder
{
+ public BarChartBuilder(SeriesBuilder seriesBuilder)
+ {
+ super(seriesBuilder);
+ }
+
@Override
public JFreeChart createChartImpl(String title, String xAxisTitle,
- String yAxisTitle, final DefaultCategoryDataset dataset, PlotOrientation plotOrientation,
+ String yAxisTitle, final Dataset dataset, PlotOrientation plotOrientation,
boolean showLegend, boolean showToolTips, boolean showUrls)
{
JFreeChart chart = ChartFactory.createBarChart(title,
xAxisTitle,
yAxisTitle,
- dataset,
+ (CategoryDataset) dataset,
plotOrientation,
showLegend,
showToolTips,
diff --git a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/BaseChartBuilder.java b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/BaseChartBuilder.java
new file mode 100644
index 0000000000..def87f5840
--- /dev/null
+++ b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/BaseChartBuilder.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.disttest.charting.chartbuilder;
+
+import java.awt.Color;
+import java.awt.GradientPaint;
+
+import org.apache.qpid.disttest.charting.definition.ChartingDefinition;
+import org.jfree.chart.JFreeChart;
+import org.jfree.chart.plot.PlotOrientation;
+import org.jfree.chart.title.ShortTextTitle;
+import org.jfree.data.general.Dataset;
+
+public abstract class BaseChartBuilder implements ChartBuilder
+{
+ private static final GradientPaint BLUE_GRADIENT = new GradientPaint(0, 0, Color.white, 0, 1000, Color.blue);
+
+ public void addCommonChartAttributes(JFreeChart chart, ChartingDefinition chartingDefinition)
+ {
+ addSubtitle(chart, chartingDefinition);
+ setBackgroundColour(chart);
+ }
+
+ private void addSubtitle(JFreeChart chart, ChartingDefinition chartingDefinition)
+ {
+ if (chartingDefinition.getChartSubtitle() != null)
+ {
+ chart.addSubtitle(new ShortTextTitle(chartingDefinition.getChartSubtitle()));
+ }
+ }
+
+ private void setBackgroundColour(JFreeChart chart)
+ {
+ chart.setBackgroundPaint(BLUE_GRADIENT);
+ }
+
+ public abstract JFreeChart createChartImpl(String title, String xAxisTitle,
+ String yAxisTitle, final Dataset dataset, PlotOrientation plotOrientation, boolean showLegend, boolean showToolTips,
+ boolean showUrls);
+
+}
diff --git a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/DataSetBasedChartBuilder.java b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/CategoryDataSetBasedChartBuilder.java
index 6e2491c883..a6c63f4560 100644
--- a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/DataSetBasedChartBuilder.java
+++ b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/CategoryDataSetBasedChartBuilder.java
@@ -19,17 +19,23 @@
*/
package org.apache.qpid.disttest.charting.chartbuilder;
+
import org.apache.qpid.disttest.charting.definition.ChartingDefinition;
import org.apache.qpid.disttest.charting.definition.SeriesDefinition;
+import org.apache.qpid.disttest.charting.seriesbuilder.SeriesBuilderCallback;
+import org.apache.qpid.disttest.charting.seriesbuilder.SeriesBuilder;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.CategoryLabelPositions;
-import org.jfree.chart.plot.PlotOrientation;
import org.jfree.data.category.DefaultCategoryDataset;
-public abstract class DataSetBasedChartBuilder implements ChartBuilder
+public abstract class CategoryDataSetBasedChartBuilder extends BaseChartBuilder
{
- private static final CategoryLabelPositions LABEL_POSITION = CategoryLabelPositions.UP_45;
- private static final PlotOrientation PLOT_ORIENTATION = PlotOrientation.VERTICAL;
+ private final SeriesBuilder _seriesBuilder;
+
+ public CategoryDataSetBasedChartBuilder(SeriesBuilder seriesBuilder)
+ {
+ _seriesBuilder = seriesBuilder;
+ }
@Override
public JFreeChart buildChart(ChartingDefinition chartingDefinition)
@@ -40,29 +46,39 @@ public abstract class DataSetBasedChartBuilder implements ChartBuilder
final DefaultCategoryDataset dataset = new DefaultCategoryDataset();
- SeriesBuilder seriesBuilder = new SeriesBuilder(new DataPointCallback()
+ _seriesBuilder.setSeriesBuilderCallback(new SeriesBuilderCallback()
{
@Override
- public void addDataPointToSeries(SeriesDefinition seriesDefinition,
- Object xValue, Object yValue)
+ public void addDataPointToSeries(SeriesDefinition seriesDefinition, Object[] row)
{
- String x = (String) xValue;
- double y = (Double) yValue;
+ String x = String.valueOf(row[0]);
+ double y = Double.parseDouble(row[1].toString());
dataset.addValue( y, seriesDefinition.getSeriesLegend(), x);
}
+
+ @Override
+ public void beginSeries(SeriesDefinition seriesDefinition)
+ {
+ // unused
+ }
+
+ @Override
+ public void endSeries(SeriesDefinition seriesDefinition)
+ {
+ // unused
+ }
+
});
- seriesBuilder.build(chartingDefinition.getSeries());
+ _seriesBuilder.build(chartingDefinition.getSeries());
JFreeChart chart = createChartImpl(title, xAxisTitle, yAxisTitle,
- dataset, PLOT_ORIENTATION, true, false, false);
+ dataset, PLOT_ORIENTATION, SHOW_LEGEND, SHOW_TOOL_TIPS, SHOW_URLS);
+
+ chart.getCategoryPlot().getDomainAxis().setCategoryLabelPositions(CategoryLabelPositions.UP_45);
- chart.getCategoryPlot().getDomainAxis().setCategoryLabelPositions(LABEL_POSITION);
+ addCommonChartAttributes(chart, chartingDefinition);
return chart;
}
-
- public abstract JFreeChart createChartImpl(String title, String xAxisTitle,
- String yAxisTitle, final DefaultCategoryDataset dataset, PlotOrientation plotOrientation,
- boolean showLegend, boolean showToolTips, boolean showUrls);
}
diff --git a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/ChartBuilder.java b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/ChartBuilder.java
index c6f5ecc175..425b83596f 100644
--- a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/ChartBuilder.java
+++ b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/ChartBuilder.java
@@ -21,10 +21,14 @@ package org.apache.qpid.disttest.charting.chartbuilder;
import org.apache.qpid.disttest.charting.definition.ChartingDefinition;
import org.jfree.chart.JFreeChart;
+import org.jfree.chart.plot.PlotOrientation;
public interface ChartBuilder
{
+ public static final boolean SHOW_URLS = false;
+ public static final boolean SHOW_TOOL_TIPS = false;
+ public static final boolean SHOW_LEGEND = true;
+ public static final PlotOrientation PLOT_ORIENTATION = PlotOrientation.VERTICAL;
public JFreeChart buildChart(ChartingDefinition chartingDefinition);
-
}
diff --git a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/ChartBuilderFactory.java b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/ChartBuilderFactory.java
index 4c5d4fa09f..f4e11a2c4d 100644
--- a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/ChartBuilderFactory.java
+++ b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/ChartBuilderFactory.java
@@ -20,18 +20,27 @@
package org.apache.qpid.disttest.charting.chartbuilder;
import org.apache.qpid.disttest.charting.ChartType;
+import org.apache.qpid.disttest.charting.seriesbuilder.SeriesBuilder;
public class ChartBuilderFactory
{
- public static ChartBuilder createChartBuilder(ChartType chartType)
+ public static ChartBuilder createChartBuilder(ChartType chartType, SeriesBuilder seriesBuilder)
{
switch (chartType)
{
case LINE:
- return new LineChartBuilder();
+ return new LineChartBuilder(seriesBuilder);
+ case LINE3D:
+ return new LineChart3DBuilder(seriesBuilder);
case BAR:
- return new BarChartBuilder();
+ return new BarChartBuilder(seriesBuilder);
+ case BAR3D:
+ return new BarChart3DBuilder(seriesBuilder);
+ case XYLINE:
+ return new XYLineChartBuilder(seriesBuilder);
+ case STATISTICAL_BAR:
+ return new StatisticalBarCharBuilder(seriesBuilder);
default:
throw new IllegalArgumentException("Unknown chart type " + chartType);
}
diff --git a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/LineChart3DBuilder.java b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/LineChart3DBuilder.java
new file mode 100644
index 0000000000..27fff12da0
--- /dev/null
+++ b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/LineChart3DBuilder.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.disttest.charting.chartbuilder;
+
+import org.apache.qpid.disttest.charting.seriesbuilder.SeriesBuilder;
+import org.jfree.chart.ChartFactory;
+import org.jfree.chart.JFreeChart;
+import org.jfree.chart.plot.PlotOrientation;
+import org.jfree.data.category.CategoryDataset;
+import org.jfree.data.general.Dataset;
+
+public class LineChart3DBuilder extends CategoryDataSetBasedChartBuilder
+{
+ public LineChart3DBuilder(SeriesBuilder seriesBuilder)
+ {
+ super(seriesBuilder);
+ }
+
+ @Override
+ public JFreeChart createChartImpl(String title, String xAxisTitle,
+ String yAxisTitle, final Dataset dataset, PlotOrientation plotOrientation,
+ boolean showLegend, boolean showToolTips, boolean showUrls)
+ {
+ JFreeChart chart = ChartFactory.createLineChart3D(title,
+ xAxisTitle,
+ yAxisTitle,
+ (CategoryDataset)dataset,
+ plotOrientation,
+ showLegend,
+ showToolTips,
+ showUrls);
+ return chart;
+ }
+
+}
diff --git a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/LineChartBuilder.java b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/LineChartBuilder.java
index 697dfdcf3e..40f3a09b6b 100644
--- a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/LineChartBuilder.java
+++ b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/LineChartBuilder.java
@@ -19,22 +19,30 @@
*/
package org.apache.qpid.disttest.charting.chartbuilder;
+import org.apache.qpid.disttest.charting.seriesbuilder.SeriesBuilder;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.plot.PlotOrientation;
-import org.jfree.data.category.DefaultCategoryDataset;
+import org.jfree.data.category.CategoryDataset;
+import org.jfree.data.general.Dataset;
-public class LineChartBuilder extends DataSetBasedChartBuilder
+public class LineChartBuilder extends CategoryDataSetBasedChartBuilder
{
+
+ public LineChartBuilder(SeriesBuilder seriesBuilder)
+ {
+ super(seriesBuilder);
+ }
+
@Override
public JFreeChart createChartImpl(String title, String xAxisTitle,
- String yAxisTitle, final DefaultCategoryDataset dataset, PlotOrientation plotOrientation,
+ String yAxisTitle, final Dataset dataset, PlotOrientation plotOrientation,
boolean showLegend, boolean showToolTips, boolean showUrls)
{
JFreeChart chart = ChartFactory.createLineChart(title,
xAxisTitle,
yAxisTitle,
- dataset,
+ (CategoryDataset)dataset,
plotOrientation,
showLegend,
showToolTips,
diff --git a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/StatisticalBarCharBuilder.java b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/StatisticalBarCharBuilder.java
new file mode 100644
index 0000000000..86c3f62e09
--- /dev/null
+++ b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/StatisticalBarCharBuilder.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.disttest.charting.chartbuilder;
+
+import java.awt.Font;
+
+import org.apache.qpid.disttest.charting.definition.ChartingDefinition;
+import org.apache.qpid.disttest.charting.definition.SeriesDefinition;
+import org.apache.qpid.disttest.charting.seriesbuilder.SeriesBuilder;
+import org.apache.qpid.disttest.charting.seriesbuilder.SeriesBuilderCallback;
+import org.jfree.chart.JFreeChart;
+import org.jfree.chart.axis.CategoryAxis;
+import org.jfree.chart.axis.CategoryLabelPositions;
+import org.jfree.chart.axis.NumberAxis;
+import org.jfree.chart.axis.ValueAxis;
+import org.jfree.chart.plot.CategoryPlot;
+import org.jfree.chart.plot.PlotOrientation;
+import org.jfree.chart.renderer.category.CategoryItemRenderer;
+import org.jfree.chart.renderer.category.StatisticalBarRenderer;
+import org.jfree.data.general.Dataset;
+import org.jfree.data.statistics.DefaultStatisticalCategoryDataset;
+import org.jfree.data.statistics.StatisticalCategoryDataset;
+
+public class StatisticalBarCharBuilder extends BaseChartBuilder
+{
+ private final SeriesBuilder _seriesBuilder;
+
+ public StatisticalBarCharBuilder(SeriesBuilder seriesBuilder)
+ {
+ _seriesBuilder = seriesBuilder;
+ }
+
+ @Override
+ public JFreeChart buildChart(ChartingDefinition chartingDefinition)
+ {
+ String title = chartingDefinition.getChartTitle();
+ String xAxisTitle = chartingDefinition.getXAxisTitle();
+ String yAxisTitle = chartingDefinition.getYAxisTitle();
+
+ final DefaultStatisticalCategoryDataset dataset = new DefaultStatisticalCategoryDataset();
+
+ _seriesBuilder.setSeriesBuilderCallback(new SeriesBuilderCallback()
+ {
+ @Override
+ public void addDataPointToSeries(SeriesDefinition seriesDefinition, Object[] row)
+ {
+ String x = String.valueOf(row[0]);
+ double mean = Double.parseDouble(row[1].toString());
+ double stdDev = Double.parseDouble(row[2].toString());
+ dataset.add(mean, stdDev, seriesDefinition.getSeriesLegend(), x);
+ }
+
+ @Override
+ public void beginSeries(SeriesDefinition seriesDefinition)
+ {
+ // unused
+ }
+
+ @Override
+ public void endSeries(SeriesDefinition seriesDefinition)
+ {
+ // unused
+ }
+
+ });
+
+ _seriesBuilder.build(chartingDefinition.getSeries());
+
+ JFreeChart chart = createChartImpl(title, xAxisTitle, yAxisTitle, dataset, PLOT_ORIENTATION, SHOW_LEGEND,
+ SHOW_TOOL_TIPS, SHOW_URLS);
+
+ chart.getCategoryPlot().getDomainAxis().setCategoryLabelPositions(CategoryLabelPositions.UP_45);
+
+ addCommonChartAttributes(chart, chartingDefinition);
+
+ return chart;
+ }
+
+ @Override
+ public JFreeChart createChartImpl(String title, String xAxisTitle, String yAxisTitle, final Dataset dataset,
+ PlotOrientation plotOrientation, boolean showLegend, boolean showToolTips, boolean showUrls)
+ {
+ CategoryAxis xAxis = new CategoryAxis(xAxisTitle);
+ ValueAxis yAxis = new NumberAxis(yAxisTitle);
+ CategoryItemRenderer renderer = new StatisticalBarRenderer();
+
+ CategoryPlot plot = new CategoryPlot((StatisticalCategoryDataset) dataset, xAxis, yAxis, renderer);
+
+ JFreeChart chart = new JFreeChart(title, new Font("Arial", Font.PLAIN, 10), plot, true);
+ return chart;
+ }
+
+}
diff --git a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/XYDataSetBasedChartBuilder.java b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/XYDataSetBasedChartBuilder.java
new file mode 100644
index 0000000000..87d61ca2ee
--- /dev/null
+++ b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/XYDataSetBasedChartBuilder.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.disttest.charting.chartbuilder;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.qpid.disttest.charting.definition.ChartingDefinition;
+import org.apache.qpid.disttest.charting.definition.SeriesDefinition;
+import org.apache.qpid.disttest.charting.seriesbuilder.SeriesBuilderCallback;
+import org.apache.qpid.disttest.charting.seriesbuilder.SeriesBuilder;
+import org.jfree.chart.JFreeChart;
+import org.jfree.chart.axis.CategoryLabelPositions;
+import org.jfree.data.xy.DefaultXYDataset;
+
+
+public abstract class XYDataSetBasedChartBuilder extends BaseChartBuilder
+{
+ private final SeriesBuilder _seriesBuilder;
+
+ public XYDataSetBasedChartBuilder(SeriesBuilder seriesBuilder)
+ {
+ this._seriesBuilder = seriesBuilder;
+ }
+
+ @Override
+ public JFreeChart buildChart(ChartingDefinition chartingDefinition)
+ {
+ String title = chartingDefinition.getChartTitle();
+ String xAxisTitle = chartingDefinition.getXAxisTitle();
+ String yAxisTitle = chartingDefinition.getYAxisTitle();
+
+ final DefaultXYDataset dataset = new DefaultXYDataset();
+ _seriesBuilder.setSeriesBuilderCallback(new SeriesBuilderCallback()
+ {
+ private List<Double[]> _xyPairs = null;
+
+ @Override
+ public void beginSeries(SeriesDefinition seriesDefinition)
+ {
+ _xyPairs = new ArrayList<Double[]>();
+ }
+
+ @Override
+ public void addDataPointToSeries(SeriesDefinition seriesDefinition,
+ Object[] row)
+ {
+ double x = Double.parseDouble(row[0].toString());
+ double y = Double.parseDouble(row[1].toString());
+ _xyPairs.add(new Double[] {x, y});
+ }
+
+
+ @Override
+ public void endSeries(SeriesDefinition seriesDefinition)
+ {
+ double[][] seriesData = listToSeriesDataArray();
+ dataset.addSeries(seriesDefinition.getSeriesLegend(), seriesData);
+ }
+
+ private double[][] listToSeriesDataArray()
+ {
+ double[][] seriesData = new double[2][_xyPairs.size()];
+ int i = 0;
+ for (Iterator<Double[]> iterator = _xyPairs.iterator(); iterator.hasNext();)
+ {
+ Double[] xyPair = iterator.next();
+ seriesData[0][i] = xyPair[0];
+ seriesData[1][i] = xyPair[1];
+ i++;
+ }
+ return seriesData;
+ }
+ });
+
+ _seriesBuilder.build(chartingDefinition.getSeries());
+
+ JFreeChart chart = createChartImpl(title, xAxisTitle, yAxisTitle,
+ dataset, PLOT_ORIENTATION, SHOW_LEGEND, SHOW_TOOL_TIPS, SHOW_URLS);
+
+ addCommonChartAttributes(chart, chartingDefinition);
+
+ return chart;
+ }
+}
diff --git a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/XYLineChartBuilder.java b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/XYLineChartBuilder.java
new file mode 100644
index 0000000000..48b02a7c60
--- /dev/null
+++ b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/XYLineChartBuilder.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.disttest.charting.chartbuilder;
+
+import org.apache.qpid.disttest.charting.seriesbuilder.SeriesBuilder;
+import org.jfree.chart.ChartFactory;
+import org.jfree.chart.JFreeChart;
+import org.jfree.chart.plot.PlotOrientation;
+import org.jfree.data.general.Dataset;
+import org.jfree.data.xy.XYDataset;
+
+public class XYLineChartBuilder extends XYDataSetBasedChartBuilder
+{
+ public XYLineChartBuilder(SeriesBuilder seriesBuilder)
+ {
+ super(seriesBuilder);
+ }
+
+ @Override
+ public JFreeChart createChartImpl(String title, String xAxisTitle,
+ String yAxisTitle, final Dataset dataset, PlotOrientation plotOrientation,
+ boolean showLegend, boolean showToolTips, boolean showUrls)
+ {
+ JFreeChart chart = ChartFactory.createXYLineChart(title,
+ xAxisTitle,
+ yAxisTitle,
+ (XYDataset)dataset,
+ plotOrientation,
+ showLegend,
+ showToolTips,
+ showUrls);
+ return chart;
+ }
+}
diff --git a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/definition/ChartingDefinition.java b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/definition/ChartingDefinition.java
index 82b59b6d6e..04b3f7ed3b 100644
--- a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/definition/ChartingDefinition.java
+++ b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/definition/ChartingDefinition.java
@@ -29,6 +29,7 @@ public class ChartingDefinition
private final String _chartStemName;
private final ChartType _chartType;
private final String _chartTitle;
+ private final String _chartSubtitle;
private final String _xaxisTitle;
private final String _yaxisTitle;
private final List<SeriesDefinition> _seriesDefinitions;
@@ -37,12 +38,13 @@ public class ChartingDefinition
public ChartingDefinition(final String chartStemName,
final ChartType chartType,
final String chartTitle,
- final String xaxisTitle,
- final String yaxisTitle, List<SeriesDefinition> seriesDefinitions)
+ final String chartSubtitle,
+ final String xaxisTitle, final String yaxisTitle, List<SeriesDefinition> seriesDefinitions)
{
_chartStemName = chartStemName;
_chartType = chartType;
_chartTitle = chartTitle;
+ _chartSubtitle = chartSubtitle;
_xaxisTitle = xaxisTitle;
_yaxisTitle = yaxisTitle;
_seriesDefinitions = seriesDefinitions;
@@ -58,6 +60,11 @@ public class ChartingDefinition
return _chartTitle;
}
+ public String getChartSubtitle()
+ {
+ return _chartSubtitle;
+ }
+
public String getXAxisTitle()
{
@@ -82,4 +89,5 @@ public class ChartingDefinition
return Collections.unmodifiableList(_seriesDefinitions);
}
+
}
diff --git a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/definition/ChartingDefinitionCreator.java b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/definition/ChartingDefinitionCreator.java
index 8a3d313519..4cbc9318a9 100644
--- a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/definition/ChartingDefinitionCreator.java
+++ b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/definition/ChartingDefinitionCreator.java
@@ -38,6 +38,7 @@ public class ChartingDefinitionCreator
public static final String CHART_TYPE_KEY = "chartType";
public static final String CHART_TITLE_KEY = "chartTitle";
+ public static final String CHART_SUBTITLE_KEY = "chartSubtitle";
public static final String XAXIS_TITLE_KEY = "xAxisTitle";
public static final String YAXIS_TITLE_KEY = "yAxisTitle";
@@ -80,6 +81,7 @@ public class ChartingDefinitionCreator
final ChartType chartType = ChartType.valueOf(props.getProperty(CHART_TYPE_KEY));
final String chartTitle = props.getProperty(CHART_TITLE_KEY);
+ final String chartSubtitle = props.getProperty(CHART_SUBTITLE_KEY);
final String xAxisTitle = props.getProperty(XAXIS_TITLE_KEY);
final String yAxisTitle = props.getProperty(YAXIS_TITLE_KEY);
@@ -88,9 +90,9 @@ public class ChartingDefinitionCreator
final ChartingDefinition chartDefinition = new ChartingDefinition(chartStemName,
chartType,
chartTitle,
+ chartSubtitle,
xAxisTitle,
- yAxisTitle,
- seriesDefinitions);
+ yAxisTitle, seriesDefinitions);
return chartDefinition;
}
catch (IOException e)
@@ -134,7 +136,4 @@ public class ChartingDefinitionCreator
return pathname.isFile() && pathname.getName().endsWith(CHARTDEF_FILE_EXTENSION);
}
}
-
-
-
}
diff --git a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/SeriesBuilder.java b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/seriesbuilder/JdbcCsvSeriesBuilder.java
index de717792db..a9adce0afc 100644
--- a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/SeriesBuilder.java
+++ b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/seriesbuilder/JdbcCsvSeriesBuilder.java
@@ -17,7 +17,7 @@
* under the License.
*
*/
-package org.apache.qpid.disttest.charting.chartbuilder;
+package org.apache.qpid.disttest.charting.seriesbuilder;
import java.io.File;
import java.sql.Connection;
@@ -31,20 +31,23 @@ import java.util.List;
import org.apache.qpid.disttest.charting.ChartingException;
import org.apache.qpid.disttest.charting.definition.SeriesDefinition;
-public class SeriesBuilder
+public class JdbcCsvSeriesBuilder implements SeriesBuilder
{
+
static
{
registerCsvDriver();
}
- private final DataPointCallback _dataPointCallback;
+ private SeriesBuilderCallback _callback;
- public SeriesBuilder(DataPointCallback dataPointCallback)
+ @Override
+ public void setSeriesBuilderCallback(SeriesBuilderCallback callback)
{
- _dataPointCallback = dataPointCallback;
+ this._callback = callback;
}
+ @Override
public void build(List<SeriesDefinition> seriesDefinitions)
{
for (Iterator<SeriesDefinition> iterator = seriesDefinitions.iterator(); iterator.hasNext();)
@@ -68,14 +71,19 @@ public class SeriesBuilder
stmt = conn.createStatement();
ResultSet results = stmt.executeQuery(seriesStatement);
-
+ int columnCount = results.getMetaData().getColumnCount();
+ _callback.beginSeries(seriesDefinition);
while (results.next())
{
- Object xValue = results.getString(1);
- Object yValue = results.getDouble(2);
+ Object[] row = new Object[columnCount];
+ for (int i = 0; i < row.length; i++)
+ {
+ row[i] = results.getObject(i+1);
+ }
- _dataPointCallback.addDataPointToSeries(seriesDefinition, xValue, yValue);
+ _callback.addDataPointToSeries(seriesDefinition, row);
}
+ _callback.endSeries(seriesDefinition);
}
catch (SQLException e)
{
diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/INotificationViewer.java b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/seriesbuilder/SeriesBuilder.java
index a7bf60cc73..86e471efaf 100644
--- a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/INotificationViewer.java
+++ b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/seriesbuilder/SeriesBuilder.java
@@ -1,5 +1,4 @@
/*
- *
* Licensed 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,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
@@ -18,15 +17,16 @@
* under the License.
*
*/
-package org.apache.qpid.management.ui.views;
-
-import org.apache.qpid.management.ui.model.NotificationObject;
+package org.apache.qpid.disttest.charting.seriesbuilder;
import java.util.List;
-public interface INotificationViewer
+import org.apache.qpid.disttest.charting.definition.SeriesDefinition;
+
+public interface SeriesBuilder
{
- public void addNotification(NotificationObject notification);
-
- public void addNotification(List<NotificationObject> notificationList);
-}
+ void build(List<SeriesDefinition> seriesDefinitions);
+
+ void setSeriesBuilderCallback(SeriesBuilderCallback seriesBuilderCallback);
+
+} \ No newline at end of file
diff --git a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/DataPointCallback.java b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/seriesbuilder/SeriesBuilderCallback.java
index a47df0e8af..7e23953fdb 100644
--- a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/DataPointCallback.java
+++ b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/seriesbuilder/SeriesBuilderCallback.java
@@ -17,11 +17,14 @@
* under the License.
*
*/
-package org.apache.qpid.disttest.charting.chartbuilder;
+package org.apache.qpid.disttest.charting.seriesbuilder;
import org.apache.qpid.disttest.charting.definition.SeriesDefinition;
-public interface DataPointCallback
+public interface SeriesBuilderCallback
{
- public void addDataPointToSeries(SeriesDefinition seriesDefinition, Object xValue, Object yValue);
+ public void beginSeries(SeriesDefinition seriesDefinition);
+ public void addDataPointToSeries(SeriesDefinition seriesDefinition, Object[] row);
+ public void endSeries(SeriesDefinition seriesDefinition);
+
}
diff --git a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/writer/ChartWriter.java b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/writer/ChartWriter.java
new file mode 100644
index 0000000000..08bdf122ba
--- /dev/null
+++ b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/writer/ChartWriter.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.disttest.charting.writer;
+
+import java.io.BufferedOutputStream;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+import org.apache.qpid.disttest.charting.ChartingException;
+import org.jfree.chart.ChartUtilities;
+import org.jfree.chart.JFreeChart;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ChartWriter
+{
+ private static final Logger LOGGER = LoggerFactory.getLogger(ChartWriter.class);
+
+ static final String SUMMARY_FILE_NAME = "chart-summary.html";
+
+ private File _chartDirectory = new File(".");
+ private SortedSet<File> _chartFiles = new TreeSet<File>();
+
+ public void writeChartToFileSystem(JFreeChart chart, String chartStemName)
+ {
+ OutputStream pngOutputStream = null;
+ try
+ {
+ File pngFile = new File(_chartDirectory, chartStemName + ".png");
+ pngOutputStream = new BufferedOutputStream(new FileOutputStream(pngFile));
+ ChartUtilities.writeChartAsPNG(pngOutputStream, chart, 600, 400, true, 0);
+ pngOutputStream.close();
+
+ _chartFiles.add(pngFile);
+
+ LOGGER.info("Written {} chart", pngFile);
+ }
+ catch (IOException e)
+ {
+ throw new ChartingException("Failed to create chart", e);
+ }
+ finally
+ {
+ if (pngOutputStream != null)
+ {
+ try
+ {
+ pngOutputStream.close();
+ }
+ catch (IOException e)
+ {
+ throw new ChartingException("Failed to create chart", e);
+ }
+ }
+ }
+ }
+
+ public void writeHtmlSummaryToFileSystem()
+ {
+ if(_chartFiles.size() < 2)
+ {
+ LOGGER.info("Only " + _chartFiles.size() + " chart image(s) have been written so no HTML summary file will be produced");
+ return;
+ }
+
+ String htmlHeader =
+ "<html>\n" +
+ " <head>\n" +
+ " <title>Performance Charts</title>\n" +
+ " </head>\n" +
+ " <body>\n";
+
+ String htmlFooter =
+ " </body>\n" +
+ "</html>";
+
+ BufferedWriter writer = null;
+ try
+ {
+ File summaryFile = new File(_chartDirectory, SUMMARY_FILE_NAME);
+ LOGGER.debug("About to produce HTML summary file " + summaryFile.getAbsolutePath() + " from charts " + _chartFiles);
+
+ writer = new BufferedWriter(new FileWriter(summaryFile));
+ writer.write(htmlHeader);
+ for (File chartFile : _chartFiles)
+ {
+ writer.write(" <img src='" + chartFile.getName() + "'/>\n");
+ }
+ writer.write(htmlFooter);
+ writer.close();
+ }
+ catch (Exception e)
+ {
+ throw new ChartingException("Failed to create HTML summary file", e);
+ }
+ finally
+ {
+ if(writer != null)
+ {
+ try
+ {
+ writer.close();
+ }
+ catch(IOException e)
+ {
+ throw new ChartingException("Failed to create HTML summary file", e);
+ }
+ }
+ }
+ }
+
+ public void setOutputDirectory(final File chartDirectory)
+ {
+ _chartDirectory = chartDirectory;
+ }
+}
diff --git a/java/perftests/visualisation-jfc/src/test/java/org/apache/qpid/disttest/charting/chartbuilder/ChartBuilderFactoryTest.java b/java/perftests/visualisation-jfc/src/test/java/org/apache/qpid/disttest/charting/chartbuilder/ChartBuilderFactoryTest.java
index bdbbc4a585..e735fb58c6 100644
--- a/java/perftests/visualisation-jfc/src/test/java/org/apache/qpid/disttest/charting/chartbuilder/ChartBuilderFactoryTest.java
+++ b/java/perftests/visualisation-jfc/src/test/java/org/apache/qpid/disttest/charting/chartbuilder/ChartBuilderFactoryTest.java
@@ -19,22 +19,44 @@
*/
package org.apache.qpid.disttest.charting.chartbuilder;
+import static org.mockito.Mockito.*;
+
import org.apache.qpid.disttest.charting.ChartType;
+import org.apache.qpid.disttest.charting.seriesbuilder.SeriesBuilder;
import junit.framework.TestCase;
public class ChartBuilderFactoryTest extends TestCase
{
+ private SeriesBuilder _seriesBuilder = mock(SeriesBuilder.class);
+
public void testLineChart()
{
- ChartBuilder builder = ChartBuilderFactory.createChartBuilder(ChartType.LINE);
+ ChartBuilder builder = ChartBuilderFactory.createChartBuilder(ChartType.LINE, _seriesBuilder);
assertTrue(builder instanceof LineChartBuilder);
}
+ public void testLineChart3D()
+ {
+ ChartBuilder builder = ChartBuilderFactory.createChartBuilder(ChartType.LINE3D, _seriesBuilder);
+ assertTrue(builder instanceof LineChart3DBuilder);
+ }
+
public void testBarChart()
{
- ChartBuilder builder = ChartBuilderFactory.createChartBuilder(ChartType.BAR);
+ ChartBuilder builder = ChartBuilderFactory.createChartBuilder(ChartType.BAR, _seriesBuilder);
assertTrue(builder instanceof BarChartBuilder);
}
+ public void testBarChart3D()
+ {
+ ChartBuilder builder = ChartBuilderFactory.createChartBuilder(ChartType.BAR3D, _seriesBuilder);
+ assertTrue(builder instanceof BarChart3DBuilder);
+ }
+
+ public void testXYLineChart()
+ {
+ ChartBuilder builder = ChartBuilderFactory.createChartBuilder(ChartType.XYLINE, _seriesBuilder);
+ assertTrue(builder instanceof XYLineChartBuilder);
+ }
}
diff --git a/java/perftests/visualisation-jfc/src/test/java/org/apache/qpid/disttest/charting/chartbuilder/ChartProductionTest.java b/java/perftests/visualisation-jfc/src/test/java/org/apache/qpid/disttest/charting/chartbuilder/ChartProductionTest.java
new file mode 100644
index 0000000000..2744e17404
--- /dev/null
+++ b/java/perftests/visualisation-jfc/src/test/java/org/apache/qpid/disttest/charting/chartbuilder/ChartProductionTest.java
@@ -0,0 +1,198 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.disttest.charting.chartbuilder;
+
+import static org.mockito.Mockito.*;
+
+import java.io.File;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.qpid.disttest.charting.ChartType;
+import org.apache.qpid.disttest.charting.definition.ChartingDefinition;
+import org.apache.qpid.disttest.charting.definition.SeriesDefinition;
+import org.apache.qpid.disttest.charting.seriesbuilder.SeriesBuilderCallback;
+import org.apache.qpid.disttest.charting.seriesbuilder.SeriesBuilder;
+import org.apache.qpid.disttest.charting.writer.ChartWriter;
+import org.apache.qpid.test.utils.TestFileUtils;
+import org.jfree.chart.JFreeChart;
+import org.jfree.chart.plot.XYPlot;
+import org.jfree.chart.title.ShortTextTitle;
+
+import junit.framework.TestCase;
+
+/**
+ * Tests the production of the different chart types. To manually
+ * verify the generated output, set the system property {@link #RETAIN_TEST_CHARTS}
+ * to prevent the automatic deletion of the test chart directory.
+ *
+ */
+public class ChartProductionTest extends TestCase
+{
+ private static final String TEST_CHARTTITLE = "TEST_CHARTTITLE";
+ private static final String TEST_CHARTSUBTITLE = "TEST_CHARTSUBTITLE";
+ private static final String TEST_XAXIS = "TEST_XAXIS";
+ private static final String TEST_YAXIS = "TEST_YAXIS";
+
+ private static final String TEST_SERIESLEGEND = "TEST_SERIESLEGEND";
+
+ private static final String RETAIN_TEST_CHARTS = "retainTestCharts";
+
+ private SeriesDefinition _seriesDefinition = mock(SeriesDefinition.class);
+ private ChartingDefinition _chartingDefinition = mock(ChartingDefinition.class);
+ private ChartWriter _writer = new ChartWriter();
+
+ @Override
+ protected void setUp() throws Exception
+ {
+ super.setUp();
+
+ when(_seriesDefinition.getSeriesLegend()).thenReturn(TEST_SERIESLEGEND);
+
+ when(_chartingDefinition.getChartTitle()).thenReturn(TEST_CHARTTITLE);
+ when(_chartingDefinition.getChartSubtitle()).thenReturn(TEST_CHARTSUBTITLE);
+ when(_chartingDefinition.getXAxisTitle()).thenReturn(TEST_XAXIS);
+ when(_chartingDefinition.getYAxisTitle()).thenReturn(TEST_YAXIS);
+ when(_chartingDefinition.getSeries()).thenReturn(Collections.singletonList(_seriesDefinition));
+
+ File chartDir = TestFileUtils.createTestDirectory("charts", false);
+ if (!System.getProperties().containsKey(RETAIN_TEST_CHARTS))
+ {
+ chartDir.deleteOnExit();
+ }
+ else
+ {
+ System.out.println("Charting directory for manual observation " + chartDir);
+ }
+
+ _writer.setOutputDirectory(chartDir);
+ }
+
+ public void testBarChart() throws Exception
+ {
+ ChartBuilder builder = ChartBuilderFactory.createChartBuilder(ChartType.BAR, new SampleSeriesBuilder());
+ assertChartTitlesAndWriteToFile(builder);
+ }
+
+ public void testBar3DChart() throws Exception
+ {
+ ChartBuilder builder = ChartBuilderFactory.createChartBuilder(ChartType.BAR3D, new SampleSeriesBuilder());
+ assertChartTitlesAndWriteToFile(builder);
+ }
+
+ public void testLineChart() throws Exception
+ {
+ ChartBuilder builder = ChartBuilderFactory.createChartBuilder(ChartType.LINE, new SampleSeriesBuilder());
+ assertChartTitlesAndWriteToFile(builder);
+ }
+
+ public void testLine3DChart() throws Exception
+ {
+ ChartBuilder builder = ChartBuilderFactory.createChartBuilder(ChartType.LINE3D, new SampleSeriesBuilder());
+ assertChartTitlesAndWriteToFile(builder);
+ }
+
+ public void testXYLineChart() throws Exception
+ {
+ ChartBuilder builder = ChartBuilderFactory.createChartBuilder(ChartType.XYLINE, new SampleSeriesBuilder());
+ assertChartTitlesAndWriteToFile(builder);
+ }
+
+ public void testStatiscticalBarChart() throws Exception
+ {
+ ChartBuilder builder = ChartBuilderFactory.createChartBuilder(
+ ChartType.STATISTICAL_BAR,
+ new SeriesBuilder()
+ {
+ private SeriesBuilderCallback _dataPointCallback;
+
+ @Override
+ public void build(List<SeriesDefinition> seriesDefinitions)
+ {
+ for (Iterator<SeriesDefinition> iterator = seriesDefinitions.iterator(); iterator.hasNext();)
+ {
+ SeriesDefinition seriesDefinition = iterator.next();
+ _dataPointCallback.beginSeries(seriesDefinition);
+ _dataPointCallback.addDataPointToSeries(seriesDefinition, new Object[]{1d, 1d, 0.5d});
+ _dataPointCallback.addDataPointToSeries(seriesDefinition, new Object[]{2d, 2d, 0.4d});
+ _dataPointCallback.addDataPointToSeries(seriesDefinition, new Object[]{4d, 4d, 0.3d});
+ _dataPointCallback.addDataPointToSeries(seriesDefinition, new Object[]{5d, 5d, 0.2d});
+ _dataPointCallback.addDataPointToSeries(seriesDefinition, new Object[]{6d, 3d, 0.1d});
+ _dataPointCallback.endSeries(seriesDefinition);
+ }
+ }
+
+ @Override
+ public void setSeriesBuilderCallback(SeriesBuilderCallback dataPointCallback)
+ {
+ _dataPointCallback = dataPointCallback;
+ }
+ });
+
+ assertChartTitlesAndWriteToFile(builder);
+ }
+
+ private void assertChartTitlesAndWriteToFile(ChartBuilder builder)
+ {
+ JFreeChart chart = builder.buildChart(_chartingDefinition);
+ assertEquals(TEST_CHARTTITLE, chart.getTitle().getText());
+ assertEquals(TEST_CHARTSUBTITLE, ((ShortTextTitle)chart.getSubtitle(1)).getText());
+ assertEquals(TEST_SERIESLEGEND, chart.getPlot().getLegendItems().get(0).getLabel());
+
+ if (chart.getPlot() instanceof XYPlot)
+ {
+ assertEquals(1, chart.getXYPlot().getDatasetCount());
+ }
+ else
+ {
+ assertEquals(1, chart.getCategoryPlot().getDatasetCount());
+ }
+
+ _writer.writeChartToFileSystem(chart, getName());
+ }
+
+ private class SampleSeriesBuilder implements SeriesBuilder
+ {
+ private SeriesBuilderCallback _dataPointCallback;
+
+ @Override
+ public void build(List<SeriesDefinition> seriesDefinitions)
+ {
+ for (Iterator<SeriesDefinition> iterator = seriesDefinitions.iterator(); iterator.hasNext();)
+ {
+ SeriesDefinition seriesDefinition = iterator.next();
+ _dataPointCallback.beginSeries(seriesDefinition);
+ _dataPointCallback.addDataPointToSeries(seriesDefinition, new Object[]{1d, 1d});
+ _dataPointCallback.addDataPointToSeries(seriesDefinition, new Object[]{2d, 2d});
+ _dataPointCallback.addDataPointToSeries(seriesDefinition, new Object[]{4d, 4d});
+ _dataPointCallback.addDataPointToSeries(seriesDefinition, new Object[]{5d, 5d});
+ _dataPointCallback.addDataPointToSeries(seriesDefinition, new Object[]{6d, 3d});
+ _dataPointCallback.endSeries(seriesDefinition);
+ }
+ }
+
+ @Override
+ public void setSeriesBuilderCallback(SeriesBuilderCallback dataPointCallback)
+ {
+ _dataPointCallback = dataPointCallback;
+ }
+ }
+}
diff --git a/java/perftests/visualisation-jfc/src/test/java/org/apache/qpid/disttest/charting/definition/ChartingDefinitionCreatorTest.java b/java/perftests/visualisation-jfc/src/test/java/org/apache/qpid/disttest/charting/definition/ChartingDefinitionCreatorTest.java
index 80d1cc3d21..5371f3df45 100644
--- a/java/perftests/visualisation-jfc/src/test/java/org/apache/qpid/disttest/charting/definition/ChartingDefinitionCreatorTest.java
+++ b/java/perftests/visualisation-jfc/src/test/java/org/apache/qpid/disttest/charting/definition/ChartingDefinitionCreatorTest.java
@@ -20,6 +20,7 @@
package org.apache.qpid.disttest.charting.definition;
import static org.apache.qpid.disttest.charting.definition.ChartingDefinitionCreator.CHART_TITLE_KEY;
+import static org.apache.qpid.disttest.charting.definition.ChartingDefinitionCreator.CHART_SUBTITLE_KEY;
import static org.apache.qpid.disttest.charting.definition.ChartingDefinitionCreator.CHART_TYPE_KEY;
import static org.apache.qpid.disttest.charting.definition.ChartingDefinitionCreator.XAXIS_TITLE_KEY;
import static org.apache.qpid.disttest.charting.definition.ChartingDefinitionCreator.YAXIS_TITLE_KEY;
@@ -38,6 +39,7 @@ import org.apache.qpid.disttest.charting.ChartingException;
public class ChartingDefinitionCreatorTest extends TestCase
{
private static final String TEST_CHART_TITLE = "CHART_TITLE";
+ private static final String TEST_CHART_SUBTITLE = "CHART_SUBTITLE";
private static final String TEST_XAXIS_TITLE = "XAXIS_TITLE";
private static final String TEST_YAXIS_TITLE = "YAXIS_TITLE";
private static final ChartType TEST_CHART_TYPE = ChartType.LINE;
@@ -83,6 +85,7 @@ public class ChartingDefinitionCreatorTest extends TestCase
ChartingDefinition definition1 = definitions.get(0);
assertEquals(TEST_CHART_TITLE, definition1.getChartTitle());
+ assertEquals(TEST_CHART_SUBTITLE, definition1.getChartSubtitle());
assertEquals(TEST_XAXIS_TITLE, definition1.getXAxisTitle());
assertEquals(TEST_YAXIS_TITLE, definition1.getYAxisTitle());
assertEquals(TEST_CHART_TYPE, definition1.getChartType());
@@ -121,6 +124,7 @@ public class ChartingDefinitionCreatorTest extends TestCase
Properties props = new Properties();
props.setProperty(CHART_TYPE_KEY, TEST_CHART_TYPE.name());
props.setProperty(CHART_TITLE_KEY, TEST_CHART_TITLE);
+ props.setProperty(CHART_SUBTITLE_KEY, TEST_CHART_SUBTITLE);
props.setProperty(XAXIS_TITLE_KEY, TEST_XAXIS_TITLE);
props.setProperty(YAXIS_TITLE_KEY, TEST_YAXIS_TITLE);
diff --git a/java/perftests/visualisation-jfc/src/test/java/org/apache/qpid/disttest/charting/chartbuilder/SeriesBuilderTest.java b/java/perftests/visualisation-jfc/src/test/java/org/apache/qpid/disttest/charting/seriesbuilder/JdbcCsvSeriesBuilderTest.java
index 1b1c9969b3..5148a25bec 100644
--- a/java/perftests/visualisation-jfc/src/test/java/org/apache/qpid/disttest/charting/chartbuilder/SeriesBuilderTest.java
+++ b/java/perftests/visualisation-jfc/src/test/java/org/apache/qpid/disttest/charting/seriesbuilder/JdbcCsvSeriesBuilderTest.java
@@ -17,7 +17,7 @@
* under the License.
*
*/
-package org.apache.qpid.disttest.charting.chartbuilder;
+package org.apache.qpid.disttest.charting.seriesbuilder;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
@@ -31,14 +31,15 @@ import java.util.Collections;
import junit.framework.TestCase;
import org.apache.qpid.disttest.charting.definition.SeriesDefinition;
+import org.apache.qpid.disttest.charting.seriesbuilder.JdbcCsvSeriesBuilder;
-public class SeriesBuilderTest extends TestCase
+public class JdbcCsvSeriesBuilderTest extends TestCase
{
private static final String TEST_SERIES_1_SELECT_STATEMENT = "SELECT A, B FROM test";
private static final String TEST_SERIES_1_LEGEND = "SERIES_1_LEGEND";
- private DataPointCallback _dataPointCallback = mock(DataPointCallback.class);
- private SeriesBuilder _seriesBuilder = new SeriesBuilder(_dataPointCallback);
+ private SeriesBuilderCallback _seriesWalkerCallback = mock(SeriesBuilderCallback.class);
+ private JdbcCsvSeriesBuilder _seriesBuilder = new JdbcCsvSeriesBuilder();
private File _testTempDir;
@@ -46,6 +47,7 @@ public class SeriesBuilderTest extends TestCase
protected void setUp() throws Exception
{
super.setUp();
+ _seriesBuilder.setSeriesBuilderCallback(_seriesWalkerCallback);
_testTempDir = createTestTemporaryDirectory();
}
@@ -56,9 +58,11 @@ public class SeriesBuilderTest extends TestCase
_seriesBuilder.build(Collections.singletonList(seriesDefinition));
- verify(_dataPointCallback).addDataPointToSeries(seriesDefinition, (Object)"elephant", (Object)2.0);
- verify(_dataPointCallback).addDataPointToSeries(seriesDefinition, (Object)"lion", (Object)3.0);
- verify(_dataPointCallback).addDataPointToSeries(seriesDefinition, (Object)"tiger", (Object)4.0);
+ verify(_seriesWalkerCallback).beginSeries(seriesDefinition);
+ verify(_seriesWalkerCallback).addDataPointToSeries(seriesDefinition, new Object[]{"elephant", "2"});
+ verify(_seriesWalkerCallback).addDataPointToSeries(seriesDefinition, new Object[]{"lion", "3"});
+ verify(_seriesWalkerCallback).addDataPointToSeries(seriesDefinition, new Object[]{"tiger", "4"});
+ verify(_seriesWalkerCallback).endSeries(seriesDefinition);
}
private void createTestCsvIn(File testDir) throws Exception
diff --git a/java/perftests/visualisation-jfc/src/test/java/org/apache/qpid/disttest/charting/writer/ChartWriterTest.java b/java/perftests/visualisation-jfc/src/test/java/org/apache/qpid/disttest/charting/writer/ChartWriterTest.java
new file mode 100644
index 0000000000..0e176d326b
--- /dev/null
+++ b/java/perftests/visualisation-jfc/src/test/java/org/apache/qpid/disttest/charting/writer/ChartWriterTest.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.disttest.charting.writer;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.InputStream;
+import java.util.Scanner;
+
+import junit.framework.TestCase;
+
+import org.apache.qpid.test.utils.TestFileUtils;
+import org.apache.qpid.util.FileUtils;
+import org.jfree.chart.ChartFactory;
+import org.jfree.chart.JFreeChart;
+import org.jfree.data.general.DefaultPieDataset;
+
+public class ChartWriterTest extends TestCase
+{
+ private JFreeChart _chart1;
+ private JFreeChart _chart2;
+
+ private File _chartDir;
+ private ChartWriter _writer;
+
+ @Override
+ public void setUp()
+ {
+ DefaultPieDataset dataset = new DefaultPieDataset();
+ dataset.setValue("a", 1);
+ dataset.setValue("b", 2);
+
+ _chart1 = ChartFactory.createPieChart("chart1", dataset, true, true, false);
+ _chart2 = ChartFactory.createPieChart("chart2", dataset, true, true, false);
+
+ _chartDir = TestFileUtils.createTestDirectory();
+
+ _writer = new ChartWriter();
+ _writer.setOutputDirectory(_chartDir);
+ }
+
+ public void testWriteChartToFileSystem()
+ {
+ File chart1File = new File(_chartDir, "chart1.png");
+ assertFalse("chart1 png should not exist yet", chart1File.exists());
+
+ _writer.writeChartToFileSystem(_chart1, "chart1");
+
+ assertTrue("chart1 png does not exist", chart1File.exists());
+ }
+
+ public void testWriteHtmlSummaryToFileSystemOverwritingExistingFile() throws Exception
+ {
+ File summaryFile = new File(_chartDir, ChartWriter.SUMMARY_FILE_NAME);
+
+ writeDummyContentToSummaryFileToEnsureItGetsOverwritten(summaryFile);
+
+ _writer.writeChartToFileSystem(_chart2, "chart2");
+ _writer.writeChartToFileSystem(_chart1, "chart1");
+
+ _writer.writeHtmlSummaryToFileSystem();
+
+ InputStream expectedSummaryFileInputStream = getClass().getResourceAsStream("expected-chart-summary.html");
+ String expectedSummaryContent = new Scanner(expectedSummaryFileInputStream).useDelimiter("\\A").next();
+ String actualSummaryContent = FileUtils.readFileAsString(summaryFile);
+
+ assertEquals("HTML summary file has unexpected content", expectedSummaryContent, actualSummaryContent);
+ }
+
+ public void testWriteHtmlSummaryToFileSystemDoesNothingIfLessThanTwoCharts()
+ {
+ File summaryFile = new File(_chartDir, ChartWriter.SUMMARY_FILE_NAME);
+
+ _writer.writeChartToFileSystem(_chart1, "chart1");
+
+ _writer.writeHtmlSummaryToFileSystem();
+
+ assertFalse("Only one chart generated so no summary file should have been written",
+ summaryFile.exists());
+ }
+
+ private void writeDummyContentToSummaryFileToEnsureItGetsOverwritten(File summaryFile) throws Exception
+ {
+ FileWriter writer = null;
+ try
+ {
+ writer = new FileWriter(summaryFile);
+ writer.write("dummy content");
+ writer.close();
+ }
+ finally
+ {
+ if (writer != null)
+ {
+ writer.close();
+ }
+ }
+ }
+}
diff --git a/java/perftests/visualisation-jfc/src/test/java/org/apache/qpid/disttest/charting/writer/expected-chart-summary.html b/java/perftests/visualisation-jfc/src/test/java/org/apache/qpid/disttest/charting/writer/expected-chart-summary.html
new file mode 100644
index 0000000000..d1f039f44a
--- /dev/null
+++ b/java/perftests/visualisation-jfc/src/test/java/org/apache/qpid/disttest/charting/writer/expected-chart-summary.html
@@ -0,0 +1,9 @@
+<html>
+ <head>
+ <title>Performance Charts</title>
+ </head>
+ <body>
+ <img src='chart1.png'/>
+ <img src='chart2.png'/>
+ </body>
+</html> \ No newline at end of file
diff --git a/java/systests/build.xml b/java/systests/build.xml
index 6adce705cd..57337bdc55 100644
--- a/java/systests/build.xml
+++ b/java/systests/build.xml
@@ -19,12 +19,17 @@ nn - or more contributor license agreements. See the NOTICE file
-
-->
<project name="System Tests" default="build">
-
<condition property="systests.optional.depends" value="bdbstore" else="">
+ <or>
<and>
<contains string="${modules.opt}" substring="bdbstore"/>
<contains string="${profile}" substring="bdb"/>
</and>
+ <and>
+ <istrue value="${optional}"/>
+ <contains string="${profile}" substring="bdb"/>
+ </and>
+ </or>
</condition>
<property name="module.depends" value="client management/common broker broker/test common amqp-1-0-common common/test jca ${systests.optional.depends}"/>
diff --git a/java/systests/etc/config-systests-bdb.xml b/java/systests/etc/config-systests-bdb.xml
index 9364006fcc..6b17b564a8 100644
--- a/java/systests/etc/config-systests-bdb.xml
+++ b/java/systests/etc/config-systests-bdb.xml
@@ -25,6 +25,5 @@
<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/broker-plugins/extras/build.xml b/java/systests/etc/config-systests-derby-mem-settings.xml
index 7c1d0be49f..69369d9ac9 100644
--- a/java/broker-plugins/extras/build.xml
+++ b/java/systests/etc/config-systests-derby-mem-settings.xml
@@ -1,15 +1,16 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
<!--
-
- Licensed to the Apache Software Foundation (ASF) under one
-nn - or more contributor license agreements. See the NOTICE file
- -n distributed with this work for additional information
+ - or more contributor license agreements. See the NOTICE file
+ - distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
- -
+ -
- http://www.apache.org/licenses/LICENSE-2.0
- -
+ -
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -18,14 +19,8 @@ nn - or more contributor license agreements. See the NOTICE file
- under the License.
-
-->
-<project name="Qpid Broker-Plugins Extras" default="build">
- <property name="module.depends" value="common client management/common broker broker-plugins"/>
- <property name="module.test.depends" value="test broker/test common/test"/>
- <property name="module.manifest" value="MANIFEST.MF"/>
- <property name="module.plugin" value="true"/>
-
- <import file="../../module.xml"/>
+<broker>
+ <virtualhosts>${QPID_HOME}/etc/virtualhosts-systests-derby-mem.xml</virtualhosts>
+</broker>
- <target name="bundle" depends="bundle-tasks" />
-</project>
diff --git a/java/systests/etc/config-systests-derby-mem.xml b/java/systests/etc/config-systests-derby-mem.xml
new file mode 100644
index 0000000000..8e40df986e
--- /dev/null
+++ b/java/systests/etc/config-systests-derby-mem.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="${QPID_HOME}/${test.config}" optional="true"/>
+ <xml fileName="${QPID_HOME}/etc/config-systests-derby-mem-settings.xml"/>
+ <xml fileName="${QPID_HOME}/etc/config-systests-settings.xml"/>
+ </override>
+</configuration>
diff --git a/java/systests/etc/config-systests-derby.xml b/java/systests/etc/config-systests-derby.xml
index 303154d8f0..21a7a8cabe 100644
--- a/java/systests/etc/config-systests-derby.xml
+++ b/java/systests/etc/config-systests-derby.xml
@@ -25,6 +25,5 @@
<xml fileName="${QPID_HOME}/${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"/>
</override>
</configuration>
diff --git a/java/systests/etc/config-systests-firewall.xml b/java/systests/etc/config-systests-firewall.xml
index c73ac6a687..a884a39614 100644
--- a/java/systests/etc/config-systests-firewall.xml
+++ b/java/systests/etc/config-systests-firewall.xml
@@ -26,6 +26,5 @@
<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"/>
- <xml fileName="${QPID_HOME}/etc/config.xml"/>
</override>
</configuration>
diff --git a/java/systests/etc/config-systests-settings.xml b/java/systests/etc/config-systests-settings.xml
index 88533400d3..0b65ad83c3 100644
--- a/java/systests/etc/config-systests-settings.xml
+++ b/java/systests/etc/config-systests-settings.xml
@@ -20,7 +20,17 @@
-
-->
<broker>
+ <prefix>${QPID_HOME}</prefix>
+ <work>${QPID_WORK}</work>
+ <conf>${prefix}/etc</conf>
+
+ <plugin-directory>${QPID_HOME}/lib/plugins</plugin-directory>
+ <cache-directory>${QPID_WORK}/cache</cache-directory>
+
<connector>
+ <!-- To enable SSL edit the keystorePath and keystorePassword
+ and set enabled to true.
+ To disable Non-SSL port set sslOnly to true -->
<ssl>
<port>15671</port>
<enabled>false</enabled>
@@ -28,14 +38,66 @@
<keyStorePath>${QPID_HOME}/../test-profiles/test_resources/ssl/java_broker_keystore.jks</keyStorePath>
<keyStorePassword>password</keyStorePassword>
</ssl>
+ <port>5672</port>
+ <socketReceiveBuffer>262144</socketReceiveBuffer>
+ <socketSendBuffer>262144</socketSendBuffer>
</connector>
<management>
<enabled>false</enabled>
+ <jmxport>
+ <registryServer>8999</registryServer>
+ <!--
+ If unspecified, connectorServer defaults to 100 + registryServer port.
+ <connectorServer>9099</connectionServer>
+ -->
+ </jmxport>
<ssl>
<enabled>false</enabled>
<keyStorePath>${QPID_HOME}/../test-profiles/test_resources/ssl/java_broker_keystore.jks</keyStorePath>
<keyStorePassword>password</keyStorePassword>
</ssl>
+ <http>
+ <enabled>false</enabled>
+ </http>
</management>
+ <advanced>
+ <framesize>65535</framesize>
+ <locale>en_US</locale>
+ </advanced>
+
+ <security>
+ <pd-auth-manager>
+ <principal-database>
+ <class>org.apache.qpid.server.security.auth.database.PlainPasswordFilePrincipalDatabase</class>
+ <attributes>
+ <attribute>
+ <name>passwordFile</name>
+ <value>${conf}/passwd</value>
+ </attribute>
+ </attributes>
+ </principal-database>
+ </pd-auth-manager>
+
+ <!-- By default, all authenticated users have permissions to perform all actions -->
+
+ <!-- ACL Example
+ This example illustrates securing the both Management (JMX) and Messaging.
+ <acl>${conf}/broker_example.acl</acl>
+ -->
+
+ <msg-auth>false</msg-auth>
+ </security>
+
<virtualhosts>${QPID_HOME}/etc/virtualhosts-systests.xml</virtualhosts>
+
+ <heartbeat>
+ <delay>0</delay>
+ <timeoutFactor>2.0</timeoutFactor>
+ </heartbeat>
+ <queue>
+ <auto_register>true</auto_register>
+ </queue>
+
+ <status-updates>ON</status-updates>
+
</broker>
diff --git a/java/systests/etc/config-systests.xml b/java/systests/etc/config-systests.xml
index 0e8f2803e3..958aafc9da 100644
--- a/java/systests/etc/config-systests.xml
+++ b/java/systests/etc/config-systests.xml
@@ -24,6 +24,5 @@
<override>
<xml fileName="${QPID_HOME}/${test.config}" optional="true"/>
<xml fileName="${QPID_HOME}/etc/config-systests-settings.xml"/>
- <xml fileName="${QPID_HOME}/etc/config.xml"/>
</override>
</configuration>
diff --git a/java/systests/etc/log.properties b/java/systests/etc/log.properties
new file mode 100644
index 0000000000..745c5187c9
--- /dev/null
+++ b/java/systests/etc/log.properties
@@ -0,0 +1,2 @@
+com.sleepycat.je.util.FileHandler.level=ALL
+com.sleepycat.je.util.ConsoleHandler.level=ALL
diff --git a/java/systests/etc/virtualhosts-systests-bdb-settings.xml b/java/systests/etc/virtualhosts-systests-bdb-settings.xml
index 216046b40b..ce16523f13 100644
--- a/java/systests/etc/virtualhosts-systests-bdb-settings.xml
+++ b/java/systests/etc/virtualhosts-systests-bdb-settings.xml
@@ -26,7 +26,7 @@
<name>localhost</name>
<localhost>
<store>
- <factoryclass>org.apache.qpid.server.store.berkeleydb.BDBMessageStoreFactory</factoryclass>
+ <class>org.apache.qpid.server.store.berkeleydb.BDBMessageStore</class>
<environment-path>${work}/bdbstore/localhost-store</environment-path>
</store>
</localhost>
@@ -36,7 +36,7 @@
<name>development</name>
<development>
<store>
- <factoryclass>org.apache.qpid.server.store.berkeleydb.BDBMessageStoreFactory</factoryclass>
+ <class>org.apache.qpid.server.store.berkeleydb.BDBMessageStore</class>
<environment-path>${work}/bdbstore/development-store</environment-path>
</store>
</development>
@@ -46,7 +46,7 @@
<name>test</name>
<test>
<store>
- <factoryclass>org.apache.qpid.server.store.berkeleydb.BDBMessageStoreFactory</factoryclass>
+ <class>org.apache.qpid.server.store.berkeleydb.BDBMessageStore</class>
<environment-path>${work}/bdbstore/test-store</environment-path>
</store>
</test>
diff --git a/java/systests/etc/virtualhosts-systests-bdb.xml b/java/systests/etc/virtualhosts-systests-bdb.xml
index 367fee65ac..a797f3dbb5 100644
--- a/java/systests/etc/virtualhosts-systests-bdb.xml
+++ b/java/systests/etc/virtualhosts-systests-bdb.xml
@@ -24,6 +24,6 @@
<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"/>
+ <xml fileName="${QPID_HOME}/etc/virtualhosts-systests-settings.xml"/>
</override>
</configuration>
diff --git a/java/systests/etc/virtualhosts-systests-derby-mem-settings.xml b/java/systests/etc/virtualhosts-systests-derby-mem-settings.xml
new file mode 100644
index 0000000000..74189ad5e9
--- /dev/null
+++ b/java/systests/etc/virtualhosts-systests-derby-mem-settings.xml
@@ -0,0 +1,54 @@
+<?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>
+ <directory>${QPID_HOME}/virtualhosts</directory>
+ <default>test</default>
+
+ <virtualhost>
+ <localhost>
+ <store>
+ <factoryclass>org.apache.qpid.server.store.derby.DerbyMessageStoreFactory</factoryclass>
+ <environment-path>:memory:</environment-path>
+ </store>
+ </localhost>
+ </virtualhost>
+
+ <virtualhost>
+ <development>
+ <store>
+ <factoryclass>org.apache.qpid.server.store.derby.DerbyMessageStoreFactory</factoryclass>
+ <environment-path>:memory:</environment-path>
+ </store>
+ </development>
+ </virtualhost>
+
+ <virtualhost>
+ <test>
+ <store>
+ <factoryclass>org.apache.qpid.server.store.derby.DerbyMessageStoreFactory</factoryclass>
+ <environment-path>:memory:</environment-path>
+ </store>
+ </test>
+ </virtualhost>
+</virtualhosts>
+
+
diff --git a/java/systests/etc/virtualhosts-systests-derby-mem.xml b/java/systests/etc/virtualhosts-systests-derby-mem.xml
new file mode 100644
index 0000000000..5fd8762ec9
--- /dev/null
+++ b/java/systests/etc/virtualhosts-systests-derby-mem.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="${QPID_HOME}/${test.virtualhosts}" optional="true"/>
+ <xml fileName="${QPID_HOME}/etc/virtualhosts-systests-derby-mem-settings.xml"/>
+ <xml fileName="${QPID_HOME}/etc/virtualhosts-systests-settings.xml"/>
+ </override>
+</configuration>
diff --git a/java/systests/etc/virtualhosts-systests-derby-settings.xml b/java/systests/etc/virtualhosts-systests-derby-settings.xml
index d494768e91..08a40ca812 100644
--- a/java/systests/etc/virtualhosts-systests-derby-settings.xml
+++ b/java/systests/etc/virtualhosts-systests-derby-settings.xml
@@ -26,7 +26,7 @@
<virtualhost>
<localhost>
<store>
- <factoryclass>org.apache.qpid.server.store.derby.DerbyMessageStoreFactory</factoryclass>
+ <class>org.apache.qpid.server.store.derby.DerbyMessageStore</class>
<environment-path>${QPID_WORK}/derbyDB/localhost-store</environment-path>
</store>
</localhost>
@@ -35,7 +35,7 @@
<virtualhost>
<development>
<store>
- <factoryclass>org.apache.qpid.server.store.derby.DerbyMessageStoreFactory</factoryclass>
+ <class>org.apache.qpid.server.store.derby.DerbyMessageStore</class>
<environment-path>${QPID_WORK}/derbyDB/development-store</environment-path>
</store>
</development>
@@ -44,7 +44,7 @@
<virtualhost>
<test>
<store>
- <factoryclass>org.apache.qpid.server.store.derby.DerbyMessageStoreFactory</factoryclass>
+ <class>org.apache.qpid.server.store.derby.DerbyMessageStore</class>
<environment-path>${QPID_WORK}/derbyDB/test-store</environment-path>
</store>
</test>
diff --git a/java/systests/etc/virtualhosts-systests-derby.xml b/java/systests/etc/virtualhosts-systests-derby.xml
index 3745100e1f..3e7034ad94 100644
--- a/java/systests/etc/virtualhosts-systests-derby.xml
+++ b/java/systests/etc/virtualhosts-systests-derby.xml
@@ -24,6 +24,6 @@
<override>
<xml fileName="${QPID_HOME}/${test.virtualhosts}" optional="true"/>
<xml fileName="${QPID_HOME}/etc/virtualhosts-systests-derby-settings.xml"/>
- <xml fileName="${QPID_HOME}/etc/virtualhosts.xml"/>
+ <xml fileName="${QPID_HOME}/etc/virtualhosts-systests-settings.xml"/>
</override>
</configuration>
diff --git a/java/systests/etc/virtualhosts-systests-firewall-2.xml b/java/systests/etc/virtualhosts-systests-firewall-2.xml
index f8e9fde8ca..20908e6eb4 100644
--- a/java/systests/etc/virtualhosts-systests-firewall-2.xml
+++ b/java/systests/etc/virtualhosts-systests-firewall-2.xml
@@ -26,7 +26,7 @@
<name>test</name>
<test>
<store>
- <factoryclass>org.apache.qpid.server.store.MemoryMessageStoreFactory</factoryclass>
+ <class>org.apache.qpid.server.store.MemoryMessageStore</class>
</store>
</test>
</virtualhost>
@@ -35,7 +35,7 @@
<name>test2</name>
<test2>
<store>
- <factoryclass>org.apache.qpid.server.store.MemoryMessageStoreFactory</factoryclass>
+ <class>org.apache.qpid.server.store.MemoryMessageStore</class>
</store>
<security>
<firewall default-action="deny">
diff --git a/java/systests/etc/virtualhosts-systests-firewall-3.xml b/java/systests/etc/virtualhosts-systests-firewall-3.xml
index 95db02672a..90377f345f 100644
--- a/java/systests/etc/virtualhosts-systests-firewall-3.xml
+++ b/java/systests/etc/virtualhosts-systests-firewall-3.xml
@@ -26,7 +26,7 @@
<name>test</name>
<test>
<store>
- <factoryclass>org.apache.qpid.server.store.MemoryMessageStoreFactory</factoryclass>
+ <class>org.apache.qpid.server.store.MemoryMessageStore</class>
</store>
</test>
</virtualhost>
@@ -35,7 +35,7 @@
<name>test2</name>
<test2>
<store>
- <factoryclass>org.apache.qpid.server.store.MemoryMessageStoreFactory</factoryclass>
+ <class>org.apache.qpid.server.store.MemoryMessageStore</class>
</store>
<security>
<firewall default-action="deny"/>
diff --git a/java/systests/etc/virtualhosts-systests-firewall.xml b/java/systests/etc/virtualhosts-systests-firewall.xml
index c5c6a86d7c..17860e4075 100644
--- a/java/systests/etc/virtualhosts-systests-firewall.xml
+++ b/java/systests/etc/virtualhosts-systests-firewall.xml
@@ -24,6 +24,6 @@
<override>
<xml fileName="${QPID_HOME}/${test.virtualhosts}" optional="true"/>
<xml fileName="${QPID_FIREWALL_VIRTUALHOSTS_SETTINGS}" optional="true"/>
- <xml fileName="${QPID_HOME}/etc/virtualhosts.xml"/>
+ <xml fileName="${QPID_HOME}/etc/virtualhosts-systests-settings.xml"/>
</override>
</configuration>
diff --git a/java/systests/etc/virtualhosts-systests-settings.xml b/java/systests/etc/virtualhosts-systests-settings.xml
new file mode 100644
index 0000000000..0ec16b31ef
--- /dev/null
+++ b/java/systests/etc/virtualhosts-systests-settings.xml
@@ -0,0 +1,157 @@
+<?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>test</default>
+ <virtualhost>
+ <name>localhost</name>
+ <localhost>
+ <store>
+ <class>org.apache.qpid.server.store.MemoryMessageStore</class>
+ </store>
+
+ <housekeeping>
+ <threadCount>2</threadCount>
+ <checkPeriod>20000</checkPeriod>
+ </housekeeping>
+
+ <exchanges>
+ <exchange>
+ <type>direct</type>
+ <name>test.direct</name>
+ <durable>true</durable>
+ </exchange>
+ <exchange>
+ <type>topic</type>
+ <name>test.topic</name>
+ </exchange>
+ </exchanges>
+ <queues>
+ <exchange>amq.direct</exchange>
+ <maximumQueueDepth>4235264</maximumQueueDepth>
+ <!-- 4Mb -->
+ <maximumMessageSize>2117632</maximumMessageSize>
+ <!-- 2Mb -->
+ <maximumMessageAge>600000</maximumMessageAge>
+ <!-- 10 mins -->
+ <maximumMessageCount>50</maximumMessageCount>
+ <!-- 50 messages -->
+
+ <queue>
+ <name>queue</name>
+ </queue>
+ <queue>
+ <name>ping</name>
+ </queue>
+ <queue>
+ <name>test-queue</name>
+ <test-queue>
+ <exchange>test.direct</exchange>
+ <durable>true</durable>
+ </test-queue>
+ </queue>
+ <queue>
+ <name>test-ping</name>
+ <test-ping>
+ <exchange>test.direct</exchange>
+ </test-ping>
+ </queue>
+
+ </queues>
+ </localhost>
+ </virtualhost>
+
+
+ <virtualhost>
+ <name>development</name>
+ <development>
+ <store>
+ <class>org.apache.qpid.server.store.MemoryMessageStore</class>
+ </store>
+
+ <queues>
+ <minimumAlertRepeatGap>30000</minimumAlertRepeatGap>
+ <maximumMessageCount>50</maximumMessageCount>
+ <queue>
+ <name>queue</name>
+ <queue>
+ <exchange>amq.direct</exchange>
+ <maximumQueueDepth>4235264</maximumQueueDepth>
+ <!-- 4Mb -->
+ <maximumMessageSize>2117632</maximumMessageSize>
+ <!-- 2Mb -->
+ <maximumMessageAge>600000</maximumMessageAge>
+ <!-- 10 mins -->
+ </queue>
+ </queue>
+ <queue>
+ <name>ping</name>
+ <ping>
+ <exchange>amq.direct</exchange>
+ <maximumQueueDepth>4235264</maximumQueueDepth>
+ <!-- 4Mb -->
+ <maximumMessageSize>2117632</maximumMessageSize>
+ <!-- 2Mb -->
+ <maximumMessageAge>600000</maximumMessageAge>
+ <!-- 10 mins -->
+ </ping>
+ </queue>
+ </queues>
+ </development>
+ </virtualhost>
+ <virtualhost>
+ <name>test</name>
+ <test>
+ <store>
+ <class>org.apache.qpid.server.store.MemoryMessageStore</class>
+ </store>
+
+ <queues>
+ <minimumAlertRepeatGap>30000</minimumAlertRepeatGap>
+ <maximumMessageCount>50</maximumMessageCount>
+ <queue>
+ <name>queue</name>
+ <queue>
+ <exchange>amq.direct</exchange>
+ <maximumQueueDepth>4235264</maximumQueueDepth>
+ <!-- 4Mb -->
+ <maximumMessageSize>2117632</maximumMessageSize>
+ <!-- 2Mb -->
+ <maximumMessageAge>600000</maximumMessageAge>
+ <!-- 10 mins -->
+ </queue>
+ </queue>
+ <queue>
+ <name>ping</name>
+ <ping>
+ <exchange>amq.direct</exchange>
+ <maximumQueueDepth>4235264</maximumQueueDepth>
+ <!-- 4Mb -->
+ <maximumMessageSize>2117632</maximumMessageSize>
+ <!-- 2Mb -->
+ <maximumMessageAge>600000</maximumMessageAge>
+ <!-- 10 mins -->
+ </ping>
+ </queue>
+ </queues>
+ </test>
+ </virtualhost>
+</virtualhosts>
diff --git a/java/systests/etc/virtualhosts-systests.xml b/java/systests/etc/virtualhosts-systests.xml
index d6aeefac72..d2bdad3cc6 100644
--- a/java/systests/etc/virtualhosts-systests.xml
+++ b/java/systests/etc/virtualhosts-systests.xml
@@ -23,6 +23,6 @@
<system/>
<override>
<xml fileName="${QPID_HOME}/${test.virtualhosts}" optional="true"/>
- <xml fileName="${QPID_HOME}/etc/virtualhosts.xml"/>
+ <xml fileName="${QPID_HOME}/etc/virtualhosts-systests-settings.xml"/>
</override>
</configuration>
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
index 526db29181..4b766864b4 100644
--- 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
@@ -19,7 +19,13 @@
package org.apache.qpid.client.failover;
import org.apache.qpid.client.AMQConnection;
+import org.apache.qpid.client.AMQConnectionFactory;
+import org.apache.qpid.client.AMQDestination;
+import org.apache.qpid.client.AMQSession;
+import org.apache.qpid.framing.AMQShortString;
+import org.apache.qpid.jms.BrokerDetails;
import org.apache.qpid.jms.ConnectionListener;
+import org.apache.qpid.jms.ConnectionURL;
import org.apache.qpid.jms.FailoverPolicy;
import org.apache.qpid.test.utils.FailoverBaseCase;
@@ -36,10 +42,14 @@ import javax.jms.QueueBrowser;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.jms.TransactionRolledBackException;
+import javax.naming.NamingException;
+
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Enumeration;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
@@ -760,6 +770,181 @@ public class FailoverBehaviourTest extends FailoverBaseCase implements Connectio
//got started, before allowing the test to tear down
awaitForFailoverCompletion(DEFAULT_FAILOVER_TIME);
}
+
+ /**
+ * This test only tests 0-8/0-9/0-9-1 failover timeout
+ */
+ public void testFailoverHandlerTimeoutExpires() throws Exception
+ {
+ _connection.close();
+ setTestSystemProperty("qpid.failover_method_timeout", "10000");
+ AMQConnection connection = null;
+ try
+ {
+ connection = createConnectionWithFailover();
+
+ // holding failover mutex should prevent the failover from proceeding
+ synchronized(connection.getFailoverMutex())
+ {
+ killBroker();
+ startBroker();
+
+ // sleep interval exceeds failover timeout interval
+ Thread.sleep(11000l);
+ }
+
+ // allows the failover thread to proceed
+ Thread.yield();
+ assertFalse("Unexpected failover", _failoverComplete.await(2000l, TimeUnit.MILLISECONDS));
+ assertTrue("Failover should not succeed due to timeout", connection.isClosed());
+ }
+ finally
+ {
+ if (connection != null)
+ {
+ connection.close();
+ }
+ }
+ }
+
+ public void testFailoverHandlerTimeoutReconnected() throws Exception
+ {
+ _connection.close();
+ setTestSystemProperty("qpid.failover_method_timeout", "10000");
+ AMQConnection connection = null;
+ try
+ {
+ connection = createConnectionWithFailover();
+
+ // holding failover mutex should prevent the failover from proceeding
+ synchronized(connection.getFailoverMutex())
+ {
+ killBroker();
+ startBroker();
+ }
+
+ // allows the failover thread to proceed
+ Thread.yield();
+ awaitForFailoverCompletion(DEFAULT_FAILOVER_TIME);
+ assertFalse("Failover should restore connectivity", connection.isClosed());
+ }
+ finally
+ {
+ if (connection != null)
+ {
+ connection.close();
+ }
+ }
+ }
+
+ /**
+ * Tests that the producer flow control flag is reset when failover occurs while
+ * the producers are being blocked by the broker.
+ *
+ * Uses Java broker specific queue configuration to enabled PSFC.
+ */
+ public void testFlowControlFlagResetOnFailover() throws Exception
+ {
+ // we do not need the connection failing to second broker
+ _connection.close();
+
+ // make sure that failover timeout is bigger than flow control timeout
+ setTestSystemProperty("qpid.failover_method_timeout", "60000");
+ setTestSystemProperty("qpid.flow_control_wait_failure", "10000");
+
+ AMQConnection connection = null;
+ try
+ {
+ connection = createConnectionWithFailover();
+
+ final Session producerSession = connection.createSession(true, Session.SESSION_TRANSACTED);
+ final Queue queue = createAndBindQueueWithFlowControlEnabled(producerSession, getTestQueueName(), DEFAULT_MESSAGE_SIZE * 3, DEFAULT_MESSAGE_SIZE * 2);
+ final AtomicInteger counter = new AtomicInteger();
+ // try to send 5 messages (should block after 4)
+ new Thread(new Runnable()
+ {
+ @Override
+ public void run()
+ {
+ try
+ {
+ MessageProducer producer = producerSession.createProducer(queue);
+ for (int i=0; i < 5; i++)
+ {
+ Message next = createNextMessage(producerSession, i);
+ producer.send(next);
+ producerSession.commit();
+ counter.incrementAndGet();
+ }
+ }
+ catch(Exception e)
+ {
+ // ignore
+ }
+ }
+ }).start();
+
+ long limit= 30000l;
+ long start = System.currentTimeMillis();
+
+ // wait until session is blocked
+ while(!((AMQSession<?,?>)producerSession).isFlowBlocked() && System.currentTimeMillis() - start < limit)
+ {
+ Thread.sleep(100l);
+ }
+
+ assertTrue("Flow is not blocked", ((AMQSession<?, ?>) producerSession).isFlowBlocked());
+ // Message counter could be 3 or 4 depending on the progression of producing thread relative
+ // to the receipt of the ChannelFlow.
+ final int currentCounter = counter.get();
+ assertTrue("Unexpected number of sent messages", currentCounter == 3 || currentCounter == 4);
+
+ killBroker();
+ startBroker();
+
+ // allows the failover thread to proceed
+ Thread.yield();
+ awaitForFailoverCompletion(60000l);
+
+ assertFalse("Flow is blocked", ((AMQSession<?, ?>) producerSession).isFlowBlocked());
+ }
+ finally
+ {
+ if (connection != null)
+ {
+ connection.close();
+ }
+ }
+ }
+
+ private Queue createAndBindQueueWithFlowControlEnabled(Session session, String queueName, int capacity, int resumeCapacity) throws Exception
+ {
+ final Map<String, Object> arguments = new HashMap<String, Object>();
+ arguments.put("x-qpid-capacity", capacity);
+ arguments.put("x-qpid-flow-resume-capacity", resumeCapacity);
+ ((AMQSession<?, ?>) session).createQueue(new AMQShortString(queueName), true, true, false, arguments);
+ Queue queue = session.createQueue("direct://amq.direct/" + queueName + "/" + queueName + "?durable='" + true
+ + "'&autodelete='" + true + "'");
+ ((AMQSession<?, ?>) session).declareAndBind((AMQDestination) queue);
+ return queue;
+ }
+
+ private AMQConnection createConnectionWithFailover() throws NamingException, JMSException
+ {
+ AMQConnection connection;
+ AMQConnectionFactory connectionFactory = (AMQConnectionFactory)getConnectionFactory("default");
+ ConnectionURL connectionURL = connectionFactory.getConnectionURL();
+ connectionURL.setOption(ConnectionURL.OPTIONS_FAILOVER, "singlebroker");
+ connectionURL.setOption(ConnectionURL.OPTIONS_FAILOVER_CYCLE, "2");
+ BrokerDetails details = connectionURL.getBrokerDetails(0);
+ details.setProperty(BrokerDetails.OPTIONS_RETRY, "200");
+ details.setProperty(BrokerDetails.OPTIONS_CONNECT_DELAY, "1000");
+
+ connection = (AMQConnection)connectionFactory.createConnection("admin", "admin");
+ connection.setConnectionListener(this);
+ return connection;
+ }
+
/**
* Tests {@link Session#close()} for session with given acknowledge mode
* to ensure that close works after failover.
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 c4b1b08eea..787e727e66 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
@@ -1,4 +1,3 @@
-package org.apache.qpid.client.message;
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
@@ -19,6 +18,7 @@ package org.apache.qpid.client.message;
* under the License.
*
*/
+package org.apache.qpid.client.message;
import org.apache.qpid.test.utils.QpidBrokerTestCase;
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 1cd088b736..39689f5096 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
@@ -46,6 +46,7 @@ public class SSLTest extends QpidBrokerTestCase
setTestClientSystemProperty("profile.use_ssl", "true");
setConfigurationProperty("connector.ssl.enabled", "true");
setConfigurationProperty("connector.ssl.sslOnly", "true");
+ setConfigurationProperty("connector.ssl.wantClientAuth", "true");
}
// set the ssl system properties
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
index ac29b72620..e18f70b01d 100644
--- 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
@@ -24,21 +24,72 @@ 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;
+import org.apache.qpid.test.unit.xa.AbstractXATestCase;
+import org.apache.qpid.client.AMQXAResource;
+
+import org.apache.qpid.dtx.XidImpl;
import javax.jms.XAConnection;
import javax.jms.XAConnectionFactory;
import javax.jms.XASession;
+import javax.transaction.xa.XAException;
import javax.transaction.xa.XAResource;
+import javax.transaction.xa.Xid;
-public class XAResourceTest extends QpidBrokerTestCase
+public class XAResourceTest extends AbstractXATestCase
{
private static final String FACTORY_NAME = "default";
private static final String ALT_FACTORY_NAME = "connection2";
+ public void init() throws Exception
+ {
+ }
+
+ public void testIsSameRMJoin() throws Exception
+ {
+ XAConnectionFactory factory = getConnectionFactory(FACTORY_NAME);
+ XAConnection conn1 = factory.createXAConnection("guest", "guest");
+ XAConnection conn2 = factory.createXAConnection("guest", "guest");
+ XAConnection conn3 = factory.createXAConnection("guest", "guest");
+
+ XASession session1 = conn1.createXASession();
+ XASession session2 = conn2.createXASession();
+ XASession session3 = conn3.createXASession();
+
+ AMQXAResource xaResource1 = (AMQXAResource)session1.getXAResource();
+ AMQXAResource xaResource2 = (AMQXAResource)session2.getXAResource();
+ AMQXAResource xaResource3 = (AMQXAResource)session3.getXAResource();
+
+ Xid xid = getNewXid();
+
+ xaResource1.start(xid, XAResource.TMNOFLAGS);
+ assertTrue("XAResource isSameRM", xaResource1.isSameRM(xaResource2));
+ xaResource2.start(xid, XAResource.TMJOIN);
+ assertTrue("AMQXAResource siblings should be 1", xaResource1.getSiblings().size() == 1);
+
+ assertTrue("AMQXAResource TMJOIN resource siblings should be 0", xaResource2.getSiblings().size() == 0);
+
+ assertTrue("XAResource isSameRM", xaResource2.isSameRM(xaResource3));
+
+
+ xaResource3.start(xid, XAResource.TMJOIN);
+ assertTrue("AMQXAResource siblings should be 1", xaResource2.getSiblings().size() == 1);
+
+ xaResource1.end(xid, XAResource.TMSUCCESS);
+ assertTrue("AMQXAResource TMJOIN resource siblings should be 0", xaResource1.getSiblings().size() == 0);
+
+ xaResource1.prepare(xid);
+ xaResource1.commit(xid, false);
+
+ conn3.close();
+ conn2.close();
+ conn1.close();
+ }
+
/*
* Test with multiple XAResources originating from the same connection factory. XAResource(s) will be equal,
- * as they originate from the same session.
+ * as they originate from the same session.
*/
public void testIsSameRMSingleCF() throws Exception
{
@@ -47,14 +98,14 @@ public class XAResourceTest extends QpidBrokerTestCase
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.
@@ -67,11 +118,11 @@ public class XAResourceTest extends QpidBrokerTestCase
XAConnectionFactory factory = new AMQConnectionFactory(url);
XAConnectionFactory factory2 = new AMQConnectionFactory(url);
XAConnectionFactory factory3 = getConnectionFactory(ALT_FACTORY_NAME);
-
+
XAConnection conn = factory.createXAConnection("guest","guest");
XAConnection conn2 = factory2.createXAConnection("guest","guest");
XAConnection conn3 = factory3.createXAConnection("guest","guest");
-
+
XASession session = conn.createXASession();
XASession session2 = conn2.createXASession();
XASession session3 = conn3.createXASession();
@@ -79,14 +130,14 @@ public class XAResourceTest extends QpidBrokerTestCase
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();
+ conn3.close();
}
@Override
@@ -103,5 +154,5 @@ public class XAResourceTest extends QpidBrokerTestCase
FileUtils.deleteDirectory(System.getProperty("QPID_WORK") + "/" + getFailingPort());
}
}
-
+
}
diff --git a/java/systests/src/main/java/org/apache/qpid/management/jmx/ManagedConnectionMBeanTest.java b/java/systests/src/main/java/org/apache/qpid/management/jmx/ManagedConnectionMBeanTest.java
deleted file mode 100644
index 3fc370dc68..0000000000
--- a/java/systests/src/main/java/org/apache/qpid/management/jmx/ManagedConnectionMBeanTest.java
+++ /dev/null
@@ -1,278 +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.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import org.apache.qpid.client.AMQSession;
-import org.apache.qpid.common.QpidProperties;
-import org.apache.qpid.management.common.mbeans.ManagedConnection;
-import org.apache.qpid.test.utils.JMXTestUtils;
-import org.apache.qpid.test.utils.QpidBrokerTestCase;
-
-import javax.jms.Connection;
-import javax.jms.Destination;
-import javax.jms.Message;
-import javax.jms.MessageConsumer;
-import javax.jms.MessageProducer;
-import javax.jms.Session;
-import javax.jms.TextMessage;
-import javax.management.JMException;
-import javax.management.openmbean.CompositeDataSupport;
-import javax.management.openmbean.TabularData;
-import java.io.IOException;
-import java.util.Date;
-import java.util.Iterator;
-import java.util.List;
-
-public class ManagedConnectionMBeanTest extends QpidBrokerTestCase
-{
- private static final Logger LOGGER = LoggerFactory.getLogger(ManagedConnectionMBeanTest.class);
-
- /**
- * JMX helper.
- */
- private JMXTestUtils _jmxUtils;
- private Connection _connection;
-
- public void setUp() throws Exception
- {
- _jmxUtils = new JMXTestUtils(this);
- _jmxUtils.setUp();
- super.setUp();
- _jmxUtils.open();
- _connection = getConnection();
- }
-
- public void tearDown() throws Exception
- {
- if (_jmxUtils != null)
- {
- _jmxUtils.close();
- }
- super.tearDown();
- }
-
- public void testChannels() throws Exception
- {
- final String queueName = getTestQueueName();
-
- final Session session = _connection.createSession(true, Session.SESSION_TRANSACTED);
- final Destination destination = session.createQueue(queueName);
- final MessageConsumer consumer = session.createConsumer(destination);
-
- final int numberOfMessages = 2;
- sendMessage(session, destination, numberOfMessages);
- _connection.start();
-
- for (int i = 0; i < numberOfMessages; i++)
- {
- final Message m = consumer.receive(1000l);
- assertNotNull("Message " + i + " is not received", m);
- }
-
- List<ManagedConnection> connections = _jmxUtils.getManagedConnections("test");
- assertNotNull("Connection MBean is not found", connections);
- assertEquals("Unexpected number of connection mbeans", 1, connections.size());
- final ManagedConnection mBean = connections.get(0);
- assertNotNull("Connection MBean is null", mBean);
-
- TabularData channelsData = mBean.channels();
- assertNotNull("Channels data are null", channelsData);
- assertEquals("Unexpected number of rows in channel table", 1, channelsData.size());
-
- final Iterator<CompositeDataSupport> rowItr = (Iterator<CompositeDataSupport>) channelsData.values().iterator();
- final CompositeDataSupport row = rowItr.next();
- Number unackCount = (Number) row.get(ManagedConnection.UNACKED_COUNT);
- final Boolean transactional = (Boolean) row.get(ManagedConnection.TRANSACTIONAL);
- final Boolean flowBlocked = (Boolean) row.get(ManagedConnection.FLOW_BLOCKED);
- assertNotNull("Channel should have unacknowledged messages", unackCount);
- assertEquals("Unexpected number of unacknowledged messages", 2, unackCount.intValue());
- assertNotNull("Channel should have transaction flag", transactional);
- assertTrue("Unexpected transaction flag", transactional);
- assertNotNull("Channel should have flow blocked flag", flowBlocked);
- assertFalse("Unexpected value of flow blocked flag", flowBlocked);
-
- final Date initialLastIOTime = mBean.getLastIoTime();
- session.commit();
- assertTrue("Last IO time should have been updated", mBean.getLastIoTime().after(initialLastIOTime));
-
- channelsData = mBean.channels();
- assertNotNull("Channels data are null", channelsData);
- assertEquals("Unexpected number of rows in channel table", 1, channelsData.size());
-
- final Iterator<CompositeDataSupport> rowItr2 = (Iterator<CompositeDataSupport>) channelsData.values().iterator();
- final CompositeDataSupport row2 = rowItr2.next();
- unackCount = (Number) row2.get(ManagedConnection.UNACKED_COUNT);
- assertNotNull("Channel should have unacknowledged messages", unackCount);
- assertEquals("Unexpected number of anacknowledged messages", 0, unackCount.intValue());
-
- _connection.close();
-
- LOGGER.debug("Querying JMX for number of open connections");
- connections = _jmxUtils.getManagedConnections("test");
- assertNotNull("Connection MBean is not found", connections);
- assertEquals("Unexpected number of connection mbeans after connection closed", 0, connections.size());
- }
-
- public void testCommit() throws Exception
- {
- final String queueName = getTestQueueName();
-
- final Session consumerSession = _connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
- final Session producerSession = _connection.createSession(true, Session.SESSION_TRANSACTED);
- final Destination destination = producerSession.createQueue(queueName);
- final MessageConsumer consumer = consumerSession.createConsumer(destination);
- final MessageProducer producer = producerSession.createProducer(destination);
-
- _connection.start();
-
- List<ManagedConnection> connections = _jmxUtils.getManagedConnections("test");
- assertNotNull("Connection MBean is not found", connections);
- assertEquals("Unexpected number of connection mbeans", 1, connections.size());
- final ManagedConnection mBean = connections.get(0);
- assertNotNull("Connection MBean is null", mBean);
-
- final int numberOfMessages = 2;
- for (int i = 0; i < numberOfMessages; i++)
- {
- producer.send(producerSession.createTextMessage("Test " + i));
- }
-
- // sync to make sure that messages are received on the broker
- // before we commit via JMX
- ((AMQSession<?, ?>) producerSession).sync();
-
- Message m = consumer.receive(500l);
- assertNull("Unexpected message received", m);
-
- Number channelId = getFirstTransactedChannelId(mBean, 2);
- mBean.commitTransactions(channelId.intValue());
-
- for (int i = 0; i < numberOfMessages; i++)
- {
- m = consumer.receive(1000l);
- assertNotNull("Message " + i + " is not received", m);
- assertEquals("Unexpected message received at " + i, "Test " + i, ((TextMessage) m).getText());
- }
- producerSession.commit();
- m = consumer.receive(500l);
- assertNull("Unexpected message received", m);
- }
-
- protected Number getFirstTransactedChannelId(final ManagedConnection mBean, int channelNumber) throws IOException, JMException
- {
- TabularData channelsData = mBean.channels();
- assertNotNull("Channels data are null", channelsData);
- assertEquals("Unexpected number of rows in channel table", channelNumber, channelsData.size());
- final Iterator<CompositeDataSupport> rowItr = (Iterator<CompositeDataSupport>) channelsData.values().iterator();
- while (rowItr.hasNext())
- {
- final CompositeDataSupport row = rowItr.next();
- Boolean transacted = (Boolean) row.get(ManagedConnection.TRANSACTIONAL);
- if (transacted.booleanValue())
- {
- return (Number) row.get(ManagedConnection.CHAN_ID);
- }
- }
- return null;
- }
-
- public void testRollback() throws Exception
- {
- final String queueName = getTestQueueName();
-
- final Session consumerSession = _connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
- final Session producerSession = _connection.createSession(true, Session.SESSION_TRANSACTED);
- final Destination destination = producerSession.createQueue(queueName);
- final MessageConsumer consumer = consumerSession.createConsumer(destination);
- final MessageProducer producer = producerSession.createProducer(destination);
-
- List<ManagedConnection> connections = _jmxUtils.getManagedConnections("test");
- assertNotNull("Connection MBean is not found", connections);
- assertEquals("Unexpected number of connection mbeans", 1, connections.size());
- final ManagedConnection mBean = connections.get(0);
- assertNotNull("Connection MBean is null", mBean);
-
- final int numberOfMessages = 2;
- for (int i = 0; i < numberOfMessages; i++)
- {
- producer.send(producerSession.createTextMessage("Test " + i));
- }
-
- // sync to make sure that messages are received on the broker
- // before we rollback via JMX
- ((AMQSession<?, ?>) producerSession).sync();
-
- Number channelId = getFirstTransactedChannelId(mBean, 2);
- mBean.rollbackTransactions(channelId.intValue());
-
- Message m = consumer.receive(1000l);
- assertNull("Unexpected message received: " + String.valueOf(m), m);
-
- producerSession.commit();
-
- _connection.start();
- m = consumer.receive(1000l);
- assertNull("Unexpected message received after commit " + String.valueOf(m), m);
- }
-
- public void testAuthorisedId() throws Exception
- {
- List<ManagedConnection> connections = _jmxUtils.getManagedConnections("test");
- assertNotNull("Connection MBean is not found", connections);
- assertEquals("Unexpected number of connection mbeans", 1, connections.size());
- final ManagedConnection mBean = connections.get(0);
- assertNotNull("Connection MBean is null", mBean);
- assertEquals("Unexpected authorized id", "guest", mBean.getAuthorizedId());
- }
-
- public void testClientVersion() throws Exception
- {
- List<ManagedConnection> connections = _jmxUtils.getManagedConnections("test");
- assertNotNull("Connection MBean is not found", connections);
- assertEquals("Unexpected number of connection mbeans", 1, connections.size());
- final ManagedConnection mBean = connections.get(0);
- assertNotNull("Connection MBean is null", mBean);
-
- String expectedVersion = QpidProperties.getReleaseVersion();
- assertNotNull("version should not be null", expectedVersion);
- assertFalse("version should not be the empty string", expectedVersion.equals(""));
- assertFalse("version should not be the string 'null'", expectedVersion.equals("null"));
-
- assertEquals("Unexpected version", expectedVersion, mBean.getVersion());
- }
-
- public void testClientId() throws Exception
- {
- List<ManagedConnection> connections = _jmxUtils.getManagedConnections("test");
- assertNotNull("Connection MBean is not found", connections);
- assertEquals("Unexpected number of connection mbeans", 1, connections.size());
- final ManagedConnection mBean = connections.get(0);
- assertNotNull("Connection MBean is null", mBean);
-
- String expectedClientId = _connection.getClientID();
- assertNotNull("ClientId should not be null", expectedClientId);
- assertFalse("ClientId should not be the empty string", expectedClientId.equals(""));
- assertFalse("ClientId should not be the string 'null'", expectedClientId.equals("null"));
-
- assertEquals("Unexpected ClientId", expectedClientId, mBean.getClientId());
- }
-}
diff --git a/java/systests/src/main/java/org/apache/qpid/management/jmx/ManagedQueueMBeanTest.java b/java/systests/src/main/java/org/apache/qpid/management/jmx/ManagedQueueMBeanTest.java
deleted file mode 100644
index 244e547e02..0000000000
--- a/java/systests/src/main/java/org/apache/qpid/management/jmx/ManagedQueueMBeanTest.java
+++ /dev/null
@@ -1,345 +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.commons.lang.time.FastDateFormat;
-
-import org.apache.log4j.Logger;
-import org.apache.qpid.client.AMQSession;
-import org.apache.qpid.configuration.ClientProperties;
-import org.apache.qpid.management.common.mbeans.ManagedQueue;
-import org.apache.qpid.server.queue.AMQQueueMBean;
-import org.apache.qpid.test.utils.JMXTestUtils;
-import org.apache.qpid.test.utils.QpidBrokerTestCase;
-
-import javax.jms.Connection;
-import javax.jms.Destination;
-import javax.jms.JMSException;
-import javax.jms.Message;
-import javax.jms.MessageConsumer;
-import javax.jms.MessageListener;
-import javax.jms.Session;
-import javax.management.openmbean.CompositeData;
-import javax.management.openmbean.TabularData;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.SortedSet;
-import java.util.TreeSet;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicInteger;
-
-/**
- * Tests the JMX API for the Managed Queue.
- *
- */
-public class ManagedQueueMBeanTest extends QpidBrokerTestCase
-{
- protected static final Logger LOGGER = Logger.getLogger(ManagedQueueMBeanTest.class);
-
- private JMXTestUtils _jmxUtils;
- private Connection _connection;
- private Session _session;
-
- private String _sourceQueueName;
- private String _destinationQueueName;
- private Destination _sourceQueue;
- private Destination _destinationQueue;
- private ManagedQueue _managedSourceQueue;
- private ManagedQueue _managedDestinationQueue;
-
- public void setUp() throws Exception
- {
- _jmxUtils = new JMXTestUtils(this);
- _jmxUtils.setUp();
-
- super.setUp();
- _sourceQueueName = getTestQueueName() + "_src";
- _destinationQueueName = getTestQueueName() + "_dest";
-
- _connection = getConnection();
- _connection.start();
-
- _session = _connection.createSession(true, Session.SESSION_TRANSACTED);
- _sourceQueue = _session.createQueue(_sourceQueueName);
- _destinationQueue = _session.createQueue(_destinationQueueName);
- createQueueOnBroker(_sourceQueue);
- createQueueOnBroker(_destinationQueue);
-
- _jmxUtils.open();
-
- _managedSourceQueue = _jmxUtils.getManagedQueue(_sourceQueueName);
- _managedDestinationQueue = _jmxUtils.getManagedQueue(_destinationQueueName);
- }
-
- public void tearDown() throws Exception
- {
- if (_jmxUtils != null)
- {
- _jmxUtils.close();
- }
- super.tearDown();
- }
-
- /**
- * Tests {@link ManagedQueue#viewMessages(long, long)} interface.
- */
- public void testViewSingleMessage() throws Exception
- {
- final List<Message> sentMessages = sendMessage(_session, _sourceQueue, 1);
- syncSession(_session);
- final Message sentMessage = sentMessages.get(0);
-
- assertEquals("Unexpected queue depth", 1, _managedSourceQueue.getMessageCount().intValue());
-
- // Check the contents of the message
- final TabularData tab = _managedSourceQueue.viewMessages(1l, 1l);
- assertEquals("Unexpected number of rows in table", 1, tab.size());
- final Iterator<CompositeData> rowItr = (Iterator<CompositeData>) tab.values().iterator();
-
- final CompositeData row1 = rowItr.next();
- assertNotNull("Message should have AMQ message id", row1.get(ManagedQueue.MSG_AMQ_ID));
- assertEquals("Unexpected queue position", 1l, row1.get(ManagedQueue.MSG_QUEUE_POS));
- assertEquals("Unexpected redelivered flag", Boolean.FALSE, row1.get(ManagedQueue.MSG_REDELIVERED));
-
- // Check the contents of header (encoded in a string array)
- final String[] headerArray = (String[]) row1.get(ManagedQueue.MSG_HEADER);
- assertNotNull("Expected message header array", headerArray);
- final Map<String, String> headers = headerArrayToMap(headerArray);
-
- final String expectedJMSMessageID = isBroker010() ? sentMessage.getJMSMessageID().replace("ID:", "") : sentMessage.getJMSMessageID();
- final String expectedFormattedJMSTimestamp = FastDateFormat.getInstance(AMQQueueMBean.JMSTIMESTAMP_DATETIME_FORMAT).format(sentMessage.getJMSTimestamp());
- assertEquals("Unexpected JMSMessageID within header", expectedJMSMessageID, headers.get("JMSMessageID"));
- assertEquals("Unexpected JMSPriority within header", String.valueOf(sentMessage.getJMSPriority()), headers.get("JMSPriority"));
- assertEquals("Unexpected JMSTimestamp within header", expectedFormattedJMSTimestamp, headers.get("JMSTimestamp"));
- }
-
- /**
- * Tests {@link ManagedQueue#moveMessages(long, long, String)} interface.
- */
- public void testMoveMessagesBetweenQueues() throws Exception
- {
- final int numberOfMessagesToSend = 10;
-
- sendMessage(_session, _sourceQueue, numberOfMessagesToSend);
- syncSession(_session);
- assertEquals("Unexpected queue depth after send", numberOfMessagesToSend, _managedSourceQueue.getMessageCount().intValue());
-
- List<Long> amqMessagesIds = getAMQMessageIdsOn(_managedSourceQueue, 1, numberOfMessagesToSend);
-
- // Move first three messages to destination
- long fromMessageId = amqMessagesIds.get(0);
- long toMessageId = amqMessagesIds.get(2);
- _managedSourceQueue.moveMessages(fromMessageId, toMessageId, _destinationQueueName);
-
- assertEquals("Unexpected queue depth on destination queue after first move", 3, _managedDestinationQueue.getMessageCount().intValue());
- assertEquals("Unexpected queue depth on source queue after first move", 7, _managedSourceQueue.getMessageCount().intValue());
-
- // Now move a further two messages to destination
- fromMessageId = amqMessagesIds.get(7);
- toMessageId = amqMessagesIds.get(8);
- _managedSourceQueue.moveMessages(fromMessageId, toMessageId, _destinationQueueName);
- assertEquals("Unexpected queue depth on destination queue after second move", 5, _managedDestinationQueue.getMessageCount().intValue());
- assertEquals("Unexpected queue depth on source queue after second move", 5, _managedSourceQueue.getMessageCount().intValue());
-
- assertMessageIndicesOn(_destinationQueue, 0, 1, 2, 7, 8);
- }
-
- /**
- * Tests {@link ManagedQueue#copyMessages(long, long, String)} interface.
- */
- public void testCopyMessagesBetweenQueues() throws Exception
- {
- final int numberOfMessagesToSend = 10;
- sendMessage(_session, _sourceQueue, numberOfMessagesToSend);
- syncSession(_session);
- assertEquals("Unexpected queue depth after send", numberOfMessagesToSend, _managedSourceQueue.getMessageCount().intValue());
-
- List<Long> amqMessagesIds = getAMQMessageIdsOn(_managedSourceQueue, 1, numberOfMessagesToSend);
-
- // Copy first three messages to destination
- long fromMessageId = amqMessagesIds.get(0);
- long toMessageId = amqMessagesIds.get(2);
- _managedSourceQueue.copyMessages(fromMessageId, toMessageId, _destinationQueueName);
-
- assertEquals("Unexpected queue depth on destination queue after first copy", 3, _managedDestinationQueue.getMessageCount().intValue());
- assertEquals("Unexpected queue depth on source queue after first copy", numberOfMessagesToSend, _managedSourceQueue.getMessageCount().intValue());
-
- // Now copy a further two messages to destination
- fromMessageId = amqMessagesIds.get(7);
- toMessageId = amqMessagesIds.get(8);
- _managedSourceQueue.copyMessages(fromMessageId, toMessageId, _destinationQueueName);
- assertEquals("Unexpected queue depth on destination queue after second copy", 5, _managedDestinationQueue.getMessageCount().intValue());
- assertEquals("Unexpected queue depth on source queue after second copy", numberOfMessagesToSend, _managedSourceQueue.getMessageCount().intValue());
-
- assertMessageIndicesOn(_destinationQueue, 0, 1, 2, 7, 8);
- }
-
- public void testMoveMessagesBetweenQueuesWithActiveConsumerOnSourceQueue() throws Exception
- {
- setTestClientSystemProperty(ClientProperties.MAX_PREFETCH_PROP_NAME, new Integer(1).toString());
- Connection asyncConnection = getConnection();
- asyncConnection.start();
-
- final int numberOfMessagesToSend = 50;
- sendMessage(_session, _sourceQueue, numberOfMessagesToSend);
- syncSession(_session);
- assertEquals("Unexpected queue depth after send", numberOfMessagesToSend, _managedSourceQueue.getMessageCount().intValue());
-
- List<Long> amqMessagesIds = getAMQMessageIdsOn(_managedSourceQueue, 1, numberOfMessagesToSend);
-
- long fromMessageId = amqMessagesIds.get(0);
- long toMessageId = amqMessagesIds.get(numberOfMessagesToSend - 1);
-
- CountDownLatch consumerReadToHalfwayLatch = new CountDownLatch(numberOfMessagesToSend / 2);
- AtomicInteger totalConsumed = new AtomicInteger(0);
- startAsyncConsumerOn(_sourceQueue, asyncConnection, consumerReadToHalfwayLatch, totalConsumed);
-
- boolean halfwayPointReached = consumerReadToHalfwayLatch.await(5000, TimeUnit.MILLISECONDS);
- assertTrue("Did not read half of messages within time allowed", halfwayPointReached);
-
- _managedSourceQueue.moveMessages(fromMessageId, toMessageId, _destinationQueueName);
-
- asyncConnection.stop();
-
- // The exact number of messages moved will be non deterministic, as the number of messages processed
- // by the consumer cannot be predicited. There is also the possibility that a message can remain
- // on the source queue. This situation will arise if a message has been acquired by the consumer, but not
- // yet delivered to the client application (i.e. MessageListener#onMessage()) when the Connection#stop() occurs.
- //
- // The number of messages moved + the number consumed + any messages remaining on source should
- // *always* be equal to the number we originally sent.
-
- int numberOfMessagesReadByConsumer = totalConsumed.intValue();
- int numberOfMessagesOnDestinationQueue = _managedDestinationQueue.getMessageCount().intValue();
- int numberOfMessagesRemainingOnSourceQueue = _managedSourceQueue.getMessageCount().intValue();
-
- LOGGER.debug("Async consumer read : " + numberOfMessagesReadByConsumer
- + " Number of messages moved to destination : " + numberOfMessagesOnDestinationQueue
- + " Number of messages remaining on source : " + numberOfMessagesRemainingOnSourceQueue);
- assertEquals("Unexpected number of messages after move", numberOfMessagesToSend, numberOfMessagesReadByConsumer + numberOfMessagesOnDestinationQueue + numberOfMessagesRemainingOnSourceQueue);
- }
-
- public void testMoveMessagesBetweenQueuesWithActiveConsumerOnDestinationQueue() throws Exception
- {
- setTestClientSystemProperty(ClientProperties.MAX_PREFETCH_PROP_NAME, new Integer(1).toString());
- Connection asyncConnection = getConnection();
- asyncConnection.start();
-
- final int numberOfMessagesToSend = 50;
- sendMessage(_session, _sourceQueue, numberOfMessagesToSend);
- syncSession(_session);
- assertEquals("Unexpected queue depth after send", numberOfMessagesToSend, _managedSourceQueue.getMessageCount().intValue());
-
- List<Long> amqMessagesIds = getAMQMessageIdsOn(_managedSourceQueue, 1, numberOfMessagesToSend);
- long fromMessageId = amqMessagesIds.get(0);
- long toMessageId = amqMessagesIds.get(numberOfMessagesToSend - 1);
-
- AtomicInteger totalConsumed = new AtomicInteger(0);
- CountDownLatch allMessagesConsumedLatch = new CountDownLatch(numberOfMessagesToSend);
- startAsyncConsumerOn(_destinationQueue, asyncConnection, allMessagesConsumedLatch, totalConsumed);
-
- _managedSourceQueue.moveMessages(fromMessageId, toMessageId, _destinationQueueName);
-
- allMessagesConsumedLatch.await(5000, TimeUnit.MILLISECONDS);
- assertEquals("Did not consume all messages from destination queue", numberOfMessagesToSend, totalConsumed.intValue());
- }
-
- private void startAsyncConsumerOn(Destination queue, Connection asyncConnection,
- final CountDownLatch requiredNumberOfMessagesRead, final AtomicInteger totalConsumed) throws Exception
- {
- Session session = asyncConnection.createSession(false, Session.AUTO_ACKNOWLEDGE);
- MessageConsumer consumer = session.createConsumer(queue);
- consumer.setMessageListener(new MessageListener()
- {
-
- @Override
- public void onMessage(Message arg0)
- {
- totalConsumed.incrementAndGet();
- requiredNumberOfMessagesRead.countDown();
- }
- });
- }
-
- private void assertMessageIndicesOn(Destination queue, int... expectedIndices) throws Exception
- {
- MessageConsumer consumer = _session.createConsumer(queue);
-
- for (int i : expectedIndices)
- {
- Message message = consumer.receive(1000);
- assertNotNull("Expected message with index " + i, message);
- assertEquals("Expected message with index " + i, i, message.getIntProperty(INDEX));
- }
-
- assertNull("Unexpected message encountered", consumer.receive(1000));
- }
-
- private List<Long> getAMQMessageIdsOn(ManagedQueue managedQueue, long startIndex, long endIndex) throws Exception
- {
- final SortedSet<Long> messageIds = new TreeSet<Long>();
-
- final TabularData tab = managedQueue.viewMessages(startIndex, endIndex);
- final Iterator<CompositeData> rowItr = (Iterator<CompositeData>) tab.values().iterator();
- while(rowItr.hasNext())
- {
- final CompositeData row = rowItr.next();
- long amqMessageId = (Long)row.get(ManagedQueue.MSG_AMQ_ID);
- messageIds.add(amqMessageId);
- }
-
- return new ArrayList<Long>(messageIds);
- }
-
- /**
- *
- * Utility method to convert array of Strings in the form x = y into a
- * map with key/value x =&gt; y.
- *
- */
- private Map<String,String> headerArrayToMap(final String[] headerArray)
- {
- final Map<String, String> headerMap = new HashMap<String, String>();
- final List<String> headerList = Arrays.asList(headerArray);
- for (Iterator<String> iterator = headerList.iterator(); iterator.hasNext();)
- {
- final String nameValuePair = iterator.next();
- final String[] nameValue = nameValuePair.split(" *= *", 2);
- headerMap.put(nameValue[0], nameValue[1]);
- }
- return headerMap;
- }
-
- private void createQueueOnBroker(Destination destination) throws JMSException
- {
- _session.createConsumer(destination).close(); // Create a consumer only to cause queue creation
- }
-
- private void syncSession(Session session) throws Exception
- {
- ((AMQSession<?,?>)session).sync();
- }
-
-}
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 9465749226..0000000000
--- a/java/systests/src/main/java/org/apache/qpid/management/jmx/MessageConnectionStatisticsTest.java
+++ /dev/null
@@ -1,101 +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.client.AMQConnection;
-import org.apache.qpid.management.common.mbeans.ManagedBroker;
-import org.apache.qpid.management.common.mbeans.ManagedConnection;
-
-import javax.jms.Connection;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * 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 bdfd1e2c14..0000000000
--- a/java/systests/src/main/java/org/apache/qpid/management/jmx/MessageStatisticsDeliveryTest.java
+++ /dev/null
@@ -1,109 +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.client.AMQConnection;
-import org.apache.qpid.management.common.mbeans.ManagedBroker;
-import org.apache.qpid.management.common.mbeans.ManagedConnection;
-
-import javax.jms.Connection;
-import javax.jms.Message;
-import javax.jms.MessageConsumer;
-import javax.jms.Session;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * 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/MessageStatisticsTest.java b/java/systests/src/main/java/org/apache/qpid/management/jmx/MessageStatisticsTest.java
deleted file mode 100644
index de4567624d..0000000000
--- a/java/systests/src/main/java/org/apache/qpid/management/jmx/MessageStatisticsTest.java
+++ /dev/null
@@ -1,196 +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.client.AMQConnection;
-import org.apache.qpid.management.common.mbeans.ManagedBroker;
-import org.apache.qpid.management.common.mbeans.ManagedConnection;
-
-import javax.jms.Connection;
-
-/**
- * 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 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 45200ba476..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 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;
-
-import javax.jms.Connection;
-import javax.jms.Destination;
-import javax.jms.JMSException;
-import javax.jms.MessageProducer;
-import javax.jms.Session;
-import javax.jms.TextMessage;
-
-/**
- * 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/ra/QpidRAXAResourceTest.java b/java/systests/src/main/java/org/apache/qpid/ra/QpidRAXAResourceTest.java
new file mode 100644
index 0000000000..c8116d8cef
--- /dev/null
+++ b/java/systests/src/main/java/org/apache/qpid/ra/QpidRAXAResourceTest.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.ra;
+
+import org.apache.qpid.test.utils.QpidBrokerTestCase;
+
+import javax.jms.Connection;
+import javax.jms.ConnectionFactory;
+import javax.jms.Message;
+import javax.jms.Session;
+
+import javax.jms.XAConnection;
+import javax.jms.XAConnectionFactory;
+import javax.jms.XASession;
+import javax.transaction.xa.XAException;
+import javax.transaction.xa.XAResource;
+
+import org.apache.qpid.client.AMQXAResource;
+
+import org.apache.qpid.ra.QpidRAConnectionFactoryImpl;
+import org.apache.qpid.ra.QpidRAManagedConnectionFactory;
+import org.apache.qpid.ra.QpidResourceAdapter;
+
+public class QpidRAXAResourceTest extends QpidBrokerTestCase
+{
+ private static final String FACTORY_NAME = "default";
+ private static final String BROKER_PORT = "15672";
+ private static final String URL = "amqp://guest:guest@client/test?brokerlist='tcp://localhost:" + BROKER_PORT + "?sasl_mechs='PLAIN''";
+
+ public void testXAResourceIsSameRM() throws Exception
+ {
+ QpidResourceAdapter ra = new QpidResourceAdapter();
+ QpidRAManagedConnectionFactory mcf = new QpidRAManagedConnectionFactory();
+ mcf.setConnectionURL(URL);
+ mcf.setResourceAdapter(ra);
+ QpidRAManagedConnection mc = (QpidRAManagedConnection)mcf.createManagedConnection(null, null);
+ AMQXAResource xa1 = (AMQXAResource)mc.getXAResource();
+
+ XAConnectionFactory factory = getConnectionFactory(FACTORY_NAME);
+ XAConnection connection = factory.createXAConnection("guest", "guest");
+ XASession s2 = connection.createXASession();
+ AMQXAResource xaResource = (AMQXAResource)connection.createXASession().getXAResource();
+
+ assertTrue("QpidRAXAResource and XAResource should be from the same RM", xa1.isSameRM(xaResource));
+ assertTrue("XAResource and QpidRAXAResource should be from the same RM", xaResource.isSameRM(xa1));
+
+ }
+
+}
diff --git a/java/systests/src/main/java/org/apache/qpid/server/SupportedProtocolVersionsTest.java b/java/systests/src/main/java/org/apache/qpid/server/SupportedProtocolVersionsTest.java
index 0e3a658e32..e8d72c13bd 100644
--- a/java/systests/src/main/java/org/apache/qpid/server/SupportedProtocolVersionsTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/server/SupportedProtocolVersionsTest.java
@@ -38,6 +38,13 @@ public class SupportedProtocolVersionsTest extends QpidBrokerTestCase
// No-op, we call super.setUp() from test methods after appropriate config overrides
}
+ private void clearProtocolSupportManipulations()
+ {
+ //Remove the QBTC provided protocol manipulations, giving only the protocols which default to enabled
+ setTestSystemProperty(QpidBrokerTestCase.BROKER_PROTOCOL_EXCLUDES, null);
+ setTestSystemProperty(QpidBrokerTestCase.BROKER_PROTOCOL_INCLUDES, null);
+ }
+
/**
* Test that 0-10, 0-9-1, 0-9, and 0-8 support is present when no
* attempt has yet been made to disable them, and forcing the client
@@ -46,7 +53,8 @@ public class SupportedProtocolVersionsTest extends QpidBrokerTestCase
*/
public void testDefaultProtocolSupport() throws Exception
{
- //Start the broker without modifying its supported protocols
+ clearProtocolSupportManipulations();
+
super.setUp();
//Verify requesting a 0-10 connection works
@@ -74,11 +82,13 @@ public class SupportedProtocolVersionsTest extends QpidBrokerTestCase
connection.close();
}
- public void testDisabling010() throws Exception
+ public void testDisabling010and10() throws Exception
{
- //disable 0-10 support
- setConfigurationProperty("connector.amqp10enabled", "false");
- setConfigurationProperty("connector.amqp010enabled", "false");
+ clearProtocolSupportManipulations();
+
+ //disable 0-10 and 1-0 support
+ setConfigurationProperty(ServerConfiguration.CONNECTOR_AMQP010ENABLED, "false");
+ setConfigurationProperty(ServerConfiguration.CONNECTOR_AMQP10ENABLED, "false");
super.setUp();
@@ -90,9 +100,11 @@ public class SupportedProtocolVersionsTest extends QpidBrokerTestCase
connection.close();
}
- public void testDisabling091and010() throws Exception
+ public void testDisabling091and010and10() throws Exception
{
- //disable 0-91 and 0-10 support
+ clearProtocolSupportManipulations();
+
+ //disable 0-91 and 0-10 and 1-0 support
setConfigurationProperty(ServerConfiguration.CONNECTOR_AMQP10ENABLED, "false");
setConfigurationProperty(ServerConfiguration.CONNECTOR_AMQP010ENABLED, "false");
setConfigurationProperty(ServerConfiguration.CONNECTOR_AMQP091ENABLED, "false");
@@ -107,9 +119,11 @@ public class SupportedProtocolVersionsTest extends QpidBrokerTestCase
connection.close();
}
- public void testDisabling09and091and010() throws Exception
+ public void testDisabling09and091and010and10() throws Exception
{
- //disable 0-9, 0-91 and 0-10 support
+ clearProtocolSupportManipulations();
+
+ //disable 0-9, 0-91, 0-10 and 1-0 support
setConfigurationProperty(ServerConfiguration.CONNECTOR_AMQP09ENABLED, "false");
setConfigurationProperty(ServerConfiguration.CONNECTOR_AMQP091ENABLED, "false");
setConfigurationProperty(ServerConfiguration.CONNECTOR_AMQP010ENABLED, "false");
@@ -127,6 +141,8 @@ public class SupportedProtocolVersionsTest extends QpidBrokerTestCase
public void testConfiguringReplyingToUnsupported010ProtocolInitiationWith09insteadOf091() throws Exception
{
+ clearProtocolSupportManipulations();
+
//disable 0-10 support, and set the default unsupported protocol initiation reply to 0-9
setConfigurationProperty(ServerConfiguration.CONNECTOR_AMQP010ENABLED, "false");
setConfigurationProperty(ServerConfiguration.CONNECTOR_AMQP_SUPPORTED_REPLY, "v0_9");
@@ -147,4 +163,72 @@ public class SupportedProtocolVersionsTest extends QpidBrokerTestCase
assertEquals("Unexpected protocol version in use", ProtocolVersion.v0_91, connection.getProtocolVersion());
connection.close();
}
+
+ public void testProtocolInclusionThroughQBTCSystemPropertiesOverridesProtocolExclusion() throws Exception
+ {
+ testProtocolInclusionOverridesProtocolExclusion(false);
+ }
+
+ public void testProtocolInclusionThroughConfigOverridesProtocolExclusion() throws Exception
+ {
+ testProtocolInclusionOverridesProtocolExclusion(true);
+ }
+
+ private void testProtocolInclusionOverridesProtocolExclusion(boolean useConfig) throws Exception
+ {
+ clearProtocolSupportManipulations();
+
+ //selectively exclude 0-10 and 1-0 on the test port
+ setTestSystemProperty(QpidBrokerTestCase.BROKER_PROTOCOL_EXCLUDES,"--exclude-0-10 @PORT --exclude-1-0 @PORT");
+
+ super.setUp();
+
+ //Verify initially requesting a 0-10 connection negotiates a 0-9-1 connection
+ setTestClientSystemProperty(ClientProperties.AMQP_VERSION, "0-10");
+ AMQConnection connection = (AMQConnection) getConnection();
+ assertEquals("Unexpected protocol version in use", ProtocolVersion.v0_91, connection.getProtocolVersion());
+ connection.close();
+
+ stopBroker();
+
+ if(useConfig)
+ {
+ //selectively include 0-10 support again on the test port through config
+ setConfigurationProperty(ServerConfiguration.CONNECTOR_INCLUDE_010, String.valueOf(getPort()));
+ }
+ else
+ {
+ //selectively include 0-10 support again on the test port through QBTC sys props
+ setTestSystemProperty(QpidBrokerTestCase.BROKER_PROTOCOL_INCLUDES,"--include-0-10 @PORT");
+ }
+
+ startBroker();
+
+ //Verify requesting a 0-10 connection now returns one
+ setTestClientSystemProperty(ClientProperties.AMQP_VERSION, "0-10");
+ connection = (AMQConnection) getConnection();
+ assertEquals("Unexpected protocol version in use", ProtocolVersion.v0_10, connection.getProtocolVersion());
+ connection.close();
+ }
+
+ public void testProtocolInclusionOverridesProtocolDisabling() throws Exception
+ {
+ clearProtocolSupportManipulations();
+
+ //disable 0-10 and 1-0
+ setConfigurationProperty(ServerConfiguration.CONNECTOR_AMQP010ENABLED, "false");
+ setConfigurationProperty(ServerConfiguration.CONNECTOR_AMQP10ENABLED, "false");
+
+ //selectively include 0-10 support again on the test port
+ setConfigurationProperty(ServerConfiguration.CONNECTOR_INCLUDE_010, String.valueOf(getPort()));
+
+ super.setUp();
+
+ //Verify initially requesting a 0-10 connection still works
+ setTestClientSystemProperty(ClientProperties.AMQP_VERSION, "0-10");
+ AMQConnection connection = (AMQConnection) getConnection();
+ assertEquals("Unexpected protocol version in use", ProtocolVersion.v0_10, connection.getProtocolVersion());
+ connection.close();
+ }
+
} \ No newline at end of file
diff --git a/java/systests/src/main/java/org/apache/qpid/server/queue/ConflationQueueTest.java b/java/systests/src/main/java/org/apache/qpid/server/queue/ConflationQueueTest.java
index ae7be6f7f4..0e59e9cceb 100644
--- a/java/systests/src/main/java/org/apache/qpid/server/queue/ConflationQueueTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/server/queue/ConflationQueueTest.java
@@ -22,7 +22,8 @@
package org.apache.qpid.server.queue;
import org.apache.log4j.Logger;
-
+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;
@@ -37,82 +38,65 @@ import javax.jms.MessageConsumer;
import javax.jms.MessageProducer;
import javax.jms.Queue;
import javax.jms.Session;
+
import java.util.ArrayList;
+import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
public class ConflationQueueTest extends QpidBrokerTestCase
{
- private static final int TIMEOUT = 1500;
-
-
- private static final Logger _logger = Logger.getLogger(ConflationQueueTest.class);
+ private static final Logger LOGGER = Logger.getLogger(ConflationQueueTest.class);
-
-
- protected final String VHOST = "/test";
- protected final String QUEUE = "ConflationQueue";
+ private static final String MESSAGE_SEQUENCE_NUMBER_PROPERTY = "msg";
+ private static final String KEY_PROPERTY = "key";
private static final int MSG_COUNT = 400;
- private Connection producerConnection;
- private MessageProducer producer;
- private Session producerSession;
- private Queue queue;
- private Connection consumerConnection;
- private Session consumerSession;
-
-
- private MessageConsumer consumer;
+ private String _queueName;
+ private Queue _queue;
+ private Connection _producerConnection;
+ private MessageProducer _producer;
+ private Session _producerSession;
+ private Connection _consumerConnection;
+ private Session _consumerSession;
+ private MessageConsumer _consumer;
protected void setUp() throws Exception
{
super.setUp();
- producerConnection = getConnection();
- producerSession = producerConnection.createSession(false, Session.AUTO_ACKNOWLEDGE);
-
- producerConnection.start();
-
-
- }
-
- protected void tearDown() throws Exception
- {
- producerConnection.close();
- consumerConnection.close();
- super.tearDown();
+ _queueName = getTestQueueName();
+ _producerConnection = getConnection();
+ _producerSession = _producerConnection.createSession(false, Session.AUTO_ACKNOWLEDGE);
}
public void testConflation() throws Exception
{
- consumerConnection = getConnection();
- consumerSession = consumerConnection.createSession(false, Session.AUTO_ACKNOWLEDGE);
-
+ _consumerConnection = getConnection();
+ _consumerSession = _consumerConnection.createSession(false, Session.AUTO_ACKNOWLEDGE);
- final Map<String,Object> arguments = new HashMap<String, Object>();
- arguments.put("qpid.last_value_queue_key","key");
- ((AMQSession) producerSession).createQueue(new AMQShortString(QUEUE), false, true, false, arguments);
- queue = new org.apache.qpid.client.AMQQueue("amq.direct",QUEUE);
- ((AMQSession) producerSession).declareAndBind((AMQDestination)queue);
- producer = producerSession.createProducer(queue);
+ createConflationQueue(_producerSession);
+ _producer = _producerSession.createProducer(_queue);
for (int msg = 0; msg < MSG_COUNT; msg++)
{
- producer.send(nextMessage(msg, producerSession));
+ _producer.send(nextMessage(msg, _producerSession));
}
- producer.close();
- producerSession.close();
- producerConnection.close();
+ _producer.close();
+ _producerSession.close();
+ _producerConnection.close();
- consumer = consumerSession.createConsumer(queue);
- consumerConnection.start();
+ _consumer = _consumerSession.createConsumer(_queue);
+ _consumerConnection.start();
Message received;
List<Message> messages = new ArrayList<Message>();
- while((received = consumer.receive(1000))!=null)
+ while((received = _consumer.receive(1000))!=null)
{
messages.add(received);
}
@@ -122,40 +106,33 @@ public class ConflationQueueTest extends QpidBrokerTestCase
for(int i = 0 ; i < 10; i++)
{
Message msg = messages.get(i);
- assertEquals("Unexpected message number received", MSG_COUNT - 10 + i, msg.getIntProperty("msg"));
+ assertEquals("Unexpected message number received", MSG_COUNT - 10 + i, msg.getIntProperty(MESSAGE_SEQUENCE_NUMBER_PROPERTY));
}
-
-
}
-
public void testConflationWithRelease() throws Exception
{
- consumerConnection = getConnection();
- consumerSession = consumerConnection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
+ _consumerConnection = getConnection();
+ _consumerSession = _consumerConnection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
- final Map<String,Object> arguments = new HashMap<String, Object>();
- arguments.put("qpid.last_value_queue_key","key");
- ((AMQSession) producerSession).createQueue(new AMQShortString(QUEUE), false, true, false, arguments);
- queue = new org.apache.qpid.client.AMQQueue("amq.direct",QUEUE);
- ((AMQSession) producerSession).declareAndBind((AMQDestination)queue);
- producer = producerSession.createProducer(queue);
+ createConflationQueue(_producerSession);
+ _producer = _producerSession.createProducer(_queue);
for (int msg = 0; msg < MSG_COUNT/2; msg++)
{
- producer.send(nextMessage(msg, producerSession));
+ _producer.send(nextMessage(msg, _producerSession));
}
// HACK to do something synchronous
- ((AMQSession)producerSession).sync();
+ ((AMQSession<?,?>)_producerSession).sync();
- consumer = consumerSession.createConsumer(queue);
- consumerConnection.start();
+ _consumer = _consumerSession.createConsumer(_queue);
+ _consumerConnection.start();
Message received;
List<Message> messages = new ArrayList<Message>();
- while((received = consumer.receive(1000))!=null)
+ while((received = _consumer.receive(1000))!=null)
{
messages.add(received);
}
@@ -165,31 +142,31 @@ public class ConflationQueueTest extends QpidBrokerTestCase
for(int i = 0 ; i < 10; i++)
{
Message msg = messages.get(i);
- assertEquals("Unexpected message number received", MSG_COUNT/2 - 10 + i, msg.getIntProperty("msg"));
+ assertEquals("Unexpected message number received", MSG_COUNT/2 - 10 + i, msg.getIntProperty(MESSAGE_SEQUENCE_NUMBER_PROPERTY));
}
- consumerSession.close();
- consumerConnection.close();
+ _consumerSession.close();
+ _consumerConnection.close();
- consumerConnection = getConnection();
- consumerSession = consumerConnection.createSession(false, Session.AUTO_ACKNOWLEDGE);
+ _consumerConnection = getConnection();
+ _consumerSession = _consumerConnection.createSession(false, Session.AUTO_ACKNOWLEDGE);
for (int msg = MSG_COUNT/2; msg < MSG_COUNT; msg++)
{
- producer.send(nextMessage(msg, producerSession));
+ _producer.send(nextMessage(msg, _producerSession));
}
// HACK to do something synchronous
- ((AMQSession)producerSession).sync();
+ ((AMQSession<?,?>)_producerSession).sync();
- consumer = consumerSession.createConsumer(queue);
- consumerConnection.start();
+ _consumer = _consumerSession.createConsumer(_queue);
+ _consumerConnection.start();
messages = new ArrayList<Message>();
- while((received = consumer.receive(1000))!=null)
+ while((received = _consumer.receive(1000))!=null)
{
messages.add(received);
}
@@ -199,39 +176,34 @@ public class ConflationQueueTest extends QpidBrokerTestCase
for(int i = 0 ; i < 10; i++)
{
Message msg = messages.get(i);
- assertEquals("Unexpected message number received", MSG_COUNT - 10 + i, msg.getIntProperty("msg"));
+ assertEquals("Unexpected message number received", MSG_COUNT - 10 + i, msg.getIntProperty(MESSAGE_SEQUENCE_NUMBER_PROPERTY));
}
}
-
public void testConflationWithReleaseAfterNewPublish() throws Exception
{
- consumerConnection = getConnection();
- consumerSession = consumerConnection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
+ _consumerConnection = getConnection();
+ _consumerSession = _consumerConnection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
- final Map<String,Object> arguments = new HashMap<String, Object>();
- arguments.put("qpid.last_value_queue_key","key");
- ((AMQSession) producerSession).createQueue(new AMQShortString(QUEUE), false, true, false, arguments);
- queue = new org.apache.qpid.client.AMQQueue("amq.direct",QUEUE);
- ((AMQSession) producerSession).declareAndBind((AMQDestination)queue);
- producer = producerSession.createProducer(queue);
+ createConflationQueue(_producerSession);
+ _producer = _producerSession.createProducer(_queue);
for (int msg = 0; msg < MSG_COUNT/2; msg++)
{
- producer.send(nextMessage(msg, producerSession));
+ _producer.send(nextMessage(msg, _producerSession));
}
// HACK to do something synchronous
- ((AMQSession)producerSession).sync();
+ ((AMQSession<?,?>)_producerSession).sync();
- consumer = consumerSession.createConsumer(queue);
- consumerConnection.start();
+ _consumer = _consumerSession.createConsumer(_queue);
+ _consumerConnection.start();
Message received;
List<Message> messages = new ArrayList<Message>();
- while((received = consumer.receive(1000))!=null)
+ while((received = _consumer.receive(1000))!=null)
{
messages.add(received);
}
@@ -241,35 +213,35 @@ public class ConflationQueueTest extends QpidBrokerTestCase
for(int i = 0 ; i < 10; i++)
{
Message msg = messages.get(i);
- assertEquals("Unexpected message number received", MSG_COUNT/2 - 10 + i, msg.getIntProperty("msg"));
+ assertEquals("Unexpected message number received", MSG_COUNT/2 - 10 + i, msg.getIntProperty(MESSAGE_SEQUENCE_NUMBER_PROPERTY));
}
- consumer.close();
+ _consumer.close();
for (int msg = MSG_COUNT/2; msg < MSG_COUNT; msg++)
{
- producer.send(nextMessage(msg, producerSession));
+ _producer.send(nextMessage(msg, _producerSession));
}
// HACK to do something synchronous
- ((AMQSession)producerSession).sync();
+ ((AMQSession<?,?>)_producerSession).sync();
// this causes the "old" messages to be released
- consumerSession.close();
- consumerConnection.close();
+ _consumerSession.close();
+ _consumerConnection.close();
- consumerConnection = getConnection();
- consumerSession = consumerConnection.createSession(false, Session.AUTO_ACKNOWLEDGE);
+ _consumerConnection = getConnection();
+ _consumerSession = _consumerConnection.createSession(false, Session.AUTO_ACKNOWLEDGE);
- consumer = consumerSession.createConsumer(queue);
- consumerConnection.start();
+ _consumer = _consumerSession.createConsumer(_queue);
+ _consumerConnection.start();
messages = new ArrayList<Message>();
- while((received = consumer.receive(1000))!=null)
+ while((received = _consumer.receive(1000))!=null)
{
messages.add(received);
}
@@ -279,40 +251,54 @@ public class ConflationQueueTest extends QpidBrokerTestCase
for(int i = 0 ; i < 10; i++)
{
Message msg = messages.get(i);
- assertEquals("Unexpected message number received", MSG_COUNT - 10 + i, msg.getIntProperty("msg"));
+ assertEquals("Unexpected message number received", MSG_COUNT - 10 + i, msg.getIntProperty(MESSAGE_SEQUENCE_NUMBER_PROPERTY));
+ }
+
+ }
+
+ public void testConflatedQueueDepth() throws Exception
+ {
+ _consumerConnection = getConnection();
+ _consumerSession = _consumerConnection.createSession(false, Session.AUTO_ACKNOWLEDGE);
+
+ createConflationQueue(_producerSession);
+ _producer = _producerSession.createProducer(_queue);
+
+ for (int msg = 0; msg < MSG_COUNT; msg++)
+ {
+ _producer.send(nextMessage(msg, _producerSession));
}
+ final long queueDepth = ((AMQSession<?, ?>)_producerSession).getQueueDepth((AMQDestination)_queue, true);
+
+ assertEquals(10, queueDepth);
}
public void testConflationBrowser() throws Exception
{
- consumerConnection = getConnection();
- consumerSession = consumerConnection.createSession(false, Session.AUTO_ACKNOWLEDGE);
+ _consumerConnection = getConnection();
+ _consumerSession = _consumerConnection.createSession(false, Session.AUTO_ACKNOWLEDGE);
- final Map<String,Object> arguments = new HashMap<String, Object>();
- arguments.put("qpid.last_value_queue_key","key");
- ((AMQSession) producerSession).createQueue(new AMQShortString(QUEUE), false, true, false, arguments);
- queue = new org.apache.qpid.client.AMQQueue("amq.direct",QUEUE);
- ((AMQSession) producerSession).declareAndBind((AMQDestination)queue);
- producer = producerSession.createProducer(queue);
+ createConflationQueue(_producerSession);
+ _producer = _producerSession.createProducer(_queue);
for (int msg = 0; msg < MSG_COUNT; msg++)
{
- producer.send(nextMessage(msg, producerSession));
+ _producer.send(nextMessage(msg, _producerSession));
}
- ((AMQSession)producerSession).sync();
+ ((AMQSession<?,?>)_producerSession).sync();
- AMQBindingURL url = new AMQBindingURL("direct://amq.direct//"+QUEUE+"?browse='true'&durable='true'");
+ AMQBindingURL url = new AMQBindingURL("direct://amq.direct//"+_queueName+"?browse='true'&durable='true'");
AMQQueue browseQueue = new AMQQueue(url);
- consumer = consumerSession.createConsumer(browseQueue);
- consumerConnection.start();
+ _consumer = _consumerSession.createConsumer(browseQueue);
+ _consumerConnection.start();
Message received;
List<Message> messages = new ArrayList<Message>();
- while((received = consumer.receive(1000))!=null)
+ while((received = _consumer.receive(1000))!=null)
{
messages.add(received);
}
@@ -322,62 +308,53 @@ public class ConflationQueueTest extends QpidBrokerTestCase
for(int i = 0 ; i < 10; i++)
{
Message msg = messages.get(i);
- assertEquals("Unexpected message number received", MSG_COUNT - 10 + i, msg.getIntProperty("msg"));
+ assertEquals("Unexpected message number received", MSG_COUNT - 10 + i, msg.getIntProperty(MESSAGE_SEQUENCE_NUMBER_PROPERTY));
}
messages.clear();
- producer.send(nextMessage(MSG_COUNT, producerSession));
+ _producer.send(nextMessage(MSG_COUNT, _producerSession));
- ((AMQSession)producerSession).sync();
+ ((AMQSession<?,?>)_producerSession).sync();
- while((received = consumer.receive(1000))!=null)
+ while((received = _consumer.receive(1000))!=null)
{
messages.add(received);
}
assertEquals("Unexpected number of messages received",1,messages.size());
- assertEquals("Unexpected message number received", MSG_COUNT, messages.get(0).getIntProperty("msg"));
-
-
- producer.close();
- producerSession.close();
- producerConnection.close();
-
+ assertEquals("Unexpected message number received", MSG_COUNT, messages.get(0).getIntProperty(MESSAGE_SEQUENCE_NUMBER_PROPERTY));
+ _producer.close();
+ _producerSession.close();
+ _producerConnection.close();
}
-
public void testConflation2Browsers() throws Exception
{
- consumerConnection = getConnection();
- consumerSession = consumerConnection.createSession(false, Session.AUTO_ACKNOWLEDGE);
+ _consumerConnection = getConnection();
+ _consumerSession = _consumerConnection.createSession(false, Session.AUTO_ACKNOWLEDGE);
- final Map<String,Object> arguments = new HashMap<String, Object>();
- arguments.put("qpid.last_value_queue_key","key");
- ((AMQSession) producerSession).createQueue(new AMQShortString(QUEUE), false, true, false, arguments);
- queue = new org.apache.qpid.client.AMQQueue("amq.direct",QUEUE);
- ((AMQSession) producerSession).declareAndBind((AMQDestination)queue);
- producer = producerSession.createProducer(queue);
+ createConflationQueue(_producerSession);
+ _producer = _producerSession.createProducer(_queue);
for (int msg = 0; msg < MSG_COUNT; msg++)
{
- producer.send(nextMessage(msg, producerSession));
-
+ _producer.send(nextMessage(msg, _producerSession));
}
- ((AMQSession)producerSession).sync();
+ ((AMQSession<?,?>)_producerSession).sync();
- AMQBindingURL url = new AMQBindingURL("direct://amq.direct//"+QUEUE+"?browse='true'&durable='true'");
+ AMQBindingURL url = new AMQBindingURL("direct://amq.direct//"+_queueName+"?browse='true'&durable='true'");
AMQQueue browseQueue = new AMQQueue(url);
- consumer = consumerSession.createConsumer(browseQueue);
- MessageConsumer consumer2 = consumerSession.createConsumer(browseQueue);
- consumerConnection.start();
+ _consumer = _consumerSession.createConsumer(browseQueue);
+ MessageConsumer consumer2 = _consumerSession.createConsumer(browseQueue);
+ _consumerConnection.start();
List<Message> messages = new ArrayList<Message>();
List<Message> messages2 = new ArrayList<Message>();
- Message received = consumer.receive(1000);
+ Message received = _consumer.receive(1000);
Message received2 = consumer2.receive(1000);
while(received!=null || received2!=null)
@@ -392,7 +369,7 @@ public class ConflationQueueTest extends QpidBrokerTestCase
}
- received = consumer.receive(1000);
+ received = _consumer.receive(1000);
received2 = consumer2.receive(1000);
}
@@ -403,33 +380,195 @@ public class ConflationQueueTest extends QpidBrokerTestCase
for(int i = 0 ; i < 10; i++)
{
Message msg = messages.get(i);
- assertEquals("Unexpected message number received on first browser", MSG_COUNT - 10 + i, msg.getIntProperty("msg"));
+ assertEquals("Unexpected message number received on first browser", MSG_COUNT - 10 + i, msg.getIntProperty(MESSAGE_SEQUENCE_NUMBER_PROPERTY));
msg = messages2.get(i);
- assertEquals("Unexpected message number received on second browser", MSG_COUNT - 10 + i, msg.getIntProperty("msg"));
+ assertEquals("Unexpected message number received on second browser", MSG_COUNT - 10 + i, msg.getIntProperty(MESSAGE_SEQUENCE_NUMBER_PROPERTY));
}
- producer.close();
- producerSession.close();
- producerConnection.close();
+ _producer.close();
+ _producerSession.close();
+ _producerConnection.close();
+ }
+
+ public void testParallelProductionAndConsumption() throws Exception
+ {
+ createConflationQueue(_producerSession);
+
+ // Start producing threads that send messages
+ BackgroundMessageProducer messageProducer1 = new BackgroundMessageProducer("Message sender1");
+ messageProducer1.startSendingMessages();
+ BackgroundMessageProducer messageProducer2 = new BackgroundMessageProducer("Message sender2");
+ messageProducer2.startSendingMessages();
+
+ Map<String, Integer> lastReceivedMessages = receiveMessages(messageProducer1);
+ messageProducer1.join();
+ messageProducer2.join();
+ final Map<String, Integer> lastSentMessages1 = messageProducer1.getMessageSequenceNumbersByKey();
+ assertEquals("Unexpected number of last sent messages sent by producer1", 2, lastSentMessages1.size());
+ final Map<String, Integer> lastSentMessages2 = messageProducer2.getMessageSequenceNumbersByKey();
+ assertEquals(lastSentMessages1, lastSentMessages2);
+ assertEquals("The last message sent for each key should match the last message received for that key",
+ lastSentMessages1, lastReceivedMessages);
+
+ assertNull("Unexpected exception from background producer thread", messageProducer1.getException());
}
+ private Map<String, Integer> receiveMessages(BackgroundMessageProducer producer) throws Exception
+ {
+ producer.waitUntilQuarterOfMessagesSentToEncourageConflation();
+ _consumerConnection = getConnection();
+ int smallPrefetchToEncourageConflation = 1;
+ _consumerSession = ((AMQConnection)_consumerConnection).createSession(false, Session.AUTO_ACKNOWLEDGE, smallPrefetchToEncourageConflation);
- private Message nextMessage(int msg, Session producerSession) throws JMSException
+ LOGGER.info("Starting to receive");
+
+ _consumer = _consumerSession.createConsumer(_queue);
+ _consumerConnection.start();
+
+ Map<String, Integer> messageSequenceNumbersByKey = new HashMap<String, Integer>();
+
+ Message message;
+ int numberOfShutdownsReceived = 0;
+ int numberOfMessagesReceived = 0;
+ while(numberOfShutdownsReceived < 2)
+ {
+ message = _consumer.receive(10000);
+ assertNotNull(message);
+
+ if (message.propertyExists(BackgroundMessageProducer.SHUTDOWN))
+ {
+ numberOfShutdownsReceived++;
+ }
+ else
+ {
+ numberOfMessagesReceived++;
+ putMessageInMap(message, messageSequenceNumbersByKey);
+ }
+ }
+
+ LOGGER.info("Finished receiving. Received " + numberOfMessagesReceived + " message(s) in total");
+
+ return messageSequenceNumbersByKey;
+ }
+
+ private void putMessageInMap(Message message, Map<String, Integer> messageSequenceNumbersByKey) throws JMSException
{
- Message send = producerSession.createTextMessage("Message: " + msg);
+ String keyValue = message.getStringProperty(KEY_PROPERTY);
+ Integer messageSequenceNumber = message.getIntProperty(MESSAGE_SEQUENCE_NUMBER_PROPERTY);
+ messageSequenceNumbersByKey.put(keyValue, messageSequenceNumber);
+ }
- send.setStringProperty("key", String.valueOf(msg % 10));
- send.setIntProperty("msg", msg);
+ private class BackgroundMessageProducer
+ {
+ static final String SHUTDOWN = "SHUTDOWN";
- return send;
+ private final String _threadName;
+
+ private volatile Exception _exception;
+
+ private Thread _thread;
+ private Map<String, Integer> _messageSequenceNumbersByKey = new HashMap<String, Integer>();
+ private CountDownLatch _quarterOfMessagesSentLatch = new CountDownLatch(MSG_COUNT/4);
+
+ public BackgroundMessageProducer(String threadName)
+ {
+ _threadName = threadName;
+ }
+
+ public void waitUntilQuarterOfMessagesSentToEncourageConflation() throws InterruptedException
+ {
+ final long latchTimeout = 60000;
+ boolean success = _quarterOfMessagesSentLatch.await(latchTimeout, TimeUnit.MILLISECONDS);
+ assertTrue("Failed to be notified that 1/4 of the messages have been sent within " + latchTimeout + " ms.", success);
+ LOGGER.info("Quarter of messages sent");
+ }
+
+ public Exception getException()
+ {
+ return _exception;
+ }
+
+ public Map<String, Integer> getMessageSequenceNumbersByKey()
+ {
+ return Collections.unmodifiableMap(_messageSequenceNumbersByKey);
+ }
+
+ public void startSendingMessages()
+ {
+ Runnable messageSender = new Runnable()
+ {
+ @Override
+ public void run()
+ {
+ try
+ {
+ LOGGER.info("Starting to send in background thread");
+ Connection producerConnection = getConnection();
+ Session producerSession = producerConnection.createSession(false, Session.AUTO_ACKNOWLEDGE);
+
+ MessageProducer backgroundProducer = producerSession.createProducer(_queue);
+ for (int messageNumber = 0; messageNumber < MSG_COUNT; messageNumber++)
+ {
+ Message message = nextMessage(messageNumber, producerSession, 2);
+ backgroundProducer.send(message);
+
+ putMessageInMap(message, _messageSequenceNumbersByKey);
+ _quarterOfMessagesSentLatch.countDown();
+ }
+
+ Message shutdownMessage = producerSession.createMessage();
+ shutdownMessage.setBooleanProperty(SHUTDOWN, true);
+ backgroundProducer.send(shutdownMessage);
+
+ LOGGER.info("Finished sending in background thread");
+ }
+ catch (Exception e)
+ {
+ _exception = e;
+ throw new RuntimeException(e);
+ }
+ }
+ };
+
+ _thread = new Thread(messageSender);
+ _thread.setName(_threadName);
+ _thread.start();
+ }
+
+ public void join() throws InterruptedException
+ {
+ final int timeoutInMillis = 120000;
+ _thread.join(timeoutInMillis);
+ assertFalse("Expected producer thread to finish within " + timeoutInMillis + "ms", _thread.isAlive());
+ }
+ }
+
+ private void createConflationQueue(Session session) throws AMQException
+ {
+ final Map<String,Object> arguments = new HashMap<String, Object>();
+ arguments.put("qpid.last_value_queue_key",KEY_PROPERTY);
+ ((AMQSession<?,?>) session).createQueue(new AMQShortString(_queueName), false, true, false, arguments);
+ _queue = new AMQQueue("amq.direct", _queueName);
+ ((AMQSession<?,?>) session).declareAndBind((AMQDestination)_queue);
}
+ private Message nextMessage(int msg, Session producerSession) throws JMSException
+ {
+ return nextMessage(msg, producerSession, 10);
+ }
-}
+ private Message nextMessage(int msg, Session producerSession, int numberOfUniqueKeyValues) throws JMSException
+ {
+ Message send = producerSession.createTextMessage("Message: " + msg);
+ send.setStringProperty(KEY_PROPERTY, String.valueOf(msg % numberOfUniqueKeyValues));
+ send.setIntProperty(MESSAGE_SEQUENCE_NUMBER_PROPERTY, msg);
+ return send;
+ }
+}
diff --git a/java/systests/src/main/java/org/apache/qpid/server/queue/ModelTest.java b/java/systests/src/main/java/org/apache/qpid/server/queue/ModelTest.java
index ab0d88c737..782709b24f 100644
--- a/java/systests/src/main/java/org/apache/qpid/server/queue/ModelTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/server/queue/ModelTest.java
@@ -333,7 +333,7 @@ public class ModelTest extends QpidBrokerTestCase
queueName));
assertEquals(queueName, managedQueue.getName());
- assertEquals(String.valueOf(owner), managedQueue.getOwner());
+ assertEquals(owner, managedQueue.getOwner());
assertEquals(durable, managedQueue.isDurable());
assertEquals(autoDelete, managedQueue.isAutoDelete());
}
diff --git a/java/systests/src/main/java/org/apache/qpid/server/security/acl/ExternalACLJMXTest.java b/java/systests/src/main/java/org/apache/qpid/server/security/acl/ExternalACLJMXTest.java
index 6e4f12b9f3..ceff2b998a 100644
--- a/java/systests/src/main/java/org/apache/qpid/server/security/acl/ExternalACLJMXTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/server/security/acl/ExternalACLJMXTest.java
@@ -19,7 +19,6 @@
package org.apache.qpid.server.security.acl;
import org.apache.qpid.management.common.mbeans.ServerInformation;
-import org.apache.qpid.server.management.ManagedObject;
import org.apache.qpid.server.security.access.ObjectType;
import org.apache.qpid.test.utils.JMXTestUtils;
@@ -30,7 +29,7 @@ import java.lang.management.RuntimeMXBean;
* Tests that access to the JMX interface is governed only by {@link ObjectType#METHOD}/{@link ObjectType#ALL}
* rules and AMQP rights have no effect.
*
- * Ensures that objects outside the Qpid domain ({@link ManagedObject#DOMAIN}) are not governed by the ACL model.
+ * Ensures that objects outside the Qpid domain are not governed by the ACL model.
*/
public class ExternalACLJMXTest extends AbstractACLTestCase
{
diff --git a/java/systests/src/main/java/org/apache/qpid/server/security/auth/manager/MultipleAuthenticationManagersTest.java b/java/systests/src/main/java/org/apache/qpid/server/security/auth/manager/MultipleAuthenticationManagersTest.java
new file mode 100644
index 0000000000..858b32c24c
--- /dev/null
+++ b/java/systests/src/main/java/org/apache/qpid/server/security/auth/manager/MultipleAuthenticationManagersTest.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.server.security.auth.manager;
+
+import javax.jms.Connection;
+import javax.jms.JMSException;
+import org.apache.qpid.AMQException;
+import org.apache.qpid.client.AMQConnection;
+import org.apache.qpid.test.utils.QpidBrokerTestCase;
+
+public class MultipleAuthenticationManagersTest 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";
+
+ @Override
+ protected void setUp() throws Exception
+ {
+ setConfigurationProperty("connector.ssl.enabled", "true");
+ setConfigurationProperty("connector.ssl.sslOnly", "false");
+ setConfigurationProperty("security.anonymous-auth-manager", "");
+ setConfigurationProperty("security.default-auth-manager", "PrincipalDatabaseAuthenticationManager");
+ setConfigurationProperty("security.port-mappings.port-mapping.port", String.valueOf(QpidBrokerTestCase.DEFAULT_SSL_PORT));
+ setConfigurationProperty("security.port-mappings.port-mapping.auth-manager", "AnonymousAuthenticationManager");
+
+ // 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");
+ super.setUp();
+ }
+
+ private Connection getAnonymousSSLConnection() throws Exception
+ {
+ String url = "amqp://:@test/?brokerlist='tcp://localhost:%s?ssl='true''";
+
+ url = String.format(url,QpidBrokerTestCase.DEFAULT_SSL_PORT);
+
+ return new AMQConnection(url);
+
+ }
+
+ private Connection getAnonymousConnection() throws Exception
+ {
+ String url = "amqp://:@test/?brokerlist='tcp://localhost:%s'";
+
+ url = String.format(url,QpidBrokerTestCase.DEFAULT_PORT);
+
+ return new AMQConnection(url);
+
+ }
+
+
+ public void testMultipleAuthenticationManagers() throws Exception
+ {
+ try
+ {
+ Connection conn = getConnection();
+ assertNotNull("Connection unexpectedly null", conn);
+ }
+ catch(JMSException e)
+ {
+ fail("Should be able to create a connection with credentials to the standard port. " + e.getMessage());
+ }
+
+ try
+ {
+ Connection conn = getAnonymousSSLConnection();
+ assertNotNull("Connection unexpectedly null", conn);
+ }
+ catch(JMSException e)
+ {
+ fail("Should be able to create a anonymous connection to the SSL port. " + e.getMessage());
+ }
+
+ try
+ {
+ Connection conn = getAnonymousConnection();
+ fail("Should not be able to create anonymous connection to the standard port");
+ }
+ catch(AMQException e)
+ {
+ // pass
+ }
+
+ }
+}
diff --git a/java/systests/src/main/java/org/apache/qpid/management/jmx/MessageStatisticsReportingTest.java b/java/systests/src/main/java/org/apache/qpid/server/stats/StatisticsReportingTest.java
index 786ef11956..c38fcd9199 100644
--- a/java/systests/src/main/java/org/apache/qpid/management/jmx/MessageStatisticsReportingTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/server/stats/StatisticsReportingTest.java
@@ -18,30 +18,75 @@
* under the License.
*
*/
-package org.apache.qpid.management.jmx;
+package org.apache.qpid.server.stats;
+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.QpidBrokerTestCase;
import org.apache.qpid.util.LogMonitor;
import java.util.List;
+import javax.jms.Connection;
+import javax.jms.Destination;
+import javax.jms.JMSException;
+import javax.jms.MessageProducer;
+import javax.jms.Session;
+import javax.jms.TextMessage;
+
/**
- * Test generation of message statistics reporting.
+ * Test generation of message/data statistics reporting and the ability
+ * to control from the configuration file.
*/
-public class MessageStatisticsReportingTest extends MessageStatisticsTestCase
+public class StatisticsReportingTest extends QpidBrokerTestCase
{
protected LogMonitor _monitor;
-
- public void configureStatistics() throws Exception
+ protected static final String USER = "admin";
+
+ protected Connection _test, _dev, _local;
+ protected String _queueName = "statistics";
+ protected Destination _queue;
+ protected String _brokerUrl;
+
+ @Override
+ public void setUp() 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);
+
+ 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();
+
+ }
+
+ @Override
+ public void tearDown() throws Exception
+ {
+ _test.close();
+ _dev.close();
+ _local.close();
+
+ super.tearDown();
}
/**
@@ -52,14 +97,14 @@ public class MessageStatisticsReportingTest extends MessageStatisticsTestCase
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());
@@ -74,17 +119,40 @@ public class MessageStatisticsReportingTest extends MessageStatisticsTestCase
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());
}
+
+ private 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);
+ }
+ }
+
+ private 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));
+ }
+ }
}
diff --git a/java/systests/src/main/java/org/apache/qpid/server/store/QuotaMessageStore.java b/java/systests/src/main/java/org/apache/qpid/server/store/QuotaMessageStore.java
new file mode 100644
index 0000000000..07965cfa95
--- /dev/null
+++ b/java/systests/src/main/java/org/apache/qpid/server/store/QuotaMessageStore.java
@@ -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.
+ *
+ */
+package org.apache.qpid.server.store;
+
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicLong;
+
+import org.apache.commons.configuration.Configuration;
+import org.apache.qpid.AMQStoreException;
+import org.apache.qpid.server.message.EnqueableMessage;
+import org.apache.qpid.server.message.MessageContentSource;
+
+public class QuotaMessageStore extends NullMessageStore
+{
+ private final AtomicLong _messageId = new AtomicLong(1);
+ private final AtomicBoolean _closed = new AtomicBoolean(false);
+
+ private long _totalStoreSize;;
+ private boolean _limitBusted;
+ private long _persistentSizeLowThreshold;
+ private long _persistentSizeHighThreshold;
+
+ private final StateManager _stateManager;
+ private final EventManager _eventManager = new EventManager();
+
+ public QuotaMessageStore()
+ {
+ _stateManager = new StateManager(_eventManager);
+ }
+
+ @Override
+ public void configureConfigStore(String name, ConfigurationRecoveryHandler recoveryHandler, Configuration config)
+ throws Exception
+ {
+ _persistentSizeHighThreshold = config.getLong(MessageStoreConstants.OVERFULL_SIZE_PROPERTY, Long.MAX_VALUE);
+ _persistentSizeLowThreshold = config.getLong(MessageStoreConstants.UNDERFULL_SIZE_PROPERTY,
+ _persistentSizeHighThreshold);
+ if (_persistentSizeLowThreshold > _persistentSizeHighThreshold || _persistentSizeLowThreshold < 0l)
+ {
+ _persistentSizeLowThreshold = _persistentSizeHighThreshold;
+ }
+ _stateManager.attainState(State.INITIALISING);
+ }
+
+ @Override
+ public void configureMessageStore(String name, MessageStoreRecoveryHandler recoveryHandler,
+ TransactionLogRecoveryHandler tlogRecoveryHandler, Configuration config) throws Exception
+ {
+ _stateManager.attainState(State.INITIALISED);
+ }
+
+ @Override
+ public void activate() throws Exception
+ {
+ _stateManager.attainState(State.ACTIVATING);
+ _stateManager.attainState(State.ACTIVE);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public StoredMessage<StorableMessageMetaData> addMessage(StorableMessageMetaData metaData)
+ {
+ final long id = _messageId.getAndIncrement();
+ return new StoredMemoryMessage(id, metaData);
+ }
+
+ @Override
+ public Transaction newTransaction()
+ {
+ return new Transaction()
+ {
+ private AtomicLong _storeSizeIncrease = new AtomicLong();
+
+ @Override
+ public StoreFuture commitTranAsync() throws AMQStoreException
+ {
+ QuotaMessageStore.this.storedSizeChange(_storeSizeIncrease.intValue());
+ return StoreFuture.IMMEDIATE_FUTURE;
+ }
+
+ @Override
+ public void enqueueMessage(TransactionLogResource queue, EnqueableMessage message) throws AMQStoreException
+ {
+ _storeSizeIncrease.addAndGet(((MessageContentSource)message).getSize());
+ }
+
+ @Override
+ public void dequeueMessage(TransactionLogResource queue, EnqueableMessage message) throws AMQStoreException
+ {
+ _storeSizeIncrease.addAndGet(-((MessageContentSource)message).getSize());
+ }
+
+ @Override
+ public void commitTran() throws AMQStoreException
+ {
+ QuotaMessageStore.this.storedSizeChange(_storeSizeIncrease.intValue());
+ }
+
+ @Override
+ public void abortTran() throws AMQStoreException
+ {
+ }
+
+ @Override
+ public void removeXid(long format, byte[] globalId, byte[] branchId)
+ {
+ }
+
+ @Override
+ public void recordXid(long format, byte[] globalId, byte[] branchId, Record[] enqueues, Record[] dequeues)
+ {
+ }
+ };
+ }
+
+ @Override
+ public boolean isPersistent()
+ {
+ return true;
+ }
+
+ @Override
+ public void close() throws Exception
+ {
+ _stateManager.attainState(State.CLOSING);
+ _closed.getAndSet(true);
+ _stateManager.attainState(State.CLOSED);
+ }
+
+ @Override
+ public void addEventListener(EventListener eventListener, Event... events)
+ {
+ _eventManager.addEventListener(eventListener, events);
+ }
+
+ private void storedSizeChange(final int delta)
+ {
+ if(_persistentSizeHighThreshold > 0)
+ {
+ synchronized (this)
+ {
+ long newSize = _totalStoreSize += delta;
+ if(!_limitBusted && newSize > _persistentSizeHighThreshold)
+ {
+ _limitBusted = true;
+ _eventManager.notifyEvent(Event.PERSISTENT_MESSAGE_SIZE_OVERFULL);
+ }
+ else if(_limitBusted && newSize < _persistentSizeHighThreshold)
+ {
+ _limitBusted = false;
+ _eventManager.notifyEvent(Event.PERSISTENT_MESSAGE_SIZE_UNDERFULL);
+ }
+ }
+ }
+ }
+
+ @Override
+ public String getStoreType()
+ {
+ return "QUOTA";
+ }
+}
diff --git a/java/systests/src/main/java/org/apache/qpid/server/store/SlowMessageStore.java b/java/systests/src/main/java/org/apache/qpid/server/store/SlowMessageStore.java
index f2d4a513be..9db04b64b3 100644
--- a/java/systests/src/main/java/org/apache/qpid/server/store/SlowMessageStore.java
+++ b/java/systests/src/main/java/org/apache/qpid/server/store/SlowMessageStore.java
@@ -24,7 +24,6 @@ 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.binding.Binding;
import org.apache.qpid.server.exchange.Exchange;
@@ -370,4 +369,10 @@ public class SlowMessageStore implements MessageStore
return _realStore.getStoreLocation();
}
+ @Override
+ public String getStoreType()
+ {
+ return "SLOW";
+ }
+
}
diff --git a/java/systests/src/main/java/org/apache/qpid/server/store/StoreOverfullTest.java b/java/systests/src/main/java/org/apache/qpid/server/store/StoreOverfullTest.java
new file mode 100644
index 0000000000..9fb1db3a4f
--- /dev/null
+++ b/java/systests/src/main/java/org/apache/qpid/server/store/StoreOverfullTest.java
@@ -0,0 +1,343 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import javax.jms.BytesMessage;
+import javax.jms.Connection;
+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 org.apache.qpid.AMQException;
+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.test.utils.QpidBrokerTestCase;
+
+public class StoreOverfullTest extends QpidBrokerTestCase
+{
+ /** Number of messages to send*/
+ public static final int TEST_SIZE = 15;
+
+ /** Message payload*/
+ private static final byte[] BYTE_32K = new byte[32*1024];
+
+ private Connection _producerConnection;
+ private Connection _consumerConnection;
+ private Session _producerSession;
+ private Session _consumerSession;
+ private MessageProducer _producer;
+ private MessageConsumer _consumer;
+ private Queue _queue;
+
+ private static final int OVERFULL_SIZE = 400000;
+ private static final int UNDERFULL_SIZE = 350000;
+
+ public void setUp() throws Exception
+ {
+ setConfigurationProperty("virtualhosts.virtualhost.test.store.class", QuotaMessageStore.class.getName());
+ setConfigurationProperty("virtualhosts.virtualhost.test.store.overfull-size", String.valueOf(OVERFULL_SIZE));
+ setConfigurationProperty("virtualhosts.virtualhost.test.store.underfull-size", String.valueOf(UNDERFULL_SIZE));
+
+ super.setUp();
+
+ _producerConnection = getConnection();
+ _producerSession = _producerConnection.createSession(false, Session.AUTO_ACKNOWLEDGE);
+
+ _producerConnection.start();
+
+ _consumerConnection = getConnection();
+ _consumerSession = _consumerConnection.createSession(false, Session.AUTO_ACKNOWLEDGE);
+
+ }
+
+ public void tearDown() throws Exception
+ {
+ try
+ {
+ _producerConnection.close();
+ _consumerConnection.close();
+ }
+ finally
+ {
+ super.tearDown();
+ }
+ }
+
+ /**
+ * Test:
+ *
+ * Send > threshold amount of data : Sender is blocked
+ * Remove 90% of data : Sender is unblocked
+ *
+ */
+ public void testCapacityExceededCausesBlock() throws Exception
+ {
+ AtomicInteger sentMessages = new AtomicInteger(0);
+ _queue = getTestQueue();
+ ((AMQSession<?,?>) _producerSession).declareAndBind((AMQDestination)_queue);
+
+ _producer = _producerSession.createProducer(_queue);
+
+ MessageSender sender = sendMessagesAsync(_producer, _producerSession, TEST_SIZE, 50L, sentMessages);
+
+ while(!((AMQSession<?,?>)_producerSession).isFlowBlocked())
+ {
+ Thread.sleep(100l);
+ }
+ int sentCount = sentMessages.get();
+ assertFalse("Did not block before sending all messages", TEST_SIZE == sentCount);
+
+ _consumer = _consumerSession.createConsumer(_queue);
+ _consumerConnection.start();
+
+ int mostMessages = (int) (0.9 * sentCount);
+ for(int i = 0; i < mostMessages; i++)
+ {
+ if(_consumer.receive(1000l) == null)
+ {
+ break;
+ }
+ }
+
+ long targetTime = System.currentTimeMillis() + 5000l;
+ while(sentMessages.get() == sentCount && System.currentTimeMillis() < targetTime)
+ {
+ Thread.sleep(100l);
+ }
+
+ assertFalse("Did not unblock on consuming messages", sentMessages.get() == sentCount);
+
+ for(int i = mostMessages; i < TEST_SIZE; i++)
+ {
+ if(_consumer.receive(1000l) == null)
+ {
+ break;
+ }
+ }
+
+ assertTrue("Not all messages were sent", sentMessages.get() == TEST_SIZE);
+ assertNull("Unexpected exception on message sending:" + sender.getException(), sender.getException());
+ }
+
+ /**
+ * Two producers on different queues
+ */
+ public void testCapacityExceededCausesBlockTwoConnections() throws Exception
+ {
+ AtomicInteger sentMessages = new AtomicInteger(0);
+ AtomicInteger sentMessages2 = new AtomicInteger(0);
+
+ _queue = getTestQueue();
+ AMQQueue queue2 = new AMQQueue(ExchangeDefaults.DIRECT_EXCHANGE_NAME, getTestQueueName() + "_2");
+
+ ((AMQSession<?,?>) _producerSession).declareAndBind((AMQDestination)_queue);
+ ((AMQSession<?,?>) _producerSession).declareAndBind((AMQDestination)queue2);
+
+ _producer = _producerSession.createProducer(_queue);
+
+ Connection secondProducerConnection = getConnection();
+ Session secondProducerSession = secondProducerConnection.createSession(false, Session.AUTO_ACKNOWLEDGE);
+ MessageProducer secondProducer = secondProducerSession.createProducer(queue2);
+
+ sendMessagesAsync(_producer, _producerSession, TEST_SIZE, 50L, sentMessages);
+ sendMessagesAsync(secondProducer, secondProducerSession, TEST_SIZE, 50L, sentMessages2);
+
+ while(!((AMQSession<?,?>)_producerSession).isFlowBlocked())
+ {
+ Thread.sleep(100l);
+ }
+ int sentCount = sentMessages.get();
+ assertFalse("Did not block before sending all messages", TEST_SIZE == sentCount);
+
+
+ while(!((AMQSession<?,?>)secondProducerSession).isFlowBlocked())
+ {
+ Thread.sleep(100l);
+ }
+ int sentCount2 = sentMessages2.get();
+ assertFalse("Did not block before sending all messages", TEST_SIZE == sentCount2);
+
+ _consumer = _consumerSession.createConsumer(_queue);
+ MessageConsumer consumer2 = _consumerSession.createConsumer(queue2);
+ _consumerConnection.start();
+
+ for(int i = 0; i < 2*TEST_SIZE; i++)
+ {
+ if(_consumer.receive(1000l) == null
+ && consumer2.receive(1000l) == null)
+ {
+ break;
+ }
+ }
+
+ assertEquals("Not all messages were sent from the first sender", TEST_SIZE, sentMessages.get());
+ assertEquals("Not all messages were sent from the second sender", TEST_SIZE, sentMessages2.get());
+ }
+
+ /**
+ * New producers are blocked
+ */
+ public void testCapacityExceededCausesBlockNewConnection() throws Exception
+ {
+ AtomicInteger sentMessages = new AtomicInteger(0);
+ AtomicInteger sentMessages2 = new AtomicInteger(0);
+
+ _queue = getTestQueue();
+
+ ((AMQSession<?,?>) _producerSession).declareAndBind((AMQDestination)_queue);
+
+ _producer = _producerSession.createProducer(_queue);
+
+ Connection secondProducerConnection = getConnection();
+ Session secondProducerSession = secondProducerConnection.createSession(false, Session.AUTO_ACKNOWLEDGE);
+ MessageProducer secondProducer = secondProducerSession.createProducer(_queue);
+
+ sendMessagesAsync(_producer, _producerSession, TEST_SIZE, 50L, sentMessages);
+
+ while(!((AMQSession<?,?>)_producerSession).isFlowBlocked())
+ {
+ Thread.sleep(100l);
+ }
+ int sentCount = sentMessages.get();
+ assertFalse("Did not block before sending all messages", TEST_SIZE == sentCount);
+
+ sendMessagesAsync(secondProducer, secondProducerSession, TEST_SIZE, 50L, sentMessages2);
+
+ while(!((AMQSession<?,?>)_producerSession).isFlowBlocked())
+ {
+ Thread.sleep(100l);
+ }
+ int sentCount2 = sentMessages2.get();
+ assertFalse("Did not block before sending all messages", TEST_SIZE == sentCount2);
+
+ _consumer = _consumerSession.createConsumer(_queue);
+ _consumerConnection.start();
+
+ for(int i = 0; i < 2*TEST_SIZE; i++)
+ {
+ if(_consumer.receive(2000l) == null)
+ {
+ break;
+ }
+ }
+
+ assertEquals("Not all messages were sent from the first sender", TEST_SIZE, sentMessages.get());
+ assertEquals("Not all messages were sent from the second sender", TEST_SIZE, sentMessages2.get());
+
+ }
+
+ private MessageSender sendMessagesAsync(final MessageProducer producer,
+ final Session producerSession,
+ final int numMessages,
+ long sleepPeriod,
+ AtomicInteger sentMessages)
+ {
+ MessageSender sender = new MessageSender(producer, producerSession, numMessages,sleepPeriod, sentMessages);
+ new Thread(sender).start();
+ return sender;
+ }
+
+ private class MessageSender implements Runnable
+ {
+ private final MessageProducer _senderProducer;
+ private final Session _senderSession;
+ private final int _numMessages;
+ private volatile JMSException _exception;
+ private CountDownLatch _exceptionThrownLatch = new CountDownLatch(1);
+ private long _sleepPeriod;
+ private final AtomicInteger _sentMessages;
+
+ public MessageSender(MessageProducer producer, Session producerSession, int numMessages, long sleepPeriod, AtomicInteger sentMessages)
+ {
+ _senderProducer = producer;
+ _senderSession = producerSession;
+ _numMessages = numMessages;
+ _sleepPeriod = sleepPeriod;
+ _sentMessages = sentMessages;
+ }
+
+ public void run()
+ {
+ try
+ {
+ sendMessages(_senderProducer, _senderSession, _numMessages, _sleepPeriod, _sentMessages);
+ }
+ catch (JMSException e)
+ {
+ _exception = e;
+ _exceptionThrownLatch.countDown();
+ }
+ }
+
+ public Exception getException()
+ {
+ return _exception;
+ }
+
+ }
+
+ private void sendMessages(MessageProducer producer, Session producerSession, int numMessages, long sleepPeriod, AtomicInteger sentMessages)
+ throws JMSException
+ {
+
+ for (int msg = 0; msg < numMessages; msg++)
+ {
+ producer.send(nextMessage(msg, producerSession));
+ sentMessages.incrementAndGet();
+
+ try
+ {
+ ((AMQSession<?,?>)producerSession).sync();
+ }
+ catch (AMQException e)
+ {
+ e.printStackTrace();
+ throw new RuntimeException(e);
+ }
+
+ try
+ {
+ Thread.sleep(sleepPeriod);
+ }
+ catch (InterruptedException e)
+ {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ private Message nextMessage(int msg, Session producerSession) throws JMSException
+ {
+ BytesMessage send = producerSession.createBytesMessage();
+ send.writeBytes(BYTE_32K);
+ send.setIntProperty("msg", msg);
+ return send;
+ }
+
+}
diff --git a/java/systests/src/main/java/org/apache/qpid/test/client/DupsOkTest.java b/java/systests/src/main/java/org/apache/qpid/test/client/DupsOkTest.java
index e06ed6e171..fa36d73283 100644
--- a/java/systests/src/main/java/org/apache/qpid/test/client/DupsOkTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/client/DupsOkTest.java
@@ -1,3 +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.
+ *
+ */
package org.apache.qpid.test.client;
import org.apache.qpid.client.AMQDestination;
@@ -16,26 +36,6 @@ import javax.jms.TextMessage;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
-/*
-*
-* Licensed to the Apache Software Foundation (ASF) under one
-* or more contributor license agreements. See the NOTICE file
-* distributed with this work for additional information
-* regarding copyright ownership. The ASF licenses this file
-* to you under the Apache License, Version 2.0 (the
-* "License"); you may not use this file except in compliance
-* with the License. You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing,
-* software distributed under the License is distributed on an
-* "AS IS" BASIS, WITHOUT 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 DupsOkTest extends QpidBrokerTestCase
{
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 2c7f426306..626592dc10 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
@@ -233,7 +233,7 @@ public class SelectorTest extends QpidBrokerTestCase implements MessageListener
{
}
- assertTrue("Connection should be closed", _connection.isClosed());
+ assertFalse("Connection should not be closed", _connection.isClosed());
}
public void testSelectorWithJMSMessageID() throws Exception
diff --git a/java/systests/src/main/java/org/apache/qpid/test/client/timeouts/SyncWaitDelayTest.java b/java/systests/src/main/java/org/apache/qpid/test/client/timeouts/SyncWaitDelayTest.java
index 91f5cb7770..ee81e7c372 100644
--- a/java/systests/src/main/java/org/apache/qpid/test/client/timeouts/SyncWaitDelayTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/client/timeouts/SyncWaitDelayTest.java
@@ -54,7 +54,7 @@ public class SyncWaitDelayTest extends QpidBrokerTestCase
public void setUp() throws Exception
{
- setConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST+".store.factoryclass", "org.apache.qpid.server.store.SlowMessageStoreFactory");
+ setConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST+".store.class", "org.apache.qpid.server.store.SlowMessageStore");
setConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST+".store.delays.commitTran.post", String.valueOf(POST_COMMIT_DELAY));
setConfigurationProperty("management.enabled", "false");
diff --git a/java/systests/src/main/java/org/apache/qpid/test/unit/client/MaxDeliveryCountTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/client/MaxDeliveryCountTest.java
index fa0fe7e0b5..bc1eead8b4 100644
--- a/java/systests/src/main/java/org/apache/qpid/test/unit/client/MaxDeliveryCountTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/unit/client/MaxDeliveryCountTest.java
@@ -41,6 +41,7 @@ import javax.jms.Session;
import javax.jms.TextMessage;
import javax.jms.Topic;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@@ -67,6 +68,9 @@ public class MaxDeliveryCountTest extends QpidBrokerTestCase
private static final int MAX_DELIVERY_COUNT = 2;
private CountDownLatch _awaitCompletion;
+ /** index numbers of messages to be redelivered */
+ private final List<Integer> _redeliverMsgs = Arrays.asList(1, 2, 5, 14);
+
public void setUp() throws Exception
{
//enable DLQ/maximumDeliveryCount support for all queues at the vhost level
@@ -144,13 +148,7 @@ public class MaxDeliveryCountTest extends QpidBrokerTestCase
*/
public void testAsynchronousClientAckSession() throws Exception
{
- final ArrayList<Integer> redeliverMsgs = new ArrayList<Integer>();
- redeliverMsgs.add(1);
- redeliverMsgs.add(2);
- redeliverMsgs.add(5);
- redeliverMsgs.add(14);
-
- doTest(Session.CLIENT_ACKNOWLEDGE, redeliverMsgs, false, false);
+ doTest(Session.CLIENT_ACKNOWLEDGE, _redeliverMsgs, false, false);
}
/**
@@ -159,13 +157,7 @@ public class MaxDeliveryCountTest extends QpidBrokerTestCase
*/
public void testAsynchronousTransactedSession() throws Exception
{
- final ArrayList<Integer> redeliverMsgs = new ArrayList<Integer>();
- redeliverMsgs.add(1);
- redeliverMsgs.add(2);
- redeliverMsgs.add(5);
- redeliverMsgs.add(14);
-
- doTest(Session.SESSION_TRANSACTED, redeliverMsgs, false, false);
+ doTest(Session.SESSION_TRANSACTED, _redeliverMsgs, false, false);
}
/**
@@ -174,13 +166,7 @@ public class MaxDeliveryCountTest extends QpidBrokerTestCase
*/
public void testAsynchronousAutoAckSession() throws Exception
{
- final ArrayList<Integer> redeliverMsgs = new ArrayList<Integer>();
- redeliverMsgs.add(1);
- redeliverMsgs.add(2);
- redeliverMsgs.add(5);
- redeliverMsgs.add(14);
-
- doTest(Session.AUTO_ACKNOWLEDGE, redeliverMsgs, false, false);
+ doTest(Session.AUTO_ACKNOWLEDGE, _redeliverMsgs, false, false);
}
/**
@@ -189,13 +175,7 @@ public class MaxDeliveryCountTest extends QpidBrokerTestCase
*/
public void testAsynchronousDupsOkSession() throws Exception
{
- final ArrayList<Integer> redeliverMsgs = new ArrayList<Integer>();
- redeliverMsgs.add(1);
- redeliverMsgs.add(2);
- redeliverMsgs.add(5);
- redeliverMsgs.add(14);
-
- doTest(Session.DUPS_OK_ACKNOWLEDGE, redeliverMsgs, false, false);
+ doTest(Session.DUPS_OK_ACKNOWLEDGE, _redeliverMsgs, false, false);
}
/**
@@ -204,13 +184,7 @@ public class MaxDeliveryCountTest extends QpidBrokerTestCase
*/
public void testSynchronousClientAckSession() throws Exception
{
- final ArrayList<Integer> redeliverMsgs = new ArrayList<Integer>();
- redeliverMsgs.add(1);
- redeliverMsgs.add(2);
- redeliverMsgs.add(3);
- redeliverMsgs.add(14);
-
- doTest(Session.CLIENT_ACKNOWLEDGE, redeliverMsgs, true, false);
+ doTest(Session.CLIENT_ACKNOWLEDGE, _redeliverMsgs, true, false);
}
/**
@@ -219,27 +193,22 @@ public class MaxDeliveryCountTest extends QpidBrokerTestCase
*/
public void testSynchronousTransactedSession() throws Exception
{
- final ArrayList<Integer> redeliverMsgs = new ArrayList<Integer>();
- redeliverMsgs.add(1);
- redeliverMsgs.add(2);
- redeliverMsgs.add(5);
- redeliverMsgs.add(14);
-
- doTest(Session.SESSION_TRANSACTED, redeliverMsgs, true, false);
+ doTest(Session.SESSION_TRANSACTED, _redeliverMsgs, true, false);
}
public void testDurableSubscription() throws Exception
{
- final ArrayList<Integer> redeliverMsgs = new ArrayList<Integer>();
- redeliverMsgs.add(1);
- redeliverMsgs.add(2);
- redeliverMsgs.add(5);
- redeliverMsgs.add(14);
+ doTest(Session.SESSION_TRANSACTED, _redeliverMsgs, false, true);
+ }
+
+ public void testWhenBrokerIsRestartedAfterEnqeuingMessages() throws Exception
+ {
+ restartBroker();
- doTest(Session.SESSION_TRANSACTED, redeliverMsgs, false, true);
+ doTest(Session.SESSION_TRANSACTED, _redeliverMsgs, true, false);
}
- public void doTest(final int deliveryMode, final ArrayList<Integer> redeliverMsgs, final boolean synchronous, final boolean durableSub) throws Exception
+ private void doTest(final int deliveryMode, final List<Integer> redeliverMsgs, final boolean synchronous, final boolean durableSub) throws Exception
{
final Connection clientConnection = getConnection();
@@ -311,7 +280,6 @@ public class MaxDeliveryCountTest extends QpidBrokerTestCase
restartBroker();
final Connection clientConnection2 = getConnection();
- final Session clientSession2 = clientConnection2.createSession(transacted, deliveryMode);
clientConnection2.start();
//verify the messages on the DLQ
@@ -406,7 +374,7 @@ public class MaxDeliveryCountTest extends QpidBrokerTestCase
}
private void addMessageListener(final Session session, final MessageConsumer consumer, final int deliveryMode, final int maxDeliveryCount,
- final int expectedTotalNumberOfDeliveries, final ArrayList<Integer> redeliverMsgs) throws JMSException
+ final int expectedTotalNumberOfDeliveries, final List<Integer> redeliverMsgs) throws JMSException
{
if(deliveryMode == org.apache.qpid.jms.Session.NO_ACKNOWLEDGE
|| deliveryMode == org.apache.qpid.jms.Session.PRE_ACKNOWLEDGE)
@@ -567,7 +535,7 @@ public class MaxDeliveryCountTest extends QpidBrokerTestCase
}
private void doSynchronousTest(final Session session, final MessageConsumer consumer, final int deliveryMode, final int maxDeliveryCount,
- final int expectedTotalNumberOfDeliveries, final ArrayList<Integer> redeliverMsgs) throws JMSException, AMQException, InterruptedException
+ final int expectedTotalNumberOfDeliveries, final List<Integer> redeliverMsgs) throws JMSException, AMQException, InterruptedException
{
if(deliveryMode == Session.AUTO_ACKNOWLEDGE
|| deliveryMode == Session.DUPS_OK_ACKNOWLEDGE
@@ -637,7 +605,7 @@ public class MaxDeliveryCountTest extends QpidBrokerTestCase
//sleep then do a synchronous op to give the broker
//time to resend all the messages
Thread.sleep(500);
- ((AMQSession) session).sync();
+ ((AMQSession<?,?>) session).sync();
break;
}
diff --git a/java/systests/src/main/java/org/apache/qpid/test/unit/client/connection/BrokerClosesClientConnectionTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/client/connection/BrokerClosesClientConnectionTest.java
index 5b3bca7033..2cd7520ae4 100644
--- a/java/systests/src/main/java/org/apache/qpid/test/unit/client/connection/BrokerClosesClientConnectionTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/unit/client/connection/BrokerClosesClientConnectionTest.java
@@ -26,7 +26,6 @@ import java.util.concurrent.TimeUnit;
import org.apache.qpid.AMQConnectionClosedException;
import org.apache.qpid.AMQDisconnectedException;
import org.apache.qpid.client.AMQConnection;
-import org.apache.qpid.management.jmx.ManagedConnectionMBeanTest;
import org.apache.qpid.test.utils.QpidBrokerTestCase;
import org.apache.qpid.transport.ConnectionException;
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
index a313475b11..bf1fbbf1a3 100644
--- 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
@@ -20,6 +20,8 @@
*/
package org.apache.qpid.test.unit.client.connection;
+import javax.jms.Connection;
+
import org.apache.qpid.client.AMQConnection;
import org.apache.qpid.client.AMQConnectionFactory;
import org.apache.qpid.test.utils.QpidBrokerTestCase;
@@ -57,5 +59,20 @@ public class ConnectionFactoryTest extends QpidBrokerTestCase
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());
}
-
+
+ /**
+ * Verifies that a connection can be made using an instance of AMQConnectionFactory created with the
+ * default constructor and provided with the connection url via setter.
+ */
+ public void testCreatingConnectionWithInstanceMadeUsingDefaultConstructor() throws Exception
+ {
+ String broker = getBroker().toString();
+ String url = "amqp://guest:guest@clientID/test?brokerlist='" + broker + "'";
+
+ AMQConnectionFactory factory = new AMQConnectionFactory();
+ factory.setConnectionURLString(url);
+
+ Connection con = factory.createConnection();
+ con.close();
+ }
}
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
index cc76d89a67..b11df5a2a0 100644
--- 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
@@ -30,7 +30,7 @@ import javax.jms.Queue;
* 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
+ * A producer that is idle for too long or open for too long will have its connection/session(0-10) closed and
* any further operations will fail with a 408 resource timeout exception. Consumers will not
* be affected by the transaction timeout configuration.
*/
diff --git a/java/systests/src/main/java/org/apache/qpid/test/unit/xa/FaultTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/xa/FaultTest.java
index e940a73bbb..39973e12c7 100644
--- a/java/systests/src/main/java/org/apache/qpid/test/unit/xa/FaultTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/unit/xa/FaultTest.java
@@ -1,6 +1,5 @@
-package org.apache.qpid.test.unit.xa;
/*
- *
+ *
* Licensed 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,17 +7,18 @@ package org.apache.qpid.test.unit.xa;
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.xa;
import junit.framework.TestSuite;
@@ -344,7 +344,7 @@ public class FaultTest extends AbstractXATestCase
{
assertEquals("Wrong error code: ", XAException.XAER_PROTO, e.errorCode);
}
- }
+ }
/**
* Strategy:
@@ -366,27 +366,28 @@ public class FaultTest extends AbstractXATestCase
/**
* Strategy:
* Check that a transaction timeout as expected
- * - set timeout to 10ms
- * - sleep 1000ms
+ * - set timeout to 1s
+ * - sleep 1500ms
* - call end and check that the expected exception is thrown
*/
public void testTransactionTimeout() throws Exception
{
+ _xaResource.setTransactionTimeout(1);
+
Xid xid = getNewXid();
try
{
_xaResource.start(xid, XAResource.TMNOFLAGS);
- assertEquals("Wrong timeout", _xaResource.getTransactionTimeout(), 0);
- _xaResource.setTransactionTimeout(10);
- Thread.sleep(1000);
+ Thread.sleep(1500);
_xaResource.end(xid, XAResource.TMSUCCESS);
+ fail("Timeout expected ");
}
catch (XAException e)
{
assertEquals("Wrong error code: ", XAException.XA_RBTIMEOUT, e.errorCode);
}
}
-
+
/**
* Strategy:
* Set the transaction timeout to 1000
@@ -394,18 +395,18 @@ public class FaultTest extends AbstractXATestCase
public void testTransactionTimeoutAfterCommit() throws Exception
{
Xid xid = getNewXid();
-
+
_xaResource.start(xid, XAResource.TMNOFLAGS);
_xaResource.setTransactionTimeout(1000);
assertEquals("Wrong timeout", 1000,_xaResource.getTransactionTimeout());
-
+
//_xaResource.prepare(xid);
_xaResource.end(xid, XAResource.TMSUCCESS);
_xaResource.commit(xid, true);
-
+
_xaResource.setTransactionTimeout(2000);
assertEquals("Wrong timeout", 2000,_xaResource.getTransactionTimeout());
-
+
xid = getNewXid();
_xaResource.start(xid, XAResource.TMNOFLAGS);
assertEquals("Wrong timeout", 2000, _xaResource.getTransactionTimeout());
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
index 66b3fe0c6a..3af57327d2 100644
--- 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
@@ -25,4 +25,5 @@ public interface BrokerHolder
String getWorkingDirectory();
void shutdown();
void kill();
+ String dumpThreads();
}
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
index adda9ca3ec..a71a4ef517 100644
--- 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
@@ -20,6 +20,11 @@
*/
package org.apache.qpid.test.utils;
+import java.lang.management.ManagementFactory;
+import java.lang.management.ThreadInfo;
+import java.lang.management.ThreadMXBean;
+import java.util.Set;
+
import org.apache.log4j.Logger;
import org.apache.qpid.server.Broker;
@@ -31,7 +36,9 @@ public class InternalBrokerHolder implements BrokerHolder
private final Broker _broker;
private final String _workingDirectory;
- public InternalBrokerHolder(final Broker broker, String workingDirectory)
+ private Set<Integer> _portsUsedByBroker;
+
+ public InternalBrokerHolder(final Broker broker, String workingDirectory, Set<Integer> portsUsedByBroker)
{
if(broker == null)
{
@@ -40,6 +47,7 @@ public class InternalBrokerHolder implements BrokerHolder
_broker = broker;
_workingDirectory = workingDirectory;
+ _portsUsedByBroker = portsUsedByBroker;
}
@Override
@@ -53,7 +61,9 @@ public class InternalBrokerHolder implements BrokerHolder
LOGGER.info("Shutting down Broker instance");
_broker.shutdown();
-
+
+ waitUntilPortsAreFree();
+
LOGGER.info("Broker instance shutdown");
}
@@ -64,5 +74,42 @@ public class InternalBrokerHolder implements BrokerHolder
shutdown();
}
+ private void waitUntilPortsAreFree()
+ {
+ new PortHelper().waitUntilPortsAreFree(_portsUsedByBroker);
+ }
+
+ @Override
+ public String dumpThreads()
+ {
+ ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
+ ThreadInfo[] threadInfos = threadMXBean.dumpAllThreads(true, true);
+ StringBuilder dump = new StringBuilder();
+ dump.append(String.format("%n"));
+ for (ThreadInfo threadInfo : threadInfos)
+ {
+ dump.append(threadInfo);
+ }
+
+ long[] deadLocks = threadMXBean.findDeadlockedThreads();
+ if (deadLocks != null && deadLocks.length > 0)
+ {
+ ThreadInfo[] deadlockedThreads = threadMXBean.getThreadInfo(deadLocks);
+ dump.append(String.format("%n"));
+ dump.append("Deadlock is detected!");
+ dump.append(String.format("%n"));
+ for (ThreadInfo threadInfo : deadlockedThreads)
+ {
+ dump.append(threadInfo);
+ }
+ }
+ return dump.toString();
+ }
+
+ @Override
+ public String toString()
+ {
+ return "InternalBrokerHolder [_portsUsedByBroker=" + _portsUsedByBroker + "]";
+ }
}
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 d9c259c389..43b80b45fb 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
@@ -33,11 +33,15 @@ import org.apache.qpid.management.common.mbeans.ManagedQueue;
import org.apache.qpid.management.common.mbeans.ServerInformation;
import org.apache.qpid.management.common.mbeans.UserManagement;
+import javax.management.InstanceNotFoundException;
import javax.management.JMException;
+import javax.management.ListenerNotFoundException;
import javax.management.MBeanException;
import javax.management.MBeanServerConnection;
import javax.management.MBeanServerInvocationHandler;
import javax.management.MalformedObjectNameException;
+import javax.management.NotificationFilter;
+import javax.management.NotificationListener;
import javax.management.ObjectName;
import javax.management.remote.JMXConnector;
import java.io.IOException;
@@ -50,8 +54,8 @@ import java.util.Set;
*/
public class JMXTestUtils
{
- private static final String DEFAULT_PASSWORD = "admin";
- private static final String DEFAULT_USERID = "admin";
+ public static final String DEFAULT_PASSWORD = "admin";
+ public static final String DEFAULT_USERID = "admin";
private MBeanServerConnection _mbsc;
private JMXConnector _jmxc;
@@ -79,8 +83,16 @@ public class JMXTestUtils
public void open() throws Exception
{
+ open(0); // Zero signifies default broker to QBTC.
+ }
+
+ public void open(final int brokerPort) throws Exception
+ {
+ int actualBrokerPort = _test.getPort(brokerPort);
+ int managementPort = _test.getManagementPort(actualBrokerPort);
+
_jmxc = JMXConnnectionFactory.getJMXConnection(5000, "127.0.0.1",
- _test.getManagementPort(_test.getPort()), _user, _password);
+ managementPort, _user, _password);
_mbsc = _jmxc.getMBeanServerConnection();
}
@@ -93,6 +105,18 @@ public class JMXTestUtils
}
}
+ public void addNotificationListener(ObjectName name, NotificationListener listener, NotificationFilter filter, Object handback)
+ throws InstanceNotFoundException, IOException
+ {
+ _mbsc.addNotificationListener(name, listener, filter, handback);
+ }
+
+ public void removeNotificationListener(ObjectName name, NotificationListener listener)
+ throws InstanceNotFoundException, IOException, ListenerNotFoundException
+ {
+ _mbsc.removeNotificationListener(name, listener);
+ }
+
/**
* Create a non-durable exchange with the requested name
*
@@ -136,7 +160,6 @@ public class JMXTestUtils
throws IOException, JMException, MBeanException
{
ManagedBroker managedBroker = getManagedBroker(virtualHostName);
-
managedBroker.unregisterExchange(exchange);
}
@@ -152,87 +175,81 @@ public class JMXTestUtils
throws IOException, JMException, MBeanException
{
ManagedBroker managedBroker = getManagedBroker(virtualHostName);
-
managedBroker.deleteQueue(queueName);
}
-
+
/**
- * Sets the logging level.
+ * Sets the logging level.
*
* @throws JMException
* @throws IOException if there is a problem with the JMX Connection
* @throws MBeanException
*/
public void setRuntimeLoggerLevel(String logger, String level)
- throws IOException, JMException, MBeanException
+ throws IOException, JMException, MBeanException
{
LoggingManagement loggingManagement = getLoggingManagement();
-
loggingManagement.setRuntimeLoggerLevel(logger, level);
}
-
+
/**
- * Reload logging config file.
+ * Reload logging config file.
*
* @throws JMException
* @throws IOException if there is a problem with the JMX Connection
* @throws MBeanException
*/
public void reloadConfigFile()
- throws IOException, JMException, MBeanException
+ throws IOException, JMException, MBeanException
{
LoggingManagement loggingManagement = getLoggingManagement();
-
loggingManagement.reloadConfigFile();
}
/**
- * Get list of available logger levels.
+ * Get list of available logger levels.
*
* @throws JMException
* @throws IOException if there is a problem with the JMX Connection
* @throws MBeanException
*/
public String[] getAvailableLoggerLevels()
- throws IOException, JMException, MBeanException
+ throws IOException, JMException, MBeanException
{
LoggingManagement loggingManagement = getLoggingManagement();
-
return loggingManagement.getAvailableLoggerLevels();
}
-
+
/**
- * Set root logger level.
+ * Set root logger level.
*
* @throws JMException
* @throws IOException if there is a problem with the JMX Connection
* @throws MBeanException
*/
public void setRuntimeRootLoggerLevel(String level)
- throws IOException, JMException, MBeanException
+ throws IOException, JMException, MBeanException
{
LoggingManagement loggingManagement = getLoggingManagement();
-
loggingManagement.setRuntimeRootLoggerLevel(level);
}
-
+
/**
- * Get root logger level.
+ * Get root logger level.
*
* @throws JMException
* @throws IOException if there is a problem with the JMX Connection
* @throws MBeanException
*/
public String getRuntimeRootLoggerLevel()
- throws IOException, JMException, MBeanException
+ throws IOException, JMException, MBeanException
{
LoggingManagement loggingManagement = getLoggingManagement();
-
return loggingManagement.getRuntimeRootLoggerLevel();
}
/**
- * Retrive the ObjectName for a Virtualhost.
+ * Retrieve the ObjectName for a Virtualhost.
*
* This is then used to create a proxy to the ManagedBroker MBean.
*
@@ -253,12 +270,12 @@ public class JMXTestUtils
// We have verified we have only one value in objectNames so return it
ObjectName objectName = objectNames.iterator().next();
- _test.getLogger().info("Loading: " + objectName);
+ _test.getLogger().info("Loading: " + objectName);
return objectName;
}
/**
- * Retrive the ObjectName for the given Queue on a Virtualhost.
+ * Retrieve the ObjectName for the given Queue on a Virtualhost.
*
* This is then used to create a proxy to the ManagedQueue MBean.
*
@@ -281,7 +298,7 @@ public class JMXTestUtils
// We have verified we have only one value in objectNames so return it
ObjectName objectName = objectNames.iterator().next();
- _test.getLogger().info("Loading: " + objectName);
+ _test.getLogger().info("Loading: " + objectName);
return objectName;
}
@@ -309,7 +326,7 @@ public class JMXTestUtils
// We have verified we have only one value in objectNames so return it
ObjectName objectName = objectNames.iterator().next();
- _test.getLogger().info("Loading: " + objectName);
+ _test.getLogger().info("Loading: " + objectName);
return objectName;
}
@@ -319,10 +336,10 @@ public class JMXTestUtils
Set<ObjectName> objectNames = queryObjects(query);
_test.assertNotNull("Null ObjectName Set returned", objectNames);
- _test.assertEquals("More than one " + managedClass + " returned", 1, objectNames.size());
+ _test.assertEquals("Unexpected number of objects matching " + managedClass + " returned", 1, objectNames.size());
ObjectName objectName = objectNames.iterator().next();
- _test.getLogger().info("Loading: " + objectName);
+ _test.getLogger().info("Loading: " + objectName);
return getManagedObject(managedClass, objectName);
}
@@ -355,34 +372,34 @@ public class JMXTestUtils
{
return getManagedObject(ManagedBroker.class, getVirtualHostManagerObjectName(virtualHost));
}
-
+
public ManagedExchange getManagedExchange(String exchangeName)
{
- ObjectName objectName = getExchangeObjectName("test", exchangeName);
+ ObjectName objectName = getExchangeObjectName("test", exchangeName);
return MBeanServerInvocationHandler.newProxyInstance(_mbsc, objectName, ManagedExchange.class, false);
}
-
+
public ManagedQueue getManagedQueue(String queueName)
{
ObjectName objectName = getQueueObjectName("test", queueName);
return getManagedObject(ManagedQueue.class, objectName);
}
- public LoggingManagement getLoggingManagement() throws MalformedObjectNameException
+ public LoggingManagement getLoggingManagement() throws MalformedObjectNameException
{
- ObjectName objectName = new ObjectName("org.apache.qpid:type=LoggingManagement,name=LoggingManagement");
+ ObjectName objectName = new ObjectName("org.apache.qpid:type=LoggingManagement,name=LoggingManagement");
return getManagedObject(LoggingManagement.class, objectName);
}
-
- public ConfigurationManagement getConfigurationManagement() throws MalformedObjectNameException
+
+ public ConfigurationManagement getConfigurationManagement() throws MalformedObjectNameException
{
- ObjectName objectName = new ObjectName("org.apache.qpid:type=ConfigurationManagement,name=ConfigurationManagement");
+ ObjectName objectName = new ObjectName("org.apache.qpid:type=ConfigurationManagement,name=ConfigurationManagement");
return getManagedObject(ConfigurationManagement.class, objectName);
}
-
- public UserManagement getUserManagement() throws MalformedObjectNameException
+
+ public UserManagement getUserManagement() throws MalformedObjectNameException
{
- ObjectName objectName = new ObjectName("org.apache.qpid:type=UserManagement,name=UserManagement");
+ ObjectName objectName = new ObjectName("org.apache.qpid:type=UserManagement,name=UserManagement");
return getManagedObject(UserManagement.class, objectName);
}
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 c070fb4de0..aa909a6674 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
@@ -17,11 +17,41 @@
*/
package org.apache.qpid.test.utils;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+
+import javax.jms.BytesMessage;
+import javax.jms.Connection;
+import javax.jms.Destination;
+import javax.jms.JMSException;
+import javax.jms.MapMessage;
+import javax.jms.Message;
+import javax.jms.MessageConsumer;
+import javax.jms.MessageProducer;
+import javax.jms.ObjectMessage;
+import javax.jms.Queue;
+import javax.jms.Session;
+import javax.jms.StreamMessage;
+import javax.jms.TextMessage;
+import javax.jms.Topic;
+import javax.naming.InitialContext;
+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.Logger;
-
import org.apache.qpid.AMQException;
import org.apache.qpid.client.AMQConnectionFactory;
import org.apache.qpid.client.AMQQueue;
@@ -33,59 +63,33 @@ 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.ProtocolInclusion;
import org.apache.qpid.server.configuration.ServerConfiguration;
import org.apache.qpid.server.protocol.AmqpProtocolVersion;
import org.apache.qpid.server.store.MessageStoreConstants;
-import org.apache.qpid.server.store.derby.DerbyMessageStoreFactory;
+import org.apache.qpid.server.store.derby.DerbyMessageStore;
import org.apache.qpid.url.URLSyntaxException;
import org.apache.qpid.util.FileUtils;
import org.apache.qpid.util.LogMonitor;
-import javax.jms.BytesMessage;
-import javax.jms.Connection;
-import javax.jms.Destination;
-import javax.jms.JMSException;
-import javax.jms.MapMessage;
-import javax.jms.Message;
-import javax.jms.MessageConsumer;
-import javax.jms.MessageProducer;
-import javax.jms.ObjectMessage;
-import javax.jms.Queue;
-import javax.jms.Session;
-import javax.jms.StreamMessage;
-import javax.jms.TextMessage;
-import javax.jms.Topic;
-import javax.naming.InitialContext;
-import javax.naming.NamingException;
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.PrintStream;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.TimeUnit;
-
/**
* Qpid base class for system testing test cases.
*/
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 */
}
+
+ public static final String GUEST_USERNAME = "guest";
+ public static final String GUEST_PASSWORD = "guest";
+
protected final static String QpidHome = System.getProperty("QPID_HOME");
protected File _configFile = new File(System.getProperty("broker.config"));
+ protected File _logConfigFile = new File(System.getProperty("log4j.configuration"));
protected static final Logger _logger = Logger.getLogger(QpidBrokerTestCase.class);
protected static final int LOGMONITOR_TIMEOUT = 5000;
@@ -113,8 +117,10 @@ public class QpidBrokerTestCase extends QpidTestCase
}
// system properties
+ private static final String TEST_VIRTUALHOSTS = "test.virtualhosts";
+ private static final String TEST_CONFIG = "test.config";
private static final String BROKER_LANGUAGE = "broker.language";
- private static final String BROKER_TYPE = "broker.type";
+ protected static final String BROKER_TYPE = "broker.type";
private static final String BROKER_COMMAND = "broker.command";
private static final String BROKER_CLEAN_BETWEEN_TESTS = "broker.clean.between.tests";
private static final String BROKER_EXISTING_QPID_WORK = "broker.existing.qpid.work";
@@ -125,7 +131,8 @@ 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";
+ public static final String BROKER_PROTOCOL_EXCLUDES = "broker.protocol.excludes";
+ public static final String BROKER_PROTOCOL_INCLUDES = "broker.protocol.includes";
// values
protected static final String JAVA = "java";
@@ -146,7 +153,6 @@ public class QpidBrokerTestCase extends QpidTestCase
private final AmqpProtocolVersion _brokerVersion = AmqpProtocolVersion.valueOf(System.getProperty(BROKER_VERSION, ""));
protected String _output = System.getProperty(TEST_OUTPUT, System.getProperty("java.io.tmpdir"));
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);
@@ -164,13 +170,13 @@ public class QpidBrokerTestCase extends QpidTestCase
protected List<Connection> _connections = new ArrayList<Connection>();
public static final String QUEUE = "queue";
public static final String TOPIC = "topic";
-
+
/** Map to hold test defined environment properties */
private Map<String, String> _env;
/** Ensure our messages have some sort of size */
protected static final int DEFAULT_MESSAGE_SIZE = 1024;
-
+
/** Size to create our message*/
private int _messageSize = DEFAULT_MESSAGE_SIZE;
/** Type of message*/
@@ -193,7 +199,7 @@ public class QpidBrokerTestCase extends QpidTestCase
{
super();
}
-
+
public Logger getLogger()
{
return QpidBrokerTestCase._logger;
@@ -219,10 +225,6 @@ public class QpidBrokerTestCase extends QpidTestCase
out = new PrintStream(new FileOutputStream(_outputFile), true);
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);
@@ -313,6 +315,24 @@ public class QpidBrokerTestCase extends QpidTestCase
}
/**
+ * The returned set of port numbers is only a guess because it assumes no ports have been overridden
+ * using system properties.
+ */
+ protected Set<Integer> guessAllPortsUsedByBroker(int mainPort)
+ {
+ Set<Integer> ports = new HashSet<Integer>();
+ int managementPort = getManagementPort(mainPort);
+ int connectorServerPort = managementPort + ServerConfiguration.JMXPORT_CONNECTORSERVER_OFFSET;
+
+ ports.add(mainPort);
+ ports.add(managementPort);
+ ports.add(connectorServerPort);
+ ports.add(DEFAULT_SSL_PORT);
+
+ return ports;
+ }
+
+ /**
* Get the Port that is use by the current broker
*
* @return the current port
@@ -338,12 +358,16 @@ public class QpidBrokerTestCase extends QpidTestCase
{
final int sslPort = port-1;
final String protocolExcludesList = getProtocolExcludesList(port, sslPort);
+ final String protocolIncludesList = getProtocolIncludesList(port, sslPort);
+
return _brokerCommand
.replace("@PORT", "" + port)
.replace("@SSL_PORT", "" + sslPort)
.replace("@MPORT", "" + getManagementPort(port))
.replace("@CONFIG_FILE", _configFile.toString())
- .replace("@EXCLUDES", protocolExcludesList);
+ .replace("@LOG_CONFIG_FILE", _logConfigFile.toString())
+ .replace("@EXCLUDES", protocolExcludesList)
+ .replace("@INCLUDES", protocolIncludesList);
}
public void startBroker() throws Exception
@@ -353,39 +377,51 @@ public class QpidBrokerTestCase extends QpidTestCase
public void startBroker(int port) throws Exception
{
+ startBroker(port, _testConfiguration, _testVirtualhosts);
+ }
+
+ public void startBroker(int port, XMLConfiguration testConfiguration, XMLConfiguration virtualHosts) throws Exception
+ {
port = getPort(port);
// Save any configuration changes that have been made
- saveTestConfiguration();
- saveTestVirtualhosts();
+ String testConfig = saveTestConfiguration(port, testConfiguration);
+ String virtualHostsConfig = saveTestVirtualhosts(port, virtualHosts);
if(_brokers.get(port) != null)
{
throw new IllegalStateException("There is already an existing broker running on port " + port);
}
+ Set<Integer> portsUsedByBroker = guessAllPortsUsedByBroker(port);
+
if (_brokerType.equals(BrokerType.INTERNAL) && !existingInternalBroker())
{
setConfigurationProperty(ServerConfiguration.MGMT_CUSTOM_REGISTRY_SOCKET, String.valueOf(false));
- saveTestConfiguration();
+ testConfig = saveTestConfiguration(port, testConfiguration);
+ _logger.info("Set test.config property to: " + testConfig);
+ _logger.info("Set test.virtualhosts property to: " + virtualHostsConfig);
+ setSystemProperty(TEST_CONFIG, testConfig);
+ setSystemProperty(TEST_VIRTUALHOSTS, virtualHostsConfig);
BrokerOptions options = new BrokerOptions();
options.setConfigFile(_configFile.getAbsolutePath());
options.addPort(port);
addExcludedPorts(port, DEFAULT_SSL_PORT, options);
+ addIncludedPorts(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());
+ options.setLogConfigFile(_logConfigFile.getAbsolutePath());
Broker broker = new Broker();
_logger.info("starting internal broker (same JVM)");
broker.startup(options);
- _brokers.put(port, new InternalBrokerHolder(broker, System.getProperty("QPID_WORK")));
+ _brokers.put(port, new InternalBrokerHolder(broker, System.getProperty("QPID_WORK"), portsUsedByBroker));
}
else if (!_brokerType.equals(BrokerType.EXTERNAL))
{
@@ -395,16 +431,16 @@ public class QpidBrokerTestCase extends QpidTestCase
_logger.info("starting external broker: " + cmd);
ProcessBuilder pb = new ProcessBuilder(cmd.split("\\s+"));
pb.redirectErrorStream(true);
- Map<String, String> env = pb.environment();
+ Map<String, String> processEnv = pb.environment();
String qpidHome = System.getProperty(QPID_HOME);
- env.put(QPID_HOME, qpidHome);
+ processEnv.put(QPID_HOME, qpidHome);
//Augment Path with bin directory in QPID_HOME.
- env.put("PATH", env.get("PATH").concat(File.pathSeparator + qpidHome + "/bin"));
+ processEnv.put("PATH", processEnv.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);
+ processEnv.put("QPID_PNAME", "-DPNAME=QPBRKR -DTNAME=\"" + getTestName() + "\"");
+ processEnv.put("QPID_WORK", qpidWork);
// Use the environment variable to set amqj.logging.level for the broker
// The value used is a 'server' value in the test configuration to
@@ -419,7 +455,7 @@ public class QpidBrokerTestCase extends QpidTestCase
{
for (Map.Entry<String, String> entry : _env.entrySet())
{
- env.put(entry.getKey(), entry.getValue());
+ processEnv.put(entry.getKey(), entry.getValue());
}
}
@@ -436,25 +472,25 @@ public class QpidBrokerTestCase extends QpidTestCase
setSystemProperty("root.logging.level");
}
+ // set test.config and test.virtualhosts
+ String qpidOpts = " -D" + TEST_CONFIG + "=" + testConfig + " -D" + TEST_VIRTUALHOSTS + "=" + virtualHostsConfig;
- String QPID_OPTS = " ";
// Add all the specified system properties to QPID_OPTS
if (!_propertiesSetForBroker.isEmpty())
{
for (String key : _propertiesSetForBroker.keySet())
{
- QPID_OPTS += "-D" + key + "=" + _propertiesSetForBroker.get(key) + " ";
- }
-
- if (env.containsKey("QPID_OPTS"))
- {
- env.put("QPID_OPTS", env.get("QPID_OPTS") + QPID_OPTS);
- }
- else
- {
- env.put("QPID_OPTS", QPID_OPTS);
+ qpidOpts += " -D" + key + "=" + _propertiesSetForBroker.get(key);
}
}
+ if (processEnv.containsKey("QPID_OPTS"))
+ {
+ qpidOpts = processEnv.get("QPID_OPTS") + qpidOpts;
+ }
+ processEnv.put("QPID_OPTS", qpidOpts);
+
+ _logger.info("Set test.config property to: " + testConfig);
+ _logger.info("Set test.virtualhosts property to: " + virtualHostsConfig);
// cpp broker requires that the work directory is created
createBrokerWork(qpidWork);
@@ -492,14 +528,14 @@ public class QpidBrokerTestCase extends QpidTestCase
// this is expect if the broker started successfully
}
- _brokers.put(port, new SpawnedBrokerHolder(process, qpidWork));
+ _brokers.put(port, new SpawnedBrokerHolder(process, qpidWork, portsUsedByBroker));
}
}
private void addExcludedPorts(int port, int sslPort, BrokerOptions options)
{
final String protocolExcludesList = getProtocolExcludesList(port, sslPort);
-
+
if (protocolExcludesList.equals(""))
{
return;
@@ -522,9 +558,36 @@ public class QpidBrokerTestCase extends QpidTestCase
protected String getProtocolExcludesList(int port, int sslPort)
{
- final String protocolExcludesList =
- _brokerProtocolExcludes.replace("@PORT", "" + port).replace("@SSL_PORT", "" + sslPort);
- return protocolExcludesList;
+ return System.getProperty(BROKER_PROTOCOL_EXCLUDES,"").replace("@PORT", "" + port).replace("@SSL_PORT", "" + sslPort);
+ }
+
+ private String getProtocolIncludesList(int port, int sslPort)
+ {
+ return System.getProperty(BROKER_PROTOCOL_INCLUDES, "").replace("@PORT", "" + port).replace("@SSL_PORT", "" + sslPort);
+ }
+
+ private void addIncludedPorts(int port, int sslPort, BrokerOptions options)
+ {
+ final String protocolIncludesList = getProtocolIncludesList(port, sslPort);
+
+ if (protocolIncludesList.equals(""))
+ {
+ return;
+ }
+ final String[] toks = protocolIncludesList.split("\\s");
+
+ if(toks.length % 2 != 0)
+ {
+ throw new IllegalArgumentException("Must be an even number of tokens in '" + protocolIncludesList + "'");
+ }
+ for (int i = 0; i < toks.length; i=i+2)
+ {
+ String includeArg = toks[i];
+ final int includedPort = Integer.parseInt(toks[i+1]);
+ options.addIncludedPort(ProtocolInclusion.lookup(includeArg), includedPort);
+
+ _logger.info("Adding protocol inclusion " + includeArg + " " + includedPort);
+ }
}
private boolean existingInternalBroker()
@@ -552,12 +615,17 @@ public class QpidBrokerTestCase extends QpidTestCase
public String getTestConfigFile()
{
- return _output + "/" + getTestQueueName() + "-config.xml";
+ return getTestConfigFile(getPort());
+ }
+
+ public String getTestConfigFile(int port)
+ {
+ return _output + "/" + getTestQueueName() + "-" + port + "-config.xml";
}
- public String getTestVirtualhostsFile()
+ public String getTestVirtualhostsFile(int port)
{
- return _output + "/" + getTestQueueName() + "-virtualhosts.xml";
+ return _output + "/" + getTestQueueName() + "-" + port + "-virtualhosts.xml";
}
private String relativeToQpidHome(String file)
@@ -567,38 +635,50 @@ public class QpidBrokerTestCase extends QpidTestCase
protected void saveTestConfiguration() throws ConfigurationException
{
+ String relative = saveTestConfiguration(getPort(), _testConfiguration);
+ _logger.info("Set test.config property to: " + relative);
+ setSystemProperty(TEST_CONFIG, relative);
+ }
+
+ protected String saveTestConfiguration(int port, XMLConfiguration testConfiguration) throws ConfigurationException
+ {
// Specify the test config file
- String testConfig = getTestConfigFile();
+ String testConfig = getTestConfigFile(port);
String relative = relativeToQpidHome(testConfig);
- setSystemProperty("test.config", relative);
- _logger.info("Set test.config property to: " + relative);
_logger.info("Saving test virtualhosts file at: " + testConfig);
// Create the file if configuration does not exist
- if (_testConfiguration.isEmpty())
+ if (testConfiguration.isEmpty())
{
- _testConfiguration.addProperty("__ignore", "true");
+ testConfiguration.addProperty("__ignore", "true");
}
- _testConfiguration.save(testConfig);
+ testConfiguration.save(testConfig);
+ return relative;
}
protected void saveTestVirtualhosts() throws ConfigurationException
{
+ String relative = saveTestVirtualhosts(getPort(), _testVirtualhosts);
+ _logger.info("Set test.virtualhosts property to: " + relative);
+ setSystemProperty(TEST_VIRTUALHOSTS, relative);
+ }
+
+ protected String saveTestVirtualhosts(int port, XMLConfiguration virtualHostConfiguration) throws ConfigurationException
+ {
// Specify the test virtualhosts file
- String testVirtualhosts = getTestVirtualhostsFile();
+ String testVirtualhosts = getTestVirtualhostsFile(port);
String relative = relativeToQpidHome(testVirtualhosts);
- setSystemProperty("test.virtualhosts", relative);
- _logger.info("Set test.virtualhosts property to: " + relative);
- _logger.info("Saving test virtualhosts file at: " + testVirtualhosts);
+ _logger.info("Set test.virtualhosts property to: " + testVirtualhosts);
// Create the file if configuration does not exist
- if (_testVirtualhosts.isEmpty())
+ if (virtualHostConfiguration.isEmpty())
{
- _testVirtualhosts.addProperty("__ignore", "true");
+ virtualHostConfiguration.addProperty("__ignore", "true");
}
- _testVirtualhosts.save(testVirtualhosts);
+ virtualHostConfiguration.save(testVirtualhosts);
+ return relative;
}
protected void cleanBrokerWork(final String qpidWork)
@@ -639,11 +719,55 @@ public class QpidBrokerTestCase extends QpidTestCase
public void stopAllBrokers()
{
+ boolean exceptionOccured = false;
Set<Integer> runningBrokerPorts = new HashSet<Integer>(getBrokerPortNumbers());
for (int brokerPortNumber : runningBrokerPorts)
{
+ if (!stopBrokerSafely(brokerPortNumber))
+ {
+ exceptionOccured = true;
+ }
+ }
+ if (exceptionOccured)
+ {
+ throw new RuntimeException("Exception occured on stopping of test broker. Please, examine logs for details");
+ }
+ }
+
+ protected boolean stopBrokerSafely(int brokerPortNumber)
+ {
+ boolean success = true;
+ BrokerHolder broker = _brokers.get(brokerPortNumber);
+ try
+ {
stopBroker(brokerPortNumber);
}
+ catch(Exception e)
+ {
+ success = false;
+ _logger.error("Failed to stop broker " + broker + " at port " + brokerPortNumber, e);
+ if (broker != null)
+ {
+ // save the thread dump in case of dead locks
+ try
+ {
+ _logger.error("Broker " + broker + " thread dump:" + broker.dumpThreads());
+ }
+ finally
+ {
+ // try to kill broker
+ try
+ {
+ broker.kill();
+ }
+ catch(Exception killException)
+ {
+ // ignore
+ }
+ }
+ }
+ }
+ return success;
}
public void stopBroker(int port)
@@ -705,21 +829,21 @@ public class QpidBrokerTestCase extends QpidTestCase
protected void makeVirtualHostPersistent(String virtualhost)
throws ConfigurationException, IOException
{
- Class<?> storeFactoryClass = null;
+ Class<?> storeClass = null;
try
{
// Try and lookup the BDB class
- storeFactoryClass = Class.forName("org.apache.qpid.server.store.berkeleydb.BDBMessageStoreFactory");
+ storeClass = Class.forName("org.apache.qpid.server.store.berkeleydb.BDBMessageStore");
}
catch (ClassNotFoundException e)
{
// No BDB store, we'll use Derby instead.
- storeFactoryClass = DerbyMessageStoreFactory.class;
+ storeClass = DerbyMessageStore.class;
}
- setConfigurationProperty("virtualhosts.virtualhost." + virtualhost + ".store.factoryclass",
- storeFactoryClass.getName());
+ setConfigurationProperty("virtualhosts.virtualhost." + virtualhost + ".store.class",
+ storeClass.getName());
setConfigurationProperty("virtualhosts.virtualhost." + virtualhost + ".store." + MessageStoreConstants.ENVIRONMENT_PATH_PROPERTY,
"${QPID_WORK}/" + virtualhost);
}
@@ -974,10 +1098,10 @@ public class QpidBrokerTestCase extends QpidTestCase
{
return (AMQConnectionFactory) getInitialContext().lookup(factoryName);
}
-
+
public Connection getConnection() throws JMSException, NamingException
{
- return getConnection("guest", "guest");
+ return getConnection(GUEST_USERNAME, GUEST_PASSWORD);
}
public Connection getConnection(ConnectionURL url) throws JMSException
@@ -1268,14 +1392,14 @@ public class QpidBrokerTestCase extends QpidTestCase
/**
* Reloads the broker security configuration using the ApplicationRegistry (InVM brokers) or the
- * ConfigurationManagementMBean via the JMX interface (Standalone brokers, management must be
+ * ConfigurationManagementMBean via the JMX interface (Standalone brokers, management must be
* enabled before calling the method).
*/
public void reloadBrokerSecurityConfig() throws Exception
{
JMXTestUtils jmxu = new JMXTestUtils(this);
jmxu.open();
-
+
try
{
ConfigurationManagement configMBean = jmxu.getConfigurationManagement();
@@ -1285,7 +1409,7 @@ public class QpidBrokerTestCase extends QpidTestCase
{
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));
@@ -1295,4 +1419,24 @@ public class QpidBrokerTestCase extends QpidTestCase
{
return FAILING_PORT;
}
+
+ public XMLConfiguration getTestVirtualhosts()
+ {
+ return _testVirtualhosts;
+ }
+
+ public void setTestVirtualhosts(XMLConfiguration testVirtualhosts)
+ {
+ _testVirtualhosts = testVirtualhosts;
+ }
+
+ public XMLConfiguration getTestConfiguration()
+ {
+ return _testConfiguration;
+ }
+
+ public void setTestConfiguration(XMLConfiguration testConfiguration)
+ {
+ _testConfiguration = testConfiguration;
+ }
}
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
index 787fc164d5..bce97a574a 100644
--- 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
@@ -20,7 +20,10 @@
*/
package org.apache.qpid.test.utils;
+import java.io.ByteArrayOutputStream;
import java.io.IOException;
+import java.io.InputStream;
+import java.util.Set;
import org.apache.log4j.Logger;
@@ -32,8 +35,9 @@ public class SpawnedBrokerHolder implements BrokerHolder
private final Process _process;
private final Integer _pid;
private final String _workingDirectory;
+ private Set<Integer> _portsUsedByBroker;
- public SpawnedBrokerHolder(final Process process, final String workingDirectory)
+ public SpawnedBrokerHolder(final Process process, final String workingDirectory, Set<Integer> portsUsedByBroker)
{
if(process == null)
{
@@ -43,6 +47,7 @@ public class SpawnedBrokerHolder implements BrokerHolder
_process = process;
_pid = retrieveUnixPidIfPossible();
_workingDirectory = workingDirectory;
+ _portsUsedByBroker = portsUsedByBroker;
}
@Override
@@ -57,6 +62,8 @@ public class SpawnedBrokerHolder implements BrokerHolder
_process.destroy();
reapChildProcess();
+
+ waitUntilPortsAreFree();
}
@Override
@@ -74,6 +81,8 @@ public class SpawnedBrokerHolder implements BrokerHolder
}
reapChildProcess();
+
+ waitUntilPortsAreFree();
}
private void sendSigkillForImmediateShutdown(Integer pid)
@@ -146,4 +155,37 @@ public class SpawnedBrokerHolder implements BrokerHolder
}
}
+ private void waitUntilPortsAreFree()
+ {
+ new PortHelper().waitUntilPortsAreFree(_portsUsedByBroker);
+ }
+
+ @Override
+ public String dumpThreads()
+ {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ try
+ {
+ Process process = Runtime.getRuntime().exec("jstack " + _pid);
+ InputStream is = process.getInputStream();
+ byte[] buffer = new byte[1024];
+ int length = -1;
+ while ((length = is.read(buffer)) != -1)
+ {
+ baos.write(buffer, 0, length);
+ }
+ }
+ catch (Exception e)
+ {
+ LOGGER.error("Error whilst collecting thread dump for " + _pid, e);
+ }
+ return new String(baos.toByteArray());
+ }
+
+ @Override
+ public String toString()
+ {
+ return "SpawnedBrokerHolder [_pid=" + _pid + ", _portsUsedByBroker="
+ + _portsUsedByBroker + "]";
+ }
}
diff --git a/java/test-profiles/CPPExcludes b/java/test-profiles/CPPExcludes
index 1943049a7b..018ced4a68 100755
--- a/java/test-profiles/CPPExcludes
+++ b/java/test-profiles/CPPExcludes
@@ -101,11 +101,8 @@ org.apache.qpid.server.logging.subjects.*
org.apache.qpid.server.logging.actors.*
// CPP Broker does not have a JMX interface to test
-org.apache.qpid.management.jmx.*
-org.apache.qpid.server.queue.AMQQueueMBeanTest#*
-org.apache.qpid.server.exchange.ExchangeMBeanTest#*
-org.apache.qpid.server.AMQBrokerManagerMBeanTest#*
-org.apache.qpid.server.protocol.AMQProtocolSessionMBeanTest#*
+org.apache.qpid.server.jmx.mbeans.*
+org.apache.qpid.systest.management.jmx.*
// JMX is used in this test for validation
org.apache.qpid.server.queue.ModelTest#*
@@ -121,6 +118,13 @@ org.apache.qpid.test.client.message.SelectorTest#testRuntimeSelectorError
//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-3986 : Flow control invoked on total store disk usage
+org.apache.qpid.server.store.StoreOverfullTest#*
+// 0-8/0-9/0-9-1 and/or Java broker specific failover tests related to the above Producer Flow Control mechanisms
+org.apache.qpid.client.failover.FailoverBehaviourTest#testFailoverHandlerTimeoutExpires
+org.apache.qpid.client.failover.FailoverBehaviourTest#testFlowControlFlagResetOnFailover
+org.apache.qpid.client.failover.AddressBasedFailoverBehaviourTest#testFailoverHandlerTimeoutExpires
+org.apache.qpid.client.failover.AddressBasedFailoverBehaviourTest#testFlowControlFlagResetOnFailover
org.apache.qpid.test.client.RollbackOrderTest#testOrderingAfterRollbackOnMessage#*
@@ -138,6 +142,7 @@ org.apache.qpid.info.systest.InfoPluginTest#*
org.apache.qpid.info.test.*
org.apache.qpid.server.security.access.*
org.apache.qpid.server.security.access.plugins.*
+org.apache.qpid.server.security.auth.manager.*
org.apache.qpid.server.security.acl.*
org.apache.qpid.server.configuration.*
org.apache.qpid.server.configuration.plugins.*
@@ -151,9 +156,8 @@ 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#*
org.apache.qpid.server.SupportedProtocolVersionsTest#*
+org.apache.qpid.server.stats.StatisticsReportingTest#*
// QPID-3133: On 0-10, the exception listener is currently not invoked when reconnection fails to occurs.
org.apache.qpid.server.failover.FailoverMethodTest#*
@@ -177,3 +181,5 @@ org.apache.qpid.client.AsynchMessageListenerTest#testImmediatePrefetchWithMessag
org.apache.qpid.systest.disttest.*
org.apache.qpid.disttest.*
+// Exclude java broker REST API tests
+org.apache.qpid.server.management.plugin.servlet.rest.*
diff --git a/java/test-profiles/Java010Excludes b/java/test-profiles/Java010Excludes
index 90df1cee81..ca2383a8f3 100755
--- a/java/test-profiles/Java010Excludes
+++ b/java/test-profiles/Java010Excludes
@@ -54,6 +54,13 @@ org.apache.qpid.test.client.destination.AddressBasedDestinationTest#testSessionC
org.apache.qpid.test.client.timeouts.SyncWaitTimeoutDelayTest#*
org.apache.qpid.test.client.timeouts.SyncWaitDelayTest#*
+// These tests test the behaviour of 0-8..-0-9-1 specific system property qpid.failover_method_timeout
+org.apache.qpid.client.failover.FailoverBehaviourTest#testFailoverHandlerTimeoutExpires
+org.apache.qpid.client.failover.FailoverBehaviourTest#testFailoverHandlerTimeoutReconnected
+org.apache.qpid.client.failover.FailoverBehaviourTest#testFlowControlFlagResetOnFailover
+org.apache.qpid.client.failover.AddressBasedFailoverBehaviourTest#testFailoverHandlerTimeoutExpires
+org.apache.qpid.client.failover.AddressBasedFailoverBehaviourTest#testFailoverHandlerTimeoutReconnected
+org.apache.qpid.client.failover.AddressBasedFailoverBehaviourTest#testFlowControlFlagResetOnFailover
+
// QPID-3604: Immediate Prefetch no longer supported by 0-10
org.apache.qpid.client.AsynchMessageListenerTest#testImmediatePrefetchWithMessageListener
-
diff --git a/java/test-profiles/JavaExcludes b/java/test-profiles/JavaExcludes
index 9741eed2e9..618dfd8586 100644
--- a/java/test-profiles/JavaExcludes
+++ b/java/test-profiles/JavaExcludes
@@ -24,13 +24,8 @@ org.apache.qpid.client.SessionCreateTest#*
org.apache.qpid.test.client.queue.QueuePolicyTest#testRingPolicy
org.apache.qpid.test.client.queue.QueuePolicyTest#testRejectPolicy
-///////////////////////////////////////////////////////
-//Moved from JavaStandaloneExcludes when it was removed
-///////////////////////////////////////////////////////
-
-//The Java broker doesnt support client auth
-org.apache.qpid.client.ssl.SSLTest#testMultipleCertsInSingleStore
-
//QPID-3605 Durable subscriber with no-local true receives messages on re-connection
org.apache.qpid.test.unit.topic.DurableSubscriptionTest#testNoLocalMessagesNotDeliveredAfterReconnection
+//QPID-4153 Messages causing a runtime selector error should be dead-lettered (or something similar)
+org.apache.qpid.test.client.message.SelectorTest#testRuntimeSelectorError
diff --git a/java/test-profiles/JavaPre010Excludes b/java/test-profiles/JavaPre010Excludes
index 18320646ee..422764bad0 100644
--- a/java/test-profiles/JavaPre010Excludes
+++ b/java/test-profiles/JavaPre010Excludes
@@ -24,7 +24,6 @@
// These tests requires a broker capable of 0-8/0-9/0-9-1 and 0-10 concurrently
org.apache.qpid.test.client.message.JMSDestinationTest#testReceiveResend
org.apache.qpid.server.message.MessageProtocolConversionTest#*
-org.apache.qpid.server.SupportedProtocolVersionsTest#*
// The new addressing based syntax is not supported for AMQP 0-8/0-9 versions
org.apache.qpid.client.failover.AddressBasedFailoverBehaviourTest#*
@@ -38,6 +37,9 @@ org.apache.qpid.server.queue.AddressBasedSortedQueueTest#*
org.apache.qpid.test.unit.message.UTF8Test#*
org.apache.qpid.client.SynchReceiveTest#testReceiveNoWait
+// Makes explicit use of 0-10 connection object
+org.apache.qpid.client.ssl.SSLTest#testMultipleCertsInSingleStore
+
// Tests 0.10 client feature
org.apache.qpid.test.unit.client.connection.ConnectionTest#testUnsupportedSASLMechanism
@@ -66,4 +68,10 @@ org.apache.qpid.test.unit.ct.DurableSubscriberTest#testResubscribeWithChangedSel
// JCA system tests require XA support (should look to see if we can reduce scope of excludes here)
org.apache.qpid.ra.QpidRAConnectionTest#*
+org.apache.qpid.ra.QpidRAXAResourceTest#*
+
+// These tests rely on new address syntax
+org.apache.qpid.systest.management.jmx.QueueManagementTest#testGetSetAlternateExchange
+org.apache.qpid.systest.management.jmx.QueueManagementTest#testRemoveAlternateExchange
+org.apache.qpid.systest.management.jmx.QueueManagementTest#testAlternateExchangeSurvivesRestart
diff --git a/java/test-profiles/JavaTransientExcludes b/java/test-profiles/JavaTransientExcludes
index eb4c1f814d..e7b423ef34 100644
--- a/java/test-profiles/JavaTransientExcludes
+++ b/java/test-profiles/JavaTransientExcludes
@@ -30,7 +30,6 @@ org.apache.qpid.test.unit.xa.TopicTest#testMultiMessagesDurSubCrash
org.apache.qpid.test.unit.xa.TopicTest#testDurSubCrash
org.apache.qpid.test.unit.xa.TopicTest#testRecover
-
org.apache.qpid.server.store.MessageStoreTest#testMessagePersistence
org.apache.qpid.server.store.MessageStoreTest#testMessageRemoval
org.apache.qpid.server.store.MessageStoreTest#testBindingPersistence
@@ -42,4 +41,11 @@ org.apache.qpid.server.store.MessageStoreTest#testDurableExchangeRemoval
org.apache.qpid.server.store.berkeleydb.*
-org.apache.qpid.server.store.DurableConfigurationStoreTest#* \ No newline at end of file
+org.apache.qpid.server.store.DurableConfigurationStoreTest#*
+
+org.apache.qpid.systest.management.jmx.QueueManagementTest#testAlternateExchangeSurvivesRestart
+org.apache.qpid.systest.management.jmx.QueueManagementTest#testQueueDescriptionSurvivesRestart
+org.apache.qpid.systest.management.jmx.QueueManagementTest#testMoveMessageBetweenQueuesWithBrokerRestart
+org.apache.qpid.systest.management.jmx.QueueManagementTest#testCopyMessageBetweenQueuesWithBrokerRestart
+
+org.apache.qpid.test.unit.client.MaxDeliveryCountTest#testWhenBrokerIsRestartedAfterEnqeuingMessages
diff --git a/java/test-profiles/java-bdb-spawn.0-10.testprofile b/java/test-profiles/java-bdb-spawn.0-10.testprofile
index 2cef1fd53e..35991645d8 100644
--- a/java/test-profiles/java-bdb-spawn.0-10.testprofile
+++ b/java/test-profiles/java-bdb-spawn.0-10.testprofile
@@ -19,11 +19,12 @@
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.command=build/bin/qpid-server -p @PORT -m @MPORT @EXCLUDES @INCLUDES -c @CONFIG_FILE -l @LOG_CONFIG_FILE
broker.ready=BRK-1004
broker.stopped=Exception
+broker.protocol.excludes=--exclude-1-0 @PORT --exclude-1-0 @SSL_PORT
broker.config=build/etc/config-systests-bdb.xml
-messagestorefactory.class.name=org.apache.qpid.server.store.berkeleydb.BDBMessageStoreFactory
+messagestore.class.name=org.apache.qpid.server.store.berkeleydb.BDBMessageStore
profile.excludes=JavaExcludes JavaPersistentExcludes Java010Excludes JavaBDBExcludes
broker.clean.between.tests=true
broker.persistent=true
diff --git a/java/test-profiles/java-bdb-spawn.0-8.testprofile b/java/test-profiles/java-bdb-spawn.0-8.testprofile
index 62c9385835..a4b74748e6 100644
--- a/java/test-profiles/java-bdb-spawn.0-8.testprofile
+++ b/java/test-profiles/java-bdb-spawn.0-8.testprofile
@@ -19,11 +19,11 @@
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.command=build/bin/qpid-server -p @PORT -m @MPORT @EXCLUDES @INCLUDES -c @CONFIG_FILE -l @LOG_CONFIG_FILE
broker.ready=BRK-1004
broker.stopped=Exception
broker.config=build/etc/config-systests-bdb.xml
-messagestorefactory.class.name=org.apache.qpid.server.store.berkeleydb.BDBMessageStoreFactory
+messagestore.class.name=org.apache.qpid.server.store.berkeleydb.BDBMessageStore
profile.excludes=JavaExcludes JavaPersistentExcludes XAExcludes JavaPre010Excludes JavaBDBExcludes
broker.clean.between.tests=true
broker.persistent=true
diff --git a/java/test-profiles/java-bdb-spawn.0-9-1.testprofile b/java/test-profiles/java-bdb-spawn.0-9-1.testprofile
index cfc2a12dde..9cd70a4ea7 100644
--- a/java/test-profiles/java-bdb-spawn.0-9-1.testprofile
+++ b/java/test-profiles/java-bdb-spawn.0-9-1.testprofile
@@ -19,11 +19,11 @@
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.command=build/bin/qpid-server -p @PORT -m @MPORT @EXCLUDES @INCLUDES -c @CONFIG_FILE -l @LOG_CONFIG_FILE
broker.ready=BRK-1004
broker.stopped=Exception
broker.config=build/etc/config-systests-bdb.xml
-messagestorefactory.class.name=org.apache.qpid.server.store.berkeleydb.BDBMessageStoreFactory
+messagestore.class.name=org.apache.qpid.server.store.berkeleydb.BDBMessageStore
profile.excludes=JavaExcludes JavaPersistentExcludes XAExcludes JavaPre010Excludes JavaBDBExcludes
broker.clean.between.tests=true
broker.persistent=true
diff --git a/java/test-profiles/java-bdb-spawn.0-9.testprofile b/java/test-profiles/java-bdb-spawn.0-9.testprofile
index 9cfa25eb9a..5c0ad2baf3 100644
--- a/java/test-profiles/java-bdb-spawn.0-9.testprofile
+++ b/java/test-profiles/java-bdb-spawn.0-9.testprofile
@@ -19,11 +19,11 @@
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.command=build/bin/qpid-server -p @PORT -m @MPORT @EXCLUDES @INCLUDES -c @CONFIG_FILE -l @LOG_CONFIG_FILE
broker.ready=BRK-1004
broker.stopped=Exception
broker.config=build/etc/config-systests-bdb.xml
-messagestorefactory.class.name=org.apache.qpid.server.store.berkeleydb.BDBMessageStoreFactory
+messagestore.class.name=org.apache.qpid.server.store.berkeleydb.BDBMessageStore
profile.excludes=JavaExcludes JavaPersistentExcludes XAExcludes JavaPre010Excludes JavaBDBExcludes
broker.clean.between.tests=true
broker.persistent=true
diff --git a/java/test-profiles/java-bdb.0-10.testprofile b/java/test-profiles/java-bdb.0-10.testprofile
index 4ac4c3baf2..892188aa24 100644
--- a/java/test-profiles/java-bdb.0-10.testprofile
+++ b/java/test-profiles/java-bdb.0-10.testprofile
@@ -20,11 +20,12 @@
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.command=build/bin/qpid-server -p @PORT -m @MPORT @EXCLUDES @INCLUDES -c @CONFIG_FILE -l @LOG_CONFIG_FILE
broker.ready=BRK-1004
broker.stopped=Exception
+broker.protocol.excludes=--exclude-1-0 @PORT --exclude-1-0 @SSL_PORT
broker.config=build/etc/config-systests-bdb.xml
-messagestorefactory.class.name=org.apache.qpid.server.store.berkeleydb.BDBMessageStoreFactory
+messagestore.class.name=org.apache.qpid.server.store.berkeleydb.BDBMessageStore
profile.excludes=JavaExcludes JavaPersistentExcludes Java010Excludes JavaBDBExcludes
broker.clean.between.tests=true
broker.persistent=true
diff --git a/java/test-profiles/java-bdb.0-8.testprofile b/java/test-profiles/java-bdb.0-8.testprofile
index 76c3ea0b72..87eea96dda 100644
--- a/java/test-profiles/java-bdb.0-8.testprofile
+++ b/java/test-profiles/java-bdb.0-8.testprofile
@@ -1,4 +1,4 @@
-#
+:
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
@@ -20,11 +20,11 @@
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.command=build/bin/qpid-server -p @PORT -m @MPORT @EXCLUDES @INCLUDES -c @CONFIG_FILE -l @LOG_CONFIG_FILE
broker.ready=BRK-1004
broker.stopped=Exception
broker.config=build/etc/config-systests-bdb.xml
-messagestorefactory.class.name=org.apache.qpid.server.store.berkeleydb.BDBMessageStoreFactory
+messagestore.class.name=org.apache.qpid.server.store.berkeleydb.BDBMessageStore
profile.excludes=JavaExcludes JavaPersistentExcludes XAExcludes JavaPre010Excludes JavaBDBExcludes
broker.clean.between.tests=true
broker.persistent=true
diff --git a/java/test-profiles/java-bdb.0-9-1.testprofile b/java/test-profiles/java-bdb.0-9-1.testprofile
index afc5f7bfd1..1339dc1dc7 100644
--- a/java/test-profiles/java-bdb.0-9-1.testprofile
+++ b/java/test-profiles/java-bdb.0-9-1.testprofile
@@ -20,11 +20,11 @@
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.command=build/bin/qpid-server -p @PORT -m @MPORT @EXCLUDES @INCLUDES -c @CONFIG_FILE -l @LOG_CONFIG_FILE
broker.ready=BRK-1004
broker.stopped=Exception
broker.config=build/etc/config-systests-bdb.xml
-messagestorefactory.class.name=org.apache.qpid.server.store.berkeleydb.BDBMessageStoreFactory
+messagestore.class.name=org.apache.qpid.server.store.berkeleydb.BDBMessageStore
profile.excludes=JavaExcludes JavaPersistentExcludes XAExcludes JavaPre010Excludes JavaBDBExcludes
broker.clean.between.tests=true
broker.persistent=true
diff --git a/java/test-profiles/java-bdb.0-9.testprofile b/java/test-profiles/java-bdb.0-9.testprofile
index 76bde0defc..c097d53c85 100644
--- a/java/test-profiles/java-bdb.0-9.testprofile
+++ b/java/test-profiles/java-bdb.0-9.testprofile
@@ -20,11 +20,11 @@
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.command=build/bin/qpid-server -p @PORT -m @MPORT @EXCLUDES @INCLUDES -c @CONFIG_FILE -l @LOG_CONFIG_FILE
broker.ready=BRK-1004
broker.stopped=Exception
broker.config=build/etc/config-systests-bdb.xml
-messagestorefactory.class.name=org.apache.qpid.server.store.berkeleydb.BDBMessageStoreFactory
+messagestore.class.name=org.apache.qpid.server.store.berkeleydb.BDBMessageStore
profile.excludes=JavaExcludes JavaPersistentExcludes XAExcludes JavaPre010Excludes JavaBDBExcludes
broker.clean.between.tests=true
broker.persistent=true
diff --git a/java/broker-plugins/experimental/shutdown/src/main/java/shutdown.bnd b/java/test-profiles/java-dby-mem.0-10.testprofile
index 60af4b89e8..33f9527c86 100755..100644
--- a/java/broker-plugins/experimental/shutdown/src/main/java/shutdown.bnd
+++ b/java/test-profiles/java-dby-mem.0-10.testprofile
@@ -16,10 +16,16 @@
# specific language governing permissions and limitations
# under the License.
#
-
-ver: 0.17.0
-
-Bundle-SymbolicName: qpid-shutdown-plugin
-Bundle-Version: ${ver}
-Export-Package: *;version=${ver}
-Bundle-RequiredExecutionEnvironment: J2SE-1.5
+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 @EXCLUDES @INCLUDES -c @CONFIG_FILE -l @LOG_CONFIG_FILE
+broker.ready=BRK-1004
+broker.stopped=Exception
+broker.protocol.excludes=--exclude-1-0 @PORT --exclude-1-0 @SSL_PORT
+broker.config=build/etc/config-systests-derby-mem.xml
+messagestorefactory.class.name=org.apache.qpid.server.store.derby.DerbyMessageStoreFactory
+profile.excludes=JavaPersistentExcludes JavaDerbyExcludes Java010Excludes
+broker.clean.between.tests=true
+broker.persistent=true
diff --git a/java/test-profiles/java-dby-mem.0-8.testprofile b/java/test-profiles/java-dby-mem.0-8.testprofile
new file mode 100644
index 0000000000..89bad84769
--- /dev/null
+++ b/java/test-profiles/java-dby-mem.0-8.testprofile
@@ -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.
+#
+broker.version=v0_8
+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 @INCLUDES -c @CONFIG_FILE -l @LOG_CONFIG_FILE
+broker.ready=BRK-1004
+broker.stopped=Exception
+broker.config=build/etc/config-systests-derby-mem.xml
+broker.protocol.excludes=--exclude-0-10 @PORT --exclude-0-10 @SSL_PORT --exclude-1-0 @PORT --exclude-1-0 @SSL_PORT --exclude-0-9-1 @PORT --exclude-0-9-1 @SSL_PORT --exclude-0-9 @PORT --exclude-0-9 @SSL_PORT
+messagestorefactory.class.name=org.apache.qpid.server.store.derby.DerbyMessageStoreFactory
+profile.excludes=JavaPersistentExcludes JavaDerbyExcludes XAExcludes 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-8
+
diff --git a/java/test-profiles/java-dby-mem.0-9-1.testprofile b/java/test-profiles/java-dby-mem.0-9-1.testprofile
new file mode 100644
index 0000000000..8deea281a4
--- /dev/null
+++ b/java/test-profiles/java-dby-mem.0-9-1.testprofile
@@ -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.
+#
+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 @INCLUDES -c @CONFIG_FILE -l @LOG_CONFIG_FILE
+broker.ready=BRK-1004
+broker.stopped=Exception
+broker.config=build/etc/config-systests-derby-mem.xml
+broker.protocol.excludes=--exclude-0-10 @PORT --exclude-0-10 @SSL_PORT --exclude-1-0 @PORT --exclude-1-0 @SSL_PORT
+messagestorefactory.class.name=org.apache.qpid.server.store.derby.DerbyMessageStoreFactory
+profile.excludes=JavaPersistentExcludes JavaDerbyExcludes XAExcludes 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-mem.0-9.testprofile b/java/test-profiles/java-dby-mem.0-9.testprofile
new file mode 100644
index 0000000000..b691a7d153
--- /dev/null
+++ b/java/test-profiles/java-dby-mem.0-9.testprofile
@@ -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.
+#
+broker.version=v0_9
+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 @INCLUDES -c @CONFIG_FILE -l @LOG_CONFIG_FILE
+broker.ready=BRK-1004
+broker.stopped=Exception
+broker.config=build/etc/config-systests-derby-mem.xml
+broker.protocol.excludes=--exclude-0-10 @PORT --exclude-0-10 @SSL_PORT --exclude-1-0 @PORT --exclude-1-0 @SSL_PORT --exclude-0-9-1 @PORT --exclude-0-9-1 @SSL_PORT
+messagestorefactory.class.name=org.apache.qpid.server.store.derby.DerbyMessageStoreFactory
+profile.excludes=JavaPersistentExcludes JavaDerbyExcludes XAExcludes 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-9
+
diff --git a/java/test-profiles/java-dby-spawn.0-10.testprofile b/java/test-profiles/java-dby-spawn.0-10.testprofile
index 3b57dca346..e2e2b44dae 100644
--- a/java/test-profiles/java-dby-spawn.0-10.testprofile
+++ b/java/test-profiles/java-dby-spawn.0-10.testprofile
@@ -19,11 +19,12 @@
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.command=build/bin/qpid-server -p @PORT -m @MPORT @EXCLUDES @INCLUDES -c @CONFIG_FILE -l @LOG_CONFIG_FILE
broker.ready=BRK-1004
broker.stopped=Exception
+broker.protocol.excludes=--exclude-1-0 @PORT --exclude-1-0 @SSL_PORT
broker.config=build/etc/config-systests-derby.xml
-messagestorefactory.class.name=org.apache.qpid.server.store.derby.DerbyMessageStoreFactory
+messagestore.class.name=org.apache.qpid.server.store.derby.DerbyMessageStore
profile.excludes=JavaPersistentExcludes JavaDerbyExcludes Java010Excludes
broker.clean.between.tests=true
broker.persistent=true
diff --git a/java/test-profiles/java-dby-spawn.0-8.testprofile b/java/test-profiles/java-dby-spawn.0-8.testprofile
index 9d421f706e..3f609226e3 100644
--- a/java/test-profiles/java-dby-spawn.0-8.testprofile
+++ b/java/test-profiles/java-dby-spawn.0-8.testprofile
@@ -19,12 +19,12 @@
broker.version=v0_8
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.command=build/bin/qpid-server -p @PORT -m @MPORT @EXCLUDES @INCLUDES -c @CONFIG_FILE -l @LOG_CONFIG_FILE
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 --exclude-1-0 @PORT --exclude-1-0 @SSL_PORT --exclude-0-9-1 @PORT --exclude-0-9-1 @SSL_PORT --exclude-0-9 @PORT --exclude-0-9 @SSL_PORT
-messagestorefactory.class.name=org.apache.qpid.server.store.derby.DerbyMessageStoreFactory
+messagestore.class.name=org.apache.qpid.server.store.derby.DerbyMessageStore
profile.excludes=JavaPersistentExcludes JavaDerbyExcludes XAExcludes JavaPre010Excludes
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
index 3038dd324e..80d40458fd 100644
--- a/java/test-profiles/java-dby-spawn.0-9-1.testprofile
+++ b/java/test-profiles/java-dby-spawn.0-9-1.testprofile
@@ -19,12 +19,12 @@
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.command=build/bin/qpid-server -p @PORT -m @MPORT @EXCLUDES @INCLUDES -c @CONFIG_FILE -l @LOG_CONFIG_FILE
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 --exclude-1-0 @PORT --exclude-1-0 @SSL_PORT
-messagestorefactory.class.name=org.apache.qpid.server.store.derby.DerbyMessageStoreFactory
+messagestore.class.name=org.apache.qpid.server.store.derby.DerbyMessageStore
profile.excludes=JavaPersistentExcludes JavaDerbyExcludes XAExcludes JavaPre010Excludes
broker.clean.between.tests=true
broker.persistent=true
diff --git a/java/test-profiles/java-dby-spawn.0-9.testprofile b/java/test-profiles/java-dby-spawn.0-9.testprofile
index 6007105097..122eccdca1 100644
--- a/java/test-profiles/java-dby-spawn.0-9.testprofile
+++ b/java/test-profiles/java-dby-spawn.0-9.testprofile
@@ -19,12 +19,12 @@
broker.version=v0_9
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.command=build/bin/qpid-server -p @PORT -m @MPORT @EXCLUDES @INCLUDES -c @CONFIG_FILE -l @LOG_CONFIG_FILE
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 --exclude-1-0 @PORT --exclude-1-0 @SSL_PORT --exclude-0-9-1 @PORT --exclude-0-9-1 @SSL_PORT
-messagestorefactory.class.name=org.apache.qpid.server.store.derby.DerbyMessageStoreFactory
+messagestore.class.name=org.apache.qpid.server.store.derby.DerbyMessageStore
profile.excludes=JavaPersistentExcludes JavaDerbyExcludes XAExcludes JavaPre010Excludes
broker.clean.between.tests=true
broker.persistent=true
diff --git a/java/test-profiles/java-dby.0-10.testprofile b/java/test-profiles/java-dby.0-10.testprofile
index 51f6c4ca6f..d3b03054de 100644
--- a/java/test-profiles/java-dby.0-10.testprofile
+++ b/java/test-profiles/java-dby.0-10.testprofile
@@ -20,11 +20,12 @@ 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.command=build/bin/qpid-server -p @PORT -m @MPORT @EXCLUDES @INCLUDES -c @CONFIG_FILE -l @LOG_CONFIG_FILE
broker.ready=BRK-1004
broker.stopped=Exception
+broker.protocol.excludes=--exclude-1-0 @PORT --exclude-1-0 @SSL_PORT
broker.config=build/etc/config-systests-derby.xml
-messagestorefactory.class.name=org.apache.qpid.server.store.derby.DerbyMessageStoreFactory
+messagestore.class.name=org.apache.qpid.server.store.derby.DerbyMessageStore
profile.excludes=JavaPersistentExcludes JavaDerbyExcludes Java010Excludes
broker.clean.between.tests=true
broker.persistent=true
diff --git a/java/test-profiles/java-dby.0-8.testprofile b/java/test-profiles/java-dby.0-8.testprofile
index c841c69922..51580e6c7a 100644
--- a/java/test-profiles/java-dby.0-8.testprofile
+++ b/java/test-profiles/java-dby.0-8.testprofile
@@ -20,12 +20,12 @@ broker.version=v0_8
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.command=build/bin/qpid-server -p @PORT -m @MPORT @EXCLUDES @INCLUDES -c @CONFIG_FILE -l @LOG_CONFIG_FILE
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 --exclude-1-0 @PORT --exclude-1-0 @SSL_PORT --exclude-0-9-1 @PORT --exclude-0-9-1 @SSL_PORT --exclude-0-9 @PORT --exclude-0-9 @SSL_PORT
-messagestorefactory.class.name=org.apache.qpid.server.store.derby.DerbyMessageStoreFactory
+messagestore.class.name=org.apache.qpid.server.store.derby.DerbyMessageStore
profile.excludes=JavaPersistentExcludes JavaDerbyExcludes XAExcludes JavaPre010Excludes
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
index fa01010d52..b92397eae7 100644
--- a/java/test-profiles/java-dby.0-9-1.testprofile
+++ b/java/test-profiles/java-dby.0-9-1.testprofile
@@ -20,12 +20,12 @@ 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.command=build/bin/qpid-server -p @PORT -m @MPORT @EXCLUDES @INCLUDES -c @CONFIG_FILE -l @LOG_CONFIG_FILE
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 --exclude-1-0 @PORT --exclude-1-0 @SSL_PORT
-messagestorefactory.class.name=org.apache.qpid.server.store.derby.DerbyMessageStoreFactory
+messagestore.class.name=org.apache.qpid.server.store.derby.DerbyMessageStore
profile.excludes=JavaPersistentExcludes JavaDerbyExcludes XAExcludes JavaPre010Excludes
broker.clean.between.tests=true
broker.persistent=true
diff --git a/java/test-profiles/java-dby.0-9.testprofile b/java/test-profiles/java-dby.0-9.testprofile
index d343185591..17363b7e47 100644
--- a/java/test-profiles/java-dby.0-9.testprofile
+++ b/java/test-profiles/java-dby.0-9.testprofile
@@ -20,12 +20,12 @@ broker.version=v0_9
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.command=build/bin/qpid-server -p @PORT -m @MPORT @EXCLUDES @INCLUDES -c @CONFIG_FILE -l @LOG_CONFIG_FILE
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 --exclude-1-0 @PORT --exclude-1-0 @SSL_PORT --exclude-0-9-1 @PORT --exclude-0-9-1 @SSL_PORT
-messagestorefactory.class.name=org.apache.qpid.server.store.derby.DerbyMessageStoreFactory
+messagestore.class.name=org.apache.qpid.server.store.derby.DerbyMessageStore
profile.excludes=JavaPersistentExcludes JavaDerbyExcludes XAExcludes JavaPre010Excludes
broker.clean.between.tests=true
broker.persistent=true
diff --git a/java/test-profiles/java-mms-spawn.0-10.testprofile b/java/test-profiles/java-mms-spawn.0-10.testprofile
index 5e5d2e8a6b..57af5c4a41 100644
--- a/java/test-profiles/java-mms-spawn.0-10.testprofile
+++ b/java/test-profiles/java-mms-spawn.0-10.testprofile
@@ -19,9 +19,10 @@
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.command=build/bin/qpid-server -p @PORT -m @MPORT @EXCLUDES @INCLUDES -c @CONFIG_FILE -l @LOG_CONFIG_FILE
broker.ready=BRK-1004
broker.stopped=Exception
+broker.protocol.excludes=--exclude-1-0 @PORT --exclude-1-0 @SSL_PORT
#
# Do not enable. Allow client to attempt 0-10 and negotiate downwards
#
diff --git a/java/test-profiles/java-mms-spawn.0-8.testprofile b/java/test-profiles/java-mms-spawn.0-8.testprofile
index 1b6b6f28a3..24f088e0c5 100644
--- a/java/test-profiles/java-mms-spawn.0-8.testprofile
+++ b/java/test-profiles/java-mms-spawn.0-8.testprofile
@@ -19,7 +19,7 @@
broker.version=v0_8
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.command=build/bin/qpid-server -p @PORT -m @MPORT @EXCLUDES @INCLUDES -c @CONFIG_FILE -l @LOG_CONFIG_FILE
broker.ready=BRK-1004
broker.stopped=Exception
broker.protocol.excludes=--exclude-0-10 @PORT --exclude-0-10 @SSL_PORT --exclude-1-0 @PORT --exclude-1-0 @SSL_PORT --exclude-0-9-1 @PORT --exclude-0-9-1 @SSL_PORT --exclude-0-9 @PORT --exclude-0-9 @SSL_PORT
diff --git a/java/test-profiles/java-mms-spawn.0-9-1.testprofile b/java/test-profiles/java-mms-spawn.0-9-1.testprofile
index e87ae2b204..c1f6d10675 100644
--- a/java/test-profiles/java-mms-spawn.0-9-1.testprofile
+++ b/java/test-profiles/java-mms-spawn.0-9-1.testprofile
@@ -19,7 +19,7 @@
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.command=build/bin/qpid-server -p @PORT -m @MPORT @EXCLUDES @INCLUDES -c @CONFIG_FILE -l @LOG_CONFIG_FILE
broker.ready=BRK-1004
broker.stopped=Exception
broker.protocol.excludes=--exclude-0-10 @PORT --exclude-0-10 @SSL_PORT --exclude-1-0 @PORT --exclude-1-0 @SSL_PORT
diff --git a/java/test-profiles/java-mms-spawn.0-9.testprofile b/java/test-profiles/java-mms-spawn.0-9.testprofile
index 2a9430242e..421ae7476e 100644
--- a/java/test-profiles/java-mms-spawn.0-9.testprofile
+++ b/java/test-profiles/java-mms-spawn.0-9.testprofile
@@ -19,7 +19,7 @@
broker.version=v0_9
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.command=build/bin/qpid-server -p @PORT -m @MPORT @EXCLUDES @INCLUDES -c @CONFIG_FILE -l @LOG_CONFIG_FILE
broker.ready=BRK-1004
broker.stopped=Exception
broker.protocol.excludes=--exclude-0-10 @PORT --exclude-0-10 @SSL_PORT --exclude-1-0 @PORT --exclude-1-0 @SSL_PORT --exclude-0-9-1 @PORT --exclude-0-9-1 @SSL_PORT
diff --git a/java/test-profiles/java-mms.0-10.testprofile b/java/test-profiles/java-mms.0-10.testprofile
index 209d384422..6dd40cff47 100644
--- a/java/test-profiles/java-mms.0-10.testprofile
+++ b/java/test-profiles/java-mms.0-10.testprofile
@@ -20,8 +20,9 @@ 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.command=build/bin/qpid-server -p @PORT -m @MPORT @EXCLUDES @INCLUDES -c @CONFIG_FILE -l @LOG_CONFIG_FILE
broker.ready=BRK-1004
broker.stopped=Exception
+broker.protocol.excludes=--exclude-1-0 @PORT --exclude-1-0 @SSL_PORT
profile.excludes=JavaTransientExcludes Java010Excludes
diff --git a/java/test-profiles/java-mms.0-8.testprofile b/java/test-profiles/java-mms.0-8.testprofile
index 1f02a49b28..f82bf8c473 100644
--- a/java/test-profiles/java-mms.0-8.testprofile
+++ b/java/test-profiles/java-mms.0-8.testprofile
@@ -20,7 +20,7 @@ broker.language=java
broker.version=v0_8
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.command=build/bin/qpid-server -p @PORT -m @MPORT @EXCLUDES @INCLUDES -c @CONFIG_FILE -l @LOG_CONFIG_FILE
broker.ready=BRK-1004
broker.stopped=Exception
broker.protocol.excludes=--exclude-0-10 @PORT --exclude-0-10 @SSL_PORT --exclude-1-0 @PORT --exclude-1-0 @SSL_PORT --exclude-0-9-1 @PORT --exclude-0-9-1 @SSL_PORT --exclude-0-9 @PORT --exclude-0-9 @SSL_PORT
diff --git a/java/test-profiles/java-mms.0-9-1.testprofile b/java/test-profiles/java-mms.0-9-1.testprofile
index ae707f025d..9b8baaa5a3 100644
--- a/java/test-profiles/java-mms.0-9-1.testprofile
+++ b/java/test-profiles/java-mms.0-9-1.testprofile
@@ -20,7 +20,7 @@ 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.command=build/bin/qpid-server -p @PORT -m @MPORT @EXCLUDES @INCLUDES -c @CONFIG_FILE -l @LOG_CONFIG_FILE
broker.ready=BRK-1004
broker.stopped=Exception
broker.protocol.excludes=--exclude-0-10 @PORT --exclude-0-10 @SSL_PORT --exclude-1-0 @PORT --exclude-1-0 @SSL_PORT
diff --git a/java/test-profiles/java-mms.0-9.testprofile b/java/test-profiles/java-mms.0-9.testprofile
index 8f372299ea..56ace6d9e1 100644
--- a/java/test-profiles/java-mms.0-9.testprofile
+++ b/java/test-profiles/java-mms.0-9.testprofile
@@ -20,7 +20,7 @@ broker.language=java
broker.version=v0_9
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.command=build/bin/qpid-server -p @PORT -m @MPORT @EXCLUDES @INCLUDES -c @CONFIG_FILE -l @LOG_CONFIG_FILE
broker.ready=BRK-1004
broker.stopped=Exception
broker.protocol.excludes=--exclude-0-10 @PORT --exclude-0-10 @SSL_PORT --exclude-1-0 @PORT --exclude-1-0 @SSL_PORT --exclude-0-9-1 @PORT --exclude-0-9-1 @SSL_PORT
diff --git a/java/test-profiles/log4j-test.xml b/java/test-profiles/log4j-test.xml
index 062acaaac9..a393fa0952 100644
--- a/java/test-profiles/log4j-test.xml
+++ b/java/test-profiles/log4j-test.xml
@@ -30,6 +30,7 @@
<appender name="console" class="org.apache.log4j.ConsoleAppender">
<param name="Target" value="System.out"/>
<param name="ImmediateFlush" value="true"/>
+ <param name="Follow" value="true"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%t %d %p [%c{4}] %m%n"/>
</layout>
diff --git a/java/test-profiles/python_tests/Java010PythonExcludes b/java/test-profiles/python_tests/Java010PythonExcludes
index 13f9d5484e..d3c058a2e9 100644
--- a/java/test-profiles/python_tests/Java010PythonExcludes
+++ b/java/test-profiles/python_tests/Java010PythonExcludes
@@ -21,6 +21,7 @@
#The broker does not have the appropriate QMF support
qpid_tests.broker_0_10.management.*
+qpid_tests.broker_0_10.qmf_events.*
qpid_tests.broker_0_10.stats.BrokerStatsTests.*
qpid_tests.broker_0_10.msg_groups.MultiConsumerMsgGroupTests.test_default_group_id
qpid_tests.broker_0_10.msg_groups.MultiConsumerMsgGroupTests.test_move_*
diff --git a/java/test-profiles/python_tests/JavaPre010PythonExcludes b/java/test-profiles/python_tests/JavaPre010PythonExcludes
new file mode 100644
index 0000000000..049b46b1d8
--- /dev/null
+++ b/java/test-profiles/python_tests/JavaPre010PythonExcludes
@@ -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.
+#
+
+qpid_tests.broker_0_8.queue.QueueTests.test_declare_exclusive
+qpid_tests.broker_0_8.queue.QueueTests.test_delete_simple
+qpid_tests.broker_0_8.queue.QueueTests.test_purge
+qpid_tests.broker_0_8.tx.TxTests.test_auto_rollback
+qpid_tests.broker_0_8.tx.TxTests.test_rollback
+
+qpid_tests.broker_0_9.query.QueryTests.test_binding_query_direct
+qpid_tests.broker_0_9.query.QueryTests.test_binding_query_fanout
+qpid_tests.broker_0_9.query.QueryTests.test_binding_query_header
+qpid_tests.broker_0_9.query.QueryTests.test_binding_query_topic
+qpid_tests.broker_0_9.query.QueryTests.test_exchange_query
+
+# QPID-3987 Tests broker_0_9.queue.QueueTests.test_unbind_fanout and broker_0_9.queue.QueueTests.test_unbind_headers fail with 404, 'No such binding'
+qpid_tests.broker_0_9.queue.QueueTests.test_unbind_fanout
+qpid_tests.broker_0_9.queue.QueueTests.test_unbind_headers
diff --git a/java/test-profiles/test_resources/ssl/java_broker_keystore.jks b/java/test-profiles/test_resources/ssl/java_broker_keystore.jks
index 38a9a269a5..29ae3a8e67 100644
--- a/java/test-profiles/test_resources/ssl/java_broker_keystore.jks
+++ b/java/test-profiles/test_resources/ssl/java_broker_keystore.jks
Binary files differ
diff --git a/java/test-profiles/testprofile.defaults b/java/test-profiles/testprofile.defaults
index 2c3c92e922..47992b9334 100644
--- a/java/test-profiles/testprofile.defaults
+++ b/java/test-profiles/testprofile.defaults
@@ -21,7 +21,7 @@ java.naming.provider.url=${test.profiles}/test-provider.properties
broker.ready=Listening on TCP
broker.config=build/etc/config-systests.xml
-messagestorefactory.class.name=org.apache.qpid.server.store.MemoryMessageStoreFactory
+messagestore.class.name=org.apache.qpid.server.store.MemoryMessageStore
broker.protocol.excludes=
broker.persistent=false
@@ -33,7 +33,7 @@ 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.configuration=test-profiles/log4j-test.xml
log4j.debug=false
# Note test-provider.properties also has variables of same name.
diff --git a/java/tools/bin/Profile-run-from-source b/java/tools/bin/Profile-run-from-source
index f8ec45ccff..179c365450 100755
--- a/java/tools/bin/Profile-run-from-source
+++ b/java/tools/bin/Profile-run-from-source
@@ -49,7 +49,7 @@ export LOG_CONFIG="-Dlog4j.configuration=file:///$QPID_CHECKOUT/java/tools/etc/t
#------------- Required for qpid-python-testkit -----------------------------------------
-PYTHONPATH=$QPID_CHECKOUT/python/qpid:$QPID_CHECKOUT/cpp/src/test/brokertest.py:$PYTHONPATH
+PYTHONPATH=$QPID_CHECKOUT/python:$QPID_CHECKOUT/cpp/src/test/brokertest.py:$PYTHONPATH
export PATH=$QPID_CHECKOUT/python:$PATH
if [ -x $QPID_CHECKOUT/cpp/src/qpidd ]; then
diff --git a/java/tools/bin/mercury-controller b/java/tools/bin/mercury-controller
index fab8614039..fab8614039 100644..100755
--- a/java/tools/bin/mercury-controller
+++ b/java/tools/bin/mercury-controller
diff --git a/java/tools/bin/mercury-start-consumers b/java/tools/bin/mercury-start-consumers
index c71fc0c21f..c71fc0c21f 100644..100755
--- a/java/tools/bin/mercury-start-consumers
+++ b/java/tools/bin/mercury-start-consumers
diff --git a/java/tools/bin/mercury-start-producers b/java/tools/bin/mercury-start-producers
index 7ba0286f7c..7ba0286f7c 100644..100755
--- a/java/tools/bin/mercury-start-producers
+++ b/java/tools/bin/mercury-start-producers
diff --git a/java/tools/bin/qpid-jms-benchmark b/java/tools/bin/qpid-jms-benchmark
new file mode 100755
index 0000000000..3d712a27dc
--- /dev/null
+++ b/java/tools/bin/qpid-jms-benchmark
@@ -0,0 +1,316 @@
+#!/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 optparse, time, qpid.messaging, re
+from threading import Thread
+from subprocess import Popen, PIPE, STDOUT
+
+op = optparse.OptionParser(usage="usage: %prog [options]",
+ description="simple performance benchmarks")
+op.add_option("-b", "--broker", default=[], action="append", type="str",
+ help="url of broker(s) to connect to, round robin on multiple brokers")
+op.add_option("-c", "--client-host", default=[], action="append", type="str",
+ help="host(s) to run clients on via ssh, round robin on mulple hosts")
+op.add_option("-q", "--queues", default=1, type="int", metavar="N",
+ help="create N queues (default %default)")
+op.add_option("-s", "--senders", default=1, type="int", metavar="N",
+ help="start N senders per queue (default %default)")
+op.add_option("-r", "--receivers", default=1, type="int", metavar="N",
+ help="start N receivers per queue (default %default)")
+op.add_option("-m", "--messages", default=100000, type="int", metavar="N",
+ help="send N messages per sender (default %default)")
+op.add_option("--queue-name", default="benchmark", metavar="NAME",
+ help="base name for queues (default %default)")
+op.add_option("--send-rate", default=0, metavar="N",
+ help="send rate limited to N messages/second, 0 means no limit (default %default)")
+op.add_option("--receive-rate", default=0, metavar="N",
+ help="receive rate limited to N messages/second, 0 means no limit (default %default)")
+op.add_option("--content-size", default=1024, type="int", metavar="BYTES",
+ help="message size in bytes (default %default)")
+op.add_option("--ack-frequency", default=100, metavar="N", type="int",
+ help="receiver ack's every N messages, 0 means unconfirmed (default %default)")
+op.add_option("--no-report-header", dest="report_header", default=True,
+ action="store_false", help="don't print header on report")
+op.add_option("--summarize", default=False, action="store_true",
+ help="print summary statistics for multiple senders/receivers: total throughput, average latency")
+op.add_option("--repeat", default=1, metavar="N", help="repeat N times", type="int")
+op.add_option("--send-option", default=[], action="append", type="str",
+ help="Additional option for sending addresses")
+op.add_option("--receive-option", default=[], action="append", type="str",
+ help="Additional option for receiving addresses")
+op.add_option("--create-option", default=[], action="append", type="str",
+ help="Additional option for creating addresses")
+op.add_option("--send-arg", default=[], action="append", type="str",
+ help="Additional argument for qpid-send")
+op.add_option("--receive-arg", default=[], action="append", type="str",
+ help="Additional argument for qpid-receive")
+op.add_option("--no-timestamp", dest="timestamp", default=True,
+ action="store_false", help="don't add a timestamp, no latency results")
+op.add_option("--sequence", dest="sequence", default=False,
+ action="store_true", help="add a sequence number to each message")
+op.add_option("--connection-options", type="str",
+ help="Connection options for senders & receivers")
+op.add_option("--durable", default=False, action="store_true",
+ help="Use durable queues and messages")
+op.add_option("--save-received", default=False, action="store_true",
+ help="Save received message content to files <queuename>-receiver-<n>.msg")
+op.add_option("--verbose", default=False, action="store_true",
+ help="Show commands executed")
+op.add_option("--no-delete", default=False, action="store_true",
+ help="Don't delete the test queues.")
+op.add_option("--fill-drain", default=False, action="store_true",
+ help="First fill the queues, then drain them")
+
+single_quote_re = re.compile("'")
+def posix_quote(string):
+ """ Quote a string for use as an argument in a posix shell"""
+ return "'" + single_quote_re.sub("\\'", string) + "'";
+
+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
+
+class PopenCommand(Popen):
+ """Like Popen but you can query for the command"""
+ def __init__(self, command, *args, **kwargs):
+ self.command = command
+ Popen.__init__(self, command, *args, **kwargs)
+
+clients = Clients()
+
+def start_receive(queue, index, opts, ready_queue, broker, host):
+ address_opts=opts.receive_option
+ if opts.durable: address_opts += ["node:{durable:true}"]
+ address="%s;{%s}"%(queue,",".join(address_opts))
+ msg_total=opts.senders*opts.messages
+ messages = msg_total/opts.receivers;
+ if (index < msg_total%opts.receivers): messages += 1
+ if (messages == 0): return None
+ command = ["qpid-jms-receive",
+ #"-b", broker,
+ "--ready-address", "benchmark-ready;{create:always}",
+ "-a", address,
+ "-m", str(messages),
+ "--forever",
+ "--print-content=no",
+ # "--receive-rate", str(opts.receive_rate),
+ "--report-total",
+ "--ack-frequency", str(opts.ack_frequency),
+ # "--ready-address", "%s;{create:always}"%ready_queue,
+ "--report-header=no -v"
+ ]
+ if opts.save_received:
+ command += ["--save-content=%s-receiver-%s.msg"%(queue,index)]
+ command += opts.receive_arg
+ if opts.connection_options:
+ command += ["--connection-options",opts.connection_options]
+ if host: command = ssh_command(host, command)
+ if opts.verbose: print "Receiver: ", command
+ return clients.add(PopenCommand(command, stdout=PIPE, stderr=PIPE))
+
+def start_send(queue, opts, broker, host):
+ address="%s;{%s}"%(queue,",".join(opts.send_option + ["create:always"]))
+ command = ["qpid-jms-send",
+ #"-b", broker,
+ "-a", address,
+ "--messages", str(opts.messages),
+ "--content-size", str(opts.content_size),
+ "--send-rate", str(opts.send_rate),
+ "--report-total",
+ "--report-header=no",
+ "--timestamp=%s"%(opts.timestamp and "yes" or "no"),
+ "--sequence=%s"%(opts.sequence and "yes" or "no"),
+ "--durable", str(opts.durable)
+ ]
+ command += opts.send_arg
+ if opts.connection_options:
+ command += ["--connection-options",opts.connection_options]
+ if host: command = ssh_command(host, command)
+ if opts.verbose: print "Sender: ", command
+ return clients.add(PopenCommand(command, stdout=PIPE, stderr=PIPE))
+
+def error_msg(out, err):
+ return ("\n[stdout]\n%s\n[stderr]\n%s[end]"%(out, err))
+
+def first_line(p):
+ out,err=p.communicate()
+ if p.returncode != 0:
+ raise Exception("Process exit %d: %s"%(p.returncode, error_msg(out,err)))
+
+ print str(out)
+ print str(err)
+ return out.split("\n")[0]
+
+def recreate_queues(queues, brokers, no_delete, opts):
+ c = qpid.messaging.Connection(brokers[0])
+ c.open()
+ s = c.session()
+ for q in queues:
+ if not no_delete:
+ try: s.sender("%s;{delete:always}"%(q)).close()
+ except qpid.messaging.exceptions.NotFound: pass
+ address = "%s;{%s}"%(q, ",".join(opts.create_option + ["create:always"]))
+ if opts.verbose: print "Creating", address
+ s.sender(address)
+ c.close()
+
+def print_header(timestamp):
+ if timestamp: latency_header="\tl-min\tl-max\tl-avg\ttotal-tp"
+ else: latency_header=""
+ print "send-tp\trecv-tp%s"%latency_header
+
+def parse(parser, lines): # Parse sender/receiver output
+ return [map(lambda p: p[0](p[1]), zip(parser,line.split())) for line in lines]
+
+def parse_senders(senders):
+ return parse([int],[first_line(p) for p in senders])
+
+def parse_receivers(receivers):
+ return parse([int,float,float,float],[first_line(p) for p in receivers if p])
+
+def print_data(send_stats, recv_stats, total_tp):
+ for send,recv in map(None, send_stats, recv_stats):
+ line=""
+ if send: line += "%d"%send[0]
+ if recv:
+ line += "\t%d"%recv[0]
+ if len(recv) == 4: line += "\t%.2f\t%.2f\t%.2f"%tuple(recv[1:])
+ if total_tp is not None:
+ line += "\t%d"%total_tp
+ total_tp = None
+ print line
+
+def print_summary(send_stats, recv_stats, total_tp):
+ def avg(s): sum(s) / len(s)
+ send_tp = sum([l[0] for l in send_stats])
+ recv_tp = sum([l[0] for l in recv_stats])
+ summary = "%d\t%d"%(send_tp, recv_tp)
+ if recv_stats and len(recv_stats[0]) == 4:
+ l_min = sum(l[1] for l in recv_stats)/len(recv_stats)
+ l_max = sum(l[2] for l in recv_stats)/len(recv_stats)
+ l_avg = sum(l[3] for l in recv_stats)/len(recv_stats)
+ summary += "\t%.2f\t%.2f\t%.2f"%(l_min, l_max, l_avg)
+ summary += "\t%d"%total_tp
+ print summary
+
+
+class ReadyReceiver:
+ """A receiver for ready messages"""
+ def __init__(self, queue, broker):
+ self.connection = qpid.messaging.Connection(broker)
+ self.connection.open()
+ self.receiver = self.connection.session().receiver(
+ "%s;{create:receiver,delete:receiver,node:{durable:false}}"%(queue))
+ self.receiver.session.sync()
+ self.timeout=10
+
+ def wait(self, receivers):
+ try:
+ for i in receivers: self.receiver.fetch(self.timeout)
+ self.connection.close()
+ except qpid.messaging.Empty:
+ for r in receivers:
+ if (r.poll() is not None):
+ out,err=r.communicate()
+ raise Exception("Receiver error: %s\n%s" %
+ (" ".join(r.command), error_msg(out,err)))
+ 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), [])
+
+class RoundRobin:
+ def __init__(self,items):
+ self.items = items
+ self.index = 0
+
+ def next(self):
+ if not self.items: return None
+ ret = self.items[self.index]
+ self.index = (self.index+1)%len(self.items)
+ return ret
+
+def main():
+ opts, args = op.parse_args()
+ opts.client_host = flatten(opts.client_host)
+ if not opts.broker:
+ if opts.client_host:
+ raise Exception("--broker must be specified if --client_host is.")
+ opts.broker = ["127.0.0.1"] # Deafult to local broker
+ opts.broker = flatten(opts.broker)
+ brokers = RoundRobin(opts.broker)
+ client_hosts = RoundRobin(opts.client_host)
+ send_out = ""
+ 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):
+ recreate_queues(queues, opts.broker, opts.no_delete, opts)
+ ready_receiver = ReadyReceiver(ready_queue, opts.broker[0])
+
+ def start_receivers():
+ return [ start_receive(q, j, opts, ready_queue, brokers.next(), client_hosts.next())
+ for q in queues for j in xrange(opts.receivers) ]
+
+
+ def start_senders():
+ return [ 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)
+
+ if opts.fill_drain:
+ # First fill the queues, then drain them
+ start = time.time()
+ senders = start_senders()
+ for p in senders: p.wait()
+ receivers = start_receivers()
+ for p in receivers: p.wait()
+ else:
+ # Run senders and receivers in parallel
+ receivers = start_receivers()
+ ready_receiver.wait(filter(None, receivers)) # Wait for receivers ready
+ start = time.time()
+ senders = start_senders()
+ for p in senders + receivers: p.wait()
+
+ total_sent = opts.queues * opts.senders * opts.messages
+ total_tp = total_sent / (time.time()-start)
+ #send_stats=parse_senders(senders)
+ recv_stats=parse_receivers(receivers)
+ #if opts.summarize: print_summary(send_stats, recv_stats, total_tp)
+ #else: print_data(send_stats, recv_stats, total_tp)
+ finally: clients.kill() # No strays
+
+if __name__ == "__main__": main()
+
diff --git a/java/tools/bin/qpid-jms-receive b/java/tools/bin/qpid-jms-receive
new file mode 100755
index 0000000000..57abe874ff
--- /dev/null
+++ b/java/tools/bin/qpid-jms-receive
@@ -0,0 +1,193 @@
+#!/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="qpid-jms-receive"
+URL="amqp://guest:guest@clientid/testpath?brokerlist='tcp://localhost:5672'"
+ADDRESS="queue;{create:always}"
+TIMEOUT="0"
+FOREVER="false"
+MESSAGES="1"
+IGNORE_DUPLICATES="false"
+CHECK_REDELIVERED="false"
+CAPACITY="1000"
+ACK_FREQUENCY="100"
+TX="0"
+ROLLBACL_FREQUENCY="0"
+PRINT_CONTENT="false"
+PRINT_HEADERS="false"
+REPORT_TOTAL="false"
+REPORT_EVERY="0"
+REPORT_HEADER="true"
+READY_ADDRES="''"
+EXTRA_JVM_ARGS=""
+VERBOSE="0"
+
+TEST_ID=`echo ${HOSTNAME} | awk -F . '{print $1}'`
+
+TEMP=$(getopt -n $PROGRAM_NAME -o b:a:f:m:vh\
+ --long broker:,address:,timeout:,forever\
+,messages:,ignore-duplicates,check-redelivered\
+,capacity:,ack-frequency:,tx:,rollback-frequency:\
+,print-content:,print-headers:,report-total\
+,report-every:,report-header:,ready-address:\
+,jvm-args:,verbose,help -- "$@")
+
+# padding the option string with 4 spaces
+# padding the desc string with 30 spaces
+usage()
+{
+ printf "\n%s\n" "Usage: $PROGRAM_NAME [option].."
+
+ printf "\n%20s\n%57s\n" "-b, --broker URL" "url of broker to connect to"
+
+ printf "\n%24s\n%53s\n" "-a,--address ADDRESS" "address to receive from"
+
+ printf "\n%25s\n%71s\n" "--timeout TIMEOUT (0)" "timeout in seconds to wait before exiting"
+
+ printf "\n%17s\n%61s\n" "-f, --forever" "ignore timeout and wait forever"
+
+ printf "\n%24s\n%89s\n" "-m, --messages N (0)" "Number of messages to receive; 0 means receive indefinitely"
+
+ printf "\n%23s\n%84s\n" "--ignore-duplicates" "Detect and ignore duplicates (by checking 'sn' header)"
+
+ printf "\n%23s\n%82s\n%92s\n" "--check-redelivered" "Fails with exception if a duplicate is not marked as" " redelivered (only relevant when ignore-duplicates is selected)"
+
+ printf "\n%23s\n%71s\n" "--capacity N (1000)" "Pre-fetch window (0 implies no pre-fetch)"
+
+ printf "\n%27s\n%94s\n" "--ack-frequency N (100)" "Ack frequency (0 implies none of the messages will get accepted)"
+
+ printf "\n%14s\n%94s\n" "--tx N (0)" "batch size for transactions (0 implies transaction are not used)"
+
+ printf "\n%30s\n%94s\n" "--rollback-frequency N (0)" "rollback frequency (0 implies no transaction will be rolledback)"
+
+ printf "\n%30s\n%55s\n" "--print-content yes|no (0)" "print out message content"
+
+ printf "\n%30s\n%55s\n" "--print-headers yes|no (0)" "print out message headers"
+
+ printf "\n%18s\n%76s\n" "--report-total" "Report total throughput and latency statistics"
+
+ printf "\n%24s\n%87s\n" "--report-every N (0)" "Report throughput and latency statistics every N messages"
+
+ printf "\n%30s\n%47s\n" "--report-header yes|no (1)" "Headers on report"
+
+ printf "\n%27s\n%82s\n" "--ready-address ADDRESS" "send a message to this address when ready to receive"
+
+ printf "\n%14s\n%69s\n" "--jvm-args" "Extra jvm arguments you want to specify"
+
+ printf "\n%17s\n%69s\n\n" "-v, --verbose" "Print debug information for this script"
+}
+
+eval set -- "$TEMP"
+while true; do
+ case $1 in
+ -b|--broker)
+ URL="$2"; shift; shift; continue
+ ;;
+ -a|--address)
+ ADDRESS="$2"; shift; shift; continue
+ ;;
+ --timeout)
+ TIMEOUT="$2"; shift; shift; continue
+ ;;
+ -f|--forever)
+ FOREVER="$2"; shift; shift; continue
+ ;;
+ -m|--messages)
+ MESSAGES="$2"; shift; shift; continue
+ ;;
+ --ignore-duplicates)
+ IGNORE_DUPLICATES="true"; shift; continue
+ ;;
+ --check-redelivered)
+ CHECK_REDELIVERED="true"; shift; continue
+ ;;
+ --capacity)
+ CAPACITY="$2"; shift; shift; continue
+ ;;
+ --ack-frequency)
+ ACK_FREQUENCY="$2"; shift; shift; continue
+ ;;
+ --tx)
+ TX="$2"; shift; shift; continue
+ ;;
+ --rollback-frequency)
+ ROLLBACK_FREQUENCY="$2"; shift; shift; continue
+ ;;
+ --print-content)
+ if [ "$2" == "yes" ]; then PRINT_CONTENT="true"; else PRINT_CONTENT="false"; fi; shift; shift; continue
+ ;;
+ --print-headers)
+ if [ "$2" == "yes" ]; then PRINT_HEADERS="true"; else PRINT_HEADERS="false"; fi; shift; shift; continue
+ ;;
+ --report-total)
+ REPORT_TOTAL="true"; shift; continue
+ ;;
+ --report-every)
+ REPORT_EVERY="$2"; shift; shift; continue
+ ;;
+ --report-header)
+ if [ "$2" == "yes" ]; then REPORT_HEADER="true"; else REPORT_HEADER="false"; fi; shift; shift; continue
+ ;;
+ --ready-address)
+ READY_ADDRESS="$2"; shift; shift; continue
+ ;;
+ -a|--jvm-args)
+ EXTRA_JVM_ARGS="$2"; shift; shift; continue
+ ;;
+ -h|--help)
+ usage
+ exit 0
+ ;;
+ -v|--verbose)
+ VERBOSE="1"; shift; continue
+ ;;
+ --)
+ # no more arguments to parse
+ break
+ ;;
+ *)
+ # no more arguments to parse
+ break
+ ;;
+ esac
+done
+
+RECEIVER_ARGS="-server -Durl=$URL \
+-Daddress=$ADDRESS \
+-Dtimeout=$TIMEOUT \
+-Dmsg-count=$MESSAGES \
+-Dack-frequency=$ACK_FREQUENCY \
+-Dtx=$TX \
+-Drollback-frequnecy=$ROLLBACL_FREQUENCY \
+-Dprint-content=$PRINT_CONTENT \
+-Dprint-headers=$PRINT_HEADERS \
+-Dreport-total=$REPORT_TOTAL \
+-Dreport-every=$REPORT_EVERY \
+-Dreport-header=$REPORT_HEADER \
+-Dmax_prefetch=$CAPACITY "
+
+if [ "x$READY_ADDRESS" != "x" ]; then RECEIVER_ARGS="$RECEIVER_ARGS -Dready-address=$READY_ADDRESS"; fi
+if [ "$VERBOSE" == "1" ]; then echo $RECEIVER_ARGS; fi
+echo $RECEIVER_ARGS
+$JAVA -cp $CLASSPATH $LOG_CONFIG $JAVA_MEM $RECEIVER_ARGS org.apache.qpid.tools.QpidReceive
diff --git a/java/tools/bin/qpid-jms-send b/java/tools/bin/qpid-jms-send
new file mode 100755
index 0000000000..d7695924f0
--- /dev/null
+++ b/java/tools/bin/qpid-jms-send
@@ -0,0 +1,261 @@
+#!/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="qpid-jms-send"
+URL="amqp://guest:guest@clientid/testpath?brokerlist='tcp://localhost:5672'"
+ADDRESS="queue;{create:always}"
+MESSAGES="1"
+ID=""
+REPLY_TO=""
+SEND_EOS="1"
+DURABLE="false"
+TTL="0"
+PRIORITY="0"
+PROPERTY=""
+CORRELATION_ID=""
+USER_ID=""
+CONTENT_STRING=""
+CONTENT_SIZE="1024"
+CONTENT_MAP=""
+CAPACITY="1000"
+ACK_FREQUENCY="100"
+TX="0"
+ROLLBACL_FREQUENCY="0"
+PRINT_CONTENT="true"
+PRINT_HEADERS="false"
+REPORT_TOTAL="false"
+REPORT_EVERY="0"
+REPORT_HEADER="true"
+SEND_RATE="-1"
+SEQUNCE="1"
+DISABLE_TIMESTAMP="false"
+EXTRA_JVM_ARGS=""
+VERBOSE="0"
+
+TEST_ID=`echo ${HOSTNAME} | awk -F . '{print $1}'`
+
+TEMP=$(getopt -n $PROGRAM_NAME -o b:a:m:i:P:M:vh\
+ --long broker:,address:,messages:,id:,reply-to:\
+,send-eos:,durable:,ttl:,property:,correlational-id:\
+,user-id:,content-string:,content-size:,content-map:\
+,capacity:,ack-frequency:,tx:,rollback-frequency:\
+,print-content:,print-headers:,report-total\
+,report-every:,report-header:,send-rate:,sequence:,timestamp:\
+,jvm-args:,verbose,help -- "$@")
+
+# padding the option string with 4 spaces
+# padding the desc string with 30 spaces
+usage()
+{
+ printf "\n%s\n" "Usage: $PROGRAM_NAME [option].."
+
+ printf "\n%20s\n%57s\n" "-b, --broker URL" "url of broker to connect to"
+
+ printf "\n%24s\n%53s\n" "-a,--address ADDRESS" "address to receive from"
+
+ printf "\n%24s\n%89s\n" "-m, --messages N (0)" "Number of messages to receive; 0 means receive indefinitely"
+
+ printf "\n%15s\n%75s\n" "-i, --id ID" "use the supplied id instead of generating one"
+
+ printf "\n%23s\n%54s\n" "--reply-to REPLY-TO" "specify reply-to address"
+
+ printf "\n%20s\n%70s\n" "--send-eos N (0)" "send N EOS messages to mark end of input"
+
+ printf "\n%24s\n%54s\n" "--durable yes|no (0)" "mark messages as durable"
+
+ printf "\n%19s\n%72s\n" "--ttl msecs (0)" "time-to-live for messages, in milliseconds"
+
+ printf "\n%27s\n%72s\n" "--priority PRIORITY (0)" "time-to-live for messages, in milliseconds"
+
+ printf "\n%29s\n%54s\n" "-P, --property NAME=VALUE" "specify message property"
+
+ printf "\n%23s\n%57s\n" "--correlation-id ID" "correlation-id for message"
+
+ printf "\n%20s\n%48s\n" "--user-id USERID" "userid for message"
+
+ printf "\n%28s\n%60s\n" "--content-string CONTENT" "use CONTENT as message content"
+
+ printf "\n%24s\n%62s\n" "--content-size N (0)" "create an N-byte message content"
+
+ printf "\n%32s\n%59s\n" "-M, --content-map NAME=VALUE" "specify entry for map content"
+
+ printf "\n%23s\n%71s\n" "--capacity N (1000)" "Pre-fetch window (0 implies no pre-fetch)"
+
+ printf "\n%27s\n%94s\n" "--ack-frequency N (100)" "Ack frequency (0 implies none of the messages will get accepted)"
+
+ printf "\n%14s\n%94s\n" "--tx N (0)" "batch size for transactions (0 implies transaction are not used)"
+
+ printf "\n%30s\n%94s\n" "--rollback-frequency N (0)" "rollback frequency (0 implies no transaction will be rolledback)"
+
+ printf "\n%30s\n%55s\n" "--print-content yes|no (1)" "print out message content"
+
+ printf "\n%30s\n%55s\n" "--print-headers yes|no (0)" "print out message headers"
+
+ printf "\n%18s\n%76s\n" "--report-total" "Report total throughput and latency statistics"
+
+ printf "\n%24s\n%87s\n" "--report-every N (0)" "Report throughput and latency statistics every N messages"
+
+ printf "\n%30s\n%47s\n" "--report-header yes|no (1)" "Headers on report"
+
+ printf "\n%21s\n%64s\n%62s\n" "--send-rate N (0)" "Send at rate of N messages/second." "0 means send as fast as possible"
+
+ printf "\n%25s\n%69s\n%77s\n" "--sequence yes|no (1)" "Add a sequence number messages property" "(required for duplicate/lost message detection)"
+
+ printf "\n%26s\n%64s\n%77s\n" "--timestamp yes|no (1)" "Add a time stamp messages property" "(required for duplicate/lost message detection)"
+
+ printf "\n%14s\n%69s\n" "--jvm-args" "Extra jvm arguments you want to specify"
+
+ printf "\n%17s\n%69s\n\n" "-v, --verbose" "Print debug information for this script"
+}
+
+eval set -- "$TEMP"
+while true; do
+ case $1 in
+ -b|--broker)
+ URL="$2"; shift; shift; continue
+ ;;
+ -a|--address)
+ ADDRESS="$2"; shift; shift; continue
+ ;;
+ -m|--messages)
+ MESSAGES="$2"; shift; shift; continue
+ ;;
+ -i|--id)
+ ID="$2"; shift; shift; continue
+ ;;
+ --reply-to)
+ REPLY_TO="$2"; shift; shift; continue
+ ;;
+ --send-eos)
+ SEND_EOS="$2"; shift; shift; continue
+ ;;
+ --durable)
+ if [ "$2" == "1" ]; then DURABLE="true"; else DURABLE="false"; fi; shift; shift; continue
+ ;;
+ --ttl)
+ TTL="$2"; shift; shift; continue
+ ;;
+ --priority)
+ PRIORITY="$2"; shift; shift; continue
+ ;;
+ -P|--property)
+ PROPERTY="$2,$PROPERTY"; shift; shift; continue
+ ;;
+ --correlation-id)
+ CORRELATION_ID="$2"; shift; shift; continue
+ ;;
+ --user-id)
+ USER_ID="$2"; shift; shift; continue
+ ;;
+ --content-string)
+ CONTENT_STRING="$2"; shift; shift; continue
+ ;;
+ --content-size)
+ CONTENT_SIZE="$2"; shift; shift; continue
+ ;;
+ -M|--content-map)
+ CONTENT_MAP="$2,$CONTENT_MAP"; shift; shift; continue
+ ;;
+ --capacity)
+ CAPACITY="$2"; shift; shift; continue
+ ;;
+ --ack-frequency)
+ ACK_FREQUENCY="$2"; shift; shift; continue
+ ;;
+ --tx)
+ TX="$2"; shift; shift; continue
+ ;;
+ --rollback-frequency)
+ ROLLBACK_FREQUENCY="$2"; shift; shift; continue
+ ;;
+ --print-content)
+ if [ "$2" == "yes" ]; then PRINT_CONTENT="true"; else PRINT_CONTENT="false"; fi; shift; shift; continue
+ ;;
+ --print-headers)
+ if [ "$2" == "yes" ]; then PRINT_HEADERS="true"; else PRINT_HEADERS="false"; fi; shift; shift; continue
+ ;;
+ --report-total)
+ REPORT_TOTAL="true"; shift; continue
+ ;;
+ --report-every)
+ REPORT_EVERY="$2"; shift; shift; continue
+ ;;
+ --report-header)
+ if [ "$2" == "yes" ]; then REPORT_HEADER="true"; else REPORT_HEADER="false"; fi; shift; shift; continue
+ ;;
+ --send-rate)
+ SEND_RATE="$2"; shift; shift; continue
+ ;;
+ --sequence)
+ if [ "$2" == "yes" ]; then SEQUENCE="true"; else SEQUENCE="false"; fi; shift; shift; continue
+ ;;
+ --timestamp)
+ if [ "$2" == "yes" ]; then DISABLE_TIMESTAMP="false"; else DISABLE_TIMESTAMP="true"; fi; shift; shift; continue
+ ;;
+ -a|--jvm-args)
+ EXTRA_JVM_ARGS="$2"; shift; shift; continue
+ ;;
+ -h|--help)
+ usage
+ exit 0
+ ;;
+ -v|--verbose)
+ VERBOSE="1"; shift; continue
+ ;;
+ --)
+ # no more arguments to parse
+ break
+ ;;
+ *)
+ # no more arguments to parse
+ break
+ ;;
+ esac
+done
+
+SENDER_ARGS="-server -Durl=$URL \
+-Daddress=$ADDRESS \
+-Dmsg-count=$MESSAGES \
+-Dsend-eos=$SEND_EOS \
+-Ddurable=$DURABLE \
+-Dmsg_size=$CONTENT_SIZE \
+-Dsend-rate=$SEND_RATE \
+-Ddisable-timestamp=$DISABLE_TIMESTAMP \
+-Dttl=$TTL \
+-Dpriority=$PRIORITY \
+-Dtx=$TX \
+-Drollback-frequnecy=$ROLLBACK_FREQUENCY \
+-Dprint-content=$PRINT_CONTENT \
+-Dprint-headers=$PRINT_HEADERS \
+-Dreport-total=$REPORT_TOTAL \
+-Dreport-every=$REPORT_EVERY \
+-Dreport-header=$REPORT_HEADER \
+-Dmax_prefetch=$CAPACITY "
+
+if [ "x$ID" != "x" ]; then SENDER_ARGS="$SENDER_ARGS -Did=$ID"; fi
+if [ "x$USER_ID" != "x" ]; then SENDER_ARGS="$SENDER_ARGS -Duser_id=$USER_ID"; fi
+if [ "x$CORRELATION_ID" != "x" ]; then SENDER_ARGS="$SENDER_ARGS -Dcorrelation_id=$CORRELATION_ID"; fi
+
+if [ "$VERBOSE" == "1" ]; then echo $SENDER_ARGS; fi
+$JAVA -cp $CLASSPATH $LOG_CONFIG $JAVA_MEM $SENDER_ARGS org.apache.qpid.tools.QpidSend
diff --git a/java/tools/build.xml b/java/tools/build.xml
index 7cd1b1172c..99b0375e95 100644
--- a/java/tools/build.xml
+++ b/java/tools/build.xml
@@ -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 @@
-
-->
<project name="Qpid Tools" default="build">
-
<property name="module.depends" value="client common"/>
<import file="../module.xml"/>
diff --git a/java/tools/src/main/java/org/apache/qpid/testkit/ErrorHandler.java b/java/tools/src/main/java/org/apache/qpid/testkit/ErrorHandler.java
index dbc73c404f..de7748acd6 100644
--- a/java/tools/src/main/java/org/apache/qpid/testkit/ErrorHandler.java
+++ b/java/tools/src/main/java/org/apache/qpid/testkit/ErrorHandler.java
@@ -1,4 +1,3 @@
-package org.apache.qpid.testkit;
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
@@ -19,6 +18,7 @@ package org.apache.qpid.testkit;
* under the License.
*
*/
+package org.apache.qpid.testkit;
public interface ErrorHandler {
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
index 4e79dd62a8..7eb83a520b 100644
--- a/java/tools/src/main/java/org/apache/qpid/tools/Clock.java
+++ b/java/tools/src/main/java/org/apache/qpid/tools/Clock.java
@@ -20,6 +20,9 @@
*/
package org.apache.qpid.tools;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
/**
* In the future this will be replaced by a Clock abstraction
* that can utilize a realtime clock when running in RT Java.
@@ -27,6 +30,8 @@ package org.apache.qpid.tools;
public class Clock
{
+ private static final Logger _logger = LoggerFactory.getLogger(Clock.class);
+
public final static long SEC = 60000;
private static Precision precision;
@@ -54,7 +59,11 @@ public class Clock
precision = Precision.getPrecision(System.getProperty("precision","mili"));
//offset = Long.getLong("offset",-1);
- System.out.println("Using precision : " + precision + " and offset " + offset);
+ if (_logger.isDebugEnabled())
+ {
+ System.out.println("Using precision : " + precision );
+ //+ " and offset " + offset);
+ }
}
public static Precision getPrecision()
diff --git a/java/tools/src/main/java/org/apache/qpid/tools/JVMArgConfiguration.java b/java/tools/src/main/java/org/apache/qpid/tools/JVMArgConfiguration.java
index c6abdf6c84..e0e48519f3 100644
--- a/java/tools/src/main/java/org/apache/qpid/tools/JVMArgConfiguration.java
+++ b/java/tools/src/main/java/org/apache/qpid/tools/JVMArgConfiguration.java
@@ -29,383 +29,422 @@ import org.apache.qpid.client.AMQConnection;
public class JVMArgConfiguration implements TestConfiguration
{
- /*
- * 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.
- */
- private String url = "amqp://guest:guest@clientid/testpath?brokerlist='tcp://localhost:5672'";
+ /*
+ * 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.
+ */
+ private String url = "amqp://guest:guest@clientid/testpath?brokerlist='tcp://localhost:5672'";
- private String host = "";
+ private String host = "";
- private int port = -1;
+ private int port = -1;
- private String address = "queue; {create : always}";
+ private String address = "queue; {create : always}";
- private int msg_size = 1024;
+ private long timeout = 0;
- private int random_msg_size_start_from = 1;
+ private int msg_size = 1024;
- private boolean cacheMessage = false;
+ private int random_msg_size_start_from = 1;
- private boolean disableMessageID = false;
+ private boolean cacheMessage = false;
- private boolean disableTimestamp = false;
+ private boolean disableMessageID = false;
- private boolean durable = false;
+ private boolean disableTimestamp = false;
- private int transaction_size = 0;
+ private boolean durable = false;
- private int ack_mode = Session.AUTO_ACKNOWLEDGE;
+ private int transaction_size = 0;
- private int msg_count = 10;
+ private int ack_mode = Session.AUTO_ACKNOWLEDGE;
- private int warmup_count = 1;
+ private int msg_count = 10;
- private boolean random_msg_size = false;
+ private int warmup_count = 1;
- private String msgType = "bytes";
+ private boolean random_msg_size = false;
- private boolean printStdDev = false;
+ private String msgType = "bytes";
- private int sendRate = 0;
+ private boolean printStdDev = false;
- private boolean externalController = false;
+ private int sendRate = 0;
- private boolean useUniqueDest = false; // useful when using multiple connections.
+ private boolean externalController = false;
- private int ackFrequency = 100;
+ private boolean useUniqueDest = false; // useful when using multiple connections.
- private DecimalFormat df = new DecimalFormat("###.##");
+ private int ackFrequency = 100;
- private int reportEvery = 0;
+ private DecimalFormat df = new DecimalFormat("###.##");
- private boolean isReportTotal = false;
-
- private boolean isReportHeader = true;
+ private int reportEvery = 0;
- private boolean isReportLatency = false;
-
- private int sendEOS = 0;
-
- private int connectionCount = 1;
-
- private int rollbackFrequency = 0;
-
- private boolean printHeaders;
-
- public JVMArgConfiguration()
- {
-
- url = System.getProperty("url",url);
- host = System.getProperty("host","");
- port = Integer.getInteger("port", -1);
- address = System.getProperty("address",address);
-
- msg_size = Integer.getInteger("msg-size", 1024);
- cacheMessage = Boolean.getBoolean("cache-msg");
- disableMessageID = Boolean.getBoolean("disable-message-id");
- disableTimestamp = Boolean.getBoolean("disable-timestamp");
- durable = Boolean.getBoolean("durable");
- transaction_size = Integer.getInteger("tx",1000);
- ack_mode = Integer.getInteger("ack-mode",Session.AUTO_ACKNOWLEDGE);
- 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");
- sendRate = Integer.getInteger("rate",0);
- externalController = Boolean.getBoolean("ext-controller");
- useUniqueDest = Boolean.getBoolean("use-unique-dest");
- random_msg_size_start_from = Integer.getInteger("random-msg-size-start-from", 1);
- reportEvery = Integer.getInteger("report-every");
- isReportTotal = Boolean.getBoolean("report-total");
- isReportHeader = (System.getProperty("report-header") == null) ? true : Boolean.getBoolean("report-header");
- isReportLatency = Boolean.getBoolean("report-latency");
- sendEOS = Integer.getInteger("send-eos");
- connectionCount = Integer.getInteger("con_count",1);
- ackFrequency = Integer.getInteger("ack-frequency");
- rollbackFrequency = Integer.getInteger("rollback-frequency");
- printHeaders = Boolean.getBoolean("print-headers");
- }
-
- /* (non-Javadoc)
- * @see org.apache.qpid.tools.TestConfiguration#getUrl()
- */
- @Override
- public String getUrl()
- {
- return url;
- }
-
- /* (non-Javadoc)
- * @see org.apache.qpid.tools.TestConfiguration#getHost()
- */
- @Override
- public String getHost()
- {
- return host;
- }
-
- /* (non-Javadoc)
- * @see org.apache.qpid.tools.TestConfiguration#getPort()
- */
- @Override
- public int getPort()
- {
- return port;
- }
-
- /* (non-Javadoc)
- * @see org.apache.qpid.tools.TestConfiguration#getAddress()
- */
- @Override
- public String getAddress()
- {
- return address;
- }
-
- /* (non-Javadoc)
- * @see org.apache.qpid.tools.TestConfiguration#getAckMode()
- */
- @Override
- public int getAckMode()
- {
- return ack_mode;
- }
-
- /* (non-Javadoc)
- * @see org.apache.qpid.tools.TestConfiguration#getMsgCount()
- */
- @Override
- public int getMsgCount()
- {
- return msg_count;
- }
-
- /* (non-Javadoc)
- * @see org.apache.qpid.tools.TestConfiguration#getMsgSize()
- */
- @Override
- public int getMsgSize()
- {
- return msg_size;
- }
-
- /* (non-Javadoc)
- * @see org.apache.qpid.tools.TestConfiguration#getRandomMsgSizeStartFrom()
- */
- @Override
- public int getRandomMsgSizeStartFrom()
- {
- return random_msg_size_start_from;
- }
-
- /* (non-Javadoc)
- * @see org.apache.qpid.tools.TestConfiguration#isDurable()
- */
- @Override
- public boolean isDurable()
- {
- return durable;
- }
-
- /* (non-Javadoc)
- * @see org.apache.qpid.tools.TestConfiguration#isTransacted()
- */
- @Override
- public boolean isTransacted()
- {
- return transaction_size > 0;
- }
-
- /* (non-Javadoc)
- * @see org.apache.qpid.tools.TestConfiguration#getTransactionSize()
- */
- @Override
- public int getTransactionSize()
- {
- return transaction_size;
- }
-
- /* (non-Javadoc)
- * @see org.apache.qpid.tools.TestConfiguration#getWarmupCount()
- */
- @Override
- public int getWarmupCount()
- {
- return warmup_count;
- }
-
- /* (non-Javadoc)
- * @see org.apache.qpid.tools.TestConfiguration#isCacheMessage()
- */
- @Override
- public boolean isCacheMessage()
- {
- return cacheMessage;
- }
-
- /* (non-Javadoc)
- * @see org.apache.qpid.tools.TestConfiguration#isDisableMessageID()
- */
- @Override
- public boolean isDisableMessageID()
- {
- return disableMessageID;
- }
-
- /* (non-Javadoc)
- * @see org.apache.qpid.tools.TestConfiguration#isDisableTimestamp()
- */
- @Override
- public boolean isDisableTimestamp()
- {
- return disableTimestamp;
- }
-
- /* (non-Javadoc)
- * @see org.apache.qpid.tools.TestConfiguration#isRandomMsgSize()
- */
- @Override
- public boolean isRandomMsgSize()
- {
- return random_msg_size;
- }
-
- /* (non-Javadoc)
- * @see org.apache.qpid.tools.TestConfiguration#getMessageType()
- */
- @Override
- public String getMessageType()
- {
- return msgType;
- }
-
- /* (non-Javadoc)
- * @see org.apache.qpid.tools.TestConfiguration#isPrintStdDev()
- */
- @Override
- public boolean isPrintStdDev()
- {
- return printStdDev;
- }
-
- /* (non-Javadoc)
- * @see org.apache.qpid.tools.TestConfiguration#getSendRate()
- */
- @Override
- public int getSendRate()
- {
- return sendRate;
- }
-
- /* (non-Javadoc)
- * @see org.apache.qpid.tools.TestConfiguration#isExternalController()
- */
- @Override
- public boolean isExternalController()
- {
- return externalController;
- }
-
- public void setAddress(String addr)
- {
- address = addr;
- }
-
- /* (non-Javadoc)
- * @see org.apache.qpid.tools.TestConfiguration#isUseUniqueDests()
- */
- @Override
- public boolean isUseUniqueDests()
- {
- return useUniqueDest;
- }
-
- /* (non-Javadoc)
- * @see org.apache.qpid.tools.TestConfiguration#getAckFrequency()
- */
- @Override
- public int getAckFrequency()
- {
- return ackFrequency;
- }
-
- /* (non-Javadoc)
- * @see org.apache.qpid.tools.TestConfiguration#createConnection()
- */
- @Override
- public Connection createConnection() throws Exception
- {
- if (getHost().equals("") || getPort() == -1)
- {
- return new AMQConnection(getUrl());
- }
- else
- {
- return new AMQConnection(getHost(),getPort(),"guest","guest","test","test");
- }
- }
-
- /* (non-Javadoc)
- * @see org.apache.qpid.tools.TestConfiguration#getDecimalFormat()
- */
- @Override
- public DecimalFormat getDecimalFormat()
- {
- return df;
- }
-
- @Override
- public int reportEvery()
- {
- return reportEvery;
- }
-
- @Override
- public boolean isReportTotal()
- {
- return isReportTotal;
- }
-
- @Override
- public boolean isReportHeader()
- {
- return isReportHeader;
- }
-
- @Override
- public boolean isReportLatency()
- {
- return isReportLatency;
- }
-
- @Override
- public int getSendEOS()
- {
- return sendEOS;
- }
-
- @Override
- public int getConnectionCount()
- {
- return connectionCount;
- }
-
- @Override
- public int getRollbackFrequency()
- {
- return rollbackFrequency;
- }
-
- @Override
- public boolean isPrintHeaders()
- {
- return printHeaders;
- }
+ private boolean isReportTotal = false;
+
+ private boolean isReportHeader = true;
+
+ private int sendEOS = 0;
+
+ private int connectionCount = 1;
+
+ private int rollbackFrequency = 0;
+
+ private boolean printHeaders;
+
+ private boolean printContent;
+
+ private long ttl;
+
+ private int priority;
+
+ private String readyAddress;
+
+ public JVMArgConfiguration()
+ {
+
+ url = System.getProperty("url",url);
+ host = System.getProperty("host","");
+ port = Integer.getInteger("port", -1);
+ address = System.getProperty("address",address);
+
+ timeout = Long.getLong("timeout",0);
+ msg_size = Integer.getInteger("msg-size", 0);
+ cacheMessage = true; //Boolean.getBoolean("cache-msg");
+ disableMessageID = Boolean.getBoolean("disable-message-id");
+ disableTimestamp = Boolean.getBoolean("disable-timestamp");
+ durable = Boolean.getBoolean("durable");
+ transaction_size = Integer.getInteger("tx",1000);
+ ack_mode = Integer.getInteger("ack-mode",Session.AUTO_ACKNOWLEDGE);
+ 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");
+ sendRate = Integer.getInteger("rate",0);
+ externalController = Boolean.getBoolean("ext-controller");
+ useUniqueDest = Boolean.getBoolean("use-unique-dest");
+ random_msg_size_start_from = Integer.getInteger("random-msg-size-start-from", 1);
+ reportEvery = Integer.getInteger("report-every",0);
+ isReportTotal = Boolean.getBoolean("report-total");
+ isReportHeader = (System.getProperty("report-header") == null) ? true : Boolean.getBoolean("report-header");
+ sendEOS = Integer.getInteger("send-eos",1);
+ connectionCount = Integer.getInteger("con_count",1);
+ ackFrequency = Integer.getInteger("ack-frequency",100);
+ rollbackFrequency = Integer.getInteger("rollback-frequency",0);
+ printHeaders = Boolean.getBoolean("print-headers");
+ printContent = Boolean.getBoolean("print-content");
+ ttl = Long.getLong("ttl", 0);
+ priority = Integer.getInteger("priority", 0);
+ readyAddress = System.getProperty("ready-address");
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.qpid.tools.TestConfiguration#getUrl()
+ */
+ @Override
+ public String getUrl()
+ {
+ return url;
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.qpid.tools.TestConfiguration#getHost()
+ */
+ @Override
+ public String getHost()
+ {
+ return host;
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.qpid.tools.TestConfiguration#getPort()
+ */
+ @Override
+ public int getPort()
+ {
+ return port;
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.qpid.tools.TestConfiguration#getAddress()
+ */
+ @Override
+ public String getAddress()
+ {
+ return address;
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.qpid.tools.TestConfiguration#getTimeout()
+ */
+ @Override
+ public long getTimeout()
+ {
+ return timeout;
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.qpid.tools.TestConfiguration#getAckMode()
+ */
+ @Override
+ public int getAckMode()
+ {
+ return ack_mode;
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.qpid.tools.TestConfiguration#getMsgCount()
+ */
+ @Override
+ public int getMsgCount()
+ {
+ return msg_count;
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.qpid.tools.TestConfiguration#getMsgSize()
+ */
+ @Override
+ public int getMsgSize()
+ {
+ return msg_size;
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.qpid.tools.TestConfiguration#getRandomMsgSizeStartFrom()
+ */
+ @Override
+ public int getRandomMsgSizeStartFrom()
+ {
+ return random_msg_size_start_from;
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.qpid.tools.TestConfiguration#isDurable()
+ */
+ @Override
+ public boolean isDurable()
+ {
+ return durable;
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.qpid.tools.TestConfiguration#isTransacted()
+ */
+ @Override
+ public boolean isTransacted()
+ {
+ return transaction_size > 0;
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.qpid.tools.TestConfiguration#getTransactionSize()
+ */
+ @Override
+ public int getTransactionSize()
+ {
+ return transaction_size;
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.qpid.tools.TestConfiguration#getWarmupCount()
+ */
+ @Override
+ public int getWarmupCount()
+ {
+ return warmup_count;
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.qpid.tools.TestConfiguration#isCacheMessage()
+ */
+ @Override
+ public boolean isCacheMessage()
+ {
+ return cacheMessage;
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.qpid.tools.TestConfiguration#isDisableMessageID()
+ */
+ @Override
+ public boolean isDisableMessageID()
+ {
+ return disableMessageID;
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.qpid.tools.TestConfiguration#isDisableTimestamp()
+ */
+ @Override
+ public boolean isDisableTimestamp()
+ {
+ return disableTimestamp;
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.qpid.tools.TestConfiguration#isRandomMsgSize()
+ */
+ @Override
+ public boolean isRandomMsgSize()
+ {
+ return random_msg_size;
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.qpid.tools.TestConfiguration#getMessageType()
+ */
+ @Override
+ public String getMessageType()
+ {
+ return msgType;
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.qpid.tools.TestConfiguration#isPrintStdDev()
+ */
+ @Override
+ public boolean isPrintStdDev()
+ {
+ return printStdDev;
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.qpid.tools.TestConfiguration#getSendRate()
+ */
+ @Override
+ public int getSendRate()
+ {
+ return sendRate;
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.qpid.tools.TestConfiguration#isExternalController()
+ */
+ @Override
+ public boolean isExternalController()
+ {
+ return externalController;
+ }
+
+ public void setAddress(String addr)
+ {
+ address = addr;
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.qpid.tools.TestConfiguration#isUseUniqueDests()
+ */
+ @Override
+ public boolean isUseUniqueDests()
+ {
+ return useUniqueDest;
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.qpid.tools.TestConfiguration#getAckFrequency()
+ */
+ @Override
+ public int getAckFrequency()
+ {
+ return ackFrequency;
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.qpid.tools.TestConfiguration#createConnection()
+ */
+ @Override
+ public Connection createConnection() throws Exception
+ {
+ if (getHost().equals("") || getPort() == -1)
+ {
+ return new AMQConnection(getUrl());
+ }
+ else
+ {
+ return new AMQConnection(getHost(),getPort(),"guest","guest","test","test");
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.qpid.tools.TestConfiguration#getDecimalFormat()
+ */
+ @Override
+ public DecimalFormat getDecimalFormat()
+ {
+ return df;
+ }
+
+ @Override
+ public int reportEvery()
+ {
+ return reportEvery;
+ }
+
+ @Override
+ public boolean isReportTotal()
+ {
+ return isReportTotal;
+ }
+
+ @Override
+ public boolean isReportHeader()
+ {
+ return isReportHeader;
+ }
+
+ @Override
+ public int getSendEOS()
+ {
+ return sendEOS;
+ }
+
+ @Override
+ public int getConnectionCount()
+ {
+ return connectionCount;
+ }
+
+ @Override
+ public int getRollbackFrequency()
+ {
+ return rollbackFrequency;
+ }
+
+ @Override
+ public boolean isPrintHeaders()
+ {
+ return printHeaders;
+ }
+
+ @Override
+ public boolean isPrintContent()
+ {
+ return printContent;
+ }
+
+ @Override
+ public long getTTL()
+ {
+ return ttl;
+ }
+
+ @Override
+ public int getPriority()
+ {
+ return priority;
+ }
+
+ @Override
+ public String getReadyAddress()
+ {
+ return readyAddress;
+ }
}
diff --git a/java/tools/src/main/java/org/apache/qpid/tools/MessageFactory.java b/java/tools/src/main/java/org/apache/qpid/tools/MessageFactory.java
index 8ab1379fce..a0ba928e1f 100644
--- a/java/tools/src/main/java/org/apache/qpid/tools/MessageFactory.java
+++ b/java/tools/src/main/java/org/apache/qpid/tools/MessageFactory.java
@@ -1,4 +1,3 @@
-package org.apache.qpid.tools;
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
@@ -19,6 +18,7 @@ package org.apache.qpid.tools;
* under the License.
*
*/
+package org.apache.qpid.tools;
import javax.jms.BytesMessage;
diff --git a/java/tools/src/main/java/org/apache/qpid/tools/QpidReceive.java b/java/tools/src/main/java/org/apache/qpid/tools/QpidReceive.java
index 02f011f1b9..6dd8b7e1ca 100644
--- a/java/tools/src/main/java/org/apache/qpid/tools/QpidReceive.java
+++ b/java/tools/src/main/java/org/apache/qpid/tools/QpidReceive.java
@@ -28,10 +28,12 @@ import javax.jms.Destination;
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 org.apache.qpid.client.AMQDestination;
+import org.apache.qpid.client.message.AbstractJMSMessage;
import org.apache.qpid.tools.TestConfiguration.MessageType;
import org.apache.qpid.tools.report.BasicReporter;
import org.apache.qpid.tools.report.Reporter;
@@ -42,140 +44,164 @@ import org.slf4j.LoggerFactory;
public class QpidReceive implements MessageListener
{
- private static final Logger _logger = LoggerFactory.getLogger(QpidSend.class);
- private final CountDownLatch testCompleted = new CountDownLatch(1);
-
- private Connection con;
- private Session session;
- private Destination dest;
- private MessageConsumer consumer;
- private boolean transacted = false;
- private boolean isRollback = false;
- private int txSize = 0;
- private int rollbackFrequency = 0;
- private int ackFrequency = 0;
- private int expected = 0;
- private int received = 0;
- private Reporter report;
- private TestConfiguration config;
-
- public QpidReceive(Reporter report, TestConfiguration config, Connection con, Destination dest)
- {
- this(report,config, con, dest, UUID.randomUUID().toString());
- }
-
- public QpidReceive(Reporter report, TestConfiguration config, Connection con, Destination dest, String prefix)
- {
- //System.out.println("Producer ID : " + id);
- this.report = report;
- this.config = config;
- this.con = con;
- this.dest = dest;
- }
-
- public void setUp() throws Exception
- {
- if (config.isTransacted())
- {
- session = con.createSession(true, Session.SESSION_TRANSACTED);
- }
- else if (config.getAckFrequency() > 0)
- {
- session = con.createSession(false, Session.DUPS_OK_ACKNOWLEDGE);
- }
- else
- {
- session = con.createSession(false, Session.AUTO_ACKNOWLEDGE);
- }
- consumer = session.createConsumer(dest);
- consumer.setMessageListener(this);
- System.out.println("Consumer: " + /*id +*/ " Receiving messages from : " + ((AMQDestination)dest).getAddressName() + "\n");
-
- transacted = config.isTransacted();
- txSize = config.getTransactionSize();
- isRollback = config.getRollbackFrequency() > 0;
- rollbackFrequency = config.getRollbackFrequency();
- ackFrequency = config.getAckFrequency();
- }
-
- public void resetCounters()
- {
- received = 0;
- expected = 0;
- report.clear();
- }
-
- public void onMessage(Message msg)
- {
- try
- {
- if (msg instanceof TextMessage &&
- TestConfiguration.EOS.equals(((TextMessage)msg).getText()))
- {
- testCompleted.countDown();
- return;
- }
-
- received++;
- report.message(msg);
-
- if (transacted && (received % txSize == 0))
- {
- if (isRollback && (received % rollbackFrequency == 0))
- {
- session.rollback();
- }
- else
- {
- session.commit();
- }
- }
- else if (ackFrequency > 0)
- {
- msg.acknowledge();
- }
-
- if (expected >= received)
- {
- testCompleted.countDown();
- }
-
- }
- catch(Exception e)
- {
- _logger.error("Error when receiving messages",e);
- }
-
- }
-
- public void waitforCompletion(int expected) throws Exception
- {
- this.expected = expected;
- testCompleted.await();
- }
-
- public void tearDown() throws Exception
- {
- session.close();
- }
-
- public static void main(String[] args) throws Exception
- {
- TestConfiguration config = new JVMArgConfiguration();
- Reporter reporter = new BasicReporter(config.isReportLatency()? ThroughputAndLatency.class : Throughput.class,
- System.out,
- config.reportEvery(),
- config.isReportHeader()
- );
- Destination dest = AMQDestination.createDestination(config.getAddress());
- QpidReceive receiver = new QpidReceive(reporter,config, config.createConnection(),dest);
- receiver.setUp();
- receiver.waitforCompletion(config.getMsgCount());
- if (config.isReportTotal())
- {
- reporter.report();
- }
- receiver.tearDown();
- }
+ private static final Logger _logger = LoggerFactory.getLogger(QpidReceive.class);
+ private final CountDownLatch testCompleted = new CountDownLatch(1);
+
+ private Connection con;
+ private Session session;
+ private Destination dest;
+ private MessageConsumer consumer;
+ private boolean transacted = false;
+ private boolean isRollback = false;
+ private int txSize = 0;
+ private int rollbackFrequency = 0;
+ private int ackFrequency = 0;
+ private int expected = 0;
+ private int received = 0;
+ private Reporter report;
+ private TestConfiguration config;
+
+ public QpidReceive(Reporter report, TestConfiguration config, Connection con, Destination dest)
+ {
+ this(report,config, con, dest, UUID.randomUUID().toString());
+ }
+
+ public QpidReceive(Reporter report, TestConfiguration config, Connection con, Destination dest, String prefix)
+ {
+ //System.out.println("Producer ID : " + id);
+ this.report = report;
+ this.config = config;
+ this.con = con;
+ this.dest = dest;
+ }
+
+ public void setUp() throws Exception
+ {
+ con.start();
+ if (config.isTransacted())
+ {
+ session = con.createSession(true, Session.SESSION_TRANSACTED);
+ }
+ else if (config.getAckFrequency() > 0)
+ {
+ session = con.createSession(false, Session.DUPS_OK_ACKNOWLEDGE);
+ }
+ else
+ {
+ session = con.createSession(false, Session.AUTO_ACKNOWLEDGE);
+ }
+ consumer = session.createConsumer(dest);
+ consumer.setMessageListener(this);
+ if (_logger.isDebugEnabled())
+ {
+ System.out.println("Consumer: " + /*id +*/ " Receiving messages from : " + ((AMQDestination)dest).getAddressName() + "\n");
+ }
+
+ transacted = config.isTransacted();
+ txSize = config.getTransactionSize();
+ isRollback = config.getRollbackFrequency() > 0;
+ rollbackFrequency = config.getRollbackFrequency();
+ ackFrequency = config.getAckFrequency();
+
+ _logger.debug("Ready address : " + config.getReadyAddress());
+ if (config.getReadyAddress() != null)
+ {
+ MessageProducer prod = session.createProducer(AMQDestination
+ .createDestination(config.getReadyAddress()));
+ prod.send(session.createMessage());
+ if (_logger.isDebugEnabled())
+ {
+ _logger.debug("Sending message to ready address " + prod.getDestination());
+ }
+ }
+ }
+
+ public void resetCounters()
+ {
+ received = 0;
+ expected = 0;
+ report.clear();
+ }
+
+ public void onMessage(Message msg)
+ {
+ try
+ {
+ if (msg instanceof TextMessage &&
+ TestConfiguration.EOS.equals(((TextMessage)msg).getText()))
+ {
+ testCompleted.countDown();
+ return;
+ }
+
+ received++;
+ report.message(msg);
+
+ if (config.isPrintHeaders())
+ {
+ System.out.println(((AbstractJMSMessage)msg).toHeaderString());
+ }
+
+ if (config.isPrintContent())
+ {
+ System.out.println(((AbstractJMSMessage)msg).toBodyString());
+ }
+
+ if (transacted && (received % txSize == 0))
+ {
+ if (isRollback && (received % rollbackFrequency == 0))
+ {
+ session.rollback();
+ }
+ else
+ {
+ session.commit();
+ }
+ }
+ else if (ackFrequency > 0)
+ {
+ msg.acknowledge();
+ }
+
+ if (received >= expected)
+ {
+ testCompleted.countDown();
+ }
+
+ }
+ catch(Exception e)
+ {
+ _logger.error("Error when receiving messages",e);
+ }
+ }
+
+ public void waitforCompletion(int expected) throws Exception
+ {
+ this.expected = expected;
+ testCompleted.await();
+ }
+
+ public void tearDown() throws Exception
+ {
+ session.close();
+ }
+
+ public static void main(String[] args) throws Exception
+ {
+ TestConfiguration config = new JVMArgConfiguration();
+ Reporter reporter = new BasicReporter(ThroughputAndLatency.class,
+ System.out,
+ config.reportEvery(),
+ config.isReportHeader());
+ Destination dest = AMQDestination.createDestination(config.getAddress());
+ QpidReceive receiver = new QpidReceive(reporter,config, config.createConnection(),dest);
+ receiver.setUp();
+ receiver.waitforCompletion(config.getMsgCount() + config.getSendEOS());
+ if (config.isReportTotal())
+ {
+ reporter.report();
+ }
+ receiver.tearDown();
+ }
}
diff --git a/java/tools/src/main/java/org/apache/qpid/tools/QpidSend.java b/java/tools/src/main/java/org/apache/qpid/tools/QpidSend.java
index c058b83d41..3d321dcade 100644
--- a/java/tools/src/main/java/org/apache/qpid/tools/QpidSend.java
+++ b/java/tools/src/main/java/org/apache/qpid/tools/QpidSend.java
@@ -43,249 +43,261 @@ import org.slf4j.LoggerFactory;
public class QpidSend
{
- private Connection con;
- private Session session;
- private Destination dest;
- private MessageProducer producer;
- private MessageType msgType;
- private Message msg;
- private Object payload;
- private List<Object> payloads;
- private boolean cacheMsg = false;
- private boolean randomMsgSize = false;
- private boolean durable = false;
- private Random random;
- private int msgSizeRange = 1024;
- private int totalMsgCount = 0;
- private boolean rateLimitProducer = false;
- private boolean transacted = false;
- private int txSize = 0;
+ private Connection con;
+ private Session session;
+ private Destination dest;
+ private MessageProducer producer;
+ private MessageType msgType;
+ private Message msg;
+ private Object payload;
+ private List<Object> payloads;
+ private boolean cacheMsg = false;
+ private boolean randomMsgSize = false;
+ private boolean durable = false;
+ private Random random;
+ private int msgSizeRange = 1024;
+ private int totalMsgCount = 0;
+ private boolean rateLimitProducer = false;
+ private boolean transacted = false;
+ private int txSize = 0;
- private static final Logger _logger = LoggerFactory.getLogger(QpidSend.class);
- Reporter report;
- TestConfiguration config;
+ private static final Logger _logger = LoggerFactory.getLogger(QpidSend.class);
+ Reporter report;
+ TestConfiguration config;
- public QpidSend(Reporter report, TestConfiguration config, Connection con, Destination dest)
- {
- this(report,config, con, dest, UUID.randomUUID().toString());
- }
+ public QpidSend(Reporter report, TestConfiguration config, Connection con, Destination dest)
+ {
+ this(report,config, con, dest, UUID.randomUUID().toString());
+ }
- public QpidSend(Reporter report, TestConfiguration config, Connection con, Destination dest, String prefix)
- {
- //System.out.println("Producer ID : " + id);
- this.report = report;
- this.config = config;
- this.con = con;
- this.dest = dest;
- }
+ public QpidSend(Reporter report, TestConfiguration config, Connection con, Destination dest, String prefix)
+ {
+ //System.out.println("Producer ID : " + id);
+ this.report = report;
+ this.config = config;
+ this.con = con;
+ this.dest = dest;
+ }
- public void setUp() throws Exception
- {
- if (config.isTransacted())
- {
- session = con.createSession(true, Session.SESSION_TRANSACTED);
- }
- else
- {
- session = con.createSession(false, Session.AUTO_ACKNOWLEDGE);
- }
+ public void setUp() throws Exception
+ {
+ con.start();
+ if (config.isTransacted())
+ {
+ session = con.createSession(true, Session.SESSION_TRANSACTED);
+ }
+ else
+ {
+ session = con.createSession(false, Session.AUTO_ACKNOWLEDGE);
+ }
- durable = config.isDurable();
- rateLimitProducer = config.getSendRate() > 0 ? true : false;
- if (_logger.isDebugEnabled() && rateLimitProducer)
- {
- System.out.println("The test will attempt to limit the producer to " + config.getSendRate() + " msg/sec");
- }
+ durable = config.isDurable();
+ rateLimitProducer = config.getSendRate() > 0 ? true : false;
+ if (_logger.isDebugEnabled() && rateLimitProducer)
+ {
+ _logger.debug("The test will attempt to limit the producer to " + config.getSendRate() + " msg/sec");
+ }
- transacted = config.isTransacted();
- txSize = config.getTransactionSize();
+ transacted = config.isTransacted();
+ txSize = config.getTransactionSize();
- msgType = MessageType.getType(config.getMessageType());
- // if message caching is enabled we pre create the message
- // else we pre create the payload
- if (config.isCacheMessage())
- {
- cacheMsg = true;
- msg = createMessage(createPayload(config.getMsgSize()));
- msg.setJMSDeliveryMode(durable?
- DeliveryMode.PERSISTENT :
- DeliveryMode.NON_PERSISTENT
- );
- }
- else if (config.isRandomMsgSize())
- {
- random = new Random(20080921);
- randomMsgSize = true;
- msgSizeRange = config.getMsgSize();
- payloads = new ArrayList<Object>(msgSizeRange);
+ msgType = MessageType.getType(config.getMessageType());
+ // if message caching is enabled we pre create the message
+ // else we pre create the payload
+ if (config.isCacheMessage())
+ {
+ cacheMsg = true;
+ msg = createMessage(createPayload(config.getMsgSize()));
+ msg.setJMSDeliveryMode(durable?
+ DeliveryMode.PERSISTENT :
+ DeliveryMode.NON_PERSISTENT
+ );
+ }
+ else if (config.isRandomMsgSize())
+ {
+ random = new Random(20080921);
+ randomMsgSize = true;
+ msgSizeRange = config.getMsgSize();
+ payloads = new ArrayList<Object>(msgSizeRange);
- for (int i=0; i < msgSizeRange; i++)
- {
- payloads.add(createPayload(i));
- }
- }
- else
- {
- payload = createPayload(config.getMsgSize());
- }
+ for (int i=0; i < msgSizeRange; i++)
+ {
+ payloads.add(createPayload(i));
+ }
+ }
+ else
+ {
+ payload = createPayload(config.getMsgSize());
+ }
- producer = session.createProducer(dest);
- if (_logger.isDebugEnabled())
- {
- System.out.println("Producer: " + /*id +*/ " Sending messages to: " + ((AMQDestination)dest).getAddressName());
- }
- producer.setDisableMessageID(config.isDisableMessageID());
- producer.setDisableMessageTimestamp(config.isDisableTimestamp());
- }
+ producer = session.createProducer(dest);
+ if (_logger.isDebugEnabled())
+ {
+ _logger.debug("Producer: " + /*id +*/ " Sending messages to: " + ((AMQDestination)dest).getAddressName());
+ }
+ producer.setDisableMessageID(config.isDisableMessageID());
+ //we add a separate timestamp to allow interoperability with other clients.
+ producer.setDisableMessageTimestamp(true);
+ if (config.getTTL() > 0)
+ {
+ producer.setTimeToLive(config.getTTL());
+ }
+ if (config.getPriority() > 0)
+ {
+ producer.setPriority(config.getPriority());
+ }
+ }
- Object createPayload(int size)
- {
- if (msgType == MessageType.TEXT)
- {
- return MessageFactory.createMessagePayload(size);
- }
- else
- {
- return MessageFactory.createMessagePayload(size).getBytes();
- }
- }
+ 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;
- }
- }
+ 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
- {
- if (cacheMsg)
- {
- return msg;
- }
- else
- {
- Message m;
+ protected Message getNextMessage() throws Exception
+ {
+ if (cacheMsg)
+ {
+ return msg;
+ }
+ else
+ {
+ Message m;
- if (!randomMsgSize)
- {
- m = createMessage(payload);
- }
- else
- {
- m = createMessage(payloads.get(random.nextInt(msgSizeRange)));
- }
- m.setJMSDeliveryMode(durable?
- DeliveryMode.PERSISTENT :
- DeliveryMode.NON_PERSISTENT
- );
- return m;
- }
- }
+ if (!randomMsgSize)
+ {
+ m = createMessage(payload);
+ }
+ else
+ {
+ m = createMessage(payloads.get(random.nextInt(msgSizeRange)));
+ }
+ m.setJMSDeliveryMode(durable?
+ DeliveryMode.PERSISTENT :
+ DeliveryMode.NON_PERSISTENT
+ );
+ return m;
+ }
+ }
- public void commit() throws Exception
- {
- session.commit();
- }
+ public void commit() throws Exception
+ {
+ session.commit();
+ }
- public void send() throws Exception
- {
- send(config.getMsgCount());
- }
+ public void send() throws Exception
+ {
+ send(config.getMsgCount());
+ }
- public void send(int count) throws Exception
- {
- int sendRate = config.getSendRate();
- if (rateLimitProducer)
- {
- int iterations = count/sendRate;
- int remainder = count%sendRate;
- for (int i=0; i < iterations; i++)
- {
- long iterationStart = Clock.getTime();
- sendMessages(sendRate);
- long elapsed = (Clock.getTime() - iterationStart)*Clock.convertToMiliSecs();
- long diff = Clock.SEC - elapsed;
- if (diff > 0)
- {
- // We have sent more messages in a sec than specified by the rate.
- Thread.sleep(diff);
- }
- }
- sendMessages(remainder);
- }
- else
- {
- sendMessages(count);
- }
- }
+ public void send(int count) throws Exception
+ {
+ int sendRate = config.getSendRate();
+ if (rateLimitProducer)
+ {
+ int iterations = count/sendRate;
+ int remainder = count%sendRate;
+ for (int i=0; i < iterations; i++)
+ {
+ long iterationStart = System.currentTimeMillis();
+ sendMessages(sendRate);
+ long elapsed = System.currentTimeMillis() - iterationStart;
+ long diff = Clock.SEC - elapsed;
+ if (diff > 0)
+ {
+ // We have sent more messages in a sec than specified by the rate.
+ Thread.sleep(diff);
+ }
+ }
+ sendMessages(remainder);
+ }
+ else
+ {
+ sendMessages(count);
+ }
+ }
- private void sendMessages(int count) throws Exception
- {
- boolean isTimestamp = config.isReportLatency();
- for(int i=0; i < count; i++ )
- {
- Message msg = getNextMessage();
- if (isTimestamp)
- {
- msg.setLongProperty(TestConfiguration.TIMESTAMP, Clock.getTime());
- }
- producer.send(msg);
- report.message(msg);
- totalMsgCount++;
+ private void sendMessages(int count) throws Exception
+ {
+ boolean isTimestamp = !config.isDisableTimestamp();
+ long s = System.currentTimeMillis();
+ for(int i=0; i < count; i++ )
+ {
+ Message msg = getNextMessage();
+ if (isTimestamp)
+ {
+ msg.setLongProperty(TestConfiguration.TIMESTAMP, System.currentTimeMillis());
+ }
+ producer.send(msg);
+ //report.message(msg);
+ totalMsgCount++;
- if ( transacted && ((totalMsgCount) % txSize == 0))
- {
- session.commit();
- }
- }
- }
+ if ( transacted && ((totalMsgCount) % txSize == 0))
+ {
+ session.commit();
+ }
+ }
+ long e = System.currentTimeMillis() - s;
+ //System.out.println("Rate : " + totalMsgCount/e);
+ }
- public void resetCounters()
- {
- totalMsgCount = 0;
- report.clear();
- }
+ public void resetCounters()
+ {
+ totalMsgCount = 0;
+ report.clear();
+ }
- public void sendEndMessage() throws Exception
- {
- Message msg = session.createMessage();
- msg.setBooleanProperty(TestConfiguration.EOS, true);
- producer.send(msg);
- }
-
- public void tearDown() throws Exception
- {
- session.close();
- }
+ public void sendEndMessage() throws Exception
+ {
+ Message msg = session.createTextMessage(TestConfiguration.EOS);
+ producer.send(msg);
+ }
- public static void main(String[] args) throws Exception
- {
- TestConfiguration config = new JVMArgConfiguration();
- Reporter reporter = new BasicReporter(Throughput.class,
- System.out,
- config.reportEvery(),
- config.isReportHeader()
- );
- Destination dest = AMQDestination.createDestination(config.getAddress());
- QpidSend sender = new QpidSend(reporter,config, config.createConnection(),dest);
- sender.setUp();
- sender.send();
- if (config.getSendEOS() > 0)
- {
- sender.sendEndMessage();
- }
- if (config.isReportTotal())
- {
- reporter.report();
- }
- sender.tearDown();
- }
+ public void tearDown() throws Exception
+ {
+ session.close();
+ }
+
+ public static void main(String[] args) throws Exception
+ {
+ TestConfiguration config = new JVMArgConfiguration();
+ Reporter reporter = new BasicReporter(Throughput.class,
+ System.out,
+ config.reportEvery(),
+ config.isReportHeader()
+ );
+ Destination dest = AMQDestination.createDestination(config.getAddress());
+ QpidSend sender = new QpidSend(reporter,config, config.createConnection(),dest);
+ sender.setUp();
+ sender.send();
+ if (config.getSendEOS() > 0)
+ {
+ sender.sendEndMessage();
+ }
+ if (config.isReportTotal())
+ {
+ reporter.report();
+ }
+ sender.tearDown();
+ }
}
diff --git a/java/tools/src/main/java/org/apache/qpid/tools/TestConfiguration.java b/java/tools/src/main/java/org/apache/qpid/tools/TestConfiguration.java
index 7f7df0e5e6..18870bac59 100644
--- a/java/tools/src/main/java/org/apache/qpid/tools/TestConfiguration.java
+++ b/java/tools/src/main/java/org/apache/qpid/tools/TestConfiguration.java
@@ -26,20 +26,20 @@ import javax.jms.Connection;
public interface TestConfiguration
{
- 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))
+ 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;
}
@@ -47,80 +47,88 @@ public interface TestConfiguration
{
return OBJECT;
}*/
- else
- {
- throw new Exception("Unsupported message type");
- }
- }
- };
+ else
+ {
+ throw new Exception("Unsupported message type");
+ }
+ }
+ };
+
+ public final static String TIMESTAMP = "ts";
+
+ public final static String EOS = "eos";
+
+ public final static String SEQUENCE_NUMBER = "sn";
+
+ public String getUrl();
- public final static String TIMESTAMP = "ts";
+ public String getHost();
- public final static String EOS = "eos";
+ public int getPort();
- public final static String SEQUENCE_NUMBER = "sn";
+ public String getAddress();
- public String getUrl();
+ public long getTimeout();
- public String getHost();
+ public int getAckMode();
- public int getPort();
+ public int getMsgCount();
- public String getAddress();
+ public int getMsgSize();
- public int getAckMode();
+ public int getRandomMsgSizeStartFrom();
- public int getMsgCount();
+ public boolean isDurable();
- public int getMsgSize();
+ public boolean isTransacted();
- public int getRandomMsgSizeStartFrom();
+ public int getTransactionSize();
- public boolean isDurable();
+ public int getWarmupCount();
- public boolean isTransacted();
+ public boolean isCacheMessage();
- public int getTransactionSize();
+ public boolean isDisableMessageID();
- public int getWarmupCount();
+ public boolean isDisableTimestamp();
- public boolean isCacheMessage();
+ public boolean isRandomMsgSize();
- public boolean isDisableMessageID();
+ public String getMessageType();
- public boolean isDisableTimestamp();
+ public boolean isPrintStdDev();
- public boolean isRandomMsgSize();
+ public int getSendRate();
- public String getMessageType();
+ public boolean isExternalController();
- public boolean isPrintStdDev();
+ public boolean isUseUniqueDests();
- public int getSendRate();
+ public int getAckFrequency();
- public boolean isExternalController();
+ public Connection createConnection() throws Exception;
- public boolean isUseUniqueDests();
+ public DecimalFormat getDecimalFormat();
- public int getAckFrequency();
+ public int reportEvery();
- public Connection createConnection() throws Exception;
+ public boolean isReportTotal();
- public DecimalFormat getDecimalFormat();
+ public boolean isReportHeader();
- public int reportEvery();
+ public int getSendEOS();
- public boolean isReportTotal();
+ public int getConnectionCount();
- public boolean isReportHeader();
+ public int getRollbackFrequency();
- public boolean isReportLatency();
+ public boolean isPrintHeaders();
- public int getSendEOS();
+ public boolean isPrintContent();
- public int getConnectionCount();
+ public long getTTL();
- public int getRollbackFrequency();
+ public int getPriority();
- public boolean isPrintHeaders();
+ public String getReadyAddress();
} \ No newline at end of file
diff --git a/java/tools/src/main/java/org/apache/qpid/tools/report/Statistics.java b/java/tools/src/main/java/org/apache/qpid/tools/report/Statistics.java
index 73efd1f1e0..db8b4ddcee 100644
--- a/java/tools/src/main/java/org/apache/qpid/tools/report/Statistics.java
+++ b/java/tools/src/main/java/org/apache/qpid/tools/report/Statistics.java
@@ -25,115 +25,121 @@ import java.text.DecimalFormat;
import javax.jms.Message;
+import org.apache.qpid.tools.TestConfiguration;
+
public interface Statistics
{
- public void message(Message msg);
- public void report(PrintStream out);
- public void header(PrintStream out);
- public void clear();
-
- static class Throughput implements Statistics
- {
- DecimalFormat df = new DecimalFormat("###.##");
- int messages = 0;
- long start = 0;
- boolean started = false;
-
- @Override
- public void message(Message msg)
- {
- ++messages;
- if (!started)
- {
- start = System.currentTimeMillis();
- started = true;
- }
- }
-
- @Override
- public void report(PrintStream out)
- {
- long elapsed = System.currentTimeMillis() - start;
- out.print(df.format((double)messages/(double)elapsed));
- }
-
- @Override
- public void header(PrintStream out)
- {
- out.print("tp(m/s)");
- }
-
- public void clear()
- {
- messages = 0;
- start = 0;
- started = false;
- }
- }
-
- static class ThroughputAndLatency extends Throughput
- {
- long minLatency = Long.MAX_VALUE;
- long maxLatency = Long.MIN_VALUE;
- double totalLatency = 0;
- int sampleCount = 0;
-
- @Override
- public void message(Message msg)
- {
- super.message(msg);
- try
- {
- long ts = msg.getLongProperty("ts");
- long latency = System.currentTimeMillis() - ts;
- minLatency = Math.min(latency, minLatency);
- maxLatency = Math.min(latency, maxLatency);
- totalLatency = totalLatency + latency;
- sampleCount++;
- }
- catch(Exception e)
- {
- System.out.println("Error calculating latency");
- }
- }
-
- @Override
- public void report(PrintStream out)
- {
- super.report(out);
- double avgLatency = totalLatency/(double)sampleCount;
- out.append('\t')
- .append(String.valueOf(minLatency))
- .append('\t')
- .append(String.valueOf(maxLatency))
- .append('\t')
- .append(df.format(avgLatency));
-
- out.flush();
- }
-
- @Override
- public void header(PrintStream out)
- {
- super.header(out);
- out.append('\t')
- .append("l-min")
- .append('\t')
- .append("l-max")
- .append('\t')
- .append("l-avg");
-
- out.flush();
- }
-
- public void clear()
- {
- super.clear();
- minLatency = 0;
- maxLatency = 0;
- totalLatency = 0;
- sampleCount = 0;
- }
- }
+ public void message(Message msg);
+ public void report(PrintStream out);
+ public void header(PrintStream out);
+ public void clear();
+
+ static class Throughput implements Statistics
+ {
+ DecimalFormat df = new DecimalFormat("###");
+ int messages = 0;
+ long start = 0;
+ boolean started = false;
+
+ @Override
+ public void message(Message msg)
+ {
+ ++messages;
+ if (!started)
+ {
+ start = System.currentTimeMillis();
+ started = true;
+ }
+ }
+
+ @Override
+ public void report(PrintStream out)
+ {
+ long elapsed = System.currentTimeMillis() - start;
+ out.println(df.format((double)messages/(double)elapsed));
+ }
+
+ @Override
+ public void header(PrintStream out)
+ {
+ out.println("tp(m/s)");
+ }
+
+ public void clear()
+ {
+ messages = 0;
+ start = 0;
+ started = false;
+ }
+ }
+
+ static class ThroughputAndLatency extends Throughput
+ {
+ long minLatency = Long.MAX_VALUE;
+ long maxLatency = Long.MIN_VALUE;
+ double totalLatency = 0;
+ int sampleCount = 0;
+
+ @Override
+ public void message(Message msg)
+ {
+ super.message(msg);
+ try
+ {
+ long ts = msg.getLongProperty(TestConfiguration.TIMESTAMP);
+ long latency = System.currentTimeMillis() - ts;
+ minLatency = Math.min(latency, minLatency);
+ maxLatency = Math.max(latency, maxLatency);
+ totalLatency = totalLatency + latency;
+ sampleCount++;
+ }
+ catch(Exception e)
+ {
+ System.out.println("Error calculating latency " + e);
+ }
+ }
+
+ @Override
+ public void report(PrintStream out)
+ {
+ long elapsed = System.currentTimeMillis() - start;
+ double rate = (double)messages/(double)elapsed;
+ double avgLatency = totalLatency/(double)sampleCount;
+ out.append("\n")
+ .append(df.format(rate))
+ .append('\t')
+ .append(String.valueOf(minLatency))
+ .append('\t')
+ .append(String.valueOf(maxLatency))
+ .append('\t')
+ .append(df.format(avgLatency))
+ .append("\n");
+
+ out.flush();
+ }
+
+ @Override
+ public void header(PrintStream out)
+ {
+ out.append("tp(m/s)")
+ .append('\t')
+ .append("l-min")
+ .append('\t')
+ .append("l-max")
+ .append('\t')
+ .append("l-avg");
+
+ out.flush();
+ }
+
+ public void clear()
+ {
+ super.clear();
+ minLatency = 0;
+ maxLatency = 0;
+ totalLatency = 0;
+ sampleCount = 0;
+ }
+ }
}
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 9442b5a5c0..66e8076767 100644
--- a/packaging/windows/INSTALL_NOTES.html
+++ b/packaging/windows/INSTALL_NOTES.html
@@ -1,11 +1,11 @@
<html>
<head>
-<title>Apache Qpid C++ 0.17 Installation Notes</title>
+<title>Apache Qpid C++ 0.19 Installation Notes</title>
</head>
<body>
-<H1>Apache Qpid C++ 0.17 Installation Notes</H1>
+<H1>Apache Qpid C++ 0.19 Installation Notes</H1>
-<p>Thank you for installing Apache Qpid version 0.17 for Windows.
+<p>Thank you for installing Apache Qpid version 0.19 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>
@@ -83,7 +83,7 @@ default; therefore, to gain support for durable items the persistence plugin
must be loaded into the broker. This can be done using the
<code>--load-module</code> option to load the needed plugins. For example:
<pre>
-cd "C:\Program Files\Apache\qpidc-0.17"
+cd "C:\Program Files\Apache\qpidc-0.19"
qpidd.exe --load-module plugins\broker\store.dll --load-module plugins\broker\msclfs_store.dll
</pre>
The <code>--load-module</code> option can also take a full path. The option
diff --git a/packaging/windows/installer.proj b/packaging/windows/installer.proj
index 699981cea0..676205898f 100644
--- a/packaging/windows/installer.proj
+++ b/packaging/windows/installer.proj
@@ -32,7 +32,7 @@
<source_root>$(MSBuildProjectDirectory)\..\..</source_root>
<staging_dir>$(MSBuildProjectDirectory)\stage</staging_dir>
<bits Condition="'$(bits)' == ''">32</bits>
- <qpid_version>0.17</qpid_version>
+ <qpid_version>0.19</qpid_version>
<OutputName>qpidc</OutputName>
<OutputType>Package</OutputType>
<WixToolPath>C:\Program Files (x86)\Windows Installer XML v3.5\bin</WixToolPath>
diff --git a/python/qpid/connection.py b/python/qpid/connection.py
index 66e1cb49be..2453f38c34 100644
--- a/python/qpid/connection.py
+++ b/python/qpid/connection.py
@@ -166,8 +166,9 @@ class Connection(Framer):
# If we have a security layer and it sends us no decoded data,
# that's OK as long as its return code is happy.
if self.security_layer_rx:
- status, data = self.security_layer_rx.decode(data)
- if not status:
+ try:
+ data = self.security_layer_rx.decode(data)
+ except:
self.detach_all()
break
# When we do not use SSL transport, we get periodic
diff --git a/python/qpid/delegates.py b/python/qpid/delegates.py
index 685cf49f54..5e44a3a6dc 100644
--- a/python/qpid/delegates.py
+++ b/python/qpid/delegates.py
@@ -24,13 +24,7 @@ from exceptions import VersionError, Closed
from logging import getLogger
from ops import Control
import sys
-
-_have_sasl = None
-try:
- import saslwrapper
- _have_sasl = True
-except:
- pass
+from qpid import sasl
log = getLogger("qpid.io.ctl")
@@ -172,20 +166,19 @@ class Client(Delegate):
self.username = username
self.password = password
- if _have_sasl:
- self.sasl = saslwrapper.Client()
- if username and len(username) > 0:
- self.sasl.setAttr("username", str(username))
- if password and len(password) > 0:
- self.sasl.setAttr("password", str(password))
- self.sasl.setAttr("service", str(kwargs.get("service", "qpidd")))
- if "host" in kwargs:
- self.sasl.setAttr("host", str(kwargs["host"]))
- if "min_ssf" in kwargs:
- self.sasl.setAttr("minssf", kwargs["min_ssf"])
- if "max_ssf" in kwargs:
- self.sasl.setAttr("maxssf", kwargs["max_ssf"])
- self.sasl.init()
+ self.sasl = sasl.Client()
+ if username and len(username) > 0:
+ self.sasl.setAttr("username", str(username))
+ if password and len(password) > 0:
+ self.sasl.setAttr("password", str(password))
+ self.sasl.setAttr("service", str(kwargs.get("service", "qpidd")))
+ if "host" in kwargs:
+ self.sasl.setAttr("host", str(kwargs["host"]))
+ if "min_ssf" in kwargs:
+ self.sasl.setAttr("minssf", kwargs["min_ssf"])
+ if "max_ssf" in kwargs:
+ self.sasl.setAttr("maxssf", kwargs["max_ssf"])
+ self.sasl.init()
def start(self):
# XXX
@@ -204,39 +197,29 @@ class Client(Delegate):
mech_list += str(mech) + " "
mech = None
initial = None
- if _have_sasl:
- status, mech, initial = self.sasl.start(mech_list)
- if status == False:
- raise Closed("SASL error: %s" % self.sasl.getError())
- else:
- if self.username and self.password and ("PLAIN" in mech_list):
- mech = "PLAIN"
- initial = "\0%s\0%s" % (self.username, self.password)
- else:
- mech = "ANONYMOUS"
- if not mech in mech_list:
- raise Closed("No acceptable SASL authentication mechanism available")
+ try:
+ mech, initial = self.sasl.start(mech_list)
+ except Exception, e:
+ raise Closed(str(e))
ch.connection_start_ok(client_properties=self.client_properties,
mechanism=mech, response=initial)
def connection_secure(self, ch, secure):
resp = None
- if _have_sasl:
- status, resp = self.sasl.step(secure.challenge)
- if status == False:
- raise Closed("SASL error: %s" % self.sasl.getError())
+ try:
+ resp = self.sasl.step(secure.challenge)
+ except Exception, e:
+ raise Closed(str(e))
ch.connection_secure_ok(response=resp)
def connection_tune(self, ch, tune):
ch.connection_tune_ok(heartbeat=self.heartbeat)
ch.connection_open()
- if _have_sasl:
- self.connection.user_id = self.sasl.getUserId()
- self.connection.security_layer_tx = self.sasl
+ self.connection.user_id = self.sasl.auth_username()
+ self.connection.security_layer_tx = self.sasl
def connection_open_ok(self, ch, open_ok):
- if _have_sasl:
- self.connection.security_layer_rx = self.sasl
+ self.connection.security_layer_rx = self.sasl
self.connection.opened = True
notify(self.connection.condition)
diff --git a/python/qpid/framer.py b/python/qpid/framer.py
index 47f57cf649..8e4ef014f1 100644
--- a/python/qpid/framer.py
+++ b/python/qpid/framer.py
@@ -51,9 +51,10 @@ class Framer(Packer):
self.sock_lock.acquire()
try:
if self.security_layer_tx:
- status, cipher_buf = self.security_layer_tx.encode(self.tx_buf)
- if status == False:
- raise Closed(self.security_layer_tx.getError())
+ try:
+ cipher_buf = self.security_layer_tx.encode(self.tx_buf)
+ except SASLError, e:
+ raise Closed(str(e))
self._write(cipher_buf)
else:
self._write(self.tx_buf)
@@ -91,9 +92,10 @@ class Framer(Packer):
try:
s = self.sock.recv(n) # NOTE: instead of "n", arg should be "self.maxbufsize"
if self.security_layer_rx:
- status, s = self.security_layer_rx.decode(s)
- if status == False:
- raise Closed(self.security_layer_tx.getError())
+ try:
+ s = self.security_layer_rx.decode(s)
+ except SASLError, e:
+ raise Closed(str(e))
except socket.timeout:
if self.aborted():
raise Closed()
diff --git a/python/qpid/messaging/util.py b/python/qpid/messaging/util.py
index 265cf7d51f..726cfd5172 100644
--- a/python/qpid/messaging/util.py
+++ b/python/qpid/messaging/util.py
@@ -50,10 +50,13 @@ def set_reconnect_urls(conn, msg):
reconnect_urls = []
urls = msg.properties["amq.failover"]
for u in urls:
+ # FIXME aconway 2012-06-12: Nasty hack parsing of the C++ broker's URL format.
if u.startswith("amqp:"):
- for p in u[5:].split(","):
- parts = p.split(":")
- host, port = parts[1:3]
+ for a in u[5:].split(","):
+ parts = a.split(":")
+ # Handle IPv6 addresses which have : in the host part.
+ port = parts[-1] # Last : separated field is port
+ host = ":".join(parts[1:-1]) # First : separated field is protocol, host is the rest.
reconnect_urls.append("%s:%s" % (host, port))
conn.reconnect_urls = reconnect_urls
log.warn("set reconnect_urls for conn %s: %s", conn, reconnect_urls)
diff --git a/python/qpid/sasl.py b/python/qpid/sasl.py
index 677a5e4e22..25de6dec45 100644
--- a/python/qpid/sasl.py
+++ b/python/qpid/sasl.py
@@ -29,6 +29,9 @@ class WrapperClient:
def setAttr(self, name, value):
status = self._cli.setAttr(str(name), str(value))
+ if status and name == 'username':
+ status = self._cli.setAttr('externaluser', str(value))
+
if not status:
raise SASLError(self._cli.getError())
diff --git a/python/qpid/selector.py b/python/qpid/selector.py
index ca5946c3f9..ff94091da0 100644
--- a/python/qpid/selector.py
+++ b/python/qpid/selector.py
@@ -16,7 +16,7 @@
# specific language governing permissions and limitations
# under the License.
#
-import atexit, time
+import atexit, time, errno
from compat import select, set, selectable_waiter
from threading import Thread, Lock
@@ -111,12 +111,24 @@ class Selector:
else:
wakeup = min(wakeup, t)
- if wakeup is None:
- timeout = None
- else:
- timeout = max(0, wakeup - time.time())
+ rd = []
+ wr = []
+ ex = []
- rd, wr, ex = select(self.reading, self.writing, (), timeout)
+ while True:
+ try:
+ if wakeup is None:
+ timeout = None
+ else:
+ timeout = max(0, wakeup - time.time())
+ rd, wr, ex = select(self.reading, self.writing, (), timeout)
+ break
+ except Exception, (err, strerror):
+ # Repeat the select call if we were interrupted.
+ if err == errno.EINTR:
+ continue
+ else:
+ raise
for sel in wr:
if sel.writing():
diff --git a/python/qpid/tests/messaging/endpoints.py b/python/qpid/tests/messaging/endpoints.py
index 62deacd0bd..a82a9e95ed 100644
--- a/python/qpid/tests/messaging/endpoints.py
+++ b/python/qpid/tests/messaging/endpoints.py
@@ -1333,3 +1333,15 @@ class SenderTests(Base):
self.drain(self.rcv, expected=msgs)
self.ssn.acknowledge()
assert caught, "did not exceed capacity"
+
+ def testEINTR(self):
+ m1 = self.content("testEINTR", 0)
+ m2 = self.content("testEINTR", 1)
+
+ self.snd.send(m1, timeout=self.timeout())
+ try:
+ os.setuid(500)
+ assert False, "setuid should fail"
+ except:
+ pass
+ self.snd.send(m2, timeout=self.timeout())
diff --git a/python/qpid/util.py b/python/qpid/util.py
index 89677289e2..7541595453 100644
--- a/python/qpid/util.py
+++ b/python/qpid/util.py
@@ -25,9 +25,9 @@ except ImportError:
from socket import ssl as wrap_socket
class ssl:
- def __init__(self, sock):
+ def __init__(self, sock, keyfile=None, certfile=None, trustfile=None):
self.sock = sock
- self.ssl = wrap_socket(sock)
+ self.ssl = wrap_socket(sock, keyfile=keyfile, certfile=certfile, ca_certs=trustfile)
def recv(self, n):
return self.ssl.read(n)
diff --git a/python/setup.py b/python/setup.py
index 225ee44b91..0b9d99a1af 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.17",
+ version="0.19",
author="Apache Qpid",
author_email="dev@qpid.apache.org",
packages=["mllib", "qpid", "qpid.messaging", "qpid.tests",
diff --git a/specs/apache-filters.xml b/specs/apache-filters.xml
index 24e1d521e2..a4e40aa93c 100644
--- a/specs/apache-filters.xml
+++ b/specs/apache-filters.xml
@@ -17,7 +17,6 @@
specific language governing permissions and limitations
under the License.
-->
-<!DOCTYPE amqp SYSTEM "amqp.dtd">
<?xml-stylesheet type="text/xsl" href="amqp.xsl"?>
<amqp name="apache-filters" label="Apache Proposed AMQP 1-0 Filters">
@@ -175,9 +174,9 @@ JMSType | annotation jms-type in message-annotations section
where <i>field_name</i> is the appropriate AMQP 1.0 field
named in the table above, with the hyphen replaced by an
underscore. For example, the selector: "JMSCorrelationID =
- ’abc’ AND color = ’blue’ AND weight > 2500" would be
- transferred over the wire as: "amqp.correlation_id = ’abc’
- AND color = ’blue’ AND weight > 2500"
+ 'abc' AND color = 'blue' AND weight > 2500" would be
+ transferred over the wire as: "amqp.correlation_id = 'abc'
+ AND color = 'blue' AND weight > 2500"
</p>
<p>
The "properties" of the JMS message are equivalent to the AMQP application-properties
diff --git a/specs/management-schema.xml b/specs/management-schema.xml
index 66e122b049..5d1fbe0110 100644
--- a/specs/management-schema.xml
+++ b/specs/management-schema.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
@@ -81,7 +81,6 @@
<property name="systemRef" type="objId" references="System" access="RO" desc="System ID" parentRef="y"/>
<property name="port" type="uint16" access="RO" desc="TCP Port for AMQP Service"/>
<property name="workerThreads" type="uint16" access="RO" desc="Thread pool size"/>
- <property name="maxConns" type="uint16" access="RO" desc="Maximum allowed connections"/>
<property name="connBacklog" type="uint16" access="RO" desc="Connection backlog limit for listening socket"/>
<property name="stagingThreshold" type="uint32" access="RO" desc="Broker stages messages over this size to disk"/>
<property name="mgmtPublish" type="bool" access="RO" desc="Broker's management agent sends unsolicited data on the publish interval"/>
@@ -164,20 +163,20 @@
<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"/>
+ <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"/>
+ <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="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>
@@ -220,7 +219,7 @@
<property name="durable" type="bool" access="RC"/>
<property name="autoDelete" type="bool" access="RC"/>
- <property name="exclusive" type="bool" access="RC"/>
+ <property name="exclusive" type="bool" access="RO"/>
<property name="arguments" type="map" access="RO" desc="Arguments supplied in queue.declare"/>
<property name="altExchange" type="objId" references="Exchange" access="RO" optional="y"/>
@@ -321,7 +320,7 @@
<statistic name="msgMatched" type="count64"/>
</class>
-
+
<!--
===============================================================
Subscription
@@ -338,7 +337,7 @@
<property name="arguments" type="map" access="RC"/>
<statistic name="delivered" type="count64" unit="message" desc="Messages delivered"/>
</class>
-
+
<!--
===============================================================
Connection
@@ -366,7 +365,7 @@
<statistic name="msgsFromClient" type="count64"/>
<statistic name="msgsToClient" type="count64"/>
- <method name="close"/>
+ <method name="close"/>
</class>
<!--
@@ -379,15 +378,17 @@
This class represents an inter-broker connection.
<property name="vhostRef" type="objId" references="Vhost" access="RC" index="y" parentRef="y"/>
- <property name="host" type="sstr" access="RC" index="y"/>
- <property name="port" type="uint16" access="RC" index="y"/>
- <property name="transport" type="sstr" access="RC"/>
+ <property name="name" type="sstr" access="RC" index="y"/>
+ <property name="host" type="sstr" access="RO"/>
+ <property name="port" type="uint16" access="RO"/>
+ <property name="transport" type="sstr" access="RO"/>
<property name="durable" type="bool" access="RC"/>
+ <property name="connectionRef" type="objId" references="Connection" access="RO"/>
<statistic name="state" type="sstr" desc="Operational state of the link"/>
<statistic name="lastError" type="lstr" desc="Reason link is not operational"/>
- <method name="close"/>
+ <method name="close"/>
<method name="bridge" desc="Bridge messages over the link">
<arg name="durable" dir="I" type="bool"/>
@@ -411,7 +412,8 @@
-->
<class name="Bridge">
<property name="linkRef" type="objId" references="Link" access="RC" index="y" parentRef="y"/>
- <property name="channelId" type="uint16" access="RC" index="y"/>
+ <property name="name" type="sstr" access="RC" index="y"/>
+ <property name="channelId" type="uint16" access="RO"/>
<property name="durable" type="bool" access="RC"/>
<property name="src" type="sstr" access="RC"/>
<property name="dest" type="sstr" access="RC"/>
@@ -422,7 +424,7 @@
<property name="excludes" type="sstr" access="RC"/>
<property name="dynamic" type="bool" access="RC"/>
<property name="sync" type="uint16" access="RC"/>
- <method name="close"/>
+ <method name="close"/>
</class>
@@ -441,7 +443,7 @@
<property name="expireTime" type="absTime" access="RO" optional="y"/>
<property name="maxClientRate" type="uint32" access="RO" unit="msgs/sec" optional="y"/>
- <statistic name="framesOutstanding" type="count32"/>
+ <statistic name="unackedMessages" type="uint64" unit="message" desc="Unacknowledged messages in the session"/>
<statistic name="TxnStarts" type="count64" unit="transaction" desc="Total transactions started "/>
<statistic name="TxnCommits" type="count64" unit="transaction" desc="Total transactions committed"/>
diff --git a/tests/setup.py b/tests/setup.py
index 36e7a0531a..8d5345d56e 100755
--- a/tests/setup.py
+++ b/tests/setup.py
@@ -20,7 +20,7 @@
from distutils.core import setup
setup(name="qpid-tests",
- version="0.17",
+ version="0.19",
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 107b34c82b..312dc22645 100644
--- a/tests/src/py/qpid_tests/broker_0_10/__init__.py
+++ b/tests/src/py/qpid_tests/broker_0_10/__init__.py
@@ -36,3 +36,4 @@ from extensions import *
from msg_groups import *
from new_api import *
from stats import *
+from qmf_events import *
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 2dd2291b2e..a1316ea854 100644
--- a/tests/src/py/qpid_tests/broker_0_10/management.py
+++ b/tests/src/py/qpid_tests/broker_0_10/management.py
@@ -302,9 +302,10 @@ class ManagementTest (TestBase010):
twenty = range(1,21)
props = session.delivery_properties(routing_key="routing_key")
+ mp = session.message_properties(application_headers={'x-qpid.trace' : 'A,B,C'})
for count in twenty:
body = "Reroute Message %d" % count
- msg = Message(props, body)
+ msg = Message(props, mp, body)
session.message_transfer(destination="amq.direct", message=msg)
pq = self.qmf.getObjects(_class="queue", name="reroute-queue")[0]
@@ -317,6 +318,16 @@ class ManagementTest (TestBase010):
self.assertEqual(pq.msgDepth,19)
self.assertEqual(aq.msgDepth,1)
+ "Verify that the trace was cleared on the rerouted message"
+ url = "%s://%s:%d" % (self.broker.scheme or "amqp", self.broker.host, self.broker.port)
+ conn = qpid.messaging.Connection(url)
+ conn.open()
+ sess = conn.session()
+ rx = sess.receiver("alt-queue1;{mode:browse}")
+ rm = rx.fetch(1)
+ self.assertEqual(rm.properties['x-qpid.trace'], '')
+ conn.close()
+
"Reroute top 9 messages from reroute-queue to alt.direct2"
result = pq.reroute(9, False, "alt.direct2", {})
self.assertEqual(result.status, 0)
diff --git a/tests/src/py/qpid_tests/broker_0_10/qmf_events.py b/tests/src/py/qpid_tests/broker_0_10/qmf_events.py
new file mode 100644
index 0000000000..7ab7b0a1ac
--- /dev/null
+++ b/tests/src/py/qpid_tests/broker_0_10/qmf_events.py
@@ -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.
+#
+
+from qpid.messaging import *
+from qpid.tests.messaging import Base
+from qpidtoollibs.broker import EventHelper
+import math
+
+class EventTests (Base):
+ """
+ Test various qmf events
+ """
+ def setup_connection(self):
+ return Connection.establish(self.broker, **self.connection_options())
+
+ def setup_session(self):
+ return self.conn.session()
+
+ def test_queue_declare(self):
+ helper = EventHelper()
+
+ # subscribe for queue declare events
+ rcv = self.ssn.receiver(helper.eventAddress("org.apache.qpid.broker", "queueDeclare"))
+ # create a queue
+ snd = self.ssn.sender("myq; {create:always, delete:always}")
+ # ensure we got an event
+ event = helper.event(rcv.fetch(timeout=1))
+ assert event.name, "org_apache_qpid_broker:queueDeclare"
+ assert event.qName, "myq"
+
+ def test_queue_delete(self):
+ helper = EventHelper()
+
+ rcv = self.ssn.receiver(helper.eventAddress("org.apache.qpid.broker", "queueDelete"))
+ snd = self.ssn.sender("myq; {create:always, delete:always}")
+ snd.close()
+
+ event = helper.event(rcv.fetch(timeout=1))
+ assert event.name, "org_apache_qpid_broker:queueDelete"
+ assert event.qName, "myq"
+
+ def test_queue_autodelete_exclusive(self):
+ helper = EventHelper()
+
+ rcv = self.ssn.receiver(helper.eventAddress("org.apache.qpid.broker", "queueDelete"))
+
+ #create new session
+ ssn2 = self.setup_session()
+ snd = ssn2.sender("myq; {create:always, node:{x-declare:{auto-delete:True, exclusive:True}}}")
+ ssn2.close()
+
+ event = helper.event(rcv.fetch(timeout=5))
+ assert event.name, "org_apache_qpid_broker:queueDelete"
+ assert event.qName, "myq"
+
+ def test_queue_autodelete_shared(self):
+ helper = EventHelper()
+
+ rcv = self.ssn.receiver(helper.eventAddress("org.apache.qpid.broker", "queueDelete"))
+
+ rcv2 = self.ssn.receiver("myq; {create:always, node:{x-declare:{auto-delete:True}}}")
+ rcv2.close()
+
+ event = helper.event(rcv.fetch(timeout=5))
+ assert event.name, "org_apache_qpid_broker:queueDelete"
+ assert event.qName, "myq"
+
diff --git a/tests/src/py/qpid_tests/broker_0_10/query.py b/tests/src/py/qpid_tests/broker_0_10/query.py
index d57e964982..fd741821d5 100644
--- a/tests/src/py/qpid_tests/broker_0_10/query.py
+++ b/tests/src/py/qpid_tests/broker_0_10/query.py
@@ -26,7 +26,7 @@ class QueryTests(TestBase010):
def test_queue_query(self):
session = self.session
- session.queue_declare(queue="my-queue", exclusive=True)
+ session.queue_declare(queue="my-queue", exclusive=True, auto_delete=True)
result = session.queue_query(queue="my-queue")
self.assertEqual("my-queue", result.queue)
diff --git a/tools/setup.py b/tools/setup.py
index 302c25502f..c9dc21c620 100755
--- a/tools/setup.py
+++ b/tools/setup.py
@@ -20,7 +20,7 @@
from distutils.core import setup
setup(name="qpid-tools",
- version="0.17",
+ version="0.19",
author="Apache Qpid",
author_email="dev@qpid.apache.org",
package_dir={'' : 'src/py'},
diff --git a/tools/src/py/.gitignore b/tools/src/py/.gitignore
index 97cb05dc36..b775fd83a1 100644
--- a/tools/src/py/.gitignore
+++ b/tools/src/py/.gitignore
@@ -19,4 +19,5 @@
# with the License. You may obtain a copy of the License at
/qpid-clusterc
/qpid-configc
+/qpid-hac
/qpid-routec
diff --git a/tools/src/py/qpid-cluster b/tools/src/py/qpid-cluster
index d4f9391dcf..7d800b52fb 100755
--- a/tools/src/py/qpid-cluster
+++ b/tools/src/py/qpid-cluster
@@ -64,17 +64,19 @@ class IpAddr:
return bestAddr
class BrokerManager:
- def __init__(self, config):
- self.config = config
- self.brokerName = None
- self.qmf = None
- self.broker = None
- self.brokers = []
+ def __init__(self, config, conn_options):
+ self.config = config
+ self.cert = None
+ self.conn_options = conn_options
+ self.brokerName = None
+ self.qmf = None
+ self.broker = None
+ self.brokers = []
def SetBroker(self, brokerUrl):
self.url = brokerUrl
self.qmf = Session()
- self.broker = self.qmf.addBroker(brokerUrl, self.config._connTimeout)
+ self.broker = self.qmf.addBroker(brokerUrl, self.config._connTimeout, **self.conn_options)
agents = self.qmf.getAgents()
for a in agents:
if a.getAgentBank() == '0':
@@ -240,6 +242,8 @@ def main(argv=None):
description="Example: $ qpid-cluster -C broker-host:10000")
parser.add_option("-t", "--timeout", action="store", type="int", default=10, metavar="SECS", help="Maximum time to wait for broker connection (in seconds)")
+ 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). SASL automatically picks the most secure available mechanism - use this option to override.")
+ parser.add_option("--ssl-certificate", action="store", type="string", metavar="<cert>", help="Client SSL certificate (PEM Format)")
parser.add_option("-C", "--all-connections", action="store_true", default=False, help="View client connections to all cluster members")
parser.add_option("-c", "--connections", metavar="ID", help="View client connections to specified member")
parser.add_option("-d", "--del-connection", metavar="HOST:PORT", help="Disconnect a client connection")
@@ -280,7 +284,13 @@ def main(argv=None):
config._force = opts.force
config._numeric = opts.numeric
- bm = BrokerManager(config)
+ conn_options = {}
+ if opts.sasl_mechanism:
+ conn_options['mechanisms'] = opts.sasl_mechanism
+ if opts.ssl_certificate:
+ conn_options['ssl_certfile'] = opts.ssl_certificate
+
+ bm = BrokerManager(config, conn_options)
try:
bm.SetBroker(config._host)
@@ -303,7 +313,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 1308df765d..df43b7ea4e 100755
--- a/tools/src/py/qpid-config
+++ b/tools/src/py/qpid-config
@@ -88,7 +88,6 @@ class Config:
self._altern_ex = None
self._durable = False
self._replicate = None
- self._ha_admin = False
self._clusterDurable = False
self._if_empty = True
self._if_unused = True
@@ -102,7 +101,6 @@ class Config:
self._ive = False
self._eventGeneration = None
self._file = None
- self._sasl_mechanism = None
self._flowStopCount = None
self._flowResumeCount = None
self._flowStopSize = None
@@ -114,6 +112,7 @@ class Config:
self._returnCode = 0
config = Config()
+conn_options = {}
FILECOUNT = "qpid.file_count"
FILESIZE = "qpid.file_size"
@@ -177,6 +176,9 @@ def OptionsAndArguments(argv):
group1.add_option("-r", "--recursive", action="store_true", help="Show bindings in queue or exchange list")
group1.add_option("-b", "--broker", 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("--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.")
+ group1.add_option("--ssl-certificate", action="store", type="string", metavar="<cert>", help="Client SSL certificate (PEM Format)")
+ group1.add_option("--ssl-key", action="store", type="string", metavar="<key>", help="Client SSL private key (PEM Format)")
+ group1.add_option("--ha-admin", action="store_true", help="Allow connection to a HA backup broker.")
parser.add_option_group(group1)
group_ls = OptionGroup(parser, "Options for Listing Exchanges and Queues")
@@ -187,7 +189,6 @@ def OptionsAndArguments(argv):
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("--durable", action="store_true", help="The new queue or exchange is durable.")
group2.add_option("--replicate", action="store", metavar="<level>", help="Enable automatic replication in a HA cluster. <level> is 'none', 'configuration' or 'all').")
- group2.add_option("--ha-admin", action="store_true", help="Allow connection to a HA backup broker.")
parser.add_option_group(group2)
group3 = OptionGroup(parser, "Options for Adding Queues")
@@ -306,6 +307,16 @@ def OptionsAndArguments(argv):
config._extra_arguments = opts.extra_arguments
if opts.start_replica:
config._start_replica = opts.start_replica
+
+ if opts.sasl_mechanism:
+ conn_options['sasl_mechanisms'] = opts.sasl_mechanism
+ if opts.ssl_certificate:
+ conn_options['ssl_certfile'] = opts.ssl_certificate
+ if opts.ssl_key:
+ conn_options['ssl_key'] = opts.ssl_key
+ if opts.ha_admin:
+ conn_options['client_properties'] = {'qpid.ha-admin' : 1}
+
return args
@@ -355,11 +366,9 @@ class BrokerManager:
self.conn = None
self.broker = None
- def SetBroker(self, brokerUrl, mechanism):
+ def SetBroker(self, brokerUrl):
self.url = brokerUrl
- client_properties={}
- if config._ha_admin: client_properties["qpid.ha-admin"] = 1
- self.conn = Connection.establish(self.url, sasl_mechanisms=mechanism, client_properties=client_properties)
+ self.conn = Connection.establish(self.url, **conn_options)
self.broker = BrokerAgent(self.conn)
def Disconnect(self):
@@ -690,7 +699,7 @@ def main(argv=None):
bm = BrokerManager()
try:
- bm.SetBroker(config._host, config._sasl_mechanism)
+ bm.SetBroker(config._host)
if len(args) == 0:
bm.Overview()
else:
diff --git a/tools/src/py/qpid-ha b/tools/src/py/qpid-ha
index bd8040cfbe..5b701a1fb4 100755
--- a/tools/src/py/qpid-ha
+++ b/tools/src/py/qpid-ha
@@ -19,8 +19,7 @@
# under the License.
#
-import qmf.console, optparse, sys, time, os
-from qpid.management import managementChannel, managementClient
+import optparse, sys, time, os
from qpid.messaging import Connection
from qpid.messaging import Message as QpidMessage
from qpidtoollibs.broker import BrokerAgent
@@ -32,29 +31,44 @@ except ImportError:
# QMF address for the HA broker object.
HA_BROKER = "org.apache.qpid.ha:habroker:ha-broker"
+class ExitStatus(Exception):
+ """Raised if a command want's a non-0 exit status from the script"""
+ def __init__(self, status): self.status = status
+
class Command:
commands = {}
- def __init__(self, name, help, args=[]):
+ def __init__(self, name, help, arg_names=[]):
Command.commands[name] = self
self.name = name
- self.args = args
- usage="%s [options] %s\n\n%s"%(name, " ".join(args), help)
+ self.arg_names = arg_names
+ usage="%s [options] %s\n\n%s"%(name, " ".join(arg_names), help)
self.help = help
self.op=optparse.OptionParser(usage)
- self.op.add_option("-b", "--broker", metavar="<url>", help="Connect to broker at <url>")
-
- def execute(self):
- opts, args = self.op.parse_args()
- if len(args) != len(self.args)+1:
+ self.op.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.")
+ self.op.add_option("--ssl-certificate", action="store", type="string", metavar="<cert>", help="Client SSL certificate (PEM Format)")
+ self.op.add_option("--ssl-key", action="store", type="string", metavar="<key>", help="Client SSL private key (PEM Format)")
+ self.op.add_option("-b", "--broker", action="store", type="string", default="localhost:5672", metavar="<address>", help="Address of qpidd broker with syntax: [username/password@] hostname | ip-address [:<port>]")
+
+ def execute(self, args):
+ opts, args = self.op.parse_args(args)
+ if len(args) != len(self.arg_names)+1:
self.op.print_help()
raise Exception("Wrong number of arguments")
- broker = opts.broker or "localhost:5672"
- connection = Connection.establish(broker, client_properties={"qpid.ha-admin":1})
+ conn_options = {}
+ if opts.sasl_mechanism:
+ conn_options['sasl_mechanisms'] = opts.sasl_mechanism
+ if opts.ssl_certificate:
+ conn_options['ssl_certfile'] = opts.ssl_certificate
+ if opts.ssl_key:
+ conn_options['ssl_key'] = opts.ssl_key
+ conn_options['client_properties'] = {'qpid.ha-admin' : 1}
+
+ connection = Connection.establish(opts.broker, **conn_options)
qmf_broker = BrokerAgent(connection)
ha_broker = qmf_broker.getHaBroker()
- if not ha_broker: raise Exception("HA module is not loaded on broker at %s"%broker)
- try: return self.do_execute(qmf_broker, ha_broker, opts, args)
+ if not ha_broker: raise Exception("HA module is not loaded on broker at %s" % opts.broker)
+ try: self.do_execute(qmf_broker, ha_broker, opts, args)
finally: connection.close()
def do_execute(self, qmf_broker, opts, args):
@@ -75,10 +89,10 @@ class StatusCmd(Command):
help="Don't print status but return 0 if it matches <status>, 1 otherwise")
def do_execute(self, qmf_broker, ha_broker, opts, args):
if opts.expect:
- if opts.expect != ha_broker.status: return 1
+ if opts.expect != ha_broker.status: raise ExitStatus(1)
else:
print ha_broker.status
- return 0
+
StatusCmd()
class ReplicateCmd(Command):
@@ -93,30 +107,31 @@ class SetCmd(Command):
Command.__init__(self, "set", "Set HA configuration settings")
def add(optname, metavar, type, help):
self.op.add_option(optname, metavar=metavar, type=type, help=help, action="store")
- add("--brokers", "<url>", "string", "HA brokers use <url> to connect to each other")
- add("--public-brokers", "<url>", "string", "Clients use <url> to connect to HA brokers")
+ add("--brokers-url", "<url>", "string", "URL with address of each broker in the cluster. Used by brokers to connect to each other.")
+ add("--public-url", "<url>", "string", "URL advertised to clients to connect to the cluster. May be a list or a VIP.")
add("--backups", "<n>", "int", "Expect <n> backups to be running"),
def do_execute(self, qmf_broker, ha_broker, opts, args):
- if (opts.brokers): qmf_broker._method("setBrokers", {"url":opts.brokers}, HA_BROKER)
- if (opts.public_brokers): qmf_broker._method("setPublicBrokers", {"url":opts.public_brokers}, HA_BROKER)
+ if (opts.brokers_url): qmf_broker._method("setBrokersUrl", {"url":opts.brokers_url}, HA_BROKER)
+ if (opts.public_url): qmf_broker._method("setPublicUrl", {"url":opts.public_url}, HA_BROKER)
if (opts.backups): qmf_broker._method("setExpectedBackups", {"expectedBackups":opts.backups}, HA_BROKER)
SetCmd()
class QueryCmd(Command):
def __init__(self):
- Command.__init__(self, "query", "Print HA configuration settings")
+ Command.__init__(self, "query", "Print HA configuration and status")
def do_execute(self, qmf_broker, ha_broker, opts, args):
hb = ha_broker
for x in [("Status:", hb.status),
- ("Brokers URL:", hb.brokers),
- ("Public URL:", hb.publicBrokers),
+ ("Brokers URL:", hb.brokersUrl),
+ ("Public URL:", hb.publicUrl),
("Expected Backups:", hb.expectedBackups),
("Replicate: ", hb.replicateDefault)
]:
print "%-20s %s"%(x[0], x[1])
+
QueryCmd()
def print_usage(prog):
@@ -133,18 +148,25 @@ def find_command(args):
return Command.commands[arg]
return None
-def main(argv):
- try:
- args=argv[1:]
- if args and args[0] == "--help-all":
- for c in Command.commands.itervalues():
- c.op.print_help(); print
- return 1
+def main_except(argv):
+ """This version of main raises exceptions"""
+ args=argv[1:]
+ if args and args[0] == "--help-all":
+ for c in Command.commands.itervalues():
+ c.op.print_help(); print
+ else:
command = find_command(args)
if not command:
print_usage(os.path.basename(argv[0]));
- return 1;
- if command.execute(): return 1
+ raise Exception("Command not found")
+ command.execute(args)
+
+def main(argv):
+ try:
+ main_except(argv)
+ return 0
+ except ExitStatus, e:
+ return e.status
except Exception, e:
print e
return 1
diff --git a/tools/src/py/qpid-printevents b/tools/src/py/qpid-printevents
index d56d2899b1..0d0f1a0782 100755
--- a/tools/src/py/qpid-printevents
+++ b/tools/src/py/qpid-printevents
@@ -21,34 +21,84 @@
import os
import optparse
-from optparse import IndentedHelpFormatter
import sys
-import socket
-from time import time, strftime, gmtime, sleep
-from qmf.console import Console, Session
+from optparse import IndentedHelpFormatter
+from time import time, strftime, gmtime, sleep
+from threading import Lock, Condition, Thread
+from qpid.messaging import Connection
+import qpid.messaging.exceptions
+home = os.environ.get("QPID_TOOLS_HOME", os.path.normpath("/usr/share/qpid-tools"))
+sys.path.append(os.path.join(home, "python"))
-class EventConsole(Console):
- def event(self, broker, event):
- print event
- sys.stdout.flush()
+from qpidtoollibs.broker import EventHelper
- def brokerConnected(self, broker):
- print strftime("%c", gmtime(time())), "NOTIC qpid-printevents:brokerConnected broker=%s" % broker.getUrl()
- sys.stdout.flush()
- def brokerConnectionFailed(self, broker):
- print strftime("%c", gmtime(time())), "NOTIC qpid-printevents:brokerConnectionFailed broker=%s %s" % (broker.getUrl(), str(broker.conn_exc))
- sys.stdout.flush()
+class Printer(object):
+ """
+ This class serializes printed lines so that events coming from different
+ threads don't overlap each other.
+ """
+ def __init__(self):
+ self.lock = Lock()
- def brokerDisconnected(self, broker):
- print strftime("%c", gmtime(time())), "NOTIC qpid-printevents:brokerDisconnected broker=%s" % broker.getUrl()
+ def pr(self, text):
+ self.lock.acquire()
+ try:
+ print text
+ finally:
+ self.lock.release()
sys.stdout.flush()
+
+
+class EventReceiver(Thread):
+ """
+ One instance of this class is created for each broker that is being monitored.
+ This class does not use the "reconnect" option because it needs to report as
+ events when the connection is established and when it's lost.
+ """
+ def __init__(self, printer, url, options):
+ Thread.__init__(self)
+ self.printer = printer
+ self.url = url
+ self.options = options
+ self.running = True
+ self.helper = EventHelper()
+
+ def cancel(self):
+ self.running = False
+
+ def run(self):
+ isOpen = False
+ while self.running:
+ try:
+ conn = Connection.establish(self.url, **options)
+ isOpen = True
+ self.printer.pr(strftime("%c", gmtime(time())) + " NOTIC qpid-printevents:brokerConnected broker=%s" % self.url)
+
+ sess = conn.session()
+ rx = sess.receiver(self.helper.eventAddress())
+
+ while self.running:
+ try:
+ msg = rx.fetch(1)
+ event = self.helper.event(msg)
+ self.printer.pr(event.__repr__())
+ sess.acknowledge()
+ except qpid.messaging.exceptions.Empty:
+ pass
+
+ except Exception, e:
+ if isOpen:
+ self.printer.pr(strftime("%c", gmtime(time())) + " NOTIC qpid-printevents:brokerDisconnected broker=%s" % self.url)
+ isOpen = False
+ sleep(1)
+
class JHelpFormatter(IndentedHelpFormatter):
- """Format usage and description without stripping newlines from usage strings
"""
-
+ Format usage and description without stripping newlines from usage strings
+ """
def format_usage(self, usage):
return usage
@@ -82,21 +132,42 @@ def main(argv=None):
p = optparse.OptionParser(usage=_usage, description=_description, formatter=JHelpFormatter())
p.add_option("--heartbeats", action="store_true", default=False, help="Use heartbeats.")
p.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.")
+ p.add_option("--ssl-certificate", action="store", type="string", metavar="<cert>", help="Client SSL certificate (PEM Format)")
+ p.add_option("--ssl-key", action="store", type="string", metavar="<key>", help="Client SSL private key (PEM Format)")
+ p.add_option("--ha-admin", action="store_true", help="Allow connection to a HA backup broker.")
options, arguments = p.parse_args(args=argv)
if len(arguments) == 0:
arguments.append("localhost")
- console = EventConsole()
- session = Session(console, rcvObjects=False, rcvHeartbeats=options.heartbeats, manageConnections=True)
- brokers = []
+ brokers = []
+ conn_options = {}
+ props = {}
+ printer = Printer()
+
+ if options.sasl_mechanism:
+ conn_options['sasl_mechanisms'] = options.sasl_mechanism
+ if options.ssl_certificate:
+ conn_options['ssl_certfile'] = options.ssl_certificate
+ if options.ssl_key:
+ conn_options['ssl_key'] = options.ssl_key
+ if options.ha_admin:
+ props['qpid.ha-admin'] = 1
+ if options.heartbeats:
+ props['heartbeat'] = 5
+
+ if len(props) > 0:
+ conn_options['client_properties'] = props
+
try:
try:
for host in arguments:
- brokers.append(session.addBroker(host, None, options.sasl_mechanism))
+ er = EventReceiver(printer, host, conn_options)
+ brokers.append(er)
+ er.start()
- while (True):
- sleep(10)
+ while (True):
+ sleep(10)
except KeyboardInterrupt:
print
@@ -106,9 +177,10 @@ def main(argv=None):
print "Failed: %s - %s" % (e.__class__.__name__, e)
return 1
finally:
- while len(brokers):
- b = brokers.pop()
- session.delBroker(b)
+ for b in brokers:
+ b.cancel()
+ for b in brokers:
+ b.join()
if __name__ == '__main__':
sys.exit(main())
diff --git a/tools/src/py/qpid-queue-stats b/tools/src/py/qpid-queue-stats
index 562ccce32d..f68609aed8 100755
--- a/tools/src/py/qpid-queue-stats
+++ b/tools/src/py/qpid-queue-stats
@@ -32,13 +32,13 @@ from qpid.connection import Connection, ConnectionFailed
from time import sleep
class BrokerManager(Console):
- def __init__(self, host, mechanism):
+ def __init__(self, host, conn_options):
self.url = host
self.objects = {}
self.filter = None
self.session = Session(self, rcvEvents=False, rcvHeartbeats=False,
userBindings=True, manageConnections=True)
- self.broker = self.session.addBroker(self.url, None, mechanism)
+ self.broker = self.session.addBroker(self.url, **conn_options)
self.firstError = True
def setFilter(self,filter):
@@ -126,17 +126,23 @@ def main(argv=None):
p.add_option('--broker-address','-a', default='localhost' , help='broker-addr is in the form: [username/password@] hostname | ip-address [:<port>] \n ex: localhost, 10.1.1.7:10000, broker-host:10000, guest/guest@localhost')
p.add_option('--filter','-f' ,default=None ,help='a list of comma separated queue names (regex are accepted) to show')
p.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.")
-
+ p.add_option("--ssl-certificate", action="store", type="string", metavar="<cert>", help="Client SSL certificate (PEM Format)")
options, arguments = p.parse_args(args=argv)
+ conn_options = {}
+ if options.sasl_mechanism:
+ conn_options['mechanisms'] = options.sasl_mechanism
+ if options.ssl_certificate:
+ conn_options['ssl_certfile'] = options.ssl_certificate
+
host = options.broker_address
filter = []
if options.filter != None:
for s in options.filter.split(","):
filter.append(re.compile(s))
- bm = BrokerManager(host, options.sasl_mechanism)
+ bm = BrokerManager(host, conn_options)
bm.setFilter(filter)
bm.Display()
diff --git a/tools/src/py/qpid-route b/tools/src/py/qpid-route
index 0316c24322..00c7c59189 100755
--- a/tools/src/py/qpid-route
+++ b/tools/src/py/qpid-route
@@ -53,16 +53,15 @@ def Usage():
class Config:
def __init__(self):
- self._verbose = False
- self._quiet = False
- self._durable = False
- self._dellink = False
- self._srclocal = False
- self._transport = "tcp"
- self._ack = 0
- self._connTimeout = 10
- self._client_sasl_mechanism = None
- self._ha_admin = False
+ self._verbose = False
+ self._quiet = False
+ self._durable = False
+ self._dellink = False
+ self._srclocal = False
+ self._transport = "tcp"
+ self._ack = 0
+ self._connTimeout = 10
+ self._conn_options = {}
config = Config()
@@ -97,6 +96,7 @@ def OptionsAndArguments(argv):
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("--ssl-certificate", action="store", type="string", metavar="<cert>", help="Client SSL certificate (PEM Format)")
parser.add_option("--ha-admin", action="store_true", help="Allow connection to a HA backup broker.")
opts, encArgs = parser.parse_args(args=argv)
@@ -130,13 +130,16 @@ def OptionsAndArguments(argv):
config._transport = opts.transport
if opts.ha_admin:
- config._ha_admin = True
+ config._conn_options['client_properties'] = {'qpid.ha-admin' : 1}
if opts.ack:
config._ack = opts.ack
if opts.client_sasl_mechanism:
- config._client_sasl_mechanism = opts.client_sasl_mechanism
+ config._conn_options['mechanisms'] = opts.client_sasl_mechanism
+
+ if opts.ssl_certificate:
+ config._conn_options['ssl_certfile'] = opts.ssl_certificate
return args
@@ -147,9 +150,7 @@ class RouteManager:
self.local = BrokerURL(localBroker)
self.remote = None
self.qmf = Session()
- client_properties = {}
- if config._ha_admin: client_properties["qpid.ha-admin"] = 1
- self.broker = self.qmf.addBroker(localBroker, config._connTimeout, config._client_sasl_mechanism, client_properties=client_properties)
+ self.broker = self.qmf.addBroker(localBroker, config._connTimeout, **config._conn_options)
self.broker._waitForStable()
self.agent = self.broker.getBrokerAgent()
diff --git a/tools/src/py/qpid-stat b/tools/src/py/qpid-stat
index 5a816baf6e..458ae36182 100755
--- a/tools/src/py/qpid-stat
+++ b/tools/src/py/qpid-stat
@@ -42,17 +42,26 @@ class Config:
self._limit = 50
self._increasing = False
self._sortcol = None
- self._sasl_mechanism = None
- self._ha_admin = False
config = Config()
+conn_options = {}
def OptionsAndArguments(argv):
""" Set global variables for options, return arguments """
global config
+ global conn_options
- parser = OptionParser(usage="usage: %prog [options] -[gcequm] [object-name]")
+ usage = \
+"""%prog -g [options]
+ %prog -c [options]
+ %prog -e [options]
+ %prog -q [options] [queue-name]
+ %prog -u [options]
+ %prog -m [options]
+ %prog --acl [options]"""
+
+ parser = OptionParser(usage=usage)
group1 = OptionGroup(parser, "General Options")
group1.add_option("-b", "--broker", action="store", type="string", default="localhost", metavar="<url>",
@@ -61,10 +70,12 @@ def OptionsAndArguments(argv):
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.")
+ group1.add_option("--ssl-certificate", action="store", type="string", metavar="<cert>", help="Client SSL certificate (PEM Format)")
+ group1.add_option("--ssl-key", action="store", type="string", metavar="<key>", help="Client SSL private key (PEM Format)")
group1.add_option("--ha-admin", action="store_true", help="Allow connection to a HA backup broker.")
parser.add_option_group(group1)
- group2 = OptionGroup(parser, "Display Options")
+ group2 = OptionGroup(parser, "Command Options")
group2.add_option("-g", "--general", help="Show General Broker Stats", action="store_const", const="g", dest="show")
group2.add_option("-c", "--connections", help="Show Connections", action="store_const", const="c", dest="show")
group2.add_option("-e", "--exchanges", help="Show Exchanges", action="store_const", const="e", dest="show")
@@ -72,12 +83,14 @@ def OptionsAndArguments(argv):
group2.add_option("-u", "--subscriptions", help="Show Subscriptions", action="store_const", const="u", dest="show")
group2.add_option("-m", "--memory", help="Show Broker Memory Stats", action="store_const", const="m", dest="show")
group2.add_option( "--acl", help="Show Access Control List Stats", action="store_const", const="acl", dest="show")
- group2.add_option("-S", "--sort-by", metavar="<colname>", help="Sort by column name")
- group2.add_option("-I", "--increasing", action="store_true", default=False, help="Sort by increasing value (default = decreasing)")
- group2.add_option("-L", "--limit", type="int", default=50, metavar="<n>", help="Limit output to n rows")
-
parser.add_option_group(group2)
+ group3 = OptionGroup(parser, "Display Options")
+ group3.add_option("-S", "--sort-by", metavar="<colname>", help="Sort by column name")
+ group3.add_option("-I", "--increasing", action="store_true", default=False, help="Sort by increasing value (default = decreasing)")
+ group3.add_option("-L", "--limit", type="int", default=50, metavar="<n>", help="Limit output to n rows")
+ parser.add_option_group(group3)
+
opts, args = parser.parse_args(args=argv)
if not opts.show:
@@ -89,8 +102,15 @@ def OptionsAndArguments(argv):
config._connTimeout = opts.timeout
config._increasing = opts.increasing
config._limit = opts.limit
- config._sasl_mechanism = opts.sasl_mechanism
- config._ha_admin = opts.ha_admin
+
+ if opts.sasl_mechanism:
+ conn_options['sasl_mechanisms'] = opts.sasl_mechanism
+ if opts.ssl_certificate:
+ conn_options['ssl_certfile'] = opts.ssl_certificate
+ if opts.ssl_key:
+ conn_options['ssl_key'] = opts.ssl_key
+ if opts.ha_admin:
+ conn_options['client_properties'] = {'qpid.ha-admin' : 1}
return args
@@ -126,11 +146,9 @@ class BrokerManager:
self.broker = None
self.cluster = None
- def SetBroker(self, brokerUrl, mechanism):
+ def SetBroker(self, brokerUrl):
self.url = brokerUrl
- client_properties={}
- if config._ha_admin: client_properties["qpid.ha-admin"] = 1
- self.connection = Connection.establish(self.url, sasl_mechanisms=mechanism, client_properties=client_properties)
+ self.connection = Connection.establish(self.url, **conn_options)
self.broker = BrokerAgent(self.connection)
def Disconnect(self):
@@ -235,9 +253,10 @@ class BrokerManager:
def displayConn(self):
disp = Display(prefix=" ")
heads = []
- heads.append(Header('client-addr'))
+ heads.append(Header('connection'))
heads.append(Header('cproc'))
heads.append(Header('cpid'))
+ heads.append(Header('mech'))
heads.append(Header('auth'))
heads.append(Header('connected', Header.DURATION))
heads.append(Header('idle', Header.DURATION))
@@ -251,6 +270,7 @@ class BrokerManager:
row.append(conn.address)
row.append(conn.remoteProcessName)
row.append(conn.remotePid)
+ row.append(conn.saslMechanism)
row.append(conn.authIdentity)
row.append(broker.getUpdateTime() - conn.getCreateTime())
row.append(broker.getUpdateTime() - conn.getUpdateTime())
@@ -416,7 +436,8 @@ class BrokerManager:
heads.append(Header("acked", Header.Y))
heads.append(Header("excl", Header.Y))
heads.append(Header("creditMode"))
- heads.append(Header("delivered", Header.KMG))
+ heads.append(Header("delivered", Header.COMMAS))
+ heads.append(Header("sessUnacked", Header.COMMAS))
rows = []
subscriptions = self.broker.getAllSubscriptions()
sessions = self.getSessionMap()
@@ -436,6 +457,7 @@ class BrokerManager:
row.append(s.exclusive)
row.append(s.creditMode)
row.append(s.delivered)
+ row.append(session.unackedMessages)
rows.append(row)
except:
pass
@@ -524,7 +546,7 @@ def main(argv=None):
bm = BrokerManager()
try:
- bm.SetBroker(config._host, config._sasl_mechanism)
+ bm.SetBroker(config._host)
bm.display(args)
bm.Disconnect()
return 0
diff --git a/tools/src/py/qpid-tool b/tools/src/py/qpid-tool
index af948b13a9..4afa18dbb1 100755
--- a/tools/src/py/qpid-tool
+++ b/tools/src/py/qpid-tool
@@ -173,11 +173,11 @@ class Mcli(Cmd):
class QmfData(Console):
"""
"""
- def __init__(self, disp, url):
+ def __init__(self, disp, url, cert):
self.disp = disp
self.url = url
self.session = Session(self, manageConnections=True)
- self.broker = self.session.addBroker(self.url)
+ self.broker = self.session.addBroker(self.url, ssl_certfile=cert)
self.lock = Lock()
self.connected = None
self.closing = None
@@ -455,6 +455,7 @@ class QmfData(Console):
rows.append(row)
else:
print "No object found with ID %d" % dispId
+ return
finally:
self.lock.release()
self.disp.table(caption, heads, rows)
@@ -723,10 +724,13 @@ if _host[0] == '-':
sys.exit(1)
disp = Display()
+cert = None
+if len(cargs) > 1:
+ cert = cargs[1]
# Attempt to make a connection to the target broker
try:
- data = QmfData(disp, _host)
+ data = QmfData(disp, _host, cert)
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/qpidtoollibs/broker.py b/tools/src/py/qpidtoollibs/broker.py
index 0bae786306..ea31aeabb0 100644
--- a/tools/src/py/qpidtoollibs/broker.py
+++ b/tools/src/py/qpidtoollibs/broker.py
@@ -18,6 +18,7 @@
#
from qpid.messaging import Message
+from qpidtoollibs.disp import TimeLong
try:
from uuid import uuid4
except ImportError:
@@ -190,9 +191,13 @@ class BrokerAgent(object):
def getAcl(self):
return self._getSingleObject(Acl)
- def echo(self, sequence, body):
+ def getMemory(self):
+ return self._getSingleObject(Memory)
+
+ def echo(self, sequence = 1, body = "Body"):
"""Request a response to test the path to the management broker"""
- pass
+ args = {'sequence' : sequence, 'body' : body}
+ return self._method('echo', args)
def connect(self, host, port, durable, authMechanism, username, password, transport):
"""Establish a connection to another broker"""
@@ -295,6 +300,41 @@ class BrokerAgent(object):
return self._getBrokerObject(self, _type, oid)
+class EventHelper(object):
+ def eventAddress(self, pkg='*', cls='*', sev='*'):
+ return "qmf.default.topic/agent.ind.event.%s.%s.%s.#" % (pkg.replace('.', '_'), cls, sev)
+
+ def event(self, msg):
+ return BrokerEvent(msg)
+
+
+class BrokerEvent(object):
+ def __init__(self, msg):
+ self.msg = msg
+ self.content = msg.content[0]
+ self.values = self.content['_values']
+ self.schema_id = self.content['_schema_id']
+ self.name = "%s:%s" % (self.schema_id['_package_name'], self.schema_id['_class_name'])
+
+ def __repr__(self):
+ rep = "%s %s" % (TimeLong(self.getTimestamp()), self.name)
+ for k,v in self.values.items():
+ rep = rep + " %s=%s" % (k, v)
+ return rep
+
+ def __getattr__(self, key):
+ if key not in self.values:
+ return None
+ value = self.values[key]
+ return value
+
+ def getAttributes(self):
+ return self.values
+
+ def getTimestamp(self):
+ return self.content['_timestamp']
+
+
class BrokerObject(object):
def __init__(self, broker, content):
self.broker = broker
@@ -362,7 +402,7 @@ class Connection(BrokerObject):
BrokerObject.__init__(self, broker, values)
def close(self):
- pass
+ self.broker._method("close", {}, "org.apache.qpid.broker:connection:%s" % self.address)
class Session(BrokerObject):
def __init__(self, broker, values):
diff --git a/tools/src/py/qpidtoollibs/disp.py b/tools/src/py/qpidtoollibs/disp.py
index a0c77370a5..21e09f8d00 100644
--- a/tools/src/py/qpidtoollibs/disp.py
+++ b/tools/src/py/qpidtoollibs/disp.py
@@ -167,7 +167,10 @@ class Display:
for head in heads:
width = len (head)
for row in rows:
- cellWidth = len (unicode (row[col]))
+ text = row[col]
+ if text.__class__ == str:
+ text = text.decode('utf-8')
+ cellWidth = len(unicode(text))
if cellWidth > width:
width = cellWidth
colWidth.append (width + self.tableSpacing)
@@ -187,9 +190,12 @@ class Display:
line = self.tablePrefix
col = 0
for width in colWidth:
- line = line + unicode (row[col])
+ text = row[col]
+ if text.__class__ == str:
+ text = text.decode('utf-8')
+ line = line + unicode(text)
if col < len (heads) - 1:
- for i in range (width - len (unicode (row[col]))):
+ for i in range (width - len(unicode(text))):
line = line + " "
col = col + 1
print line
diff --git a/wcf/src/Apache/Qpid/Interop/InputLink.cpp b/wcf/src/Apache/Qpid/Interop/InputLink.cpp
index 2b0119e338..f8189df0dd 100644
--- a/wcf/src/Apache/Qpid/Interop/InputLink.cpp
+++ b/wcf/src/Apache/Qpid/Interop/InputLink.cpp
@@ -21,6 +21,7 @@
#include <msclr\lock.h>
#include "qpid/client/AsyncSession.h"
+#include "qpid/framing/FieldValue.h"
#include "qpid/framing/FrameSet.h"
#include "qpid/client/SubscriptionManager.h"
#include "qpid/client/Connection.h"